mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-27 15:50:19 +02:00
Merge pull request #507 from klickverbot/issue-454
Use Module::members -> Dsymbol::codegen to define symbols.
This commit is contained in:
+3
-3
@@ -209,7 +209,7 @@ struct StructDeclaration : AggregateDeclaration
|
|||||||
StructDeclaration *isStructDeclaration() { return this; }
|
StructDeclaration *isStructDeclaration() { return this; }
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
void codegen(Ir*);
|
void codegen(IRState*);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ struct ClassDeclaration : AggregateDeclaration
|
|||||||
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
|
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
virtual void codegen(Ir*);
|
virtual void codegen(IRState*);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -367,7 +367,7 @@ struct InterfaceDeclaration : ClassDeclaration
|
|||||||
InterfaceDeclaration *isInterfaceDeclaration() { return this; }
|
InterfaceDeclaration *isInterfaceDeclaration() { return this; }
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
void codegen(Ir*);
|
void codegen(IRState*);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -63,7 +63,7 @@ struct AttribDeclaration : Dsymbol
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
virtual void codegen(Ir*);
|
void codegen(IRState*);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ struct PragmaDeclaration : AttribDeclaration
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
void codegen(Ir*);
|
void codegen(IRState*);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+12
-11
@@ -189,11 +189,6 @@ struct Declaration : Dsymbol
|
|||||||
enum PROT prot();
|
enum PROT prot();
|
||||||
|
|
||||||
Declaration *isDeclaration() { return this; }
|
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
|
#if IN_LLVM
|
||||||
void semantic3(Scope *sc);
|
void semantic3(Scope *sc);
|
||||||
/// Codegen traversal
|
/// Codegen traversal
|
||||||
void codegen(Ir* ir);
|
void codegen(IRState* ir);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -256,7 +251,7 @@ struct TypedefDeclaration : Declaration
|
|||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
/// Codegen traversal
|
/// Codegen traversal
|
||||||
void codegen(Ir* ir);
|
void codegen(IRState* ir);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -362,7 +357,7 @@ struct VarDeclaration : Declaration
|
|||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
/// Codegen traversal
|
/// Codegen traversal
|
||||||
virtual void codegen(Ir* ir);
|
void codegen(IRState* ir);
|
||||||
|
|
||||||
/// Index into parent aggregate.
|
/// Index into parent aggregate.
|
||||||
/// Set during type generation.
|
/// Set during type generation.
|
||||||
@@ -455,7 +450,7 @@ struct TypeInfoDeclaration : VarDeclaration
|
|||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
/// Codegen traversal
|
/// Codegen traversal
|
||||||
void codegen(Ir* ir);
|
void codegen(IRState* ir);
|
||||||
virtual void llvmDefine();
|
virtual void llvmDefine();
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -483,7 +478,11 @@ struct TypeInfoClassDeclaration : TypeInfoDeclaration
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IN_LLVM
|
#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();
|
void llvmDefine();
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -819,7 +818,9 @@ struct FuncDeclaration : Declaration
|
|||||||
// functions
|
// functions
|
||||||
FuncDeclarations siblingCallers; // Sibling nested functions which
|
FuncDeclarations siblingCallers; // Sibling nested functions which
|
||||||
// called this one
|
// called this one
|
||||||
|
#if IN_DMD
|
||||||
FuncDeclarations deferred; // toObjFile() these functions after this one
|
FuncDeclarations deferred; // toObjFile() these functions after this one
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
#define FUNCFLAGpurityInprocess 1 // working on determining purity
|
#define FUNCFLAGpurityInprocess 1 // working on determining purity
|
||||||
@@ -918,7 +919,7 @@ struct FuncDeclaration : Declaration
|
|||||||
IrFuncTy irFty;
|
IrFuncTy irFty;
|
||||||
|
|
||||||
/// Codegen traversal
|
/// Codegen traversal
|
||||||
void codegen(Ir* ir);
|
void codegen(IRState* ir);
|
||||||
|
|
||||||
// vars declared in this function that nested funcs reference
|
// vars declared in this function that nested funcs reference
|
||||||
// is this is not empty, nestedFrameRef is set and these VarDecls
|
// is this is not empty, nestedFrameRef is set and these VarDecls
|
||||||
|
|||||||
+2
-2
@@ -95,7 +95,7 @@ struct TYPE;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
class Ir;
|
class IRState;
|
||||||
namespace llvm
|
namespace llvm
|
||||||
{
|
{
|
||||||
class Value;
|
class Value;
|
||||||
@@ -287,7 +287,7 @@ struct Dsymbol : Object
|
|||||||
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
|
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
|
||||||
|
|
||||||
/// Codegen traversal
|
/// Codegen traversal
|
||||||
virtual void codegen(Ir* ir);
|
virtual void codegen(IRState* p);
|
||||||
|
|
||||||
// llvm stuff
|
// llvm stuff
|
||||||
int llvmInternal;
|
int llvmInternal;
|
||||||
|
|||||||
+1
-1
@@ -76,7 +76,7 @@ struct EnumDeclaration : ScopeDsymbol
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
void codegen(Ir*);
|
void codegen(IRState*);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4735,11 +4735,7 @@ void UnitTestDeclaration::semantic(Scope *sc)
|
|||||||
{ sc = scope;
|
{ sc = scope;
|
||||||
scope = NULL;
|
scope = NULL;
|
||||||
}
|
}
|
||||||
#if IN_LLVM
|
|
||||||
if (global.params.useUnitTests && sc->module->isRoot)
|
|
||||||
#else
|
|
||||||
if (global.params.useUnitTests)
|
if (global.params.useUnitTests)
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
if (!type)
|
if (!type)
|
||||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||||
|
|||||||
-202
@@ -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 */
|
|
||||||
+1
-2
@@ -28,7 +28,6 @@ class Library;
|
|||||||
|
|
||||||
// Back end
|
// Back end
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
class Ir;
|
|
||||||
class DValue;
|
class DValue;
|
||||||
typedef DValue elem;
|
typedef DValue elem;
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@@ -196,7 +195,7 @@ struct Module : Package
|
|||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
// LDC
|
// LDC
|
||||||
llvm::Module* genLLVMModule(llvm::LLVMContext& context, Ir* sir);
|
llvm::Module* genLLVMModule(llvm::LLVMContext& context);
|
||||||
void buildTargetFiles(bool singleObj);
|
void buildTargetFiles(bool singleObj);
|
||||||
File* buildFilePath(const char* forcename, const char* path, const char* ext);
|
File* buildFilePath(const char* forcename, const char* path, const char* ext);
|
||||||
Module *isModule() { return this; }
|
Module *isModule() { return this; }
|
||||||
|
|||||||
@@ -50,9 +50,6 @@
|
|||||||
#include "aggregate.h"
|
#include "aggregate.h"
|
||||||
#include "hdrgen.h"
|
#include "hdrgen.h"
|
||||||
|
|
||||||
#if IN_LLVM
|
|
||||||
Ir* Type::sir = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FuncDeclaration *hasThis(Scope *sc);
|
FuncDeclaration *hasThis(Scope *sc);
|
||||||
|
|
||||||
@@ -197,11 +194,7 @@ char Type::needThisPrefix()
|
|||||||
return 'M'; // name mangling prefix for functions needing 'this'
|
return 'M'; // name mangling prefix for functions needing 'this'
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IN_LLVM
|
|
||||||
void Type::init(Ir* _sir)
|
|
||||||
#else
|
|
||||||
void Type::init()
|
void Type::init()
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
stringtable._init(1543);
|
stringtable._init(1543);
|
||||||
Lexer::initKeywords();
|
Lexer::initKeywords();
|
||||||
@@ -353,10 +346,6 @@ void Type::init()
|
|||||||
Tptrdiff_t = Tint32;
|
Tptrdiff_t = Tint32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IN_LLVM
|
|
||||||
sir = _sir;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
tsize_t = basic[Tsize_t];
|
tsize_t = basic[Tsize_t];
|
||||||
tptrdiff_t = basic[Tptrdiff_t];
|
tptrdiff_t = basic[Tptrdiff_t];
|
||||||
thash_t = tsize_t;
|
thash_t = tsize_t;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
#include "../ir/irfuncty.h"
|
#include "../ir/irfuncty.h"
|
||||||
namespace llvm { class Type; }
|
namespace llvm { class Type; }
|
||||||
class Ir;
|
|
||||||
class IrType;
|
class IrType;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -247,11 +246,7 @@ struct Type : Object
|
|||||||
int covariant(Type *t, StorageClass *pstc = NULL);
|
int covariant(Type *t, StorageClass *pstc = NULL);
|
||||||
char *toChars();
|
char *toChars();
|
||||||
static char needThisPrefix();
|
static char needThisPrefix();
|
||||||
#if IN_LLVM
|
|
||||||
static void init(Ir*);
|
|
||||||
#else
|
|
||||||
static void init();
|
static void init();
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SIZE_INVALID (~(d_uns64)0)
|
#define SIZE_INVALID (~(d_uns64)0)
|
||||||
d_uns64 size();
|
d_uns64 size();
|
||||||
@@ -371,7 +366,6 @@ struct Type : Object
|
|||||||
virtual TypeBasic *isTypeBasic();
|
virtual TypeBasic *isTypeBasic();
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
static Ir* sir;
|
|
||||||
IrType* irtype;
|
IrType* irtype;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-2
@@ -356,7 +356,7 @@ struct TemplateInstance : ScopeDsymbol
|
|||||||
bool ignore; // true if the instance must be ignored when codegen'ing
|
bool ignore; // true if the instance must be ignored when codegen'ing
|
||||||
Module* emittedInModule; // which module this template instance has been emitted in
|
Module* emittedInModule; // which module this template instance has been emitted in
|
||||||
|
|
||||||
void codegen(Ir*);
|
void codegen(IRState*);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -386,7 +386,7 @@ struct TemplateMixin : TemplateInstance
|
|||||||
TemplateMixin *isTemplateMixin() { return this; }
|
TemplateMixin *isTemplateMixin() { return this; }
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
void codegen(Ir*);
|
void codegen(IRState*);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+2
-5
@@ -614,9 +614,6 @@ int main(int argc, char **argv)
|
|||||||
if (global.errors)
|
if (global.errors)
|
||||||
fatal();
|
fatal();
|
||||||
|
|
||||||
// create a proper target
|
|
||||||
Ir ir;
|
|
||||||
|
|
||||||
// Set up the TargetMachine.
|
// Set up the TargetMachine.
|
||||||
ExplicitBitness::Type bitness = ExplicitBitness::None;
|
ExplicitBitness::Type bitness = ExplicitBitness::None;
|
||||||
if ((m32bits || m64bits) && (!mArch.empty() || !mTargetTriple.empty()))
|
if ((m32bits || m64bits) && (!mArch.empty() || !mTargetTriple.empty()))
|
||||||
@@ -669,7 +666,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
Type::init(&ir);
|
Type::init();
|
||||||
Id::initialize();
|
Id::initialize();
|
||||||
Module::init();
|
Module::init();
|
||||||
Target::init();
|
Target::init();
|
||||||
@@ -987,7 +984,7 @@ int main(int argc, char **argv)
|
|||||||
printf("code %s\n", m->toChars());
|
printf("code %s\n", m->toChars());
|
||||||
if (global.params.obj)
|
if (global.params.obj)
|
||||||
{
|
{
|
||||||
llvm::Module* lm = m->genLLVMModule(context, &ir);
|
llvm::Module* lm = m->genLLVMModule(context);
|
||||||
if (!singleObj)
|
if (!singleObj)
|
||||||
{
|
{
|
||||||
m->deleteObjFile();
|
m->deleteObjFile();
|
||||||
|
|||||||
@@ -867,14 +867,6 @@ static LLValue* DtoArrayEqCmp_impl(Loc& loc, const char* func, DValue* l, DValue
|
|||||||
if (useti) {
|
if (useti) {
|
||||||
Type* t = l->getType();
|
Type* t = l->getType();
|
||||||
LLValue* tival = DtoTypeInfoOf(t);
|
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)));
|
args.push_back(DtoBitCast(tival, fn->getFunctionType()->getParamType(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-65
@@ -35,24 +35,21 @@
|
|||||||
|
|
||||||
void DtoResolveClass(ClassDeclaration* cd)
|
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;
|
if (cd->ir.resolved) return;
|
||||||
cd->ir.resolved = true;
|
cd->ir.resolved = true;
|
||||||
|
|
||||||
Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
|
Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
|
||||||
LOG_SCOPE;
|
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
|
// make sure type exists
|
||||||
DtoType(cd->type);
|
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
|
// emit the interfaceInfosZ symbol if necessary
|
||||||
if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0)
|
if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0)
|
||||||
irAggr->getInterfaceArraySymbol(); // initializer is applied when it's built
|
irAggr->getInterfaceArraySymbol(); // initializer is applied when it's built
|
||||||
@@ -87,43 +79,6 @@ void DtoResolveClass(ClassDeclaration* cd)
|
|||||||
{
|
{
|
||||||
irAggr->initializeInterface();
|
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)
|
DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
|
||||||
{
|
{
|
||||||
// resolve type
|
// resolve type
|
||||||
tc->sym->codegen(Type::sir);
|
DtoResolveClass(tc->sym);
|
||||||
|
|
||||||
// allocate
|
// allocate
|
||||||
LLValue* mem;
|
LLValue* mem;
|
||||||
@@ -143,7 +98,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
|
|||||||
// custom allocator
|
// custom allocator
|
||||||
else if (newexp->allocator)
|
else if (newexp->allocator)
|
||||||
{
|
{
|
||||||
newexp->allocator->codegen(Type::sir);
|
DtoResolveFunction(newexp->allocator);
|
||||||
DFuncValue dfn(newexp->allocator, newexp->allocator->ir.irFunc->func);
|
DFuncValue dfn(newexp->allocator, newexp->allocator->ir.irFunc->func);
|
||||||
DValue* res = DtoCallFunction(newexp->loc, NULL, &dfn, newexp->newargs);
|
DValue* res = DtoCallFunction(newexp->loc, NULL, &dfn, newexp->newargs);
|
||||||
mem = DtoBitCast(res->getRVal(), DtoType(tc), ".newclass_custom");
|
mem = DtoBitCast(res->getRVal(), DtoType(tc), ".newclass_custom");
|
||||||
@@ -184,7 +139,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
|
|||||||
{
|
{
|
||||||
Logger::println("Calling constructor");
|
Logger::println("Calling constructor");
|
||||||
assert(newexp->arguments != NULL);
|
assert(newexp->arguments != NULL);
|
||||||
newexp->member->codegen(Type::sir);
|
DtoResolveFunction(newexp->member);
|
||||||
DFuncValue dfn(newexp->member, newexp->member->ir.irFunc->func, mem);
|
DFuncValue dfn(newexp->member, newexp->member->ir.irFunc->func, mem);
|
||||||
return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments);
|
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)
|
void DtoInitClass(TypeClass* tc, LLValue* dst)
|
||||||
{
|
{
|
||||||
tc->sym->codegen(Type::sir);
|
DtoResolveClass(tc->sym);
|
||||||
|
|
||||||
uint64_t n = tc->sym->structsize - Target::ptrsize * 2;
|
uint64_t n = tc->sym->structsize - Target::ptrsize * 2;
|
||||||
|
|
||||||
@@ -365,8 +320,8 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to)
|
|||||||
// call:
|
// call:
|
||||||
// Object _d_dynamic_cast(Object o, ClassInfo c)
|
// Object _d_dynamic_cast(Object o, ClassInfo c)
|
||||||
|
|
||||||
ClassDeclaration::object->codegen(Type::sir);
|
DtoResolveClass(ClassDeclaration::object);
|
||||||
ClassDeclaration::classinfo->codegen(Type::sir);
|
DtoResolveClass(ClassDeclaration::classinfo);
|
||||||
|
|
||||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
|
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
|
||||||
LLFunctionType* funcTy = func->getFunctionType();
|
LLFunctionType* funcTy = func->getFunctionType();
|
||||||
@@ -378,7 +333,7 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to)
|
|||||||
|
|
||||||
// ClassInfo c
|
// ClassInfo c
|
||||||
TypeClass* to = static_cast<TypeClass*>(_to->toBasetype());
|
TypeClass* to = static_cast<TypeClass*>(_to->toBasetype());
|
||||||
to->sym->codegen(Type::sir);
|
DtoResolveClass(to->sym);
|
||||||
|
|
||||||
LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol();
|
LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol();
|
||||||
// unfortunately this is needed as the implementation of object differs somehow from the declaration
|
// 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:
|
// call:
|
||||||
// Object _d_interface_cast(void* p, ClassInfo c)
|
// Object _d_interface_cast(void* p, ClassInfo c)
|
||||||
|
|
||||||
ClassDeclaration::object->codegen(Type::sir);
|
DtoResolveClass(ClassDeclaration::object);
|
||||||
ClassDeclaration::classinfo->codegen(Type::sir);
|
DtoResolveClass(ClassDeclaration::classinfo);
|
||||||
|
|
||||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast");
|
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast");
|
||||||
LLFunctionType* funcTy = func->getFunctionType();
|
LLFunctionType* funcTy = func->getFunctionType();
|
||||||
@@ -440,7 +395,7 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
|
|||||||
|
|
||||||
// ClassInfo c
|
// ClassInfo c
|
||||||
TypeClass* to = static_cast<TypeClass*>(_to->toBasetype());
|
TypeClass* to = static_cast<TypeClass*>(_to->toBasetype());
|
||||||
to->sym->codegen(Type::sir);
|
DtoResolveClass(to->sym);
|
||||||
LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol();
|
LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol();
|
||||||
// unfortunately this is needed as the implementation of object differs somehow from the declaration
|
// unfortunately this is needed as the implementation of object differs somehow from the declaration
|
||||||
// this could happen in user code as well :/
|
// this could happen in user code as well :/
|
||||||
@@ -623,7 +578,7 @@ static LLConstant* build_class_dtor(ClassDeclaration* cd)
|
|||||||
if (!dtor)
|
if (!dtor)
|
||||||
return getNullPtr(getVoidPtrType());
|
return getNullPtr(getVoidPtrType());
|
||||||
|
|
||||||
dtor->codegen(Type::sir);
|
DtoResolveFunction(dtor);
|
||||||
return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::getInt8Ty(gIR->context())));
|
return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::getInt8Ty(gIR->context())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+131
-80
@@ -14,73 +14,144 @@
|
|||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "rmem.h"
|
#include "rmem.h"
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
|
#include "gen/classes.h"
|
||||||
|
#include "gen/functions.h"
|
||||||
#include "gen/irstate.h"
|
#include "gen/irstate.h"
|
||||||
#include "gen/llvm.h"
|
#include "gen/llvm.h"
|
||||||
#include "gen/llvmhelpers.h"
|
#include "gen/llvmhelpers.h"
|
||||||
#include "gen/logger.h"
|
#include "gen/logger.h"
|
||||||
#include "gen/tollvm.h"
|
#include "gen/tollvm.h"
|
||||||
#include "ir/ir.h"
|
#include "gen/utils.h"
|
||||||
#include "ir/irtype.h"
|
#include "ir/irtype.h"
|
||||||
#include "ir/irvar.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)
|
if (type->ty == Terror)
|
||||||
{ error("had semantic errors when compiling");
|
{ error("had semantic errors when compiling");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (members && symtab)
|
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)
|
if (type->ty == Terror)
|
||||||
{ error("had semantic errors when compiling");
|
{ error("had semantic errors when compiling");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (members && symtab)
|
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)
|
if (type->ty == Terror)
|
||||||
{ error("had semantic errors when compiling");
|
{ error("had semantic errors when compiling");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (members && symtab)
|
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(isexp);
|
||||||
assert(objects);
|
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;
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
if (ir.defined) return;
|
||||||
|
ir.defined = true;
|
||||||
|
|
||||||
if (type->ty == Terror)
|
if (type->ty == Terror)
|
||||||
{ error("had semantic errors when compiling");
|
{ error("had semantic errors when compiling");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DtoResolveVariable(this);
|
||||||
|
|
||||||
// just forward aliases
|
// just forward aliases
|
||||||
if (aliassym)
|
if (aliassym)
|
||||||
{
|
{
|
||||||
@@ -115,10 +191,6 @@ void VarDeclaration::codegen(Ir* p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// output the parent aggregate first
|
|
||||||
if (AggregateDeclaration* ad = isMember())
|
|
||||||
ad->codegen(p);
|
|
||||||
|
|
||||||
// global variable
|
// global variable
|
||||||
if (isDataseg() || (storage_class & (STCconst | STCimmutable) && init))
|
if (isDataseg() || (storage_class & (STCconst | STCimmutable) && init))
|
||||||
{
|
{
|
||||||
@@ -129,37 +201,14 @@ void VarDeclaration::codegen(Ir* p)
|
|||||||
"manifest constant being codegen'd!");
|
"manifest constant being codegen'd!");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// don't duplicate work
|
llvm::GlobalVariable *gvar = llvm::cast<llvm::GlobalVariable>(
|
||||||
if (this->ir.resolved) return;
|
this->ir.irGlobal->value);
|
||||||
this->ir.resolved = true;
|
assert(gvar && "DtoResolveVariable should have created value");
|
||||||
this->ir.declared = true;
|
|
||||||
|
|
||||||
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);
|
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.
|
// 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!
|
// Build the initializer. Might use this->ir.irGlobal->value!
|
||||||
LLConstant *initVal = DtoConstInitializer(loc, type, init);
|
LLConstant *initVal = DtoConstInitializer(loc, type, init);
|
||||||
@@ -168,10 +217,12 @@ void VarDeclaration::codegen(Ir* p)
|
|||||||
if (initVal->getType() != gvar->getType()->getElementType())
|
if (initVal->getType() != gvar->getType()->getElementType())
|
||||||
{
|
{
|
||||||
llvm::GlobalVariable* newGvar = getOrCreateGlobal(loc,
|
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.
|
"", // We take on the name of the old global below.
|
||||||
isThreadlocal());
|
gvar->isThreadLocal());
|
||||||
|
|
||||||
|
newGvar->setAlignment(gvar->getAlignment());
|
||||||
newGvar->takeName(gvar);
|
newGvar->takeName(gvar);
|
||||||
|
|
||||||
llvm::Constant* newValue =
|
llvm::Constant* newValue =
|
||||||
@@ -187,22 +238,17 @@ void VarDeclaration::codegen(Ir* p)
|
|||||||
assert(!ir.irGlobal->constInit);
|
assert(!ir.irGlobal->constInit);
|
||||||
ir.irGlobal->constInit = initVal;
|
ir.irGlobal->constInit = initVal;
|
||||||
gvar->setInitializer(initVal);
|
gvar->setInitializer(initVal);
|
||||||
|
gvar->setLinkage(llLinkage);
|
||||||
|
|
||||||
// Also set up the edbug info.
|
// 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
|
// 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
|
// artificial "use" for it, or it could be removed by the optimizer if
|
||||||
// the only reference to it is in inline asm.
|
// the only reference to it is in inline asm.
|
||||||
if (nakedUse)
|
if (nakedUse)
|
||||||
gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
|
p->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
|
||||||
|
|
||||||
if (Logger::enabled())
|
if (Logger::enabled())
|
||||||
Logger::cout() << *gvar << '\n';
|
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;
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
if (ir.defined) return;
|
||||||
|
ir.defined = true;
|
||||||
|
|
||||||
if (type->ty == Terror)
|
if (type->ty == Terror)
|
||||||
{ error("had semantic errors when compiling");
|
{ error("had semantic errors when compiling");
|
||||||
return;
|
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)
|
if (type->ty == Terror)
|
||||||
{ error("had semantic errors when compiling");
|
{ 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
|
// don't touch function aliases, they don't contribute any new symbols
|
||||||
if (!isFuncAliasDeclaration())
|
if (!isFuncAliasDeclaration())
|
||||||
{
|
{
|
||||||
DtoResolveDsymbol(this);
|
DtoDefineFunction(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================================== */
|
/* ================================================================== */
|
||||||
|
|
||||||
void TemplateInstance::codegen(Ir* p)
|
void TemplateInstance::codegen(IRState *p)
|
||||||
{
|
{
|
||||||
#if LOG
|
IF_LOG Logger::println("TemplateInstance::codegen: '%s'", toPrettyChars());
|
||||||
printf("TemplateInstance::codegen('%s', this = %p)\n", toChars(), this);
|
LOG_SCOPE
|
||||||
#endif
|
|
||||||
if (ignore)
|
if (ir.defined) return;
|
||||||
return;
|
ir.defined = true;
|
||||||
|
|
||||||
if (!errors && members)
|
if (!errors && members)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < members->dim; i++)
|
for (unsigned i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = static_cast<Dsymbol *>(members->data[i]);
|
(*members)[i]->codegen(p);
|
||||||
s->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)
|
if (!errors && members)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < members->dim; i++)
|
for (unsigned i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = static_cast<Dsymbol *>(members->data[i]);
|
(*members)[i]->codegen(p);
|
||||||
if (s->isVarDeclaration())
|
|
||||||
continue;
|
|
||||||
s->codegen(p);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================================== */
|
/* ================================================================== */
|
||||||
|
|
||||||
void AttribDeclaration::codegen(Ir* p)
|
void AttribDeclaration::codegen(IRState *p)
|
||||||
{
|
{
|
||||||
Array *d = include(NULL, NULL);
|
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)
|
if (ident == Id::lib)
|
||||||
{
|
{
|
||||||
|
|||||||
+43
-50
@@ -702,6 +702,12 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
|||||||
Logger::println("DtoDeclareFunction(%s): %s", fdecl->toPrettyChars(), fdecl->loc.toChars());
|
Logger::println("DtoDeclareFunction(%s): %s", fdecl->toPrettyChars(), fdecl->loc.toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
if (fdecl->isUnitTestDeclaration() && !global.params.useUnitTests)
|
||||||
|
{
|
||||||
|
Logger::println("unit tests not enabled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//printf("declare function: %s\n", fdecl->toPrettyChars());
|
//printf("declare function: %s\n", fdecl->toPrettyChars());
|
||||||
|
|
||||||
// intrinsic sanity check
|
// intrinsic sanity check
|
||||||
@@ -715,10 +721,6 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
|||||||
TypeFunction* f = static_cast<TypeFunction*>(t);
|
TypeFunction* f = static_cast<TypeFunction*>(t);
|
||||||
|
|
||||||
IrFuncTy &irFty = fdecl->irFty;
|
IrFuncTy &irFty = fdecl->irFty;
|
||||||
bool declareOnly = !mustDefineSymbol(fdecl);
|
|
||||||
|
|
||||||
if (fdecl->llvmInternal == LLVMva_start)
|
|
||||||
declareOnly = true;
|
|
||||||
|
|
||||||
if (!fdecl->ir.irFunc) {
|
if (!fdecl->ir.irFunc) {
|
||||||
fdecl->ir.irFunc = new IrFunction(fdecl);
|
fdecl->ir.irFunc = new IrFunction(fdecl);
|
||||||
@@ -753,9 +755,16 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
|||||||
LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangledName);
|
LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangledName);
|
||||||
if (!func) {
|
if (!func) {
|
||||||
if(fdecl->llvmInternal == LLVMinline_ir)
|
if(fdecl->llvmInternal == LLVMinline_ir)
|
||||||
|
{
|
||||||
func = DtoInlineIRFunction(fdecl);
|
func = DtoInlineIRFunction(fdecl);
|
||||||
|
}
|
||||||
else
|
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) {
|
} else if (func->getFunctionType() != functype) {
|
||||||
error(fdecl->loc, "Function type does not match previously declared function with the same mangled name: %s", fdecl->mangle());
|
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;
|
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)
|
if (fdecl->neverInline)
|
||||||
{
|
{
|
||||||
fdecl->ir.irFunc->setNeverInline();
|
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);
|
DtoDeclareFunction(fd);
|
||||||
|
|
||||||
if (fd->ir.defined) return;
|
|
||||||
fd->ir.defined = true;
|
|
||||||
|
|
||||||
assert(fd->ir.declared);
|
assert(fd->ir.declared);
|
||||||
|
|
||||||
if (Logger::enabled())
|
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;
|
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 this function is naked, we take over right away! no standard processing!
|
||||||
if (fd->naked)
|
if (fd->naked)
|
||||||
{
|
{
|
||||||
@@ -954,9 +948,6 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||||||
|
|
||||||
llvm::Function* func = fd->ir.irFunc->func;
|
llvm::Function* func = fd->ir.irFunc->func;
|
||||||
|
|
||||||
// sanity check
|
|
||||||
assert(mustDefineSymbol(fd));
|
|
||||||
|
|
||||||
// set module owner
|
// set module owner
|
||||||
fd->ir.DModule = gIR->dmodule;
|
fd->ir.DModule = gIR->dmodule;
|
||||||
|
|
||||||
@@ -972,6 +963,8 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||||||
if (fd->isMain())
|
if (fd->isMain())
|
||||||
gIR->emitMain = true;
|
gIR->emitMain = true;
|
||||||
|
|
||||||
|
func->setLinkage(DtoLinkage(fd));
|
||||||
|
|
||||||
// On x86_64, always set 'uwtable' for System V ABI compatibility.
|
// On x86_64, always set 'uwtable' for System V ABI compatibility.
|
||||||
// TODO: Find a better place for this.
|
// TODO: Find a better place for this.
|
||||||
if (global.params.targetTriple.getArch() == llvm::Triple::x86_64)
|
if (global.params.targetTriple.getArch() == llvm::Triple::x86_64)
|
||||||
@@ -1185,7 +1178,7 @@ llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DtoResolveDsymbol(f);
|
DtoResolveFunction(f);
|
||||||
return llvm::cast<llvm::FunctionType>(DtoType(f->type));
|
return llvm::cast<llvm::FunctionType>(DtoType(f->type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+107
-153
@@ -737,10 +737,10 @@ DValue* DtoCastNull(Loc& loc, DValue* val, Type* to)
|
|||||||
Type* totype = to->toBasetype();
|
Type* totype = to->toBasetype();
|
||||||
LLType* tolltype = DtoType(to);
|
LLType* tolltype = DtoType(to);
|
||||||
|
|
||||||
if (totype->ty == Tpointer)
|
if (totype->ty == Tpointer || totype->ty == Tclass)
|
||||||
{
|
{
|
||||||
if (Logger::enabled())
|
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);
|
LLValue *rval = DtoBitCast(val->getRVal(), tolltype);
|
||||||
return new DImValue(to, rval);
|
return new DImValue(to, rval);
|
||||||
}
|
}
|
||||||
@@ -1005,8 +1005,86 @@ void DtoResolveDsymbol(Dsymbol* dsym)
|
|||||||
else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
|
else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
|
||||||
DtoResolveTypeInfo(fd);
|
DtoResolveTypeInfo(fd);
|
||||||
}
|
}
|
||||||
else {
|
else if (VarDeclaration* vd = dsym->isVarDeclaration()) {
|
||||||
llvm_unreachable("Unsupported DSymbol for DtoResolveDsymbol.");
|
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
|
// static
|
||||||
if (vd->isDataseg())
|
if (vd->isDataseg())
|
||||||
{
|
{
|
||||||
vd->codegen(Type::sir);
|
vd->codegen(gIR);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1144,19 +1222,19 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
|
|||||||
else if (StructDeclaration* s = declaration->isStructDeclaration())
|
else if (StructDeclaration* s = declaration->isStructDeclaration())
|
||||||
{
|
{
|
||||||
Logger::println("StructDeclaration");
|
Logger::println("StructDeclaration");
|
||||||
s->codegen(Type::sir);
|
s->codegen(gIR);
|
||||||
}
|
}
|
||||||
// function declaration
|
// function declaration
|
||||||
else if (FuncDeclaration* f = declaration->isFuncDeclaration())
|
else if (FuncDeclaration* f = declaration->isFuncDeclaration())
|
||||||
{
|
{
|
||||||
Logger::println("FuncDeclaration");
|
Logger::println("FuncDeclaration");
|
||||||
f->codegen(Type::sir);
|
f->codegen(gIR);
|
||||||
}
|
}
|
||||||
// class
|
// class
|
||||||
else if (ClassDeclaration* e = declaration->isClassDeclaration())
|
else if (ClassDeclaration* e = declaration->isClassDeclaration())
|
||||||
{
|
{
|
||||||
Logger::println("ClassDeclaration");
|
Logger::println("ClassDeclaration");
|
||||||
e->codegen(Type::sir);
|
e->codegen(gIR);
|
||||||
}
|
}
|
||||||
// typedef
|
// typedef
|
||||||
else if (TypedefDeclaration* tdef = declaration->isTypedefDeclaration())
|
else if (TypedefDeclaration* tdef = declaration->isTypedefDeclaration())
|
||||||
@@ -1293,7 +1371,7 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
|
|||||||
else if (StructInitializer* si = init->isStructInitializer())
|
else if (StructInitializer* si = init->isStructInitializer())
|
||||||
{
|
{
|
||||||
Logger::println("const struct initializer");
|
Logger::println("const struct initializer");
|
||||||
si->ad->codegen(Type::sir);
|
DtoResolveDsymbol(si->ad);
|
||||||
return si->ad->ir.irAggr->createStructInitializer(si);
|
return si->ad->ir.irAggr->createStructInitializer(si);
|
||||||
}
|
}
|
||||||
else if (ArrayInitializer* ai = init->isArrayInitializer())
|
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)
|
LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp)
|
||||||
{
|
{
|
||||||
IF_LOG Logger::println("DtoConstExpInit(targetType = %s, exp = %s)",
|
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)
|
if (expBase->equals(targetBase) && targetBase->ty != Tbool)
|
||||||
{
|
{
|
||||||
Logger::println("Matching D types, nothing left to do.");
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1393,7 +1435,12 @@ LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp)
|
|||||||
fatal();
|
fatal();
|
||||||
}
|
}
|
||||||
Logger::println("Building constant array initializer to single value.");
|
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)
|
if (targetBase->ty == Tvector)
|
||||||
@@ -1428,11 +1475,14 @@ LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp)
|
|||||||
|
|
||||||
LLConstant* DtoTypeInfoOf(Type* type, bool base)
|
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 = type->merge2(); // needed.. getTypeInfo does the same
|
||||||
type->getTypeInfo(NULL);
|
type->getTypeInfo(NULL);
|
||||||
TypeInfoDeclaration* tidecl = type->vtinfo;
|
TypeInfoDeclaration* tidecl = type->vtinfo;
|
||||||
assert(tidecl);
|
assert(tidecl);
|
||||||
tidecl->codegen(Type::sir);
|
tidecl->codegen(gIR);
|
||||||
assert(tidecl->ir.irGlobal != NULL);
|
assert(tidecl->ir.irGlobal != NULL);
|
||||||
assert(tidecl->ir.irGlobal->value != NULL);
|
assert(tidecl->ir.irGlobal->value != NULL);
|
||||||
LLConstant* c = isaConstant(tidecl->ir.irGlobal->value);
|
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)
|
bool hasUnalignedFields(Type* t)
|
||||||
{
|
{
|
||||||
t = t->toBasetype();
|
t = t->toBasetype();
|
||||||
@@ -1732,7 +1690,7 @@ void callPostblit(Loc &loc, Expression *exp, LLValue *val)
|
|||||||
FuncDeclaration *fd = sd->postblit;
|
FuncDeclaration *fd = sd->postblit;
|
||||||
if (fd->storage_class & STCdisable)
|
if (fd->storage_class & STCdisable)
|
||||||
fd->toParent()->error(loc, "is not copyable because it is annotated with @disable");
|
fd->toParent()->error(loc, "is not copyable because it is annotated with @disable");
|
||||||
fd->codegen(Type::sir);
|
DtoResolveFunction(fd);
|
||||||
Expressions args;
|
Expressions args;
|
||||||
DFuncValue dfn(fd, fd->ir.irFunc->func, val);
|
DFuncValue dfn(fd, fd->ir.irFunc->func, val);
|
||||||
DtoCallFunction(loc, Type::basic[Tvoid], &dfn, &args);
|
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())
|
else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration())
|
||||||
{
|
{
|
||||||
Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
|
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());
|
return new DVarValue(type, vd, cid->cd->ir.irAggr->getClassInfoSymbol());
|
||||||
}
|
}
|
||||||
// typeinfo
|
// typeinfo
|
||||||
else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
|
else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
|
||||||
{
|
{
|
||||||
Logger::println("TypeInfoDeclaration");
|
Logger::println("TypeInfoDeclaration");
|
||||||
tid->codegen(Type::sir);
|
DtoResolveTypeInfo(tid);
|
||||||
assert(tid->ir.getIrValue());
|
assert(tid->ir.getIrValue());
|
||||||
LLType* vartype = DtoType(type);
|
LLType* vartype = DtoType(type);
|
||||||
LLValue* m = tid->ir.getIrValue();
|
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
|
// take care of forward references of global variables
|
||||||
const bool isGlobal = vd->isDataseg() || (vd->storage_class & STCextern);
|
const bool isGlobal = vd->isDataseg() || (vd->storage_class & STCextern);
|
||||||
if (isGlobal)
|
if (isGlobal)
|
||||||
vd->codegen(Type::sir);
|
DtoResolveVariable(vd);
|
||||||
|
|
||||||
assert(vd->ir.isSet() && "Variable not resolved.");
|
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())
|
if (FuncDeclaration* fdecl = decl->isFuncDeclaration())
|
||||||
{
|
{
|
||||||
Logger::println("FuncDeclaration");
|
Logger::println("FuncDeclaration");
|
||||||
LLValue* func = 0;
|
|
||||||
fdecl = fdecl->toAliasFunc();
|
fdecl = fdecl->toAliasFunc();
|
||||||
if (fdecl->llvmInternal == LLVMinline_asm)
|
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");
|
error("special ldc inline asm is not a normal function");
|
||||||
fatal();
|
fatal();
|
||||||
}
|
}
|
||||||
else if (fdecl->llvmInternal != LLVMva_arg)
|
DtoResolveFunction(fdecl);
|
||||||
{
|
return new DFuncValue(fdecl, fdecl->ir.irFunc->func);
|
||||||
fdecl->codegen(Type::sir);
|
|
||||||
func = fdecl->ir.irFunc->func;
|
|
||||||
}
|
|
||||||
return new DFuncValue(fdecl, func);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SymbolDeclaration* sdecl = decl->isSymbolDeclaration())
|
if (SymbolDeclaration* sdecl = decl->isSymbolDeclaration())
|
||||||
@@ -1973,7 +1927,7 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl)
|
|||||||
assert(sdecltype->ty == Tstruct);
|
assert(sdecltype->ty == Tstruct);
|
||||||
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
|
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
|
||||||
assert(ts->sym);
|
assert(ts->sym);
|
||||||
ts->sym->codegen(Type::sir);
|
DtoResolveStruct(ts->sym);
|
||||||
|
|
||||||
LLValue* initsym = ts->sym->ir.irAggr->getInitSymbol();
|
LLValue* initsym = ts->sym->ir.irAggr->getInitSymbol();
|
||||||
initsym = DtoBitCast(initsym, DtoType(ts->pointerTo()));
|
initsym = DtoBitCast(initsym, DtoType(ts->pointerTo()));
|
||||||
@@ -2009,7 +1963,7 @@ llvm::Constant* DtoConstSymbolAddress(const Loc& loc, Declaration* decl)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
vd->codegen(Type::sir);
|
DtoResolveVariable(vd);
|
||||||
LLConstant* llc = llvm::dyn_cast<LLConstant>(vd->ir.getIrValue());
|
LLConstant* llc = llvm::dyn_cast<LLConstant>(vd->ir.getIrValue());
|
||||||
assert(llc);
|
assert(llc);
|
||||||
return llc;
|
return llc;
|
||||||
@@ -2017,7 +1971,7 @@ llvm::Constant* DtoConstSymbolAddress(const Loc& loc, Declaration* decl)
|
|||||||
// static function
|
// static function
|
||||||
else if (FuncDeclaration* fd = decl->isFuncDeclaration())
|
else if (FuncDeclaration* fd = decl->isFuncDeclaration())
|
||||||
{
|
{
|
||||||
fd->codegen(Type::sir);
|
DtoResolveFunction(fd);
|
||||||
IrFunction* irfunc = fd->ir.irFunc;
|
IrFunction* irfunc = fd->ir.irFunc;
|
||||||
return irfunc->func;
|
return irfunc->func;
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -102,9 +102,15 @@ DValue* DtoPaintType(Loc& loc, DValue* val, Type* to);
|
|||||||
// is template instance check, returns module where instantiated
|
// is template instance check, returns module where instantiated
|
||||||
TemplateInstance* DtoIsTemplateInstance(Dsymbol* s, bool checkLiteralOwner = false);
|
TemplateInstance* DtoIsTemplateInstance(Dsymbol* s, bool checkLiteralOwner = false);
|
||||||
|
|
||||||
/// Generate code for the symbol.
|
/// Makes sure the declarations corresponding to the given D symbol have been
|
||||||
/// Dispatches as appropriate.
|
/// 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 DtoResolveDsymbol(Dsymbol* dsym);
|
||||||
|
void DtoResolveVariable(VarDeclaration* var);
|
||||||
|
|
||||||
// declaration inside a declarationexp
|
// declaration inside a declarationexp
|
||||||
void DtoVarDeclaration(VarDeclaration* var);
|
void DtoVarDeclaration(VarDeclaration* var);
|
||||||
@@ -135,12 +141,6 @@ void findDefaultTarget();
|
|||||||
/// Fixup an overloaded intrinsic name string.
|
/// Fixup an overloaded intrinsic name string.
|
||||||
void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name);
|
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.
|
/// Returns true if there is any unaligned type inside the aggregate.
|
||||||
bool hasUnalignedFields(Type* t);
|
bool hasUnalignedFields(Type* t);
|
||||||
|
|
||||||
|
|||||||
+6
-15
@@ -326,7 +326,7 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
|
|||||||
return ctor;
|
return ctor;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir)
|
llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context)
|
||||||
{
|
{
|
||||||
bool logenabled = Logger::enabled();
|
bool logenabled = Logger::enabled();
|
||||||
if (llvmForceLogging && !logenabled)
|
if (llvmForceLogging && !logenabled)
|
||||||
@@ -363,8 +363,6 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir)
|
|||||||
// reset all IR data stored in Dsymbols
|
// reset all IR data stored in Dsymbols
|
||||||
IrDsymbol::resetAll();
|
IrDsymbol::resetAll();
|
||||||
|
|
||||||
sir->setState(&ir);
|
|
||||||
|
|
||||||
// set target triple
|
// set target triple
|
||||||
ir.module->setTargetTriple(global.params.targetTriple.str());
|
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++) {
|
for (unsigned k=0; k < members->dim; k++) {
|
||||||
Dsymbol* dsym = static_cast<Dsymbol*>(members->data[k]);
|
Dsymbol* dsym = static_cast<Dsymbol*>(members->data[k]);
|
||||||
assert(dsym);
|
assert(dsym);
|
||||||
dsym->codegen(sir);
|
dsym->codegen(&ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// emit function bodies
|
|
||||||
sir->emitFunctionBodies();
|
|
||||||
|
|
||||||
// for singleobj-compilation, fully emit all seen template instances
|
// for singleobj-compilation, fully emit all seen template instances
|
||||||
if (global.params.singleObj)
|
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();
|
IRState::TemplateInstanceSet::iterator it, end = ir.seenTemplateInstances.end();
|
||||||
for (it = ir.seenTemplateInstances.begin(); it != end; ++it)
|
for (it = ir.seenTemplateInstances.begin(); it != end; ++it)
|
||||||
(*it)->codegen(sir);
|
(*it)->codegen(&ir);
|
||||||
ir.seenTemplateInstances.clear();
|
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();
|
Logger::disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
sir->setState(NULL);
|
|
||||||
|
|
||||||
return ir.module;
|
return ir.module;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,8 +522,8 @@ void Module::genmoduleinfo()
|
|||||||
std::vector<LLConstant*> classInits;
|
std::vector<LLConstant*> classInits;
|
||||||
for (size_t i = 0; i < aclasses.dim; i++)
|
for (size_t i = 0; i < aclasses.dim; i++)
|
||||||
{
|
{
|
||||||
ClassDeclaration* cd = static_cast<ClassDeclaration*>(aclasses.data[i]);
|
ClassDeclaration* cd = aclasses[i];
|
||||||
cd->codegen(Type::sir);
|
DtoResolveClass(cd);
|
||||||
|
|
||||||
if (cd->isInterfaceDeclaration())
|
if (cd->isInterfaceDeclaration())
|
||||||
{
|
{
|
||||||
@@ -638,6 +628,7 @@ void Module::genmoduleinfo()
|
|||||||
// create and set initializer
|
// create and set initializer
|
||||||
LLGlobalVariable *moduleInfoSym = moduleInfoSymbol();
|
LLGlobalVariable *moduleInfoSym = moduleInfoSymbol();
|
||||||
b.finalize(moduleInfoSym->getType()->getPointerElementType(), moduleInfoSym);
|
b.finalize(moduleInfoSym->getType()->getPointerElementType(), moduleInfoSym);
|
||||||
|
moduleInfoSym->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
||||||
|
|
||||||
// build the modulereference and ctor for registering it
|
// build the modulereference and ctor for registering it
|
||||||
LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSym);
|
LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSym);
|
||||||
|
|||||||
+2
-1
@@ -85,7 +85,8 @@ void ExpStatement::toNakedIR(IRState *p)
|
|||||||
// enum decls should always be safe
|
// enum decls should always be safe
|
||||||
|
|
||||||
// make sure the symbols gets processed
|
// make sure the symbols gets processed
|
||||||
d->declaration->codegen(Type::sir);
|
// TODO: codegen() here is likely incorrect
|
||||||
|
d->declaration->codegen(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
+6
-4
@@ -11,6 +11,7 @@
|
|||||||
#include "aggregate.h"
|
#include "aggregate.h"
|
||||||
#include "mtype.h"
|
#include "mtype.h"
|
||||||
#include "gen/arrays.h"
|
#include "gen/arrays.h"
|
||||||
|
#include "gen/functions.h"
|
||||||
#include "gen/irstate.h"
|
#include "gen/irstate.h"
|
||||||
#include "gen/linkage.h"
|
#include "gen/linkage.h"
|
||||||
#include "gen/llvm.h"
|
#include "gen/llvm.h"
|
||||||
@@ -20,8 +21,7 @@
|
|||||||
|
|
||||||
RTTIBuilder::RTTIBuilder(AggregateDeclaration* base_class)
|
RTTIBuilder::RTTIBuilder(AggregateDeclaration* base_class)
|
||||||
{
|
{
|
||||||
// make sure the base typeinfo class has been processed
|
DtoResolveDsymbol(base_class);
|
||||||
base_class->codegen(Type::sir);
|
|
||||||
|
|
||||||
base = base_class;
|
base = base_class;
|
||||||
basetype = static_cast<TypeClass*>(base->type);
|
basetype = static_cast<TypeClass*>(base->type);
|
||||||
@@ -136,7 +136,7 @@ void RTTIBuilder::push_funcptr(FuncDeclaration* fd, Type* castto)
|
|||||||
{
|
{
|
||||||
if (fd)
|
if (fd)
|
||||||
{
|
{
|
||||||
fd->codegen(Type::sir);
|
DtoResolveFunction(fd);
|
||||||
LLConstant* F = fd->ir.irFunc->func;
|
LLConstant* F = fd->ir.irFunc->func;
|
||||||
if (castto)
|
if (castto)
|
||||||
F = DtoBitCast(F, DtoType(castto));
|
F = DtoBitCast(F, DtoType(castto));
|
||||||
@@ -177,7 +177,9 @@ void RTTIBuilder::finalize(LLType* type, LLValue* value)
|
|||||||
LLConstant* tiInit = LLConstantStruct::get(st, inits);
|
LLConstant* tiInit = LLConstantStruct::get(st, inits);
|
||||||
|
|
||||||
// set the initializer
|
// 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)
|
LLConstant* RTTIBuilder::get_constant(LLStructType *initType)
|
||||||
|
|||||||
@@ -55,32 +55,6 @@ void DtoResolveStruct(StructDeclaration* sd)
|
|||||||
assert(!vd->ir.irField);
|
assert(!vd->ir.irField);
|
||||||
(void)new IrField(vd);
|
(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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
+8
-10
@@ -10,14 +10,10 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
#include "gen/irstate.h"
|
||||||
#include "mars.h"
|
#include "mars.h"
|
||||||
#include "mtype.h"
|
#include "mtype.h"
|
||||||
|
|
||||||
unsigned GetTypeAlignment(Type* t);
|
|
||||||
unsigned GetPointerSize();
|
|
||||||
unsigned GetTypeStoreSize(Type* t);
|
|
||||||
unsigned GetTypeAllocSize(Type* t);
|
|
||||||
|
|
||||||
int Target::ptrsize;
|
int Target::ptrsize;
|
||||||
int Target::realsize;
|
int Target::realsize;
|
||||||
int Target::realpad;
|
int Target::realpad;
|
||||||
@@ -25,10 +21,12 @@ int Target::realalignsize;
|
|||||||
|
|
||||||
void Target::init()
|
void Target::init()
|
||||||
{
|
{
|
||||||
ptrsize = GetPointerSize();
|
ptrsize = gDataLayout->getPointerSize(ADDRESS_SPACE);
|
||||||
realsize = GetTypeAllocSize(Type::basic[Tfloat80]);
|
|
||||||
realpad = realsize - GetTypeStoreSize(Type::basic[Tfloat80]);
|
llvm::Type* real = DtoType(Type::basic[Tfloat80]);
|
||||||
realalignsize = GetTypeAlignment(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());
|
assert (type->isTypeBasic());
|
||||||
if (type->ty == Tvoid) return 1;
|
if (type->ty == Tvoid) return 1;
|
||||||
return GetTypeAlignment(type);
|
return gDataLayout->getABITypeAlignment(DtoType(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************
|
/******************************
|
||||||
|
|||||||
+36
-20
@@ -13,6 +13,7 @@
|
|||||||
#include "id.h"
|
#include "id.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "mtype.h"
|
#include "mtype.h"
|
||||||
|
#include "module.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
#include "rmem.h"
|
#include "rmem.h"
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
@@ -200,8 +201,7 @@ LLConstant* VarExp::toConstElem(IRState* p)
|
|||||||
Logger::print("Sym: type=%s\n", sdecltype->toChars());
|
Logger::print("Sym: type=%s\n", sdecltype->toChars());
|
||||||
assert(sdecltype->ty == Tstruct);
|
assert(sdecltype->ty == Tstruct);
|
||||||
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
|
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
|
||||||
ts->sym->codegen(Type::sir);
|
DtoResolveStruct(ts->sym);
|
||||||
|
|
||||||
return ts->sym->ir.irAggr->getDefaultInit();
|
return ts->sym->ir.irAggr->getDefaultInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1186,7 +1186,7 @@ LLConstant* CastExp::toConstElem(IRState* p)
|
|||||||
else if (tb->ty == Tpointer && e1->op == TOKvar) {
|
else if (tb->ty == Tpointer && e1->op == TOKvar) {
|
||||||
VarDeclaration *vd = static_cast<VarExp*>(e1)->var->isVarDeclaration();
|
VarDeclaration *vd = static_cast<VarExp*>(e1)->var->isVarDeclaration();
|
||||||
assert(vd);
|
assert(vd);
|
||||||
vd->codegen(Type::sir);
|
DtoResolveVariable(vd);
|
||||||
LLConstant *value = vd->ir.irGlobal ? isaConstant(vd->ir.irGlobal->value) : 0;
|
LLConstant *value = vd->ir.irGlobal ? isaConstant(vd->ir.irGlobal->value) : 0;
|
||||||
if (!value)
|
if (!value)
|
||||||
goto Lerr;
|
goto Lerr;
|
||||||
@@ -1355,7 +1355,7 @@ DValue* AddrExp::toElem(IRState* p)
|
|||||||
//Logger::println("FuncDeclaration");
|
//Logger::println("FuncDeclaration");
|
||||||
FuncDeclaration* fd = fv->func;
|
FuncDeclaration* fd = fv->func;
|
||||||
assert(fd);
|
assert(fd);
|
||||||
fd->codegen(Type::sir);
|
DtoResolveFunction(fd);
|
||||||
return new DFuncValue(fd, fd->ir.irFunc->func);
|
return new DFuncValue(fd, fd->ir.irFunc->func);
|
||||||
}
|
}
|
||||||
else if (v->isIm()) {
|
else if (v->isIm()) {
|
||||||
@@ -1407,7 +1407,7 @@ LLConstant* AddrExp::toConstElem(IRState* p)
|
|||||||
VarDeclaration* vd = vexp->var->isVarDeclaration();
|
VarDeclaration* vd = vexp->var->isVarDeclaration();
|
||||||
assert(vd);
|
assert(vd);
|
||||||
assert(vd->type->toBasetype()->ty == Tsarray);
|
assert(vd->type->toBasetype()->ty == Tsarray);
|
||||||
vd->codegen(Type::sir);
|
DtoResolveVariable(vd);
|
||||||
assert(vd->ir.irGlobal);
|
assert(vd->ir.irGlobal);
|
||||||
|
|
||||||
// get index
|
// get index
|
||||||
@@ -1585,7 +1585,7 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||||||
}
|
}
|
||||||
else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
|
else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
|
||||||
{
|
{
|
||||||
DtoResolveDsymbol(fdecl);
|
DtoResolveFunction(fdecl);
|
||||||
|
|
||||||
// This is a bit more convoluted than it would need to be, because it
|
// This is a bit more convoluted than it would need to be, because it
|
||||||
// has to take templated interface methods into account, for which
|
// has to take templated interface methods into account, for which
|
||||||
@@ -1632,7 +1632,6 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fdecl->codegen(Type::sir);
|
|
||||||
funcval = fdecl->ir.irFunc->func;
|
funcval = fdecl->ir.irFunc->func;
|
||||||
}
|
}
|
||||||
assert(funcval);
|
assert(funcval);
|
||||||
@@ -2123,7 +2122,7 @@ DValue* NewExp::toElem(IRState* p)
|
|||||||
if (allocator)
|
if (allocator)
|
||||||
{
|
{
|
||||||
// custom allocator
|
// custom allocator
|
||||||
allocator->codegen(Type::sir);
|
DtoResolveFunction(allocator);
|
||||||
DFuncValue dfn(allocator, allocator->ir.irFunc->func);
|
DFuncValue dfn(allocator, allocator->ir.irFunc->func);
|
||||||
DValue* res = DtoCallFunction(loc, NULL, &dfn, newargs);
|
DValue* res = DtoCallFunction(loc, NULL, &dfn, newargs);
|
||||||
mem = DtoBitCast(res->getRVal(), DtoType(ntype->pointerTo()), ".newstruct_custom");
|
mem = DtoBitCast(res->getRVal(), DtoType(ntype->pointerTo()), ".newstruct_custom");
|
||||||
@@ -2139,7 +2138,7 @@ DValue* NewExp::toElem(IRState* p)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert(ts->sym);
|
assert(ts->sym);
|
||||||
ts->sym->codegen(Type::sir);
|
DtoResolveStruct(ts->sym);
|
||||||
DtoAggrCopy(mem, ts->sym->ir.irAggr->getInitSymbol());
|
DtoAggrCopy(mem, ts->sym->ir.irAggr->getInitSymbol());
|
||||||
}
|
}
|
||||||
if (ts->sym->isNested() && ts->sym->vthis)
|
if (ts->sym->isNested() && ts->sym->vthis)
|
||||||
@@ -2150,7 +2149,7 @@ DValue* NewExp::toElem(IRState* p)
|
|||||||
{
|
{
|
||||||
Logger::println("Calling constructor");
|
Logger::println("Calling constructor");
|
||||||
assert(arguments != NULL);
|
assert(arguments != NULL);
|
||||||
member->codegen(Type::sir);
|
DtoResolveFunction(member);
|
||||||
DFuncValue dfn(member, member->ir.irFunc->func, mem);
|
DFuncValue dfn(member, member->ir.irFunc->func, mem);
|
||||||
DtoCallFunction(loc, ts, &dfn, arguments);
|
DtoCallFunction(loc, ts, &dfn, arguments);
|
||||||
}
|
}
|
||||||
@@ -2313,7 +2312,7 @@ DValue* AssertExp::toElem(IRState* p)
|
|||||||
(invdecl = static_cast<TypeStruct*>(condty->nextOf())->sym->inv) != NULL)
|
(invdecl = static_cast<TypeStruct*>(condty->nextOf())->sym->inv) != NULL)
|
||||||
{
|
{
|
||||||
Logger::print("calling struct invariant");
|
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());
|
DFuncValue invfunc(invdecl, invdecl->ir.irFunc->func, cond->getRVal());
|
||||||
DtoCallFunction(loc, NULL, &invfunc, NULL);
|
DtoCallFunction(loc, NULL, &invfunc, NULL);
|
||||||
}
|
}
|
||||||
@@ -2541,7 +2540,21 @@ DValue* DelegateExp::toElem(IRState* p)
|
|||||||
llvm_unreachable("Delegate to interface method not implemented.");
|
llvm_unreachable("Delegate to interface method not implemented.");
|
||||||
else
|
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;
|
castfptr = func->ir.irFunc->func;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2785,7 +2798,9 @@ DValue* FuncExp::toElem(IRState* p)
|
|||||||
if (fd->isNested()) Logger::println("nested");
|
if (fd->isNested()) Logger::println("nested");
|
||||||
Logger::println("kind = %s", fd->kind());
|
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);
|
assert(fd->ir.irFunc->func);
|
||||||
|
|
||||||
if (fd->isNested()) {
|
if (fd->isNested()) {
|
||||||
@@ -2852,7 +2867,9 @@ LLConstant* FuncExp::toConstElem(IRState* p)
|
|||||||
return 0;
|
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);
|
assert(fd->ir.irFunc->func);
|
||||||
|
|
||||||
return fd->ir.irFunc->func;
|
return fd->ir.irFunc->func;
|
||||||
@@ -2987,7 +3004,7 @@ DValue* StructLiteralExp::toElem(IRState* p)
|
|||||||
assert(sdecltype->ty == Tstruct);
|
assert(sdecltype->ty == Tstruct);
|
||||||
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
|
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
|
||||||
assert(ts->sym);
|
assert(ts->sym);
|
||||||
ts->sym->codegen(Type::sir);
|
DtoResolveStruct(ts->sym);
|
||||||
|
|
||||||
LLValue* initsym = ts->sym->ir.irAggr->getInitSymbol();
|
LLValue* initsym = ts->sym->ir.irAggr->getInitSymbol();
|
||||||
initsym = DtoBitCast(initsym, DtoType(ts->pointerTo()));
|
initsym = DtoBitCast(initsym, DtoType(ts->pointerTo()));
|
||||||
@@ -2997,7 +3014,7 @@ DValue* StructLiteralExp::toElem(IRState* p)
|
|||||||
if (inProgressMemory) return new DVarValue(type, inProgressMemory);
|
if (inProgressMemory) return new DVarValue(type, inProgressMemory);
|
||||||
|
|
||||||
// make sure the struct is fully resolved
|
// make sure the struct is fully resolved
|
||||||
sd->codegen(Type::sir);
|
DtoResolveStruct(sd);
|
||||||
|
|
||||||
// alloca a stack slot
|
// alloca a stack slot
|
||||||
inProgressMemory = DtoRawAlloca(DtoType(type), 0, ".structliteral");
|
inProgressMemory = DtoRawAlloca(DtoType(type), 0, ".structliteral");
|
||||||
@@ -3101,13 +3118,13 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p)
|
|||||||
Logger::print("Sym: type=%s\n", sdecltype->toChars());
|
Logger::print("Sym: type=%s\n", sdecltype->toChars());
|
||||||
assert(sdecltype->ty == Tstruct);
|
assert(sdecltype->ty == Tstruct);
|
||||||
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
|
TypeStruct* ts = static_cast<TypeStruct*>(sdecltype);
|
||||||
ts->sym->codegen(Type::sir);
|
DtoResolveStruct(ts->sym);
|
||||||
|
|
||||||
return ts->sym->ir.irAggr->getDefaultInit();
|
return ts->sym->ir.irAggr->getDefaultInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the struct is resolved
|
// make sure the struct is resolved
|
||||||
sd->codegen(Type::sir);
|
DtoResolveStruct(sd);
|
||||||
|
|
||||||
std::map<VarDeclaration*, llvm::Constant*> varInits;
|
std::map<VarDeclaration*, llvm::Constant*> varInits;
|
||||||
const size_t nexprs = elements->dim;
|
const size_t nexprs = elements->dim;
|
||||||
@@ -3129,8 +3146,7 @@ llvm::Constant* ClassReferenceExp::toConstElem(IRState *p)
|
|||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
ClassDeclaration* origClass = originalClass();
|
ClassDeclaration* origClass = originalClass();
|
||||||
|
DtoResolveClass(origClass);
|
||||||
origClass->codegen(Type::sir);
|
|
||||||
|
|
||||||
if (value->globalVar)
|
if (value->globalVar)
|
||||||
{
|
{
|
||||||
|
|||||||
+40
-63
@@ -294,22 +294,17 @@ LLValue* DtoDelegateEquals(TOK op, LLValue* lhs, LLValue* rhs)
|
|||||||
|
|
||||||
LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
|
LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
|
||||||
{
|
{
|
||||||
const bool mustDefine = mustDefineSymbol(sym);
|
|
||||||
|
|
||||||
// global/static variable
|
// global/static variable
|
||||||
if (VarDeclaration* vd = sym->isVarDeclaration())
|
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
|
// generated by inlining semantics run
|
||||||
if (vd->availableExternally && mustDefine)
|
if (vd->availableExternally)
|
||||||
return llvm::GlobalValue::AvailableExternallyLinkage;
|
return llvm::GlobalValue::AvailableExternallyLinkage;
|
||||||
// template
|
// template
|
||||||
if (needsTemplateLinkage(sym))
|
if (DtoIsTemplateInstance(sym))
|
||||||
return templateLinkage;
|
return templateLinkage;
|
||||||
|
|
||||||
// Currently, we have to consider all variables, even function-local
|
// 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())
|
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);
|
assert(fdecl->type->ty == Tfunction);
|
||||||
TypeFunction* ft = static_cast<TypeFunction*>(fdecl->type);
|
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
|
// available_externally. Naked functions are turned into module-level
|
||||||
// inline asm and are thus declaration-only as far as the LLVM IR level
|
// inline asm and are thus declaration-only as far as the LLVM IR level
|
||||||
// is concerned.
|
// is concerned.
|
||||||
if (fdecl->availableExternally && mustDefine && !fdecl->naked)
|
if (fdecl->availableExternally && !fdecl->naked)
|
||||||
return llvm::GlobalValue::AvailableExternallyLinkage;
|
return llvm::GlobalValue::AvailableExternallyLinkage;
|
||||||
|
|
||||||
// array operations are always template linkage
|
// array operations are always template linkage
|
||||||
@@ -357,7 +349,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
|
|||||||
// template instances should have weak linkage
|
// template instances should have weak linkage
|
||||||
// but only if there's a body, and it's not naked
|
// but only if there's a body, and it's not naked
|
||||||
// otherwise we make it external
|
// otherwise we make it external
|
||||||
if (needsTemplateLinkage(fdecl) && fdecl->fbody && !fdecl->naked)
|
if (DtoIsTemplateInstance(fdecl) && fdecl->fbody && !fdecl->naked)
|
||||||
return templateLinkage;
|
return templateLinkage;
|
||||||
|
|
||||||
// extern(C) functions are always external
|
// extern(C) functions are always external
|
||||||
@@ -375,16 +367,14 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
|
|||||||
// class
|
// class
|
||||||
else if (ClassDeclaration* cd = sym->isClassDeclaration())
|
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
|
// generated by inlining semantics run
|
||||||
if (cd->availableExternally && mustDefine)
|
if (cd->availableExternally)
|
||||||
return llvm::GlobalValue::AvailableExternallyLinkage;
|
return llvm::GlobalValue::AvailableExternallyLinkage;
|
||||||
// template
|
// template
|
||||||
if (needsTemplateLinkage(cd))
|
if (DtoIsTemplateInstance(cd))
|
||||||
return templateLinkage;
|
return templateLinkage;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -392,10 +382,8 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
|
|||||||
llvm_unreachable("not global/function");
|
llvm_unreachable("not global/function");
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the function needs to be defined in the current module, check if it
|
// Check if sym is a nested function and we can declare it as internal.
|
||||||
// is a nested function and we can declare it as internal.
|
//
|
||||||
bool canInternalize = mustDefine;
|
|
||||||
|
|
||||||
// Nested naked functions and the implicitly generated __require/__ensure
|
// Nested naked functions and the implicitly generated __require/__ensure
|
||||||
// functions for in/out contracts cannot be internalized. The reason
|
// functions for in/out contracts cannot be internalized. The reason
|
||||||
// for the latter is that contract functions, despite being nested, can be
|
// 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
|
// interface methods (where __require/__ensure are emitted to the module
|
||||||
// where the interface is declared, but an actual interface implementation
|
// where the interface is declared, but an actual interface implementation
|
||||||
// can be in a completely different place).
|
// can be in a completely different place).
|
||||||
if (canInternalize)
|
FuncDeclaration* fd = sym->isFuncDeclaration();
|
||||||
{
|
if (!fd || (!fd->naked && fd->ident != Id::require && fd->ident != Id::ensure))
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
// 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)
|
for (Dsymbol* parent = sym->parent; parent ; parent = parent->parent)
|
||||||
{
|
{
|
||||||
FuncDeclaration *fd = parent->isFuncDeclaration();
|
FuncDeclaration *parentFd = parent->isFuncDeclaration();
|
||||||
if (fd && !fd->canInline(fd->needThis(), false, false))
|
if (parentFd && !parentFd->canInline(parentFd->needThis(), false, false))
|
||||||
{
|
{
|
||||||
// We also cannot internalize nested functions which are
|
// We also cannot internalize nested functions which are
|
||||||
// leaked to the outside via a templated return type, because
|
// 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
|
// Since we can't easily determine if this is really the case
|
||||||
// here, just don't internalize it if the parent returns a
|
// here, just don't internalize it if the parent returns a
|
||||||
// template at all, to be safe.
|
// template at all, to be safe.
|
||||||
TypeFunction* tf = static_cast<TypeFunction*>(fd->type);
|
TypeFunction* tf = static_cast<TypeFunction*>(parentFd->type);
|
||||||
if (!DtoIsTemplateInstance(tf->next->toDsymbol(fd->scope)))
|
if (!DtoIsTemplateInstance(tf->next->toDsymbol(parentFd->scope)))
|
||||||
return llvm::GlobalValue::InternalLinkage;
|
return llvm::GlobalValue::InternalLinkage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -468,8 +445,8 @@ static bool isAvailableExternally(Dsymbol* sym)
|
|||||||
|
|
||||||
llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
|
llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
|
||||||
{
|
{
|
||||||
if (needsTemplateLinkage(sym)) {
|
if (DtoIsTemplateInstance(sym)) {
|
||||||
if (isAvailableExternally(sym) && mustDefineSymbol(sym))
|
if (isAvailableExternally(sym))
|
||||||
return llvm::GlobalValue::AvailableExternallyLinkage;
|
return llvm::GlobalValue::AvailableExternallyLinkage;
|
||||||
return templateLinkage;
|
return templateLinkage;
|
||||||
}
|
}
|
||||||
@@ -479,9 +456,9 @@ llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
|
|||||||
|
|
||||||
llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym)
|
llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym)
|
||||||
{
|
{
|
||||||
if (needsTemplateLinkage(sym))
|
if (DtoIsTemplateInstance(sym))
|
||||||
return templateLinkage;
|
return templateLinkage;
|
||||||
else if (isAvailableExternally(sym) && mustDefineSymbol(sym))
|
else if (isAvailableExternally(sym))
|
||||||
return llvm::GlobalValue::AvailableExternallyLinkage;
|
return llvm::GlobalValue::AvailableExternallyLinkage;
|
||||||
else
|
else
|
||||||
return llvm::GlobalValue::ExternalLinkage;
|
return llvm::GlobalValue::ExternalLinkage;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
struct TypeInfoDeclaration;
|
struct TypeInfoDeclaration;
|
||||||
void DtoResolveTypeInfo(TypeInfoDeclaration* tid);
|
void DtoResolveTypeInfo(TypeInfoDeclaration* tid);
|
||||||
void DtoDeclareTypeInfo(TypeInfoDeclaration* tid);
|
|
||||||
void DtoConstInitTypeInfo(TypeInfoDeclaration* tid);
|
void DtoConstInitTypeInfo(TypeInfoDeclaration* tid);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+59
-57
@@ -115,7 +115,9 @@ Expression *Type::getInternalTypeInfo(Scope *sc)
|
|||||||
|
|
||||||
Expression *Type::getTypeInfo(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)
|
if (!Type::typeinfo)
|
||||||
{
|
{
|
||||||
error(Loc(), "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch");
|
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
|
else // if in obj generation pass
|
||||||
{
|
{
|
||||||
t->vtinfo->codegen(sir);
|
t->vtinfo->codegen(gIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,40 +282,8 @@ int TypeClass::builtinTypeInfo()
|
|||||||
// (wut?)
|
// (wut?)
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void DtoResolveTypeInfo(TypeInfoDeclaration* tid);
|
static void emitTypeMetadata(TypeInfoDeclaration *tid)
|
||||||
void DtoDeclareTypeInfo(TypeInfoDeclaration* tid);
|
|
||||||
|
|
||||||
void TypeInfoDeclaration::codegen(Ir*)
|
|
||||||
{
|
{
|
||||||
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
|
// 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
|
// 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.
|
// 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();
|
Type* t = tid->tinfo->toBasetype();
|
||||||
if (t->ty < Terror && t->ty != Tvoid && t->ty != Tfunction && t->ty != Tident) {
|
if (t->ty < Terror && t->ty != Tvoid && t->ty != Tfunction && t->ty != Tident) {
|
||||||
// Add some metadata for use by optimization passes.
|
// 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);
|
llvm::NamedMDNode* meta = gIR->module->getNamedMetadata(metaname);
|
||||||
|
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
// Construct the fields
|
// Construct the fields
|
||||||
MDNodeField* mdVals[TD_NumFields];
|
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));
|
mdVals[TD_Type] = llvm::UndefValue::get(DtoType(tid->tinfo));
|
||||||
|
|
||||||
// Construct the metadata and insert it into the module.
|
// Construct the metadata and insert it into the module.
|
||||||
@@ -337,39 +308,59 @@ void DtoResolveTypeInfo(TypeInfoDeclaration* tid)
|
|||||||
llvm::makeArrayRef(mdVals, TD_NumFields)));
|
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;
|
// TypeInfo instances (except ClassInfo ones) are always emitted as weak
|
||||||
tid->ir.declared = true;
|
// 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;
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
if (ir.defined) return;
|
||||||
|
ir.defined = true;
|
||||||
|
|
||||||
|
std::string mangled(mangle());
|
||||||
if (Logger::enabled())
|
if (Logger::enabled())
|
||||||
{
|
{
|
||||||
std::string mangled(tid->mangle());
|
Logger::println("type = '%s'", tinfo->toChars());
|
||||||
Logger::println("type = '%s'", tid->tinfo->toChars());
|
|
||||||
Logger::println("typeinfo mangle: %s", mangled.c_str());
|
Logger::println("typeinfo mangle: %s", mangled.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
IrGlobal* irg = tid->ir.irGlobal;
|
IrGlobal* irg = new IrGlobal(this);
|
||||||
assert(irg->value != NULL);
|
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
|
// this is a declaration of a builtin __initZ var
|
||||||
if (tid->tinfo->builtinTypeInfo()) {
|
if (tinfo->builtinTypeInfo()) {
|
||||||
LLGlobalVariable* g = isaGlobalVar(irg->value);
|
LLGlobalVariable* g = isaGlobalVar(irg->value);
|
||||||
g->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
g->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// define custom typedef
|
// define custom typedef
|
||||||
tid->llvmDefine();
|
llvmDefine();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
@@ -611,7 +602,7 @@ void TypeInfoStructDeclaration::llvmDefine()
|
|||||||
fatal();
|
fatal();
|
||||||
}
|
}
|
||||||
|
|
||||||
sd->codegen(Type::sir);
|
DtoResolveStruct(sd);
|
||||||
IrAggr* iraggr = sd->ir.irAggr;
|
IrAggr* iraggr = sd->ir.irAggr;
|
||||||
|
|
||||||
RTTIBuilder b(Type::typeinfostruct);
|
RTTIBuilder b(Type::typeinfostruct);
|
||||||
@@ -737,20 +728,31 @@ void TypeInfoStructDeclaration::llvmDefine()
|
|||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
void TypeInfoClassDeclaration::codegen(Ir*i)
|
void TypeInfoClassDeclaration::codegen(IRState *p)
|
||||||
{
|
{
|
||||||
|
// For classes, the TypeInfo is in fact a ClassInfo instance and emitted
|
||||||
IrGlobal* irg = new IrGlobal(this);
|
// 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;
|
ir.irGlobal = irg;
|
||||||
|
|
||||||
assert(tinfo->ty == Tclass);
|
assert(tinfo->ty == Tclass);
|
||||||
TypeClass *tc = static_cast<TypeClass *>(tinfo);
|
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->value = tc->sym->ir.irAggr->getClassInfoSymbol();
|
||||||
|
irg->type = irg->value->getType()->getContainedType(0);
|
||||||
|
|
||||||
|
if (!tc->sym->isInterfaceDeclaration())
|
||||||
|
{
|
||||||
|
emitTypeMetadata(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeInfoClassDeclaration::llvmDefine()
|
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
|
// make sure interface is resolved
|
||||||
assert(tinfo->ty == Tclass);
|
assert(tinfo->ty == Tclass);
|
||||||
TypeClass *tc = static_cast<TypeClass *>(tinfo);
|
TypeClass *tc = static_cast<TypeClass *>(tinfo);
|
||||||
tc->sym->codegen(Type::sir);
|
DtoResolveClass(tc->sym);
|
||||||
|
|
||||||
RTTIBuilder b(Type::typeinfointerface);
|
RTTIBuilder b(Type::typeinfointerface);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
+9
-6
@@ -61,10 +61,8 @@ LLGlobalVariable * IrAggr::getInitSymbol()
|
|||||||
initname.append(aggrdecl->mangle());
|
initname.append(aggrdecl->mangle());
|
||||||
initname.append("6__initZ");
|
initname.append("6__initZ");
|
||||||
|
|
||||||
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
|
|
||||||
|
|
||||||
init = getOrCreateGlobal(aggrdecl->loc,
|
init = getOrCreateGlobal(aggrdecl->loc,
|
||||||
*gIR->module, init_type, true, _linkage, NULL, initname);
|
*gIR->module, init_type, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);
|
||||||
|
|
||||||
// set alignment
|
// set alignment
|
||||||
init->setAlignment(type->alignsize());
|
init->setAlignment(type->alignsize());
|
||||||
@@ -207,14 +205,19 @@ LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init)
|
|||||||
{
|
{
|
||||||
return DtoConstInitializer(init->loc, vd->type, init);
|
return DtoConstInitializer(init->loc, vd->type, init);
|
||||||
}
|
}
|
||||||
else if (vd->init)
|
|
||||||
|
if (vd->init)
|
||||||
{
|
{
|
||||||
return DtoConstInitializer(vd->init->loc, vd->type, 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
|
// return a constant array of type arrTypeD initialized with a constant value, or that constant value
|
||||||
|
|||||||
+2
-3
@@ -15,7 +15,6 @@
|
|||||||
#ifndef LDC_IR_IRAGGR_H
|
#ifndef LDC_IR_IRAGGR_H
|
||||||
#define LDC_IR_IRAGGR_H
|
#define LDC_IR_IRAGGR_H
|
||||||
|
|
||||||
#include "ir/ir.h"
|
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -57,9 +56,9 @@ struct IrAggr
|
|||||||
/// Builds the __vtblZ initializer constant lazily.
|
/// Builds the __vtblZ initializer constant lazily.
|
||||||
LLConstant* getVtblInit();
|
LLConstant* getVtblInit();
|
||||||
|
|
||||||
/// Create the __ClassZ symbol lazily.
|
/// Create the __ClassZ/__InterfaceZ symbol lazily.
|
||||||
LLGlobalVariable* getClassInfoSymbol();
|
LLGlobalVariable* getClassInfoSymbol();
|
||||||
/// Builds the __ClassZ initializer constant lazily.
|
/// Builds the __ClassZ/__InterfaceZ initializer constant lazily.
|
||||||
LLConstant* getClassInfoInit();
|
LLConstant* getClassInfoInit();
|
||||||
|
|
||||||
/// Create the __interfaceInfos symbol lazily.
|
/// Create the __interfaceInfos symbol lazily.
|
||||||
|
|||||||
+10
-14
@@ -53,12 +53,10 @@ LLGlobalVariable * IrAggr::getVtblSymbol()
|
|||||||
initname.append(aggrdecl->mangle());
|
initname.append(aggrdecl->mangle());
|
||||||
initname.append("6__vtblZ");
|
initname.append("6__vtblZ");
|
||||||
|
|
||||||
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
|
|
||||||
|
|
||||||
LLType* vtblTy = stripModifiers(type)->irtype->isClass()->getVtbl();
|
LLType* vtblTy = stripModifiers(type)->irtype->isClass()->getVtbl();
|
||||||
|
|
||||||
vtbl = getOrCreateGlobal(aggrdecl->loc,
|
vtbl = getOrCreateGlobal(aggrdecl->loc,
|
||||||
*gIR->module, vtblTy, true, _linkage, NULL, initname);
|
*gIR->module, vtblTy, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);
|
||||||
|
|
||||||
return vtbl;
|
return vtbl;
|
||||||
}
|
}
|
||||||
@@ -79,8 +77,9 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol()
|
|||||||
else
|
else
|
||||||
initname.append("7__ClassZ");
|
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;
|
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
|
||||||
DtoType(cinfo->type);
|
DtoType(cinfo->type);
|
||||||
IrTypeClass* tc = stripModifiers(cinfo->type)->irtype->isClass();
|
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
|
// classinfos cannot be constants since they're used as locks for synchronized
|
||||||
classInfo = getOrCreateGlobal(aggrdecl->loc,
|
classInfo = getOrCreateGlobal(aggrdecl->loc,
|
||||||
*gIR->module, tc->getMemoryLLType(), false, _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.
|
// Generate some metadata on this ClassInfo if it's for a class.
|
||||||
ClassDeclaration* classdecl = aggrdecl->isClassDeclaration();
|
ClassDeclaration* classdecl = aggrdecl->isClassDeclaration();
|
||||||
@@ -138,9 +138,8 @@ LLGlobalVariable * IrAggr::getInterfaceArraySymbol()
|
|||||||
name.append(cd->mangle());
|
name.append(cd->mangle());
|
||||||
name.append("16__interfaceInfosZ");
|
name.append("16__interfaceInfosZ");
|
||||||
|
|
||||||
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
|
|
||||||
classInterfacesArray = getOrCreateGlobal(cd->loc, *gIR->module,
|
classInterfacesArray = getOrCreateGlobal(cd->loc, *gIR->module,
|
||||||
array_type, true, _linkage, NULL, name);
|
array_type, true, llvm::GlobalValue::ExternalLinkage, NULL, name);
|
||||||
|
|
||||||
return classInterfacesArray;
|
return classInterfacesArray;
|
||||||
}
|
}
|
||||||
@@ -182,7 +181,7 @@ LLConstant * IrAggr::getVtblInit()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fd->codegen(Type::sir);
|
DtoResolveFunction(fd);
|
||||||
assert(fd->ir.irFunc && "invalid vtbl function");
|
assert(fd->ir.irFunc && "invalid vtbl function");
|
||||||
c = fd->ir.irFunc->func;
|
c = fd->ir.irFunc->func;
|
||||||
if (cd->isFuncHidden(fd))
|
if (cd->isFuncHidden(fd))
|
||||||
@@ -320,7 +319,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance
|
|||||||
assert((!fd->isAbstract() || fd->fbody) &&
|
assert((!fd->isAbstract() || fd->fbody) &&
|
||||||
"null symbol in interface implementation vtable");
|
"null symbol in interface implementation vtable");
|
||||||
|
|
||||||
fd->codegen(Type::sir);
|
DtoResolveFunction(fd);
|
||||||
assert(fd->ir.irFunc && "invalid vtbl function");
|
assert(fd->ir.irFunc && "invalid vtbl function");
|
||||||
|
|
||||||
LLFunction *fn = fd->ir.irFunc->func;
|
LLFunction *fn = fd->ir.irFunc->func;
|
||||||
@@ -380,9 +379,6 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance
|
|||||||
// build the vtbl constant
|
// build the vtbl constant
|
||||||
llvm::Constant* vtbl_constant = LLConstantStruct::getAnon(gIR->context(), constants, false);
|
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");
|
std::string mangle("_D");
|
||||||
mangle.append(cd->mangle());
|
mangle.append(cd->mangle());
|
||||||
mangle.append("11__interface");
|
mangle.append("11__interface");
|
||||||
@@ -393,7 +389,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance
|
|||||||
*gIR->module,
|
*gIR->module,
|
||||||
vtbl_constant->getType(),
|
vtbl_constant->getType(),
|
||||||
true,
|
true,
|
||||||
_linkage,
|
llvm::GlobalValue::ExternalLinkage,
|
||||||
vtbl_constant,
|
vtbl_constant,
|
||||||
mangle
|
mangle
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "gen/llvm.h"
|
#include "gen/llvm.h"
|
||||||
#include "gen/logger.h"
|
#include "gen/logger.h"
|
||||||
#include "ir/ir.h"
|
|
||||||
#include "ir/irdsymbol.h"
|
#include "ir/irdsymbol.h"
|
||||||
#include "ir/irvar.h"
|
#include "ir/irvar.h"
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ struct IrParameter;
|
|||||||
struct IrField;
|
struct IrField;
|
||||||
struct IrVar;
|
struct IrVar;
|
||||||
struct Dsymbol;
|
struct Dsymbol;
|
||||||
|
struct Module;
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class Value;
|
class Value;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#define LDC_IR_IRFUNCTION_H
|
#define LDC_IR_IRFUNCTION_H
|
||||||
|
|
||||||
#include "gen/llvm.h"
|
#include "gen/llvm.h"
|
||||||
#include "ir/ir.h"
|
|
||||||
#include "ir/irlandingpad.h"
|
#include "ir/irlandingpad.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,6 @@
|
|||||||
#ifndef LDC_IR_IRFUNCTY_H
|
#ifndef LDC_IR_IRFUNCTY_H
|
||||||
#define LDC_IR_IRFUNCTY_H
|
#define LDC_IR_IRFUNCTY_H
|
||||||
|
|
||||||
#include "ir/ir.h"
|
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#if LDC_LLVM_VER >= 303
|
#if LDC_LLVM_VER >= 303
|
||||||
#include "llvm/IR/Attributes.h"
|
#include "llvm/IR/Attributes.h"
|
||||||
@@ -27,6 +26,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class DValue;
|
class DValue;
|
||||||
|
struct Type;
|
||||||
struct ABIRewrite;
|
struct ABIRewrite;
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class Type;
|
class Type;
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ IRLandingPadCatchInfo::IRLandingPadCatchInfo(Catch* catchstmt_, llvm::BasicBlock
|
|||||||
assert(catchStmt->type);
|
assert(catchStmt->type);
|
||||||
catchType = catchStmt->type->toBasetype()->isClassHandle();
|
catchType = catchStmt->type->toBasetype()->isClassHandle();
|
||||||
assert(catchType);
|
assert(catchType);
|
||||||
catchType->codegen(Type::sir);
|
DtoResolveClass(catchType);
|
||||||
|
|
||||||
if (catchStmt->var) {
|
if (catchStmt->var) {
|
||||||
if (!catchStmt->var->nestedrefs.dim) {
|
if (!catchStmt->var->nestedrefs.dim) {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#define LDC_IR_IRLANDINGPADINFO_H
|
#define LDC_IR_IRLANDINGPADINFO_H
|
||||||
|
|
||||||
#include "statement.h"
|
#include "statement.h"
|
||||||
#include "ir/ir.h"
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -15,9 +15,11 @@
|
|||||||
#ifndef LDC_IR_IRMODULE_H
|
#ifndef LDC_IR_IRMODULE_H
|
||||||
#define LDC_IR_IRMODULE_H
|
#define LDC_IR_IRMODULE_H
|
||||||
|
|
||||||
#include "ir/ir.h"
|
|
||||||
|
|
||||||
struct Module;
|
struct Module;
|
||||||
|
namespace llvm
|
||||||
|
{
|
||||||
|
class GlobalVariable;
|
||||||
|
}
|
||||||
|
|
||||||
struct IrModule
|
struct IrModule
|
||||||
{
|
{
|
||||||
@@ -26,7 +28,7 @@ struct IrModule
|
|||||||
|
|
||||||
Module* M;
|
Module* M;
|
||||||
|
|
||||||
LLGlobalVariable* fileName;
|
llvm::GlobalVariable* fileName;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -81,7 +81,7 @@ public:
|
|||||||
///
|
///
|
||||||
virtual IrTypeStruct* isStruct() { return 0; }
|
virtual IrTypeStruct* isStruct() { return 0; }
|
||||||
///
|
///
|
||||||
IrTypeVector* isVector() { return 0; }
|
virtual IrTypeVector* isVector() { return 0; }
|
||||||
|
|
||||||
///
|
///
|
||||||
Type* getDType() { return dtype; }
|
Type* getDType() { return dtype; }
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,6 @@
|
|||||||
#ifndef LDC_IR_IRVAR_H
|
#ifndef LDC_IR_IRVAR_H
|
||||||
#define LDC_IR_IRVAR_H
|
#define LDC_IR_IRVAR_H
|
||||||
|
|
||||||
#include "ir/ir.h"
|
|
||||||
#if LDC_LLVM_VER >= 303
|
#if LDC_LLVM_VER >= 303
|
||||||
#include "llvm/IR/Type.h"
|
#include "llvm/IR/Type.h"
|
||||||
#else
|
#else
|
||||||
@@ -23,6 +22,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct IrFuncTyArg;
|
struct IrFuncTyArg;
|
||||||
|
struct VarDeclaration;
|
||||||
|
|
||||||
struct IrVar
|
struct IrVar
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user