From f5f711f4c3a767e843e4e64ee864847e3aba3366 Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Tue, 18 Jul 2023 11:44:59 +0200 Subject: [PATCH 1/8] test:hl:cxx: Move C++ tests to separate dir. --- test/vast/Dialect/HighLevel/{ => Cxx}/class-a.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/vast/Dialect/HighLevel/{ => Cxx}/class-a.cpp (100%) diff --git a/test/vast/Dialect/HighLevel/class-a.cpp b/test/vast/Dialect/HighLevel/Cxx/class-a.cpp similarity index 100% rename from test/vast/Dialect/HighLevel/class-a.cpp rename to test/vast/Dialect/HighLevel/Cxx/class-a.cpp From a662b58bc5c9df53efacc18a0c8c3f00402878b1 Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Tue, 18 Jul 2023 17:19:11 +0200 Subject: [PATCH 2/8] hl:cxx: Add `MethodOp`. --- .../vast/Dialect/HighLevel/HighLevelOps.td | 35 ++++++++++--------- .../vast/Dialect/HighLevel/HighLevelOpsCxx.td | 29 +++++++++++++++ include/vast/Translation/CodeGenContext.hpp | 12 +++++-- .../vast/Translation/CodeGenDeclVisitor.hpp | 30 +++++++++++----- lib/vast/Dialect/HighLevel/HighLevelOps.cpp | 22 ++++++++---- 5 files changed, 95 insertions(+), 33 deletions(-) diff --git a/include/vast/Dialect/HighLevel/HighLevelOps.td b/include/vast/Dialect/HighLevel/HighLevelOps.td index f7edaa30ca..47ad4a0b5e 100644 --- a/include/vast/Dialect/HighLevel/HighLevelOps.td +++ b/include/vast/Dialect/HighLevel/HighLevelOps.td @@ -43,12 +43,18 @@ def ScopeOp : HighLevel_Op< "scope", [NoTerminator] > let assemblyFormat = [{ $body attr-dict }]; } -def FuncOp : HighLevel_Op< "func", [ - AutomaticAllocationScope, CallableOpInterface, FunctionOpInterface, - IsolatedFromAbove, Symbol, NoTerminator -] > { - let summary = "VAST high-level function definintion or declaration"; - +class FuncLikeOp< string mnemonic, dag additional_args > + : HighLevel_Op< mnemonic, [ + AutomaticAllocationScope, CallableOpInterface, FunctionOpInterface, + IsolatedFromAbove, Symbol, NoTerminator ] > + , Arguments< !con((ins + SymbolNameAttr:$sym_name, + TypeAttrOf:$function_type, + DefaultValuedAttr:$linkage, + OptionalAttr:$sym_visibility, + OptionalAttr:$arg_attrs, + OptionalAttr:$res_attrs ), additional_args) > +{ let description = [{ Inspired by `cir::FuncOp` and `mlir::func::FuncOp`: > Operations within the function cannot implicitly capture values defined @@ -62,15 +68,6 @@ def FuncOp : HighLevel_Op< "func", [ `GlobalLinkageKind` attribute. }]; - let arguments =(ins - SymbolNameAttr:$sym_name, - TypeAttrOf:$function_type, - DefaultValuedAttr:$linkage, - OptionalAttr:$sym_visibility, - OptionalAttr:$arg_attrs, - OptionalAttr:$res_attrs - ); - let regions = (region AnyRegion:$body); let skipDefaultBuilders = 1; @@ -139,11 +136,15 @@ def FuncOp : HighLevel_Op< "func", [ bool isDeclaration() { return isExternal(); } }]; + let hasVerifier = 1; +} + +def FuncOp : FuncLikeOp< "func", (ins) > { + let summary = "VAST high-level function definintion or declaration"; + let assemblyFormat = [{ $linkage $sym_name custom< FunctionSignatureAndBody >($function_type, attr-dict, $body) }]; - - let hasVerifier = 1; } def TypeDeclOp diff --git a/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td b/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td index 91db69aea0..cd7c84f4c5 100644 --- a/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td +++ b/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td @@ -85,4 +85,33 @@ def ThisOp }]; } +def NoRef : + I32EnumAttrCase<"ref_none", 0, "ref_none">; +def LValueRef : + I32EnumAttrCase<"ref_lvalue", 1, "ref_lvalue">; +def RValueRef : + I32EnumAttrCase<"ref_rvalue", 2, "ref_rvalue">; + +def RefQualifier : I32EnumAttr< + "RefQualifier", "ref qualifier", + [ + NoRef, LValueRef, RValueRef + ]> +{ + let cppNamespace = "::vast::hl"; +} + +def MethodOp + : FuncLikeOp< "method", (ins + UnitAttr:$is_virtual, + RefQualifier:$ref, + CVQualifiers:$cv) > +{ + let summary = "VAST high-level method definintion or declaration"; + + let assemblyFormat = [{ + $linkage (`virtual` $is_virtual^)? $ref $cv $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/CodeGenContext.hpp b/include/vast/Translation/CodeGenContext.hpp index f394919bbb..2d384176fe 100644 --- a/include/vast/Translation/CodeGenContext.hpp +++ b/include/vast/Translation/CodeGenContext.hpp @@ -78,6 +78,9 @@ namespace vast::cg using FuncDeclTable = scoped_table< mangled_name_ref, hl::FuncOp >; FuncDeclTable funcdecls; + using MethodDeclTable = scoped_table< mangled_name_ref, hl::MethodOp >; + MethodDeclTable methdecls; + using EnumDecls = scoped_table< const clang::EnumDecl *, hl::EnumDeclOp >; EnumDecls enumdecls; @@ -207,8 +210,13 @@ namespace vast::cg return symbol(funcdecls, mangled, "undeclared function '" + mangled.name + "'", with_error); } - hl::FuncOp declare(mangled_name_ref mangled, auto vast_decl_builder) { - return declare< hl::FuncOp >(funcdecls, mangled, vast_decl_builder, mangled.name); + template< typename 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 { + return declare< Op >(methdecls, mangled, vast_decl_builder, mangled.name); + } } mlir_value declare(const clang::VarDecl *decl, mlir_value vast_value) { diff --git a/include/vast/Translation/CodeGenDeclVisitor.hpp b/include/vast/Translation/CodeGenDeclVisitor.hpp index 339c49044c..70570f3089 100644 --- a/include/vast/Translation/CodeGenDeclVisitor.hpp +++ b/include/vast/Translation/CodeGenDeclVisitor.hpp @@ -85,7 +85,7 @@ namespace vast::cg { // make function header, that will be later filled with function body // or returned as declaration in the case of external function - auto fn = context().declare(mangled_name, [&] () { + auto fn = context().template declare< hl::FuncOp >(mangled_name, [&] () { return make< hl::FuncOp >(loc, mangled_name.name, fty, linkage); }); @@ -293,8 +293,8 @@ namespace vast::cg { } // FIXME: remove as this duplicates logic from codegen driver - template< typename Decl > - operation VisitFunctionLikeDecl(const Decl *decl) { + 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); @@ -402,12 +402,12 @@ namespace vast::cg { auto linkage = hl::get_function_linkage(gdecl); - auto fn = context().declare(mangled, [&] () { + auto fn = context().template declare< Op >(mangled, [&] () { auto loc = meta_location(decl); auto type = visit(decl->getFunctionType()).template cast< mlir::FunctionType >(); // make function header, that will be later filled with function body // or returned as declaration in the case of external function - return make< hl::FuncOp >(loc, mangled.name, type, linkage); + return builder_callback(loc, mangled.name, type, linkage); }); if (!is_definition) { @@ -426,15 +426,27 @@ namespace vast::cg { } operation VisitFunctionDecl(const clang::FunctionDecl *decl) { - return VisitFunctionLikeDecl(decl); + return VisitFunctionLikeDecl< hl::FuncOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { + return make< hl::FuncOp >(loc, name, type, linkage); + }); + } + + operation VisitCXXMethodDecl(const clang::CXXMethodDecl *decl) { + return VisitFunctionLikeDecl< hl::MethodOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { + return make< hl::MethodOp >(loc, name, type, linkage); + }); } operation VisitCXXConstructorDecl(const clang::CXXConstructorDecl *decl) { - return VisitFunctionLikeDecl(decl); + return VisitFunctionLikeDecl< hl::FuncOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { + return make< hl::FuncOp >(loc, name, type, linkage); + }); } operation VisitCXXDestructorDecl(const clang::CXXDestructorDecl *decl) { - return VisitFunctionLikeDecl(decl); + return VisitFunctionLikeDecl< hl::FuncOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { + return make< hl::FuncOp >(loc, name, type, linkage); + }); } // @@ -685,6 +697,8 @@ namespace vast::cg { visit(ctor); } else if (auto dtor = clang::dyn_cast< clang::CXXDestructorDecl >(child)) { visit(dtor); + } else if (auto method = clang::dyn_cast< clang::CXXMethodDecl >(child)) { + visit(method); } else if (auto func = clang::dyn_cast< clang::FunctionDecl >(child)) { auto name = func->getDeclName(); if (name.getNameKind() != clang::DeclarationName::NameKind::Identifier) { diff --git a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp index 556d54041b..fef7edc273 100644 --- a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp +++ b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp @@ -36,22 +36,23 @@ namespace vast::hl // Verifies linkage types, similar to LLVM: // - functions don't have 'common' linkage // - external functions have 'external' or 'extern_weak' linkage - logical_result FuncOp::verify() { - auto linkage = getLinkage(); + template + logical_result verify_funclike(Op* self) { + auto linkage = self->getLinkage(); constexpr auto common = GlobalLinkageKind::CommonLinkage; if (linkage == common) { - return emitOpError() << "functions cannot have '" + return self->emitOpError() << "functions cannot have '" << stringifyGlobalLinkageKind(common) << "' linkage"; } // isExternal(FunctionOpInterface) only checks for empty bodyonly checks for empty body... // We need to be able to handle functions with internal linkage without body. - if (linkage != GlobalLinkageKind::InternalLinkage && isExternal()) { + if (linkage != GlobalLinkageKind::InternalLinkage && self->isExternal()) { constexpr auto external = GlobalLinkageKind::ExternalLinkage; constexpr auto weak_external = GlobalLinkageKind::ExternalWeakLinkage; if (linkage != external && linkage != weak_external) { - return emitOpError() << "external functions must have '" + return self->emitOpError() << "external functions must have '" << stringifyGlobalLinkageKind(external) << "' or '" << stringifyGlobalLinkageKind(weak_external) @@ -62,6 +63,14 @@ namespace vast::hl return mlir::success(); } + logical_result FuncOp::verify() { + return verify_funclike(this); + } + + logical_result MethodOp::verify() { + return verify_funclike(this); + } + ParseResult parseFunctionSignatureAndBody( Parser &parser, Attribute &funcion_type, mlir::NamedAttrList &attr_dict, Region &body ) { @@ -116,8 +125,9 @@ namespace vast::hl return mlir::success(); } + template< typename Op > void printFunctionSignatureAndBody( - Printer &printer, FuncOp op, Attribute /* funcion_type */, mlir::DictionaryAttr, Region &body + Printer &printer, Op op, Attribute /* funcion_type */, mlir::DictionaryAttr, Region &body ) { auto fty = op.getFunctionType(); mlir::function_interface_impl::printFunctionSignature( From 75e0a8b046b6c5b82c30becef670ba440277b8ad Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Wed, 19 Jul 2023 17:17:13 +0200 Subject: [PATCH 3/8] hl: Fix missing scope assertion. --- include/vast/Translation/CodeGen.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/vast/Translation/CodeGen.hpp b/include/vast/Translation/CodeGen.hpp index a56f18d692..cbd25aefff 100644 --- a/include/vast/Translation/CodeGen.hpp +++ b/include/vast/Translation/CodeGen.hpp @@ -89,6 +89,7 @@ namespace vast::cg using EnumConstantsScope = ScopedSymbolTable< const clang::EnumConstantDecl *, hl::EnumConstantOp >; 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 VariablesScope = ScopedSymbolTable< const clang::VarDecl *, Value >; struct CodegenScope { @@ -98,6 +99,7 @@ namespace vast::cg EnumConstantsScope enumconsts; LabelTable labels; FunctionsScope funcdecls; + MethodsScope methdecls; VariablesScope globs; }; @@ -597,6 +599,7 @@ namespace vast::cg .enumconsts = _cgctx.enumconsts, .labels = _cgctx.labels, .funcdecls = _cgctx.funcdecls, + .methdecls = _cgctx.methdecls, .globs = _cgctx.vars }); From d6c72dc728f23af9d670219357e33b0e0ba44c4e Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Wed, 19 Jul 2023 17:18:32 +0200 Subject: [PATCH 4/8] hl: Lookup correct operation kind. --- include/vast/Translation/CodeGenContext.hpp | 4 ++ .../vast/Translation/CodeGenDeclVisitor.hpp | 46 ++++++++++++++++--- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/include/vast/Translation/CodeGenContext.hpp b/include/vast/Translation/CodeGenContext.hpp index 2d384176fe..3d3897d3bf 100644 --- a/include/vast/Translation/CodeGenContext.hpp +++ b/include/vast/Translation/CodeGenContext.hpp @@ -210,6 +210,10 @@ namespace vast::cg return symbol(funcdecls, mangled, "undeclared function '" + mangled.name + "'", with_error); } + hl::MethodOp lookup_method(mangled_name_ref mangled, bool with_error = true) { + return symbol(methdecls, mangled, "undeclared method '" + mangled.name + "'", with_error); + } + template< typename Op > Op declare(mangled_name_ref mangled, auto vast_decl_builder) { if constexpr (std::is_same_v< Op, hl::FuncOp >) { diff --git a/include/vast/Translation/CodeGenDeclVisitor.hpp b/include/vast/Translation/CodeGenDeclVisitor.hpp index 70570f3089..4471d2ba95 100644 --- a/include/vast/Translation/CodeGenDeclVisitor.hpp +++ b/include/vast/Translation/CodeGenDeclVisitor.hpp @@ -298,8 +298,16 @@ namespace vast::cg { auto gdecl = get_gdecl(decl); auto mangled = context().get_mangled_name(gdecl); - if (auto fn = context().lookup_function(mangled, false /* emit no error */)) { - return fn; + 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; + } } InsertionGuard guard(builder()); @@ -433,19 +441,31 @@ namespace vast::cg { operation VisitCXXMethodDecl(const clang::CXXMethodDecl *decl) { return VisitFunctionLikeDecl< hl::MethodOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { - return make< hl::MethodOp >(loc, name, type, linkage); + return make< hl::MethodOp >(loc, name, type, linkage, + decl->isVirtual(), + decl->isConst(), + decl->isVolatile(), + convert_ref_qual(decl->getRefQualifier())); }); } operation VisitCXXConstructorDecl(const clang::CXXConstructorDecl *decl) { - return VisitFunctionLikeDecl< hl::FuncOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { - return make< hl::FuncOp >(loc, name, type, linkage); + 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())); }); } operation VisitCXXDestructorDecl(const clang::CXXDestructorDecl *decl) { - return VisitFunctionLikeDecl< hl::FuncOp >(decl, [&](auto loc, auto name, auto type, auto linkage) { - return make< hl::FuncOp >(loc, name, type, linkage); + 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())); }); } @@ -661,6 +681,18 @@ namespace vast::cg { VAST_UNREACHABLE("unknown access specifier"); } + hl::RefQualifier convert_ref_qual(clang::RefQualifierKind kind) { + switch(kind) { + case clang::RefQualifierKind::RQ_None: + return hl::RefQualifier::ref_none; + case clang::RefQualifierKind::RQ_LValue: + return hl::RefQualifier::ref_lvalue; + case clang::RefQualifierKind::RQ_RValue: + return hl::RefQualifier::ref_rvalue; + } + VAST_UNREACHABLE("unknown ref qualifier"); + } + // // Record Declaration // From 5dec8d7db9783dc972c86c69308d8ea9e5a41677 Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Wed, 19 Jul 2023 17:19:45 +0200 Subject: [PATCH 5/8] hl: Refactor CV representation. --- .../vast/Dialect/HighLevel/HighLevelOps.td | 8 +-- .../vast/Dialect/HighLevel/HighLevelOpsCxx.td | 71 +++++++++++++++++-- 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/include/vast/Dialect/HighLevel/HighLevelOps.td b/include/vast/Dialect/HighLevel/HighLevelOps.td index 47ad4a0b5e..057441ffaf 100644 --- a/include/vast/Dialect/HighLevel/HighLevelOps.td +++ b/include/vast/Dialect/HighLevel/HighLevelOps.td @@ -43,17 +43,17 @@ def ScopeOp : HighLevel_Op< "scope", [NoTerminator] > let assemblyFormat = [{ $body attr-dict }]; } -class FuncLikeOp< string mnemonic, dag additional_args > +class FuncLikeOp< string mnemonic > : HighLevel_Op< mnemonic, [ AutomaticAllocationScope, CallableOpInterface, FunctionOpInterface, IsolatedFromAbove, Symbol, NoTerminator ] > - , Arguments< !con((ins + , Arguments< (ins SymbolNameAttr:$sym_name, TypeAttrOf:$function_type, DefaultValuedAttr:$linkage, OptionalAttr:$sym_visibility, OptionalAttr:$arg_attrs, - OptionalAttr:$res_attrs ), additional_args) > + OptionalAttr:$res_attrs) > { let description = [{ Inspired by `cir::FuncOp` and `mlir::func::FuncOp`: @@ -139,7 +139,7 @@ class FuncLikeOp< string mnemonic, dag additional_args > let hasVerifier = 1; } -def FuncOp : FuncLikeOp< "func", (ins) > { +def FuncOp : FuncLikeOp< "func" > { let summary = "VAST high-level function definintion or declaration"; let assemblyFormat = [{ diff --git a/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td b/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td index cd7c84f4c5..0681f2e1e1 100644 --- a/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td +++ b/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td @@ -102,15 +102,76 @@ def RefQualifier : I32EnumAttr< } def MethodOp - : FuncLikeOp< "method", (ins - UnitAttr:$is_virtual, - RefQualifier:$ref, - CVQualifiers:$cv) > + : FuncLikeOp< "method" > { let summary = "VAST high-level method definintion or declaration"; + let arguments = (ins + SymbolNameAttr:$sym_name, + TypeAttrOf:$function_type, + DefaultValuedAttr:$linkage, + UnitAttr:$is_virtual, + UnitAttr:$is_const, + UnitAttr:$is_volatile, + RefQualifier:$ref, + OptionalAttr:$sym_visibility, + OptionalAttr:$arg_attrs, + OptionalAttr:$res_attrs); + + let builders = [OpBuilder< (ins + "llvm::StringRef":$name, + "mlir::FunctionType":$type, + CArg< "GlobalLinkageKind", "GlobalLinkageKind::ExternalLinkage" >:$linkage, + CArg< "bool", "false" >:$is_virtual, + CArg< "bool", "false" >:$is_const, + CArg< "bool", "false" >:$is_volatile, + CArg< "RefQualifier", "RefQualifier::ref_none" >:$ref, + CArg< "llvm::ArrayRef", "{}" >:$attrs, + CArg< "llvm::ArrayRef", "{}" >:$arg_attrs, + CArg< "llvm::ArrayRef", "{}" >:$res_attrs, + CArg< "BuilderCallback", "std::nullopt" >:$body), [{ + InsertionGuard guard($_builder); + build_region($_builder, $_state, body); + + $_state.addAttribute( + mlir::SymbolTable::getSymbolAttrName(), $_builder.getStringAttr(name) + ); + $_state.addAttribute(getFunctionTypeAttrName($_state.name), mlir::TypeAttr::get(type)); + $_state.addAttribute( + "linkage", GlobalLinkageKindAttr::get($_builder.getContext(), linkage) + ); + if (is_virtual) { + $_state.addAttribute( + "is_virtual", mlir::UnitAttr::get($_builder.getContext()) + ); + } + if (is_const) { + $_state.addAttribute( + "is_const", mlir::UnitAttr::get($_builder.getContext()) + ); + } + if (is_volatile) { + $_state.addAttribute( + "is_volatile", mlir::UnitAttr::get($_builder.getContext()) + ); + } + $_state.addAttribute( + "ref", RefQualifierAttr::get($_builder.getContext(), ref) + ); + $_state.attributes.append(attrs.begin(), attrs.end()); + + if (arg_attrs.empty()) + return; + + mlir::function_interface_impl::addArgAndResultAttrs( + $_builder, $_state, arg_attrs, res_attrs, + getArgAttrsAttrName($_state.name), getResAttrsAttrName($_state.name) + ); + }] > + ]; + let assemblyFormat = [{ - $linkage (`virtual` $is_virtual^)? $ref $cv $sym_name custom< FunctionSignatureAndBody >($function_type, attr-dict, $body) + $linkage (`virtual` $is_virtual^)? $ref (`const` $is_const^)? (`volatile` $is_volatile^)? $sym_name custom< FunctionSignatureAndBody >($function_type, attr-dict, $body) }]; } From 74d430ec55de9233429b60496f075f3e0268df9a Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Wed, 19 Jul 2023 17:28:09 +0200 Subject: [PATCH 6/8] test:hl:cxx: Add CV and ref qualifiers test. --- test/vast/Dialect/HighLevel/Cxx/class-a.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/vast/Dialect/HighLevel/Cxx/class-a.cpp b/test/vast/Dialect/HighLevel/Cxx/class-a.cpp index 6d0737be20..2bb19cb414 100644 --- a/test/vast/Dialect/HighLevel/Cxx/class-a.cpp +++ b/test/vast/Dialect/HighLevel/Cxx/class-a.cpp @@ -19,4 +19,19 @@ class C : public A, protected virtual B { // CHECK: %0 = hl.var "C::y" sc_static : !hl.lvalue static int y; + + // CHECK: hl.method external virtual ref_none @_ZN1C5get_xEv () -> !hl.int + virtual int get_x(); + + // CHECK: hl.method external ref_none const @_ZNK1C5get_yEv () -> !hl.int + int get_y() const; + + // CHECK: hl.method external ref_none volatile @_ZNV1C5get_zEv () -> !hl.int + int get_z() volatile; + + // CHECK: hl.method external ref_lvalue @_ZNR1C5get_wEv () -> !hl.int + int get_w() &; + + // CHECK: hl.method external ref_rvalue @_ZNO1C5get_pEv () -> !hl.int + int get_p() &&; }; \ No newline at end of file From 16bafbd57f3163ff460d19c55dd10c04b80b484b Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Thu, 20 Jul 2023 11:37:42 +0200 Subject: [PATCH 7/8] hl: Do not print special `MethodOp` attributes. --- lib/vast/Dialect/HighLevel/HighLevelOps.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp index fef7edc273..a3857e1634 100644 --- a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp +++ b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp @@ -135,7 +135,14 @@ namespace vast::hl ); mlir::function_interface_impl::printFunctionAttributes( - printer, op, {"linkage", op.getFunctionTypeAttrName() } + printer, op, { + "linkage", + op.getFunctionTypeAttrName(), + "is_virtual", + "is_const", + "is_volatile", + "ref" + } ); if (!body.empty()) { From b8509f38fa37e34f9dbc526731f635e0f56957a9 Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Thu, 20 Jul 2023 12:44:11 +0200 Subject: [PATCH 8/8] hl: Refactor to remove code duplication. --- .../vast/Dialect/HighLevel/HighLevelOps.td | 23 +++-- .../vast/Dialect/HighLevel/HighLevelOpsCxx.td | 93 ++++++------------- 2 files changed, 41 insertions(+), 75 deletions(-) diff --git a/include/vast/Dialect/HighLevel/HighLevelOps.td b/include/vast/Dialect/HighLevel/HighLevelOps.td index 057441ffaf..8e321f251d 100644 --- a/include/vast/Dialect/HighLevel/HighLevelOps.td +++ b/include/vast/Dialect/HighLevel/HighLevelOps.td @@ -43,17 +43,18 @@ def ScopeOp : HighLevel_Op< "scope", [NoTerminator] > let assemblyFormat = [{ $body attr-dict }]; } -class FuncLikeOp< string mnemonic > +class FuncLikeOp< string mnemonic, dag add_args = (ins), dag add_builders = (ins), string add_init = "" > : HighLevel_Op< mnemonic, [ AutomaticAllocationScope, CallableOpInterface, FunctionOpInterface, IsolatedFromAbove, Symbol, NoTerminator ] > - , Arguments< (ins + , Arguments< !con((ins SymbolNameAttr:$sym_name, TypeAttrOf:$function_type, - DefaultValuedAttr:$linkage, - OptionalAttr:$sym_visibility, + DefaultValuedAttr:$linkage), + add_args, + (ins OptionalAttr:$sym_visibility, OptionalAttr:$arg_attrs, - OptionalAttr:$res_attrs) > + OptionalAttr:$res_attrs)) > { let description = [{ Inspired by `cir::FuncOp` and `mlir::func::FuncOp`: @@ -71,14 +72,15 @@ class FuncLikeOp< string mnemonic > let regions = (region AnyRegion:$body); let skipDefaultBuilders = 1; - let builders = [OpBuilder< (ins + let builders = [OpBuilder< !con((ins "llvm::StringRef":$name, "mlir::FunctionType":$type, - CArg< "GlobalLinkageKind", "GlobalLinkageKind::ExternalLinkage" >:$linkage, - CArg< "llvm::ArrayRef", "{}" >:$attrs, + CArg< "GlobalLinkageKind", "GlobalLinkageKind::ExternalLinkage" >:$linkage), + add_builders, + (ins CArg< "llvm::ArrayRef", "{}" >:$attrs, CArg< "llvm::ArrayRef", "{}" >:$arg_attrs, CArg< "llvm::ArrayRef", "{}" >:$res_attrs, - CArg< "BuilderCallback", "std::nullopt" >:$body), [{ + CArg< "BuilderCallback", "std::nullopt" >:$body)), !strconcat([{ InsertionGuard guard($_builder); build_region($_builder, $_state, body); @@ -89,6 +91,7 @@ class FuncLikeOp< string mnemonic > $_state.addAttribute( "linkage", GlobalLinkageKindAttr::get($_builder.getContext(), linkage) ); + }], add_init, [{ $_state.attributes.append(attrs.begin(), attrs.end()); if (arg_attrs.empty()) @@ -98,7 +101,7 @@ class FuncLikeOp< string mnemonic > $_builder, $_state, arg_attrs, res_attrs, getArgAttrsAttrName($_state.name), getResAttrsAttrName($_state.name) ); - }] > + }]) > ]; let extraClassDeclaration = [{ diff --git a/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td b/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td index 0681f2e1e1..6a18f70d60 100644 --- a/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td +++ b/include/vast/Dialect/HighLevel/HighLevelOpsCxx.td @@ -102,74 +102,37 @@ def RefQualifier : I32EnumAttr< } def MethodOp - : FuncLikeOp< "method" > + : FuncLikeOp< "method", (ins + UnitAttr:$is_virtual, + UnitAttr:$is_const, + UnitAttr:$is_volatile, + RefQualifier:$ref), (ins + CArg< "bool", "false" >:$is_virtual, + CArg< "bool", "false" >:$is_const, + CArg< "bool", "false" >:$is_volatile, + CArg< "RefQualifier", "RefQualifier::ref_none" >:$ref), [{ + if (is_virtual) { + $_state.addAttribute( + "is_virtual", mlir::UnitAttr::get($_builder.getContext()) + ); + } + if (is_const) { + $_state.addAttribute( + "is_const", mlir::UnitAttr::get($_builder.getContext()) + ); + } + if (is_volatile) { + $_state.addAttribute( + "is_volatile", mlir::UnitAttr::get($_builder.getContext()) + ); + } + $_state.addAttribute( + "ref", RefQualifierAttr::get($_builder.getContext(), ref) + ); + }] > { let summary = "VAST high-level method definintion or declaration"; - let arguments = (ins - SymbolNameAttr:$sym_name, - TypeAttrOf:$function_type, - DefaultValuedAttr:$linkage, - UnitAttr:$is_virtual, - UnitAttr:$is_const, - UnitAttr:$is_volatile, - RefQualifier:$ref, - OptionalAttr:$sym_visibility, - OptionalAttr:$arg_attrs, - OptionalAttr:$res_attrs); - - let builders = [OpBuilder< (ins - "llvm::StringRef":$name, - "mlir::FunctionType":$type, - CArg< "GlobalLinkageKind", "GlobalLinkageKind::ExternalLinkage" >:$linkage, - CArg< "bool", "false" >:$is_virtual, - CArg< "bool", "false" >:$is_const, - CArg< "bool", "false" >:$is_volatile, - CArg< "RefQualifier", "RefQualifier::ref_none" >:$ref, - CArg< "llvm::ArrayRef", "{}" >:$attrs, - CArg< "llvm::ArrayRef", "{}" >:$arg_attrs, - CArg< "llvm::ArrayRef", "{}" >:$res_attrs, - CArg< "BuilderCallback", "std::nullopt" >:$body), [{ - InsertionGuard guard($_builder); - build_region($_builder, $_state, body); - - $_state.addAttribute( - mlir::SymbolTable::getSymbolAttrName(), $_builder.getStringAttr(name) - ); - $_state.addAttribute(getFunctionTypeAttrName($_state.name), mlir::TypeAttr::get(type)); - $_state.addAttribute( - "linkage", GlobalLinkageKindAttr::get($_builder.getContext(), linkage) - ); - if (is_virtual) { - $_state.addAttribute( - "is_virtual", mlir::UnitAttr::get($_builder.getContext()) - ); - } - if (is_const) { - $_state.addAttribute( - "is_const", mlir::UnitAttr::get($_builder.getContext()) - ); - } - if (is_volatile) { - $_state.addAttribute( - "is_volatile", mlir::UnitAttr::get($_builder.getContext()) - ); - } - $_state.addAttribute( - "ref", RefQualifierAttr::get($_builder.getContext(), ref) - ); - $_state.attributes.append(attrs.begin(), attrs.end()); - - if (arg_attrs.empty()) - return; - - mlir::function_interface_impl::addArgAndResultAttrs( - $_builder, $_state, arg_attrs, res_attrs, - getArgAttrsAttrName($_state.name), getResAttrsAttrName($_state.name) - ); - }] > - ]; - let assemblyFormat = [{ $linkage (`virtual` $is_virtual^)? $ref (`const` $is_const^)? (`volatile` $is_volatile^)? $sym_name custom< FunctionSignatureAndBody >($function_type, attr-dict, $body) }];