[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.

This commit is contained in:
Tomas Lindquist Olsen
2007-10-31 09:34:18 +01:00
parent fcdb174faf
commit 0979d55d26
5 changed files with 114 additions and 80 deletions

View File

@@ -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; }
};

View File

@@ -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';
}

View File

@@ -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());
}

View File

@@ -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"

View File

@@ -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