mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-31 03:53:14 +01:00
Fixed weird struct problem from downs, see mini/compile_structs1.d
Rewrote DtoIndexStruct/Class , the old implementation were way too complex for what we really need now - since the DotVar changes.
This commit is contained in:
@@ -1094,75 +1094,34 @@ void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, DStructIndexVector& idxs)
|
||||
LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
|
||||
{
|
||||
Logger::println("checking for offset %u type %s:", os, t->toChars());
|
||||
Logger::println("indexing class field %s:", vd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (idxs.empty())
|
||||
idxs.push_back(0);
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "src: " << *src << '\n';
|
||||
|
||||
// vd must be a field
|
||||
IrField* field = vd->ir.irField;
|
||||
assert(field);
|
||||
|
||||
unsigned idx = field->index + 2; // vtbl & monitor
|
||||
unsigned off = field->indexOffset;
|
||||
|
||||
const LLType* st = DtoType(cd->type);
|
||||
if (ptr->getType() != st) {
|
||||
ptr = gIR->ir->CreateBitCast(ptr, st, "tmp");
|
||||
}
|
||||
src = DtoBitCast(src, st);
|
||||
|
||||
const LLType* llt = getPtrToType(DtoType(t));
|
||||
unsigned dataoffset = 2;
|
||||
LLValue* val = DtoGEPi(src, 0,idx);
|
||||
val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
|
||||
|
||||
IrStruct* irstruct = cd->ir.irStruct;
|
||||
for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
|
||||
VarDeclaration* vd = i->second.var;
|
||||
assert(vd);
|
||||
Type* vdtype = vd->type->toBasetype();
|
||||
//Logger::println("found %u type %s", vd->offset, vdtype->toChars());
|
||||
assert(vd->ir.irField->index >= 0);
|
||||
if (os == vd->offset && vdtype->toBasetype() == t->toBasetype()) {
|
||||
Logger::println("found %s %s", vdtype->toChars(), vd->toChars());
|
||||
idxs.push_back(vd->ir.irField->index + dataoffset);
|
||||
//Logger::cout() << "indexing: " << *ptr << '\n';
|
||||
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
//Logger::cout() << "indexing: " << *ptr << '\n';
|
||||
if (vd->ir.irField->indexOffset)
|
||||
ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
|
||||
//Logger::cout() << "indexing: " << *ptr << '\n';
|
||||
return ptr;
|
||||
}
|
||||
else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
|
||||
TypeStruct* ts = (TypeStruct*)vdtype;
|
||||
StructDeclaration* ssd = ts->sym;
|
||||
idxs.push_back(vd->ir.irField->index + dataoffset);
|
||||
if (vd->ir.irField->indexOffset) {
|
||||
Logger::println("has union field offset");
|
||||
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
|
||||
DStructIndexVector tmp;
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
else {
|
||||
const LLType* sty = getPtrToType(DtoType(vd->type));
|
||||
if (ptr->getType() != sty) {
|
||||
ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
|
||||
DStructIndexVector tmp;
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
else {
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (off)
|
||||
val = DtoGEPi1(val, off);
|
||||
|
||||
assert(0);
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "value: " << *val << '\n';
|
||||
|
||||
size_t llt_sz = getABITypeSize(llt->getContainedType(0));
|
||||
assert(os % llt_sz == 0);
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
return llvm::GetElementPtrInst::Create(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
|
||||
return val;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -37,7 +37,7 @@ DValue* DtoDynamicCastObject(DValue* val, Type* to);
|
||||
DValue* DtoCastInterfaceToObject(DValue* val, Type* to);
|
||||
DValue* DtoDynamicCastInterface(DValue* val, Type* to);
|
||||
|
||||
LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, DStructIndexVector& idxs);
|
||||
LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* sd, VarDeclaration* vd);
|
||||
|
||||
LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl);
|
||||
|
||||
|
||||
@@ -52,73 +52,31 @@ LLConstant* DtoConstStructInitializer(StructInitializer* si)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, DStructIndexVector& idxs)
|
||||
LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
|
||||
{
|
||||
Logger::println("checking for offset %u type %s:", os, t->toChars());
|
||||
Logger::println("indexing struct field %s:", vd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (idxs.empty())
|
||||
idxs.push_back(0);
|
||||
// vd must be a field
|
||||
IrField* field = vd->ir.irField;
|
||||
assert(field);
|
||||
|
||||
unsigned idx = field->index;
|
||||
unsigned off = field->indexOffset;
|
||||
|
||||
const LLType* llt = getPtrToType(DtoType(t));
|
||||
const LLType* st = getPtrToType(DtoType(sd->type));
|
||||
src = DtoBitCast(src, st);
|
||||
|
||||
LLValue* val = DtoGEPi(src, 0,idx);
|
||||
val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
|
||||
|
||||
if (off)
|
||||
val = DtoGEPi1(val, off);
|
||||
|
||||
if (Logger::enabled())
|
||||
{
|
||||
Logger::cout() << "ptr = " << *ptr << '\n';
|
||||
Logger::cout() << "st = " << *st << '\n';
|
||||
}
|
||||
Logger::cout() << "value: " << *val << '\n';
|
||||
|
||||
if (ptr->getType() != st) {
|
||||
assert(sd->ir.irStruct->hasUnions);
|
||||
ptr = gIR->ir->CreateBitCast(ptr, st, "tmp");
|
||||
}
|
||||
|
||||
for (unsigned i=0; i<sd->fields.dim; ++i) {
|
||||
VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
|
||||
Type* vdtype = vd->type->toBasetype();
|
||||
//Logger::println("found %u type %s", vd->offset, vdtype->toChars());
|
||||
assert(vd->ir.irField->index >= 0);
|
||||
if (os == vd->offset && vdtype == t) {
|
||||
idxs.push_back(vd->ir.irField->index);
|
||||
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
if (vd->ir.irField->indexOffset)
|
||||
ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "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->ir.irField->index);
|
||||
if (vd->ir.irField->indexOffset) {
|
||||
Logger::println("has union field offset");
|
||||
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = DtoBitCast(ptr, llt);
|
||||
ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
|
||||
DStructIndexVector tmp;
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
else {
|
||||
const LLType* sty = getPtrToType(DtoType(vd->type));
|
||||
if (ptr->getType() != sty) {
|
||||
ptr = DtoBitCast(ptr, sty);
|
||||
DStructIndexVector tmp;
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
else {
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t llt_sz = getTypeStoreSize(llt->getContainedType(0));
|
||||
assert(os % llt_sz == 0);
|
||||
ptr = DtoBitCast(ptr, llt);
|
||||
return llvm::GetElementPtrInst::Create(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
|
||||
return val;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -30,8 +30,8 @@ void DtoDefineStruct(StructDeclaration* sd);
|
||||
*/
|
||||
LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs);
|
||||
|
||||
typedef LLSmallVector<unsigned, 3> DStructIndexVector;
|
||||
LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, DStructIndexVector& idxs);
|
||||
// index a struct one level
|
||||
LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd);
|
||||
|
||||
struct DUnionField
|
||||
{
|
||||
|
||||
43
gen/toir.cpp
43
gen/toir.cpp
@@ -500,18 +500,7 @@ DValue* AddExp::toElem(IRState* p)
|
||||
Type* e2type = e2->type->toBasetype();
|
||||
|
||||
if (e1type != e2type) {
|
||||
/*if (llvmFieldIndex) {
|
||||
assert(e1type->ty == Tpointer && e1next && e1next->ty == Tstruct);
|
||||
Logger::println("add to AddrExp of struct");
|
||||
assert(r->isConst());
|
||||
llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
|
||||
|
||||
TypeStruct* ts = (TypeStruct*)e1next;
|
||||
DStructIndexVector offsets;
|
||||
LLValue* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets);
|
||||
return new DFieldValue(type, v);
|
||||
}
|
||||
else*/ if (e1type->ty == Tpointer) {
|
||||
if (e1type->ty == Tpointer) {
|
||||
Logger::println("add to pointer");
|
||||
if (r->isConst()) {
|
||||
llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
|
||||
@@ -943,34 +932,21 @@ DValue* DotVarExp::toElem(IRState* p)
|
||||
|
||||
if (VarDeclaration* vd = var->isVarDeclaration()) {
|
||||
LLValue* arrptr;
|
||||
// indexing struct pointer
|
||||
if (e1type->ty == Tpointer) {
|
||||
assert(e1type->next->ty == Tstruct);
|
||||
TypeStruct* ts = (TypeStruct*)e1type->next;
|
||||
Logger::println("Struct member offset:%d", vd->offset);
|
||||
|
||||
LLValue* src = l->getRVal();
|
||||
|
||||
DStructIndexVector vdoffsets;
|
||||
arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
|
||||
arrptr = DtoIndexStruct(l->getRVal(), ts->sym, vd);
|
||||
}
|
||||
// happens for tuples
|
||||
// indexing normal struct
|
||||
else if (e1type->ty == Tstruct) {
|
||||
TypeStruct* ts = (TypeStruct*)e1type;
|
||||
Logger::println("Struct member offset:%d", vd->offset);
|
||||
|
||||
LLValue* src = l->getRVal();
|
||||
|
||||
DStructIndexVector vdoffsets;
|
||||
arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
|
||||
arrptr = DtoIndexStruct(l->getRVal(), ts->sym, vd);
|
||||
}
|
||||
// indexing class
|
||||
else if (e1type->ty == Tclass) {
|
||||
TypeClass* tc = (TypeClass*)e1type;
|
||||
Logger::println("Class member offset: %d", vd->offset);
|
||||
|
||||
LLValue* src = l->getRVal();
|
||||
|
||||
DStructIndexVector vdoffsets;
|
||||
arrptr = DtoIndexClass(src, tc->sym, vd->type, vd->offset, vdoffsets);
|
||||
arrptr = DtoIndexClass(l->getRVal(), tc->sym, vd);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
@@ -1343,6 +1319,11 @@ DValue* EqualExp::toElem(IRState* p)
|
||||
if (rv->getType() != lv->getType()) {
|
||||
rv = DtoBitCast(rv, lv->getType());
|
||||
}
|
||||
if (Logger::enabled())
|
||||
{
|
||||
Logger::cout() << "lv: " << *lv << '\n';
|
||||
Logger::cout() << "rv: " << *rv << '\n';
|
||||
}
|
||||
eval = p->ir->CreateICmp(cmpop, lv, rv, "tmp");
|
||||
}
|
||||
else if (t->iscomplex())
|
||||
|
||||
@@ -389,20 +389,6 @@ LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const char* var, llvm::B
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLValue* DtoGEPi(LLValue* ptr, const DStructIndexVector& src, const char* var, llvm::BasicBlock* bb)
|
||||
{
|
||||
size_t n = src.size();
|
||||
LLSmallVector<LLValue*, 3> dst(n);
|
||||
|
||||
size_t j=0;
|
||||
for (DStructIndexVector::const_iterator i=src.begin(); i!=src.end(); ++i)
|
||||
dst[j++] = DtoConstUint(*i);
|
||||
|
||||
return llvm::GetElementPtrInst::Create(ptr, dst.begin(), dst.end(), var?var:"tmp", bb?bb:gIR->scopebb());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLValue* DtoGEPi1(LLValue* ptr, unsigned i, const char* var, llvm::BasicBlock* bb)
|
||||
{
|
||||
return llvm::GetElementPtrInst::Create(ptr, DtoConstUint(i), var?var:"tmp", bb?bb:gIR->scopebb());
|
||||
|
||||
@@ -48,7 +48,7 @@ const LLStructType* DtoModuleReferenceType();
|
||||
// getelementptr helpers
|
||||
LLValue* DtoGEP1(LLValue* ptr, LLValue* i0, const char* var=NULL, llvm::BasicBlock* bb=NULL);
|
||||
LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const char* var=NULL, llvm::BasicBlock* bb=NULL);
|
||||
LLValue* DtoGEPi(LLValue* ptr, const DStructIndexVector& src, const char* var=NULL, llvm::BasicBlock* bb=NULL);
|
||||
|
||||
LLValue* DtoGEPi1(LLValue* ptr, unsigned i0, const char* var=NULL, llvm::BasicBlock* bb=NULL);
|
||||
LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const char* var=NULL, llvm::BasicBlock* bb=NULL);
|
||||
|
||||
|
||||
4
tests/mini/compile_structs1.d
Normal file
4
tests/mini/compile_structs1.d
Normal file
@@ -0,0 +1,4 @@
|
||||
struct Foo { int a, b, c; union Data { } Data data; }
|
||||
struct Bar { int a, b; }
|
||||
struct Baz { int a; union { Foo foo; Bar bar; } }
|
||||
void test() { Baz baz; if (baz.bar.a) return; }
|
||||
Reference in New Issue
Block a user