mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-30 11:33:14 +01:00
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
This commit is contained in:
@@ -104,7 +104,6 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
llvm::ConstantStruct* llvmConstVtbl;
|
||||
llvm::Constant* llvmInitZ;
|
||||
bool llvmHasUnions;
|
||||
virtual size_t offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result); // converts a DMD field offsets to LLVM struct index vector
|
||||
|
||||
AggregateDeclaration *isAggregateDeclaration() { return this; }
|
||||
};
|
||||
@@ -240,7 +239,7 @@ struct ClassDeclaration : AggregateDeclaration
|
||||
|
||||
Symbol *vtblsym;
|
||||
|
||||
virtual size_t offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
|
||||
void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
|
||||
|
||||
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
|
||||
};
|
||||
|
||||
36
gen/toir.c
36
gen/toir.c
@@ -640,9 +640,8 @@ elem* AddExp::toElem(IRState* p)
|
||||
llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->val);
|
||||
|
||||
TypeStruct* ts = (TypeStruct*)e1type->next;
|
||||
std::vector<unsigned> offsets(1,0);
|
||||
ts->sym->offsetToIndex(t->next, cofs->getZExtValue(), offsets);
|
||||
e->mem = LLVM_DtoGEP(l->getValue(), offsets, "tmp", p->scopebb());
|
||||
std::vector<unsigned> offsets;
|
||||
e->mem = LLVM_DtoIndexStruct(l->getValue(), ts->sym, t->next, cofs->getZExtValue(), offsets);
|
||||
e->type = elem::VAR;
|
||||
e->field = true;
|
||||
}
|
||||
@@ -1454,8 +1453,9 @@ elem* SymOffExp::toElem(IRState* p)
|
||||
e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp");
|
||||
}
|
||||
else {
|
||||
std::vector<unsigned> dst(1,0);
|
||||
size_t fo = vdt->sym->offsetToIndex(tnext, offset, dst);
|
||||
std::vector<unsigned> dst;
|
||||
e->mem = LLVM_DtoIndexStruct(llvalue,vdt->sym, 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");
|
||||
@@ -1469,7 +1469,7 @@ elem* SymOffExp::toElem(IRState* p)
|
||||
}
|
||||
else if (fo) {
|
||||
e->mem = new llvm::GetElementPtrInst(e->mem, LLVM_DtoConstUint(fo), "tmp", p->scopebb());
|
||||
}
|
||||
}*/
|
||||
}
|
||||
e->type = elem::VAL;
|
||||
e->field = true;
|
||||
@@ -1564,25 +1564,26 @@ elem* DotVarExp::toElem(IRState* p)
|
||||
Logger::print("e1->type=%s\n", e1type->toChars());
|
||||
|
||||
if (VarDeclaration* vd = var->isVarDeclaration()) {
|
||||
std::vector<unsigned> vdoffsets(1,0);
|
||||
llvm::Value* src = 0;
|
||||
llvm::Value* arrptr;
|
||||
if (e1type->ty == Tpointer) {
|
||||
assert(e1type->next->ty == Tstruct);
|
||||
TypeStruct* ts = (TypeStruct*)e1type->next;
|
||||
ts->sym->offsetToIndex(vd->type, vd->offset, vdoffsets);
|
||||
Logger::println("Struct member offset:%d", vd->offset);
|
||||
src = l->val ? l->val : l->mem;
|
||||
llvm::Value* src = l->val ? l->val : l->mem;
|
||||
std::vector<unsigned> vdoffsets;
|
||||
arrptr = LLVM_DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
|
||||
}
|
||||
else if (e1->type->ty == Tclass) {
|
||||
TypeClass* tc = (TypeClass*)e1type;
|
||||
Logger::println("Class member offset: %d", vd->offset);
|
||||
std::vector<unsigned> vdoffsets(1,0);
|
||||
tc->sym->offsetToIndex(vd->type, vd->offset, vdoffsets);
|
||||
src = l->getValue();
|
||||
llvm::Value* src = l->getValue();
|
||||
Logger::cout() << "src: " << *src << '\n';
|
||||
arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb());
|
||||
}
|
||||
assert(vdoffsets.size() != 1);
|
||||
assert(src != 0);
|
||||
Logger::cout() << "src: " << *src << '\n';
|
||||
llvm::Value* arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb());
|
||||
else
|
||||
assert(0);
|
||||
e->mem = arrptr;
|
||||
Logger::cout() << "mem: " << *e->mem << '\n';
|
||||
e->type = elem::VAR;
|
||||
@@ -1698,7 +1699,10 @@ elem* StructLiteralExp::toElem(IRState* p)
|
||||
}
|
||||
const llvm::StructType* t = llvm::StructType::get(tys);
|
||||
if (t != llt) {
|
||||
assert(gTargetData->getTypeSize(t) == gTargetData->getTypeSize(llt));
|
||||
if (gTargetData->getTypeSize(t) != gTargetData->getTypeSize(llt)) {
|
||||
Logger::cout() << "got size " << gTargetData->getTypeSize(t) << ", expected " << gTargetData->getTypeSize(llt) << '\n';
|
||||
assert(0 && "type size mismatch");
|
||||
}
|
||||
sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp");
|
||||
Logger::cout() << "sptr type is now: " << *t << '\n';
|
||||
}
|
||||
|
||||
59
gen/tollvm.c
59
gen/tollvm.c
@@ -1387,3 +1387,62 @@ void LLVM_DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes)
|
||||
|
||||
new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::Value* LLVM_DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs)
|
||||
{
|
||||
Logger::println("checking for offset %u type %s:", os, t->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (idxs.empty())
|
||||
idxs.push_back(0);
|
||||
|
||||
const llvm::Type* llt = llvm::PointerType::get(LLVM_DtoType(t));
|
||||
|
||||
for (unsigned i=0; i<sd->fields.dim; ++i) {
|
||||
VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
|
||||
Type* vdtype = LLVM_DtoDType(vd->type);
|
||||
Logger::println("found %u type %s", vd->offset, vdtype->toChars());
|
||||
assert(vd->llvmFieldIndex >= 0);
|
||||
if (os == vd->offset && vdtype == t) {
|
||||
idxs.push_back(vd->llvmFieldIndex);
|
||||
ptr = LLVM_DtoGEP(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
if (vd->llvmFieldIndexOffset)
|
||||
ptr = new llvm::GetElementPtrInst(ptr, LLVM_DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
|
||||
return ptr;
|
||||
}
|
||||
else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
|
||||
TypeStruct* ts = (TypeStruct*)vdtype;
|
||||
StructDeclaration* ssd = ts->sym;
|
||||
idxs.push_back(vd->llvmFieldIndex);
|
||||
if (vd->llvmFieldIndexOffset) {
|
||||
Logger::println("has union field offset");
|
||||
ptr = LLVM_DtoGEP(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
ptr = new llvm::GetElementPtrInst(ptr, LLVM_DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
|
||||
std::vector<unsigned> tmp;
|
||||
return LLVM_DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
else {
|
||||
const llvm::Type* sty = llvm::PointerType::get(LLVM_DtoType(vd->type));
|
||||
if (ptr->getType() != sty) {
|
||||
ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
|
||||
std::vector<unsigned> tmp;
|
||||
return LLVM_DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
else {
|
||||
return LLVM_DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
|
||||
assert(os % llt_sz == 0);
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
return new llvm::GetElementPtrInst(ptr, LLVM_DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
|
||||
}
|
||||
|
||||
@@ -65,4 +65,6 @@ llvm::Constant* LLVM_DtoConstString(const char*);
|
||||
|
||||
void LLVM_DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
|
||||
|
||||
llvm::Value* LLVM_DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs);
|
||||
|
||||
#include "enums.h"
|
||||
|
||||
94
gen/toobj.c
94
gen/toobj.c
@@ -148,67 +148,6 @@ void Declaration::toObjFile()
|
||||
|
||||
/* ================================================================== */
|
||||
|
||||
/// Returns the LLVM style index from a DMD style offset
|
||||
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;
|
||||
for (unsigned i=0; i<fields.dim; ++i) {
|
||||
VarDeclaration* vd = (VarDeclaration*)fields.data[i];
|
||||
Type* vdtype = LLVM_DtoDType(vd->type);
|
||||
Logger::println("found %u type %s", vd->offset, vdtype->toChars());
|
||||
if (os == vd->offset && vdtype == t) {
|
||||
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);
|
||||
return sd->offsetToIndex(t, os - vd->offset, result);
|
||||
}
|
||||
}
|
||||
//assert(0 && "Offset not found in any aggregate field");
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
|
||||
static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
|
||||
{
|
||||
// start at the bottom of the inheritance chain
|
||||
if (cd->baseClass != 0) {
|
||||
unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx);
|
||||
if (o != (unsigned)-1)
|
||||
return o;
|
||||
}
|
||||
|
||||
// check this class
|
||||
unsigned i;
|
||||
for (i=0; i<cd->fields.dim; ++i) {
|
||||
VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i];
|
||||
if (os == vd->offset)
|
||||
return i+idx;
|
||||
}
|
||||
idx += i;
|
||||
|
||||
return (unsigned)-1;
|
||||
}
|
||||
|
||||
/// Returns the LLVM style index from a DMD style offset
|
||||
/// Handles class inheritance
|
||||
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;
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
|
||||
void InterfaceDeclaration::toObjFile()
|
||||
{
|
||||
Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
|
||||
@@ -271,7 +210,7 @@ void StructDeclaration::toObjFile()
|
||||
const llvm::Type* t = LLVM_DtoType(i->second.var->type);
|
||||
size_t s = gTargetData->getTypeSize(t);
|
||||
if (s > prevsize) {
|
||||
fieldpad = s - prevsize;
|
||||
fieldpad += s - prevsize;
|
||||
prevsize = s;
|
||||
}
|
||||
llvmHasUnions = true;
|
||||
@@ -396,6 +335,37 @@ void StructDeclaration::toObjFile()
|
||||
|
||||
/* ================================================================== */
|
||||
|
||||
static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
|
||||
{
|
||||
// start at the bottom of the inheritance chain
|
||||
if (cd->baseClass != 0) {
|
||||
unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx);
|
||||
if (o != (unsigned)-1)
|
||||
return o;
|
||||
}
|
||||
|
||||
// check this class
|
||||
unsigned i;
|
||||
for (i=0; i<cd->fields.dim; ++i) {
|
||||
VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i];
|
||||
if (os == vd->offset)
|
||||
return i+idx;
|
||||
}
|
||||
idx += i;
|
||||
|
||||
return (unsigned)-1;
|
||||
}
|
||||
|
||||
void 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
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
|
||||
static void LLVM_AddBaseClassData(BaseClasses* bcs)
|
||||
{
|
||||
// add base class data members first
|
||||
|
||||
Reference in New Issue
Block a user