Skip to content

Commit e1b804f

Browse files
committed
[Moore] Implement new operator
Adds heap allocation support for class objects. - **New op:** `moore.class.new` - Allocates a new instance of a class symbol (`!moore.class.object<@C>`). - Implements `MemoryEffectsOpInterface` (reports `Allocate`). - Verifies that the referenced class symbol exists and is a valid `ClassDeclOp`. - **Importer:** - `ImportVerilog/Expressions.cpp` now lowers `new` expressions to `moore.class.new`. - Emits an error if a constructor call is present (not yet supported). - **Tests:** - Added `testModule3` in `classes.sv` to verify `new` lowering and expected IR.
1 parent 09ee6e7 commit e1b804f

File tree

4 files changed

+81
-0
lines changed

4 files changed

+81
-0
lines changed

include/circt/Dialect/Moore/MooreOps.td

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2395,5 +2395,22 @@ def ClassDeclOp
23952395
let hasVerifier = 1;
23962396
}
23972397

2398+
def ClassNewOp
2399+
: MooreOp<
2400+
"class.new", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
2401+
let summary = "Allocate a new class instance";
2402+
let description = [{
2403+
Allocates a new instance of class @C. This op does not call the constructor.
2404+
The result is a non-null `!moore.class.object<@C>` handle.
2405+
}];
2406+
2407+
let arguments = (ins);
2408+
let results = (outs ClassHandleType:$result);
2409+
2410+
let assemblyFormat = [{
2411+
`:` type($result) attr-dict
2412+
}];
2413+
let hasVerifier = 1;
2414+
}
23982415

23992416
#endif // CIRCT_DIALECT_MOORE_MOOREOPS

lib/Conversion/ImportVerilog/Expressions.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,22 @@ struct RvalueExprVisitor : public ExprVisitor {
15591559
return context.convertAssertionExpression(expr.body, loc);
15601560
}
15611561

1562+
Value visit(const slang::ast::NewClassExpression &expr) {
1563+
auto type = context.convertType(*expr.type);
1564+
auto classTy = dyn_cast<moore::ClassHandleType>(type);
1565+
if (!classTy)
1566+
return {};
1567+
1568+
auto newOp = moore::ClassNewOp::create(builder, loc, classTy, {});
1569+
auto constructor = expr.constructorCall();
1570+
if (!constructor)
1571+
return newOp.getResult();
1572+
1573+
mlir::emitError(loc) << "New expression requires constructor call, which "
1574+
"is not yet implemented!";
1575+
return {};
1576+
}
1577+
15621578
/// Emit an error for all other expressions.
15631579
template <typename T>
15641580
Value visit(T &&node) {

lib/Dialect/Moore/MooreOps.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,34 @@ LogicalResult ClassDeclOp::verify() {
13881388
return mlir::success();
13891389
}
13901390

1391+
LogicalResult ClassNewOp::verify() {
1392+
// The result is constrained to ClassHandleType in ODS, so this cast should be
1393+
// safe.
1394+
auto handleTy = cast<ClassHandleType>(getResult().getType());
1395+
mlir::SymbolRefAttr classSym = handleTy.getClassSym();
1396+
if (!classSym)
1397+
return emitOpError("result type is missing a class symbol");
1398+
1399+
// Resolve the referenced symbol starting from the nearest symbol table.
1400+
mlir::Operation *sym = mlir::SymbolTable::lookupNearestSymbolFrom(getOperation(), classSym);
1401+
if (!sym)
1402+
return emitOpError("referenced class symbol `")
1403+
<< classSym << "` was not found";
1404+
1405+
if (!llvm::isa<ClassDeclOp>(sym))
1406+
return emitOpError("symbol `")
1407+
<< classSym << "` does not name a `moore.class.classdecl`";
1408+
1409+
return mlir::success();
1410+
}
1411+
1412+
void ClassNewOp::getEffects(
1413+
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
1414+
&effects) {
1415+
// Always allocates heap memory.
1416+
effects.emplace_back(MemoryEffects::Allocate::get());
1417+
}
1418+
13911419
//===----------------------------------------------------------------------===//
13921420
// TableGen generated logic.
13931421
//===----------------------------------------------------------------------===//

test/Conversion/ImportVerilog/classes.sv

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,23 @@ module testModule2 #();
143143
testModuleClass t;
144144

145145
endmodule
146+
147+
/// Check calls to new without explicit constructor
148+
149+
// CHECK-LABEL: moore.module @testModule3() {
150+
// CHECK: [[T:%.*]] = moore.variable : <class<@"testModule3::testModuleClass">>
151+
// CHECK: moore.procedure initial {
152+
// CHECK: [[NEW:%.*]] = moore.class.new : <@"testModule3::testModuleClass">
153+
// CHECK: moore.blocking_assign [[T]], [[NEW]] : class<@"testModule3::testModuleClass">
154+
// CHECK: moore.return
155+
// CHECK: }
156+
// CHECK: moore.output
157+
158+
module testModule3;
159+
class testModuleClass;
160+
endclass
161+
testModuleClass t;
162+
initial begin
163+
t = new;
164+
end
165+
endmodule

0 commit comments

Comments
 (0)