diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td index 4c1db58da45f0..c1820904f2665 100644 --- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td +++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td @@ -116,6 +116,37 @@ def EmitC_FileOp let skipDefaultBuilders = 1; } +def EmitC_AddressOfOp : EmitC_Op<"address_of", [ + CExpressionInterface, + TypesMatchWith<"input and result reference the same type", "reference", "result", + "emitc::PointerType::get(::llvm::cast($_self).getValueType())"> +]> { + let summary = "Address operation"; + let description = [{ + This operation models the C & (address of) operator for a single operand, + which must be an emitc.lvalue, and returns an emitc pointer to its location. + + Example: + + ```mlir + // Custom form of applying the & operator. + %0 = emitc.address_of %arg0 : (!emitc.lvalue) -> !emitc.ptr + ``` + }]; + let arguments = (ins EmitC_LValueType:$reference); + let results = (outs EmitC_PointerType:$result); + let assemblyFormat = [{ + $reference `:` qualified(type($reference)) attr-dict + }]; + let hasVerifier = 1; + + let extraClassDeclaration = [{ + bool hasSideEffects() { + return false; + } + }]; +} + def EmitC_AddOp : EmitC_BinaryOp<"add", []> { let summary = "Addition operation"; let description = [{ @@ -140,7 +171,7 @@ def EmitC_AddOp : EmitC_BinaryOp<"add", []> { } def EmitC_ApplyOp : EmitC_Op<"apply", [CExpressionInterface]> { - let summary = "Apply operation"; + let summary = "Deprecated (use address_of/dereference)"; let description = [{ With the `emitc.apply` operation the operators & (address of) and * (contents of) can be applied to a single operand. @@ -439,6 +470,31 @@ def EmitC_ConstantOp }]; } +def EmitC_DereferenceOp : EmitC_Op<"dereference", [ + TypesMatchWith<"input and result reference the same type", "pointer", "result", + "emitc::LValueType::get(::llvm::cast($_self).getPointee())"> +]> { + let summary = "Dereference operation"; + let description = [{ + This operation models the C * (dereference) operator, which must be of + !emitc.ptr<> type, returning an !emitc.lvalue<> the value pointed to by the + pointer. + + Example: + + ```mlir + // Custom form of the dereference operator. + %0 = emitc.dereference %arg0 : (!emitc.ptr) -> !emitc.lvalue + ``` + }]; + let arguments = (ins EmitC_PointerType:$pointer); + let results = (outs EmitC_LValueType:$result); + let assemblyFormat = [{ + $pointer `:` qualified(type($pointer)) attr-dict + }]; + let hasVerifier = 1; +} + def EmitC_DivOp : EmitC_BinaryOp<"div", []> { let summary = "Division operation"; let description = [{ diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td index 134ef04f26dd4..e75b06e57e543 100644 --- a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td +++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td @@ -185,4 +185,19 @@ class EmitC_LValueOf allowedTypes> : "::mlir::emitc::LValueType" >; +class EmitC_TypesMatchOnElementType< + string summary, string lhsArg, string rhsArg, string transformL, string transformR, + string comparator = "std::equal_to<>()" +> : PredOpTrait +> { + string lhs = lhsArg; + string rhs = rhsArg; + string transformerL = transformL; + string transformerR = transformR; +} + #endif // MLIR_DIALECT_EMITC_IR_EMITCTYPES diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp index 11f866c103639..0a382d812f362 100644 --- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp +++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp @@ -122,7 +122,7 @@ static Value calculateMemrefTotalSizeBytes(Location loc, MemRefType memrefType, return totalSizeBytes.getResult(); } -static emitc::ApplyOp +static emitc::AddressOfOp createPointerFromEmitcArray(Location loc, OpBuilder &builder, TypedValue arrayValue) { @@ -133,9 +133,9 @@ createPointerFromEmitcArray(Location loc, OpBuilder &builder, llvm::SmallVector indices(arrayType.getRank(), zeroIndex); emitc::SubscriptOp subPtr = emitc::SubscriptOp::create(builder, loc, arrayValue, ValueRange(indices)); - emitc::ApplyOp ptr = emitc::ApplyOp::create( + emitc::AddressOfOp ptr = emitc::AddressOfOp::create( builder, loc, emitc::PointerType::get(arrayType.getElementType()), - builder.getStringAttr("&"), subPtr); + subPtr); return ptr; } @@ -225,12 +225,12 @@ struct ConvertCopy final : public OpConversionPattern { auto srcArrayValue = cast>(operands.getSource()); - emitc::ApplyOp srcPtr = + emitc::AddressOfOp srcPtr = createPointerFromEmitcArray(loc, rewriter, srcArrayValue); auto targetArrayValue = cast>(operands.getTarget()); - emitc::ApplyOp targetPtr = + emitc::AddressOfOp targetPtr = createPointerFromEmitcArray(loc, rewriter, targetArrayValue); emitc::CallOpaqueOp memCpyCall = emitc::CallOpaqueOp::create( @@ -319,8 +319,8 @@ struct ConvertGetGlobal final emitc::GetGlobalOp globalLValue = emitc::GetGlobalOp::create( rewriter, op.getLoc(), lvalueType, operands.getNameAttr()); emitc::PointerType pointerType = emitc::PointerType::get(resultTy); - rewriter.replaceOpWithNewOp( - op, pointerType, rewriter.getStringAttr("&"), globalLValue); + rewriter.replaceOpWithNewOp(op, pointerType, + globalLValue); return success(); } rewriter.replaceOpWithNewOp(op, resultTy, diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp index d478220221f7a..b0566dd10f490 100644 --- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp +++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp @@ -225,6 +225,21 @@ FailureOr> parseFormatString( return items; } +//===----------------------------------------------------------------------===// +// AddressOfOp +//===----------------------------------------------------------------------===// + +LogicalResult AddressOfOp::verify() { + emitc::LValueType referenceType = getReference().getType(); + emitc::PointerType resultType = getResult().getType(); + + if (referenceType.getValueType() != resultType.getPointee()) + return emitOpError("requires result to be a pointer to the type " + "referenced by operand"); + + return success(); +} + //===----------------------------------------------------------------------===// // AddOp //===----------------------------------------------------------------------===// @@ -379,6 +394,20 @@ LogicalResult emitc::ConstantOp::verify() { OpFoldResult emitc::ConstantOp::fold(FoldAdaptor adaptor) { return getValue(); } +//===----------------------------------------------------------------------===// +// DereferenceOp +//===----------------------------------------------------------------------===// + +LogicalResult DereferenceOp::verify() { + emitc::PointerType pointerType = getPointer().getType(); + + if (pointerType.getPointee() != getResult().getType().getValueType()) + return emitOpError("requires result to be an lvalue of the type " + "pointed to by operand"); + + return success(); +} + //===----------------------------------------------------------------------===// // ExpressionOp //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp index 6bd76bb1ffc4b..01978d483a4f7 100644 --- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp +++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp @@ -70,6 +70,7 @@ static inline LogicalResult interleaveCommaWithError(const Container &c, /// imply higher precedence. static FailureOr getOperatorPrecedence(Operation *operation) { return llvm::TypeSwitch>(operation) + .Case([&](auto op) { return 15; }) .Case([&](auto op) { return 12; }) .Case([&](auto op) { return 15; }) .Case([&](auto op) { return 7; }) @@ -393,6 +394,15 @@ static bool shouldBeInlined(ExpressionOp expressionOp) { return false; } +static LogicalResult printOperation(CppEmitter &emitter, + emitc::DereferenceOp dereferenceOp) { + std::string out; + llvm::raw_string_ostream ss(out); + ss << "*" << emitter.getOrCreateName(dereferenceOp.getPointer()); + emitter.cacheDeferredOpResult(dereferenceOp.getResult(), out); + return success(); +} + static LogicalResult printOperation(CppEmitter &emitter, emitc::GetFieldOp getFieldOp) { emitter.cacheDeferredOpResult(getFieldOp.getResult(), @@ -476,6 +486,17 @@ static LogicalResult printConstantOp(CppEmitter &emitter, Operation *operation, return emitter.emitAttribute(operation->getLoc(), value); } +static LogicalResult printOperation(CppEmitter &emitter, + emitc::AddressOfOp addressOfOp) { + raw_ostream &os = emitter.ostream(); + Operation &op = *addressOfOp.getOperation(); + + if (failed(emitter.emitAssignPrefix(op))) + return failure(); + os << "&"; + return emitter.emitOperand(addressOfOp.getReference()); +} + static LogicalResult printOperation(CppEmitter &emitter, emitc::ConstantOp constantOp) { Operation *operation = constantOp.getOperation(); @@ -1769,14 +1790,14 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) { .Case( [&](auto op) { return printOperation(*this, op); }) // EmitC ops. - .Case) { // CHECK: %[[UNREALIZED_CONVERSION_CAST_1:.*]] = builtin.unrealized_conversion_cast %[[CAST_0]] : !emitc.ptr to !emitc.array<999xi32> // CHECK: %[[VAL_1:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index // CHECK: %[[SUBSCRIPT_0:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_0]]{{\[}}%[[VAL_1]]] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK: %[[APPLY_0:.*]] = emitc.apply "&"(%[[SUBSCRIPT_0]]) : (!emitc.lvalue) -> !emitc.ptr +// CHECK: %[[ADDRESS_OF_0:.*]] = emitc.address_of %[[SUBSCRIPT_0]] : !emitc.lvalue // CHECK: %[[VAL_2:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index // CHECK: %[[SUBSCRIPT_1:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_1]]{{\[}}%[[VAL_2]]] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK: %[[APPLY_1:.*]] = emitc.apply "&"(%[[SUBSCRIPT_1]]) : (!emitc.lvalue) -> !emitc.ptr +// CHECK: %[[ADDRESS_OF_1:.*]] = emitc.address_of %[[SUBSCRIPT_1]] : !emitc.lvalue // CHECK: %[[CALL_OPAQUE_2:.*]] = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t // CHECK: %[[VAL_3:.*]] = "emitc.constant"() <{value = 999 : index}> : () -> index // CHECK: %[[MUL_1:.*]] = emitc.mul %[[CALL_OPAQUE_2]], %[[VAL_3]] : (!emitc.size_t, index) -> !emitc.size_t -// CHECK: emitc.call_opaque "memcpy"(%[[APPLY_1]], %[[APPLY_0]], %[[MUL_1]]) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () +// CHECK: emitc.call_opaque "memcpy"(%[[ADDRESS_OF_1]], %[[ADDRESS_OF_0]], %[[MUL_1]]) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () // CHECK: %[[CALL_OPAQUE_3:.*]] = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t // CHECK: %[[VAL_4:.*]] = "emitc.constant"() <{value = 999 : index}> : () -> index // CHECK: %[[MUL_2:.*]] = emitc.mul %[[CALL_OPAQUE_3]], %[[VAL_4]] : (!emitc.size_t, index) -> !emitc.size_t @@ -42,13 +42,13 @@ func.func @alloc_copy(%arg0: memref<999xi32>) { // CHECK: %[[UNREALIZED_CONVERSION_CAST_2:.*]] = builtin.unrealized_conversion_cast %[[CAST_1]] : !emitc.ptr to !emitc.array<999xi32> // CHECK: %[[VAL_5:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index // CHECK: %[[SUBSCRIPT_2:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_0]]{{\[}}%[[VAL_5]]] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK: %[[APPLY_2:.*]] = emitc.apply "&"(%[[SUBSCRIPT_2]]) : (!emitc.lvalue) -> !emitc.ptr +// CHECK: %[[ADDRESS_OF_2:.*]] = emitc.address_of %[[SUBSCRIPT_2]] : !emitc.lvalue // CHECK: %[[VAL_6:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index // CHECK: %[[SUBSCRIPT_3:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_2]]{{\[}}%[[VAL_6]]] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK: %[[APPLY_3:.*]] = emitc.apply "&"(%[[SUBSCRIPT_3]]) : (!emitc.lvalue) -> !emitc.ptr +// CHECK: %[[ADDRESS_OF_3:.*]] = emitc.address_of %[[SUBSCRIPT_3]] : !emitc.lvalue // CHECK: %[[CALL_OPAQUE_5:.*]] = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t // CHECK: %[[VAL_7:.*]] = "emitc.constant"() <{value = 999 : index}> : () -> index // CHECK: %[[MUL_3:.*]] = emitc.mul %[[CALL_OPAQUE_5]], %[[VAL_7]] : (!emitc.size_t, index) -> !emitc.size_t -// CHECK: emitc.call_opaque "memcpy"(%[[APPLY_3]], %[[APPLY_2]], %[[MUL_3]]) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () +// CHECK: emitc.call_opaque "memcpy"(%[[ADDRESS_OF_3]], %[[ADDRESS_OF_2]], %[[MUL_3]]) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () // CHECK: return // CHECK: } diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir index 829f267743d93..3de2d25f2b0d4 100644 --- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir @@ -17,14 +17,14 @@ func.func @copying(%arg0 : memref<9x4x5x7xf32>, %arg1 : memref<9x4x5x7xf32>) { // CHECK: %[[UNREALIZED_CONVERSION_CAST_1:.*]] = builtin.unrealized_conversion_cast %[[ARG0]] : memref<9x4x5x7xf32> to !emitc.array<9x4x5x7xf32> // CHECK: %[[VAL_0:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index // CHECK: %[[SUBSCRIPT_0:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_1]]{{\[}}%[[VAL_0]], %[[VAL_0]], %[[VAL_0]], %[[VAL_0]]] : (!emitc.array<9x4x5x7xf32>, index, index, index, index) -> !emitc.lvalue -// CHECK: %[[APPLY_0:.*]] = emitc.apply "&"(%[[SUBSCRIPT_0]]) : (!emitc.lvalue) -> !emitc.ptr +// CHECK: %[[ADDRESS_OF_0:.*]] = emitc.address_of %[[SUBSCRIPT_0]] : !emitc.lvalue // CHECK: %[[VAL_1:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index // CHECK: %[[SUBSCRIPT_1:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_0]]{{\[}}%[[VAL_1]], %[[VAL_1]], %[[VAL_1]], %[[VAL_1]]] : (!emitc.array<9x4x5x7xf32>, index, index, index, index) -> !emitc.lvalue -// CHECK: %[[APPLY_1:.*]] = emitc.apply "&"(%[[SUBSCRIPT_1]]) : (!emitc.lvalue) -> !emitc.ptr +// CHECK: %[[ADDRESS_OF_1:.*]] = emitc.address_of %[[SUBSCRIPT_1]] : !emitc.lvalue // CHECK: %[[CALL_OPAQUE_0:.*]] = emitc.call_opaque "sizeof"() {args = [f32]} : () -> !emitc.size_t // CHECK: %[[VAL_2:.*]] = "emitc.constant"() <{value = 1260 : index}> : () -> index // CHECK: %[[MUL_0:.*]] = emitc.mul %[[CALL_OPAQUE_0]], %[[VAL_2]] : (!emitc.size_t, index) -> !emitc.size_t -// CHECK: emitc.call_opaque "memcpy"(%[[APPLY_1]], %[[APPLY_0]], %[[MUL_0]]) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () +// CHECK: emitc.call_opaque "memcpy"(%[[ADDRESS_OF_1]], %[[ADDRESS_OF_0]], %[[MUL_0]]) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () // CHECK: return // CHECK: } diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir index 2b4eda37903d4..c7b043b8e2370 100644 --- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir @@ -53,7 +53,7 @@ module @globals { // CHECK-NEXT: emitc.get_global @public_global : !emitc.array<3x7xf32> %0 = memref.get_global @public_global : memref<3x7xf32> // CHECK-NEXT: emitc.get_global @__constant_xi32 : !emitc.lvalue - // CHECK-NEXT: emitc.apply "&"(%1) : (!emitc.lvalue) -> !emitc.ptr + // CHECK-NEXT: emitc.address_of %1 : !emitc.lvalue %1 = memref.get_global @__constant_xi32 : memref return } diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir index f285196d466ce..d1601bed29ca9 100644 --- a/mlir/test/Dialect/EmitC/invalid_ops.mlir +++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir @@ -914,3 +914,19 @@ func.func @test_for_unmatch_type(%arg0: index) { ) : (index, index, index) -> () return } + +// ----- + +func.func @address_of(%arg0: !emitc.lvalue) { + // expected-error @+1 {{failed to verify that input and result reference the same type}} + %1 = "emitc.address_of"(%arg0) : (!emitc.lvalue) -> !emitc.ptr + return +} + +// ----- + +func.func @dereference(%arg0: !emitc.ptr) { + // expected-error @+1 {{failed to verify that input and result reference the same type}} + %1 = "emitc.dereference"(%arg0) : (!emitc.ptr) -> !emitc.lvalue + return +} diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir index 1259748dfce84..b2c8b843ec14b 100644 --- a/mlir/test/Dialect/EmitC/ops.mlir +++ b/mlir/test/Dialect/EmitC/ops.mlir @@ -355,3 +355,13 @@ func.func @do(%arg0 : !emitc.ptr) { return } + +func.func @address_of(%arg0: !emitc.lvalue) { + %1 = emitc.address_of %arg0 : !emitc.lvalue + return +} + +func.func @dereference(%arg0: !emitc.ptr) { + %1 = emitc.dereference %arg0 : !emitc.ptr + return +} diff --git a/mlir/test/Target/Cpp/common-cpp.mlir b/mlir/test/Target/Cpp/common-cpp.mlir index 294e6af65bf14..abf85c8e9a359 100644 --- a/mlir/test/Target/Cpp/common-cpp.mlir +++ b/mlir/test/Target/Cpp/common-cpp.mlir @@ -105,6 +105,25 @@ func.func @apply() -> !emitc.ptr { return %1 : !emitc.ptr } + +// CHECK-LABEL: void address_of() { +func.func @address_of() { + // CHECK-NEXT: int32_t [[V1:[^ ]*]]; + %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue + // CHECK-NEXT: int32_t* [[V2:[^ ]*]] = &[[V1]]; + %1 = emitc.address_of %0 : !emitc.lvalue + return +} + +// CHECK-LABEL: void dereference +// CHECK-SAME: (int32_t* [[ARG0:[^ ]*]]) { +func.func @dereference(%arg0: !emitc.ptr) { + // CHECK: int32_t [[V1:[^ ]*]] = *[[ARG0]]; + %2 = emitc.dereference %arg0 : !emitc.ptr + emitc.load %2 : !emitc.lvalue + return +} + // CHECK: void array_type(int32_t v1[3], float v2[10][20]) func.func @array_type(%arg0: !emitc.array<3xi32>, %arg1: !emitc.array<10x20xf32>) { return diff --git a/mlir/test/Target/Cpp/expressions.mlir b/mlir/test/Target/Cpp/expressions.mlir index 9f1c816ddabbc..2de94d0b11fc8 100644 --- a/mlir/test/Target/Cpp/expressions.mlir +++ b/mlir/test/Target/Cpp/expressions.mlir @@ -314,14 +314,14 @@ func.func @different_expressions(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) return %v_load : i32 } -// CPP-DEFAULT: int32_t expression_with_dereference(int32_t [[VAL_1:v[0-9]+]], int32_t* [[VAL_2]]) { +// CPP-DEFAULT: int32_t expression_with_dereference_apply(int32_t [[VAL_1:v[0-9]+]], int32_t* [[VAL_2]]) { // CPP-DEFAULT-NEXT: return *([[VAL_2]] - [[VAL_1]]); // CPP-DEFAULT-NEXT: } -// CPP-DECLTOP: int32_t expression_with_dereference(int32_t [[VAL_1:v[0-9]+]], int32_t* [[VAL_2]]) { +// CPP-DECLTOP: int32_t expression_with_dereference_apply(int32_t [[VAL_1:v[0-9]+]], int32_t* [[VAL_2]]) { // CPP-DECLTOP-NEXT: return *([[VAL_2]] - [[VAL_1]]); // CPP-DECLTOP-NEXT: } -emitc.func @expression_with_dereference(%arg1: i32, %arg2: !emitc.ptr) -> i32 { +emitc.func @expression_with_dereference_apply(%arg1: i32, %arg2: !emitc.ptr) -> i32 { %c = emitc.expression %arg1, %arg2 : (i32, !emitc.ptr) -> i32 { %e = emitc.sub %arg2, %arg1 : (!emitc.ptr, i32) -> !emitc.ptr %d = emitc.apply "*"(%e) : (!emitc.ptr) -> i32 @@ -330,6 +330,28 @@ emitc.func @expression_with_dereference(%arg1: i32, %arg2: !emitc.ptr) -> i return %c : i32 } +// CPP-DEFAULT: bool expression_with_address_taken_apply(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t* [[VAL_3]]) { +// CPP-DEFAULT-NEXT: int32_t [[VAL_4:v[0-9]+]] = 42; +// CPP-DEFAULT-NEXT: return &[[VAL_4]] - [[VAL_2]] < [[VAL_3]]; +// CPP-DEFAULT-NEXT: } + +// CPP-DECLTOP: bool expression_with_address_taken_apply(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t* [[VAL_3]]) { +// CPP-DECLTOP-NEXT: int32_t [[VAL_4:v[0-9]+]]; +// CPP-DECLTOP-NEXT: [[VAL_4]] = 42; +// CPP-DECLTOP-NEXT: return &[[VAL_4]] - [[VAL_2]] < [[VAL_3]]; +// CPP-DECLTOP-NEXT: } + +func.func @expression_with_address_taken_apply(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr) -> i1 { + %a = "emitc.variable"(){value = 42 : i32} : () -> !emitc.lvalue + %c = emitc.expression %arg1, %arg2, %a : (i32, !emitc.ptr, !emitc.lvalue) -> i1 { + %d = emitc.apply "&"(%a) : (!emitc.lvalue) -> !emitc.ptr + %e = emitc.sub %d, %arg1 : (!emitc.ptr, i32) -> !emitc.ptr + %f = emitc.cmp lt, %e, %arg2 : (!emitc.ptr, !emitc.ptr) -> i1 + emitc.yield %f : i1 + } + return %c : i1 +} + // CPP-DEFAULT: bool expression_with_address_taken(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t* [[VAL_3]]) { // CPP-DEFAULT-NEXT: int32_t [[VAL_4:v[0-9]+]] = 42; // CPP-DEFAULT-NEXT: return &[[VAL_4]] - [[VAL_2]] < [[VAL_3]]; @@ -344,7 +366,7 @@ emitc.func @expression_with_dereference(%arg1: i32, %arg2: !emitc.ptr) -> i func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr) -> i1 { %a = "emitc.variable"(){value = 42 : i32} : () -> !emitc.lvalue %c = emitc.expression %arg1, %arg2, %a : (i32, !emitc.ptr, !emitc.lvalue) -> i1 { - %d = emitc.apply "&"(%a) : (!emitc.lvalue) -> !emitc.ptr + %d = emitc.address_of %a : !emitc.lvalue %e = emitc.sub %d, %arg1 : (!emitc.ptr, i32) -> !emitc.ptr %f = emitc.cmp lt, %e, %arg2 : (!emitc.ptr, !emitc.ptr) -> i1 emitc.yield %f : i1