mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-13 03:13:13 +01:00
Merge pull request #507 from klickverbot/issue-454
Use Module::members -> Dsymbol::codegen to define symbols.
This commit is contained in:
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -76,7 +76,7 @@ struct EnumDeclaration : ScopeDsymbol
|
||||
#endif
|
||||
|
||||
#if IN_LLVM
|
||||
void codegen(Ir*);
|
||||
void codegen(IRState*);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
202
dmd2/irstate.c
202
dmd2/irstate.c
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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; }
|
||||
|
||||
11
dmd2/mtype.c
11
dmd2/mtype.c
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
|
||||
@@ -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())));
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/******************************
|
||||
|
||||
56
gen/toir.cpp
56
gen/toir.cpp
@@ -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)
|
||||
{
|
||||
|
||||
103
gen/tollvm.cpp
103
gen/tollvm.cpp
@@ -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;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
struct TypeInfoDeclaration;
|
||||
void DtoResolveTypeInfo(TypeInfoDeclaration* tid);
|
||||
void DtoDeclareTypeInfo(TypeInfoDeclaration* tid);
|
||||
void DtoConstInitTypeInfo(TypeInfoDeclaration* tid);
|
||||
|
||||
#endif
|
||||
|
||||
116
gen/typinf.cpp
116
gen/typinf.cpp
@@ -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);
|
||||
|
||||
|
||||
64
ir/ir.cpp
64
ir/ir.cpp
@@ -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
43
ir/ir.h
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "gen/llvm.h"
|
||||
#include "gen/logger.h"
|
||||
#include "ir/ir.h"
|
||||
#include "ir/irdsymbol.h"
|
||||
#include "ir/irvar.h"
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ struct IrParameter;
|
||||
struct IrField;
|
||||
struct IrVar;
|
||||
struct Dsymbol;
|
||||
struct Module;
|
||||
|
||||
namespace llvm {
|
||||
class Value;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define LDC_IR_IRLANDINGPADINFO_H
|
||||
|
||||
#include "statement.h"
|
||||
#include "ir/ir.h"
|
||||
#include <deque>
|
||||
#include <stack>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
///
|
||||
virtual IrTypeStruct* isStruct() { return 0; }
|
||||
///
|
||||
IrTypeVector* isVector() { return 0; }
|
||||
virtual IrTypeVector* isVector() { return 0; }
|
||||
|
||||
///
|
||||
Type* getDType() { return dtype; }
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user