@@ -115,6 +115,119 @@ def ConstantOp : CIR_Op<"const",
115115 let hasFolder = 1;
116116}
117117
118+ //===----------------------------------------------------------------------===//
119+ // AllocaOp
120+ //===----------------------------------------------------------------------===//
121+
122+ class AllocaTypesMatchWith<string summary, string lhsArg, string rhsArg,
123+ string transform, string comparator = "std::equal_to<>()">
124+ : PredOpTrait<summary, CPred<
125+ comparator # "(" #
126+ !subst("$_self", "$" # lhsArg # ".getType()", transform) #
127+ ", $" # rhsArg # ")">> {
128+ string lhs = lhsArg;
129+ string rhs = rhsArg;
130+ string transformer = transform;
131+ }
132+
133+ def AllocaOp : CIR_Op<"alloca", [
134+ AllocaTypesMatchWith<"'allocaType' matches pointee type of 'addr'",
135+ "addr", "allocaType",
136+ "cast<PointerType>($_self).getPointee()">,
137+ DeclareOpInterfaceMethods<PromotableAllocationOpInterface>]> {
138+ let summary = "Defines a scope-local variable";
139+ let description = [{
140+ The `cir.alloca` operation defines a scope-local variable.
141+
142+ The presence of the `const` attribute indicates that the local variable is
143+ declared with C/C++ `const` keyword.
144+
145+ The result type is a pointer to the input's type.
146+
147+ Example:
148+
149+ ```mlir
150+ // int count;
151+ %0 = cir.alloca i32, !cir.ptr<i32>, ["count"] {alignment = 4 : i64}
152+
153+ // int *ptr;
154+ %1 = cir.alloca !cir.ptr<i32>, !cir.ptr<!cir.ptr<i32>>, ["ptr"] {alignment = 8 : i64}
155+ ...
156+ ```
157+ }];
158+
159+ let arguments = (ins
160+ TypeAttr:$allocaType,
161+ StrAttr:$name,
162+ UnitAttr:$init,
163+ UnitAttr:$constant,
164+ ConfinedAttr<OptionalAttr<I64Attr>, [IntMinValue<0>]>:$alignment,
165+ OptionalAttr<ArrayAttr>:$annotations
166+ );
167+
168+ let results = (outs Res<CIR_PointerType, "",
169+ [MemAlloc<AutomaticAllocationScopeResource>]>:$addr);
170+
171+ let skipDefaultBuilders = 1;
172+ let builders = [
173+ OpBuilder<(ins "mlir::Type":$addr,
174+ "mlir::Type":$allocaType,
175+ "llvm::StringRef":$name,
176+ "mlir::IntegerAttr":$alignment)>
177+ ];
178+
179+ let extraClassDeclaration = [{
180+ // Whether the alloca input type is a pointer.
181+ bool isPointerType() { return ::mlir::isa<::cir::PointerType>(getAllocaType()); }
182+ }];
183+
184+ let assemblyFormat = [{
185+ $allocaType `,` qualified(type($addr)) `,`
186+ `[` $name
187+ (`,` `init` $init^)?
188+ (`,` `const` $constant^)?
189+ `]`
190+ ($annotations^)? attr-dict
191+ }];
192+
193+ let hasVerifier = 0;
194+ }
195+
196+ //===----------------------------------------------------------------------===//
197+ // LoadOp
198+ //===----------------------------------------------------------------------===//
199+
200+ def LoadOp : CIR_Op<"load", [
201+ TypesMatchWith<"type of 'result' matches pointee type of 'addr'",
202+ "addr", "result",
203+ "cast<PointerType>($_self).getPointee()">,
204+ DeclareOpInterfaceMethods<PromotableMemOpInterface>]> {
205+
206+ let summary = "Load value from memory adddress";
207+ let description = [{
208+ `cir.load` reads a value (lvalue to rvalue conversion) given an address
209+ backed up by a `cir.ptr` type.
210+
211+ Example:
212+
213+ ```mlir
214+
215+ // Read from local variable, address in %0.
216+ %1 = cir.load %0 : !cir.ptr<i32>, i32
217+ ```
218+ }];
219+
220+ let arguments = (ins Arg<CIR_PointerType, "the address to load from",
221+ [MemRead]>:$addr);
222+ let results = (outs CIR_AnyType:$result);
223+
224+ let assemblyFormat = [{
225+ $addr `:` qualified(type($addr)) `,` type($result) attr-dict
226+ }];
227+
228+ // FIXME: add verifier.
229+ }
230+
118231//===----------------------------------------------------------------------===//
119232// ReturnOp
120233//===----------------------------------------------------------------------===//
0 commit comments