diff --git a/include/vast/Dialect/HighLevel/HighLevelOps.hpp b/include/vast/Dialect/HighLevel/HighLevelOps.hpp index 690247176e..4efe894d61 100644 --- a/include/vast/Dialect/HighLevel/HighLevelOps.hpp +++ b/include/vast/Dialect/HighLevel/HighLevelOps.hpp @@ -86,4 +86,14 @@ namespace vast::hl namespace vast::hl { FuncOp getCallee(CallOp call); + + using funclike_ops = util::type_list< + hl::FuncOp, + hl::MethodOp, + hl::DtorOp, + hl::CtorOp + >; + + template< typename T > + concept function_like = funclike_ops::contains< T >; } \ No newline at end of file diff --git a/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td b/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td index 6a18f70d60..6b9ddc8132 100644 --- a/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td +++ b/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td @@ -101,7 +101,7 @@ def RefQualifier : I32EnumAttr< let cppNamespace = "::vast::hl"; } -def MethodOp +def MethodOp : FuncLikeOp< "method", (ins UnitAttr:$is_virtual, UnitAttr:$is_const, @@ -138,4 +138,32 @@ def MethodOp }]; } +def DtorOp + : FuncLikeOp< "dtor", + (ins UnitAttr:$is_virtual), + (ins CArg< "bool", "false" >:$is_virtual), + [{ + if (is_virtual) { + $_state.addAttribute( + "is_virtual", mlir::UnitAttr::get($_builder.getContext()) + ); + } + }] > +{ + let summary = "VAST high-level destructor definintion or declaration"; + + let assemblyFormat = [{ + $linkage (`virtual` $is_virtual^)? $sym_name custom< FunctionSignatureAndBody >($function_type, attr-dict, $body) + }]; +} + +def CtorOp : FuncLikeOp< "ctor" > +{ + let summary = "VAST high-level constructor definintion or declaration"; + + let assemblyFormat = [{ + $linkage $sym_name custom< FunctionSignatureAndBody >($function_type, attr-dict, $body) + }]; +} + #endif // VAST_DIALECT_HIGHLEVEL_IR_HIGHLEVELOPS_CXX \ No newline at end of file diff --git a/include/vast/Translation/CodeGen.hpp b/include/vast/Translation/CodeGen.hpp index cbd25aefff..f2b7f13c3d 100644 --- a/include/vast/Translation/CodeGen.hpp +++ b/include/vast/Translation/CodeGen.hpp @@ -90,6 +90,8 @@ namespace vast::cg using LabelTable = ScopedSymbolTable< const clang::LabelDecl*, hl::LabelDeclOp >; using FunctionsScope = ScopedSymbolTable< mangled_name_ref, hl::FuncOp >; using MethodsScope = ScopedSymbolTable< mangled_name_ref, hl::MethodOp >; + using DtorsScope = ScopedSymbolTable< mangled_name_ref, hl::DtorOp >; + using CtorsScope = ScopedSymbolTable< mangled_name_ref, hl::CtorOp >; using VariablesScope = ScopedSymbolTable< const clang::VarDecl *, Value >; struct CodegenScope { @@ -100,6 +102,8 @@ namespace vast::cg LabelTable labels; FunctionsScope funcdecls; MethodsScope methdecls; + DtorsScope dtordecls; + CtorsScope ctordecls; VariablesScope globs; }; @@ -600,6 +604,8 @@ namespace vast::cg .labels = _cgctx.labels, .funcdecls = _cgctx.funcdecls, .methdecls = _cgctx.methdecls, + .dtordecls = _cgctx.dtordecls, + .ctordecls = _cgctx.ctordecls, .globs = _cgctx.vars }); diff --git a/include/vast/Translation/CodeGenContext.hpp b/include/vast/Translation/CodeGenContext.hpp index 3d3897d3bf..78e7a582c9 100644 --- a/include/vast/Translation/CodeGenContext.hpp +++ b/include/vast/Translation/CodeGenContext.hpp @@ -81,6 +81,12 @@ namespace vast::cg using MethodDeclTable = scoped_table< mangled_name_ref, hl::MethodOp >; MethodDeclTable methdecls; + using DtorDeclTable = scoped_table< mangled_name_ref, hl::DtorOp >; + DtorDeclTable dtordecls; + + using CtorDeclTable = scoped_table< mangled_name_ref, hl::CtorOp >; + CtorDeclTable ctordecls; + using EnumDecls = scoped_table< const clang::EnumDecl *, hl::EnumDeclOp >; EnumDecls enumdecls; @@ -214,12 +220,24 @@ namespace vast::cg return symbol(methdecls, mangled, "undeclared method '" + mangled.name + "'", with_error); } - template< typename Op > + hl::DtorOp lookup_destructor(mangled_name_ref mangled, bool with_error = true) { + return symbol(dtordecls, mangled, "undeclared destructor '" + mangled.name + "'", with_error); + } + + hl::CtorOp lookup_constructor(mangled_name_ref mangled, bool with_error = true) { + return symbol(ctordecls, mangled, "undeclared constructor '" + mangled.name + "'", with_error); + } + + template< hl::function_like Op > Op declare(mangled_name_ref mangled, auto vast_decl_builder) { if constexpr (std::is_same_v< Op, hl::FuncOp >) { return declare< Op >(funcdecls, mangled, vast_decl_builder, mangled.name); - } else { + } else if constexpr (std::is_same_v< Op, hl::MethodOp >) { return declare< Op >(methdecls, mangled, vast_decl_builder, mangled.name); + } else if constexpr (std::is_same_v< Op, hl::DtorOp >) { + return declare< Op >(dtordecls, mangled, vast_decl_builder, mangled.name); + } else if constexpr (std::is_same_v< Op, hl::CtorOp >) { + return declare< Op >(ctordecls, mangled, vast_decl_builder, mangled.name); } } diff --git a/include/vast/Translation/CodeGenDeclVisitor.hpp b/include/vast/Translation/CodeGenDeclVisitor.hpp index 4471d2ba95..bcf451cc10 100644 --- a/include/vast/Translation/CodeGenDeclVisitor.hpp +++ b/include/vast/Translation/CodeGenDeclVisitor.hpp @@ -292,22 +292,27 @@ namespace vast::cg { return clang::GlobalDecl(decl, clang::CXXDtorType::Dtor_Complete); } + template< hl::function_like Op > + operation lookup_funclike(mangled_name_ref mangled) { + if constexpr (std::is_same_v< Op, hl::FuncOp >) { + return context().lookup_function(mangled, false /* emit no error */); + } else if constexpr (std::is_same_v< Op, hl::MethodOp >) { + return context().lookup_method(mangled, false /* emit no error */); + } else if constexpr (std::is_same_v< Op, hl::DtorOp >) { + return context().lookup_destructor(mangled, false /* emit no error */); + } else if constexpr (std::is_same_v< Op, hl::CtorOp >) { + return context().lookup_constructor(mangled, false /* emit no error */); + } + } + // FIXME: remove as this duplicates logic from codegen driver template< typename Op, typename Decl, typename Builder > operation VisitFunctionLikeDecl(const Decl *decl, Builder builder_callback) { auto gdecl = get_gdecl(decl); auto mangled = context().get_mangled_name(gdecl); - if constexpr (std::is_same_v< Op, hl::FuncOp >) { - if (auto fn = context().lookup_function(mangled, false /* emit no error */)) { - return fn; - } - } - - if constexpr (std::is_same_v< Op, hl::MethodOp >) { - if (auto fn = context().lookup_method(mangled, false /* emit no error */)) { - return fn; - } + if (auto fn = lookup_funclike< Op >(mangled)) { + return fn; } InsertionGuard guard(builder()); @@ -450,22 +455,14 @@ namespace vast::cg { } operation VisitCXXConstructorDecl(const clang::CXXConstructorDecl *decl) { - return VisitFunctionLikeDecl< hl::MethodOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { - return make< hl::MethodOp >(loc, name, type, linkage, - decl->isVirtual(), - decl->isConst(), - decl->isVolatile(), - convert_ref_qual(decl->getRefQualifier())); + return VisitFunctionLikeDecl< hl::CtorOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { + return make< hl::CtorOp >(loc, name, type, linkage); }); } operation VisitCXXDestructorDecl(const clang::CXXDestructorDecl *decl) { - return VisitFunctionLikeDecl< hl::MethodOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { - return make< hl::MethodOp >(loc, name, type, linkage, - decl->isVirtual(), - decl->isConst(), - decl->isVolatile(), - convert_ref_qual(decl->getRefQualifier())); + return VisitFunctionLikeDecl< hl::DtorOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { + return make< hl::DtorOp >(loc, name, type, linkage, decl->isVirtual()); }); } diff --git a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp index a3857e1634..decd9a4134 100644 --- a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp +++ b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp @@ -71,6 +71,14 @@ namespace vast::hl return verify_funclike(this); } + logical_result DtorOp::verify() { + return verify_funclike(this); + } + + logical_result CtorOp::verify() { + return verify_funclike(this); + } + ParseResult parseFunctionSignatureAndBody( Parser &parser, Attribute &funcion_type, mlir::NamedAttrList &attr_dict, Region &body ) { diff --git a/test/vast/Dialect/HighLevel/Cxx/class-a.cpp b/test/vast/Dialect/HighLevel/Cxx/class-a.cpp index 2bb19cb414..c97aa0c60f 100644 --- a/test/vast/Dialect/HighLevel/Cxx/class-a.cpp +++ b/test/vast/Dialect/HighLevel/Cxx/class-a.cpp @@ -2,7 +2,12 @@ // RUN: vast-cc --from-source %s > %t && vast-opt %t | diff -B %t - // CHECK: hl.class "A" : -class A {}; +class A { +// CHECK: hl.access protected +protected: + // CHECK: hl.dtor external virtual @_ZN1AD1Ev () + virtual ~A(); +}; // CHECK: hl.class "B" : class B {}; @@ -34,4 +39,7 @@ class C : public A, protected virtual B { // CHECK: hl.method external ref_rvalue @_ZNO1C5get_pEv () -> !hl.int int get_p() &&; + + // CHECK: hl.ctor external @_ZN1CC1Ei (!hl.lvalue) + C(int x); }; \ No newline at end of file