Merge pull request #974 from klickverbot/singleobj-rework

Avoid using llvm::Linker
This commit is contained in:
Kai Nacke 2015-06-27 23:26:22 +02:00
commit ec0d7bbcf1
38 changed files with 696 additions and 788 deletions

View file

@ -228,6 +228,7 @@ file(GLOB IR_SRC ir/*.cpp)
file(GLOB IR_HDR ir/*.h)
set(DRV_SRC
driver/cl_options.cpp
driver/codegenerator.cpp
driver/configfile.cpp
driver/targetmachine.cpp
driver/toobj.cpp
@ -239,6 +240,7 @@ set(DRV_SRC
set(DRV_HDR
driver/linker.h
driver/cl_options.h
driver/codegenerator.h
driver/configfile.h
driver/ldc-version.h
driver/targetmachine.h

View file

@ -84,24 +84,12 @@ class Expression;
class DeleteDeclaration;
class OverloadSet;
struct AA;
#if IN_LLVM
class TypeInfoDeclaration;
class ClassInfoDeclaration;
#endif
#ifdef IN_GCC
typedef union tree_node TYPE;
#else
struct TYPE;
#endif
#if IN_LLVM
struct IRState;
namespace llvm
{
class Value;
}
#endif
struct Ungag
{
unsigned oldgag;

View file

@ -134,7 +134,6 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do
// LDC
llvmForceLogging = false;
noModuleInfo = false;
moduleInfoVar = NULL;
this->doDocComment = doDocComment;
this->doHdrGen = doHdrGen;
this->arrayfuncs = 0;

View file

@ -193,11 +193,9 @@ public:
llvm::Module* genLLVMModule(llvm::LLVMContext& context);
void buildTargetFiles(bool singleObj, bool library);
File* buildFilePath(const char* forcename, const char* path, const char* ext);
llvm::GlobalVariable* moduleInfoSymbol();
bool llvmForceLogging;
bool noModuleInfo; /// Do not emit any module metadata.
llvm::GlobalVariable* moduleInfoVar;
// array ops emitted in this module already
AA *arrayfuncs;

215
driver/codegenerator.cpp Normal file
View 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
View 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

View file

@ -18,11 +18,6 @@
#include "gen/optimizer.h"
#include "gen/programs.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/Program.h"
#include "llvm/Support/Path.h"

View file

@ -21,11 +21,11 @@
#include "scope.h"
#include "dmd2/target.h"
#include "driver/cl_options.h"
#include "driver/codegenerator.h"
#include "driver/configfile.h"
#include "driver/ldc-version.h"
#include "driver/linker.h"
#include "driver/targetmachine.h"
#include "driver/toobj.h"
#include "gen/cl_helpers.h"
#include "gen/irstate.h"
#include "gen/linkage.h"
@ -40,11 +40,6 @@
#include "llvm/InitializePasses.h"
#endif
#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/Host.h"
#include "llvm/Support/ManagedStatic.h"
@ -873,105 +868,52 @@ static void dumpPredefinedVersions()
}
}
static Module *entrypoint = NULL;
static Module *rootHasMain = NULL;
/// Callback to generate a C main() function, invoked by the frontend.
void genCmain(Scope *sc)
/// Emits the .json AST description file.
///
/// This (ugly) piece of code has been taken from DMD's mars.c and should be
/// kept in sync with the former.
static void emitJson(Modules &modules)
{
if (entrypoint)
return;
OutBuffer buf;
json_generate(&buf, &modules);
/* 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\
";
// Write buf to file
const char *name = global.params.jsonfilename;
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(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");
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 LDC_LLVM_VER >= 306
// FIXME: A possible error message is written to the diagnostic context
// Do we show these messages?
linker.linkInModule(entryModule);
#else
std::string linkError;
#if LDC_LLVM_VER >= 303
const bool hadError = linker.linkInModule(entryModule, &linkError);
#else
const bool hadError = linker.LinkInModule(entryModule, &linkError);
linker.releaseModule();
#endif
if (hadError)
error(Loc(), "%s", linkError.c_str());
#endif
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);
}
}
@ -1334,175 +1276,42 @@ int main(int argc, char **argv)
// the user requested it.
if (global.params.moduleDepsFile != NULL)
{
assert (global.params.moduleDepsFile != NULL);
File deps(global.params.moduleDepsFile);
OutBuffer* ob = global.params.moduleDeps;
deps.setbuffer(static_cast<void*>(ob->data), ob->offset);
deps.write();
}
// collects llvm modules to be linked if singleobj is passed
std::vector<llvm::Module*> llvmModules;
llvm::LLVMContext& context = llvm::getGlobalContext();
// Generate output files
for (unsigned i = 0; i < modules.dim; i++)
// Generate one or more object/IR/bitcode files.
if (global.params.obj && !modules.empty())
{
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "code %s\n", m->toChars());
if (global.params.obj)
ldc::CodeGenerator cg(llvm::getGlobalContext(), singleObj);
for (unsigned i = 0; i < modules.dim; i++)
{
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)
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
if (singleObj && llvmModules.size() > 0)
// Generate DDoc output files.
if (global.params.doDocComments)
{
Module *m = modules[0];
const char* oname;
const char* filename;
if ((oname = global.params.exefile) || (oname = global.params.objname))
for (unsigned i = 0; i < modules.dim; i++)
{
filename = FileName::forceExt(oname, global.obj_ext);
if (global.params.objdir)
{
filename = FileName::combine(global.params.objdir, FileName::name(filename));
}
gendocfile(modules[i]);
}
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)
{
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);
}
}
emitJson(modules);
LLVM_D_FreeRuntime();
llvm::llvm_shutdown();
@ -1510,6 +1319,8 @@ int main(int argc, char **argv)
if (global.errors)
fatal();
// Finally, produce the final executable/archive and run it, if we are
// supposed to.
int status = EXIT_SUCCESS;
if (!global.params.objfiles->dim)
{
@ -1529,8 +1340,7 @@ int main(int argc, char **argv)
{
status = runExecutable();
/* Delete .obj files and .exe file
*/
/// Delete .obj files and .exe file.
for (unsigned i = 0; i < modules.dim; i++)
{
modules[i]->deleteObjFile();

View file

@ -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
// 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.
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)
// we need to return pointer to the static array.
@ -477,7 +477,7 @@ void initializeArrayLiteral(IRState* p, ArrayLiteralExp* ale, LLValue* dstMem)
else
{
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
*gIR->module,
gIR->module,
constarr->getType(),
true,
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);
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()));
}
else

View file

@ -507,7 +507,7 @@ static LLConstant* build_offti_array(ClassDeclaration* cd, LLType* arrayT)
LLConstant* arrInit = LLConstantArray::get(arrTy, arrayInits);
// 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");
ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType()));

View file

@ -17,39 +17,38 @@
void emitCoverageLinecountInc(Loc &loc) {
// Only emit coverage increment for locations in the source of the current module
// (for example, 'inlined' methods from other source files should be skipped).
if ( global.params.cov && (loc.linnum != 0) && loc.filename
&& (gIR->module->getModuleIdentifier().compare(loc.filename) == 0) )
{
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);
}
if (!global.params.cov || !loc.linnum || !loc.filename ||
strcmp(gIR->dmodule->srcfile->name->toChars(), loc.filename) != 0) {
return;
}
}
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);
}

View file

@ -256,7 +256,7 @@ public:
if (initVal->getType() != gvar->getType()->getElementType())
{
llvm::GlobalVariable* newGvar = getOrCreateGlobal(decl->loc,
*irs->module, initVal->getType(), gvar->isConstant(),
irs->module, initVal->getType(), gvar->isConstant(),
llLinkage, 0,
"", // We take on the name of the old global below.
gvar->isThreadLocal());

View file

@ -53,8 +53,8 @@ Module *ldc::DIBuilder::getDefinedModule(Dsymbol *s)
////////////////////////////////////////////////////////////////////////////////
ldc::DIBuilder::DIBuilder(IRState *const IR, llvm::Module &M)
: IR(IR), DBuilder(M)
ldc::DIBuilder::DIBuilder(IRState *const IR)
: IR(IR), DBuilder(IR->module), CUNode(0)
{
}
@ -656,13 +656,16 @@ void ldc::DIBuilder::EmitCompileUnit(Module *m)
Logger::println("D to dwarf compile_unit");
LOG_SCOPE;
assert(!CUNode &&
"Already created compile unit for this DIBuilder instance");
// prepare srcpath
llvm::SmallString<128> srcpath(m->srcfile->name->toChars());
llvm::sys::fs::make_absolute(srcpath);
#if LDC_LLVM_VER >= 304
// 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 =
#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)
return;

View file

@ -127,7 +127,7 @@ class DIBuilder
}
public:
DIBuilder(IRState *const IR, llvm::Module &M);
DIBuilder(IRState *const IR);
/// \brief Emit the Dwarf compile_unit global for a Module m.
/// \param m Module to emit as compile unit.
@ -183,7 +183,7 @@ public:
/// \param vd Variable declaration to emit debug info for.
DIGlobalVariable EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd); // FIXME
void EmitModuleEnd();
void Finalize();
private:
llvm::LLVMContext &getContext();

View file

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "gen/functions.h"
#include "aggregate.h"
#include "declaration.h"
#include "id.h"
@ -20,6 +21,7 @@
#include "gen/arrays.h"
#include "gen/classes.h"
#include "gen/dvalue.h"
#include "gen/inlineir.h"
#include "gen/irstate.h"
#include "gen/linkage.h"
#include "gen/llvm.h"
@ -30,11 +32,7 @@
#include "gen/pragma.h"
#include "gen/runtime.h"
#include "gen/tollvm.h"
#if LDC_LLVM_VER >= 305
#include "llvm/Linker/Linker.h"
#else
#include "llvm/Linker.h"
#endif
#include "ir/irmodule.h"
#if LDC_LLVM_VER >= 303
#include "llvm/IR/Intrinsics.h"
#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)
{
IrFuncTy &irFty = getIrFunc(fdecl, true)->irFty;
@ -593,7 +483,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
// construct function
LLFunctionType* functype = DtoFunctionType(fdecl);
LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangledName);
LLFunction* func = vafunc ? vafunc : gIR->module.getFunction(mangledName);
if (!func) {
if(fdecl->llvmInternal == LLVMinline_ir)
{
@ -604,7 +494,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
// All function declarations are "external" - any other linkage type
// is set when actually defining the function.
func = LLFunction::Create(functype,
llvm::GlobalValue::ExternalLinkage, mangledName, gIR->module);
llvm::GlobalValue::ExternalLinkage, mangledName, &gIR->module);
}
} else if (func->getFunctionType() != functype) {
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);
if (fd->isUnitTestDeclaration()) {
gIR->unitTests.push_back(fd);
getIrModule(gIR->dmodule)->unitTests.push_back(fd);
} else if (fd->isSharedStaticCtorDeclaration()) {
gIR->sharedCtors.push_back(fd);
getIrModule(gIR->dmodule)->sharedCtors.push_back(fd);
} else if (StaticDtorDeclaration *dtorDecl = fd->isSharedStaticDtorDeclaration()) {
gIR->sharedDtors.push_front(fd);
if (dtorDecl->vgate)
gIR->sharedGates.push_front(dtorDecl->vgate);
getIrModule(gIR->dmodule)->sharedDtors.push_front(fd);
if (dtorDecl->vgate) {
getIrModule(gIR->dmodule)->sharedGates.push_front(dtorDecl->vgate);
}
} else if (fd->isStaticCtorDeclaration()) {
gIR->ctors.push_back(fd);
getIrModule(gIR->dmodule)->ctors.push_back(fd);
} else if (StaticDtorDeclaration *dtorDecl = fd->isStaticDtorDeclaration()) {
gIR->dtors.push_front(fd);
if (dtorDecl->vgate)
gIR->gates.push_front(dtorDecl->vgate);
getIrModule(gIR->dmodule)->dtors.push_front(fd);
if (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());
gIR->functions.push_back(irFunc);
if (fd->isMain())
gIR->emitMain = true;
func->setLinkage(lowerFuncLinkage(fd));
// On x86_64, always set 'uwtable' for System V ABI compatibility.

107
gen/inlineir.cpp Normal file
View 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
View 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

View file

@ -67,15 +67,13 @@ IRTargetScope::IRTargetScope(
}
//////////////////////////////////////////////////////////////////////////////////////////
IRState::IRState(llvm::Module* m)
: module(m), DBuilder(this, *m)
IRState::IRState(const char *name, llvm::LLVMContext &context)
: module(name, context), DBuilder(this)
{
interfaceInfoType = NULL;
mutexType = NULL;
moduleRefType = NULL;
dmodule = 0;
emitMain = false;
mainFunc = 0;
ir.state = this;
asmBlock = NULL;
@ -93,12 +91,6 @@ llvm::Function* IRState::topfunc()
return functions.back()->func;
}
TypeFunction* IRState::topfunctype()
{
assert(!functions.empty() && "Function stack is empty!");
return functions.back()->type;
}
llvm::Instruction* IRState::topallocapoint()
{
assert(!functions.empty() && "AllocaPoint stack is empty!");

View file

@ -121,31 +121,26 @@ struct IRAsmBlock
// represents the module
struct IRState
{
IRState(llvm::Module* m);
IRState(const char *name, llvm::LLVMContext &context);
// module
Module* dmodule;
llvm::Module* module;
llvm::Module module;
llvm::LLVMContext& context() const { return module.getContext(); }
Module *dmodule;
// interface info type, used in DtoInterfaceInfoType
LLStructType* interfaceInfoType;
LLStructType* mutexType;
LLStructType* moduleRefType;
// helper to get the LLVMContext of the module
llvm::LLVMContext& context() const { return module->getContext(); }
// functions
typedef std::vector<IrFunction*> FunctionVector;
FunctionVector functions;
IrFunction* func();
llvm::Function* topfunc();
TypeFunction* topfunctype();
llvm::Instruction* topallocapoint();
// D main function
bool emitMain;
// The function containing the D main() body, if any (not the actual main()
// implicitly emitted).
llvm::Function* mainFunc;
// basic block scopes
@ -177,17 +172,6 @@ struct IRState
// debug info helper
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
IRAsmBlock* asmBlock;
std::ostringstream nakedAsm;

View file

@ -69,7 +69,7 @@
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

View file

@ -219,17 +219,8 @@ void DtoAssert(Module* M, Loc& loc, DValue* msg)
LLValue *DtoModuleFileName(Module* M, const Loc& loc)
{
// we might be generating for an imported template function
const char* cur_file = 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);
}
return DtoConstString(loc.filename ? loc.filename :
M->srcfile->name->toChars());
}
/****************************************************************************************/
@ -975,7 +966,7 @@ void DtoResolveVariable(VarDeclaration* vd)
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,
vd->isThreadlocal());
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)
{
if (isCtor)
llvm::appendToGlobalCtors(*gIR->module, func, priority);
llvm::appendToGlobalCtors(gIR->module, func, priority);
else
llvm::appendToGlobalDtors(*gIR->module, func, priority);
llvm::appendToGlobalDtors(gIR->module, func, priority);
}
//////////////////////////////////////////////////////////////////////////////////////////

View file

@ -45,9 +45,9 @@ void Stream::writeValue(std::ostream& OS, const llvm::Value& V) {
llvm::raw_os_ostream raw(OS);
if (llvm::isa<llvm::Constant>(V) && !llvm::isa<llvm::GlobalValue>(V))
#if LDC_LLVM_VER >= 305
V.printAsOperand(raw, true, gIR->module);
V.printAsOperand(raw, true, &gIR->module);
#else
llvm::WriteAsOperand(raw, &V, true, gIR->module);
llvm::WriteAsOperand(raw, &V, true, &gIR->module);
#endif
else
V.print(raw);

View file

@ -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
// if (forcename)
// return new File(argobj);
// return new File(argobj);
// else
// allow for .o and .obj on windows
#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);
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::GlobalValue::InternalLinkage, symbolName, gIR->module);
llvm::GlobalValue::InternalLinkage, symbolName, &gIR->module);
fn->setCallingConv(gABI->callingConv(LINKd));
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
llvm::Function* build_module_ctor()
static llvm::Function* build_module_ctor(Module *m)
{
std::string name("_D");
name.append(mangle(gIR->dmodule));
name.append(mangle(m));
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
static llvm::Function* build_module_dtor()
static llvm::Function* build_module_dtor(Module *m)
{
std::string name("_D");
name.append(mangle(gIR->dmodule));
name.append(mangle(m));
name.append("6__dtorZ");
return build_module_function(name, gIR->dtors);
return build_module_function(name, getIrModule(m)->dtors);
}
// build module unittest
static llvm::Function* build_module_unittest()
static llvm::Function* build_module_unittest(Module *m)
{
std::string name("_D");
name.append(mangle(gIR->dmodule));
name.append(mangle(m));
name.append("10__unittestZ");
return build_module_function(name, gIR->unitTests);
return build_module_function(name, getIrModule(m)->unitTests);
}
// build module shared ctor
llvm::Function* build_module_shared_ctor()
static llvm::Function* build_module_shared_ctor(Module *m)
{
std::string name("_D");
name.append(mangle(gIR->dmodule));
name.append(mangle(m));
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
static llvm::Function* build_module_shared_dtor()
static llvm::Function* build_module_shared_dtor(Module *m)
{
std::string name("_D");
name.append(mangle(gIR->dmodule));
name.append(mangle(m));
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
static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
static LLFunction* build_module_reference_and_ctor(const char *moduleMangle, LLConstant* moduleinfo)
{
// build ctor type
LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<LLType*>(), false);
// build ctor name
std::string fname = "_D";
fname += mangle(gIR->dmodule);
fname += moduleMangle;
fname += "16__moduleinfoCtorZ";
// 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
LLStructType* modulerefTy = DtoModuleReferenceType();
@ -306,17 +308,17 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
// create the ModuleReference node for this module
std::string thismrefname = "_D";
thismrefname += mangle(gIR->dmodule);
thismrefname += moduleMangle;
thismrefname += "11__moduleRefZ";
Loc loc;
LLGlobalVariable* thismref = getOrCreateGlobal(loc, *gIR->module,
LLGlobalVariable* thismref = getOrCreateGlobal(loc, gIR->module,
modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit,
thismrefname);
// make sure _Dmodule_ref is declared
LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref");
LLConstant* mref = gIR->module.getNamedGlobal("_Dmodule_ref");
LLType *modulerefPtrTy = getPtrToType(modulerefTy);
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));
// 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.
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
// so that they end up in the correct order in the object file.
llvm::GlobalVariable* minfoBeg = new llvm::GlobalVariable(
*gIR->module,
gIR->module,
moduleInfoPtrTy,
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
llvm::GlobalValue::LinkOnceODRLinkage,
@ -440,10 +442,10 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo)
minfoBeg->setVisibility(llvm::GlobalValue::HiddenVisibility);
std::string thismrefname = "_D";
thismrefname += mangle(gIR->dmodule);
thismrefname += moduleMangle;
thismrefname += "11__moduleRefZ";
llvm::GlobalVariable* thismref = new llvm::GlobalVariable(
*gIR->module,
gIR->module,
moduleInfoPtrTy,
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
llvm::GlobalValue::LinkOnceODRLinkage,
@ -454,7 +456,7 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo)
gIR->usedArray.push_back(thismref);
llvm::GlobalVariable* minfoEnd = new llvm::GlobalVariable(
*gIR->module,
gIR->module,
moduleInfoPtrTy,
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
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.
llvm::GlobalVariable* dsoSlot = new llvm::GlobalVariable(
*gIR->module,
gIR->module,
getVoidPtrType(),
false,
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.
llvm::GlobalVariable* dsoInitialized = new llvm::GlobalVariable(
*gIR->module,
gIR->module,
llvm::Type::getInt8Ty(gIR->context()),
false,
llvm::GlobalValue::LinkOnceODRLinkage,
@ -524,26 +526,26 @@ static void build_dso_registry_calls(llvm::Constant* thisModuleInfo)
llvm::Value* minfoRefPtr = DtoBitCast(thismref, getVoidPtrType());
std::string ctorName = "ldc.dso_ctor.";
ctorName += mangle(gIR->dmodule);
ctorName += moduleMangle;
llvm::Function* dsoCtor = llvm::Function::Create(
llvm::FunctionType::get(llvm::Type::getVoidTy(gIR->context()), false),
llvm::GlobalValue::LinkOnceODRLinkage,
ctorName,
gIR->module
&gIR->module
);
dsoCtor->setVisibility(llvm::GlobalValue::HiddenVisibility);
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::FunctionType::get(llvm::Type::getVoidTy(gIR->context()), false),
llvm::GlobalValue::LinkOnceODRLinkage,
"ldc.dso_dtor",
gIR->module
&gIR->module
);
dsoDtor->setVisibility(llvm::GlobalValue::HiddenVisibility);
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)
@ -562,7 +564,7 @@ static void build_llvm_used_array(IRState* p)
llvm::ArrayType *arrayType = llvm::ArrayType::get(
getVoidPtrType(), usedVoidPtrs.size());
llvm::GlobalVariable* llvmUsed = new llvm::GlobalVariable(
*p->module,
p->module,
arrayType,
false,
llvm::GlobalValue::AppendingLinkage,
@ -595,7 +597,7 @@ static void addCoverageAnalysis(Module* m)
llvm::ArrayType* type = llvm::ArrayType::get(DtoSize_t(), array_size);
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) };
d_cover_valid_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()),
llvm::ConstantExpr::getGetElementPtr(
@ -616,7 +618,7 @@ static void addCoverageAnalysis(Module* m)
LLArrayType* type = LLArrayType::get(LLType::getInt32Ty(gIR->context()), m->numlines);
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) };
d_cover_data_slice = DtoConstSlice( DtoConstSize_t(type->getArrayNumElements()),
llvm::ConstantExpr::getGetElementPtr(
@ -630,13 +632,13 @@ static void addCoverageAnalysis(Module* m)
// Build ctor name
LLFunction* ctor = NULL;
std::string ctorname = "_D";
ctorname += mangle(gIR->dmodule);
ctorname += mangle(m);
ctorname += "12_coverageanalysisCtor1FZv";
{
IF_LOG Logger::println("Build Coverage Analysis constructor: %s", ctorname.c_str());
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));
// Set function attributes. See functions.cpp:DtoDefineFunction()
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
llvm::Function* fn = LLVM_D_GetRuntimeFunction(Loc(), gIR->module, "_d_cover_register2");
LLValue* args[] = {
getIrModule(m)->fileName->getInitializer(),
DtoConstString(m->srcfile->name->toChars()),
d_cover_valid_slice,
d_cover_data_slice,
DtoConstUbyte(global.params.covPercent)
@ -672,7 +674,7 @@ static void addCoverageAnalysis(Module* m)
fd->linkage = LINKd;
IrFunction* irfunc = getIrFunc(fd, true);
irfunc->func = ctor;
gIR->sharedCtors.push_back(fd);
getIrModule(m)->sharedCtors.push_back(fd);
}
IF_LOG Logger::undent();
@ -695,19 +697,31 @@ static void addCoverageAnalysisInitializer(Module* m) {
static void genModuleInfo(Module *m);
static void codegenModule(Module* m)
void codegenModule(IRState *irs, Module* m)
{
// debug info
gIR->DBuilder.EmitCompileUnit(m);
assert(!irs->dmodule && "irs->module not null, codegen already in progress?!");
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
for (unsigned k=0; k < m->members->dim; k++) {
for (unsigned k=0; k < m->members->dim; k++)
{
Dsymbol* dsym = (*m->members)[k];
assert(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.
if (!m->noModuleInfo)
@ -715,145 +729,16 @@ static void codegenModule(Module* m)
// generate ModuleInfo
genModuleInfo(m);
build_llvm_used_array(gIR);
#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
build_llvm_used_array(irs);
}
// finalize debug info
gIR->DBuilder.EmitModuleEnd();
// verify the llvm
verifyModule(*gIR->module);
}
llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context)
{
bool logenabled = Logger::enabled();
if (llvmForceLogging && !logenabled)
if (m->d_cover_valid)
{
Logger::enable();
addCoverageAnalysisInitializer(m);
}
IF_LOG Logger::println("Generating module: %s", (md ? md->toChars() : toChars()));
LOG_SCOPE;
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;
gIR = 0;
irs->dmodule = 0;
}
// Put out instance of ModuleInfo for this Module
@ -880,7 +765,8 @@ static void genModuleInfo(Module *m)
RTTIBuilder b(Module::moduleinfo);
// 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();
// importedModules[]
@ -890,21 +776,15 @@ static void genModuleInfo(Module *m)
for (size_t i = 0; i < m->aimports.dim; i++)
{
Module *mod = static_cast<Module *>(m->aimports.data[i]);
if (!mod->needModuleInfo() || mod == m)
continue;
if (!mod->needModuleInfo() || mod == m) continue;
// declare the imported module info
std::string m_name("_D");
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);
importInits.push_back(
DtoBitCast(getIrModule(mod)->moduleInfoSymbol(), moduleInfoPtrTy));
}
// has import array?
if (!importInits.empty())
{
importedModulesTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size());
importedModulesTy = llvm::ArrayType::get(moduleInfoPtrTy, importInits.size());
importedModules = LLConstantArray::get(importedModulesTy, importInits);
}
@ -958,11 +838,11 @@ static void genModuleInfo(Module *m)
#define MIlocalClasses 0x800
#define MInew 0x80000000 // it's the "new" layout
llvm::Function* fsharedctor = build_module_shared_ctor();
llvm::Function* fshareddtor = build_module_shared_dtor();
llvm::Function* funittest = build_module_unittest();
llvm::Function* fctor = build_module_ctor();
llvm::Function* fdtor = build_module_dtor();
llvm::Function* fsharedctor = build_module_shared_ctor(m);
llvm::Function* fshareddtor = build_module_shared_dtor(m);
llvm::Function* funittest = build_module_unittest(m);
llvm::Function* fctor = build_module_ctor(m);
llvm::Function* fdtor = build_module_dtor(m);
unsigned flags = MInew;
if (fctor)
@ -1025,15 +905,15 @@ static void genModuleInfo(Module *m)
b.push(toConstantArray(it, at, name, len, false));
// create and set initializer
LLGlobalVariable *moduleInfoSym = m->moduleInfoSymbol();
LLGlobalVariable *moduleInfoSym = getIrModule(m)->moduleInfoSymbol();
b.finalize(moduleInfoSym->getType()->getPointerElementType(), moduleInfoSym);
moduleInfoSym->setLinkage(llvm::GlobalValue::ExternalLinkage);
if (global.params.isLinux) {
build_dso_registry_calls(moduleInfoSym);
build_dso_registry_calls(mangle(m), moduleInfoSym);
} else {
// 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);
}
}

View file

@ -243,7 +243,7 @@ void DtoDefineNakedFunction(FuncDeclaration* fd)
asmstr << "\t.size\t" << mangle << ", .-" << mangle << std::endl << std::endl;
}
gIR->module->appendModuleInlineAsm(asmstr.str());
gIR->module.appendModuleInlineAsm(asmstr.str());
asmstr.str("");
gIR->functions.pop_back();

View file

@ -87,7 +87,7 @@ void RTTIBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* ma
initname.append(".rtti.voidarr.data");
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());
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");
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());
push_array(dim, DtoBitCast(G, DtoType(valtype->pointerTo())));

View file

@ -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);
@ -137,7 +137,7 @@ llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target,
LLVM_D_InitRuntime();
}
LLFunction* fn = target->getFunction(name);
LLFunction* fn = target.getFunction(name);
if (fn)
return fn;
@ -145,7 +145,7 @@ llvm::Function* LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module* target,
assert(fn && "Runtime function not found.");
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->setCallingConv(fn->getCallingConv());
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) {
return gv;
}
@ -174,7 +174,7 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(Loc& loc, llvm::Module* target, co
}
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());
}

View file

@ -28,9 +28,9 @@ struct Loc;
bool LLVM_D_InitRuntime();
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 _adCmp "_adCmp2"

View file

@ -1209,7 +1209,7 @@ public:
LLType* elemTy = DtoType(stmt->condition->type);
LLArrayType* arrTy = llvm::ArrayType::get(elemTy, inits.size());
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);
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");
LLValue *moduleInfoSymbol = gIR->func()->decl->getModule()->moduleInfoSymbol();
LLValue *moduleInfoSymbol = getIrModule(gIR->func()->decl->getModule())->moduleInfoSymbol();
LLType *moduleInfoType = DtoType(Module::moduleinfo->type);
LLValue* args[] = {

View file

@ -218,7 +218,7 @@ static LLValue* getTypeinfoArrayArgumentForDVarArg(Expressions* arguments, int b
LLArrayType* typeinfoarraytype = LLArrayType::get(typeinfotype, numVariadicArgs);
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';
std::vector<LLConstant*> vtypeinfos;
@ -239,7 +239,7 @@ static LLValue* getTypeinfoArrayArgumentForDVarArg(Expressions* arguments, int b
};
LLType* tiarrty = DtoType(Type::dtypeinfo->type->arrayOf());
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");
return DtoLoad(typeinfoarrayparam);

View file

@ -214,7 +214,7 @@ public:
if (gvar == 0)
{
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);
(*stringLiteralCache)[key] = gvar;
}
@ -490,7 +490,7 @@ public:
return;
}
se->globalVar = new llvm::GlobalVariable(*p->module,
se->globalVar = new llvm::GlobalVariable(p->module,
DtoType(e->e1->type), false, llvm::GlobalValue::InternalLinkage, 0,
".structliteral");
@ -498,7 +498,7 @@ public:
if (constValue->getType() != se->globalVar->getType()->getContainedType(0))
{
llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable(
*p->module, constValue->getType(), false,
p->module, constValue->getType(), false,
llvm::GlobalValue::InternalLinkage, 0, ".structliteral");
se->globalVar->replaceAllUsesWith(
DtoBitCast(finalGlobalVar, se->globalVar->getType()));
@ -589,7 +589,7 @@ public:
}
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,
".dynarrayStorage");
gvar->setUnnamedAddr(canBeConst);
@ -670,7 +670,7 @@ public:
}
else
{
value->globalVar = new llvm::GlobalVariable(*p->module,
value->globalVar = new llvm::GlobalVariable(p->module,
origClass->type->ctype->isClass()->getMemoryLLType(),
false, llvm::GlobalValue::InternalLinkage, 0, ".classref");
@ -713,7 +713,7 @@ public:
if (constValue->getType() != value->globalVar->getType()->getContainedType(0))
{
llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable(
*p->module, constValue->getType(), false,
p->module, constValue->getType(), false,
llvm::GlobalValue::InternalLinkage, 0, ".classref");
value->globalVar->replaceAllUsesWith(
DtoBitCast(finalGlobalVar, value->globalVar->getType()));

View file

@ -410,7 +410,7 @@ public:
Logger::cout() << "type: " << *at << '\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);
(*stringLiteralCache)[key] = gvar;
}
@ -2714,7 +2714,7 @@ public:
{
llvm::Constant* init = arrayLiteralToConst(p, e);
llvm::GlobalVariable* global = new llvm::GlobalVariable(
*gIR->module,
gIR->module,
init->getType(),
true,
llvm::GlobalValue::InternalLinkage,
@ -2904,7 +2904,7 @@ public:
LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
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");
#if LDC_LLVM_VER >= 307
LLConstant* slice = llvm::ConstantExpr::getGetElementPtr(isaPointer(globalstore)->getElementType(), globalstore, idxs, true);
@ -2915,7 +2915,7 @@ public:
LLValue* keysArray = DtoAggrPaint(slice, funcTy->getParamType(1));
initval = arrayConst(valuesInits, vtype);
globalstore = new LLGlobalVariable(*gIR->module, initval->getType(),
globalstore = new LLGlobalVariable(gIR->module, initval->getType(),
false, LLGlobalValue::InternalLinkage, initval, ".aaValuesStorage");
#if LDC_LLVM_VER >= 307
slice = llvm::ConstantExpr::getGetElementPtr(isaPointer(globalstore)->getElementType(), globalstore, idxs, true);

View file

@ -409,13 +409,13 @@ LLValue* DtoMemCmp(LLValue* lhs, LLValue* rhs, LLValue* nbytes)
// int memcmp ( const void * ptr1, const void * ptr2, size_t num );
LLType* VoidPtrTy = getVoidPtrType();
LLFunction* fn = gIR->module->getFunction("memcmp");
LLFunction* fn = gIR->module.getFunction("memcmp");
if (!fn)
{
LLType* Tys[] = { VoidPtrTy, VoidPtrTy, DtoSize_t() };
LLFunctionType* fty = LLFunctionType::get(LLType::getInt32Ty(gIR->context()),
Tys, false);
fn = LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, "memcmp", gIR->module);
fn = LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, "memcmp", &gIR->module);
}
lhs = DtoBitCast(lhs, VoidPtrTy);
@ -508,7 +508,7 @@ LLConstant* DtoConstString(const char* str)
if (gvar == 0)
{
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");
gvar->setUnnamedAddr(true);
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()
{
if (gIR->mutexType)

View file

@ -60,7 +60,6 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym);
// some types
LLIntegerType* DtoSize_t();
LLStructType* DtoInterfaceInfoType();
LLStructType* DtoMutexType();
LLStructType* DtoModuleReferenceType();

View file

@ -194,7 +194,7 @@ static void emitTypeMetadata(TypeInfoDeclaration *tid)
// Add some metadata for use by optimization passes.
std::string metaname(TD_PREFIX);
metaname += mangle(tid);
llvm::NamedMDNode* meta = gIR->module->getNamedMetadata(metaname);
llvm::NamedMDNode* meta = gIR->module.getNamedMetadata(metaname);
if (!meta) {
// Construct the fields
@ -209,7 +209,7 @@ static void emitTypeMetadata(TypeInfoDeclaration *tid)
#endif
// 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(),
llvm::makeArrayRef(mdVals, TD_NumFields)));
}
@ -674,7 +674,7 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState* p)
}
IrGlobal* irg = getIrGlobal(decl, true);
irg->value = gIR->module->getGlobalVariable(mangled);
irg->value = gIR->module.getGlobalVariable(mangled);
if (irg->value) {
irg->type = irg->value->getType()->getContainedType(0);
assert(irg->type->isStructTy());
@ -683,7 +683,7 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState* p)
irg->type = Type::dtypeinfo->type->ctype->isClass()->getMemoryLLType();
else
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);
}

View file

@ -55,7 +55,7 @@ LLGlobalVariable * IrAggr::getInitSymbol()
initname.append("6__initZ");
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
init->setAlignment(type->alignsize());

View file

@ -55,7 +55,7 @@ LLGlobalVariable * IrAggr::getVtblSymbol()
LLType* vtblTy = stripModifiers(type)->ctype->isClass()->getVtbl();
vtbl = getOrCreateGlobal(aggrdecl->loc,
*gIR->module, vtblTy, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);
gIR->module, vtblTy, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);
return vtbl;
}
@ -86,7 +86,7 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol()
// classinfos cannot be constants since they're used as locks for synchronized
classInfo = getOrCreateGlobal(aggrdecl->loc,
*gIR->module, tc->getMemoryLLType(), false,
gIR->module, tc->getMemoryLLType(), false,
llvm::GlobalValue::ExternalLinkage, NULL, initname);
// Generate some metadata on this ClassInfo if it's for a class.
@ -111,7 +111,7 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol()
#endif
// Construct the metadata and insert it into the module.
llvm::SmallString<64> name;
llvm::NamedMDNode* node = gIR->module->getOrInsertNamedMetadata(
llvm::NamedMDNode* node = gIR->module.getOrInsertNamedMetadata(
llvm::Twine(CD_PREFIX, initname).toStringRef(name));
node->addOperand(llvm::MDNode::get(gIR->context(),
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 emit the initializer later.
classInterfacesArray = getOrCreateGlobal(cd->loc, *gIR->module,
classInterfacesArray = getOrCreateGlobal(cd->loc, gIR->module,
array_type, true, llvm::GlobalValue::ExternalLinkage, NULL, name);
return classInterfacesArray;
@ -349,7 +349,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance
name.printf("%i", b->offset);
name.writestring(mangleExact(fd));
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
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");
llvm::GlobalVariable* GV = getOrCreateGlobal(cd->loc,
*gIR->module,
gIR->module,
vtbl_constant->getType(),
true,
DtoLinkage(cd),

View file

@ -14,29 +14,33 @@
#include "ir/irdsymbol.h"
#include "ir/irmodule.h"
IrModule::IrModule(Module* module, const char* srcfilename)
{
M = module;
IrModule::IrModule(Module *module, const char *srcfilename)
: M(module), moduleInfoVar_(0) {}
LLConstant* slice = DtoConstString(srcfilename);
fileName = new llvm::GlobalVariable(
*gIR->module, slice->getType(), true, LLGlobalValue::InternalLinkage, slice, ".modulefilename");
IrModule::~IrModule() {}
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");
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.m_type = IrDsymbol::ModuleType;
}
assert(m->ir.m_type == IrDsymbol::ModuleType);
return m->ir.irModule;
}

View file

@ -7,8 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
// Represents the state of a D module on its way through code generation. Also
// see the TODO in gen/module.cpp parts of IRState really belong here.
// Represents the state of a D module on its way through code generation.
//
//===----------------------------------------------------------------------===//
@ -16,19 +15,31 @@
#define LDC_IR_IRMODULE_H
class Module;
namespace llvm
{
class GlobalVariable;
namespace llvm {
class GlobalVariable;
}
struct IrModule
{
IrModule(Module* module, const char* srcfilename);
struct IrModule {
IrModule(Module *module, const char *srcfilename);
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);