I have a toy language called Rice that I want to compile to C through MLIR. I’m representing strings as memref<?xi8> and I’m having trouble lowering my rice.print operator to EmitC with the following “Hello World” program:
module {
memref.global constant @str_0 : memref<12xi8> = dense<[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]>
func.func @main() {
%0 = memref.get_global @str_0 : memref<12xi8>
%cast = memref.cast %0 : memref<12xi8> to memref<?xi8>
"rice.print"(%cast) : (memref<?xi8>) -> ()
%c0_i32 = arith.constant 0 : i32
return
}
}
My thought was that rice.print can simply get transformed into an emitc.call that calls puts (for more complete calls I want to use printf but for starters I’m testing with puts). Ideally this should get lowered into:
module {
emitc.global extern const @str_0 : !emitc.array<12xi8> = dense<[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]>
emitc.func private @puts(!emitc.ptr<i8>) -> i32 attributes {specifiers = ["extern"]}
emitc.func @main() -> i32 {
%0 = emitc.get_global @str_0 : !emitc.array<12xi8>
%ptr = emitc.cast %0 : !emitc.array<12xi8> to !emitc.ptr<i8>
%result = emitc.call @puts(%ptr) : (!emitc.ptr<i8>) -> i32
%zero = "emitc.constant"() <{value = 0 : i32}> : () -> i32
emitc.return %zero : i32
}
}
My dilemma is that EmitC doesn’t take memref<?xi8>, and the --convert-memref-to-emitc` rejects memref<?xi8>. My first naive lowering transforms rice.print into a func.call of the external function puts:
module {
func.func private @puts(memref<?xi8>)
memref.global constant @str_0 : memref<12xi8> = dense<[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]>
func.func @main() {
%0 = memref.get_global @str_0 : memref<12xi8>
%cast = memref.cast %0 : memref<12xi8> to memref<?xi8>
func.call @puts(%cast) : (memref<?xi8>) -> ()
%c0_i32 = arith.constant 0 : i32
return
}
}
And mlir-opt is not happy with memref<?xi8>
> mlir-opt --convert-memref-to-emitc --convert-func-to-emitc test2.mlir
test2.mlir:8:13: error: failed to legalize operation 'memref.cast' that was explicitly marked illegal
%cast = memref.cast %0 : memref<12xi8> to memref<?xi8>
^
test2.mlir:8:13: note: see current operation: %2 = "memref.cast"(%1) : (memref<12xi8>) -> memref<?xi8>
How should I deal with memref<?xi8> if I want to lower to EmitC? Should I be writing my own RiceAndMemRefToEmitCPass that mix n’ match the OpConversionPatterns defined in MemRefToEmitC.cpp plus my own pattern that converts memref.cast into a emitc.cast?