@kern_h responded to this topic on the LLVM Discord #mlir
channel:
@modocache i tried commenting out those checks too and was excited when all existing tests passed. it was soon pointed out to me though that there’s no code that knows how to handle something like memref<1xmemref<f32>>
. even if parsing and construction succeeds, it will presumably fail during conversion.
I hadn’t realized this because my frontend is successfully using MLIR for the following C program:
// Compiles and executes to return an exit code of 9.
int main() {
int a;
a = 1;
int *b;
b = &a;
int **c;
c = &*&b;
**c = 3;
return a + *b + **c;
}
My frontend emits the following MLIR when converted to ‘std’:
module @"cl/test/CodeGen/pointer.c" {
func @main() -> i32 {
%0 = alloca() : memref<1xi32> cl/test/CodeGen/pointer.c:9:1
%c0_i32 = constant 0 : i32 cl/test/CodeGen/pointer.c:9:1
%c0 = constant 0 : index cl/test/CodeGen/pointer.c:9:1
store %c0_i32, %0[%c0] : memref<1xi32> cl/test/CodeGen/pointer.c:9:1
%1 = alloca() : memref<1xi32> cl/test/CodeGen/pointer.c:10:7
%c1_i32 = constant 1 : i32 cl/test/CodeGen/pointer.c:11:7
%c0_0 = constant 0 : index cl/test/CodeGen/pointer.c:11:3
store %c1_i32, %1[%c0_0] : memref<1xi32> cl/test/CodeGen/pointer.c:11:3
%2 = alloca() : memref<1xmemref<1xi32>> cl/test/CodeGen/pointer.c:13:8
%c0_1 = constant 0 : index cl/test/CodeGen/pointer.c:14:3
store %1, %2[%c0_1] : memref<1xmemref<1xi32>> cl/test/CodeGen/pointer.c:14:3
%3 = alloca() : memref<1xmemref<1xmemref<1xi32>>> cl/test/CodeGen/pointer.c:16:9
%c0_2 = constant 0 : index cl/test/CodeGen/pointer.c:17:3
store %2, %3[%c0_2] : memref<1xmemref<1xmemref<1xi32>>> cl/test/CodeGen/pointer.c:17:3
%c3_i32 = constant 3 : i32 cl/test/CodeGen/pointer.c:19:9
%c0_3 = constant 0 : index cl/test/CodeGen/pointer.c:19:5
%4 = load %3[%c0_3] : memref<1xmemref<1xmemref<1xi32>>> cl/test/CodeGen/pointer.c:19:5
%c0_4 = constant 0 : index cl/test/CodeGen/pointer.c:19:4
%5 = load %4[%c0_4] : memref<1xmemref<1xi32>> cl/test/CodeGen/pointer.c:19:4
%c0_5 = constant 0 : index cl/test/CodeGen/pointer.c:19:3
store %c3_i32, %5[%c0_5] : memref<1xi32> cl/test/CodeGen/pointer.c:19:3
%c0_6 = constant 0 : index cl/test/CodeGen/pointer.c:21:10
%6 = load %1[%c0_6] : memref<1xi32> cl/test/CodeGen/pointer.c:21:10
%c0_7 = constant 0 : index cl/test/CodeGen/pointer.c:21:15
%7 = load %2[%c0_7] : memref<1xmemref<1xi32>> cl/test/CodeGen/pointer.c:21:15
%c0_8 = constant 0 : index cl/test/CodeGen/pointer.c:21:14
%8 = load %7[%c0_8] : memref<1xi32> cl/test/CodeGen/pointer.c:21:14
%9 = addi %6, %8 : i32 cl/test/CodeGen/pointer.c:21:10
%c0_9 = constant 0 : index cl/test/CodeGen/pointer.c:21:21
%10 = load %3[%c0_9] : memref<1xmemref<1xmemref<1xi32>>> cl/test/CodeGen/pointer.c:21:21
%c0_10 = constant 0 : index cl/test/CodeGen/pointer.c:21:20
%11 = load %10[%c0_10] : memref<1xmemref<1xi32>> cl/test/CodeGen/pointer.c:21:20
%c0_11 = constant 0 : index cl/test/CodeGen/pointer.c:21:19
%12 = load %11[%c0_11] : memref<1xi32> cl/test/CodeGen/pointer.c:21:19
%13 = addi %9, %12 : i32 cl/test/CodeGen/pointer.c:21:10
%c0_12 = constant 0 : index cl/test/CodeGen/pointer.c:21:3
store %13, %0[%c0_12] : memref<1xi32> cl/test/CodeGen/pointer.c:21:3
br ^bb1 cl/test/CodeGen/pointer.c:21:3
^bb1: // pred: ^bb0
%c0_13 = constant 0 : index cl/test/CodeGen/pointer.c:9:1
%14 = load %0[%c0_13] : memref<1xi32> cl/test/CodeGen/pointer.c:9:1
return %14 : i32 cl/test/CodeGen/pointer.c:9:1
} cl/test/CodeGen/pointer.c:9:1
} cl/test/CodeGen/pointer.c:9:1
Lowered to LLVM IR this produces:
; ModuleID = 'LLVMDialectModule'
source_filename = "LLVMDialectModule"
declare i8* @malloc(i64)
declare void @free(i8*)
define i32 @main() !dbg !3 {
%1 = alloca i32, i64 ptrtoint (i32* getelementptr (i32, i32* null, i64 1) to i64), align 4, !dbg !7
%2 = insertvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } undef, i32* %1, 0, !dbg !7
%3 = insertvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %2, i32* %1, 1, !dbg !7
%4 = insertvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %3, i64 0, 2, !dbg !7
%5 = insertvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %4, i64 1, 3, 0, !dbg !7
%6 = insertvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %5, i64 1, 4, 0, !dbg !7
%7 = extractvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %6, 1, !dbg !7
%8 = getelementptr i32, i32* %7, i64 0, !dbg !7
store i32 0, i32* %8, align 4, !dbg !7
%9 = alloca i32, i64 ptrtoint (i32* getelementptr (i32, i32* null, i64 1) to i64), align 4, !dbg !9
%10 = insertvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } undef, i32* %9, 0, !dbg !9
%11 = insertvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %10, i32* %9, 1, !dbg !9
%12 = insertvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %11, i64 0, 2, !dbg !9
%13 = insertvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %12, i64 1, 3, 0, !dbg !9
%14 = insertvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %13, i64 1, 4, 0, !dbg !9
%15 = extractvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %14, 1, !dbg !10
%16 = getelementptr i32, i32* %15, i64 0, !dbg !10
store i32 1, i32* %16, align 4, !dbg !10
%17 = alloca { i32*, i32*, i64, [1 x i64], [1 x i64] }, i64 ptrtoint ({ i32*, i32*, i64, [1 x i64], [1 x i64] }* getelementptr ({ i32*, i32*, i64, [1 x i64], [1 x i64] }, { i32*, i32*, i64, [1 x i64], [1 x i64] }* null, i64 1) to i64), align 8, !dbg !11
%18 = insertvalue { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } undef, { i32*, i32*, i64, [1 x i64], [1 x i64] }* %17, 0, !dbg !11
%19 = insertvalue { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %18, { i32*, i32*, i64, [1 x i64], [1 x i64] }* %17, 1, !dbg !11
%20 = insertvalue { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %19, i64 0, 2, !dbg !11
%21 = insertvalue { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %20, i64 1, 3, 0, !dbg !11
%22 = insertvalue { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %21, i64 1, 4, 0, !dbg !11
%23 = extractvalue { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %22, 1, !dbg !12
%24 = getelementptr { i32*, i32*, i64, [1 x i64], [1 x i64] }, { i32*, i32*, i64, [1 x i64], [1 x i64] }* %23, i64 0, !dbg !12
store { i32*, i32*, i64, [1 x i64], [1 x i64] } %14, { i32*, i32*, i64, [1 x i64], [1 x i64] }* %24, align 8, !dbg !12
%25 = alloca { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }, i64 ptrtoint ({ { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }* getelementptr ({ { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }* null, i64 1) to i64), align 8, !dbg !13
%26 = insertvalue { { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } undef, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }* %25, 0, !dbg !13
%27 = insertvalue { { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %26, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }* %25, 1, !dbg !13
%28 = insertvalue { { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %27, i64 0, 2, !dbg !13
%29 = insertvalue { { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %28, i64 1, 3, 0, !dbg !13
%30 = insertvalue { { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %29, i64 1, 4, 0, !dbg !13
%31 = extractvalue { { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %30, 1, !dbg !14
%32 = getelementptr { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }* %31, i64 0, !dbg !14
store { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %22, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }* %32, align 8, !dbg !14
%33 = extractvalue { { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %30, 1, !dbg !15
%34 = getelementptr { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }* %33, i64 0, !dbg !15
%35 = load { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }* %34, align 8, !dbg !15
%36 = extractvalue { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %35, 1, !dbg !16
%37 = getelementptr { i32*, i32*, i64, [1 x i64], [1 x i64] }, { i32*, i32*, i64, [1 x i64], [1 x i64] }* %36, i64 0, !dbg !16
%38 = load { i32*, i32*, i64, [1 x i64], [1 x i64] }, { i32*, i32*, i64, [1 x i64], [1 x i64] }* %37, align 8, !dbg !16
%39 = extractvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %38, 1, !dbg !17
%40 = getelementptr i32, i32* %39, i64 0, !dbg !17
store i32 3, i32* %40, align 4, !dbg !17
%41 = extractvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %14, 1, !dbg !18
%42 = getelementptr i32, i32* %41, i64 0, !dbg !18
%43 = load i32, i32* %42, align 4, !dbg !18
%44 = extractvalue { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %22, 1, !dbg !19
%45 = getelementptr { i32*, i32*, i64, [1 x i64], [1 x i64] }, { i32*, i32*, i64, [1 x i64], [1 x i64] }* %44, i64 0, !dbg !19
%46 = load { i32*, i32*, i64, [1 x i64], [1 x i64] }, { i32*, i32*, i64, [1 x i64], [1 x i64] }* %45, align 8, !dbg !19
%47 = extractvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %46, 1, !dbg !20
%48 = getelementptr i32, i32* %47, i64 0, !dbg !20
%49 = load i32, i32* %48, align 4, !dbg !20
%50 = add i32 %43, %49, !dbg !18
%51 = extractvalue { { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %30, 1, !dbg !21
%52 = getelementptr { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }* %51, i64 0, !dbg !21
%53 = load { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }, { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] }* %52, align 8, !dbg !21
%54 = extractvalue { { i32*, i32*, i64, [1 x i64], [1 x i64] }*, { i32*, i32*, i64, [1 x i64], [1 x i64] }*, i64, [1 x i64], [1 x i64] } %53, 1, !dbg !22
%55 = getelementptr { i32*, i32*, i64, [1 x i64], [1 x i64] }, { i32*, i32*, i64, [1 x i64], [1 x i64] }* %54, i64 0, !dbg !22
%56 = load { i32*, i32*, i64, [1 x i64], [1 x i64] }, { i32*, i32*, i64, [1 x i64], [1 x i64] }* %55, align 8, !dbg !22
%57 = extractvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %56, 1, !dbg !23
%58 = getelementptr i32, i32* %57, i64 0, !dbg !23
%59 = load i32, i32* %58, align 4, !dbg !23
%60 = add i32 %50, %59, !dbg !18
%61 = extractvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %6, 1, !dbg !24
%62 = getelementptr i32, i32* %61, i64 0, !dbg !24
store i32 %60, i32* %62, align 4, !dbg !24
br label %63, !dbg !24
63: ; preds = %0
%64 = extractvalue { i32*, i32*, i64, [1 x i64], [1 x i64] } %6, 1, !dbg !7
%65 = getelementptr i32, i32* %64, i64 0, !dbg !7
%66 = load i32, i32* %65, align 4, !dbg !7
ret i32 %66, !dbg !7
}
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2}
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "mlir", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
!1 = !DIFile(filename: "LLVMDialectModule", directory: "/")
!2 = !{i32 2, !"Debug Info Version", i32 3}
!3 = distinct !DISubprogram(name: "main", linkageName: "main", scope: null, file: !4, line: 9, type: !5, scopeLine: 9, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !6)
!4 = !DIFile(filename: "cl/test/CodeGen/pointer.c", directory: "/home/modocache/Source/llvm/git/dev/llvm-project")
!5 = !DISubroutineType(types: !6)
!6 = !{}
!7 = !DILocation(line: 9, column: 1, scope: !8)
!8 = !DILexicalBlockFile(scope: !3, file: !4, discriminator: 0)
!9 = !DILocation(line: 10, column: 7, scope: !8)
!10 = !DILocation(line: 11, column: 3, scope: !8)
!11 = !DILocation(line: 13, column: 8, scope: !8)
!12 = !DILocation(line: 14, column: 3, scope: !8)
!13 = !DILocation(line: 16, column: 9, scope: !8)
!14 = !DILocation(line: 17, column: 3, scope: !8)
!15 = !DILocation(line: 19, column: 5, scope: !8)
!16 = !DILocation(line: 19, column: 4, scope: !8)
!17 = !DILocation(line: 19, column: 3, scope: !8)
!18 = !DILocation(line: 21, column: 10, scope: !8)
!19 = !DILocation(line: 21, column: 15, scope: !8)
!20 = !DILocation(line: 21, column: 14, scope: !8)
!21 = !DILocation(line: 21, column: 21, scope: !8)
!22 = !DILocation(line: 21, column: 20, scope: !8)
!23 = !DILocation(line: 21, column: 19, scope: !8)
!24 = !DILocation(line: 21, column: 3, scope: !8)
So, while I can’t be certain the LLVM IR is exactly correct, it is at least producing the correct result for my toy program. Anyway, I thought I’d at least share the specific code I’m generating, in case it’s helpful when discussing this.
Based on @kern_h’s comment it sounds like this has been discussed before, and suggestion (3) from my original post was not considered a viable approach. In that case, I’m wondering what (4) would look like: some sort of “support” for pointers in the ‘std’ dialect.