@@ -139,17 +139,17 @@ def EmitC_ApplyOp : EmitC_Op<"apply", [CExpression]> {
139139
140140 ```mlir
141141 // Custom form of applying the & operator.
142- %0 = emitc.apply "&"(%arg0) : (i32) -> !emitc.ptr<i32>
142+ %0 = emitc.apply "&"(%arg0) : (!emitc.lvalue< i32> ) -> !emitc.ptr<i32>
143143
144144 // Generic form of the same operation.
145145 %0 = "emitc.apply"(%arg0) {applicableOperator = "&"}
146- : (i32) -> !emitc.ptr<i32>
146+ : (!emitc.lvalue< i32> ) -> !emitc.ptr<i32>
147147
148148 ```
149149 }];
150150 let arguments = (ins
151151 Arg<StrAttr, "the operator to apply">:$applicableOperator,
152- EmitCType:$operand
152+ AnyTypeOf<[ EmitCType, EmitC_LValueType]> :$operand
153153 );
154154 let results = (outs EmitCType:$result);
155155 let assemblyFormat = [{
@@ -895,6 +895,35 @@ def EmitC_LogicalOrOp : EmitC_BinaryOp<"logical_or", [CExpression]> {
895895 let assemblyFormat = "operands attr-dict `:` type(operands)";
896896}
897897
898+ def EmitC_LoadOp : EmitC_Op<"load", [
899+ TypesMatchWith<"result type matches value type of 'operand'",
900+ "operand", "result",
901+ "::llvm::cast<LValueType>($_self).getValueType()">
902+ ]> {
903+ let summary = "Load an lvalue into an SSA value.";
904+ let description = [{
905+ This operation loads the content of a modifiable lvalue into an SSA value.
906+ Modifications of the lvalue executed after the load are not observable on
907+ the produced value.
908+
909+ Example:
910+
911+ ```mlir
912+ %1 = emitc.load %0 : !emitc.lvalue<i32>
913+ ```
914+ ```c++
915+ // Code emitted for the operation above.
916+ int32_t v2 = v1;
917+ ```
918+ }];
919+
920+ let arguments = (ins
921+ Res<EmitC_LValueType, "", [MemRead<DefaultResource, 0, FullEffect>]>:$operand);
922+ let results = (outs AnyType:$result);
923+
924+ let assemblyFormat = "$operand attr-dict `:` type($operand)";
925+ }
926+
898927def EmitC_MulOp : EmitC_BinaryOp<"mul", [CExpression]> {
899928 let summary = "Multiplication operation";
900929 let description = [{
@@ -977,15 +1006,15 @@ def EmitC_MemberOp : EmitC_Op<"member"> {
9771006
9781007 ```mlir
9791008 %0 = "emitc.member" (%arg0) {member = "a"}
980- : (!emitc.opaque<"mystruct">) -> i32
1009+ : (!emitc.lvalue<!emitc. opaque<"mystruct">> ) -> !emitc.lvalue< i32>
9811010 ```
9821011 }];
9831012
9841013 let arguments = (ins
9851014 Arg<StrAttr, "the member to access">:$member,
986- EmitC_OpaqueType:$operand
1015+ EmitC_LValueOf<[ EmitC_OpaqueType]> :$operand
9871016 );
988- let results = (outs EmitCType);
1017+ let results = (outs EmitC_LValueOf<[ EmitCType]> );
9891018}
9901019
9911020def EmitC_MemberOfPtrOp : EmitC_Op<"member_of_ptr"> {
@@ -998,15 +1027,16 @@ def EmitC_MemberOfPtrOp : EmitC_Op<"member_of_ptr"> {
9981027
9991028 ```mlir
10001029 %0 = "emitc.member_of_ptr" (%arg0) {member = "a"}
1001- : (!emitc.ptr<!emitc.opaque<"mystruct">>) -> i32
1030+ : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>)
1031+ -> !emitc.lvalue<i32>
10021032 ```
10031033 }];
10041034
10051035 let arguments = (ins
10061036 Arg<StrAttr, "the member to access">:$member,
1007- AnyTypeOf <[EmitC_OpaqueType,EmitC_PointerType]>:$operand
1037+ EmitC_LValueOf <[EmitC_OpaqueType,EmitC_PointerType]>:$operand
10081038 );
1009- let results = (outs EmitCType);
1039+ let results = (outs EmitC_LValueOf<[ EmitCType]> );
10101040}
10111041
10121042def EmitC_ConditionalOp : EmitC_Op<"conditional",
@@ -1090,28 +1120,29 @@ def EmitC_VariableOp : EmitC_Op<"variable", []> {
10901120
10911121 ```mlir
10921122 // Integer variable
1093- %0 = "emitc.variable"(){value = 42 : i32} : () -> i32
1123+ %0 = "emitc.variable"(){value = 42 : i32} : () -> !emitc.lvalue< i32>
10941124
10951125 // Variable emitted as `int32_t* = NULL;`
10961126 %1 = "emitc.variable"() {value = #emitc.opaque<"NULL">}
1097- : () -> !emitc.ptr<!emitc.opaque<"int32_t">>
1127+ : () -> !emitc.lvalue<!emitc. ptr<!emitc.opaque<"int32_t"> >>
10981128 ```
10991129
11001130 Since folding is not supported, it can be used with pointers.
11011131 As an example, it is valid to create pointers to `variable` operations
11021132 by using `apply` operations and pass these to a `call` operation.
11031133 ```mlir
1104- %0 = "emitc.variable"() {value = 0 : i32} : () -> i32
1105- %1 = "emitc.variable"() {value = 0 : i32} : () -> i32
1106- %2 = emitc.apply "&"(%0) : (i32) -> !emitc.ptr<i32>
1107- %3 = emitc.apply "&"(%1) : (i32) -> !emitc.ptr<i32>
1134+ %0 = "emitc.variable"() {value = 0 : i32} : () -> !emitc.lvalue< i32>
1135+ %1 = "emitc.variable"() {value = 0 : i32} : () -> !emitc.lvalue< i32>
1136+ %2 = emitc.apply "&"(%0) : (!emitc.lvalue< i32> ) -> !emitc.ptr<i32>
1137+ %3 = emitc.apply "&"(%1) : (!emitc.lvalue< i32> ) -> !emitc.ptr<i32>
11081138 emitc.call_opaque "write"(%2, %3)
11091139 : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> ()
11101140 ```
11111141 }];
11121142
11131143 let arguments = (ins EmitC_OpaqueOrTypedAttr:$value);
1114- let results = (outs EmitCType);
1144+ let results = (outs Res<AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>, "",
1145+ [MemAlloc<DefaultResource, 0, FullEffect>]>);
11151146
11161147 let hasVerifier = 1;
11171148}
@@ -1179,11 +1210,12 @@ def EmitC_GetGlobalOp : EmitC_Op<"get_global",
11791210
11801211 ```mlir
11811212 %x = emitc.get_global @foo : !emitc.array<2xf32>
1213+ %y = emitc.get_global @bar : !emitc.lvalue<i32>
11821214 ```
11831215 }];
11841216
11851217 let arguments = (ins FlatSymbolRefAttr:$name);
1186- let results = (outs EmitCType :$result);
1218+ let results = (outs AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]> :$result);
11871219 let assemblyFormat = "$name `:` type($result) attr-dict";
11881220}
11891221
@@ -1250,15 +1282,17 @@ def EmitC_AssignOp : EmitC_Op<"assign", []> {
12501282
12511283 ```mlir
12521284 // Integer variable
1253- %0 = "emitc.variable"(){value = 42 : i32} : () -> i32
1285+ %0 = "emitc.variable"(){value = 42 : i32} : () -> !emitc.lvalue< i32>
12541286 %1 = emitc.call_opaque "foo"() : () -> (i32)
12551287
12561288 // Assign emitted as `... = ...;`
1257- "emitc.assign"(%0, %1) : (i32, i32) -> ()
1289+ "emitc.assign"(%0, %1) : (!emitc.lvalue< i32> , i32) -> ()
12581290 ```
12591291 }];
12601292
1261- let arguments = (ins EmitCType:$var, EmitCType:$value);
1293+ let arguments = (ins
1294+ Res<EmitC_LValueType, "", [MemWrite<DefaultResource, 1, FullEffect>]>:$var,
1295+ EmitCType:$value);
12621296 let results = (outs);
12631297
12641298 let hasVerifier = 1;
@@ -1354,8 +1388,10 @@ def EmitC_SubscriptOp : EmitC_Op<"subscript", []> {
13541388 ```mlir
13551389 %i = index.constant 1
13561390 %j = index.constant 7
1357- %0 = emitc.subscript %arg0[%i, %j] : !emitc.array<4x8xf32>, index, index
1358- %1 = emitc.subscript %arg1[%i] : !emitc.ptr<i32>, index
1391+ %0 = emitc.subscript %arg0[%i, %j] : (!emitc.array<4x8xf32>, index, index)
1392+ -> !emitc.lvalue<f32>
1393+ %1 = emitc.subscript %arg1[%i] : (!emitc.ptr<i32>, index)
1394+ -> !emitc.lvalue<i32>
13591395 ```
13601396 }];
13611397 let arguments = (ins Arg<AnyTypeOf<[
@@ -1364,15 +1400,26 @@ def EmitC_SubscriptOp : EmitC_Op<"subscript", []> {
13641400 EmitC_PointerType]>,
13651401 "the value to subscript">:$value,
13661402 Variadic<EmitCType>:$indices);
1367- let results = (outs EmitCType :$result);
1403+ let results = (outs EmitC_LValueType :$result);
13681404
13691405 let builders = [
13701406 OpBuilder<(ins "TypedValue<ArrayType>":$array, "ValueRange":$indices), [{
1371- build($_builder, $_state, array.getType().getElementType(), array, indices);
1407+ build(
1408+ $_builder,
1409+ $_state,
1410+ emitc::LValueType::get(array.getType().getElementType()),
1411+ array,
1412+ indices
1413+ );
13721414 }]>,
13731415 OpBuilder<(ins "TypedValue<PointerType>":$pointer, "Value":$index), [{
1374- build($_builder, $_state, pointer.getType().getPointee(), pointer,
1375- ValueRange{index});
1416+ build(
1417+ $_builder,
1418+ $_state,
1419+ emitc::LValueType::get(pointer.getType().getPointee()),
1420+ pointer,
1421+ ValueRange{index}
1422+ );
13761423 }]>
13771424 ];
13781425
@@ -1416,7 +1463,7 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
14161463 emitc.yield
14171464 }
14181465 default {
1419- %3 = "emitc.variable "(){value = 42.0 : f32} : () -> f32
1466+ %3 = "emitc.constant "(){value = 42.0 : f32} : () -> f32
14201467 emitc.call_opaque "func2" (%3) : (f32) -> ()
14211468 }
14221469 ```
0 commit comments