From 0511f9368841a5cb11813cb9fc4f22d16dff8f9e Mon Sep 17 00:00:00 2001 From: Henrich Lauko Date: Wed, 25 Oct 2023 22:43:53 +0200 Subject: [PATCH] cc: Splice codegen generator into ast consumer. --- include/vast/CodeGen/CodeGenDriver.hpp | 3 +- include/vast/CodeGen/Generator.hpp | 69 -------------- include/vast/Frontend/Consumer.hpp | 15 ++-- lib/vast/CodeGen/CMakeLists.txt | 1 - lib/vast/CodeGen/Generator.cpp | 120 ------------------------- lib/vast/Frontend/Consumer.cpp | 91 +++++++++++++++---- 6 files changed, 78 insertions(+), 221 deletions(-) delete mode 100644 include/vast/CodeGen/Generator.hpp delete mode 100644 lib/vast/CodeGen/Generator.cpp diff --git a/include/vast/CodeGen/CodeGenDriver.hpp b/include/vast/CodeGen/CodeGenDriver.hpp index 7923c02f2b..5edf03d93c 100644 --- a/include/vast/CodeGen/CodeGenDriver.hpp +++ b/include/vast/CodeGen/CodeGenDriver.hpp @@ -56,8 +56,7 @@ namespace vast::cg struct codegen_driver { explicit codegen_driver( - codegen_context &cgctx - , codegen_options opts + codegen_context &cgctx, codegen_options opts ) : actx(cgctx.actx) , mctx(cgctx.mctx) diff --git a/include/vast/CodeGen/Generator.hpp b/include/vast/CodeGen/Generator.hpp deleted file mode 100644 index 072e5b361c..0000000000 --- a/include/vast/CodeGen/Generator.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2022-present, Trail of Bits, Inc. - -#pragma once - -#include "vast/Util/Warnings.hpp" - -VAST_RELAX_WARNINGS -#include -#include -#include -#include -VAST_UNRELAX_WARNINGS - -#include "vast/Frontend/Diagnostics.hpp" -#include "vast/CodeGen/CodeGenDriver.hpp" -#include "vast/Util/Common.hpp" - -#include - -namespace vast::cg { - - using clang_ast_consumer = clang::ASTConsumer; - - struct vast_generator : clang_ast_consumer { - - vast_generator( - cc::diagnostics_engine &diags - , const cc::codegen_options &cgo - , const cc::language_options &lang_ops - ) - : diags(diags), cgo(cgo), lang_ops(lang_ops) - {} - - void Initialize(acontext_t &) override; - - bool HandleTopLevelDecl(clang::DeclGroupRef) override; - void HandleTranslationUnit(acontext_t &) override; - void HandleInlineFunctionDefinition(clang::FunctionDecl *) override; - void HandleTagDeclDefinition(clang::TagDecl *) override; - void HandleTagDeclRequiredDefinition(const clang::TagDecl *) override; - void CompleteTentativeDefinition(clang::VarDecl *decl) override; - - owning_module_ref freeze(); - std::unique_ptr< mcontext_t > take_context(); - - bool verify_module() const; - - target_info_t &get_target_info(); - type_info_t &get_type_info(); - - void dump_module() { codegen->dump_module(); } - - protected: - std::unique_ptr< mcontext_t > mcontext = nullptr; - std::unique_ptr< codegen_context > cgcontext = nullptr; - std::unique_ptr< codegen_driver > codegen = nullptr; - - private: - virtual void anchor(); - - cc::diagnostics_engine &diags; - acontext_t *acontext; - - const cc::codegen_options cgo; // intentionally copied - - const cc::language_options &lang_ops; - }; - -} // namespace vast::cg diff --git a/include/vast/Frontend/Consumer.hpp b/include/vast/Frontend/Consumer.hpp index 565eaea8a7..785587b11b 100644 --- a/include/vast/Frontend/Consumer.hpp +++ b/include/vast/Frontend/Consumer.hpp @@ -13,8 +13,8 @@ VAST_UNRELAX_WARNINGS #include "vast/Frontend/FrontendAction.hpp" #include "vast/Frontend/Options.hpp" -#include "vast/CodeGen/Generator.hpp" #include "vast/CodeGen/CodeGenContext.hpp" +#include "vast/CodeGen/CodeGenDriver.hpp" namespace vast::cc { @@ -29,8 +29,6 @@ namespace vast::cc { struct vast_consumer : clang_ast_consumer { - using vast_generator_ptr = std::unique_ptr< cg::vast_generator >; - vast_consumer( output_type act, action_options opts, const vast_args &vargs, output_stream_ptr os @@ -39,10 +37,7 @@ namespace vast::cc { , opts(std::move(opts)) , vargs(vargs) , output_stream(std::move(os)) - , generator(std::make_unique< cg::vast_generator >( - opts.diags, opts.codegen, opts.lang - ) - ) {} + {} void Initialize(acontext_t &ctx) override; @@ -95,8 +90,8 @@ namespace vast::cc { // // contexts // - acontext_t *acontext = nullptr; - - vast_generator_ptr generator; + std::unique_ptr< mcontext_t > mctx = nullptr; + std::unique_ptr< cg::codegen_context > cgctx = nullptr; + std::unique_ptr< cg::codegen_driver > codegen = nullptr; }; } // namespace vast::cc diff --git a/lib/vast/CodeGen/CMakeLists.txt b/lib/vast/CodeGen/CMakeLists.txt index bba34e716c..f385acb86e 100644 --- a/lib/vast/CodeGen/CMakeLists.txt +++ b/lib/vast/CodeGen/CMakeLists.txt @@ -14,7 +14,6 @@ add_vast_library(CodeGen CodeGenFunction.cpp DataLayout.cpp FunctionInfo.cpp - Generator.cpp ItaniumCXXABI.cpp Mangler.cpp Passes.cpp diff --git a/lib/vast/CodeGen/Generator.cpp b/lib/vast/CodeGen/Generator.cpp deleted file mode 100644 index cd99bd20bd..0000000000 --- a/lib/vast/CodeGen/Generator.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2023-present, Trail of Bits, Inc. - -#include "vast/CodeGen/Generator.hpp" -#include "vast/CodeGen/CodeGenContext.hpp" - -#include "vast/Dialect/Core/CoreAttributes.hpp" - -#include - -namespace vast::cg { - - void vast_generator::anchor() {} - - using source_language = core::SourceLanguage; - - source_language get_source_language(const cc::language_options &opts) { - using ClangStd = clang::LangStandard; - - if (opts.CPlusPlus || opts.CPlusPlus11 || opts.CPlusPlus14 || - opts.CPlusPlus17 || opts.CPlusPlus20 || opts.CPlusPlus23 || - opts.CPlusPlus26) - return source_language::CXX; - if (opts.C99 || opts.C11 || opts.C17 || opts.C2x || - opts.LangStd == ClangStd::lang_c89) - return source_language::C; - - // TODO: support remaining source languages. - VAST_UNIMPLEMENTED_MSG("VAST does not yet support the given source language"); - } - - void vast_generator::Initialize(acontext_t &actx) { - this->acontext = &actx; - this->mcontext = std::make_unique< mcontext_t >(); - - codegen_options options { - .verbose_diagnostics = true, - // forwarded options form clang codegen - .coverage_mapping = bool(cgo.CoverageMapping), - .keep_static_consts = bool(cgo.KeepStaticConsts), - .patchable_function_entry_count = cgo.PatchableFunctionEntryCount, - .patchable_function_entry_offset = cgo.PatchableFunctionEntryOffset, - .no_use_jump_tables = bool(cgo.NoUseJumpTables), - .no_inline_line_tables = bool(cgo.NoInlineLineTables), - .packed_stack = bool(cgo.PackedStack), - .warn_stack_size = cgo.WarnStackSize, - .strict_return = bool(cgo.StrictReturn), - .optimization_level = cgo.OptimizationLevel, - .lang = get_source_language(lang_ops) - }; - - this->cgcontext = std::make_unique< codegen_context >( - *this->mcontext, *this->acontext, options.lang - ); - - // TODO initialize dialects here - this->codegen = std::make_unique< codegen_driver >(*this->cgcontext, options); - } - - std::unique_ptr< mcontext_t > vast_generator::take_context() { - return std::move(mcontext); - } - - bool vast_generator::HandleTopLevelDecl(clang::DeclGroupRef decls) { - if (diags.hasErrorOccurred()) - return true; - - return codegen->handle_top_level_decl(decls), true; - } - - void vast_generator::HandleTranslationUnit(acontext_t &acontext) { - codegen->handle_translation_unit(acontext); - } - - void vast_generator::HandleInlineFunctionDefinition(clang::FunctionDecl */* decl */) { - VAST_UNIMPLEMENTED; - } - - void vast_generator::CompleteTentativeDefinition(clang::VarDecl *decl){ - codegen->handle_top_level_decl(decl); - } - - // HandleTagDeclDefinition - This callback is invoked each time a TagDecl to - // (e.g. struct, union, enum, class) is completed. This allows the client hack - // on the type, which can occur at any point in the file (because these can be - // defined in declspecs). - void vast_generator::HandleTagDeclDefinition(clang::TagDecl *decl) { - if (diags.hasErrorOccurred()) { - return; - } - - // Don't allow re-entrant calls to generator triggered by PCH - // deserialization to emit deferred decls. - defer_handle_of_top_level_decl handling_decl(*codegen, /* emit deferred */false); - - codegen->update_completed_type(decl); - - // For MSVC compatibility, treat declarations of static data members with - // inline initializers as definitions. - if (acontext->getTargetInfo().getCXXABI().isMicrosoft()) { - VAST_UNIMPLEMENTED; - } - - // For OpenMP emit declare reduction functions, if required. - if (acontext->getLangOpts().OpenMP) { - VAST_UNIMPLEMENTED; - } - } - - void vast_generator::HandleTagDeclRequiredDefinition(const clang::TagDecl */* decl */) { - VAST_UNIMPLEMENTED; - } - - bool vast_generator::verify_module() const { return codegen->verify_module(); } - - owning_module_ref vast_generator::freeze() { return std::move(cgcontext->mod); } - - type_info_t &vast_generator::get_type_info() { return codegen->get_type_info(); } - target_info_t &vast_generator::get_target_info() { return codegen->get_target_info(); } - -} // namespace vast::cc diff --git a/lib/vast/Frontend/Consumer.cpp b/lib/vast/Frontend/Consumer.cpp index 402be55daa..ed00002bb7 100644 --- a/lib/vast/Frontend/Consumer.cpp +++ b/lib/vast/Frontend/Consumer.cpp @@ -13,6 +13,11 @@ VAST_RELAX_WARNINGS VAST_UNRELAX_WARNINGS #include "vast/CodeGen/Passes.hpp" +#include "vast/CodeGen/CodeGenContext.hpp" +#include "vast/CodeGen/CodeGenDriver.hpp" + +#include "vast/Util/Common.hpp" + #include "vast/Target/LLVMIR/Convert.hpp" namespace vast::cc { @@ -33,18 +38,31 @@ namespace vast::cc { void emit_mlir_output(target_dialect target, owning_module_ref mod, mcontext_t *mctx); - void vast_consumer::Initialize(acontext_t &ctx) { - VAST_CHECK(!acontext, "initialized multiple times"); - acontext = &ctx; - generator->Initialize(ctx); + using source_language = core::SourceLanguage; + + source_language get_source_language(const cc::language_options &opts); + + void vast_consumer::Initialize(acontext_t &actx) { + VAST_CHECK(!mctx, "initialized multiple times"); + mctx = std::make_unique< mcontext_t >(); + cgctx = std::make_unique< cg::codegen_context >( + *mctx, actx, get_source_language(opts.lang) + ); + + codegen = std::make_unique< cg::codegen_driver >(*cgctx, opts.codegen); } bool vast_consumer::HandleTopLevelDecl(clang::DeclGroupRef decls) { clang::PrettyStackTraceDecl crash_info( - *decls.begin(), clang::SourceLocation(), acontext->getSourceManager(), + *decls.begin(), clang::SourceLocation(), cgctx->actx.getSourceManager(), "LLVM IR generation of declaration" ); - return generator->HandleTopLevelDecl(decls); + + if (opts.diags.hasErrorOccurred()) { + return true; + } + + return codegen->handle_top_level_decl(decls), true; } void vast_consumer::HandleCXXStaticMemberVarInstantiation(clang::VarDecl * /* decl */) { @@ -59,20 +77,19 @@ namespace vast::cc { VAST_UNIMPLEMENTED; } - void vast_consumer::HandleTranslationUnit(acontext_t &acontext) { + void vast_consumer::HandleTranslationUnit(acontext_t &actx) { // Note that this method is called after `HandleTopLevelDecl` has already // ran all over the top level decls. Here clang mostly wraps defered and // global codegen, followed by running vast passes. - generator->HandleTranslationUnit(acontext); + codegen->handle_translation_unit(actx); if (!vargs.has_option(opt::disable_vast_verifier)) { - if (!generator->verify_module()) { + if (!codegen->verify_module()) { VAST_UNREACHABLE("codegen: module verification error before running vast passes"); } } - auto mod = generator->freeze(); - auto mctx = generator->take_context(); + auto mod = std::move(cgctx->mod); compile_via_vast(mod.get(), mctx.get()); @@ -99,12 +116,34 @@ namespace vast::cc { } void vast_consumer::HandleTagDeclDefinition(clang::TagDecl *decl) { + auto &actx = cgctx->actx; clang::PrettyStackTraceDecl crash_info( - decl, clang::SourceLocation(), acontext->getSourceManager(), + decl, clang::SourceLocation(), actx.getSourceManager(), "vast generation of declaration" ); - generator->HandleTagDeclDefinition(decl); + if (opts.diags.hasErrorOccurred()) { + return; + } + + // Don't allow re-entrant calls to generator triggered by PCH + // deserialization to emit deferred decls. + cg::defer_handle_of_top_level_decl handling_decl( + *codegen, /* emit deferred */false + ); + + codegen->update_completed_type(decl); + + // For MSVC compatibility, treat declarations of static data members with + // inline initializers as definitions. + if (actx.getTargetInfo().getCXXABI().isMicrosoft()) { + VAST_UNIMPLEMENTED; + } + + // For OpenMP emit declare reduction functions, if required. + if (actx.getLangOpts().OpenMP) { + VAST_UNIMPLEMENTED; + } } // void vast_consumer::HandleTagDeclRequiredDefinition(clang::TagDecl */* decl */) { @@ -112,7 +151,7 @@ namespace vast::cc { // } void vast_consumer::CompleteTentativeDefinition(clang::VarDecl *decl) { - generator->CompleteTentativeDefinition(decl); + codegen->handle_top_level_decl(decl); } void vast_consumer::CompleteExternalDeclaration(clang::VarDecl * /* decl */) { @@ -134,11 +173,10 @@ namespace vast::cc { llvmir::lower_hl_module(mlir_module.get(), pipeline); auto mod = llvmir::translate(mlir_module.get(), llvm_context); - + auto dl = cgctx->actx.getTargetInfo().getDataLayoutString(); clang::EmitBackendOutput( - opts.diags, opts.headers, opts.codegen, opts.target, opts.lang, - acontext->getTargetInfo().getDataLayoutString(), mod.get(), backend_action, &opts.vfs, - std::move(output_stream) + opts.diags, opts.headers, opts.codegen, opts.target, opts.lang, dl, mod.get(), + backend_action, &opts.vfs, std::move(output_stream) ); } @@ -166,7 +204,7 @@ namespace vast::cc { // Handle source manager properly given that lifetime analysis // might emit warnings and remarks. - auto &src_mgr = acontext->getSourceManager(); + auto &src_mgr = cgctx->actx.getSourceManager(); auto main_file_id = src_mgr.getMainFileID(); auto file_buff = llvm::MemoryBuffer::getMemBuffer( @@ -212,6 +250,21 @@ namespace vast::cc { } } + source_language get_source_language(const cc::language_options &opts) { + using ClangStd = clang::LangStandard; + + if (opts.CPlusPlus || opts.CPlusPlus11 || opts.CPlusPlus14 || + opts.CPlusPlus17 || opts.CPlusPlus20 || opts.CPlusPlus23 || + opts.CPlusPlus26) + return source_language::CXX; + if (opts.C99 || opts.C11 || opts.C17 || opts.C2x || + opts.LangStd == ClangStd::lang_c89) + return source_language::C; + + // TODO: support remaining source languages. + VAST_UNIMPLEMENTED_MSG("VAST does not yet support the given source language"); + } + target_dialect parse_target_dialect(const vast_args::maybe_option_list &list) { if (!list) { return target_dialect::high_level;