Merge pull request #507 from klickverbot/issue-454

Use Module::members -> Dsymbol::codegen to define symbols.
This commit is contained in:
David Nadlinger
2013-10-13 12:16:16 -07:00
42 changed files with 522 additions and 1016 deletions

View File

@@ -209,7 +209,7 @@ struct StructDeclaration : AggregateDeclaration
StructDeclaration *isStructDeclaration() { return this; }
#if IN_LLVM
void codegen(Ir*);
void codegen(IRState*);
#endif
};
@@ -337,7 +337,7 @@ struct ClassDeclaration : AggregateDeclaration
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
#if IN_LLVM
virtual void codegen(Ir*);
virtual void codegen(IRState*);
#endif
};
@@ -367,7 +367,7 @@ struct InterfaceDeclaration : ClassDeclaration
InterfaceDeclaration *isInterfaceDeclaration() { return this; }
#if IN_LLVM
void codegen(Ir*);
void codegen(IRState*);
#endif
};

View File

@@ -63,7 +63,7 @@ struct AttribDeclaration : Dsymbol
#endif
#if IN_LLVM
virtual void codegen(Ir*);
void codegen(IRState*);
#endif
};
@@ -161,7 +161,7 @@ struct PragmaDeclaration : AttribDeclaration
#endif
#if IN_LLVM
void codegen(Ir*);
void codegen(IRState*);
#endif
};

View File

@@ -189,11 +189,6 @@ struct Declaration : Dsymbol
enum PROT prot();
Declaration *isDeclaration() { return this; }
#if IN_LLVM
/// Codegen traversal
virtual void codegen(Ir* ir);
#endif
};
/**************************************************************/
@@ -216,7 +211,7 @@ struct TupleDeclaration : Declaration
#if IN_LLVM
void semantic3(Scope *sc);
/// Codegen traversal
void codegen(Ir* ir);
void codegen(IRState* ir);
#endif
};
@@ -256,7 +251,7 @@ struct TypedefDeclaration : Declaration
#if IN_LLVM
/// Codegen traversal
void codegen(Ir* ir);
void codegen(IRState* ir);
#endif
};
@@ -362,7 +357,7 @@ struct VarDeclaration : Declaration
#if IN_LLVM
/// Codegen traversal
virtual void codegen(Ir* ir);
void codegen(IRState* ir);
/// Index into parent aggregate.
/// Set during type generation.
@@ -455,7 +450,7 @@ struct TypeInfoDeclaration : VarDeclaration
#if IN_LLVM
/// Codegen traversal
void codegen(Ir* ir);
void codegen(IRState* ir);
virtual void llvmDefine();
#endif
};
@@ -483,7 +478,11 @@ struct TypeInfoClassDeclaration : TypeInfoDeclaration
#endif
#if IN_LLVM
void codegen(Ir*);
// TypeInfoClassDeclaration instances are different; they describe
// __ClassZ/__InterfaceZ symbols instead of a TypeInfo_….init one. DMD also
// generates them for SomeInterface.classinfo access, so we can't just
// distinguish between them using tinfo and thus need to override codegen().
void codegen(IRState* ir);
void llvmDefine();
#endif
};
@@ -819,7 +818,9 @@ struct FuncDeclaration : Declaration
// functions
FuncDeclarations siblingCallers; // Sibling nested functions which
// called this one
#if IN_DMD
FuncDeclarations deferred; // toObjFile() these functions after this one
#endif
unsigned flags;
#define FUNCFLAGpurityInprocess 1 // working on determining purity
@@ -918,7 +919,7 @@ struct FuncDeclaration : Declaration
IrFuncTy irFty;
/// Codegen traversal
void codegen(Ir* ir);
void codegen(IRState* ir);
// vars declared in this function that nested funcs reference
// is this is not empty, nestedFrameRef is set and these VarDecls

View File

@@ -95,7 +95,7 @@ struct TYPE;
#endif
#if IN_LLVM
class Ir;
class IRState;
namespace llvm
{
class Value;
@@ -287,7 +287,7 @@ struct Dsymbol : Object
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
/// Codegen traversal
virtual void codegen(Ir* ir);
virtual void codegen(IRState* p);
// llvm stuff
int llvmInternal;

View File

@@ -76,7 +76,7 @@ struct EnumDeclaration : ScopeDsymbol
#endif
#if IN_LLVM
void codegen(Ir*);
void codegen(IRState*);
#endif
};

View File

@@ -4735,11 +4735,7 @@ void UnitTestDeclaration::semantic(Scope *sc)
{ sc = scope;
scope = NULL;
}
#if IN_LLVM
if (global.params.useUnitTests && sc->module->isRoot)
#else
if (global.params.useUnitTests)
#endif
{
if (!type)
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);

View File

@@ -1,202 +0,0 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#include <stdio.h>
#include "mars.h"
#include "mtype.h"
#include "declaration.h"
#include "irstate.h"
#include "statement.h"
IRState::IRState(IRState *irs, Statement *s)
{
prev = irs;
statement = s;
symbol = NULL;
breakBlock = NULL;
contBlock = NULL;
switchBlock = NULL;
defaultBlock = NULL;
ident = NULL;
ehidden = NULL;
startaddress = NULL;
if (irs)
{
m = irs->m;
shidden = irs->shidden;
sclosure = irs->sclosure;
sthis = irs->sthis;
blx = irs->blx;
deferToObj = irs->deferToObj;
varsInScope = irs->varsInScope;
}
else
{
m = NULL;
shidden = NULL;
sclosure = NULL;
sthis = NULL;
blx = NULL;
deferToObj = NULL;
varsInScope = NULL;
}
}
IRState::IRState(IRState *irs, Dsymbol *s)
{
prev = irs;
statement = NULL;
symbol = s;
breakBlock = NULL;
contBlock = NULL;
switchBlock = NULL;
defaultBlock = NULL;
ident = NULL;
ehidden = NULL;
startaddress = NULL;
if (irs)
{
m = irs->m;
shidden = irs->shidden;
sclosure = irs->sclosure;
sthis = irs->sthis;
blx = irs->blx;
deferToObj = irs->deferToObj;
varsInScope = irs->varsInScope;
}
else
{
m = NULL;
shidden = NULL;
sclosure = NULL;
sthis = NULL;
blx = NULL;
deferToObj = NULL;
varsInScope = NULL;
}
}
IRState::IRState(Module *m, Dsymbol *s)
{
prev = NULL;
statement = NULL;
this->m = m;
symbol = s;
breakBlock = NULL;
contBlock = NULL;
switchBlock = NULL;
defaultBlock = NULL;
ident = NULL;
ehidden = NULL;
shidden = NULL;
sclosure = NULL;
sthis = NULL;
blx = NULL;
deferToObj = NULL;
startaddress = NULL;
varsInScope = NULL;
}
block *IRState::getBreakBlock(Identifier *ident)
{
IRState *bc;
if (ident) {
Statement *related = NULL;
block *ret = NULL;
for (bc = this; bc; bc = bc->prev) {
// The label for a breakBlock may actually be some levels up (e.g.
// on a try/finally wrapping a loop). We'll see if this breakBlock
// is the one to return once we reach that outer statement (which
// in many cases will be this same statement).
if (bc->breakBlock) {
related = bc->statement->getRelatedLabeled();
ret = bc->breakBlock;
}
if (bc->statement == related && bc->prev->ident == ident)
return ret;
}
} else {
for (bc = this; bc; bc = bc->prev) {
if (bc->breakBlock)
return bc->breakBlock;
}
}
return NULL;
}
block *IRState::getContBlock(Identifier *ident)
{
IRState *bc;
for (bc = this; bc; bc = bc->prev)
{
if (ident)
{
if (bc->prev && bc->prev->ident == ident)
return bc->contBlock;
}
else if (bc->contBlock)
return bc->contBlock;
}
return NULL;
}
block *IRState::getSwitchBlock()
{
IRState *bc;
for (bc = this; bc; bc = bc->prev)
{
if (bc->switchBlock)
return bc->switchBlock;
}
return NULL;
}
block *IRState::getDefaultBlock()
{
IRState *bc;
for (bc = this; bc; bc = bc->prev)
{
if (bc->defaultBlock)
return bc->defaultBlock;
}
return NULL;
}
FuncDeclaration *IRState::getFunc()
{
IRState *bc;
for (bc = this; bc->prev; bc = bc->prev)
{
}
return (FuncDeclaration *)(bc->symbol);
}
/**********************
* Return !=0 if do array bounds checking
*/
int IRState::arrayBoundsCheck()
{
int result = global.params.useArrayBounds;
if (result == 1)
{ // For safe functions only
result = 0;
FuncDeclaration *fd = getFunc();
if (fd)
{ Type *t = fd->type;
if (t->ty == Tfunction && ((TypeFunction *)t)->trust == TRUSTsafe)
result = 1;
}
}
return result;
}

View File

@@ -1,64 +0,0 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#ifndef DMD_CONTEXT_H
#define DMD_CONTEXT_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
struct Module;
struct Statement;
struct block;
struct Dsymbol;
struct Identifier;
struct Symbol;
struct FuncDeclaration;
struct Blockx;
#if IN_LLVM
class DValue;
typedef DValue elem;
#else
struct elem;
#endif
#include "arraytypes.h"
struct IRState
{
IRState *prev;
Statement *statement;
Module *m; // module
Dsymbol *symbol;
Identifier *ident;
Symbol *shidden; // hidden parameter to function
Symbol *sthis; // 'this' parameter to function (member and nested)
Symbol *sclosure; // pointer to closure instance
Blockx *blx;
Dsymbols *deferToObj; // array of Dsymbol's to run toObjFile(int multiobj) on later
elem *ehidden; // transmit hidden pointer to CallExp::toElem()
Symbol *startaddress;
VarDeclarations *varsInScope; // variables that are in scope that will need destruction later
block *breakBlock;
block *contBlock;
block *switchBlock;
block *defaultBlock;
IRState(IRState *irs, Statement *s);
IRState(IRState *irs, Dsymbol *s);
IRState(Module *m, Dsymbol *s);
block *getBreakBlock(Identifier *ident);
block *getContBlock(Identifier *ident);
block *getSwitchBlock();
block *getDefaultBlock();
FuncDeclaration *getFunc();
int arrayBoundsCheck();
};
#endif /* DMD_CONTEXT_H */

View File

@@ -28,7 +28,6 @@ class Library;
// Back end
#if IN_LLVM
class Ir;
class DValue;
typedef DValue elem;
namespace llvm {
@@ -196,7 +195,7 @@ struct Module : Package
#if IN_LLVM
// LDC
llvm::Module* genLLVMModule(llvm::LLVMContext& context, Ir* sir);
llvm::Module* genLLVMModule(llvm::LLVMContext& context);
void buildTargetFiles(bool singleObj);
File* buildFilePath(const char* forcename, const char* path, const char* ext);
Module *isModule() { return this; }

View File

@@ -50,9 +50,6 @@
#include "aggregate.h"
#include "hdrgen.h"
#if IN_LLVM
Ir* Type::sir = NULL;
#endif
FuncDeclaration *hasThis(Scope *sc);
@@ -197,11 +194,7 @@ char Type::needThisPrefix()
return 'M'; // name mangling prefix for functions needing 'this'
}
#if IN_LLVM
void Type::init(Ir* _sir)
#else
void Type::init()
#endif
{
stringtable._init(1543);
Lexer::initKeywords();
@@ -353,10 +346,6 @@ void Type::init()
Tptrdiff_t = Tint32;
}
#if IN_LLVM
sir = _sir;
#endif
tsize_t = basic[Tsize_t];
tptrdiff_t = basic[Tptrdiff_t];
thash_t = tsize_t;

View File

@@ -24,7 +24,6 @@
#if IN_LLVM
#include "../ir/irfuncty.h"
namespace llvm { class Type; }
class Ir;
class IrType;
#endif
@@ -247,11 +246,7 @@ struct Type : Object
int covariant(Type *t, StorageClass *pstc = NULL);
char *toChars();
static char needThisPrefix();
#if IN_LLVM
static void init(Ir*);
#else
static void init();
#endif
#define SIZE_INVALID (~(d_uns64)0)
d_uns64 size();
@@ -371,7 +366,6 @@ struct Type : Object
virtual TypeBasic *isTypeBasic();
#if IN_LLVM
static Ir* sir;
IrType* irtype;
#endif
};

View File

@@ -356,7 +356,7 @@ struct TemplateInstance : ScopeDsymbol
bool ignore; // true if the instance must be ignored when codegen'ing
Module* emittedInModule; // which module this template instance has been emitted in
void codegen(Ir*);
void codegen(IRState*);
#endif
};
@@ -386,7 +386,7 @@ struct TemplateMixin : TemplateInstance
TemplateMixin *isTemplateMixin() { return this; }
#if IN_LLVM
void codegen(Ir*);
void codegen(IRState*);
#endif
};

View File

@@ -614,9 +614,6 @@ int main(int argc, char **argv)
if (global.errors)
fatal();
// create a proper target
Ir ir;
// Set up the TargetMachine.
ExplicitBitness::Type bitness = ExplicitBitness::None;
if ((m32bits || m64bits) && (!mArch.empty() || !mTargetTriple.empty()))
@@ -669,7 +666,7 @@ int main(int argc, char **argv)
}
// Initialization
Type::init(&ir);
Type::init();
Id::initialize();
Module::init();
Target::init();
@@ -987,7 +984,7 @@ int main(int argc, char **argv)
printf("code %s\n", m->toChars());
if (global.params.obj)
{
llvm::Module* lm = m->genLLVMModule(context, &ir);
llvm::Module* lm = m->genLLVMModule(context);
if (!singleObj)
{
m->deleteObjFile();

View File

@@ -867,14 +867,6 @@ static LLValue* DtoArrayEqCmp_impl(Loc& loc, const char* func, DValue* l, DValue
if (useti) {
Type* t = l->getType();
LLValue* tival = DtoTypeInfoOf(t);
// DtoTypeInfoOf only does declare, not enough in this case :/
t->vtinfo->codegen(Type::sir);
#if 0
if (Logger::enabled())
Logger::cout() << "typeinfo decl: " << *tival << '\n';
#endif
args.push_back(DtoBitCast(tival, fn->getFunctionType()->getParamType(2)));
}

View File

@@ -35,24 +35,21 @@
void DtoResolveClass(ClassDeclaration* cd)
{
// make sure the base classes are processed first
ArrayIter<BaseClass> base_iter(cd->baseclasses);
while (base_iter.more())
{
BaseClass* bc = base_iter.get();
if (bc)
{
bc->base->codegen(Type::sir);
}
base_iter.next();
}
if (cd->ir.resolved) return;
cd->ir.resolved = true;
Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
LOG_SCOPE;
// make sure the base classes are processed first
ArrayIter<BaseClass> base_iter(cd->baseclasses);
while (base_iter.more())
{
BaseClass* bc = base_iter.get();
DtoResolveClass(bc->base);
base_iter.next();
}
// make sure type exists
DtoType(cd->type);
@@ -73,11 +70,6 @@ void DtoResolveClass(ClassDeclaration* cd)
}
}
bool needs_def = mustDefineSymbol(cd);
// emit the ClassZ symbol
LLGlobalVariable* ClassZ = irAggr->getClassInfoSymbol();
// emit the interfaceInfosZ symbol if necessary
if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0)
irAggr->getInterfaceArraySymbol(); // initializer is applied when it's built
@@ -87,43 +79,6 @@ void DtoResolveClass(ClassDeclaration* cd)
{
irAggr->initializeInterface();
}
else
{
// emit the initZ symbol
LLGlobalVariable* initZ = irAggr->getInitSymbol();
// emit the vtblZ symbol
LLGlobalVariable* vtblZ = irAggr->getVtblSymbol();
// perform definition
if (needs_def)
{
// set symbol initializers
initZ->setInitializer(irAggr->getDefaultInit());
vtblZ->setInitializer(irAggr->getVtblInit());
}
}
// emit members
if (cd->members)
{
ArrayIter<Dsymbol> it(*cd->members);
while (!it.done())
{
Dsymbol* member = it.get();
if (member)
member->codegen(Type::sir);
it.next();
}
}
if (needs_def)
{
// emit typeinfo
DtoTypeInfoOf(cd->type);
// define classinfo
ClassZ->setInitializer(irAggr->getClassInfoInit());
}
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -131,7 +86,7 @@ void DtoResolveClass(ClassDeclaration* cd)
DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
{
// resolve type
tc->sym->codegen(Type::sir);
DtoResolveClass(tc->sym);
// allocate
LLValue* mem;
@@ -143,7 +98,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
// custom allocator
else if (newexp->allocator)
{
newexp->allocator->codegen(Type::sir);
DtoResolveFunction(newexp->allocator);
DFuncValue dfn(newexp->allocator, newexp->allocator->ir.irFunc->func);
DValue* res = DtoCallFunction(newexp->loc, NULL, &dfn, newexp->newargs);
mem = DtoBitCast(res->getRVal(), DtoType(tc), ".newclass_custom");
@@ -184,7 +139,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
{
Logger::println("Calling constructor");
assert(newexp->arguments != NULL);
newexp->member->codegen(Type::sir);
DtoResolveFunction(newexp->member);
DFuncValue dfn(newexp->member, newexp->member->ir.irFunc->func, mem);
return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments);
}
@@ -197,7 +152,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
void DtoInitClass(TypeClass* tc, LLValue* dst)
{
tc->sym->codegen(Type::sir);
DtoResolveClass(tc->sym);
uint64_t n = tc->sym->structsize - Target::ptrsize * 2;
@@ -365,8 +320,8 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to)
// call:
// Object _d_dynamic_cast(Object o, ClassInfo c)
ClassDeclaration::object->codegen(Type::sir);
ClassDeclaration::classinfo->codegen(Type::sir);
DtoResolveClass(ClassDeclaration::object);
DtoResolveClass(ClassDeclaration::classinfo);
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
LLFunctionType* funcTy = func->getFunctionType();
@@ -378,7 +333,7 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to)
// ClassInfo c
TypeClass* to = static_cast<TypeClass*>(_to->toBasetype());
to->sym->codegen(Type::sir);
DtoResolveClass(to->sym);
LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol();
// unfortunately this is needed as the implementation of object differs somehow from the declaration
@@ -428,8 +383,8 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
// call:
// Object _d_interface_cast(void* p, ClassInfo c)
ClassDeclaration::object->codegen(Type::sir);
ClassDeclaration::classinfo->codegen(Type::sir);
DtoResolveClass(ClassDeclaration::object);
DtoResolveClass(ClassDeclaration::classinfo);
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast");
LLFunctionType* funcTy = func->getFunctionType();
@@ -440,7 +395,7 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
// ClassInfo c
TypeClass* to = static_cast<TypeClass*>(_to->toBasetype());
to->sym->codegen(Type::sir);
DtoResolveClass(to->sym);
LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol();
// unfortunately this is needed as the implementation of object differs somehow from the declaration
// this could happen in user code as well :/
@@ -623,7 +578,7 @@ static LLConstant* build_class_dtor(ClassDeclaration* cd)
if (!dtor)
return getNullPtr(getVoidPtrType());
dtor->codegen(Type::sir);
DtoResolveFunction(dtor);
return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::getInt8Ty(gIR->context())));
}

View File

@@ -14,73 +14,144 @@
#include "init.h"
#include "rmem.h"
#include "template.h"
#include "gen/classes.h"
#include "gen/functions.h"
#include "gen/irstate.h"
#include "gen/llvm.h"
#include "gen/llvmhelpers.h"
#include "gen/logger.h"
#include "gen/tollvm.h"
#include "ir/ir.h"
#include "gen/utils.h"
#include "ir/irtype.h"
#include "ir/irvar.h"
/* ================================================================== */
void Dsymbol::codegen(Ir*)
void Dsymbol::codegen(IRState *)
{
Logger::println("Ignoring Dsymbol::codegen for %s", toChars());
IF_LOG Logger::println("Ignoring Dsymbol::codegen for %s", toPrettyChars());
}
/* ================================================================== */
void Declaration::codegen(Ir*)
void InterfaceDeclaration::codegen(IRState *p)
{
Logger::println("Ignoring Declaration::codegen for %s", toChars());
}
IF_LOG Logger::println("InterfaceDeclaration::codegen: '%s'", toPrettyChars());
LOG_SCOPE
/* ================================================================== */
if (ir.defined) return;
ir.defined = true;
void InterfaceDeclaration::codegen(Ir*)
{
if (type->ty == Terror)
{ error("had semantic errors when compiling");
return;
}
if (members && symtab)
DtoResolveDsymbol(this);
{
DtoResolveClass(this);
// Emit any members (e.g. final functions).
for (ArrayIter<Dsymbol> it(members); !it.done(); it.next())
{
it->codegen(p);
}
// Emit TypeInfo.
DtoTypeInfoOf(type);
// Define __InterfaceZ.
llvm::GlobalVariable *interfaceZ = ir.irAggr->getClassInfoSymbol();
interfaceZ->setInitializer(ir.irAggr->getClassInfoInit());
interfaceZ->setLinkage(DtoExternalLinkage(this));
}
}
/* ================================================================== */
void StructDeclaration::codegen(Ir*)
void StructDeclaration::codegen(IRState *p)
{
IF_LOG Logger::println("StructDeclaration::codegen: '%s'", toPrettyChars());
LOG_SCOPE
if (ir.defined) return;
ir.defined = true;
if (type->ty == Terror)
{ error("had semantic errors when compiling");
return;
}
if (members && symtab)
DtoResolveDsymbol(this);
{
DtoResolveStruct(this);
for (ArrayIter<Dsymbol> it(members); !it.done(); it.next())
{
it->codegen(p);
}
// Define the __initZ symbol.
llvm::GlobalVariable *initZ = ir.irAggr->getInitSymbol();
initZ->setInitializer(ir.irAggr->getDefaultInit());
initZ->setLinkage(DtoExternalLinkage(this));
// emit typeinfo
DtoTypeInfoOf(type);
}
}
/* ================================================================== */
void ClassDeclaration::codegen(Ir*)
void ClassDeclaration::codegen(IRState *p)
{
IF_LOG Logger::println("ClassDeclaration::codegen: '%s'", toPrettyChars());
LOG_SCOPE
if (ir.defined) return;
ir.defined = true;
if (type->ty == Terror)
{ error("had semantic errors when compiling");
return;
}
if (members && symtab)
DtoResolveDsymbol(this);
{
DtoResolveClass(this);
for (ArrayIter<Dsymbol> it(members); !it.done(); it.next())
{
it->codegen(p);
}
llvm::GlobalValue::LinkageTypes const linkage = DtoExternalLinkage(this);
llvm::GlobalVariable *initZ = ir.irAggr->getInitSymbol();
initZ->setInitializer(ir.irAggr->getDefaultInit());
initZ->setLinkage(linkage);
llvm::GlobalVariable *vtbl = ir.irAggr->getVtblSymbol();
vtbl->setInitializer(ir.irAggr->getVtblInit());
vtbl->setLinkage(linkage);
llvm::GlobalVariable *classZ = ir.irAggr->getClassInfoSymbol();
classZ->setInitializer(ir.irAggr->getClassInfoInit());
classZ->setLinkage(linkage);
// No need to do TypeInfo here, it is <name>__classZ for classes in D2.
}
}
/* ================================================================== */
void TupleDeclaration::codegen(Ir* p)
void TupleDeclaration::codegen(IRState *p)
{
Logger::println("TupleDeclaration::codegen(): %s", toChars());
IF_LOG Logger::println("TupleDeclaration::codegen(): '%s'", toPrettyChars());
LOG_SCOPE
if (ir.defined) return;
ir.defined = true;
assert(isexp);
assert(objects);
@@ -97,16 +168,21 @@ void TupleDeclaration::codegen(Ir* p)
/* ================================================================== */
void VarDeclaration::codegen(Ir* p)
void VarDeclaration::codegen(IRState *p)
{
Logger::print("VarDeclaration::codegen(): %s | %s\n", toChars(), type->toChars());
IF_LOG Logger::println("VarDeclaration::codegen(): '%s'", toPrettyChars());
LOG_SCOPE;
if (ir.defined) return;
ir.defined = true;
if (type->ty == Terror)
{ error("had semantic errors when compiling");
return;
}
DtoResolveVariable(this);
// just forward aliases
if (aliassym)
{
@@ -115,10 +191,6 @@ void VarDeclaration::codegen(Ir* p)
return;
}
// output the parent aggregate first
if (AggregateDeclaration* ad = isMember())
ad->codegen(p);
// global variable
if (isDataseg() || (storage_class & (STCconst | STCimmutable) && init))
{
@@ -129,37 +201,14 @@ void VarDeclaration::codegen(Ir* p)
"manifest constant being codegen'd!");
#endif
// don't duplicate work
if (this->ir.resolved) return;
this->ir.resolved = true;
this->ir.declared = true;
llvm::GlobalVariable *gvar = llvm::cast<llvm::GlobalVariable>(
this->ir.irGlobal->value);
assert(gvar && "DtoResolveVariable should have created value");
this->ir.irGlobal = new IrGlobal(this);
Logger::println("parent: %s (%s)", parent->toChars(), parent->kind());
const bool isLLConst = isConst() && init;
const llvm::GlobalValue::LinkageTypes llLinkage = DtoLinkage(this);
assert(!ir.initialized);
ir.initialized = gIR->dmodule;
std::string llName(mangle());
// Since the type of a global must exactly match the type of its
// initializer, we cannot know the type until after we have emitted the
// latter (e.g. in case of unions, …). However, it is legal for the
// initializer to refer to the address of the variable. Thus, we first
// create a global with the generic type (note the assignment to
// this->ir.irGlobal->value!), and in case we also do an initializer
// with a different type later, swap it out and replace any existing
// uses with bitcasts to the previous type.
llvm::GlobalVariable* gvar = getOrCreateGlobal(loc, *gIR->module,
i1ToI8(DtoType(type)), isLLConst, llLinkage, 0, llName,
isThreadlocal());
this->ir.irGlobal->value = gvar;
// Check if we are defining or just declaring the global in this module.
if (!(storage_class & STCextern) && mustDefineSymbol(this))
if (!(storage_class & STCextern))
{
// Build the initializer. Might use this->ir.irGlobal->value!
LLConstant *initVal = DtoConstInitializer(loc, type, init);
@@ -168,10 +217,12 @@ void VarDeclaration::codegen(Ir* p)
if (initVal->getType() != gvar->getType()->getElementType())
{
llvm::GlobalVariable* newGvar = getOrCreateGlobal(loc,
*gIR->module, initVal->getType(), isLLConst, llLinkage, 0,
*p->module, initVal->getType(), gvar->isConstant(),
llLinkage, 0,
"", // We take on the name of the old global below.
isThreadlocal());
gvar->isThreadLocal());
newGvar->setAlignment(gvar->getAlignment());
newGvar->takeName(gvar);
llvm::Constant* newValue =
@@ -187,22 +238,17 @@ void VarDeclaration::codegen(Ir* p)
assert(!ir.irGlobal->constInit);
ir.irGlobal->constInit = initVal;
gvar->setInitializer(initVal);
gvar->setLinkage(llLinkage);
// Also set up the edbug info.
gIR->DBuilder.EmitGlobalVariable(gvar, this);
p->DBuilder.EmitGlobalVariable(gvar, this);
}
// Set the alignment (it is important not to use type->alignsize because
// VarDeclarations can have an align() attribute independent of the type
// as well).
if (alignment != STRUCTALIGN_DEFAULT)
gvar->setAlignment(alignment);
// If this global is used from a naked function, we need to create an
// artificial "use" for it, or it could be removed by the optimizer if
// the only reference to it is in inline asm.
if (nakedUse)
gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
p->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
if (Logger::enabled())
Logger::cout() << *gvar << '\n';
@@ -211,11 +257,14 @@ void VarDeclaration::codegen(Ir* p)
/* ================================================================== */
void TypedefDeclaration::codegen(Ir*)
void TypedefDeclaration::codegen(IRState *)
{
Logger::print("TypedefDeclaration::codegen: %s\n", toChars());
IF_LOG Logger::println("TypedefDeclaration::codegen: '%s'", toPrettyChars());
LOG_SCOPE;
if (ir.defined) return;
ir.defined = true;
if (type->ty == Terror)
{ error("had semantic errors when compiling");
return;
@@ -227,9 +276,9 @@ void TypedefDeclaration::codegen(Ir*)
/* ================================================================== */
void EnumDeclaration::codegen(Ir*)
void EnumDeclaration::codegen(IRState *)
{
Logger::println("Ignoring EnumDeclaration::codegen for %s", toChars());
IF_LOG Logger::println("Ignoring EnumDeclaration::codegen: '%s'", toPrettyChars());
if (type->ty == Terror)
{ error("had semantic errors when compiling");
@@ -239,54 +288,56 @@ void EnumDeclaration::codegen(Ir*)
/* ================================================================== */
void FuncDeclaration::codegen(Ir* p)
void FuncDeclaration::codegen(IRState *p)
{
// don't touch function aliases, they don't contribute any new symbols
if (!isFuncAliasDeclaration())
{
DtoResolveDsymbol(this);
DtoDefineFunction(this);
}
}
/* ================================================================== */
void TemplateInstance::codegen(Ir* p)
void TemplateInstance::codegen(IRState *p)
{
#if LOG
printf("TemplateInstance::codegen('%s', this = %p)\n", toChars(), this);
#endif
if (ignore)
return;
IF_LOG Logger::println("TemplateInstance::codegen: '%s'", toPrettyChars());
LOG_SCOPE
if (ir.defined) return;
ir.defined = true;
if (!errors && members)
{
for (unsigned i = 0; i < members->dim; i++)
{
Dsymbol *s = static_cast<Dsymbol *>(members->data[i]);
s->codegen(p);
(*members)[i]->codegen(p);
}
}
}
/* ================================================================== */
void TemplateMixin::codegen(Ir* p)
void TemplateMixin::codegen(IRState *p)
{
IF_LOG Logger::println("TemplateInstance::codegen: '%s'", toPrettyChars());
LOG_SCOPE
if (ir.defined) return;
ir.defined = true;
if (!errors && members)
{
for (unsigned i = 0; i < members->dim; i++)
{
Dsymbol *s = static_cast<Dsymbol *>(members->data[i]);
if (s->isVarDeclaration())
continue;
s->codegen(p);
(*members)[i]->codegen(p);
}
}
}
/* ================================================================== */
void AttribDeclaration::codegen(Ir* p)
void AttribDeclaration::codegen(IRState *p)
{
Array *d = include(NULL, NULL);
@@ -301,7 +352,7 @@ void AttribDeclaration::codegen(Ir* p)
/* ================================================================== */
void PragmaDeclaration::codegen(Ir* p)
void PragmaDeclaration::codegen(IRState *p)
{
if (ident == Id::lib)
{

View File

@@ -702,6 +702,12 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
Logger::println("DtoDeclareFunction(%s): %s", fdecl->toPrettyChars(), fdecl->loc.toChars());
LOG_SCOPE;
if (fdecl->isUnitTestDeclaration() && !global.params.useUnitTests)
{
Logger::println("unit tests not enabled");
return;
}
//printf("declare function: %s\n", fdecl->toPrettyChars());
// intrinsic sanity check
@@ -715,10 +721,6 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
TypeFunction* f = static_cast<TypeFunction*>(t);
IrFuncTy &irFty = fdecl->irFty;
bool declareOnly = !mustDefineSymbol(fdecl);
if (fdecl->llvmInternal == LLVMva_start)
declareOnly = true;
if (!fdecl->ir.irFunc) {
fdecl->ir.irFunc = new IrFunction(fdecl);
@@ -753,9 +755,16 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangledName);
if (!func) {
if(fdecl->llvmInternal == LLVMinline_ir)
{
func = DtoInlineIRFunction(fdecl);
}
else
func = LLFunction::Create(functype, DtoLinkage(fdecl), mangledName, gIR->module);
{
// 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);
}
} else if (func->getFunctionType() != functype) {
error(fdecl->loc, "Function type does not match previously declared function with the same mangled name: %s", fdecl->mangle());
}
@@ -792,35 +801,6 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
gIR->mainFunc = func;
}
// shared static ctor
if (fdecl->isSharedStaticCtorDeclaration()) {
if (mustDefineSymbol(fdecl)) {
gIR->sharedCtors.push_back(fdecl);
}
}
// shared static dtor
else if (StaticDtorDeclaration *dtorDecl = fdecl->isSharedStaticDtorDeclaration()) {
if (mustDefineSymbol(fdecl)) {
gIR->sharedDtors.push_front(fdecl);
if (dtorDecl->vgate)
gIR->sharedGates.push_front(dtorDecl->vgate);
}
} else
// static ctor
if (fdecl->isStaticCtorDeclaration()) {
if (mustDefineSymbol(fdecl)) {
gIR->ctors.push_back(fdecl);
}
}
// static dtor
else if (StaticDtorDeclaration *dtorDecl = fdecl->isStaticDtorDeclaration()) {
if (mustDefineSymbol(fdecl)) {
gIR->dtors.push_front(fdecl);
if (dtorDecl->vgate)
gIR->gates.push_front(dtorDecl->vgate);
}
}
if (fdecl->neverInline)
{
fdecl->ir.irFunc->setNeverInline();
@@ -909,14 +889,6 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
}
}
}
if (fdecl->isUnitTestDeclaration() && !declareOnly)
gIR->unitTests.push_back(fdecl);
if (!declareOnly)
Type::sir->addFunctionBody(fdecl->ir.irFunc);
else
assert(func->getLinkage() != llvm::GlobalValue::InternalLinkage);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -927,15 +899,37 @@ void DtoDefineFunction(FuncDeclaration* fd)
{
DtoDeclareFunction(fd);
if (fd->ir.defined) return;
fd->ir.defined = true;
assert(fd->ir.declared);
if (Logger::enabled())
Logger::println("DtoDefineFunc(%s): %s", fd->toPrettyChars(), fd->loc.toChars());
Logger::println("DtoDefineFunction(%s): %s", fd->toPrettyChars(), fd->loc.toChars());
LOG_SCOPE;
// Be sure to call DtoDeclareFunction first, as LDC_inline_asm functions are
// "defined" there. TODO: Clean this up.
if (fd->ir.defined) return;
fd->ir.defined = true;
if (fd->isUnitTestDeclaration()) {
if (global.params.useUnitTests)
gIR->unitTests.push_back(fd);
else
return;
} else if (fd->isSharedStaticCtorDeclaration()) {
gIR->sharedCtors.push_back(fd);
} else if (StaticDtorDeclaration *dtorDecl = fd->isSharedStaticDtorDeclaration()) {
gIR->sharedDtors.push_front(fd);
if (dtorDecl->vgate)
gIR->sharedGates.push_front(dtorDecl->vgate);
} else if (fd->isStaticCtorDeclaration()) {
gIR->ctors.push_back(fd);
} else if (StaticDtorDeclaration *dtorDecl = fd->isStaticDtorDeclaration()) {
gIR->dtors.push_front(fd);
if (dtorDecl->vgate)
gIR->gates.push_front(dtorDecl->vgate);
}
// if this function is naked, we take over right away! no standard processing!
if (fd->naked)
{
@@ -954,9 +948,6 @@ void DtoDefineFunction(FuncDeclaration* fd)
llvm::Function* func = fd->ir.irFunc->func;
// sanity check
assert(mustDefineSymbol(fd));
// set module owner
fd->ir.DModule = gIR->dmodule;
@@ -972,6 +963,8 @@ void DtoDefineFunction(FuncDeclaration* fd)
if (fd->isMain())
gIR->emitMain = true;
func->setLinkage(DtoLinkage(fd));
// On x86_64, always set 'uwtable' for System V ABI compatibility.
// TODO: Find a better place for this.
if (global.params.targetTriple.getArch() == llvm::Triple::x86_64)
@@ -1185,7 +1178,7 @@ llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl)
break;
}
DtoResolveDsymbol(f);
DtoResolveFunction(f);
return llvm::cast<llvm::FunctionType>(DtoType(f->type));
}

View File

@@ -737,10 +737,10 @@ DValue* DtoCastNull(Loc& loc, DValue* val, Type* to)
Type* totype = to->toBasetype();
LLType* tolltype = DtoType(to);
if (totype->ty == Tpointer)
if (totype->ty == Tpointer || totype->ty == Tclass)
{
if (Logger::enabled())
Logger::cout() << "cast null to pointer: " << *tolltype << '\n';
Logger::cout() << "cast null to pointer/class: " << *tolltype << '\n';
LLValue *rval = DtoBitCast(val->getRVal(), tolltype);
return new DImValue(to, rval);
}
@@ -1005,8 +1005,86 @@ void DtoResolveDsymbol(Dsymbol* dsym)
else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
DtoResolveTypeInfo(fd);
}
else {
llvm_unreachable("Unsupported DSymbol for DtoResolveDsymbol.");
else if (VarDeclaration* vd = dsym->isVarDeclaration()) {
DtoResolveVariable(vd);
}
}
void DtoResolveVariable(VarDeclaration* vd)
{
if (vd->isTypeInfoDeclaration())
return DtoResolveTypeInfo(static_cast<TypeInfoDeclaration *>(vd));
IF_LOG Logger::println("DtoResolveVariable(%s)", vd->toPrettyChars());
LOG_SCOPE;
// just forward aliases
// TODO: Is this required here or is the check in VarDeclaration::codegen
// sufficient?
if (vd->aliassym)
{
Logger::println("alias sym");
DtoResolveDsymbol(vd->aliassym);
return;
}
if (AggregateDeclaration* ad = vd->isMember())
DtoResolveDsymbol(ad);
// global variable
if (vd->isDataseg() || (vd->storage_class & (STCconst | STCimmutable) && vd->init))
{
Logger::println("data segment");
#if 0 // TODO:
assert(!(storage_class & STCmanifest) &&
"manifest constant being codegen'd!");
#endif
// don't duplicate work
if (vd->ir.resolved) return;
vd->ir.resolved = true;
vd->ir.declared = true;
vd->ir.irGlobal = new IrGlobal(vd);
IF_LOG {
if (vd->parent)
Logger::println("parent: %s (%s)", vd->parent->toChars(), vd->parent->kind());
else
Logger::println("parent: null");
}
const bool isLLConst = vd->isConst() && vd->init;
assert(!vd->ir.initialized);
vd->ir.initialized = gIR->dmodule;
std::string llName(vd->mangle());
// Since the type of a global must exactly match the type of its
// initializer, we cannot know the type until after we have emitted the
// latter (e.g. in case of unions, …). However, it is legal for the
// initializer to refer to the address of the variable. Thus, we first
// create a global with the generic type (note the assignment to
// vd->ir.irGlobal->value!), and in case we also do an initializer
// with a different type later, swap it out and replace any existing
// uses with bitcasts to the previous type.
//
// We always start out with external linkage; any other type is set
// when actually defining it in VarDeclaration::codegen.
llvm::GlobalVariable* gvar = getOrCreateGlobal(vd->loc, *gIR->module,
i1ToI8(DtoType(vd->type)), isLLConst, llvm::GlobalValue::ExternalLinkage,
0, llName, vd->isThreadlocal());
vd->ir.irGlobal->value = gvar;
// Set the alignment (it is important not to use type->alignsize because
// VarDeclarations can have an align() attribute independent of the type
// as well).
if (vd->alignment != STRUCTALIGN_DEFAULT)
gvar->setAlignment(vd->alignment);
if (Logger::enabled())
Logger::cout() << *gvar << '\n';
}
}
@@ -1132,7 +1210,7 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
// static
if (vd->isDataseg())
{
vd->codegen(Type::sir);
vd->codegen(gIR);
}
else
{
@@ -1144,19 +1222,19 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
else if (StructDeclaration* s = declaration->isStructDeclaration())
{
Logger::println("StructDeclaration");
s->codegen(Type::sir);
s->codegen(gIR);
}
// function declaration
else if (FuncDeclaration* f = declaration->isFuncDeclaration())
{
Logger::println("FuncDeclaration");
f->codegen(Type::sir);
f->codegen(gIR);
}
// class
else if (ClassDeclaration* e = declaration->isClassDeclaration())
{
Logger::println("ClassDeclaration");
e->codegen(Type::sir);
e->codegen(gIR);
}
// typedef
else if (TypedefDeclaration* tdef = declaration->isTypedefDeclaration())
@@ -1293,7 +1371,7 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
else if (StructInitializer* si = init->isStructInitializer())
{
Logger::println("const struct initializer");
si->ad->codegen(Type::sir);
DtoResolveDsymbol(si->ad);
return si->ad->ir.irAggr->createStructInitializer(si);
}
else if (ArrayInitializer* ai = init->isArrayInitializer())
@@ -1315,41 +1393,6 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
//////////////////////////////////////////////////////////////////////////////////////////
static LLConstant* expand_to_sarray(Type* targetType, Type* initType, LLConstant* initConst)
{
Type* expbase = stripModifiers(initType);
IF_LOG Logger::println("expbase: %s", expbase->toChars());
Type* t = targetType;
LLSmallVector<size_t, 4> dims;
while(1)
{
Logger::println("t: %s", t->toChars());
if (t->equals(expbase))
break;
assert(t->ty == Tsarray);
TypeSArray* tsa = static_cast<TypeSArray*>(t);
dims.push_back(tsa->dim->toInteger());
assert(t->nextOf());
t = stripModifiers(t->nextOf()->toBasetype());
}
size_t i = dims.size();
assert(i);
std::vector<LLConstant*> inits;
while (i--)
{
LLArrayType* arrty = LLArrayType::get(initConst->getType(), dims[i]);
inits.clear();
inits.insert(inits.end(), dims[i], initConst);
initConst = LLConstantArray::get(arrty, inits);
}
return initConst;
}
LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp)
{
IF_LOG Logger::println("DtoConstExpInit(targetType = %s, exp = %s)",
@@ -1374,7 +1417,6 @@ LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp)
if (expBase->equals(targetBase) && targetBase->ty != Tbool)
{
Logger::println("Matching D types, nothing left to do.");
return val;
}
@@ -1393,7 +1435,12 @@ LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp)
fatal();
}
Logger::println("Building constant array initializer to single value.");
return expand_to_sarray(targetBase, expBase, val);
d_uns64 elemCount = targetBase->size() / expBase->size();
assert(targetBase->size() % expBase->size() == 0);
std::vector<llvm::Constant*> initVals(elemCount, val);
return llvm::ConstantArray::get(llvm::ArrayType::get(llType, elemCount), initVals);
}
if (targetBase->ty == Tvector)
@@ -1428,11 +1475,14 @@ LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp)
LLConstant* DtoTypeInfoOf(Type* type, bool base)
{
IF_LOG Logger::println("DtoTypeInfoOf(type = '%s', base='%d')", type->toChars(), base);
LOG_SCOPE
type = type->merge2(); // needed.. getTypeInfo does the same
type->getTypeInfo(NULL);
TypeInfoDeclaration* tidecl = type->vtinfo;
assert(tidecl);
tidecl->codegen(Type::sir);
tidecl->codegen(gIR);
assert(tidecl->ir.irGlobal != NULL);
assert(tidecl->ir.irGlobal->value != NULL);
LLConstant* c = isaConstant(tidecl->ir.irGlobal->value);
@@ -1500,98 +1550,6 @@ void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, s
//////////////////////////////////////////////////////////////////////////////////////////
bool mustDefineSymbol(Dsymbol* s)
{
if (FuncDeclaration* fd = s->isFuncDeclaration())
{
// we can't (and probably shouldn't?) define functions
// that weren't semantic3'ed
if (fd->semanticRun < PASSsemantic3)
return false;
// If a function has no body, we cannot possibly emit it (and so it
// cannot be available_externally either).
if (!fd->fbody)
return false;
if (fd->isArrayOp == 1)
return true;
if (global.inExtraInliningSemantic && fd->availableExternally) {
// Emit extra functions if we're inlining.
// These will get available_externally linkage,
// so they shouldn't end up in object code.
assert(fd->type->ty == Tfunction);
// * If we define extra static constructors, static destructors
// and unittests they'll get registered to run, and we won't
// be calling them directly anyway.
// * If it's a large function, don't emit it unnecessarily.
// Use DMD's canInline() to determine whether it's large.
// inlineCost() members have been changed to pay less attention
// to DMDs limitations, but still have some issues. The most glaring
// offenders are any kind of control flow statements other than
// 'if' and 'return'.
if ( !fd->isStaticCtorDeclaration()
&& !fd->isStaticDtorDeclaration()
&& !fd->isUnitTestDeclaration()
&& fd->canInline(true, false, false))
{
return true;
}
// This was only semantic'ed for inlining checks.
// We won't be inlining this, so we only need to emit a declaration.
return false;
}
}
if (VarDeclaration* vd = s->isVarDeclaration())
{
// Never define 'extern' variables.
if (vd->storage_class & STCextern)
return false;
}
// Inlining checks may create some variable and class declarations
// we don't need to emit.
if (global.inExtraInliningSemantic)
{
if (VarDeclaration* vd = s->isVarDeclaration())
if (vd->availableExternally)
return false;
if (ClassDeclaration* cd = s->isClassDeclaration())
if (cd->availableExternally)
return false;
}
TemplateInstance* tinst = DtoIsTemplateInstance(s, true);
if (tinst)
{
if (!global.params.singleObj)
return true;
if (!tinst->emittedInModule)
{
gIR->seenTemplateInstances.insert(tinst);
tinst->emittedInModule = gIR->dmodule;
}
return tinst->emittedInModule == gIR->dmodule;
}
return s->getModule() == gIR->dmodule;
}
//////////////////////////////////////////////////////////////////////////////////////////
bool needsTemplateLinkage(Dsymbol* s)
{
return DtoIsTemplateInstance(s) && mustDefineSymbol(s);
}
//////////////////////////////////////////////////////////////////////////////////////////
bool hasUnalignedFields(Type* t)
{
t = t->toBasetype();
@@ -1732,7 +1690,7 @@ void callPostblit(Loc &loc, Expression *exp, LLValue *val)
FuncDeclaration *fd = sd->postblit;
if (fd->storage_class & STCdisable)
fd->toParent()->error(loc, "is not copyable because it is annotated with @disable");
fd->codegen(Type::sir);
DtoResolveFunction(fd);
Expressions args;
DFuncValue dfn(fd, fd->ir.irFunc->func, val);
DtoCallFunction(loc, Type::basic[Tvoid], &dfn, &args);
@@ -1865,14 +1823,14 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl)
else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration())
{
Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
cid->cd->codegen(Type::sir);;
DtoResolveClass(cid->cd);
return new DVarValue(type, vd, cid->cd->ir.irAggr->getClassInfoSymbol());
}
// typeinfo
else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
{
Logger::println("TypeInfoDeclaration");
tid->codegen(Type::sir);
DtoResolveTypeInfo(tid);
assert(tid->ir.getIrValue());
LLType* vartype = DtoType(type);
LLValue* m = tid->ir.getIrValue();
@@ -1921,7 +1879,7 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl)
// take care of forward references of global variables
const bool isGlobal = vd->isDataseg() || (vd->storage_class & STCextern);
if (isGlobal)
vd->codegen(Type::sir);
DtoResolveVariable(vd);
assert(vd->ir.isSet() && "Variable not resolved.");
@@ -1950,19 +1908,15 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl)
if (FuncDeclaration* fdecl = decl->isFuncDeclaration())
{
Logger::println("FuncDeclaration");
LLValue* func = 0;
fdecl = fdecl->toAliasFunc();
if (fdecl->llvmInternal == LLVMinline_asm)
{
// TODO: Is this needed? If so, what about other intrinsics?
error("special ldc inline asm is not a normal function");
fatal();
}
else if (fdecl->llvmInternal != LLVMva_arg)
{
fdecl->codegen(Type::sir);
func = fdecl->ir.irFunc->func;
}
return new DFuncValue(fdecl, func);
DtoResolveFunction(fdecl);
return new DFuncValue(fdecl, fdecl->ir.irFunc->func);
}
if (SymbolDeclaration* sdecl = decl->isSymbolDeclaration())
@@ -1973,7 +1927,7 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl)
assert(sdecltype->ty == Tstruct);
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
assert(ts->sym);
ts->sym->codegen(Type::sir);
DtoResolveStruct(ts->sym);
LLValue* initsym = ts->sym->ir.irAggr->getInitSymbol();
initsym = DtoBitCast(initsym, DtoType(ts->pointerTo()));
@@ -2009,7 +1963,7 @@ llvm::Constant* DtoConstSymbolAddress(const Loc& loc, Declaration* decl)
return NULL;
}
vd->codegen(Type::sir);
DtoResolveVariable(vd);
LLConstant* llc = llvm::dyn_cast<LLConstant>(vd->ir.getIrValue());
assert(llc);
return llc;
@@ -2017,7 +1971,7 @@ llvm::Constant* DtoConstSymbolAddress(const Loc& loc, Declaration* decl)
// static function
else if (FuncDeclaration* fd = decl->isFuncDeclaration())
{
fd->codegen(Type::sir);
DtoResolveFunction(fd);
IrFunction* irfunc = fd->ir.irFunc;
return irfunc->func;
}

View File

@@ -102,9 +102,15 @@ DValue* DtoPaintType(Loc& loc, DValue* val, Type* to);
// is template instance check, returns module where instantiated
TemplateInstance* DtoIsTemplateInstance(Dsymbol* s, bool checkLiteralOwner = false);
/// Generate code for the symbol.
/// Dispatches as appropriate.
/// Makes sure the declarations corresponding to the given D symbol have been
/// emitted to the currently processed LLVM module.
///
/// This means that dsym->ir can be expected to set to reasonable values.
///
/// This function does *not* emit any (function, variable) *definitions*; this
/// is done by Dsymbol::codegen.
void DtoResolveDsymbol(Dsymbol* dsym);
void DtoResolveVariable(VarDeclaration* var);
// declaration inside a declarationexp
void DtoVarDeclaration(VarDeclaration* var);
@@ -135,12 +141,6 @@ void findDefaultTarget();
/// Fixup an overloaded intrinsic name string.
void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name);
/// Returns true if the symbol should be defined in the current module, not just declared.
bool mustDefineSymbol(Dsymbol* s);
/// Returns true if the symbol needs template linkage, or just external.
bool needsTemplateLinkage(Dsymbol* s);
/// Returns true if there is any unaligned type inside the aggregate.
bool hasUnalignedFields(Type* t);

View File

@@ -326,7 +326,7 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
return ctor;
}
llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir)
llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context)
{
bool logenabled = Logger::enabled();
if (llvmForceLogging && !logenabled)
@@ -363,8 +363,6 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir)
// reset all IR data stored in Dsymbols
IrDsymbol::resetAll();
sir->setState(&ir);
// set target triple
ir.module->setTargetTriple(global.params.targetTriple.str());
@@ -395,12 +393,9 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir)
for (unsigned k=0; k < members->dim; k++) {
Dsymbol* dsym = static_cast<Dsymbol*>(members->data[k]);
assert(dsym);
dsym->codegen(sir);
dsym->codegen(&ir);
}
// emit function bodies
sir->emitFunctionBodies();
// for singleobj-compilation, fully emit all seen template instances
if (global.params.singleObj)
{
@@ -408,11 +403,8 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir)
{
IRState::TemplateInstanceSet::iterator it, end = ir.seenTemplateInstances.end();
for (it = ir.seenTemplateInstances.begin(); it != end; ++it)
(*it)->codegen(sir);
(*it)->codegen(&ir);
ir.seenTemplateInstances.clear();
// emit any newly added function bodies
sir->emitFunctionBodies();
}
}
@@ -432,8 +424,6 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir)
Logger::disable();
}
sir->setState(NULL);
return ir.module;
}
@@ -532,8 +522,8 @@ void Module::genmoduleinfo()
std::vector<LLConstant*> classInits;
for (size_t i = 0; i < aclasses.dim; i++)
{
ClassDeclaration* cd = static_cast<ClassDeclaration*>(aclasses.data[i]);
cd->codegen(Type::sir);
ClassDeclaration* cd = aclasses[i];
DtoResolveClass(cd);
if (cd->isInterfaceDeclaration())
{
@@ -638,6 +628,7 @@ void Module::genmoduleinfo()
// create and set initializer
LLGlobalVariable *moduleInfoSym = moduleInfoSymbol();
b.finalize(moduleInfoSym->getType()->getPointerElementType(), moduleInfoSym);
moduleInfoSym->setLinkage(llvm::GlobalValue::ExternalLinkage);
// build the modulereference and ctor for registering it
LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSym);

View File

@@ -85,7 +85,8 @@ void ExpStatement::toNakedIR(IRState *p)
// enum decls should always be safe
// make sure the symbols gets processed
d->declaration->codegen(Type::sir);
// TODO: codegen() here is likely incorrect
d->declaration->codegen(p);
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -11,6 +11,7 @@
#include "aggregate.h"
#include "mtype.h"
#include "gen/arrays.h"
#include "gen/functions.h"
#include "gen/irstate.h"
#include "gen/linkage.h"
#include "gen/llvm.h"
@@ -20,8 +21,7 @@
RTTIBuilder::RTTIBuilder(AggregateDeclaration* base_class)
{
// make sure the base typeinfo class has been processed
base_class->codegen(Type::sir);
DtoResolveDsymbol(base_class);
base = base_class;
basetype = static_cast<TypeClass*>(base->type);
@@ -136,7 +136,7 @@ void RTTIBuilder::push_funcptr(FuncDeclaration* fd, Type* castto)
{
if (fd)
{
fd->codegen(Type::sir);
DtoResolveFunction(fd);
LLConstant* F = fd->ir.irFunc->func;
if (castto)
F = DtoBitCast(F, DtoType(castto));
@@ -177,7 +177,9 @@ void RTTIBuilder::finalize(LLType* type, LLValue* value)
LLConstant* tiInit = LLConstantStruct::get(st, inits);
// set the initializer
isaGlobalVar(value)->setInitializer(tiInit);
llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(value);
gvar->setInitializer(tiInit);
gvar->setLinkage(TYPEINFO_LINKAGE_TYPE);
}
LLConstant* RTTIBuilder::get_constant(LLStructType *initType)

View File

@@ -55,32 +55,6 @@ void DtoResolveStruct(StructDeclaration* sd)
assert(!vd->ir.irField);
(void)new IrField(vd);
}
// perform definition
bool emitGlobalData = mustDefineSymbol(sd);
if (emitGlobalData)
{
// emit the initZ symbol
LLGlobalVariable* initZ = iraggr->getInitSymbol();
// set initZ initializer
initZ->setInitializer(iraggr->getDefaultInit());
}
// emit members
if (sd->members)
{
for (ArrayIter<Dsymbol> it(sd->members); !it.done(); it.next())
{
it.get()->codegen(Type::sir);
}
}
if (emitGlobalData)
{
// emit typeinfo
DtoTypeInfoOf(sd->type);
}
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -10,14 +10,10 @@
#include <assert.h>
#include "target.h"
#include "gen/irstate.h"
#include "mars.h"
#include "mtype.h"
unsigned GetTypeAlignment(Type* t);
unsigned GetPointerSize();
unsigned GetTypeStoreSize(Type* t);
unsigned GetTypeAllocSize(Type* t);
int Target::ptrsize;
int Target::realsize;
int Target::realpad;
@@ -25,10 +21,12 @@ int Target::realalignsize;
void Target::init()
{
ptrsize = GetPointerSize();
realsize = GetTypeAllocSize(Type::basic[Tfloat80]);
realpad = realsize - GetTypeStoreSize(Type::basic[Tfloat80]);
realalignsize = GetTypeAlignment(Type::basic[Tfloat80]);
ptrsize = gDataLayout->getPointerSize(ADDRESS_SPACE);
llvm::Type* real = DtoType(Type::basic[Tfloat80]);
realsize = gDataLayout->getTypeAllocSize(real);
realpad = realsize - gDataLayout->getTypeStoreSize(real);
realalignsize = gDataLayout->getABITypeAlignment(real);
}
/******************************
@@ -39,7 +37,7 @@ unsigned Target::alignsize (Type* type)
{
assert (type->isTypeBasic());
if (type->ty == Tvoid) return 1;
return GetTypeAlignment(type);
return gDataLayout->getABITypeAlignment(DtoType(type));
}
/******************************

View File

@@ -13,6 +13,7 @@
#include "id.h"
#include "init.h"
#include "mtype.h"
#include "module.h"
#include "port.h"
#include "rmem.h"
#include "template.h"
@@ -200,8 +201,7 @@ LLConstant* VarExp::toConstElem(IRState* p)
Logger::print("Sym: type=%s\n", sdecltype->toChars());
assert(sdecltype->ty == Tstruct);
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
ts->sym->codegen(Type::sir);
DtoResolveStruct(ts->sym);
return ts->sym->ir.irAggr->getDefaultInit();
}
@@ -1186,7 +1186,7 @@ LLConstant* CastExp::toConstElem(IRState* p)
else if (tb->ty == Tpointer && e1->op == TOKvar) {
VarDeclaration *vd = static_cast<VarExp*>(e1)->var->isVarDeclaration();
assert(vd);
vd->codegen(Type::sir);
DtoResolveVariable(vd);
LLConstant *value = vd->ir.irGlobal ? isaConstant(vd->ir.irGlobal->value) : 0;
if (!value)
goto Lerr;
@@ -1355,7 +1355,7 @@ DValue* AddrExp::toElem(IRState* p)
//Logger::println("FuncDeclaration");
FuncDeclaration* fd = fv->func;
assert(fd);
fd->codegen(Type::sir);
DtoResolveFunction(fd);
return new DFuncValue(fd, fd->ir.irFunc->func);
}
else if (v->isIm()) {
@@ -1407,7 +1407,7 @@ LLConstant* AddrExp::toConstElem(IRState* p)
VarDeclaration* vd = vexp->var->isVarDeclaration();
assert(vd);
assert(vd->type->toBasetype()->ty == Tsarray);
vd->codegen(Type::sir);
DtoResolveVariable(vd);
assert(vd->ir.irGlobal);
// get index
@@ -1585,7 +1585,7 @@ DValue* DotVarExp::toElem(IRState* p)
}
else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
{
DtoResolveDsymbol(fdecl);
DtoResolveFunction(fdecl);
// This is a bit more convoluted than it would need to be, because it
// has to take templated interface methods into account, for which
@@ -1632,7 +1632,6 @@ DValue* DotVarExp::toElem(IRState* p)
}
else
{
fdecl->codegen(Type::sir);
funcval = fdecl->ir.irFunc->func;
}
assert(funcval);
@@ -2123,7 +2122,7 @@ DValue* NewExp::toElem(IRState* p)
if (allocator)
{
// custom allocator
allocator->codegen(Type::sir);
DtoResolveFunction(allocator);
DFuncValue dfn(allocator, allocator->ir.irFunc->func);
DValue* res = DtoCallFunction(loc, NULL, &dfn, newargs);
mem = DtoBitCast(res->getRVal(), DtoType(ntype->pointerTo()), ".newstruct_custom");
@@ -2139,7 +2138,7 @@ DValue* NewExp::toElem(IRState* p)
}
else {
assert(ts->sym);
ts->sym->codegen(Type::sir);
DtoResolveStruct(ts->sym);
DtoAggrCopy(mem, ts->sym->ir.irAggr->getInitSymbol());
}
if (ts->sym->isNested() && ts->sym->vthis)
@@ -2150,7 +2149,7 @@ DValue* NewExp::toElem(IRState* p)
{
Logger::println("Calling constructor");
assert(arguments != NULL);
member->codegen(Type::sir);
DtoResolveFunction(member);
DFuncValue dfn(member, member->ir.irFunc->func, mem);
DtoCallFunction(loc, ts, &dfn, arguments);
}
@@ -2313,7 +2312,7 @@ DValue* AssertExp::toElem(IRState* p)
(invdecl = static_cast<TypeStruct*>(condty->nextOf())->sym->inv) != NULL)
{
Logger::print("calling struct invariant");
static_cast<TypeStruct*>(condty->nextOf())->sym->codegen(Type::sir);
DtoResolveFunction(invdecl);
DFuncValue invfunc(invdecl, invdecl->ir.irFunc->func, cond->getRVal());
DtoCallFunction(loc, NULL, &invfunc, NULL);
}
@@ -2541,7 +2540,21 @@ DValue* DelegateExp::toElem(IRState* p)
llvm_unreachable("Delegate to interface method not implemented.");
else
{
func->codegen(Type::sir);
DtoResolveFunction(func);
// We need to actually codegen the function here, as literals are not
// added to the module member list.
if (func->semanticRun == PASSsemantic3done)
{
Dsymbol *owner = func->toParent();
while (!owner->isTemplateInstance() && owner->toParent())
owner = owner->toParent();
if (owner->isTemplateInstance() || owner == p->dmodule)
{
func->codegen(p);
}
}
castfptr = func->ir.irFunc->func;
}
@@ -2785,7 +2798,9 @@ DValue* FuncExp::toElem(IRState* p)
if (fd->isNested()) Logger::println("nested");
Logger::println("kind = %s", fd->kind());
fd->codegen(Type::sir);
// We need to actually codegen the function here, as literals are not added
// to the module member list.
fd->codegen(p);
assert(fd->ir.irFunc->func);
if (fd->isNested()) {
@@ -2852,7 +2867,9 @@ LLConstant* FuncExp::toConstElem(IRState* p)
return 0;
}
fd->codegen(Type::sir);
// We need to actually codegen the function here, as literals are not added
// to the module member list.
fd->codegen(p);
assert(fd->ir.irFunc->func);
return fd->ir.irFunc->func;
@@ -2987,7 +3004,7 @@ DValue* StructLiteralExp::toElem(IRState* p)
assert(sdecltype->ty == Tstruct);
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
assert(ts->sym);
ts->sym->codegen(Type::sir);
DtoResolveStruct(ts->sym);
LLValue* initsym = ts->sym->ir.irAggr->getInitSymbol();
initsym = DtoBitCast(initsym, DtoType(ts->pointerTo()));
@@ -2997,7 +3014,7 @@ DValue* StructLiteralExp::toElem(IRState* p)
if (inProgressMemory) return new DVarValue(type, inProgressMemory);
// make sure the struct is fully resolved
sd->codegen(Type::sir);
DtoResolveStruct(sd);
// alloca a stack slot
inProgressMemory = DtoRawAlloca(DtoType(type), 0, ".structliteral");
@@ -3101,13 +3118,13 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p)
Logger::print("Sym: type=%s\n", sdecltype->toChars());
assert(sdecltype->ty == Tstruct);
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
ts->sym->codegen(Type::sir);
DtoResolveStruct(ts->sym);
return ts->sym->ir.irAggr->getDefaultInit();
}
// make sure the struct is resolved
sd->codegen(Type::sir);
DtoResolveStruct(sd);
std::map<VarDeclaration*, llvm::Constant*> varInits;
const size_t nexprs = elements->dim;
@@ -3129,8 +3146,7 @@ llvm::Constant* ClassReferenceExp::toConstElem(IRState *p)
LOG_SCOPE;
ClassDeclaration* origClass = originalClass();
origClass->codegen(Type::sir);
DtoResolveClass(origClass);
if (value->globalVar)
{

View File

@@ -294,22 +294,17 @@ LLValue* DtoDelegateEquals(TOK op, LLValue* lhs, LLValue* rhs)
LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
{
const bool mustDefine = mustDefineSymbol(sym);
// global/static variable
if (VarDeclaration* vd = sym->isVarDeclaration())
{
if (mustDefine)
{
IF_LOG Logger::println("Variable %savailable externally: %s",
(vd->availableExternally ? "" : "not "), vd->toChars());
}
IF_LOG Logger::println("Variable %savailable externally: %s",
(vd->availableExternally ? "" : "not "), vd->toChars());
// generated by inlining semantics run
if (vd->availableExternally && mustDefine)
if (vd->availableExternally)
return llvm::GlobalValue::AvailableExternallyLinkage;
// template
if (needsTemplateLinkage(sym))
if (DtoIsTemplateInstance(sym))
return templateLinkage;
// Currently, we have to consider all variables, even function-local
@@ -330,11 +325,8 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
}
else if (FuncDeclaration* fdecl = sym->isFuncDeclaration())
{
if (mustDefine)
{
IF_LOG Logger::println("Function %savailable externally: %s",
(fdecl->availableExternally ? "" : "not "), fdecl->toChars());
}
IF_LOG Logger::println("Function %savailable externally: %s",
(fdecl->availableExternally ? "" : "not "), fdecl->toChars());
assert(fdecl->type->ty == Tfunction);
TypeFunction* ft = static_cast<TypeFunction*>(fdecl->type);
@@ -347,7 +339,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
// available_externally. Naked functions are turned into module-level
// inline asm and are thus declaration-only as far as the LLVM IR level
// is concerned.
if (fdecl->availableExternally && mustDefine && !fdecl->naked)
if (fdecl->availableExternally && !fdecl->naked)
return llvm::GlobalValue::AvailableExternallyLinkage;
// array operations are always template linkage
@@ -357,7 +349,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
// template instances should have weak linkage
// but only if there's a body, and it's not naked
// otherwise we make it external
if (needsTemplateLinkage(fdecl) && fdecl->fbody && !fdecl->naked)
if (DtoIsTemplateInstance(fdecl) && fdecl->fbody && !fdecl->naked)
return templateLinkage;
// extern(C) functions are always external
@@ -375,16 +367,14 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
// class
else if (ClassDeclaration* cd = sym->isClassDeclaration())
{
if (mustDefine)
{
IF_LOG Logger::println("Class %savailable externally: %s",
(cd->availableExternally ? "" : "not "), vd->toChars());
}
IF_LOG Logger::println("Class %savailable externally: %s",
(cd->availableExternally ? "" : "not "), vd->toChars());
// generated by inlining semantics run
if (cd->availableExternally && mustDefine)
if (cd->availableExternally)
return llvm::GlobalValue::AvailableExternallyLinkage;
// template
if (needsTemplateLinkage(cd))
if (DtoIsTemplateInstance(cd))
return templateLinkage;
}
else
@@ -392,10 +382,8 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
llvm_unreachable("not global/function");
}
// If the function needs to be defined in the current module, check if it
// is a nested function and we can declare it as internal.
bool canInternalize = mustDefine;
// Check if sym is a nested function and we can declare it as internal.
//
// Nested naked functions and the implicitly generated __require/__ensure
// functions for in/out contracts cannot be internalized. The reason
// for the latter is that contract functions, despite being nested, can be
@@ -403,39 +391,28 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
// interface methods (where __require/__ensure are emitted to the module
// where the interface is declared, but an actual interface implementation
// can be in a completely different place).
if (canInternalize)
{
if (FuncDeclaration* fd = sym->isFuncDeclaration())
{
if ((fd->naked != 0) ||
(fd->ident == Id::require) || (fd->ident == Id::ensure))
{
canInternalize = false;
}
}
}
// Any symbol nested in a function that cannot be inlined can't be
// referenced directly from outside that function, so we can give
// such symbols internal linkage. This holds even if nested indirectly,
// such as member functions of aggregates nested in functions.
//
// Note: This must be checked after things like template member-ness or
// symbols nested in templates would get duplicated for each module,
// breaking things like
// ---
// int counter(T)() { static int i; return i++; }"
// ---
// if instances get emitted in multiple object files because they'd use
// different instances of 'i'.
// TODO: Check if we are giving away too much inlining potential due to
// canInline being overly conservative here.
if (canInternalize)
FuncDeclaration* fd = sym->isFuncDeclaration();
if (!fd || (!fd->naked && fd->ident != Id::require && fd->ident != Id::ensure))
{
// Any symbol nested in a function that cannot be inlined can't be
// referenced directly from outside that function, so we can give
// such symbols internal linkage. This holds even if nested indirectly,
// such as member functions of aggregates nested in functions.
//
// Note: This must be checked after things like template member-ness or
// symbols nested in templates would get duplicated for each module,
// breaking things like
// ---
// int counter(T)() { static int i; return i++; }"
// ---
// if instances get emitted in multiple object files because they'd use
// different instances of 'i'.
// TODO: Check if we are giving away too much inlining potential due to
// canInline being overly conservative here.
for (Dsymbol* parent = sym->parent; parent ; parent = parent->parent)
{
FuncDeclaration *fd = parent->isFuncDeclaration();
if (fd && !fd->canInline(fd->needThis(), false, false))
FuncDeclaration *parentFd = parent->isFuncDeclaration();
if (parentFd && !parentFd->canInline(parentFd->needThis(), false, false))
{
// We also cannot internalize nested functions which are
// leaked to the outside via a templated return type, because
@@ -444,8 +421,8 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
// Since we can't easily determine if this is really the case
// here, just don't internalize it if the parent returns a
// template at all, to be safe.
TypeFunction* tf = static_cast<TypeFunction*>(fd->type);
if (!DtoIsTemplateInstance(tf->next->toDsymbol(fd->scope)))
TypeFunction* tf = static_cast<TypeFunction*>(parentFd->type);
if (!DtoIsTemplateInstance(tf->next->toDsymbol(parentFd->scope)))
return llvm::GlobalValue::InternalLinkage;
}
}
@@ -468,8 +445,8 @@ static bool isAvailableExternally(Dsymbol* sym)
llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
{
if (needsTemplateLinkage(sym)) {
if (isAvailableExternally(sym) && mustDefineSymbol(sym))
if (DtoIsTemplateInstance(sym)) {
if (isAvailableExternally(sym))
return llvm::GlobalValue::AvailableExternallyLinkage;
return templateLinkage;
}
@@ -479,9 +456,9 @@ llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym)
{
if (needsTemplateLinkage(sym))
if (DtoIsTemplateInstance(sym))
return templateLinkage;
else if (isAvailableExternally(sym) && mustDefineSymbol(sym))
else if (isAvailableExternally(sym))
return llvm::GlobalValue::AvailableExternallyLinkage;
else
return llvm::GlobalValue::ExternalLinkage;

View File

@@ -17,7 +17,6 @@
struct TypeInfoDeclaration;
void DtoResolveTypeInfo(TypeInfoDeclaration* tid);
void DtoDeclareTypeInfo(TypeInfoDeclaration* tid);
void DtoConstInitTypeInfo(TypeInfoDeclaration* tid);
#endif

View File

@@ -115,7 +115,9 @@ Expression *Type::getInternalTypeInfo(Scope *sc)
Expression *Type::getTypeInfo(Scope *sc)
{
//printf("Type::getTypeInfo() %p, %s\n", this, toChars());
IF_LOG Logger::println("Type::getTypeInfo(): %s", toChars());
LOG_SCOPE
if (!Type::typeinfo)
{
error(Loc(), "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch");
@@ -150,7 +152,7 @@ Expression *Type::getTypeInfo(Scope *sc)
}
else // if in obj generation pass
{
t->vtinfo->codegen(sir);
t->vtinfo->codegen(gIR);
}
}
}
@@ -280,40 +282,8 @@ int TypeClass::builtinTypeInfo()
// (wut?)
//////////////////////////////////////////////////////////////////////////////
void DtoResolveTypeInfo(TypeInfoDeclaration* tid);
void DtoDeclareTypeInfo(TypeInfoDeclaration* tid);
void TypeInfoDeclaration::codegen(Ir*)
static void emitTypeMetadata(TypeInfoDeclaration *tid)
{
DtoResolveTypeInfo(this);
}
void DtoResolveTypeInfo(TypeInfoDeclaration* tid)
{
if (tid->ir.resolved) return;
tid->ir.resolved = true;
Logger::println("DtoResolveTypeInfo(%s)", tid->toChars());
LOG_SCOPE;
std::string mangle(tid->mangle());
IrGlobal* irg = new IrGlobal(tid);
irg->value = gIR->module->getGlobalVariable(mangle);
if (!irg->value) {
if (tid->tinfo->builtinTypeInfo()) // this is a declaration of a builtin __initZ var
irg->type = Type::typeinfo->type->irtype->isClass()->getMemoryLLType();
else
irg->type = LLStructType::create(gIR->context(), tid->toPrettyChars());
irg->value = new llvm::GlobalVariable(*gIR->module, irg->type, true,
TYPEINFO_LINKAGE_TYPE, NULL, mangle);
} else {
irg->type = irg->value->getType()->getContainedType(0);
}
tid->ir.irGlobal = irg;
// We don't want to generate metadata for non-concrete types (such as tuple
// types, slice types, typeof(expr), etc.), void and function types (without
// an indirection), as there must be a valid LLVM undef value of that type.
@@ -322,13 +292,14 @@ void DtoResolveTypeInfo(TypeInfoDeclaration* tid)
Type* t = tid->tinfo->toBasetype();
if (t->ty < Terror && t->ty != Tvoid && t->ty != Tfunction && t->ty != Tident) {
// Add some metadata for use by optimization passes.
std::string metaname = std::string(TD_PREFIX) + mangle;
std::string metaname(TD_PREFIX);
metaname += tid->mangle();
llvm::NamedMDNode* meta = gIR->module->getNamedMetadata(metaname);
if (!meta) {
// Construct the fields
MDNodeField* mdVals[TD_NumFields];
mdVals[TD_TypeInfo] = llvm::cast<MDNodeField>(irg->value);
mdVals[TD_TypeInfo] = llvm::cast<MDNodeField>(tid->ir.irGlobal->value);
mdVals[TD_Type] = llvm::UndefValue::get(DtoType(tid->tinfo));
// Construct the metadata and insert it into the module.
@@ -337,39 +308,59 @@ void DtoResolveTypeInfo(TypeInfoDeclaration* tid)
llvm::makeArrayRef(mdVals, TD_NumFields)));
}
}
DtoDeclareTypeInfo(tid);
}
void DtoDeclareTypeInfo(TypeInfoDeclaration* tid)
void DtoResolveTypeInfo(TypeInfoDeclaration* tid)
{
DtoResolveTypeInfo(tid);
if (tid->ir.resolved) return;
tid->ir.resolved = true;
if (tid->ir.declared) return;
tid->ir.declared = true;
// TypeInfo instances (except ClassInfo ones) are always emitted as weak
// symbols when they are used.
tid->codegen(gIR);
}
Logger::println("DtoDeclareTypeInfo(%s)", tid->toChars());
void TypeInfoDeclaration::codegen(IRState* p)
{
Logger::println("TypeInfoDeclaration::codegen(%s)", toPrettyChars());
LOG_SCOPE;
if (ir.defined) return;
ir.defined = true;
std::string mangled(mangle());
if (Logger::enabled())
{
std::string mangled(tid->mangle());
Logger::println("type = '%s'", tid->tinfo->toChars());
Logger::println("type = '%s'", tinfo->toChars());
Logger::println("typeinfo mangle: %s", mangled.c_str());
}
IrGlobal* irg = tid->ir.irGlobal;
assert(irg->value != NULL);
IrGlobal* irg = new IrGlobal(this);
ir.irGlobal = irg;
irg->value = gIR->module->getGlobalVariable(mangled);
if (irg->value) {
irg->type = irg->value->getType()->getContainedType(0);
assert(irg->type->isStructTy());
} else {
if (tinfo->builtinTypeInfo()) // this is a declaration of a builtin __initZ var
irg->type = Type::typeinfo->type->irtype->isClass()->getMemoryLLType();
else
irg->type = LLStructType::create(gIR->context(), toPrettyChars());
irg->value = new llvm::GlobalVariable(*gIR->module, irg->type, true,
llvm::GlobalValue::ExternalLinkage, NULL, mangled);
}
emitTypeMetadata(this);
// this is a declaration of a builtin __initZ var
if (tid->tinfo->builtinTypeInfo()) {
if (tinfo->builtinTypeInfo()) {
LLGlobalVariable* g = isaGlobalVar(irg->value);
g->setLinkage(llvm::GlobalValue::ExternalLinkage);
return;
}
// define custom typedef
tid->llvmDefine();
llvmDefine();
}
/* ========================================================================= */
@@ -611,7 +602,7 @@ void TypeInfoStructDeclaration::llvmDefine()
fatal();
}
sd->codegen(Type::sir);
DtoResolveStruct(sd);
IrAggr* iraggr = sd->ir.irAggr;
RTTIBuilder b(Type::typeinfostruct);
@@ -737,20 +728,31 @@ void TypeInfoStructDeclaration::llvmDefine()
/* ========================================================================= */
void TypeInfoClassDeclaration::codegen(Ir*i)
void TypeInfoClassDeclaration::codegen(IRState *p)
{
IrGlobal* irg = new IrGlobal(this);
// For classes, the TypeInfo is in fact a ClassInfo instance and emitted
// as a __ClassZ symbol. For interfaces, the __InterfaceZ symbol is
// referenced as "info" member in a (normal) TypeInfo_Interface instance.
IrGlobal *irg = new IrGlobal(this);
ir.irGlobal = irg;
assert(tinfo->ty == Tclass);
TypeClass *tc = static_cast<TypeClass *>(tinfo);
tc->sym->codegen(Type::sir); // make sure class is resolved
DtoResolveClass(tc->sym);
irg->value = tc->sym->ir.irAggr->getClassInfoSymbol();
irg->type = irg->value->getType()->getContainedType(0);
if (!tc->sym->isInterfaceDeclaration())
{
emitTypeMetadata(this);
}
}
void TypeInfoClassDeclaration::llvmDefine()
{
llvm_unreachable("TypeInfoClassDeclaration should not be called for D2");
llvm_unreachable("TypeInfoClassDeclaration::llvmDefine() should not be called, "
"as a custom Dsymbol::codegen() override is used");
}
/* ========================================================================= */
@@ -763,7 +765,7 @@ void TypeInfoInterfaceDeclaration::llvmDefine()
// make sure interface is resolved
assert(tinfo->ty == Tclass);
TypeClass *tc = static_cast<TypeClass *>(tinfo);
tc->sym->codegen(Type::sir);
DtoResolveClass(tc->sym);
RTTIBuilder b(Type::typeinfointerface);

View File

@@ -1,64 +0,0 @@
//===-- ir.cpp ------------------------------------------------------------===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
#if LDC_LLVM_VER >= 303
#include "llvm/IR/DataLayout.h"
#elif LDC_LLVM_VER == 302
#include "llvm/DataLayout.h"
#else
#include "llvm/Target/TargetData.h"
#endif
#include "gen/irstate.h"
#include "gen/tollvm.h"
#include "gen/functions.h"
#include "ir/ir.h"
#include "ir/irfunction.h"
unsigned GetTypeAlignment(Type* t)
{
return gDataLayout->getABITypeAlignment(DtoType(t));
}
unsigned GetPointerSize()
{
return gDataLayout->getPointerSize(ADDRESS_SPACE);
}
unsigned GetTypeStoreSize(Type* t)
{
return gDataLayout->getTypeStoreSize(DtoType(t));
}
unsigned GetTypeAllocSize(Type* t)
{
return gDataLayout->getTypeAllocSize(DtoType(t));
}
Ir::Ir()
: irs(NULL)
{
}
void Ir::addFunctionBody(IrFunction * f)
{
functionbodies.push_back(f);
}
void Ir::emitFunctionBodies()
{
while (!functionbodies.empty())
{
IrFunction* irf = functionbodies.front();
functionbodies.pop_front();
DtoDefineFunction(irf->decl);
}
}

43
ir/ir.h
View File

@@ -1,43 +0,0 @@
//===-- ir/ir.h - Base definitions for codegen metadata ---------*- C++ -*-===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
//
// Declares the base class for all codegen info classes and the top-level Ir
// class.
//
//===----------------------------------------------------------------------===//
#ifndef LDC_IR_IR_H
#define LDC_IR_IR_H
#include "root.h"
#include "ir/irforw.h"
#include <deque>
struct IRState;
struct IrFunction;
class Ir
{
public:
Ir();
void setState(IRState* p) { irs = p; }
IRState* getState() { return irs; }
void addFunctionBody(IrFunction* f);
void emitFunctionBodies();
private:
IRState* irs;
std::deque<IrFunction*> functionbodies;
};
#endif

View File

@@ -61,10 +61,8 @@ LLGlobalVariable * IrAggr::getInitSymbol()
initname.append(aggrdecl->mangle());
initname.append("6__initZ");
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
init = getOrCreateGlobal(aggrdecl->loc,
*gIR->module, init_type, true, _linkage, NULL, initname);
*gIR->module, init_type, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);
// set alignment
init->setAlignment(type->alignsize());
@@ -207,14 +205,19 @@ LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init)
{
return DtoConstInitializer(init->loc, vd->type, init);
}
else if (vd->init)
if (vd->init)
{
return DtoConstInitializer(vd->init->loc, vd->type, vd->init);
}
else
if (vd->type->size(vd->loc) == 0)
{
return DtoConstExpInit(vd->loc, vd->type, vd->type->defaultInit(vd->loc));
// We need to be able to handle void[0] struct members even if void has
// no default initializer.
return llvm::ConstantPointerNull::get(getPtrToType(DtoType(vd->type)));
}
return DtoConstExpInit(vd->loc, vd->type, vd->type->defaultInit(vd->loc));
}
// return a constant array of type arrTypeD initialized with a constant value, or that constant value

View File

@@ -15,7 +15,6 @@
#ifndef LDC_IR_IRAGGR_H
#define LDC_IR_IRAGGR_H
#include "ir/ir.h"
#include "llvm/ADT/SmallVector.h"
#include <map>
#include <vector>
@@ -57,9 +56,9 @@ struct IrAggr
/// Builds the __vtblZ initializer constant lazily.
LLConstant* getVtblInit();
/// Create the __ClassZ symbol lazily.
/// Create the __ClassZ/__InterfaceZ symbol lazily.
LLGlobalVariable* getClassInfoSymbol();
/// Builds the __ClassZ initializer constant lazily.
/// Builds the __ClassZ/__InterfaceZ initializer constant lazily.
LLConstant* getClassInfoInit();
/// Create the __interfaceInfos symbol lazily.

View File

@@ -53,12 +53,10 @@ LLGlobalVariable * IrAggr::getVtblSymbol()
initname.append(aggrdecl->mangle());
initname.append("6__vtblZ");
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
LLType* vtblTy = stripModifiers(type)->irtype->isClass()->getVtbl();
vtbl = getOrCreateGlobal(aggrdecl->loc,
*gIR->module, vtblTy, true, _linkage, NULL, initname);
*gIR->module, vtblTy, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);
return vtbl;
}
@@ -79,8 +77,9 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol()
else
initname.append("7__ClassZ");
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
// The type is also ClassInfo for interfaces the actual TypeInfo for them
// is a TypeInfo_Interface instance that references __ClassZ in its "base"
// member.
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
DtoType(cinfo->type);
IrTypeClass* tc = stripModifiers(cinfo->type)->irtype->isClass();
@@ -88,7 +87,8 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol()
// classinfos cannot be constants since they're used as locks for synchronized
classInfo = getOrCreateGlobal(aggrdecl->loc,
*gIR->module, tc->getMemoryLLType(), false, _linkage, NULL, initname);
*gIR->module, tc->getMemoryLLType(), false,
llvm::GlobalValue::ExternalLinkage, NULL, initname);
// Generate some metadata on this ClassInfo if it's for a class.
ClassDeclaration* classdecl = aggrdecl->isClassDeclaration();
@@ -138,9 +138,8 @@ LLGlobalVariable * IrAggr::getInterfaceArraySymbol()
name.append(cd->mangle());
name.append("16__interfaceInfosZ");
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
classInterfacesArray = getOrCreateGlobal(cd->loc, *gIR->module,
array_type, true, _linkage, NULL, name);
array_type, true, llvm::GlobalValue::ExternalLinkage, NULL, name);
return classInterfacesArray;
}
@@ -182,7 +181,7 @@ LLConstant * IrAggr::getVtblInit()
}
else
{
fd->codegen(Type::sir);
DtoResolveFunction(fd);
assert(fd->ir.irFunc && "invalid vtbl function");
c = fd->ir.irFunc->func;
if (cd->isFuncHidden(fd))
@@ -320,7 +319,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance
assert((!fd->isAbstract() || fd->fbody) &&
"null symbol in interface implementation vtable");
fd->codegen(Type::sir);
DtoResolveFunction(fd);
assert(fd->ir.irFunc && "invalid vtbl function");
LLFunction *fn = fd->ir.irFunc->func;
@@ -380,9 +379,6 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance
// build the vtbl constant
llvm::Constant* vtbl_constant = LLConstantStruct::getAnon(gIR->context(), constants, false);
// create the global variable to hold it
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
std::string mangle("_D");
mangle.append(cd->mangle());
mangle.append("11__interface");
@@ -393,7 +389,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance
*gIR->module,
vtbl_constant->getType(),
true,
_linkage,
llvm::GlobalValue::ExternalLinkage,
vtbl_constant,
mangle
);

View File

@@ -9,7 +9,6 @@
#include "gen/llvm.h"
#include "gen/logger.h"
#include "ir/ir.h"
#include "ir/irdsymbol.h"
#include "ir/irvar.h"

View File

@@ -25,6 +25,7 @@ struct IrParameter;
struct IrField;
struct IrVar;
struct Dsymbol;
struct Module;
namespace llvm {
class Value;

View File

@@ -17,7 +17,6 @@
#define LDC_IR_IRFUNCTION_H
#include "gen/llvm.h"
#include "ir/ir.h"
#include "ir/irlandingpad.h"
#include <map>
#include <stack>

View File

@@ -16,7 +16,6 @@
#ifndef LDC_IR_IRFUNCTY_H
#define LDC_IR_IRFUNCTY_H
#include "ir/ir.h"
#include "llvm/ADT/SmallVector.h"
#if LDC_LLVM_VER >= 303
#include "llvm/IR/Attributes.h"
@@ -27,6 +26,7 @@
#include <vector>
class DValue;
struct Type;
struct ABIRewrite;
namespace llvm {
class Type;

View File

@@ -34,7 +34,7 @@ IRLandingPadCatchInfo::IRLandingPadCatchInfo(Catch* catchstmt_, llvm::BasicBlock
assert(catchStmt->type);
catchType = catchStmt->type->toBasetype()->isClassHandle();
assert(catchType);
catchType->codegen(Type::sir);
DtoResolveClass(catchType);
if (catchStmt->var) {
if (!catchStmt->var->nestedrefs.dim) {

View File

@@ -16,7 +16,6 @@
#define LDC_IR_IRLANDINGPADINFO_H
#include "statement.h"
#include "ir/ir.h"
#include <deque>
#include <stack>

View File

@@ -15,9 +15,11 @@
#ifndef LDC_IR_IRMODULE_H
#define LDC_IR_IRMODULE_H
#include "ir/ir.h"
struct Module;
namespace llvm
{
class GlobalVariable;
}
struct IrModule
{
@@ -26,7 +28,7 @@ struct IrModule
Module* M;
LLGlobalVariable* fileName;
llvm::GlobalVariable* fileName;
};
#endif

View File

@@ -81,7 +81,7 @@ public:
///
virtual IrTypeStruct* isStruct() { return 0; }
///
IrTypeVector* isVector() { return 0; }
virtual IrTypeVector* isVector() { return 0; }
///
Type* getDType() { return dtype; }

View File

@@ -15,7 +15,6 @@
#ifndef LDC_IR_IRVAR_H
#define LDC_IR_IRVAR_H
#include "ir/ir.h"
#if LDC_LLVM_VER >= 303
#include "llvm/IR/Type.h"
#else
@@ -23,6 +22,7 @@
#endif
struct IrFuncTyArg;
struct VarDeclaration;
struct IrVar
{