-
-
Notifications
You must be signed in to change notification settings - Fork 264
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Backport of "Avoid using llvm::Linker" to master.
See pull request #974 for the original code.
- Loading branch information
Showing
39 changed files
with
751 additions
and
810 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,221 @@ | ||
| //===-- codegenerator.cpp -------------------------------------------------===// | ||
| // | ||
| // LDC – the LLVM D compiler | ||
| // | ||
| // This file is distributed under the BSD-style LDC license. See the LICENSE | ||
| // file for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "driver/codegenerator.h" | ||
|
|
||
| #include "id.h" | ||
| #include "mars.h" | ||
| #include "module.h" | ||
| #include "parse.h" | ||
| #include "scope.h" | ||
| #include "driver/toobj.h" | ||
| #include "gen/logger.h" | ||
| #include "gen/runtime.h" | ||
|
|
||
| void codegenModule(IRState *irs, Module *m, bool emitFullModuleInfo); | ||
|
|
||
| namespace { | ||
| Module *g_entrypointModule = 0; | ||
| Module *g_dMainModule = 0; | ||
| } | ||
|
|
||
| /// Callback to generate a C main() function, invoked by the frontend. | ||
| void genCmain(Scope *sc) { | ||
| if (g_entrypointModule) return; | ||
|
|
||
| /* The D code to be generated is provided as D source code in the form of a | ||
| * string. | ||
| * Note that Solaris, for unknown reasons, requires both a main() and an | ||
| * _main() | ||
| */ | ||
| static utf8_t code[] = "extern(C) {\n\ | ||
| int _d_run_main(int argc, char **argv, void* mainFunc);\n\ | ||
| int _Dmain(char[][] args);\n\ | ||
| int main(int argc, char **argv) { return _d_run_main(argc, argv, &_Dmain); }\n\ | ||
| version (Solaris) int _main(int argc, char** argv) { return main(argc, argv); }\n\ | ||
| }\n\ | ||
| pragma(LDC_no_moduleinfo);\n\ | ||
| "; | ||
|
|
||
| Identifier *id = Id::entrypoint; | ||
| Module *m = new Module("__entrypoint.d", id, 0, 0); | ||
|
|
||
| Parser p(m, code, sizeof(code) / sizeof(code[0]), 0); | ||
| p.scanloc = Loc(); | ||
| p.nextToken(); | ||
| m->members = p.parseModule(); | ||
| assert(p.token.value == TOKeof); | ||
|
|
||
| char v = global.params.verbose; | ||
| global.params.verbose = 0; | ||
| m->importedFrom = m; | ||
| m->importAll(0); | ||
| m->semantic(); | ||
| m->semantic2(); | ||
| m->semantic3(); | ||
| global.params.verbose = v; | ||
|
|
||
| g_entrypointModule = m; | ||
| g_dMainModule = sc->module; | ||
| } | ||
|
|
||
| namespace { | ||
| /// Emits a declaration for the given symbol, which is assumed to be of type | ||
| /// i8*, and defines a second globally visible i8* that contains the address | ||
| /// of the first symbol. | ||
| void emitSymbolAddrGlobal(llvm::Module &lm, const char *symbolName, | ||
| const char *addrName) { | ||
| llvm::Type *voidPtr = | ||
| llvm::PointerType::get(llvm::Type::getInt8Ty(lm.getContext()), 0); | ||
| llvm::GlobalVariable *targetSymbol = new llvm::GlobalVariable( | ||
| lm, voidPtr, false, llvm::GlobalValue::ExternalWeakLinkage, 0, | ||
| symbolName); | ||
| new llvm::GlobalVariable( | ||
| lm, voidPtr, false, llvm::GlobalValue::ExternalLinkage, | ||
| llvm::ConstantExpr::getBitCast(targetSymbol, voidPtr), addrName); | ||
| } | ||
| } | ||
|
|
||
| namespace ldc { | ||
| CodeGenerator::CodeGenerator(llvm::LLVMContext &context, bool singleObj) | ||
| : context_(context), moduleCount_(0), singleObj_(singleObj), ir_(0), | ||
| firstModuleObjfileName_(0) { | ||
| if (!ClassDeclaration::object) { | ||
| error(Loc(), "declaration for class Object not found; druntime not " | ||
| "configured properly"); | ||
| fatal(); | ||
| } | ||
| } | ||
|
|
||
| CodeGenerator::~CodeGenerator() { | ||
| if (singleObj_) { | ||
| const char *oname; | ||
| const char *filename; | ||
| if ((oname = global.params.exefile) || | ||
| (oname = global.params.objname)) { | ||
| filename = FileName::forceExt(oname, global.obj_ext); | ||
| if (global.params.objdir) { | ||
| filename = FileName::combine(global.params.objdir, | ||
| FileName::name(filename)); | ||
| } | ||
| } else { | ||
| filename = firstModuleObjfileName_; | ||
| } | ||
|
|
||
| writeAndFreeLLModule(filename); | ||
| } | ||
| } | ||
|
|
||
| void CodeGenerator::prepareLLModule(Module *m) { | ||
| if (!firstModuleObjfileName_) { | ||
| firstModuleObjfileName_ = m->objfile->name->str; | ||
| } | ||
| ++moduleCount_; | ||
|
|
||
| if (singleObj_ && ir_) return; | ||
|
|
||
| assert(!ir_); | ||
|
|
||
| // See http://llvm.org/bugs/show_bug.cgi?id=11479 – just use the source file | ||
| // name, as it should not collide with a symbol name used somewhere in the | ||
| // module. | ||
| ir_ = new IRState(m->srcfile->toChars(), context_); | ||
| ir_->module.setTargetTriple(global.params.targetTriple.str()); | ||
| ir_->module.setDataLayout(gDataLayout->getStringRepresentation()); | ||
|
|
||
| // TODO: Make ldc::DIBuilder per-Module to be able to emit several CUs for | ||
| // singleObj compilations? | ||
| ir_->DBuilder.EmitCompileUnit(m); | ||
|
|
||
| IrDsymbol::resetAll(); | ||
| } | ||
|
|
||
| void CodeGenerator::finishLLModule(Module *m) { | ||
| if (singleObj_) return; | ||
|
|
||
| m->deleteObjFile(); | ||
| writeAndFreeLLModule(m->objfile->name->str); | ||
| } | ||
|
|
||
| void CodeGenerator::writeAndFreeLLModule(const char *filename) { | ||
| ir_->DBuilder.Finalize(); | ||
|
|
||
| #if LDC_LLVM_VER >= 303 | ||
| // Add the linker options metadata flag. | ||
| ir_->module.addModuleFlag( | ||
| llvm::Module::AppendUnique, "Linker Options", | ||
| llvm::MDNode::get(ir_->context(), ir_->LinkerMetadataArgs)); | ||
| #endif | ||
|
|
||
| #if LDC_LLVM_VER >= 304 | ||
| // Emit ldc version as llvm.ident metadata. | ||
| llvm::NamedMDNode *IdentMetadata = | ||
| ir_->module.getOrInsertNamedMetadata("llvm.ident"); | ||
| std::string Version("ldc version "); | ||
| Version.append(global.ldc_version); | ||
| #if LDC_LLVM_VER >= 306 | ||
| llvm::Metadata *IdentNode[] = | ||
| #else | ||
| llvm::Value *IdentNode[] = | ||
| #endif | ||
| {llvm::MDString::get(ir_->context(), Version)}; | ||
| IdentMetadata->addOperand(llvm::MDNode::get(ir_->context(), IdentNode)); | ||
| #endif | ||
|
|
||
| writeModule(&ir_->module, filename); | ||
| global.params.objfiles->push(const_cast<char *>(filename)); | ||
| delete ir_; | ||
| ir_ = 0; | ||
| } | ||
|
|
||
| void CodeGenerator::emit(Module *m) { | ||
| bool const loggerWasEnabled = Logger::enabled(); | ||
| if (m->llvmForceLogging && !loggerWasEnabled) { | ||
| Logger::enable(); | ||
| } | ||
|
|
||
| IF_LOG Logger::println("CodeGenerator::emit(%s)", m->toPrettyChars()); | ||
| LOG_SCOPE; | ||
|
|
||
| if (global.params.verbose_cg) { | ||
| printf("codegen: %s (%s)\n", m->toPrettyChars(), m->srcfile->toChars()); | ||
| } | ||
|
|
||
| if (global.errors) { | ||
| Logger::println("Aborting because of errors"); | ||
| fatal(); | ||
| } | ||
|
|
||
| prepareLLModule(m); | ||
|
|
||
| // If we are compiling to a single object file then only the first module needs | ||
| // to generate a call to _d_dso_registry(). All other modules only add a module | ||
| // reference. | ||
| // FIXME Find better name. | ||
| const bool emitFullModuleInfo = !singleObj_ || (singleObj_ && moduleCount_ == 1); | ||
| codegenModule(ir_, m, emitFullModuleInfo); | ||
| if (m == g_dMainModule) { | ||
| codegenModule(ir_, g_entrypointModule, emitFullModuleInfo); | ||
|
|
||
| // On Linux, strongly define the excecutabe BSS bracketing symbols in | ||
| // the main module for druntime use (see rt.sections_linux). | ||
| if (global.params.isLinux) { | ||
| emitSymbolAddrGlobal(ir_->module, "__bss_start", | ||
| "_d_execBssBegAddr"); | ||
| emitSymbolAddrGlobal(ir_->module, "_end", "_d_execBssEndAddr"); | ||
| } | ||
| } | ||
|
|
||
| finishLLModule(m); | ||
|
|
||
| if (m->llvmForceLogging && !loggerWasEnabled) { | ||
| Logger::disable(); | ||
| } | ||
| } | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| //===-- driver/codegenerator.h - D module codegen entry point ---*- C++ -*-===// | ||
| // | ||
| // LDC – the LLVM D compiler | ||
| // | ||
| // This file is distributed under the BSD-style LDC license. See the LICENSE | ||
| // file for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Contains ldc::CodeGenerator, which is the main entry point for emitting code | ||
| // for one or more D modules to LLVM IR and subsequently to whatever output | ||
| // format has been chosen globally. | ||
| // | ||
| // Currently reads parts of the configuration from global.params, as the code | ||
| // has been extracted straight out of main(). This should be cleaned up in the | ||
| // future. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LDC_DRIVER_CODEGENERATOR_H | ||
| #define LDC_DRIVER_CODEGENERATOR_H | ||
|
|
||
| #include "gen/irstate.h" | ||
|
|
||
| namespace ldc { | ||
|
|
||
| class CodeGenerator { | ||
| public: | ||
| CodeGenerator(llvm::LLVMContext &context, bool singleObj); | ||
| ~CodeGenerator(); | ||
| void emit(Module *m); | ||
|
|
||
| private: | ||
| void prepareLLModule(Module *m); | ||
| void finishLLModule(Module *m); | ||
| void writeAndFreeLLModule(const char *filename); | ||
|
|
||
| llvm::LLVMContext &context_; | ||
| int moduleCount_; | ||
| bool const singleObj_; | ||
| IRState *ir_; | ||
| const char *firstModuleObjfileName_; | ||
| }; | ||
| } | ||
|
|
||
| #endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.