mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-08-02 04:20:05 +02:00
[svn r77] Fixed foreach on slice.
Fixed some nested function problems when accessing outer function parameters. Major changes to handling of structs. Initial support for unions. Probably more...
This commit is contained in:
@@ -7,5 +7,6 @@ enum
|
||||
LLVMbind,
|
||||
LLVMva_arg,
|
||||
LLVMva_start,
|
||||
LLVMva_intrinsic
|
||||
LLVMva_intrinsic,
|
||||
LLVMnotypeinfo
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "tollvm.h"
|
||||
|
||||
IRState* gIR = 0;
|
||||
llvm::TargetData* gTargetData = 0;
|
||||
const llvm::TargetData* gTargetData = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRScope::IRScope()
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
|
||||
#include "root.h"
|
||||
|
||||
// global ir state for current module
|
||||
struct IRState;
|
||||
extern IRState* gIR;
|
||||
extern llvm::TargetData* gTargetData;
|
||||
extern const llvm::TargetData* gTargetData;
|
||||
|
||||
struct TypeFunction;
|
||||
struct TypeStruct;
|
||||
@@ -40,20 +41,28 @@ struct IRScope
|
||||
// represents a struct or class
|
||||
struct IRStruct
|
||||
{
|
||||
typedef std::vector<const llvm::Type*> TypeVector;
|
||||
typedef std::vector<llvm::Constant*> ConstantVector;
|
||||
typedef std::vector<FuncDeclaration*> FuncDeclVec;
|
||||
struct Offset
|
||||
{
|
||||
VarDeclaration* var;
|
||||
llvm::Constant* init;
|
||||
|
||||
Offset(VarDeclaration* v, llvm::Constant* i)
|
||||
: var(v), init(i) {}
|
||||
};
|
||||
|
||||
typedef std::vector<FuncDeclaration*> FuncDeclVector;
|
||||
typedef std::multimap<unsigned, Offset> OffsetMap;
|
||||
|
||||
public:
|
||||
IRStruct();
|
||||
IRStruct(Type*);
|
||||
|
||||
Type* type;
|
||||
TypeVector fields;
|
||||
ConstantVector inits;
|
||||
llvm::PATypeHolder recty;
|
||||
FuncDeclVec funcs;
|
||||
FuncDeclVector funcs;
|
||||
bool queueFuncs;
|
||||
|
||||
OffsetMap offsets;
|
||||
};
|
||||
|
||||
// represents a finally block
|
||||
|
||||
@@ -672,8 +672,14 @@ void ForeachStatement::toIR(IRState* p)
|
||||
}
|
||||
else if (aggrtype->ty == Tarray)
|
||||
{
|
||||
numiters = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,0,"tmp",p->scopebb()));
|
||||
val = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,1,"tmp",p->scopebb()));
|
||||
if (arr->type == elem::SLICE) {
|
||||
numiters = arr->arg;
|
||||
val = arr->mem;
|
||||
}
|
||||
else {
|
||||
numiters = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,0,"tmp",p->scopebb()));
|
||||
val = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,1,"tmp",p->scopebb()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
91
gen/toir.c
91
gen/toir.c
@@ -1449,17 +1449,27 @@ elem* SymOffExp::toElem(IRState* p)
|
||||
TypeStruct* vdt = (TypeStruct*)vdtype;
|
||||
assert(vdt->sym);
|
||||
e = new elem;
|
||||
bool donormally = true;
|
||||
const llvm::Type* llt = LLVM_DtoType(t);
|
||||
if (offset == 0) {
|
||||
const llvm::Type* llt = LLVM_DtoType(t);
|
||||
e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp");
|
||||
}
|
||||
else {
|
||||
std::vector<unsigned> dst(1,0);
|
||||
vdt->sym->offsetToIndex(tnext, offset, dst);
|
||||
size_t fo = vdt->sym->offsetToIndex(tnext, offset, dst);
|
||||
llvm::Value* ptr = llvalue;
|
||||
assert(ptr);
|
||||
e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
|
||||
if (e->mem->getType() != llt) {
|
||||
e->mem = p->ir->CreateBitCast(e->mem, llt, "tmp");
|
||||
}
|
||||
if (fo == (size_t)-1) {
|
||||
size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
|
||||
assert(offset % llt_sz == 0);
|
||||
e->mem = new llvm::GetElementPtrInst(e->mem, LLVM_DtoConstUint(offset / llt_sz), "tmp", p->scopebb());
|
||||
}
|
||||
else if (fo) {
|
||||
e->mem = new llvm::GetElementPtrInst(e->mem, LLVM_DtoConstUint(fo), "tmp", p->scopebb());
|
||||
}
|
||||
}
|
||||
e->type = elem::VAL;
|
||||
e->field = true;
|
||||
@@ -1678,29 +1688,52 @@ elem* StructLiteralExp::toElem(IRState* p)
|
||||
|
||||
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
|
||||
unsigned n = elements->dim;
|
||||
for (unsigned i=0; i<n; ++i)
|
||||
{
|
||||
llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
|
||||
llvm::Value* arrptr = LLVM_DtoGEP(sptr,zero,offset,"tmp",p->scopebb());
|
||||
if (sd->isUnionDeclaration()) {
|
||||
Logger::println("num elements = %d", elements->dim);
|
||||
//assert(elements->dim == 1);
|
||||
Expression* vx = (Expression*)elements->data[0];
|
||||
assert(vx);
|
||||
|
||||
Expression* vx = (Expression*)elements->data[i];
|
||||
if (vx != 0) {
|
||||
p->exps.push_back(IRExp(NULL,vx,arrptr));
|
||||
elem* ve = vx->toElem(p);
|
||||
p->exps.pop_back();
|
||||
Type* vxtype = LLVM_DtoDType(vx->type);
|
||||
const llvm::Type* llvxty = llvm::PointerType::get(LLVM_DtoType(vxtype));
|
||||
llvm::Value* arrptr = p->ir->CreateBitCast(sptr, llvxty, "tmp");
|
||||
|
||||
if (!ve->inplace) {
|
||||
llvm::Value* val = ve->getValue();
|
||||
Logger::cout() << *val << " | " << *arrptr << '\n';
|
||||
p->exps.push_back(IRExp(NULL,vx,arrptr));
|
||||
elem* ve = vx->toElem(p);
|
||||
p->exps.pop_back();
|
||||
|
||||
Type* vxtype = LLVM_DtoDType(vx->type);
|
||||
LLVM_DtoAssign(vxtype, arrptr, val);
|
||||
}
|
||||
delete ve;
|
||||
if (!ve->inplace) {
|
||||
llvm::Value* val = ve->getValue();
|
||||
Logger::cout() << *val << " | " << *arrptr << '\n';
|
||||
LLVM_DtoAssign(vxtype, arrptr, val);
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
delete ve;
|
||||
}
|
||||
else {
|
||||
unsigned n = elements->dim;
|
||||
for (unsigned i=0; i<n; ++i)
|
||||
{
|
||||
llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
|
||||
llvm::Value* arrptr = LLVM_DtoGEP(sptr,zero,offset,"tmp",p->scopebb());
|
||||
|
||||
Expression* vx = (Expression*)elements->data[i];
|
||||
if (vx != 0) {
|
||||
p->exps.push_back(IRExp(NULL,vx,arrptr));
|
||||
elem* ve = vx->toElem(p);
|
||||
p->exps.pop_back();
|
||||
|
||||
if (!ve->inplace) {
|
||||
llvm::Value* val = ve->getValue();
|
||||
Logger::cout() << *val << " | " << *arrptr << '\n';
|
||||
|
||||
Type* vxtype = LLVM_DtoDType(vx->type);
|
||||
LLVM_DtoAssign(vxtype, arrptr, val);
|
||||
}
|
||||
delete ve;
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1835,8 +1868,13 @@ elem* SliceExp::toElem(IRState* p)
|
||||
else if (e1type->ty == Tsarray) {
|
||||
e->mem = LLVM_DtoGEP(v->mem,zero,lo->getValue(),"tmp",p->scopebb());
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
else if (e1type->ty == Tpointer) {
|
||||
e->mem = new llvm::GetElementPtrInst(v->getValue(),lo->getValue(),"tmp",p->scopebb());
|
||||
}
|
||||
else {
|
||||
Logger::println("type = %s", e1type->toChars());
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
elem* up = upr->toElem(p);
|
||||
@@ -2559,8 +2597,8 @@ elem* IdentityExp::toElem(IRState* p)
|
||||
|
||||
elem* e = new elem;
|
||||
|
||||
llvm::Value* l = u->getValue();
|
||||
llvm::Value* r = v->getValue();
|
||||
llvm::Value* l = u->field ? u->mem : u->getValue();
|
||||
llvm::Value* r = v->field ? v->mem : v->getValue();
|
||||
|
||||
Type* t1 = LLVM_DtoDType(e1->type);
|
||||
|
||||
@@ -2578,6 +2616,7 @@ elem* IdentityExp::toElem(IRState* p)
|
||||
if (t1->ty == Tpointer && v->type == elem::NUL && l->getType() != r->getType()) {
|
||||
r = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(l->getType()));
|
||||
}
|
||||
Logger::cout() << "l = " << *l << " r = " << *r << '\n';
|
||||
e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
|
||||
}
|
||||
e->type = elem::VAL;
|
||||
|
||||
28
gen/tollvm.c
28
gen/tollvm.c
@@ -17,15 +17,8 @@
|
||||
|
||||
bool LLVM_DtoIsPassedByRef(Type* type)
|
||||
{
|
||||
TY t = type->ty;
|
||||
if (t == Tstruct || t == Tarray || t == Tdelegate)
|
||||
return true;
|
||||
else if (t == Ttypedef) {
|
||||
Type* bt = type->toBasetype();
|
||||
assert(bt);
|
||||
return LLVM_DtoIsPassedByRef(bt);
|
||||
}
|
||||
return false;
|
||||
TY t = LLVM_DtoDType(type)->ty;
|
||||
return (t == Tstruct || t == Tarray || t == Tdelegate);
|
||||
}
|
||||
|
||||
Type* LLVM_DtoDType(Type* t)
|
||||
@@ -530,13 +523,11 @@ llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si)
|
||||
assert(vd);
|
||||
Logger::println("vars[%d] = %s", i, vd->toChars());
|
||||
|
||||
std::vector<unsigned> idxs;
|
||||
si->ad->offsetToIndex(vdtype, vd->offset, idxs);
|
||||
assert(idxs.size() == 1);
|
||||
unsigned idx = idxs[0];
|
||||
|
||||
llvm::Constant* v = 0;
|
||||
|
||||
assert(vd->llvmFieldIndex >= 0);
|
||||
unsigned idx = vd->llvmFieldIndex;
|
||||
|
||||
if (ExpInitializer* ex = ini->isExpInitializer())
|
||||
{
|
||||
v = ex->exp->toConstElem(gIR);
|
||||
@@ -557,6 +548,7 @@ llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si)
|
||||
assert(v);
|
||||
|
||||
inits[idx] = v;
|
||||
Logger::cout() << "init[" << idx << "] = " << *v << '\n';
|
||||
}
|
||||
|
||||
// fill out nulls
|
||||
@@ -1271,8 +1263,10 @@ llvm::Value* LLVM_DtoNestedVariable(VarDeclaration* vd)
|
||||
// on this stack
|
||||
if (fd == f) {
|
||||
llvm::Value* v = LLVM_DtoGEPi(vd->llvmValue,0,unsigned(vd->llvmNestedIndex),"tmp");
|
||||
if (vd->isParameter() && (vd->isRef() || vd->isOut()))
|
||||
if (vd->isParameter() && (vd->isRef() || vd->isOut() || LLVM_DtoIsPassedByRef(vd->type))) {
|
||||
Logger::cout() << "1267 loading: " << *v << '\n';
|
||||
v = gIR->ir->CreateLoad(v,"tmp");
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1293,8 +1287,10 @@ llvm::Value* LLVM_DtoNestedVariable(VarDeclaration* vd)
|
||||
while (f) {
|
||||
if (fd == f) {
|
||||
llvm::Value* v = LLVM_DtoGEPi(ptr,0,vd->llvmNestedIndex,"tmp");
|
||||
if (vd->isParameter() && (vd->isRef() || vd->isOut()))
|
||||
if (vd->isParameter() && (vd->isRef() || vd->isOut() || LLVM_DtoIsPassedByRef(vd->type))) {
|
||||
Logger::cout() << "1291 loading: " << *v << '\n';
|
||||
v = gIR->ir->CreateLoad(v,"tmp");
|
||||
}
|
||||
return v;
|
||||
}
|
||||
else {
|
||||
|
||||
171
gen/toobj.c
171
gen/toobj.c
@@ -65,7 +65,15 @@ Module::genobjfile()
|
||||
ir.module->setTargetTriple(target_triple);
|
||||
ir.module->setDataLayout(global.params.data_layout);
|
||||
|
||||
gTargetData = new llvm::TargetData(ir.module);
|
||||
// heavily inspired by tools/llc/llc.cpp:200-230
|
||||
const llvm::TargetMachineRegistry::Entry* targetEntry;
|
||||
std::string targetError;
|
||||
targetEntry = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(*ir.module, targetError);
|
||||
assert(targetEntry && "Failed to find a static target for module");
|
||||
std::auto_ptr<llvm::TargetMachine> targetPtr(targetEntry->CtorFn(*ir.module, "")); // TODO: replace "" with features
|
||||
assert(targetPtr.get() && "Could not allocate target machine!");
|
||||
llvm::TargetMachine &targetMachine = *targetPtr.get();
|
||||
gTargetData = targetMachine.getTargetData();
|
||||
|
||||
// process module members
|
||||
for (int k=0; k < members->dim; k++) {
|
||||
@@ -74,7 +82,6 @@ Module::genobjfile()
|
||||
dsym->toObjFile();
|
||||
}
|
||||
|
||||
delete gTargetData;
|
||||
gTargetData = 0;
|
||||
|
||||
// emit the llvm main function if necessary
|
||||
@@ -142,7 +149,7 @@ void Declaration::toObjFile()
|
||||
/* ================================================================== */
|
||||
|
||||
/// Returns the LLVM style index from a DMD style offset
|
||||
void AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
|
||||
size_t AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
|
||||
{
|
||||
Logger::println("checking for offset %u type %s:", os, t->toChars());
|
||||
LOG_SCOPE;
|
||||
@@ -151,18 +158,19 @@ void AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsig
|
||||
Type* vdtype = LLVM_DtoDType(vd->type);
|
||||
Logger::println("found %u type %s", vd->offset, vdtype->toChars());
|
||||
if (os == vd->offset && vdtype == t) {
|
||||
result.push_back(i);
|
||||
return;
|
||||
assert(vd->llvmFieldIndex >= 0);
|
||||
result.push_back(vd->llvmFieldIndex);
|
||||
return vd->llvmFieldIndexOffset;
|
||||
}
|
||||
else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
|
||||
TypeStruct* ts = (TypeStruct*)vdtype;
|
||||
StructDeclaration* sd = ts->sym;
|
||||
result.push_back(i);
|
||||
sd->offsetToIndex(t, os - vd->offset, result);
|
||||
return;
|
||||
return sd->offsetToIndex(t, os - vd->offset, result);
|
||||
}
|
||||
}
|
||||
assert(0 && "Offset not found in any aggregate field");
|
||||
//assert(0 && "Offset not found in any aggregate field");
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
@@ -190,12 +198,13 @@ static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsig
|
||||
|
||||
/// Returns the LLVM style index from a DMD style offset
|
||||
/// Handles class inheritance
|
||||
void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
|
||||
size_t ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
|
||||
{
|
||||
unsigned idx = 0;
|
||||
unsigned r = LLVM_ClassOffsetToIndex(this, os, idx);
|
||||
assert(r != (unsigned)-1 && "Offset not found in any aggregate field");
|
||||
result.push_back(r+1); // vtable is 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
@@ -224,13 +233,97 @@ void StructDeclaration::toObjFile()
|
||||
dsym->toObjFile();
|
||||
}
|
||||
|
||||
if (gIR->topstruct().fields.empty())
|
||||
{
|
||||
gIR->topstruct().fields.push_back(llvm::Type::Int8Ty);
|
||||
gIR->topstruct().inits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
|
||||
}
|
||||
Logger::println("doing struct fields");
|
||||
|
||||
llvm::StructType* structtype = llvm::StructType::get(gIR->topstruct().fields);
|
||||
llvm::StructType* structtype = 0;
|
||||
std::vector<llvm::Constant*> fieldinits;
|
||||
|
||||
if (gIR->topstruct().offsets.empty())
|
||||
{
|
||||
std::vector<const llvm::Type*> fieldtypes;
|
||||
Logger::println("has no fields");
|
||||
fieldtypes.push_back(llvm::Type::Int8Ty);
|
||||
fieldinits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
|
||||
structtype = llvm::StructType::get(fieldtypes);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::println("has fields");
|
||||
std::vector<const llvm::Type*> fieldtypes;
|
||||
unsigned prevsize = (unsigned)-1;
|
||||
unsigned lastoffset = (unsigned)-1;
|
||||
const llvm::Type* fieldtype = NULL;
|
||||
llvm::Constant* fieldinit = NULL;
|
||||
size_t fieldpad = 0;
|
||||
int idx = 0;
|
||||
for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
|
||||
// first iteration
|
||||
if (lastoffset == (unsigned)-1) {
|
||||
lastoffset = i->first;
|
||||
assert(lastoffset == 0);
|
||||
fieldtype = LLVM_DtoType(i->second.var->type);
|
||||
fieldinit = i->second.init;
|
||||
prevsize = gTargetData->getTypeSize(fieldtype);
|
||||
i->second.var->llvmFieldIndex = idx;
|
||||
}
|
||||
// colliding offset?
|
||||
else if (lastoffset == i->first) {
|
||||
const llvm::Type* t = LLVM_DtoType(i->second.var->type);
|
||||
size_t s = gTargetData->getTypeSize(t);
|
||||
if (s > prevsize) {
|
||||
fieldpad = s - prevsize;
|
||||
prevsize = s;
|
||||
}
|
||||
llvmHasUnions = true;
|
||||
i->second.var->llvmFieldIndex = idx;
|
||||
}
|
||||
// intersecting offset?
|
||||
else if (i->first < (lastoffset + prevsize)) {
|
||||
const llvm::Type* t = LLVM_DtoType(i->second.var->type);
|
||||
size_t s = gTargetData->getTypeSize(t);
|
||||
assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
|
||||
llvmHasUnions = true;
|
||||
i->second.var->llvmFieldIndex = idx;
|
||||
i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s;
|
||||
}
|
||||
// fresh offset
|
||||
else {
|
||||
// commit the field
|
||||
fieldtypes.push_back(fieldtype);
|
||||
fieldinits.push_back(fieldinit);
|
||||
if (fieldpad) {
|
||||
// match up with below
|
||||
std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
|
||||
llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
|
||||
fieldtypes.push_back(c->getType());
|
||||
fieldinits.push_back(c);
|
||||
idx++;
|
||||
}
|
||||
|
||||
idx++;
|
||||
|
||||
// start new
|
||||
lastoffset = i->first;
|
||||
fieldtype = LLVM_DtoType(i->second.var->type);
|
||||
fieldinit = i->second.init;
|
||||
prevsize = gTargetData->getTypeSize(fieldtype);
|
||||
i->second.var->llvmFieldIndex = idx;
|
||||
fieldpad = 0;
|
||||
}
|
||||
}
|
||||
fieldtypes.push_back(fieldtype);
|
||||
fieldinits.push_back(fieldinit);
|
||||
if (fieldpad) {
|
||||
// match up with above
|
||||
std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
|
||||
llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
|
||||
fieldtypes.push_back(c->getType());
|
||||
fieldinits.push_back(c);
|
||||
}
|
||||
|
||||
Logger::println("creating struct type");
|
||||
structtype = llvm::StructType::get(fieldtypes);
|
||||
}
|
||||
|
||||
// refine abstract types for stuff like: struct S{S* next;}
|
||||
if (gIR->topstruct().recty != 0)
|
||||
@@ -254,18 +347,18 @@ void StructDeclaration::toObjFile()
|
||||
// always generate the constant initalizer
|
||||
if (!zeroInit) {
|
||||
Logger::println("Not zero initialized");
|
||||
//assert(tk == gIR->topstruct().size());
|
||||
//assert(tk == gIR->gIR->topstruct()().size());
|
||||
#ifndef LLVMD_NO_LOGGER
|
||||
Logger::cout() << *structtype << '\n';
|
||||
for (size_t k=0; k<gIR->topstruct().inits.size(); ++k) {
|
||||
Logger::cout() << "struct type: " << *structtype << '\n';
|
||||
for (size_t k=0; k<fieldinits.size(); ++k) {
|
||||
Logger::cout() << "Type:" << '\n';
|
||||
Logger::cout() << *gIR->topstruct().inits[k]->getType() << '\n';
|
||||
Logger::cout() << *fieldinits[k]->getType() << '\n';
|
||||
Logger::cout() << "Value:" << '\n';
|
||||
Logger::cout() << *gIR->topstruct().inits[k] << '\n';
|
||||
Logger::cout() << *fieldinits[k] << '\n';
|
||||
}
|
||||
Logger::cout() << "Initializer printed" << '\n';
|
||||
#endif
|
||||
llvmInitZ = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
|
||||
llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits);
|
||||
}
|
||||
else {
|
||||
Logger::println("Zero initialized");
|
||||
@@ -278,14 +371,15 @@ void StructDeclaration::toObjFile()
|
||||
_init = llvmInitZ;
|
||||
}
|
||||
|
||||
std::string initname(mangle());
|
||||
initname.append("__initZ");
|
||||
std::string initname("_D");
|
||||
initname.append(mangle());
|
||||
initname.append("6__initZ");
|
||||
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module);
|
||||
ts->llvmInit = initvar;
|
||||
|
||||
// generate member function definitions
|
||||
gIR->topstruct().queueFuncs = false;
|
||||
IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
|
||||
IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
|
||||
size_t n = mfs.size();
|
||||
for (size_t i=0; i<n; ++i) {
|
||||
mfs[i]->toObjFile();
|
||||
@@ -296,7 +390,7 @@ void StructDeclaration::toObjFile()
|
||||
gIR->structs.pop_back();
|
||||
|
||||
// generate typeinfo
|
||||
if (getModule() == gIR->dmodule)
|
||||
if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo)
|
||||
type->getTypeInfo(NULL);
|
||||
}
|
||||
|
||||
@@ -341,8 +435,12 @@ void ClassDeclaration::toObjFile()
|
||||
// add vtable
|
||||
llvm::PATypeHolder pa = llvm::OpaqueType::get();
|
||||
const llvm::Type* vtabty = llvm::PointerType::get(pa);
|
||||
gIR->topstruct().fields.push_back(vtabty);
|
||||
gIR->topstruct().inits.push_back(0);
|
||||
|
||||
std::vector<const llvm::Type*> fieldtypes;
|
||||
fieldtypes.push_back(vtabty);
|
||||
|
||||
std::vector<llvm::Constant*> fieldinits;
|
||||
fieldinits.push_back(0);
|
||||
|
||||
// base classes first
|
||||
LLVM_AddBaseClassData(&baseclasses);
|
||||
@@ -353,7 +451,13 @@ void ClassDeclaration::toObjFile()
|
||||
dsym->toObjFile();
|
||||
}
|
||||
|
||||
llvm::StructType* structtype = llvm::StructType::get(gIR->topstruct().fields);
|
||||
// fill out fieldtypes/inits
|
||||
for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
|
||||
fieldtypes.push_back(LLVM_DtoType(i->second.var->type));
|
||||
fieldinits.push_back(i->second.init);
|
||||
}
|
||||
|
||||
llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
|
||||
// refine abstract types for stuff like: class C {C next;}
|
||||
if (gIR->topstruct().recty != 0)
|
||||
{
|
||||
@@ -441,9 +545,9 @@ void ClassDeclaration::toObjFile()
|
||||
|
||||
// first field is always the vtable
|
||||
assert(svtblVar != 0);
|
||||
gIR->topstruct().inits[0] = svtblVar;
|
||||
fieldinits[0] = svtblVar;
|
||||
|
||||
llvmInitZ = _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
|
||||
llvmInitZ = _init = llvm::ConstantStruct::get(structtype,fieldinits);
|
||||
assert(_init);
|
||||
|
||||
std::string initname("_D");
|
||||
@@ -457,7 +561,7 @@ void ClassDeclaration::toObjFile()
|
||||
initvar->setInitializer(_init);
|
||||
// generate member functions
|
||||
gIR->topstruct().queueFuncs = false;
|
||||
IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
|
||||
IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
|
||||
size_t n = mfs.size();
|
||||
for (size_t i=0; i<n; ++i) {
|
||||
mfs[i]->toObjFile();
|
||||
@@ -573,7 +677,6 @@ void VarDeclaration::toObjFile()
|
||||
|
||||
Type* t = LLVM_DtoDType(type);
|
||||
const llvm::Type* _type = LLVM_DtoType(t);
|
||||
gIR->topstruct().fields.push_back(_type);
|
||||
|
||||
llvm::Constant*_init = LLVM_DtoConstInitializer(t, init);
|
||||
assert(_init);
|
||||
@@ -610,7 +713,9 @@ void VarDeclaration::toObjFile()
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
gIR->topstruct().inits.push_back(_init);
|
||||
|
||||
// add the field in the IRStruct
|
||||
gIR->topstruct().offsets.insert(std::make_pair(offset, IRStruct::Offset(this,_init)));
|
||||
}
|
||||
|
||||
Logger::println("VarDeclaration::toObjFile is done");
|
||||
|
||||
147
gen/typinf.c
147
gen/typinf.c
@@ -324,7 +324,7 @@ void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
|
||||
|
||||
// create the symbol
|
||||
llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module);
|
||||
|
||||
llvmValue = gvar;
|
||||
}
|
||||
@@ -389,7 +389,7 @@ void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
|
||||
|
||||
// create the symbol
|
||||
llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module);
|
||||
|
||||
llvmValue = gvar;
|
||||
}
|
||||
@@ -421,7 +421,7 @@ static llvm::Constant* LLVM_D_Create_TypeInfoBase(Type* basetype, TypeInfoDeclar
|
||||
|
||||
// create the symbol
|
||||
llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,tid->toChars(),gIR->module);
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,tid->toChars(),gIR->module);
|
||||
|
||||
tid->llvmValue = gvar;
|
||||
}
|
||||
@@ -545,6 +545,7 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
// char[] name
|
||||
char *name = sd->toPrettyChars();
|
||||
sinits.push_back(LLVM_DtoConstString(name));
|
||||
Logger::println("************** A");
|
||||
assert(sinits.back()->getType() == stype->getElementType(1));
|
||||
|
||||
// void[] init
|
||||
@@ -606,6 +607,7 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
}
|
||||
#endif
|
||||
|
||||
Logger::println("************** B");
|
||||
const llvm::PointerType* ptty = llvm::cast<llvm::PointerType>(stype->getElementType(3));
|
||||
|
||||
s = search_function(sd, Id::tohash);
|
||||
@@ -633,6 +635,7 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Logger::println("************** C %d", i);
|
||||
ptty = llvm::cast<llvm::PointerType>(stype->getElementType(4+i));
|
||||
if (fdx)
|
||||
{
|
||||
@@ -657,6 +660,7 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
}
|
||||
|
||||
Logger::println("************** D");
|
||||
ptty = llvm::cast<llvm::PointerType>(stype->getElementType(6));
|
||||
s = search_function(sd, Id::tostring);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
@@ -684,144 +688,9 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
|
||||
// create the symbol
|
||||
llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module);
|
||||
|
||||
llvmValue = gvar;
|
||||
|
||||
/*
|
||||
//printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars());
|
||||
|
||||
unsigned offset = Type::typeinfostruct->structsize;
|
||||
|
||||
dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct
|
||||
dtdword(pdt, 0); // monitor
|
||||
|
||||
assert(tinfo->ty == Tstruct);
|
||||
|
||||
TypeStruct *tc = (TypeStruct *)tinfo;
|
||||
StructDeclaration *sd = tc->sym;
|
||||
|
||||
// Put out:
|
||||
// char[] name;
|
||||
// void[] init;
|
||||
// hash_t function(void*) xtoHash;
|
||||
// int function(void*,void*) xopEquals;
|
||||
// int function(void*,void*) xopCmp;
|
||||
// char[] function(void*) xtoString;
|
||||
// uint m_flags;
|
||||
//
|
||||
// name[]
|
||||
//
|
||||
|
||||
char *name = sd->toPrettyChars();
|
||||
size_t namelen = strlen(name);
|
||||
dtdword(pdt, namelen);
|
||||
//dtabytes(pdt, TYnptr, 0, namelen + 1, name);
|
||||
dtxoff(pdt, toSymbol(), offset, TYnptr);
|
||||
offset += namelen + 1;
|
||||
|
||||
// void[] init;
|
||||
dtdword(pdt, sd->structsize); // init.length
|
||||
if (sd->zeroInit)
|
||||
dtdword(pdt, 0); // NULL for 0 initialization
|
||||
else
|
||||
dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr
|
||||
|
||||
FuncDeclaration *fd;
|
||||
FuncDeclaration *fdx;
|
||||
TypeFunction *tf;
|
||||
Type *ta;
|
||||
Dsymbol *s;
|
||||
|
||||
static TypeFunction *tftohash;
|
||||
static TypeFunction *tftostring;
|
||||
|
||||
if (!tftohash)
|
||||
{
|
||||
Scope sc;
|
||||
|
||||
tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
|
||||
tftohash = (TypeFunction *)tftohash->semantic(0, &sc);
|
||||
|
||||
tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd);
|
||||
tftostring = (TypeFunction *)tftostring->semantic(0, &sc);
|
||||
}
|
||||
|
||||
TypeFunction *tfeqptr;
|
||||
{
|
||||
Scope sc;
|
||||
Arguments *arguments = new Arguments;
|
||||
Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL);
|
||||
|
||||
arguments->push(arg);
|
||||
tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
|
||||
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc);
|
||||
}
|
||||
|
||||
#if 0
|
||||
TypeFunction *tfeq;
|
||||
{
|
||||
Scope sc;
|
||||
Array *arguments = new Array;
|
||||
Argument *arg = new Argument(In, tc, NULL, NULL);
|
||||
|
||||
arguments->push(arg);
|
||||
tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
|
||||
tfeq = (TypeFunction *)tfeq->semantic(0, &sc);
|
||||
}
|
||||
#endif
|
||||
|
||||
s = search_function(sd, Id::tohash);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
if (fdx)
|
||||
{ fd = fdx->overloadExactMatch(tftohash);
|
||||
if (fd)
|
||||
dtxoff(pdt, fd->toSymbol(), 0, TYnptr);
|
||||
else
|
||||
//fdx->error("must be declared as extern (D) uint toHash()");
|
||||
dtdword(pdt, 0);
|
||||
}
|
||||
else
|
||||
dtdword(pdt, 0);
|
||||
|
||||
s = search_function(sd, Id::eq);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (fdx)
|
||||
{ fd = fdx->overloadExactMatch(tfeqptr);
|
||||
if (fd)
|
||||
dtxoff(pdt, fd->toSymbol(), 0, TYnptr);
|
||||
else
|
||||
//fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars());
|
||||
dtdword(pdt, 0);
|
||||
}
|
||||
else
|
||||
dtdword(pdt, 0);
|
||||
|
||||
s = search_function(sd, Id::cmp);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
}
|
||||
|
||||
s = search_function(sd, Id::tostring);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
if (fdx)
|
||||
{ fd = fdx->overloadExactMatch(tftostring);
|
||||
if (fd)
|
||||
dtxoff(pdt, fd->toSymbol(), 0, TYnptr);
|
||||
else
|
||||
//fdx->error("must be declared as extern (D) char[] toString()");
|
||||
dtdword(pdt, 0);
|
||||
}
|
||||
else
|
||||
dtdword(pdt, 0);
|
||||
|
||||
// uint m_flags;
|
||||
dtdword(pdt, tc->hasPointers());
|
||||
|
||||
// name[]
|
||||
dtnbytes(pdt, namelen + 1, name);
|
||||
*/
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
Reference in New Issue
Block a user