Fixed some minitest regressions.

This commit is contained in:
Tomas Lindquist Olsen
2009-04-16 19:21:30 +02:00
parent 5db458d8da
commit 9a86f9c0b5
9 changed files with 272 additions and 53 deletions

View File

@@ -486,8 +486,7 @@ LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
LLValue* funcval = vthis;
// get the vtbl for objects
if (!fdecl->isMember()->isInterfaceDeclaration())
funcval = DtoGEPi(funcval, 0, 0, "tmp");
funcval = DtoGEPi(funcval, 0, 0, "tmp");
// load vtbl ptr
funcval = DtoLoad(funcval);
// index vtbl

View File

@@ -22,46 +22,6 @@
//////////////////////////////////////////////////////////////////////////////////////////
LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
{
Logger::println("indexing struct field %s:", vd->toPrettyChars());
LOG_SCOPE;
DtoResolveStruct(sd);
// vd must be a field
IrField* field = vd->ir.irField;
assert(field);
// get the start pointer
const LLType* st = getPtrToType(DtoType(sd->type));
// cast to the formal struct type
src = DtoBitCast(src, st);
// gep to the index
LLValue* val = DtoGEPi(src, 0, field->index);
// do we need to offset further? (union area)
if (field->unionOffset)
{
// cast to void*
val = DtoBitCast(val, getVoidPtrType());
// offset
val = DtoGEPi1(val, field->unionOffset);
}
// cast it to the right type
val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
if (Logger::enabled())
Logger::cout() << "value: " << *val << '\n';
return val;
}
//////////////////////////////////////////////////////////////////////////////////////////
void DtoResolveStruct(StructDeclaration* sd)
{
// don't do anything if already been here
@@ -128,3 +88,226 @@ LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs)
LLValue* val = DtoMemCmp(lhs->getRVal(), rhs->getRVal(), DtoConstSize_t(sz));
return gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false), "tmp");
}
//////////////////////////////////////////////////////////////////////////////////////////
LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
{
Logger::println("indexing struct field %s:", vd->toPrettyChars());
LOG_SCOPE;
DtoResolveStruct(sd);
// vd must be a field
IrField* field = vd->ir.irField;
assert(field);
// get the start pointer
const LLType* st = getPtrToType(DtoType(sd->type));
// cast to the formal struct type
src = DtoBitCast(src, st);
// gep to the index
LLValue* val = DtoGEPi(src, 0, field->index);
// do we need to offset further? (union area)
if (field->unionOffset)
{
// cast to void*
val = DtoBitCast(val, getVoidPtrType());
// offset
val = DtoGEPi1(val, field->unionOffset);
}
// cast it to the right type
val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
if (Logger::enabled())
Logger::cout() << "value: " << *val << '\n';
return val;
}
//////////////////////////////////////////////////////////////////////////////////////////
// helper function that adds zero bytes to a vector of constants
size_t add_zeros(std::vector<llvm::Value*>& values, size_t diff)
{
size_t n = values.size();
bool is64 = global.params.is64bit;
while (diff)
{
if (is64 && diff % 8 == 0)
{
values.push_back(llvm::Constant::getNullValue(llvm::Type::Int64Ty));
diff -= 8;
}
else if (diff % 4 == 0)
{
values.push_back(llvm::Constant::getNullValue(llvm::Type::Int32Ty));
diff -= 4;
}
else if (diff % 2 == 0)
{
values.push_back(llvm::Constant::getNullValue(llvm::Type::Int16Ty));
diff -= 2;
}
else
{
values.push_back(llvm::Constant::getNullValue(llvm::Type::Int8Ty));
diff -= 1;
}
}
return values.size() - n;
}
std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd, const std::vector<llvm::Value*>& inits)
{
// get arrays
size_t nvars = sd->fields.dim;
VarDeclaration** vars = (VarDeclaration**)sd->fields.data;
assert(inits.size() == nvars);
// first locate all explicit initializers
std::vector<VarDeclaration*> explicitInits;
for (size_t i=0; i < nvars; i++)
{
if (inits[i])
{
explicitInits.push_back(vars[i]);
}
}
// vector of values to build aggregate from
std::vector<llvm::Value*> values;
// offset trackers
size_t lastoffset = 0;
size_t lastsize = 0;
// index of next explicit init
size_t exidx = 0;
// number of explicit inits
size_t nex = explicitInits.size();
// for through each field and build up the struct, padding with zeros
size_t i;
for (i=0; i<nvars; i++)
{
VarDeclaration* var = vars[i];
// get var info
size_t os = var->offset;
size_t sz = var->type->size();
// get next explicit
VarDeclaration* nextVar = NULL;
size_t nextOs = 0;
if (exidx < nex)
{
nextVar = explicitInits[exidx];
nextOs = nextVar->offset;
}
// none, rest is defaults
else
{
break;
}
// not explicit initializer, default initialize if there is room, otherwise skip
if (!inits[i])
{
// default init if there is room
// (past current offset) and (small enough to fit before next explicit)
if ((os >= lastoffset + lastsize) && (os+sz <= nextOs))
{
// add any 0 padding needed before this field
if (os > lastoffset + lastsize)
{
//printf("1added %lu zeros\n", os - lastoffset - lastsize);
add_zeros(values, os - lastoffset - lastsize);
}
// get field default init
IrField* f = var->ir.irField;
assert(f);
values.push_back(f->getDefaultInit());
lastoffset = os;
lastsize = sz;
//printf("added default: %s : %lu (%lu)\n", var->toChars(), os, sz);
}
// skip
continue;
}
assert(nextVar == var);
// add any 0 padding needed before this field
if (os > lastoffset + lastsize)
{
//printf("added %lu zeros\n", os - lastoffset - lastsize);
add_zeros(values, os - lastoffset - lastsize);
}
// add the expression value
values.push_back(inits[i]);
// update offsets
lastoffset = os;
lastsize = sz;
// go to next explicit init
exidx++;
//printf("added field: %s : %lu (%lu)\n", var->toChars(), os, sz);
}
// fill out rest with default initializers
const LLType* structtype = DtoType(sd->type);
size_t structsize = getTypePaddedSize(structtype);
// FIXME: this could probably share some code with the above
if (structsize > lastoffset+lastsize)
{
for (/*continue from first loop*/; i < nvars; i++)
{
VarDeclaration* var = vars[i];
// get var info
size_t os = var->offset;
size_t sz = var->type->size();
// skip?
if (os < lastoffset + lastsize)
continue;
// add any 0 padding needed before this field
if (os > lastoffset + lastsize)
{
//printf("2added %lu zeros\n", os - lastoffset - lastsize);
add_zeros(values, os - lastoffset - lastsize);
}
// get field default init
IrField* f = var->ir.irField;
assert(f);
values.push_back(f->getDefaultInit());
lastoffset = os;
lastsize = sz;
//printf("2added default: %s : %lu (%lu)\n", var->toChars(), os, sz);
}
}
// add any 0 padding needed at the end of the literal
if (structsize > lastoffset+lastsize)
{
//printf("3added %lu zeros\n", structsize - lastoffset - lastsize);
add_zeros(values, structsize - lastoffset - lastsize);
}
return values;
}

View File

@@ -982,6 +982,7 @@ LLConstant* AddrExp::toConstElem(IRState* p)
}
else if (e1->op == TOKstructliteral)
{
// FIXME: is this right?
StructLiteralExp* slexp = (StructLiteralExp*)e1;
LLConstant* lit = slexp->toConstElem(p);
return lit;
@@ -2409,8 +2410,7 @@ DValue* StructLiteralExp::toElem(IRState* p)
}
// vector of values to build aggregate from
std::vector<LLValue*> values;// = DtoStructLiteralValues(sd, inits);
assert(0 && "struct literal exp todo");
std::vector<LLValue*> values = DtoStructLiteralValues(sd, inits);
// get the struct type from the values
size_t n = values.size();
@@ -2459,8 +2459,7 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p)
inits[i] = exprs[i]->toConstElem(p);
// vector of values to build aggregate from
std::vector<LLValue*> values;// = DtoStructLiteralValues(sd, inits);
assert(0 && "struct literal const exp todo");
std::vector<LLValue*> values = DtoStructLiteralValues(sd, inits);
// we know those values are constants.. cast them
std::vector<LLConstant*> constvals(values.size(), NULL);

View File

@@ -81,6 +81,8 @@ LLGlobalVariable * IrStruct::getInterfaceArraySymbol()
ClassDeclaration* cd = aggrdecl->isClassDeclaration();
// FIXME:
// also happens for mini/s.d :(
assert(cd->vtblInterfaces && cd->vtblInterfaces->dim > 0 &&
"should not create interface info array for class with no explicit "
"interface implementations");
@@ -324,7 +326,14 @@ llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instan
for (size_t i = 1; i < n; i++)
{
Dsymbol* dsym = (Dsymbol*)vtbl_array.data[i];
assert(dsym && "null vtbl member");
if (dsym == NULL)
{
// FIXME
// why is this null?
// happens for mini/s.d
constants.push_back(getNullValue(getVoidPtrType()));
continue;
}
FuncDeclaration* fd = dsym->isFuncDeclaration();
assert(fd && "vtbl entry not a function");

View File

@@ -23,7 +23,9 @@ IrStruct::IrStruct(AggregateDeclaration* aggr)
type = aggr->type;
packed = false;
packed = (type->ty == Tstruct)
? type->alignsize() == 1
: false;
// above still need to be looked at
@@ -190,8 +192,10 @@ LLConstant * IrStruct::createStructDefaultInitializer()
IF_LOG Logger::cout() << "final default initializer: " << *definit << std::endl;
// sanity check
assert(definit->getType() == type->irtype->get() &&
"default initializer type does not match the default struct type");
if (definit->getType() != type->irtype->get())
{
assert(0 && "default initializer type does not match the default struct type");
}
return definit;
}

View File

@@ -212,7 +212,17 @@ const llvm::Type* IrTypeClass::buildVtblType(Type* first, Array* vtbl_array)
for (; !it.done(); it.next())
{
FuncDeclaration* fd = it.get()->isFuncDeclaration();
Dsymbol* dsym = it.get();
if (dsym == NULL)
{
// FIXME
// why is this null?
// happens for mini/s.d
types.push_back(getVoidPtrType());
continue;
}
FuncDeclaration* fd = dsym->isFuncDeclaration();
assert(fd && "invalid vtbl entry");
IF_LOG Logger::println("Adding type of %s", fd->toPrettyChars());

View File

@@ -138,8 +138,8 @@ const llvm::Type* IrTypeStruct::buildType()
// name types
Type::sir->getState()->module->addTypeName(sd->toPrettyChars(), pa.get());
#if 0
IF_LOG Logger::cout() << "struct type: " << *pa.get() << std::endl;
#if 1
IF_LOG Logger::cout() << "final struct type: " << *pa.get() << std::endl;
#endif
return pa.get();

View File

@@ -46,6 +46,18 @@ IrField::IrField(VarDeclaration* v, size_t idx, size_t offset) : IrVar(v)
V->ir.irField = this;
}
extern LLConstant* get_default_initializer(
VarDeclaration* vd,
Initializer* init);
llvm::Constant * IrField::getDefaultInit()
{
if (constInit)
return constInit;
constInit = get_default_initializer(V, V->init);
return constInit;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

View File

@@ -39,7 +39,10 @@ struct IrField : IrVar
unsigned index;
unsigned unionOffset;
llvm::Constant* getDefaultInit();
protected:
/// FIXME: only used for StructLiteralsExps
llvm::Constant* constInit;
};