// -*- C++ -*- (c) 2016 Vladimír Štill #pragma once #include #include #include #include #include #include namespace brick { namespace llvm { struct Linker; struct ArchiveReader; } } // avoid header dependency namespace divine { namespace cc { // get generate source which defines symbol with name 'name' in namespaces 'ns' // which contains char array literal 'value' std::string stringifyToCode( std::vector< std::string > ns, std::string name, std::string value ); struct Compile { using ModulePtr = std::unique_ptr< llvm::Module >; explicit Compile( std::shared_ptr< llvm::LLVMContext > ctx ) : Compile( Options(), ctx ) {} explicit Compile( Options opts = Options(), std::shared_ptr< llvm::LLVMContext > ctx = nullptr ); ~Compile(); void compileAndLink( std::string path, std::vector< std::string > flags = {} ); void compileAndLink( std::string path, Compiler::FileType type, std::vector< std::string > flags = {} ); void linkLibs( const std::vector< std::string > &libs ); void linkEssentials(); static const std::vector< std::string > defaultDIVINELibs; ModulePtr compile( std::string path, std::vector< std::string > flags = { } ); ModulePtr compile( std::string path, Compiler::FileType type, std::vector< std::string > flags = {} ); // Run the compiler based on invocation arguments (including files). The // arguments should not contain -o or linker arguments. // // The callback (if present) is invoked for every compiled module, with // pointer to the module, and the name of the file from which the module // was created. // // If the callback returns a module, this module is linked to the // composite, which can be later obtained using getLinked(). Otherwise, the // module is skipped and the callback can transfer its ownership, or delete // it. Normally, the implementation would handle non-liking modules and // return without modification modules which should be linked. void runCC( std::vector< std::string > rawCCOpts, std::function< ModulePtr( ModulePtr &&, std::string ) > moduleCallback = nullptr ); llvm::Module *getLinked(); void writeToFile( std::string filename ); void writeToFile( std::string filename, llvm::Module *module ); std::string serialize(); void addDirectory( std::string path ); void addFlags( std::vector< std::string > flags ); std::shared_ptr< llvm::LLVMContext > context(); template< typename RT > void setupFS( RT each ) { each( [&]( auto path, auto c ) { if ( brick::string::endsWith( path, ".a" ) ) setupLib( path, c ); else compiler.mapVirtualFile( path, c ); } ); } private: void setupLib( std::string name, std::string_view content ); Options opts; Compiler compiler; std::unique_ptr< brick::llvm::Linker > linker; std::vector< std::string > commonFlags; // set in CPP std::string runtimeVersMeta = "divine.compile.runtime.version"; std::map< std::string, brick::llvm::ArchiveReader > libs; }; } }