mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-08 03:46:02 +03:00
Merge pull request #974 from klickverbot/singleobj-rework
Avoid using llvm::Linker
This commit is contained in:
commit
ec0d7bbcf1
38 changed files with 696 additions and 788 deletions
|
@ -228,6 +228,7 @@ file(GLOB IR_SRC ir/*.cpp)
|
||||||
file(GLOB IR_HDR ir/*.h)
|
file(GLOB IR_HDR ir/*.h)
|
||||||
set(DRV_SRC
|
set(DRV_SRC
|
||||||
driver/cl_options.cpp
|
driver/cl_options.cpp
|
||||||
|
driver/codegenerator.cpp
|
||||||
driver/configfile.cpp
|
driver/configfile.cpp
|
||||||
driver/targetmachine.cpp
|
driver/targetmachine.cpp
|
||||||
driver/toobj.cpp
|
driver/toobj.cpp
|
||||||
|
@ -239,6 +240,7 @@ set(DRV_SRC
|
||||||
set(DRV_HDR
|
set(DRV_HDR
|
||||||
driver/linker.h
|
driver/linker.h
|
||||||
driver/cl_options.h
|
driver/cl_options.h
|
||||||
|
driver/codegenerator.h
|
||||||
driver/configfile.h
|
driver/configfile.h
|
||||||
driver/ldc-version.h
|
driver/ldc-version.h
|
||||||
driver/targetmachine.h
|
driver/targetmachine.h
|
||||||
|
|
|
@ -84,24 +84,12 @@ class Expression;
|
||||||
class DeleteDeclaration;
|
class DeleteDeclaration;
|
||||||
class OverloadSet;
|
class OverloadSet;
|
||||||
struct AA;
|
struct AA;
|
||||||
#if IN_LLVM
|
|
||||||
class TypeInfoDeclaration;
|
|
||||||
class ClassInfoDeclaration;
|
|
||||||
#endif
|
|
||||||
#ifdef IN_GCC
|
#ifdef IN_GCC
|
||||||
typedef union tree_node TYPE;
|
typedef union tree_node TYPE;
|
||||||
#else
|
#else
|
||||||
struct TYPE;
|
struct TYPE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IN_LLVM
|
|
||||||
struct IRState;
|
|
||||||
namespace llvm
|
|
||||||
{
|
|
||||||
class Value;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct Ungag
|
struct Ungag
|
||||||
{
|
{
|
||||||
unsigned oldgag;
|
unsigned oldgag;
|
||||||
|
|
|
@ -134,7 +134,6 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do
|
||||||
// LDC
|
// LDC
|
||||||
llvmForceLogging = false;
|
llvmForceLogging = false;
|
||||||
noModuleInfo = false;
|
noModuleInfo = false;
|
||||||
moduleInfoVar = NULL;
|
|
||||||
this->doDocComment = doDocComment;
|
this->doDocComment = doDocComment;
|
||||||
this->doHdrGen = doHdrGen;
|
this->doHdrGen = doHdrGen;
|
||||||
this->arrayfuncs = 0;
|
this->arrayfuncs = 0;
|
||||||
|
|
|
@ -193,11 +193,9 @@ public:
|
||||||
llvm::Module* genLLVMModule(llvm::LLVMContext& context);
|
llvm::Module* genLLVMModule(llvm::LLVMContext& context);
|
||||||
void buildTargetFiles(bool singleObj, bool library);
|
void buildTargetFiles(bool singleObj, bool library);
|
||||||
File* buildFilePath(const char* forcename, const char* path, const char* ext);
|
File* buildFilePath(const char* forcename, const char* path, const char* ext);
|
||||||
llvm::GlobalVariable* moduleInfoSymbol();
|
|
||||||
|
|
||||||
bool llvmForceLogging;
|
bool llvmForceLogging;
|
||||||
bool noModuleInfo; /// Do not emit any module metadata.
|
bool noModuleInfo; /// Do not emit any module metadata.
|
||||||
llvm::GlobalVariable* moduleInfoVar;
|
|
||||||
|
|
||||||
// array ops emitted in this module already
|
// array ops emitted in this module already
|
||||||
AA *arrayfuncs;
|
AA *arrayfuncs;
|
||||||
|
|
215
driver/codegenerator.cpp
Normal file
215
driver/codegenerator.cpp
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
//===-- 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);
|
||||||
|
|
||||||
|
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), 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
codegenModule(ir_, m);
|
||||||
|
if (m == g_dMainModule) {
|
||||||
|
codegenModule(ir_, g_entrypointModule);
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
driver/codegenerator.h
Normal file
45
driver/codegenerator.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
//===-- 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_;
|
||||||
|
bool const singleObj_;
|
||||||
|
IRState *ir_;
|
||||||
|
const char *firstModuleObjfileName_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,11 +18,6 @@
|
||||||
#include "gen/optimizer.h"
|
#include "gen/optimizer.h"
|
||||||
#include "gen/programs.h"
|
#include "gen/programs.h"
|
||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/Triple.h"
|
||||||
#if LDC_LLVM_VER >= 305
|
|
||||||
#include "llvm/Linker/Linker.h"
|
|
||||||
#else
|
|
||||||
#include "llvm/Linker.h"
|
|
||||||
#endif
|
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/Program.h"
|
#include "llvm/Support/Program.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
|
|
312
driver/main.cpp
312
driver/main.cpp
|
@ -21,11 +21,11 @@
|
||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
#include "dmd2/target.h"
|
#include "dmd2/target.h"
|
||||||
#include "driver/cl_options.h"
|
#include "driver/cl_options.h"
|
||||||
|
#include "driver/codegenerator.h"
|
||||||
#include "driver/configfile.h"
|
#include "driver/configfile.h"
|
||||||
#include "driver/ldc-version.h"
|
#include "driver/ldc-version.h"
|
||||||
#include "driver/linker.h"
|
#include "driver/linker.h"
|
||||||
#include "driver/targetmachine.h"
|
#include "driver/targetmachine.h"
|
||||||
#include "driver/toobj.h"
|
|
||||||
#include "gen/cl_helpers.h"
|
#include "gen/cl_helpers.h"
|
||||||
#include "gen/irstate.h"
|
#include "gen/irstate.h"
|
||||||
#include "gen/linkage.h"
|
#include "gen/linkage.h"
|
||||||
|
@ -40,11 +40,6 @@
|
||||||
#include "llvm/InitializePasses.h"
|
#include "llvm/InitializePasses.h"
|
||||||
#endif
|
#endif
|
||||||
#include "llvm/LinkAllPasses.h"
|
#include "llvm/LinkAllPasses.h"
|
||||||
#if LDC_LLVM_VER >= 305
|
|
||||||
#include "llvm/Linker/Linker.h"
|
|
||||||
#else
|
|
||||||
#include "llvm/Linker.h"
|
|
||||||
#endif
|
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/Host.h"
|
#include "llvm/Support/Host.h"
|
||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
|
@ -873,105 +868,52 @@ static void dumpPredefinedVersions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Module *entrypoint = NULL;
|
/// Emits the .json AST description file.
|
||||||
static Module *rootHasMain = NULL;
|
///
|
||||||
|
/// This (ugly) piece of code has been taken from DMD's mars.c and should be
|
||||||
/// Callback to generate a C main() function, invoked by the frontend.
|
/// kept in sync with the former.
|
||||||
void genCmain(Scope *sc)
|
static void emitJson(Modules &modules)
|
||||||
{
|
{
|
||||||
if (entrypoint)
|
OutBuffer buf;
|
||||||
return;
|
json_generate(&buf, &modules);
|
||||||
|
|
||||||
/* The D code to be generated is provided as D source code in the form of a string.
|
// Write buf to file
|
||||||
* Note that Solaris, for unknown reasons, requires both a main() and an _main()
|
const char *name = global.params.jsonfilename;
|
||||||
*/
|
|
||||||
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;
|
if (name && name[0] == '-' && name[1] == 0)
|
||||||
Module *m = new Module("__entrypoint.d", id, 0, 0);
|
{ // Write to stdout; assume it succeeds
|
||||||
|
(void)fwrite(buf.data, 1, buf.offset, stdout);
|
||||||
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(NULL);
|
|
||||||
m->semantic();
|
|
||||||
m->semantic2();
|
|
||||||
m->semantic3();
|
|
||||||
global.params.verbose = v;
|
|
||||||
|
|
||||||
entrypoint = m;
|
|
||||||
rootHasMain = sc->module;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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.
|
|
||||||
static 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,
|
|
||||||
NULL, symbolName
|
|
||||||
);
|
|
||||||
new llvm::GlobalVariable(lm, voidPtr, false,
|
|
||||||
llvm::GlobalValue::ExternalLinkage,
|
|
||||||
llvm::ConstantExpr::getBitCast(targetSymbol, voidPtr),
|
|
||||||
addrName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds the __entrypoint module and related support code into the given LLVM
|
|
||||||
/// module. This assumes that genCmain() has already been called.
|
|
||||||
static void emitEntryPointInto(llvm::Module* lm)
|
|
||||||
{
|
|
||||||
assert(entrypoint && "Entry point Dmodule has not been generated.");
|
|
||||||
#if LDC_LLVM_VER >= 303
|
|
||||||
llvm::Linker linker(lm);
|
|
||||||
#else
|
|
||||||
llvm::Linker linker("ldc", lm);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
llvm::LLVMContext& context = lm->getContext();
|
|
||||||
llvm::Module* entryModule = entrypoint->genLLVMModule(context);
|
|
||||||
|
|
||||||
// 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(*entryModule, "__bss_start", "_d_execBssBegAddr");
|
|
||||||
emitSymbolAddrGlobal(*entryModule, "_end", "_d_execBssEndAddr");
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The filename generation code here should be harmonized with Module::setOutfile()
|
||||||
|
*/
|
||||||
|
const char *jsonfilename;
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 306
|
if (name && *name)
|
||||||
// FIXME: A possible error message is written to the diagnostic context
|
{
|
||||||
// Do we show these messages?
|
jsonfilename = FileName::defaultExt(name, global.json_ext);
|
||||||
linker.linkInModule(entryModule);
|
}
|
||||||
#else
|
else
|
||||||
std::string linkError;
|
{
|
||||||
#if LDC_LLVM_VER >= 303
|
// Generate json file name from first obj name
|
||||||
const bool hadError = linker.linkInModule(entryModule, &linkError);
|
const char *n = (*global.params.objfiles)[0];
|
||||||
#else
|
n = FileName::name(n);
|
||||||
const bool hadError = linker.LinkInModule(entryModule, &linkError);
|
|
||||||
linker.releaseModule();
|
//if (!FileName::absolute(name))
|
||||||
#endif
|
//name = FileName::combine(dir, name);
|
||||||
if (hadError)
|
|
||||||
error(Loc(), "%s", linkError.c_str());
|
jsonfilename = FileName::forceExt(n, global.json_ext);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
ensurePathToNameExists(Loc(), jsonfilename);
|
||||||
|
|
||||||
|
File *jsonfile = new File(jsonfilename);
|
||||||
|
|
||||||
|
jsonfile->setbuffer(buf.data, buf.offset);
|
||||||
|
jsonfile->ref = 1;
|
||||||
|
writeFile(Loc(), jsonfile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1334,175 +1276,42 @@ int main(int argc, char **argv)
|
||||||
// the user requested it.
|
// the user requested it.
|
||||||
if (global.params.moduleDepsFile != NULL)
|
if (global.params.moduleDepsFile != NULL)
|
||||||
{
|
{
|
||||||
assert (global.params.moduleDepsFile != NULL);
|
|
||||||
|
|
||||||
File deps(global.params.moduleDepsFile);
|
File deps(global.params.moduleDepsFile);
|
||||||
OutBuffer* ob = global.params.moduleDeps;
|
OutBuffer* ob = global.params.moduleDeps;
|
||||||
deps.setbuffer(static_cast<void*>(ob->data), ob->offset);
|
deps.setbuffer(static_cast<void*>(ob->data), ob->offset);
|
||||||
deps.write();
|
deps.write();
|
||||||
}
|
}
|
||||||
|
|
||||||
// collects llvm modules to be linked if singleobj is passed
|
// Generate one or more object/IR/bitcode files.
|
||||||
std::vector<llvm::Module*> llvmModules;
|
if (global.params.obj && !modules.empty())
|
||||||
llvm::LLVMContext& context = llvm::getGlobalContext();
|
|
||||||
|
|
||||||
// Generate output files
|
|
||||||
for (unsigned i = 0; i < modules.dim; i++)
|
|
||||||
{
|
{
|
||||||
Module *m = modules[i];
|
ldc::CodeGenerator cg(llvm::getGlobalContext(), singleObj);
|
||||||
if (global.params.verbose)
|
|
||||||
fprintf(global.stdmsg, "code %s\n", m->toChars());
|
for (unsigned i = 0; i < modules.dim; i++)
|
||||||
if (global.params.obj)
|
|
||||||
{
|
{
|
||||||
llvm::Module* lm = m->genLLVMModule(context);
|
Module * const m = modules[i];
|
||||||
|
if (global.params.verbose)
|
||||||
|
fprintf(global.stdmsg, "code %s\n", m->toChars());
|
||||||
|
|
||||||
|
cg.emit(m);
|
||||||
|
|
||||||
if (global.errors)
|
if (global.errors)
|
||||||
fatal();
|
fatal();
|
||||||
|
|
||||||
if (entrypoint && rootHasMain == m)
|
|
||||||
emitEntryPointInto(lm);
|
|
||||||
|
|
||||||
if (!singleObj)
|
|
||||||
{
|
|
||||||
m->deleteObjFile();
|
|
||||||
writeModule(lm, m->objfile->name->str);
|
|
||||||
global.params.objfiles->push(const_cast<char*>(m->objfile->name->str));
|
|
||||||
delete lm;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
llvmModules.push_back(lm);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (global.params.doDocComments)
|
|
||||||
gendocfile(m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal linking for singleobj
|
// Generate DDoc output files.
|
||||||
if (singleObj && llvmModules.size() > 0)
|
if (global.params.doDocComments)
|
||||||
{
|
{
|
||||||
Module *m = modules[0];
|
for (unsigned i = 0; i < modules.dim; i++)
|
||||||
|
|
||||||
const char* oname;
|
|
||||||
const char* filename;
|
|
||||||
if ((oname = global.params.exefile) || (oname = global.params.objname))
|
|
||||||
{
|
{
|
||||||
filename = FileName::forceExt(oname, global.obj_ext);
|
gendocfile(modules[i]);
|
||||||
if (global.params.objdir)
|
|
||||||
{
|
|
||||||
filename = FileName::combine(global.params.objdir, FileName::name(filename));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
filename = m->objfile->name->str;
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
// Temporary workaround for http://llvm.org/bugs/show_bug.cgi?id=11479.
|
|
||||||
char* moduleName = const_cast<char*>(filename);
|
|
||||||
#else
|
|
||||||
char* moduleName = m->toChars();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 306
|
|
||||||
llvm::Linker linker(llvmModules[0]);
|
|
||||||
#elif LDC_LLVM_VER >= 303
|
|
||||||
llvm::Linker linker(new llvm::Module(moduleName, context));
|
|
||||||
#else
|
|
||||||
llvm::Linker linker("ldc", moduleName, context);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string errormsg;
|
|
||||||
#if LDC_LLVM_VER >= 306
|
|
||||||
for (size_t i = 1; i < llvmModules.size(); i++)
|
|
||||||
#else
|
|
||||||
for (size_t i = 0; i < llvmModules.size(); i++)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#if LDC_LLVM_VER >= 306
|
|
||||||
// Issue #855: There seems to be a problem with identified structs.
|
|
||||||
// If a module imports a class or struct from another module and
|
|
||||||
// both modules are compiled together then both modules use the
|
|
||||||
// same type object. The error happens if the type is already
|
|
||||||
// remapped in one module and then the other module is linked.
|
|
||||||
// The workaround seems to be to do the linking twice, always
|
|
||||||
// uniquing all identified structs.
|
|
||||||
//
|
|
||||||
// This replaces the line:
|
|
||||||
// linker.linkInModule(llvmModules[i]);
|
|
||||||
//
|
|
||||||
// TODO: Check LLVM bug database if this is a bug.
|
|
||||||
llvm::Linker dummy(new llvm::Module("dummy module", context));
|
|
||||||
dummy.linkInModule(llvmModules[i]);
|
|
||||||
linker.linkInModule(dummy.getModule());
|
|
||||||
dummy.deleteModule();
|
|
||||||
#else
|
|
||||||
#if LDC_LLVM_VER >= 303
|
|
||||||
if (linker.linkInModule(llvmModules[i], &errormsg))
|
|
||||||
#else
|
|
||||||
if (linker.LinkInModule(llvmModules[i], &errormsg))
|
|
||||||
#endif
|
|
||||||
error(Loc(), "%s", errormsg.c_str());
|
|
||||||
#endif
|
|
||||||
delete llvmModules[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
m->deleteObjFile();
|
|
||||||
writeModule(linker.getModule(), filename);
|
|
||||||
global.params.objfiles->push(const_cast<char*>(filename));
|
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 304
|
|
||||||
linker.deleteModule();
|
|
||||||
#elif LDC_LLVM_VER == 303
|
|
||||||
delete linker.getModule();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// output json file
|
// Generate the AST-describing JSON file.
|
||||||
if (global.params.doJsonGeneration)
|
if (global.params.doJsonGeneration)
|
||||||
{
|
emitJson(modules);
|
||||||
OutBuffer buf;
|
|
||||||
json_generate(&buf, &modules);
|
|
||||||
|
|
||||||
// Write buf to file
|
|
||||||
const char *name = global.params.jsonfilename;
|
|
||||||
|
|
||||||
if (name && name[0] == '-' && name[1] == 0)
|
|
||||||
{ // Write to stdout; assume it succeeds
|
|
||||||
(void)fwrite(buf.data, 1, buf.offset, stdout);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The filename generation code here should be harmonized with Module::setOutfile()
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char *jsonfilename;
|
|
||||||
|
|
||||||
if (name && *name)
|
|
||||||
{
|
|
||||||
jsonfilename = FileName::defaultExt(name, global.json_ext);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Generate json file name from first obj name
|
|
||||||
const char *n = (*global.params.objfiles)[0];
|
|
||||||
n = FileName::name(n);
|
|
||||||
|
|
||||||
//if (!FileName::absolute(name))
|
|
||||||
//name = FileName::combine(dir, name);
|
|
||||||
|
|
||||||
jsonfilename = FileName::forceExt(n, global.json_ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
ensurePathToNameExists(Loc(), jsonfilename);
|
|
||||||
|
|
||||||
File *jsonfile = new File(jsonfilename);
|
|
||||||
|
|
||||||
jsonfile->setbuffer(buf.data, buf.offset);
|
|
||||||
jsonfile->ref = 1;
|
|
||||||
writeFile(Loc(), jsonfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LLVM_D_FreeRuntime();
|
LLVM_D_FreeRuntime();
|
||||||
llvm::llvm_shutdown();
|
llvm::llvm_shutdown();
|
||||||
|
@ -1510,6 +1319,8 @@ int main(int argc, char **argv)
|
||||||
if (global.errors)
|
if (global.errors)
|
||||||
fatal();
|
fatal();
|
||||||
|
|
||||||
|
// Finally, produce the final executable/archive and run it, if we are
|
||||||
|
// supposed to.
|
||||||
int status = EXIT_SUCCESS;
|
int status = EXIT_SUCCESS;
|
||||||
if (!global.params.objfiles->dim)
|
if (!global.params.objfiles->dim)
|
||||||
{
|
{
|
||||||
|
@ -1529,8 +1340,7 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
status = runExecutable();
|
status = runExecutable();
|
||||||
|
|
||||||
/* Delete .obj files and .exe file
|
/// Delete .obj files and .exe file.
|
||||||
*/
|
|
||||||
for (unsigned i = 0; i < modules.dim; i++)
|
for (unsigned i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
modules[i]->deleteObjFile();
|
modules[i]->deleteObjFile();
|
||||||
|
|
|
@ -381,7 +381,7 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
|
||||||
// we need to make a global with the data, so we have a pointer to the array
|
// we need to make a global with the data, so we have a pointer to the array
|
||||||
// Important: don't make the gvar constant, since this const initializer might
|
// Important: don't make the gvar constant, since this const initializer might
|
||||||
// be used as an initializer for a static T[] - where modifying contents is allowed.
|
// be used as an initializer for a static T[] - where modifying contents is allowed.
|
||||||
LLGlobalVariable* gvar = new LLGlobalVariable(*gIR->module, constarr->getType(), false, LLGlobalValue::InternalLinkage, constarr, ".constarray");
|
LLGlobalVariable* gvar = new LLGlobalVariable(gIR->module, constarr->getType(), false, LLGlobalValue::InternalLinkage, constarr, ".constarray");
|
||||||
|
|
||||||
if (arrty->ty == Tpointer)
|
if (arrty->ty == Tpointer)
|
||||||
// we need to return pointer to the static array.
|
// we need to return pointer to the static array.
|
||||||
|
@ -477,7 +477,7 @@ void initializeArrayLiteral(IRState* p, ArrayLiteralExp* ale, LLValue* dstMem)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
|
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
|
||||||
*gIR->module,
|
gIR->module,
|
||||||
constarr->getType(),
|
constarr->getType(),
|
||||||
true,
|
true,
|
||||||
LLGlobalValue::InternalLinkage,
|
LLGlobalValue::InternalLinkage,
|
||||||
|
@ -669,7 +669,7 @@ DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Constant* dims = llvm::ConstantArray::get(llvm::ArrayType::get(DtoSize_t(), ndims), argsdims);
|
llvm::Constant* dims = llvm::ConstantArray::get(llvm::ArrayType::get(DtoSize_t(), ndims), argsdims);
|
||||||
LLGlobalVariable* gvar = new llvm::GlobalVariable(*gIR->module, dims->getType(), true, LLGlobalValue::InternalLinkage, dims, ".dimsarray");
|
LLGlobalVariable* gvar = new llvm::GlobalVariable(gIR->module, dims->getType(), true, LLGlobalValue::InternalLinkage, dims, ".dimsarray");
|
||||||
array = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(dims->getType()));
|
array = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(dims->getType()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -507,7 +507,7 @@ static LLConstant* build_offti_array(ClassDeclaration* cd, LLType* arrayT)
|
||||||
LLConstant* arrInit = LLConstantArray::get(arrTy, arrayInits);
|
LLConstant* arrInit = LLConstantArray::get(arrTy, arrayInits);
|
||||||
|
|
||||||
// create symbol
|
// create symbol
|
||||||
llvm::GlobalVariable* gvar = getOrCreateGlobal(cd->loc, *gIR->module, arrTy,
|
llvm::GlobalVariable* gvar = getOrCreateGlobal(cd->loc, gIR->module, arrTy,
|
||||||
true, llvm::GlobalValue::InternalLinkage, arrInit, ".offti");
|
true, llvm::GlobalValue::InternalLinkage, arrInit, ".offti");
|
||||||
ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType()));
|
ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType()));
|
||||||
|
|
||||||
|
|
|
@ -17,39 +17,38 @@
|
||||||
void emitCoverageLinecountInc(Loc &loc) {
|
void emitCoverageLinecountInc(Loc &loc) {
|
||||||
// Only emit coverage increment for locations in the source of the current module
|
// Only emit coverage increment for locations in the source of the current module
|
||||||
// (for example, 'inlined' methods from other source files should be skipped).
|
// (for example, 'inlined' methods from other source files should be skipped).
|
||||||
if ( global.params.cov && (loc.linnum != 0) && loc.filename
|
if (!global.params.cov || !loc.linnum || !loc.filename ||
|
||||||
&& (gIR->module->getModuleIdentifier().compare(loc.filename) == 0) )
|
strcmp(gIR->dmodule->srcfile->name->toChars(), loc.filename) != 0) {
|
||||||
{
|
return;
|
||||||
unsigned line = loc.linnum-1; // convert to 0-based line# index
|
|
||||||
assert(line < gIR->dmodule->numlines);
|
|
||||||
{
|
|
||||||
IF_LOG Logger::println("Coverage: increment _d_cover_data[%d]", line);
|
|
||||||
|
|
||||||
// Get GEP into _d_cover_data array
|
|
||||||
LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(line) };
|
|
||||||
LLValue* ptr = llvm::ConstantExpr::getGetElementPtr(
|
|
||||||
#if LDC_LLVM_VER >= 307
|
|
||||||
LLArrayType::get(LLType::getInt32Ty(gIR->context()), gIR->dmodule->numlines),
|
|
||||||
#endif
|
|
||||||
gIR->dmodule->d_cover_data, idxs, true);
|
|
||||||
|
|
||||||
// Do an atomic increment, so this works when multiple threads are executed.
|
|
||||||
gIR->ir->CreateAtomicRMW(
|
|
||||||
llvm::AtomicRMWInst::Add,
|
|
||||||
ptr,
|
|
||||||
DtoConstUint(1),
|
|
||||||
llvm::Monotonic
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
unsigned num_sizet_bits = gDataLayout->getTypeSizeInBits(DtoSize_t());
|
|
||||||
unsigned idx = line / num_sizet_bits;
|
|
||||||
unsigned bitidx = line % num_sizet_bits;
|
|
||||||
|
|
||||||
IF_LOG Logger::println(" _d_cover_valid[%d] |= (1 << %d)", idx, bitidx);
|
|
||||||
|
|
||||||
gIR->dmodule->d_cover_valid_init[idx] |= (size_t(1) << bitidx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
const unsigned line = loc.linnum - 1; // convert to 0-based line# index
|
||||||
|
assert(line < gIR->dmodule->numlines);
|
||||||
|
|
||||||
|
IF_LOG Logger::println("Coverage: increment _d_cover_data[%d]", line);
|
||||||
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
// Get GEP into _d_cover_data array
|
||||||
|
LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(line) };
|
||||||
|
LLValue* ptr = llvm::ConstantExpr::getGetElementPtr(
|
||||||
|
#if LDC_LLVM_VER >= 307
|
||||||
|
LLArrayType::get(LLType::getInt32Ty(gIR->context()), gIR->dmodule->numlines),
|
||||||
|
#endif
|
||||||
|
gIR->dmodule->d_cover_data, idxs, true);
|
||||||
|
|
||||||
|
// Do an atomic increment, so this works when multiple threads are executed.
|
||||||
|
gIR->ir->CreateAtomicRMW(
|
||||||
|
llvm::AtomicRMWInst::Add,
|
||||||
|
ptr,
|
||||||
|
DtoConstUint(1),
|
||||||
|
llvm::Monotonic
|
||||||
|
);
|
||||||
|
|
||||||
|
unsigned num_sizet_bits = gDataLayout->getTypeSizeInBits(DtoSize_t());
|
||||||
|
unsigned idx = line / num_sizet_bits;
|
||||||
|
unsigned bitidx = line % num_sizet_bits;
|
||||||
|
|
||||||
|
IF_LOG Logger::println("_d_cover_valid[%d] |= (1 << %d)", idx, bitidx);
|
||||||
|
|
||||||
|
gIR->dmodule->d_cover_valid_init[idx] |= (size_t(1) << bitidx);
|
||||||
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ public:
|
||||||
if (initVal->getType() != gvar->getType()->getElementType())
|
if (initVal->getType() != gvar->getType()->getElementType())
|
||||||
{
|
{
|
||||||
llvm::GlobalVariable* newGvar = getOrCreateGlobal(decl->loc,
|
llvm::GlobalVariable* newGvar = getOrCreateGlobal(decl->loc,
|
||||||
*irs->module, initVal->getType(), gvar->isConstant(),
|
irs->module, initVal->getType(), gvar->isConstant(),
|
||||||
llLinkage, 0,
|
llLinkage, 0,
|
||||||
"", // We take on the name of the old global below.
|
"", // We take on the name of the old global below.
|
||||||
gvar->isThreadLocal());
|
gvar->isThreadLocal());
|
||||||
|
|
|
@ -53,8 +53,8 @@ Module *ldc::DIBuilder::getDefinedModule(Dsymbol *s)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ldc::DIBuilder::DIBuilder(IRState *const IR, llvm::Module &M)
|
ldc::DIBuilder::DIBuilder(IRState *const IR)
|
||||||
: IR(IR), DBuilder(M)
|
: IR(IR), DBuilder(IR->module), CUNode(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,13 +656,16 @@ void ldc::DIBuilder::EmitCompileUnit(Module *m)
|
||||||
Logger::println("D to dwarf compile_unit");
|
Logger::println("D to dwarf compile_unit");
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
assert(!CUNode &&
|
||||||
|
"Already created compile unit for this DIBuilder instance");
|
||||||
|
|
||||||
// prepare srcpath
|
// prepare srcpath
|
||||||
llvm::SmallString<128> srcpath(m->srcfile->name->toChars());
|
llvm::SmallString<128> srcpath(m->srcfile->name->toChars());
|
||||||
llvm::sys::fs::make_absolute(srcpath);
|
llvm::sys::fs::make_absolute(srcpath);
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 304
|
#if LDC_LLVM_VER >= 304
|
||||||
// Metadata without a correct version will be stripped by UpgradeDebugInfo.
|
// Metadata without a correct version will be stripped by UpgradeDebugInfo.
|
||||||
gIR->module->addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION);
|
IR->module.addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION);
|
||||||
|
|
||||||
CUNode =
|
CUNode =
|
||||||
#endif
|
#endif
|
||||||
|
@ -971,7 +974,7 @@ ldc::DIGlobalVariable ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *l
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ldc::DIBuilder::EmitModuleEnd()
|
void ldc::DIBuilder::Finalize()
|
||||||
{
|
{
|
||||||
if (!global.params.symdebug)
|
if (!global.params.symdebug)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -127,7 +127,7 @@ class DIBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DIBuilder(IRState *const IR, llvm::Module &M);
|
DIBuilder(IRState *const IR);
|
||||||
|
|
||||||
/// \brief Emit the Dwarf compile_unit global for a Module m.
|
/// \brief Emit the Dwarf compile_unit global for a Module m.
|
||||||
/// \param m Module to emit as compile unit.
|
/// \param m Module to emit as compile unit.
|
||||||
|
@ -183,7 +183,7 @@ public:
|
||||||
/// \param vd Variable declaration to emit debug info for.
|
/// \param vd Variable declaration to emit debug info for.
|
||||||
DIGlobalVariable EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd); // FIXME
|
DIGlobalVariable EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd); // FIXME
|
||||||
|
|
||||||
void EmitModuleEnd();
|
void Finalize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
llvm::LLVMContext &getContext();
|
llvm::LLVMContext &getContext();
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "gen/functions.h"
|
#include "gen/functions.h"
|
||||||
|
|
||||||
#include "aggregate.h"
|
#include "aggregate.h"
|
||||||
#include "declaration.h"
|
#include "declaration.h"
|
||||||
#include "id.h"
|
#include "id.h"
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
#include "gen/arrays.h"
|
#include "gen/arrays.h"
|
||||||
#include "gen/classes.h"
|
#include "gen/classes.h"
|
||||||
#include "gen/dvalue.h"
|
#include "gen/dvalue.h"
|
||||||
|
#include "gen/inlineir.h"
|
||||||
#include "gen/irstate.h"
|
#include "gen/irstate.h"
|
||||||
#include "gen/linkage.h"
|
#include "gen/linkage.h"
|
||||||
#include "gen/llvm.h"
|
#include "gen/llvm.h"
|
||||||
|
@ -30,11 +32,7 @@
|
||||||
#include "gen/pragma.h"
|
#include "gen/pragma.h"
|
||||||
#include "gen/runtime.h"
|
#include "gen/runtime.h"
|
||||||
#include "gen/tollvm.h"
|
#include "gen/tollvm.h"
|
||||||
#if LDC_LLVM_VER >= 305
|
#include "ir/irmodule.h"
|
||||||
#include "llvm/Linker/Linker.h"
|
|
||||||
#else
|
|
||||||
#include "llvm/Linker.h"
|
|
||||||
#endif
|
|
||||||
#if LDC_LLVM_VER >= 303
|
#if LDC_LLVM_VER >= 303
|
||||||
#include "llvm/IR/Intrinsics.h"
|
#include "llvm/IR/Intrinsics.h"
|
||||||
#else
|
#else
|
||||||
|
@ -222,114 +220,6 @@ llvm::FunctionType* DtoFunctionType(Type* type, IrFuncTy &irFty, Type* thistype,
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
#include "llvm/Support/SourceMgr.h"
|
|
||||||
#if LDC_LLVM_VER >= 305
|
|
||||||
#include "llvm/AsmParser/Parser.h"
|
|
||||||
#else
|
|
||||||
#include "llvm/Assembly/Parser.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LLFunction* DtoInlineIRFunction(FuncDeclaration* fdecl)
|
|
||||||
{
|
|
||||||
const char* mangled_name = mangleExact(fdecl);
|
|
||||||
TemplateInstance* tinst = fdecl->parent->isTemplateInstance();
|
|
||||||
assert(tinst);
|
|
||||||
|
|
||||||
Objects& objs = tinst->tdtypes;
|
|
||||||
assert(objs.dim == 3);
|
|
||||||
|
|
||||||
Expression* a0 = isExpression(objs[0]);
|
|
||||||
assert(a0);
|
|
||||||
StringExp* strexp = a0->toStringExp();
|
|
||||||
assert(strexp);
|
|
||||||
assert(strexp->sz == 1);
|
|
||||||
std::string code(static_cast<char*>(strexp->string), strexp->len);
|
|
||||||
|
|
||||||
Type* ret = isType(objs[1]);
|
|
||||||
assert(ret);
|
|
||||||
|
|
||||||
Tuple* a2 = isTuple(objs[2]);
|
|
||||||
assert(a2);
|
|
||||||
Objects& arg_types = a2->objects;
|
|
||||||
|
|
||||||
std::string str;
|
|
||||||
llvm::raw_string_ostream stream(str);
|
|
||||||
stream << "define " << *DtoType(ret) << " @" << mangled_name << "(";
|
|
||||||
|
|
||||||
for(size_t i = 0; ;)
|
|
||||||
{
|
|
||||||
Type* ty = isType(arg_types[i]);
|
|
||||||
//assert(ty);
|
|
||||||
if(!ty)
|
|
||||||
{
|
|
||||||
error(tinst->loc,
|
|
||||||
"All parameters of a template defined with pragma llvm_inline_ir, except for the first one, should be types");
|
|
||||||
fatal();
|
|
||||||
}
|
|
||||||
stream << *DtoType(ty);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
if(i >= arg_types.dim)
|
|
||||||
break;
|
|
||||||
|
|
||||||
stream << ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ret->ty == Tvoid)
|
|
||||||
code.append("\nret void");
|
|
||||||
|
|
||||||
stream << ")\n{\n" << code << "\n}";
|
|
||||||
|
|
||||||
llvm::SMDiagnostic err;
|
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 306
|
|
||||||
std::unique_ptr<llvm::Module> m = llvm::parseAssemblyString(
|
|
||||||
stream.str().c_str(), err, gIR->context());
|
|
||||||
#elif LDC_LLVM_VER >= 303
|
|
||||||
llvm::Module* m = llvm::ParseAssemblyString(
|
|
||||||
stream.str().c_str(), NULL, err, gIR->context());
|
|
||||||
#else
|
|
||||||
llvm::ParseAssemblyString(
|
|
||||||
stream.str().c_str(), gIR->module, err, gIR->context());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string errstr = err.getMessage();
|
|
||||||
if(errstr != "")
|
|
||||||
error(tinst->loc,
|
|
||||||
"can't parse inline LLVM IR:\n%s\n%s\n%s\nThe input string was: \n%s",
|
|
||||||
#if LDC_LLVM_VER >= 303
|
|
||||||
err.getLineContents().str().c_str(),
|
|
||||||
#else
|
|
||||||
err.getLineContents().c_str(),
|
|
||||||
#endif
|
|
||||||
(std::string(err.getColumnNo(), ' ') + '^').c_str(),
|
|
||||||
errstr.c_str(), stream.str().c_str());
|
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 306
|
|
||||||
llvm::Linker(gIR->module).linkInModule(m.get());
|
|
||||||
#else
|
|
||||||
#if LDC_LLVM_VER >= 303
|
|
||||||
std::string errstr2 = "";
|
|
||||||
#if LDC_LLVM_VER >= 306
|
|
||||||
llvm::Linker(gIR->module).linkInModule(m.get(), &errstr2);
|
|
||||||
#else
|
|
||||||
llvm::Linker(gIR->module).linkInModule(m, &errstr2);
|
|
||||||
#endif
|
|
||||||
if(errstr2 != "")
|
|
||||||
error(tinst->loc,
|
|
||||||
"Error when linking in llvm inline ir: %s", errstr2.c_str());
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LLFunction* fun = gIR->module->getFunction(mangled_name);
|
|
||||||
fun->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
|
|
||||||
fun->addFnAttr(LDC_ATTRIBUTE(AlwaysInline));
|
|
||||||
return fun;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
|
static llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
|
||||||
{
|
{
|
||||||
IrFuncTy &irFty = getIrFunc(fdecl, true)->irFty;
|
IrFuncTy &irFty = getIrFunc(fdecl, true)->irFty;
|
||||||
|
@ -593,7 +483,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||||
|
|
||||||
// construct function
|
// construct function
|
||||||
LLFunctionType* functype = DtoFunctionType(fdecl);
|
LLFunctionType* functype = DtoFunctionType(fdecl);
|
||||||
LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangledName);
|
LLFunction* func = vafunc ? vafunc : gIR->module.getFunction(mangledName);
|
||||||
if (!func) {
|
if (!func) {
|
||||||
if(fdecl->llvmInternal == LLVMinline_ir)
|
if(fdecl->llvmInternal == LLVMinline_ir)
|
||||||
{
|
{
|
||||||
|
@ -604,7 +494,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||||
// All function declarations are "external" - any other linkage type
|
// All function declarations are "external" - any other linkage type
|
||||||
// is set when actually defining the function.
|
// is set when actually defining the function.
|
||||||
func = LLFunction::Create(functype,
|
func = LLFunction::Create(functype,
|
||||||
llvm::GlobalValue::ExternalLinkage, mangledName, gIR->module);
|
llvm::GlobalValue::ExternalLinkage, mangledName, &gIR->module);
|
||||||
}
|
}
|
||||||
} else if (func->getFunctionType() != functype) {
|
} else if (func->getFunctionType() != functype) {
|
||||||
error(fdecl->loc, "Function type does not match previously declared function with the same mangled name: %s", mangleExact(fdecl));
|
error(fdecl->loc, "Function type does not match previously declared function with the same mangled name: %s", mangleExact(fdecl));
|
||||||
|
@ -833,19 +723,21 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
||||||
assert(fd->ident != Id::empty);
|
assert(fd->ident != Id::empty);
|
||||||
|
|
||||||
if (fd->isUnitTestDeclaration()) {
|
if (fd->isUnitTestDeclaration()) {
|
||||||
gIR->unitTests.push_back(fd);
|
getIrModule(gIR->dmodule)->unitTests.push_back(fd);
|
||||||
} else if (fd->isSharedStaticCtorDeclaration()) {
|
} else if (fd->isSharedStaticCtorDeclaration()) {
|
||||||
gIR->sharedCtors.push_back(fd);
|
getIrModule(gIR->dmodule)->sharedCtors.push_back(fd);
|
||||||
} else if (StaticDtorDeclaration *dtorDecl = fd->isSharedStaticDtorDeclaration()) {
|
} else if (StaticDtorDeclaration *dtorDecl = fd->isSharedStaticDtorDeclaration()) {
|
||||||
gIR->sharedDtors.push_front(fd);
|
getIrModule(gIR->dmodule)->sharedDtors.push_front(fd);
|
||||||
if (dtorDecl->vgate)
|
if (dtorDecl->vgate) {
|
||||||
gIR->sharedGates.push_front(dtorDecl->vgate);
|
getIrModule(gIR->dmodule)->sharedGates.push_front(dtorDecl->vgate);
|
||||||
|
}
|
||||||
} else if (fd->isStaticCtorDeclaration()) {
|
} else if (fd->isStaticCtorDeclaration()) {
|
||||||
gIR->ctors.push_back(fd);
|
getIrModule(gIR->dmodule)->ctors.push_back(fd);
|
||||||
} else if (StaticDtorDeclaration *dtorDecl = fd->isStaticDtorDeclaration()) {
|
} else if (StaticDtorDeclaration *dtorDecl = fd->isStaticDtorDeclaration()) {
|
||||||
gIR->dtors.push_front(fd);
|
getIrModule(gIR->dmodule)->dtors.push_front(fd);
|
||||||
if (dtorDecl->vgate)
|
if (dtorDecl->vgate) {
|
||||||
gIR->gates.push_front(dtorDecl->vgate);
|
getIrModule(gIR->dmodule)->gates.push_front(dtorDecl->vgate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -875,9 +767,6 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
||||||
IF_LOG Logger::println("Doing function body for: %s", fd->toChars());
|
IF_LOG Logger::println("Doing function body for: %s", fd->toChars());
|
||||||
gIR->functions.push_back(irFunc);
|
gIR->functions.push_back(irFunc);
|
||||||
|
|
||||||
if (fd->isMain())
|
|
||||||
gIR->emitMain = true;
|
|
||||||
|
|
||||||
func->setLinkage(lowerFuncLinkage(fd));
|
func->setLinkage(lowerFuncLinkage(fd));
|
||||||
|
|
||||||
// On x86_64, always set 'uwtable' for System V ABI compatibility.
|
// On x86_64, always set 'uwtable' for System V ABI compatibility.
|
||||||
|
|
107
gen/inlineir.cpp
Normal file
107
gen/inlineir.cpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#include "gen/inlineir.h"
|
||||||
|
|
||||||
|
#include "declaration.h"
|
||||||
|
#include "template.h"
|
||||||
|
#include "gen/irstate.h"
|
||||||
|
#include "gen/tollvm.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include "llvm/Support/SourceMgr.h"
|
||||||
|
#if LDC_LLVM_VER >= 305
|
||||||
|
#include "llvm/AsmParser/Parser.h"
|
||||||
|
#include "llvm/Linker/Linker.h"
|
||||||
|
#else
|
||||||
|
#include "llvm/Assembly/Parser.h"
|
||||||
|
#include "llvm/Linker.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
llvm::Function* DtoInlineIRFunction(FuncDeclaration* fdecl)
|
||||||
|
{
|
||||||
|
const char* mangled_name = mangleExact(fdecl);
|
||||||
|
TemplateInstance* tinst = fdecl->parent->isTemplateInstance();
|
||||||
|
assert(tinst);
|
||||||
|
|
||||||
|
Objects& objs = tinst->tdtypes;
|
||||||
|
assert(objs.dim == 3);
|
||||||
|
|
||||||
|
Expression* a0 = isExpression(objs[0]);
|
||||||
|
assert(a0);
|
||||||
|
StringExp* strexp = a0->toStringExp();
|
||||||
|
assert(strexp);
|
||||||
|
assert(strexp->sz == 1);
|
||||||
|
std::string code(static_cast<char*>(strexp->string), strexp->len);
|
||||||
|
|
||||||
|
Type* ret = isType(objs[1]);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
Tuple* a2 = isTuple(objs[2]);
|
||||||
|
assert(a2);
|
||||||
|
Objects& arg_types = a2->objects;
|
||||||
|
|
||||||
|
std::string str;
|
||||||
|
llvm::raw_string_ostream stream(str);
|
||||||
|
stream << "define " << *DtoType(ret) << " @" << mangled_name << "(";
|
||||||
|
|
||||||
|
for(size_t i = 0; ;)
|
||||||
|
{
|
||||||
|
Type* ty = isType(arg_types[i]);
|
||||||
|
//assert(ty);
|
||||||
|
if(!ty)
|
||||||
|
{
|
||||||
|
error(tinst->loc,
|
||||||
|
"All parameters of a template defined with pragma llvm_inline_ir, except for the first one, should be types");
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
stream << *DtoType(ty);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
if(i >= arg_types.dim)
|
||||||
|
break;
|
||||||
|
|
||||||
|
stream << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret->ty == Tvoid)
|
||||||
|
code.append("\nret void");
|
||||||
|
|
||||||
|
stream << ")\n{\n" << code << "\n}";
|
||||||
|
|
||||||
|
llvm::SMDiagnostic err;
|
||||||
|
|
||||||
|
#if LDC_LLVM_VER >= 306
|
||||||
|
std::unique_ptr<llvm::Module> m = llvm::parseAssemblyString(
|
||||||
|
stream.str().c_str(), err, gIR->context());
|
||||||
|
#elif LDC_LLVM_VER >= 303
|
||||||
|
llvm::Module* m = llvm::ParseAssemblyString(
|
||||||
|
stream.str().c_str(), NULL, err, gIR->context());
|
||||||
|
#else
|
||||||
|
llvm::ParseAssemblyString(
|
||||||
|
stream.str().c_str(), &gIR->module, err, gIR->context());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string errstr = err.getMessage();
|
||||||
|
if(errstr != "")
|
||||||
|
error(tinst->loc,
|
||||||
|
"can't parse inline LLVM IR:\n%s\n%s\n%s\nThe input string was: \n%s",
|
||||||
|
#if LDC_LLVM_VER >= 303
|
||||||
|
err.getLineContents().str().c_str(),
|
||||||
|
#else
|
||||||
|
err.getLineContents().c_str(),
|
||||||
|
#endif
|
||||||
|
(std::string(err.getColumnNo(), ' ') + '^').c_str(),
|
||||||
|
errstr.c_str(), stream.str().c_str());
|
||||||
|
|
||||||
|
#if LDC_LLVM_VER >= 306
|
||||||
|
llvm::Linker(&gIR->module).linkInModule(m.get());
|
||||||
|
#elif LDC_LLVM_VER >= 303
|
||||||
|
std::string errstr2 = "";
|
||||||
|
llvm::Linker(&gIR->module).linkInModule(m, &errstr2);
|
||||||
|
if(errstr2 != "")
|
||||||
|
error(tinst->loc,
|
||||||
|
"Error when linking in llvm inline ir: %s", errstr2.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LLFunction* fun = gIR->module.getFunction(mangled_name);
|
||||||
|
fun->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
|
||||||
|
fun->addFnAttr(LDC_ATTRIBUTE(AlwaysInline));
|
||||||
|
return fun;
|
||||||
|
}
|
24
gen/inlineir.h
Normal file
24
gen/inlineir.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
//===-- gen/irstate.h - Inline IR implementation-----------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// LDC – the LLVM D compiler
|
||||||
|
//
|
||||||
|
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||||||
|
// file for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Contains the implementation for the LDC-specific LLVM inline IR feature.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LDC_GEN_INLINEIR_H
|
||||||
|
#define LDC_GEN_INLINEIR_H
|
||||||
|
|
||||||
|
class FuncDeclaration;
|
||||||
|
namespace llvm {
|
||||||
|
class Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Function* DtoInlineIRFunction(FuncDeclaration* fdecl);
|
||||||
|
|
||||||
|
#endif
|
|
@ -67,15 +67,13 @@ IRTargetScope::IRTargetScope(
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
IRState::IRState(llvm::Module* m)
|
IRState::IRState(const char *name, llvm::LLVMContext &context)
|
||||||
: module(m), DBuilder(this, *m)
|
: module(name, context), DBuilder(this)
|
||||||
{
|
{
|
||||||
interfaceInfoType = NULL;
|
|
||||||
mutexType = NULL;
|
mutexType = NULL;
|
||||||
moduleRefType = NULL;
|
moduleRefType = NULL;
|
||||||
|
|
||||||
dmodule = 0;
|
dmodule = 0;
|
||||||
emitMain = false;
|
|
||||||
mainFunc = 0;
|
mainFunc = 0;
|
||||||
ir.state = this;
|
ir.state = this;
|
||||||
asmBlock = NULL;
|
asmBlock = NULL;
|
||||||
|
@ -93,12 +91,6 @@ llvm::Function* IRState::topfunc()
|
||||||
return functions.back()->func;
|
return functions.back()->func;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeFunction* IRState::topfunctype()
|
|
||||||
{
|
|
||||||
assert(!functions.empty() && "Function stack is empty!");
|
|
||||||
return functions.back()->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::Instruction* IRState::topallocapoint()
|
llvm::Instruction* IRState::topallocapoint()
|
||||||
{
|
{
|
||||||
assert(!functions.empty() && "AllocaPoint stack is empty!");
|
assert(!functions.empty() && "AllocaPoint stack is empty!");
|
||||||
|
|
|
@ -121,31 +121,26 @@ struct IRAsmBlock
|
||||||
// represents the module
|
// represents the module
|
||||||
struct IRState
|
struct IRState
|
||||||
{
|
{
|
||||||
IRState(llvm::Module* m);
|
IRState(const char *name, llvm::LLVMContext &context);
|
||||||
|
|
||||||
// module
|
llvm::Module module;
|
||||||
Module* dmodule;
|
llvm::LLVMContext& context() const { return module.getContext(); }
|
||||||
llvm::Module* module;
|
|
||||||
|
Module *dmodule;
|
||||||
|
|
||||||
// interface info type, used in DtoInterfaceInfoType
|
|
||||||
LLStructType* interfaceInfoType;
|
|
||||||
LLStructType* mutexType;
|
LLStructType* mutexType;
|
||||||
LLStructType* moduleRefType;
|
LLStructType* moduleRefType;
|
||||||
|
|
||||||
// helper to get the LLVMContext of the module
|
|
||||||
llvm::LLVMContext& context() const { return module->getContext(); }
|
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
typedef std::vector<IrFunction*> FunctionVector;
|
typedef std::vector<IrFunction*> FunctionVector;
|
||||||
FunctionVector functions;
|
FunctionVector functions;
|
||||||
IrFunction* func();
|
IrFunction* func();
|
||||||
|
|
||||||
llvm::Function* topfunc();
|
llvm::Function* topfunc();
|
||||||
TypeFunction* topfunctype();
|
|
||||||
llvm::Instruction* topallocapoint();
|
llvm::Instruction* topallocapoint();
|
||||||
|
|
||||||
// D main function
|
// The function containing the D main() body, if any (not the actual main()
|
||||||
bool emitMain;
|
// implicitly emitted).
|
||||||
llvm::Function* mainFunc;
|
llvm::Function* mainFunc;
|
||||||
|
|
||||||
// basic block scopes
|
// basic block scopes
|
||||||
|
@ -177,17 +172,6 @@ struct IRState
|
||||||
// debug info helper
|
// debug info helper
|
||||||
ldc::DIBuilder DBuilder;
|
ldc::DIBuilder DBuilder;
|
||||||
|
|
||||||
// static ctors/dtors/unittests
|
|
||||||
typedef std::list<FuncDeclaration*> FuncDeclList;
|
|
||||||
typedef std::list<VarDeclaration*> GatesList;
|
|
||||||
FuncDeclList ctors;
|
|
||||||
FuncDeclList dtors;
|
|
||||||
FuncDeclList sharedCtors;
|
|
||||||
FuncDeclList sharedDtors;
|
|
||||||
GatesList gates;
|
|
||||||
GatesList sharedGates;
|
|
||||||
FuncDeclList unitTests;
|
|
||||||
|
|
||||||
// for inline asm
|
// for inline asm
|
||||||
IRAsmBlock* asmBlock;
|
IRAsmBlock* asmBlock;
|
||||||
std::ostringstream nakedAsm;
|
std::ostringstream nakedAsm;
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
|
|
||||||
using llvm::IRBuilder;
|
using llvm::IRBuilder;
|
||||||
|
|
||||||
#define GET_INTRINSIC_DECL(_X) (llvm::Intrinsic::getDeclaration(gIR->module, llvm::Intrinsic:: _X ))
|
#define GET_INTRINSIC_DECL(_X) (llvm::Intrinsic::getDeclaration(&gIR->module, llvm::Intrinsic:: _X ))
|
||||||
|
|
||||||
// shortcuts for the common llvm types
|
// shortcuts for the common llvm types
|
||||||
|
|
||||||
|
|
|
@ -219,17 +219,8 @@ void DtoAssert(Module* M, Loc& loc, DValue* msg)
|
||||||
|
|
||||||
LLValue *DtoModuleFileName(Module* M, const Loc& loc)
|
LLValue *DtoModuleFileName(Module* M, const Loc& loc)
|
||||||
{
|
{
|
||||||
// we might be generating for an imported template function
|
return DtoConstString(loc.filename ? loc.filename :
|
||||||
const char* cur_file = M->srcfile->name->toChars();
|
M->srcfile->name->toChars());
|
||||||
if (loc.filename && strcmp(loc.filename, cur_file) != 0)
|
|
||||||
{
|
|
||||||
return DtoConstString(loc.filename);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IrModule* irmod = getIrModule(M);
|
|
||||||
return DtoLoad(irmod->fileName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
|
@ -975,7 +966,7 @@ void DtoResolveVariable(VarDeclaration* vd)
|
||||||
linkage = llvm::GlobalValue::ExternalWeakLinkage;
|
linkage = llvm::GlobalValue::ExternalWeakLinkage;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::GlobalVariable* gvar = getOrCreateGlobal(vd->loc, *gIR->module,
|
llvm::GlobalVariable* gvar = getOrCreateGlobal(vd->loc, gIR->module,
|
||||||
i1ToI8(DtoType(vd->type)), isLLConst, linkage, 0, llName,
|
i1ToI8(DtoType(vd->type)), isLLConst, linkage, 0, llName,
|
||||||
vd->isThreadlocal());
|
vd->isThreadlocal());
|
||||||
getIrGlobal(vd)->value = gvar;
|
getIrGlobal(vd)->value = gvar;
|
||||||
|
@ -1619,9 +1610,9 @@ void printLabelName(std::ostream& target, const char* func_mangle, const char* l
|
||||||
void AppendFunctionToLLVMGlobalCtorsDtors(llvm::Function* func, const uint32_t priority, const bool isCtor)
|
void AppendFunctionToLLVMGlobalCtorsDtors(llvm::Function* func, const uint32_t priority, const bool isCtor)
|
||||||
{
|
{
|
||||||
if (isCtor)
|
if (isCtor)
|
||||||
llvm::appendToGlobalCtors(*gIR->module, func, priority);
|
llvm::appendToGlobalCtors(gIR->module, func, priority);
|
||||||
else
|
else
|
||||||
llvm::appendToGlobalDtors(*gIR->module, func, priority);
|
llvm::appendToGlobalDtors(gIR->module, func, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -45,9 +45,9 @@ void Stream::writeValue(std::ostream& OS, const llvm::Value& V) {
|
||||||
llvm::raw_os_ostream raw(OS);
|
llvm::raw_os_ostream raw(OS);
|
||||||
if (llvm::isa<llvm::Constant>(V) && !llvm::isa<llvm::GlobalValue>(V))
|
if (llvm::isa<llvm::Constant>(V) && !llvm::isa<llvm::GlobalValue>(V))
|
||||||
#if LDC_LLVM_VER >= 305
|
#if LDC_LLVM_VER >= 305
|
||||||
V.printAsOperand(raw, true, gIR->module);
|
V.printAsOperand(raw, true, &gIR->module);
|
||||||
#else
|
#else
|
||||||
llvm::WriteAsOperand(raw, &V, true, gIR->module);
|
llvm::WriteAsOperand(raw, &V, true, &gIR->module);
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
V.print(raw);
|
V.print(raw);
|
||||||
|
|
284
gen/module.cpp
284
gen/module.cpp
|
@ -169,7 +169,7 @@ File* Module::buildFilePath(const char* forcename, const char* path, const char*
|
||||||
|
|
||||||
// always append the extension! otherwise hard to make output switches consistent
|
// always append the extension! otherwise hard to make output switches consistent
|
||||||
// if (forcename)
|
// if (forcename)
|
||||||
// return new File(argobj);
|
// return new File(argobj);
|
||||||
// else
|
// else
|
||||||
// allow for .o and .obj on windows
|
// allow for .o and .obj on windows
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
|
@ -195,9 +195,9 @@ static llvm::Function* build_module_function(const std::string &name, const std:
|
||||||
LLFunctionType* fnTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<LLType*>(), false);
|
LLFunctionType* fnTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<LLType*>(), false);
|
||||||
|
|
||||||
std::string const symbolName = gABI->mangleForLLVM(name, LINKd);
|
std::string const symbolName = gABI->mangleForLLVM(name, LINKd);
|
||||||
assert(gIR->module->getFunction(symbolName) == NULL);
|
assert(gIR->module.getFunction(symbolName) == NULL);
|
||||||
llvm::Function* fn = llvm::Function::Create(fnTy,
|
llvm::Function* fn = llvm::Function::Create(fnTy,
|
||||||
llvm::GlobalValue::InternalLinkage, symbolName, gIR->module);
|
llvm::GlobalValue::InternalLinkage, symbolName, &gIR->module);
|
||||||
fn->setCallingConv(gABI->callingConv(LINKd));
|
fn->setCallingConv(gABI->callingConv(LINKd));
|
||||||
|
|
||||||
llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "", fn);
|
llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "", fn);
|
||||||
|
@ -234,67 +234,69 @@ static llvm::Function* build_module_function(const std::string &name, const std:
|
||||||
|
|
||||||
// build module ctor
|
// build module ctor
|
||||||
|
|
||||||
llvm::Function* build_module_ctor()
|
static llvm::Function* build_module_ctor(Module *m)
|
||||||
{
|
{
|
||||||
std::string name("_D");
|
std::string name("_D");
|
||||||
name.append(mangle(gIR->dmodule));
|
name.append(mangle(m));
|
||||||
name.append("6__ctorZ");
|
name.append("6__ctorZ");
|
||||||
return build_module_function(name, gIR->ctors, gIR->gates);
|
IrModule *irm = getIrModule(m);
|
||||||
|
return build_module_function(name, irm->ctors, irm->gates);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build module dtor
|
// build module dtor
|
||||||
|
|
||||||
static llvm::Function* build_module_dtor()
|
static llvm::Function* build_module_dtor(Module *m)
|
||||||
{
|
{
|
||||||
std::string name("_D");
|
std::string name("_D");
|
||||||
name.append(mangle(gIR->dmodule));
|
name.append(mangle(m));
|
||||||
name.append("6__dtorZ");
|
name.append("6__dtorZ");
|
||||||
return build_module_function(name, gIR->dtors);
|
return build_module_function(name, getIrModule(m)->dtors);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build module unittest
|
// build module unittest
|
||||||
|
|
||||||
static llvm::Function* build_module_unittest()
|
static llvm::Function* build_module_unittest(Module *m)
|
||||||
{
|
{
|
||||||
std::string name("_D");
|
std::string name("_D");
|
||||||
name.append(mangle(gIR->dmodule));
|
name.append(mangle(m));
|
||||||
name.append("10__unittestZ");
|
name.append("10__unittestZ");
|
||||||
return build_module_function(name, gIR->unitTests);
|
return build_module_function(name, getIrModule(m)->unitTests);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build module shared ctor
|
// build module shared ctor
|
||||||
|
|
||||||
llvm::Function* build_module_shared_ctor()
|
static llvm::Function* build_module_shared_ctor(Module *m)
|
||||||
{
|
{
|
||||||
std::string name("_D");
|
std::string name("_D");
|
||||||
name.append(mangle(gIR->dmodule));
|
name.append(mangle(m));
|
||||||
name.append("13__shared_ctorZ");
|
name.append("13__shared_ctorZ");
|
||||||
return build_module_function(name, gIR->sharedCtors, gIR->sharedGates);
|
IrModule *irm = getIrModule(m);
|
||||||
|
return build_module_function(name, irm->sharedCtors, irm->sharedGates);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build module shared dtor
|
// build module shared dtor
|
||||||
|
|
||||||
static llvm::Function* build_module_shared_dtor()
|
static llvm::Function* build_module_shared_dtor(Module *m)
|
||||||
{
|
{
|
||||||
std::string name("_D");
|
std::string name("_D");
|
||||||
name.append(mangle(gIR->dmodule));
|
name.append(mangle(m));
|
||||||
name.append("13__shared_dtorZ");
|
name.append("13__shared_dtorZ");
|
||||||
return build_module_function(name, gIR->sharedDtors);
|
return build_module_function(name, getIrModule(m)->sharedDtors);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build ModuleReference and register function, to register the module info in the global linked list
|
// build ModuleReference and register function, to register the module info in the global linked list
|
||||||
static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
|
static LLFunction* build_module_reference_and_ctor(const char *moduleMangle, LLConstant* moduleinfo)
|
||||||
{
|
{
|
||||||
// build ctor type
|
// build ctor type
|
||||||
LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<LLType*>(), false);
|
LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<LLType*>(), false);
|
||||||
|
|
||||||
// build ctor name
|
// build ctor name
|
||||||
std::string fname = "_D";
|
std::string fname = "_D";
|
||||||
fname += mangle(gIR->dmodule);
|
fname += moduleMangle;
|
||||||
fname += "16__moduleinfoCtorZ";
|
fname += "16__moduleinfoCtorZ";
|
||||||
|
|
||||||
// build a function that registers the moduleinfo in the global moduleinfo linked list
|
// build a function that registers the moduleinfo in the global moduleinfo linked list
|
||||||
LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, gIR->module);
|
LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, &gIR->module);
|
||||||
|
|
||||||
// provide the default initializer
|
// provide the default initializer
|
||||||
LLStructType* modulerefTy = DtoModuleReferenceType();
|
LLStructType* modulerefTy = DtoModuleReferenceType();
|
||||||
|
@ -306,17 +308,17 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
|
||||||
|
|
||||||
// create the ModuleReference node for this module
|
// create the ModuleReference node for this module
|
||||||
std::string thismrefname = "_D";
|
std::string thismrefname = "_D";
|
||||||
thismrefname += mangle(gIR->dmodule);
|
thismrefname += moduleMangle;
|
||||||
thismrefname += "11__moduleRefZ";
|
thismrefname += "11__moduleRefZ";
|
||||||
Loc loc;
|
Loc loc;
|
||||||
LLGlobalVariable* thismref = getOrCreateGlobal(loc, *gIR->module,
|
LLGlobalVariable* thismref = getOrCreateGlobal(loc, gIR->module,
|
||||||
modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit,
|
modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit,
|
||||||
thismrefname);
|
thismrefname);
|
||||||
// make sure _Dmodule_ref is declared
|
// make sure _Dmodule_ref is declared
|
||||||
LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref");
|
LLConstant* mref = gIR->module.getNamedGlobal("_Dmodule_ref");
|
||||||
LLType *modulerefPtrTy = getPtrToType(modulerefTy);
|
LLType *modulerefPtrTy = getPtrToType(modulerefTy);
|
||||||
if (!mref)
|
if (!mref)
|
||||||
mref = new LLGlobalVariable(*gIR->module, modulerefPtrTy, false, LLGlobalValue::ExternalLinkage, NULL, "_Dmodule_ref");
|
mref = new LLGlobalVariable(gIR->module, modulerefPtrTy, false, LLGlobalValue::ExternalLinkage, NULL, "_Dmodule_ref");
|
||||||
mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy));
|
mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy));
|
||||||
|
|
||||||
// make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list
|
// make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list
|
||||||
|
@ -419,7 +421,7 @@ static void build_dso_ctor_dtor_body(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void build_dso_registry_calls(llvm::Constant* thisModuleInfo)
|
static void build_dso_registry_calls(std::string moduleMangle, llvm::Constant* thisModuleInfo)
|
||||||
{
|
{
|
||||||
// Build the ModuleInfo reference and bracketing symbols.
|
// Build the ModuleInfo reference and bracketing symbols.
|
||||||
llvm::Type* const moduleInfoPtrTy =
|
llvm::Type* const moduleInfoPtrTy =
|
||||||
|
@ -429,7 +431,7 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo)
|
||||||
// bracketing sections right before/after the ModuleInfo reference
|
// bracketing sections right before/after the ModuleInfo reference
|
||||||
// so that they end up in the correct order in the object file.
|
// so that they end up in the correct order in the object file.
|
||||||
llvm::GlobalVariable* minfoBeg = new llvm::GlobalVariable(
|
llvm::GlobalVariable* minfoBeg = new llvm::GlobalVariable(
|
||||||
*gIR->module,
|
gIR->module,
|
||||||
moduleInfoPtrTy,
|
moduleInfoPtrTy,
|
||||||
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
|
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
|
||||||
llvm::GlobalValue::LinkOnceODRLinkage,
|
llvm::GlobalValue::LinkOnceODRLinkage,
|
||||||
|
@ -440,10 +442,10 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo)
|
||||||
minfoBeg->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
minfoBeg->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
||||||
|
|
||||||
std::string thismrefname = "_D";
|
std::string thismrefname = "_D";
|
||||||
thismrefname += mangle(gIR->dmodule);
|
thismrefname += moduleMangle;
|
||||||
thismrefname += "11__moduleRefZ";
|
thismrefname += "11__moduleRefZ";
|
||||||
llvm::GlobalVariable* thismref = new llvm::GlobalVariable(
|
llvm::GlobalVariable* thismref = new llvm::GlobalVariable(
|
||||||
*gIR->module,
|
gIR->module,
|
||||||
moduleInfoPtrTy,
|
moduleInfoPtrTy,
|
||||||
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
|
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
|
||||||
llvm::GlobalValue::LinkOnceODRLinkage,
|
llvm::GlobalValue::LinkOnceODRLinkage,
|
||||||
|
@ -454,7 +456,7 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo)
|
||||||
gIR->usedArray.push_back(thismref);
|
gIR->usedArray.push_back(thismref);
|
||||||
|
|
||||||
llvm::GlobalVariable* minfoEnd = new llvm::GlobalVariable(
|
llvm::GlobalVariable* minfoEnd = new llvm::GlobalVariable(
|
||||||
*gIR->module,
|
gIR->module,
|
||||||
moduleInfoPtrTy,
|
moduleInfoPtrTy,
|
||||||
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
|
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
|
||||||
llvm::GlobalValue::LinkOnceODRLinkage,
|
llvm::GlobalValue::LinkOnceODRLinkage,
|
||||||
|
@ -468,7 +470,7 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo)
|
||||||
|
|
||||||
// This is the DSO slot for use by the druntime implementation.
|
// This is the DSO slot for use by the druntime implementation.
|
||||||
llvm::GlobalVariable* dsoSlot = new llvm::GlobalVariable(
|
llvm::GlobalVariable* dsoSlot = new llvm::GlobalVariable(
|
||||||
*gIR->module,
|
gIR->module,
|
||||||
getVoidPtrType(),
|
getVoidPtrType(),
|
||||||
false,
|
false,
|
||||||
llvm::GlobalValue::LinkOnceODRLinkage,
|
llvm::GlobalValue::LinkOnceODRLinkage,
|
||||||
|
@ -507,7 +509,7 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo)
|
||||||
// directly using e.g. "g++ dcode.o cppcode.o", though.
|
// directly using e.g. "g++ dcode.o cppcode.o", though.
|
||||||
|
|
||||||
llvm::GlobalVariable* dsoInitialized = new llvm::GlobalVariable(
|
llvm::GlobalVariable* dsoInitialized = new llvm::GlobalVariable(
|
||||||
*gIR->module,
|
gIR->module,
|
||||||
llvm::Type::getInt8Ty(gIR->context()),
|
llvm::Type::getInt8Ty(gIR->context()),
|
||||||
false,
|
false,
|
||||||
llvm::GlobalValue::LinkOnceODRLinkage,
|
llvm::GlobalValue::LinkOnceODRLinkage,
|
||||||
|
@ -524,26 +526,26 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo)
|
||||||
llvm::Value* minfoRefPtr = DtoBitCast(thismref, getVoidPtrType());
|
llvm::Value* minfoRefPtr = DtoBitCast(thismref, getVoidPtrType());
|
||||||
|
|
||||||
std::string ctorName = "ldc.dso_ctor.";
|
std::string ctorName = "ldc.dso_ctor.";
|
||||||
ctorName += mangle(gIR->dmodule);
|
ctorName += moduleMangle;
|
||||||
llvm::Function* dsoCtor = llvm::Function::Create(
|
llvm::Function* dsoCtor = llvm::Function::Create(
|
||||||
llvm::FunctionType::get(llvm::Type::getVoidTy(gIR->context()), false),
|
llvm::FunctionType::get(llvm::Type::getVoidTy(gIR->context()), false),
|
||||||
llvm::GlobalValue::LinkOnceODRLinkage,
|
llvm::GlobalValue::LinkOnceODRLinkage,
|
||||||
ctorName,
|
ctorName,
|
||||||
gIR->module
|
&gIR->module
|
||||||
);
|
);
|
||||||
dsoCtor->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
dsoCtor->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
||||||
build_dso_ctor_dtor_body(dsoCtor, dsoInitialized, dsoSlot, minfoBeg, minfoEnd, minfoRefPtr, false);
|
build_dso_ctor_dtor_body(dsoCtor, dsoInitialized, dsoSlot, minfoBeg, minfoEnd, minfoRefPtr, false);
|
||||||
llvm::appendToGlobalCtors(*gIR->module, dsoCtor, 65535);
|
llvm::appendToGlobalCtors(gIR->module, dsoCtor, 65535);
|
||||||
|
|
||||||
llvm::Function* dsoDtor = llvm::Function::Create(
|
llvm::Function* dsoDtor = llvm::Function::Create(
|
||||||
llvm::FunctionType::get(llvm::Type::getVoidTy(gIR->context()), false),
|
llvm::FunctionType::get(llvm::Type::getVoidTy(gIR->context()), false),
|
||||||
llvm::GlobalValue::LinkOnceODRLinkage,
|
llvm::GlobalValue::LinkOnceODRLinkage,
|
||||||
"ldc.dso_dtor",
|
"ldc.dso_dtor",
|
||||||
gIR->module
|
&gIR->module
|
||||||
);
|
);
|
||||||
dsoDtor->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
dsoDtor->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
||||||
build_dso_ctor_dtor_body(dsoDtor, dsoInitialized, dsoSlot, minfoBeg, minfoEnd, minfoRefPtr, true);
|
build_dso_ctor_dtor_body(dsoDtor, dsoInitialized, dsoSlot, minfoBeg, minfoEnd, minfoRefPtr, true);
|
||||||
llvm::appendToGlobalDtors(*gIR->module, dsoDtor, 65535);
|
llvm::appendToGlobalDtors(gIR->module, dsoDtor, 65535);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void build_llvm_used_array(IRState* p)
|
static void build_llvm_used_array(IRState* p)
|
||||||
|
@ -562,7 +564,7 @@ static void build_llvm_used_array(IRState* p)
|
||||||
llvm::ArrayType *arrayType = llvm::ArrayType::get(
|
llvm::ArrayType *arrayType = llvm::ArrayType::get(
|
||||||
getVoidPtrType(), usedVoidPtrs.size());
|
getVoidPtrType(), usedVoidPtrs.size());
|
||||||
llvm::GlobalVariable* llvmUsed = new llvm::GlobalVariable(
|
llvm::GlobalVariable* llvmUsed = new llvm::GlobalVariable(
|
||||||
*p->module,
|
p->module,
|
||||||
arrayType,
|
arrayType,
|
||||||
false,
|
false,
|
||||||
llvm::GlobalValue::AppendingLinkage,
|
llvm::GlobalValue::AppendingLinkage,
|
||||||
|
@ -595,7 +597,7 @@ static void addCoverageAnalysis(Module* m)
|
||||||
|
|
||||||
llvm::ArrayType* type = llvm::ArrayType::get(DtoSize_t(), array_size);
|
llvm::ArrayType* type = llvm::ArrayType::get(DtoSize_t(), array_size);
|
||||||
llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type);
|
llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type);
|
||||||
m->d_cover_valid = new llvm::GlobalVariable(*gIR->module, type, true, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_valid");
|
m->d_cover_valid = new llvm::GlobalVariable(gIR->module, type, true, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_valid");
|
||||||
LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) };
|
LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) };
|
||||||
d_cover_valid_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()),
|
d_cover_valid_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()),
|
||||||
llvm::ConstantExpr::getGetElementPtr(
|
llvm::ConstantExpr::getGetElementPtr(
|
||||||
|
@ -616,7 +618,7 @@ static void addCoverageAnalysis(Module* m)
|
||||||
|
|
||||||
LLArrayType* type = LLArrayType::get(LLType::getInt32Ty(gIR->context()), m->numlines);
|
LLArrayType* type = LLArrayType::get(LLType::getInt32Ty(gIR->context()), m->numlines);
|
||||||
llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type);
|
llvm::ConstantAggregateZero* zeroinitializer = llvm::ConstantAggregateZero::get(type);
|
||||||
m->d_cover_data = new llvm::GlobalVariable(*gIR->module, type, false, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_data");
|
m->d_cover_data = new llvm::GlobalVariable(gIR->module, type, false, LLGlobalValue::InternalLinkage, zeroinitializer, "_d_cover_data");
|
||||||
LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) };
|
LLConstant* idxs[] = { DtoConstUint(0), DtoConstUint(0) };
|
||||||
d_cover_data_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()),
|
d_cover_data_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()),
|
||||||
llvm::ConstantExpr::getGetElementPtr(
|
llvm::ConstantExpr::getGetElementPtr(
|
||||||
|
@ -630,13 +632,13 @@ static void addCoverageAnalysis(Module* m)
|
||||||
// Build ctor name
|
// Build ctor name
|
||||||
LLFunction* ctor = NULL;
|
LLFunction* ctor = NULL;
|
||||||
std::string ctorname = "_D";
|
std::string ctorname = "_D";
|
||||||
ctorname += mangle(gIR->dmodule);
|
ctorname += mangle(m);
|
||||||
ctorname += "12_coverageanalysisCtor1FZv";
|
ctorname += "12_coverageanalysisCtor1FZv";
|
||||||
{
|
{
|
||||||
IF_LOG Logger::println("Build Coverage Analysis constructor: %s", ctorname.c_str());
|
IF_LOG Logger::println("Build Coverage Analysis constructor: %s", ctorname.c_str());
|
||||||
|
|
||||||
LLFunctionType* ctorTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<LLType*>(), false);
|
LLFunctionType* ctorTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<LLType*>(), false);
|
||||||
ctor = LLFunction::Create(ctorTy, LLGlobalValue::InternalLinkage, ctorname, gIR->module);
|
ctor = LLFunction::Create(ctorTy, LLGlobalValue::InternalLinkage, ctorname, &gIR->module);
|
||||||
ctor->setCallingConv(gABI->callingConv(LINKd));
|
ctor->setCallingConv(gABI->callingConv(LINKd));
|
||||||
// Set function attributes. See functions.cpp:DtoDefineFunction()
|
// Set function attributes. See functions.cpp:DtoDefineFunction()
|
||||||
if (global.params.targetTriple.getArch() == llvm::Triple::x86_64)
|
if (global.params.targetTriple.getArch() == llvm::Triple::x86_64)
|
||||||
|
@ -650,7 +652,7 @@ static void addCoverageAnalysis(Module* m)
|
||||||
// Set up call to _d_cover_register2
|
// Set up call to _d_cover_register2
|
||||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(Loc(), gIR->module, "_d_cover_register2");
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(Loc(), gIR->module, "_d_cover_register2");
|
||||||
LLValue* args[] = {
|
LLValue* args[] = {
|
||||||
getIrModule(m)->fileName->getInitializer(),
|
DtoConstString(m->srcfile->name->toChars()),
|
||||||
d_cover_valid_slice,
|
d_cover_valid_slice,
|
||||||
d_cover_data_slice,
|
d_cover_data_slice,
|
||||||
DtoConstUbyte(global.params.covPercent)
|
DtoConstUbyte(global.params.covPercent)
|
||||||
|
@ -672,7 +674,7 @@ static void addCoverageAnalysis(Module* m)
|
||||||
fd->linkage = LINKd;
|
fd->linkage = LINKd;
|
||||||
IrFunction* irfunc = getIrFunc(fd, true);
|
IrFunction* irfunc = getIrFunc(fd, true);
|
||||||
irfunc->func = ctor;
|
irfunc->func = ctor;
|
||||||
gIR->sharedCtors.push_back(fd);
|
getIrModule(m)->sharedCtors.push_back(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
IF_LOG Logger::undent();
|
IF_LOG Logger::undent();
|
||||||
|
@ -695,19 +697,31 @@ static void addCoverageAnalysisInitializer(Module* m) {
|
||||||
|
|
||||||
static void genModuleInfo(Module *m);
|
static void genModuleInfo(Module *m);
|
||||||
|
|
||||||
static void codegenModule(Module* m)
|
void codegenModule(IRState *irs, Module* m)
|
||||||
{
|
{
|
||||||
// debug info
|
assert(!irs->dmodule && "irs->module not null, codegen already in progress?!");
|
||||||
gIR->DBuilder.EmitCompileUnit(m);
|
irs->dmodule = m;
|
||||||
|
assert(!gIR && "gIR not null, codegen already in progress?!");
|
||||||
|
gIR = irs;
|
||||||
|
|
||||||
|
LLVM_D_InitRuntime();
|
||||||
|
|
||||||
|
// Skip pseudo-modules for coverage analysis
|
||||||
|
std::string name = m->toChars();
|
||||||
|
if (global.params.cov && name != "__entrypoint" && name != "__main")
|
||||||
|
{
|
||||||
|
addCoverageAnalysis(m);
|
||||||
|
}
|
||||||
|
|
||||||
// process module members
|
// process module members
|
||||||
for (unsigned k=0; k < m->members->dim; k++) {
|
for (unsigned k=0; k < m->members->dim; k++)
|
||||||
|
{
|
||||||
Dsymbol* dsym = (*m->members)[k];
|
Dsymbol* dsym = (*m->members)[k];
|
||||||
assert(dsym);
|
assert(dsym);
|
||||||
Declaration_codegen(dsym);
|
Declaration_codegen(dsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global.errors) return;
|
if (global.errors) fatal();
|
||||||
|
|
||||||
// Skip emission of all the additional module metadata if requested by the user.
|
// Skip emission of all the additional module metadata if requested by the user.
|
||||||
if (!m->noModuleInfo)
|
if (!m->noModuleInfo)
|
||||||
|
@ -715,145 +729,16 @@ static void codegenModule(Module* m)
|
||||||
// generate ModuleInfo
|
// generate ModuleInfo
|
||||||
genModuleInfo(m);
|
genModuleInfo(m);
|
||||||
|
|
||||||
build_llvm_used_array(gIR);
|
build_llvm_used_array(irs);
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 303
|
|
||||||
// Add the linker options metadata flag.
|
|
||||||
gIR->module->addModuleFlag(llvm::Module::AppendUnique, "Linker Options",
|
|
||||||
llvm::MDNode::get(gIR->context(), gIR->LinkerMetadataArgs));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 304
|
|
||||||
// Emit ldc version as llvm.ident metadata.
|
|
||||||
llvm::NamedMDNode *IdentMetadata = gIR->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(gIR->context(), Version)
|
|
||||||
};
|
|
||||||
IdentMetadata->addOperand(llvm::MDNode::get(gIR->context(), IdentNode));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// finalize debug info
|
if (m->d_cover_valid)
|
||||||
gIR->DBuilder.EmitModuleEnd();
|
|
||||||
|
|
||||||
// verify the llvm
|
|
||||||
verifyModule(*gIR->module);
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context)
|
|
||||||
{
|
|
||||||
bool logenabled = Logger::enabled();
|
|
||||||
if (llvmForceLogging && !logenabled)
|
|
||||||
{
|
{
|
||||||
Logger::enable();
|
addCoverageAnalysisInitializer(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
IF_LOG Logger::println("Generating module: %s", (md ? md->toChars() : toChars()));
|
gIR = 0;
|
||||||
LOG_SCOPE;
|
irs->dmodule = 0;
|
||||||
|
|
||||||
if (global.params.verbose_cg)
|
|
||||||
printf("codegen: %s (%s)\n", toPrettyChars(), srcfile->toChars());
|
|
||||||
|
|
||||||
if (global.errors)
|
|
||||||
{
|
|
||||||
Logger::println("Aborting because of errors");
|
|
||||||
fatal();
|
|
||||||
}
|
|
||||||
|
|
||||||
// name the module
|
|
||||||
#if 1
|
|
||||||
// Temporary workaround for http://llvm.org/bugs/show_bug.cgi?id=11479 –
|
|
||||||
// just use the source file name, as it is unlikely to collide with a
|
|
||||||
// symbol name used somewhere in the module.
|
|
||||||
llvm::StringRef mname(srcfile->toChars());
|
|
||||||
#else
|
|
||||||
llvm::StringRef mname(toChars());
|
|
||||||
if (md != 0)
|
|
||||||
mname = md->toChars();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// create a new ir state
|
|
||||||
// TODO look at making the instance static and moving most functionality into IrModule where it belongs
|
|
||||||
IRState ir(new llvm::Module(mname, context));
|
|
||||||
gIR = &ir;
|
|
||||||
ir.dmodule = this;
|
|
||||||
|
|
||||||
// reset all IR data stored in Dsymbols
|
|
||||||
IrDsymbol::resetAll();
|
|
||||||
|
|
||||||
// set target triple
|
|
||||||
ir.module->setTargetTriple(global.params.targetTriple.str());
|
|
||||||
|
|
||||||
// set final data layout
|
|
||||||
ir.module->setDataLayout(gDataLayout->getStringRepresentation());
|
|
||||||
#if LDC_LLVM_VER >= 307
|
|
||||||
IF_LOG Logger::cout() << "Final data layout: " << ir.module->getDataLayout().getStringRepresentation() << '\n';
|
|
||||||
#else
|
|
||||||
IF_LOG Logger::cout() << "Final data layout: " << ir.module->getDataLayout() << '\n';
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// handle invalid 'objectø module
|
|
||||||
if (!ClassDeclaration::object) {
|
|
||||||
error("is missing 'class Object'");
|
|
||||||
fatal();
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVM_D_InitRuntime();
|
|
||||||
|
|
||||||
// Note, skip pseudo-modules for coverage analysis
|
|
||||||
if ( global.params.cov && !mname.equals("__entrypoint.d") && !mname.equals("__main.d") )
|
|
||||||
{
|
|
||||||
addCoverageAnalysis(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
codegenModule(this);
|
|
||||||
|
|
||||||
if ( gIR->dmodule->d_cover_valid )
|
|
||||||
{
|
|
||||||
addCoverageAnalysisInitializer(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
gIR = NULL;
|
|
||||||
|
|
||||||
if (llvmForceLogging && !logenabled)
|
|
||||||
{
|
|
||||||
Logger::disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ir.module;
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::GlobalVariable* Module::moduleInfoSymbol()
|
|
||||||
{
|
|
||||||
// create name
|
|
||||||
std::string MIname("_D");
|
|
||||||
MIname.append(mangle(this));
|
|
||||||
MIname.append("12__ModuleInfoZ");
|
|
||||||
|
|
||||||
if (gIR->dmodule != this) {
|
|
||||||
LLType* moduleinfoTy = DtoType(moduleinfo->type);
|
|
||||||
LLGlobalVariable *var = gIR->module->getGlobalVariable(MIname);
|
|
||||||
if (!var)
|
|
||||||
var = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname);
|
|
||||||
return var;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!moduleInfoVar) {
|
|
||||||
// declare global
|
|
||||||
// flags will be modified at runtime so can't make it constant
|
|
||||||
LLType *moduleInfoType = llvm::StructType::create(llvm::getGlobalContext());
|
|
||||||
moduleInfoVar = getOrCreateGlobal(loc, *gIR->module, moduleInfoType,
|
|
||||||
false, llvm::GlobalValue::ExternalLinkage, NULL, MIname);
|
|
||||||
}
|
|
||||||
|
|
||||||
return moduleInfoVar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put out instance of ModuleInfo for this Module
|
// Put out instance of ModuleInfo for this Module
|
||||||
|
@ -880,7 +765,8 @@ static void genModuleInfo(Module *m)
|
||||||
RTTIBuilder b(Module::moduleinfo);
|
RTTIBuilder b(Module::moduleinfo);
|
||||||
|
|
||||||
// some types
|
// some types
|
||||||
LLType* moduleinfoTy = Module::moduleinfo->type->ctype->getLLType();
|
llvm::Type* const moduleInfoPtrTy =
|
||||||
|
getPtrToType(DtoType(Module::moduleinfo->type));
|
||||||
LLType* classinfoTy = Type::typeinfoclass->type->ctype->getLLType();
|
LLType* classinfoTy = Type::typeinfoclass->type->ctype->getLLType();
|
||||||
|
|
||||||
// importedModules[]
|
// importedModules[]
|
||||||
|
@ -890,21 +776,15 @@ static void genModuleInfo(Module *m)
|
||||||
for (size_t i = 0; i < m->aimports.dim; i++)
|
for (size_t i = 0; i < m->aimports.dim; i++)
|
||||||
{
|
{
|
||||||
Module *mod = static_cast<Module *>(m->aimports.data[i]);
|
Module *mod = static_cast<Module *>(m->aimports.data[i]);
|
||||||
if (!mod->needModuleInfo() || mod == m)
|
if (!mod->needModuleInfo() || mod == m) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
// declare the imported module info
|
importInits.push_back(
|
||||||
std::string m_name("_D");
|
DtoBitCast(getIrModule(mod)->moduleInfoSymbol(), moduleInfoPtrTy));
|
||||||
m_name.append(mangle(mod));
|
|
||||||
m_name.append("12__ModuleInfoZ");
|
|
||||||
llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name);
|
|
||||||
if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name);
|
|
||||||
importInits.push_back(m_gvar);
|
|
||||||
}
|
}
|
||||||
// has import array?
|
// has import array?
|
||||||
if (!importInits.empty())
|
if (!importInits.empty())
|
||||||
{
|
{
|
||||||
importedModulesTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size());
|
importedModulesTy = llvm::ArrayType::get(moduleInfoPtrTy, importInits.size());
|
||||||
importedModules = LLConstantArray::get(importedModulesTy, importInits);
|
importedModules = LLConstantArray::get(importedModulesTy, importInits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -958,11 +838,11 @@ static void genModuleInfo(Module *m)
|
||||||
#define MIlocalClasses 0x800
|
#define MIlocalClasses 0x800
|
||||||
#define MInew 0x80000000 // it's the "new" layout
|
#define MInew 0x80000000 // it's the "new" layout
|
||||||
|
|
||||||
llvm::Function* fsharedctor = build_module_shared_ctor();
|
llvm::Function* fsharedctor = build_module_shared_ctor(m);
|
||||||
llvm::Function* fshareddtor = build_module_shared_dtor();
|
llvm::Function* fshareddtor = build_module_shared_dtor(m);
|
||||||
llvm::Function* funittest = build_module_unittest();
|
llvm::Function* funittest = build_module_unittest(m);
|
||||||
llvm::Function* fctor = build_module_ctor();
|
llvm::Function* fctor = build_module_ctor(m);
|
||||||
llvm::Function* fdtor = build_module_dtor();
|
llvm::Function* fdtor = build_module_dtor(m);
|
||||||
|
|
||||||
unsigned flags = MInew;
|
unsigned flags = MInew;
|
||||||
if (fctor)
|
if (fctor)
|
||||||
|
@ -1025,15 +905,15 @@ static void genModuleInfo(Module *m)
|
||||||
b.push(toConstantArray(it, at, name, len, false));
|
b.push(toConstantArray(it, at, name, len, false));
|
||||||
|
|
||||||
// create and set initializer
|
// create and set initializer
|
||||||
LLGlobalVariable *moduleInfoSym = m->moduleInfoSymbol();
|
LLGlobalVariable *moduleInfoSym = getIrModule(m)->moduleInfoSymbol();
|
||||||
b.finalize(moduleInfoSym->getType()->getPointerElementType(), moduleInfoSym);
|
b.finalize(moduleInfoSym->getType()->getPointerElementType(), moduleInfoSym);
|
||||||
moduleInfoSym->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
moduleInfoSym->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
||||||
|
|
||||||
if (global.params.isLinux) {
|
if (global.params.isLinux) {
|
||||||
build_dso_registry_calls(moduleInfoSym);
|
build_dso_registry_calls(mangle(m), moduleInfoSym);
|
||||||
} else {
|
} else {
|
||||||
// build the modulereference and ctor for registering it
|
// build the modulereference and ctor for registering it
|
||||||
LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSym);
|
LLFunction* mictor = build_module_reference_and_ctor(mangle(m), moduleInfoSym);
|
||||||
AppendFunctionToLLVMGlobalCtorsDtors(mictor, 65535, true);
|
AppendFunctionToLLVMGlobalCtorsDtors(mictor, 65535, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,7 +243,7 @@ void DtoDefineNakedFunction(FuncDeclaration* fd)
|
||||||
asmstr << "\t.size\t" << mangle << ", .-" << mangle << std::endl << std::endl;
|
asmstr << "\t.size\t" << mangle << ", .-" << mangle << std::endl << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
gIR->module->appendModuleInlineAsm(asmstr.str());
|
gIR->module.appendModuleInlineAsm(asmstr.str());
|
||||||
asmstr.str("");
|
asmstr.str("");
|
||||||
|
|
||||||
gIR->functions.pop_back();
|
gIR->functions.pop_back();
|
||||||
|
|
|
@ -87,7 +87,7 @@ void RTTIBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* ma
|
||||||
initname.append(".rtti.voidarr.data");
|
initname.append(".rtti.voidarr.data");
|
||||||
|
|
||||||
LLGlobalVariable* G = new LLGlobalVariable(
|
LLGlobalVariable* G = new LLGlobalVariable(
|
||||||
*gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname);
|
gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname);
|
||||||
G->setAlignment(valtype->alignsize());
|
G->setAlignment(valtype->alignsize());
|
||||||
|
|
||||||
push_void_array(getTypePaddedSize(CI->getType()), G);
|
push_void_array(getTypePaddedSize(CI->getType()), G);
|
||||||
|
@ -106,7 +106,7 @@ void RTTIBuilder::push_array(llvm::Constant * CI, uint64_t dim, Type* valtype, D
|
||||||
initname.append(".data");
|
initname.append(".data");
|
||||||
|
|
||||||
LLGlobalVariable* G = new LLGlobalVariable(
|
LLGlobalVariable* G = new LLGlobalVariable(
|
||||||
*gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname);
|
gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname);
|
||||||
G->setAlignment(valtype->alignsize());
|
G->setAlignment(valtype->alignsize());
|
||||||
|
|
||||||
push_array(dim, DtoBitCast(G, DtoType(valtype->pointerTo())));
|
push_array(dim, DtoBitCast(G, DtoType(valtype->pointerTo())));
|
||||||
|
|
|
@ -129,7 +129,7 @@ void LLVM_D_FreeRuntime()
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target, const char* name)
|
llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module& target, const char* name)
|
||||||
{
|
{
|
||||||
checkForImplicitGCCall(loc, name);
|
checkForImplicitGCCall(loc, name);
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target,
|
||||||
LLVM_D_InitRuntime();
|
LLVM_D_InitRuntime();
|
||||||
}
|
}
|
||||||
|
|
||||||
LLFunction* fn = target->getFunction(name);
|
LLFunction* fn = target.getFunction(name);
|
||||||
if (fn)
|
if (fn)
|
||||||
return fn;
|
return fn;
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target,
|
||||||
assert(fn && "Runtime function not found.");
|
assert(fn && "Runtime function not found.");
|
||||||
|
|
||||||
LLFunctionType* fnty = fn->getFunctionType();
|
LLFunctionType* fnty = fn->getFunctionType();
|
||||||
LLFunction* resfn = llvm::cast<llvm::Function>(target->getOrInsertFunction(name, fnty));
|
LLFunction* resfn = llvm::cast<llvm::Function>(target.getOrInsertFunction(name, fnty));
|
||||||
resfn->setAttributes(fn->getAttributes());
|
resfn->setAttributes(fn->getAttributes());
|
||||||
resfn->setCallingConv(fn->getCallingConv());
|
resfn->setCallingConv(fn->getCallingConv());
|
||||||
return resfn;
|
return resfn;
|
||||||
|
@ -153,9 +153,9 @@ llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target,
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(Loc& loc, llvm::Module* target, const char* name)
|
llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(Loc& loc, llvm::Module& target, const char* name)
|
||||||
{
|
{
|
||||||
LLGlobalVariable* gv = target->getNamedGlobal(name);
|
LLGlobalVariable* gv = target.getNamedGlobal(name);
|
||||||
if (gv) {
|
if (gv) {
|
||||||
return gv;
|
return gv;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(Loc& loc, llvm::Module* target, co
|
||||||
}
|
}
|
||||||
|
|
||||||
LLPointerType* t = g->getType();
|
LLPointerType* t = g->getType();
|
||||||
return getOrCreateGlobal(loc, *target, t->getElementType(), g->isConstant(),
|
return getOrCreateGlobal(loc, target, t->getElementType(), g->isConstant(),
|
||||||
g->getLinkage(), NULL, g->getName());
|
g->getLinkage(), NULL, g->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,9 @@ struct Loc;
|
||||||
bool LLVM_D_InitRuntime();
|
bool LLVM_D_InitRuntime();
|
||||||
void LLVM_D_FreeRuntime();
|
void LLVM_D_FreeRuntime();
|
||||||
|
|
||||||
llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target, const char* name);
|
llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module& target, const char* name);
|
||||||
|
|
||||||
llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(const Loc &loc, llvm::Module* target, const char* name);
|
llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(const Loc &loc, llvm::Module& target, const char* name);
|
||||||
|
|
||||||
#define _adEq "_adEq2"
|
#define _adEq "_adEq2"
|
||||||
#define _adCmp "_adCmp2"
|
#define _adCmp "_adCmp2"
|
||||||
|
|
|
@ -1209,7 +1209,7 @@ public:
|
||||||
LLType* elemTy = DtoType(stmt->condition->type);
|
LLType* elemTy = DtoType(stmt->condition->type);
|
||||||
LLArrayType* arrTy = llvm::ArrayType::get(elemTy, inits.size());
|
LLArrayType* arrTy = llvm::ArrayType::get(elemTy, inits.size());
|
||||||
LLConstant* arrInit = LLConstantArray::get(arrTy, inits);
|
LLConstant* arrInit = LLConstantArray::get(arrTy, inits);
|
||||||
LLGlobalVariable* arr = new llvm::GlobalVariable(*gIR->module, arrTy, true, llvm::GlobalValue::InternalLinkage, arrInit, ".string_switch_table_data");
|
LLGlobalVariable* arr = new llvm::GlobalVariable(gIR->module, arrTy, true, llvm::GlobalValue::InternalLinkage, arrInit, ".string_switch_table_data");
|
||||||
|
|
||||||
LLType* elemPtrTy = getPtrToType(elemTy);
|
LLType* elemPtrTy = getPtrToType(elemTy);
|
||||||
LLConstant* arrPtr = llvm::ConstantExpr::getBitCast(arr, elemPtrTy);
|
LLConstant* arrPtr = llvm::ConstantExpr::getBitCast(arr, elemPtrTy);
|
||||||
|
@ -1780,7 +1780,7 @@ public:
|
||||||
|
|
||||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(stmt->loc, gIR->module, "_d_switch_error");
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(stmt->loc, gIR->module, "_d_switch_error");
|
||||||
|
|
||||||
LLValue *moduleInfoSymbol = gIR->func()->decl->getModule()->moduleInfoSymbol();
|
LLValue *moduleInfoSymbol = getIrModule(gIR->func()->decl->getModule())->moduleInfoSymbol();
|
||||||
LLType *moduleInfoType = DtoType(Module::moduleinfo->type);
|
LLType *moduleInfoType = DtoType(Module::moduleinfo->type);
|
||||||
|
|
||||||
LLValue* args[] = {
|
LLValue* args[] = {
|
||||||
|
|
|
@ -218,7 +218,7 @@ static LLValue* getTypeinfoArrayArgumentForDVarArg(Expressions* arguments, int b
|
||||||
LLArrayType* typeinfoarraytype = LLArrayType::get(typeinfotype, numVariadicArgs);
|
LLArrayType* typeinfoarraytype = LLArrayType::get(typeinfotype, numVariadicArgs);
|
||||||
|
|
||||||
llvm::GlobalVariable* typeinfomem =
|
llvm::GlobalVariable* typeinfomem =
|
||||||
new llvm::GlobalVariable(*gIR->module, typeinfoarraytype, true, llvm::GlobalValue::InternalLinkage, NULL, "._arguments.storage");
|
new llvm::GlobalVariable(gIR->module, typeinfoarraytype, true, llvm::GlobalValue::InternalLinkage, NULL, "._arguments.storage");
|
||||||
IF_LOG Logger::cout() << "_arguments storage: " << *typeinfomem << '\n';
|
IF_LOG Logger::cout() << "_arguments storage: " << *typeinfomem << '\n';
|
||||||
|
|
||||||
std::vector<LLConstant*> vtypeinfos;
|
std::vector<LLConstant*> vtypeinfos;
|
||||||
|
@ -239,7 +239,7 @@ static LLValue* getTypeinfoArrayArgumentForDVarArg(Expressions* arguments, int b
|
||||||
};
|
};
|
||||||
LLType* tiarrty = DtoType(Type::dtypeinfo->type->arrayOf());
|
LLType* tiarrty = DtoType(Type::dtypeinfo->type->arrayOf());
|
||||||
tiinits = LLConstantStruct::get(isaStruct(tiarrty), llvm::ArrayRef<LLConstant*>(pinits));
|
tiinits = LLConstantStruct::get(isaStruct(tiarrty), llvm::ArrayRef<LLConstant*>(pinits));
|
||||||
LLValue* typeinfoarrayparam = new llvm::GlobalVariable(*gIR->module, tiarrty,
|
LLValue* typeinfoarrayparam = new llvm::GlobalVariable(gIR->module, tiarrty,
|
||||||
true, llvm::GlobalValue::InternalLinkage, tiinits, "._arguments.array");
|
true, llvm::GlobalValue::InternalLinkage, tiinits, "._arguments.array");
|
||||||
|
|
||||||
return DtoLoad(typeinfoarrayparam);
|
return DtoLoad(typeinfoarrayparam);
|
||||||
|
|
|
@ -214,7 +214,7 @@ public:
|
||||||
if (gvar == 0)
|
if (gvar == 0)
|
||||||
{
|
{
|
||||||
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::PrivateLinkage;
|
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::PrivateLinkage;
|
||||||
gvar = new llvm::GlobalVariable(*gIR->module, _init->getType(), true, _linkage, _init, ".str");
|
gvar = new llvm::GlobalVariable(gIR->module, _init->getType(), true, _linkage, _init, ".str");
|
||||||
gvar->setUnnamedAddr(true);
|
gvar->setUnnamedAddr(true);
|
||||||
(*stringLiteralCache)[key] = gvar;
|
(*stringLiteralCache)[key] = gvar;
|
||||||
}
|
}
|
||||||
|
@ -490,7 +490,7 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
se->globalVar = new llvm::GlobalVariable(*p->module,
|
se->globalVar = new llvm::GlobalVariable(p->module,
|
||||||
DtoType(e->e1->type), false, llvm::GlobalValue::InternalLinkage, 0,
|
DtoType(e->e1->type), false, llvm::GlobalValue::InternalLinkage, 0,
|
||||||
".structliteral");
|
".structliteral");
|
||||||
|
|
||||||
|
@ -498,7 +498,7 @@ public:
|
||||||
if (constValue->getType() != se->globalVar->getType()->getContainedType(0))
|
if (constValue->getType() != se->globalVar->getType()->getContainedType(0))
|
||||||
{
|
{
|
||||||
llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable(
|
llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable(
|
||||||
*p->module, constValue->getType(), false,
|
p->module, constValue->getType(), false,
|
||||||
llvm::GlobalValue::InternalLinkage, 0, ".structliteral");
|
llvm::GlobalValue::InternalLinkage, 0, ".structliteral");
|
||||||
se->globalVar->replaceAllUsesWith(
|
se->globalVar->replaceAllUsesWith(
|
||||||
DtoBitCast(finalGlobalVar, se->globalVar->getType()));
|
DtoBitCast(finalGlobalVar, se->globalVar->getType()));
|
||||||
|
@ -589,7 +589,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canBeConst = e->type->isConst() || e->type->isImmutable();
|
bool canBeConst = e->type->isConst() || e->type->isImmutable();
|
||||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(*gIR->module,
|
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(gIR->module,
|
||||||
initval->getType(), canBeConst, llvm::GlobalValue::InternalLinkage, initval,
|
initval->getType(), canBeConst, llvm::GlobalValue::InternalLinkage, initval,
|
||||||
".dynarrayStorage");
|
".dynarrayStorage");
|
||||||
gvar->setUnnamedAddr(canBeConst);
|
gvar->setUnnamedAddr(canBeConst);
|
||||||
|
@ -670,7 +670,7 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value->globalVar = new llvm::GlobalVariable(*p->module,
|
value->globalVar = new llvm::GlobalVariable(p->module,
|
||||||
origClass->type->ctype->isClass()->getMemoryLLType(),
|
origClass->type->ctype->isClass()->getMemoryLLType(),
|
||||||
false, llvm::GlobalValue::InternalLinkage, 0, ".classref");
|
false, llvm::GlobalValue::InternalLinkage, 0, ".classref");
|
||||||
|
|
||||||
|
@ -713,7 +713,7 @@ public:
|
||||||
if (constValue->getType() != value->globalVar->getType()->getContainedType(0))
|
if (constValue->getType() != value->globalVar->getType()->getContainedType(0))
|
||||||
{
|
{
|
||||||
llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable(
|
llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable(
|
||||||
*p->module, constValue->getType(), false,
|
p->module, constValue->getType(), false,
|
||||||
llvm::GlobalValue::InternalLinkage, 0, ".classref");
|
llvm::GlobalValue::InternalLinkage, 0, ".classref");
|
||||||
value->globalVar->replaceAllUsesWith(
|
value->globalVar->replaceAllUsesWith(
|
||||||
DtoBitCast(finalGlobalVar, value->globalVar->getType()));
|
DtoBitCast(finalGlobalVar, value->globalVar->getType()));
|
||||||
|
|
|
@ -410,7 +410,7 @@ public:
|
||||||
Logger::cout() << "type: " << *at << '\n';
|
Logger::cout() << "type: " << *at << '\n';
|
||||||
Logger::cout() << "init: " << *_init << '\n';
|
Logger::cout() << "init: " << *_init << '\n';
|
||||||
}
|
}
|
||||||
gvar = new llvm::GlobalVariable(*gIR->module, at, true, _linkage, _init, ".str");
|
gvar = new llvm::GlobalVariable(gIR->module, at, true, _linkage, _init, ".str");
|
||||||
gvar->setUnnamedAddr(true);
|
gvar->setUnnamedAddr(true);
|
||||||
(*stringLiteralCache)[key] = gvar;
|
(*stringLiteralCache)[key] = gvar;
|
||||||
}
|
}
|
||||||
|
@ -2714,7 +2714,7 @@ public:
|
||||||
{
|
{
|
||||||
llvm::Constant* init = arrayLiteralToConst(p, e);
|
llvm::Constant* init = arrayLiteralToConst(p, e);
|
||||||
llvm::GlobalVariable* global = new llvm::GlobalVariable(
|
llvm::GlobalVariable* global = new llvm::GlobalVariable(
|
||||||
*gIR->module,
|
gIR->module,
|
||||||
init->getType(),
|
init->getType(),
|
||||||
true,
|
true,
|
||||||
llvm::GlobalValue::InternalLinkage,
|
llvm::GlobalValue::InternalLinkage,
|
||||||
|
@ -2904,7 +2904,7 @@ public:
|
||||||
LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
|
LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
|
||||||
|
|
||||||
LLConstant* initval = arrayConst(keysInits, indexType);
|
LLConstant* initval = arrayConst(keysInits, indexType);
|
||||||
LLConstant* globalstore = new LLGlobalVariable(*gIR->module, initval->getType(),
|
LLConstant* globalstore = new LLGlobalVariable(gIR->module, initval->getType(),
|
||||||
false, LLGlobalValue::InternalLinkage, initval, ".aaKeysStorage");
|
false, LLGlobalValue::InternalLinkage, initval, ".aaKeysStorage");
|
||||||
#if LDC_LLVM_VER >= 307
|
#if LDC_LLVM_VER >= 307
|
||||||
LLConstant* slice = llvm::ConstantExpr::getGetElementPtr(isaPointer(globalstore)->getElementType(), globalstore, idxs, true);
|
LLConstant* slice = llvm::ConstantExpr::getGetElementPtr(isaPointer(globalstore)->getElementType(), globalstore, idxs, true);
|
||||||
|
@ -2915,7 +2915,7 @@ public:
|
||||||
LLValue* keysArray = DtoAggrPaint(slice, funcTy->getParamType(1));
|
LLValue* keysArray = DtoAggrPaint(slice, funcTy->getParamType(1));
|
||||||
|
|
||||||
initval = arrayConst(valuesInits, vtype);
|
initval = arrayConst(valuesInits, vtype);
|
||||||
globalstore = new LLGlobalVariable(*gIR->module, initval->getType(),
|
globalstore = new LLGlobalVariable(gIR->module, initval->getType(),
|
||||||
false, LLGlobalValue::InternalLinkage, initval, ".aaValuesStorage");
|
false, LLGlobalValue::InternalLinkage, initval, ".aaValuesStorage");
|
||||||
#if LDC_LLVM_VER >= 307
|
#if LDC_LLVM_VER >= 307
|
||||||
slice = llvm::ConstantExpr::getGetElementPtr(isaPointer(globalstore)->getElementType(), globalstore, idxs, true);
|
slice = llvm::ConstantExpr::getGetElementPtr(isaPointer(globalstore)->getElementType(), globalstore, idxs, true);
|
||||||
|
|
|
@ -409,13 +409,13 @@ LLValue* DtoMemCmp(LLValue* lhs, LLValue* rhs, LLValue* nbytes)
|
||||||
// int memcmp ( const void * ptr1, const void * ptr2, size_t num );
|
// int memcmp ( const void * ptr1, const void * ptr2, size_t num );
|
||||||
|
|
||||||
LLType* VoidPtrTy = getVoidPtrType();
|
LLType* VoidPtrTy = getVoidPtrType();
|
||||||
LLFunction* fn = gIR->module->getFunction("memcmp");
|
LLFunction* fn = gIR->module.getFunction("memcmp");
|
||||||
if (!fn)
|
if (!fn)
|
||||||
{
|
{
|
||||||
LLType* Tys[] = { VoidPtrTy, VoidPtrTy, DtoSize_t() };
|
LLType* Tys[] = { VoidPtrTy, VoidPtrTy, DtoSize_t() };
|
||||||
LLFunctionType* fty = LLFunctionType::get(LLType::getInt32Ty(gIR->context()),
|
LLFunctionType* fty = LLFunctionType::get(LLType::getInt32Ty(gIR->context()),
|
||||||
Tys, false);
|
Tys, false);
|
||||||
fn = LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, "memcmp", gIR->module);
|
fn = LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, "memcmp", &gIR->module);
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs = DtoBitCast(lhs, VoidPtrTy);
|
lhs = DtoBitCast(lhs, VoidPtrTy);
|
||||||
|
@ -508,7 +508,7 @@ LLConstant* DtoConstString(const char* str)
|
||||||
if (gvar == 0)
|
if (gvar == 0)
|
||||||
{
|
{
|
||||||
llvm::Constant* init = llvm::ConstantDataArray::getString(gIR->context(), s, true);
|
llvm::Constant* init = llvm::ConstantDataArray::getString(gIR->context(), s, true);
|
||||||
gvar = new llvm::GlobalVariable(*gIR->module, init->getType(), true,
|
gvar = new llvm::GlobalVariable(gIR->module, init->getType(), true,
|
||||||
llvm::GlobalValue::PrivateLinkage, init, ".str");
|
llvm::GlobalValue::PrivateLinkage, init, ".str");
|
||||||
gvar->setUnnamedAddr(true);
|
gvar->setUnnamedAddr(true);
|
||||||
gIR->stringLiteral1ByteCache[s] = gvar;
|
gIR->stringLiteral1ByteCache[s] = gvar;
|
||||||
|
@ -755,33 +755,6 @@ unsigned char getABITypeAlign(LLType* t)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLStructType* DtoInterfaceInfoType()
|
|
||||||
{
|
|
||||||
if (gIR->interfaceInfoType)
|
|
||||||
return gIR->interfaceInfoType;
|
|
||||||
|
|
||||||
// build interface info type
|
|
||||||
LLSmallVector<LLType*, 3> types;
|
|
||||||
// ClassInfo classinfo
|
|
||||||
ClassDeclaration* cd2 = Type::typeinfoclass;
|
|
||||||
DtoResolveClass(cd2);
|
|
||||||
types.push_back(DtoType(cd2->type));
|
|
||||||
// void*[] vtbl
|
|
||||||
LLSmallVector<LLType*, 2> vtbltypes;
|
|
||||||
vtbltypes.push_back(DtoSize_t());
|
|
||||||
LLType* byteptrptrty = getPtrToType(getPtrToType(LLType::getInt8Ty(gIR->context())));
|
|
||||||
vtbltypes.push_back(byteptrptrty);
|
|
||||||
types.push_back(LLStructType::get(gIR->context(), vtbltypes));
|
|
||||||
// int offset
|
|
||||||
types.push_back(LLType::getInt32Ty(gIR->context()));
|
|
||||||
// create type
|
|
||||||
gIR->interfaceInfoType = LLStructType::get(gIR->context(), types);
|
|
||||||
|
|
||||||
return gIR->interfaceInfoType;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
LLStructType* DtoMutexType()
|
LLStructType* DtoMutexType()
|
||||||
{
|
{
|
||||||
if (gIR->mutexType)
|
if (gIR->mutexType)
|
||||||
|
|
|
@ -60,7 +60,6 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym);
|
||||||
|
|
||||||
// some types
|
// some types
|
||||||
LLIntegerType* DtoSize_t();
|
LLIntegerType* DtoSize_t();
|
||||||
LLStructType* DtoInterfaceInfoType();
|
|
||||||
LLStructType* DtoMutexType();
|
LLStructType* DtoMutexType();
|
||||||
LLStructType* DtoModuleReferenceType();
|
LLStructType* DtoModuleReferenceType();
|
||||||
|
|
||||||
|
|
|
@ -194,7 +194,7 @@ static void emitTypeMetadata(TypeInfoDeclaration *tid)
|
||||||
// Add some metadata for use by optimization passes.
|
// Add some metadata for use by optimization passes.
|
||||||
std::string metaname(TD_PREFIX);
|
std::string metaname(TD_PREFIX);
|
||||||
metaname += mangle(tid);
|
metaname += mangle(tid);
|
||||||
llvm::NamedMDNode* meta = gIR->module->getNamedMetadata(metaname);
|
llvm::NamedMDNode* meta = gIR->module.getNamedMetadata(metaname);
|
||||||
|
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
// Construct the fields
|
// Construct the fields
|
||||||
|
@ -209,7 +209,7 @@ static void emitTypeMetadata(TypeInfoDeclaration *tid)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Construct the metadata and insert it into the module.
|
// Construct the metadata and insert it into the module.
|
||||||
llvm::NamedMDNode* node = gIR->module->getOrInsertNamedMetadata(metaname);
|
llvm::NamedMDNode* node = gIR->module.getOrInsertNamedMetadata(metaname);
|
||||||
node->addOperand(llvm::MDNode::get(gIR->context(),
|
node->addOperand(llvm::MDNode::get(gIR->context(),
|
||||||
llvm::makeArrayRef(mdVals, TD_NumFields)));
|
llvm::makeArrayRef(mdVals, TD_NumFields)));
|
||||||
}
|
}
|
||||||
|
@ -674,7 +674,7 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState* p)
|
||||||
}
|
}
|
||||||
|
|
||||||
IrGlobal* irg = getIrGlobal(decl, true);
|
IrGlobal* irg = getIrGlobal(decl, true);
|
||||||
irg->value = gIR->module->getGlobalVariable(mangled);
|
irg->value = gIR->module.getGlobalVariable(mangled);
|
||||||
if (irg->value) {
|
if (irg->value) {
|
||||||
irg->type = irg->value->getType()->getContainedType(0);
|
irg->type = irg->value->getType()->getContainedType(0);
|
||||||
assert(irg->type->isStructTy());
|
assert(irg->type->isStructTy());
|
||||||
|
@ -683,7 +683,7 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState* p)
|
||||||
irg->type = Type::dtypeinfo->type->ctype->isClass()->getMemoryLLType();
|
irg->type = Type::dtypeinfo->type->ctype->isClass()->getMemoryLLType();
|
||||||
else
|
else
|
||||||
irg->type = LLStructType::create(gIR->context(), decl->toPrettyChars());
|
irg->type = LLStructType::create(gIR->context(), decl->toPrettyChars());
|
||||||
irg->value = new llvm::GlobalVariable(*gIR->module, irg->type, true,
|
irg->value = new llvm::GlobalVariable(gIR->module, irg->type, true,
|
||||||
llvm::GlobalValue::ExternalLinkage, NULL, mangled);
|
llvm::GlobalValue::ExternalLinkage, NULL, mangled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ LLGlobalVariable * IrAggr::getInitSymbol()
|
||||||
initname.append("6__initZ");
|
initname.append("6__initZ");
|
||||||
|
|
||||||
init = getOrCreateGlobal(aggrdecl->loc,
|
init = getOrCreateGlobal(aggrdecl->loc,
|
||||||
*gIR->module, init_type, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);
|
gIR->module, init_type, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);
|
||||||
|
|
||||||
// set alignment
|
// set alignment
|
||||||
init->setAlignment(type->alignsize());
|
init->setAlignment(type->alignsize());
|
||||||
|
|
|
@ -55,7 +55,7 @@ LLGlobalVariable * IrAggr::getVtblSymbol()
|
||||||
LLType* vtblTy = stripModifiers(type)->ctype->isClass()->getVtbl();
|
LLType* vtblTy = stripModifiers(type)->ctype->isClass()->getVtbl();
|
||||||
|
|
||||||
vtbl = getOrCreateGlobal(aggrdecl->loc,
|
vtbl = getOrCreateGlobal(aggrdecl->loc,
|
||||||
*gIR->module, vtblTy, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);
|
gIR->module, vtblTy, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);
|
||||||
|
|
||||||
return vtbl;
|
return vtbl;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol()
|
||||||
|
|
||||||
// classinfos cannot be constants since they're used as locks for synchronized
|
// classinfos cannot be constants since they're used as locks for synchronized
|
||||||
classInfo = getOrCreateGlobal(aggrdecl->loc,
|
classInfo = getOrCreateGlobal(aggrdecl->loc,
|
||||||
*gIR->module, tc->getMemoryLLType(), false,
|
gIR->module, tc->getMemoryLLType(), false,
|
||||||
llvm::GlobalValue::ExternalLinkage, NULL, initname);
|
llvm::GlobalValue::ExternalLinkage, NULL, initname);
|
||||||
|
|
||||||
// Generate some metadata on this ClassInfo if it's for a class.
|
// Generate some metadata on this ClassInfo if it's for a class.
|
||||||
|
@ -111,7 +111,7 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol()
|
||||||
#endif
|
#endif
|
||||||
// Construct the metadata and insert it into the module.
|
// Construct the metadata and insert it into the module.
|
||||||
llvm::SmallString<64> name;
|
llvm::SmallString<64> name;
|
||||||
llvm::NamedMDNode* node = gIR->module->getOrInsertNamedMetadata(
|
llvm::NamedMDNode* node = gIR->module.getOrInsertNamedMetadata(
|
||||||
llvm::Twine(CD_PREFIX, initname).toStringRef(name));
|
llvm::Twine(CD_PREFIX, initname).toStringRef(name));
|
||||||
node->addOperand(llvm::MDNode::get(gIR->context(),
|
node->addOperand(llvm::MDNode::get(gIR->context(),
|
||||||
llvm::makeArrayRef(mdVals, CD_NumFields)));
|
llvm::makeArrayRef(mdVals, CD_NumFields)));
|
||||||
|
@ -145,7 +145,7 @@ LLGlobalVariable * IrAggr::getInterfaceArraySymbol()
|
||||||
|
|
||||||
// We keep this as external for now and only consider template linkage if
|
// We keep this as external for now and only consider template linkage if
|
||||||
// we emit the initializer later.
|
// we emit the initializer later.
|
||||||
classInterfacesArray = getOrCreateGlobal(cd->loc, *gIR->module,
|
classInterfacesArray = getOrCreateGlobal(cd->loc, gIR->module,
|
||||||
array_type, true, llvm::GlobalValue::ExternalLinkage, NULL, name);
|
array_type, true, llvm::GlobalValue::ExternalLinkage, NULL, name);
|
||||||
|
|
||||||
return classInterfacesArray;
|
return classInterfacesArray;
|
||||||
|
@ -349,7 +349,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance
|
||||||
name.printf("%i", b->offset);
|
name.printf("%i", b->offset);
|
||||||
name.writestring(mangleExact(fd));
|
name.writestring(mangleExact(fd));
|
||||||
LLFunction *thunk = LLFunction::Create(isaFunction(fn->getType()->getContainedType(0)),
|
LLFunction *thunk = LLFunction::Create(isaFunction(fn->getType()->getContainedType(0)),
|
||||||
DtoLinkage(fd), name.extractString(), gIR->module);
|
DtoLinkage(fd), name.extractString(), &gIR->module);
|
||||||
|
|
||||||
// create entry and end blocks
|
// create entry and end blocks
|
||||||
llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(gIR->context(), "", thunk);
|
llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(gIR->context(), "", thunk);
|
||||||
|
@ -398,7 +398,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance
|
||||||
mangledName.append("6__vtblZ");
|
mangledName.append("6__vtblZ");
|
||||||
|
|
||||||
llvm::GlobalVariable* GV = getOrCreateGlobal(cd->loc,
|
llvm::GlobalVariable* GV = getOrCreateGlobal(cd->loc,
|
||||||
*gIR->module,
|
gIR->module,
|
||||||
vtbl_constant->getType(),
|
vtbl_constant->getType(),
|
||||||
true,
|
true,
|
||||||
DtoLinkage(cd),
|
DtoLinkage(cd),
|
||||||
|
|
|
@ -14,29 +14,33 @@
|
||||||
#include "ir/irdsymbol.h"
|
#include "ir/irdsymbol.h"
|
||||||
#include "ir/irmodule.h"
|
#include "ir/irmodule.h"
|
||||||
|
|
||||||
IrModule::IrModule(Module* module, const char* srcfilename)
|
IrModule::IrModule(Module *module, const char *srcfilename)
|
||||||
{
|
: M(module), moduleInfoVar_(0) {}
|
||||||
M = module;
|
|
||||||
|
|
||||||
LLConstant* slice = DtoConstString(srcfilename);
|
IrModule::~IrModule() {}
|
||||||
fileName = new llvm::GlobalVariable(
|
|
||||||
*gIR->module, slice->getType(), true, LLGlobalValue::InternalLinkage, slice, ".modulefilename");
|
llvm::GlobalVariable *IrModule::moduleInfoSymbol() {
|
||||||
|
if (moduleInfoVar_) return moduleInfoVar_;
|
||||||
|
|
||||||
|
std::string name("_D");
|
||||||
|
name.append(mangle(M));
|
||||||
|
name.append("12__ModuleInfoZ");
|
||||||
|
|
||||||
|
moduleInfoVar_ = new llvm::GlobalVariable(
|
||||||
|
gIR->module, llvm::StructType::create(gIR->context()), false,
|
||||||
|
llvm::GlobalValue::ExternalLinkage, NULL, name);
|
||||||
|
return moduleInfoVar_;
|
||||||
}
|
}
|
||||||
|
|
||||||
IrModule::~IrModule()
|
IrModule *getIrModule(Module *m) {
|
||||||
{
|
if (!m) m = gIR->func()->decl->getModule();
|
||||||
}
|
|
||||||
|
|
||||||
IrModule *getIrModule(Module *m)
|
|
||||||
{
|
|
||||||
if (m == NULL)
|
|
||||||
m = gIR->func()->decl->getModule();
|
|
||||||
assert(m && "null module");
|
assert(m && "null module");
|
||||||
if (m->ir.m_type == IrDsymbol::NotSet)
|
if (m->ir.m_type == IrDsymbol::NotSet) {
|
||||||
{
|
|
||||||
m->ir.irModule = new IrModule(m, m->srcfile->toChars());
|
m->ir.irModule = new IrModule(m, m->srcfile->toChars());
|
||||||
m->ir.m_type = IrDsymbol::ModuleType;
|
m->ir.m_type = IrDsymbol::ModuleType;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m->ir.m_type == IrDsymbol::ModuleType);
|
assert(m->ir.m_type == IrDsymbol::ModuleType);
|
||||||
return m->ir.irModule;
|
return m->ir.irModule;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// Represents the state of a D module on its way through code generation. Also
|
// Represents the state of a D module on its way through code generation.
|
||||||
// see the TODO in gen/module.cpp – parts of IRState really belong here.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
@ -16,19 +15,31 @@
|
||||||
#define LDC_IR_IRMODULE_H
|
#define LDC_IR_IRMODULE_H
|
||||||
|
|
||||||
class Module;
|
class Module;
|
||||||
namespace llvm
|
namespace llvm {
|
||||||
{
|
class GlobalVariable;
|
||||||
class GlobalVariable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IrModule
|
struct IrModule {
|
||||||
{
|
IrModule(Module *module, const char *srcfilename);
|
||||||
IrModule(Module* module, const char* srcfilename);
|
|
||||||
virtual ~IrModule();
|
virtual ~IrModule();
|
||||||
|
|
||||||
Module* M;
|
Module *const M;
|
||||||
|
|
||||||
llvm::GlobalVariable* fileName;
|
llvm::GlobalVariable *moduleInfoSymbol();
|
||||||
|
|
||||||
|
// static ctors/dtors/unittests
|
||||||
|
typedef std::list<FuncDeclaration *> FuncDeclList;
|
||||||
|
typedef std::list<VarDeclaration *> GatesList;
|
||||||
|
FuncDeclList ctors;
|
||||||
|
FuncDeclList dtors;
|
||||||
|
FuncDeclList sharedCtors;
|
||||||
|
FuncDeclList sharedDtors;
|
||||||
|
GatesList gates;
|
||||||
|
GatesList sharedGates;
|
||||||
|
FuncDeclList unitTests;
|
||||||
|
|
||||||
|
private:
|
||||||
|
llvm::GlobalVariable *moduleInfoVar_;
|
||||||
};
|
};
|
||||||
|
|
||||||
IrModule *getIrModule(Module *m);
|
IrModule *getIrModule(Module *m);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue