mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 16:11:08 +03:00
[svn r349] Fixed problems with static arrays of void as well as a static arrays with zero length.
Fixed issues with DMD generated assert statements when using class invariants, generally due to incomplete ASTs. Removed some dead code. Added a few comments.
This commit is contained in:
parent
bace4dd0e7
commit
521de1a47e
8 changed files with 56 additions and 89 deletions
|
@ -7682,6 +7682,8 @@ Expression *MinExp::semantic(Scope *sc)
|
||||||
typeCombine(sc); // make sure pointer types are compatible
|
typeCombine(sc); // make sure pointer types are compatible
|
||||||
type = Type::tptrdiff_t;
|
type = Type::tptrdiff_t;
|
||||||
stride = t2->next->size();
|
stride = t2->next->size();
|
||||||
|
if (!stride)
|
||||||
|
return new IntegerExp(0, 0, Type::tptrdiff_t);
|
||||||
e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
|
e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
|
||||||
e->type = Type::tptrdiff_t;
|
e->type = Type::tptrdiff_t;
|
||||||
return e;
|
return e;
|
||||||
|
|
|
@ -34,21 +34,16 @@ const LLStructType* DtoArrayType(const LLType* t)
|
||||||
|
|
||||||
const LLArrayType* DtoStaticArrayType(Type* t)
|
const LLArrayType* DtoStaticArrayType(Type* t)
|
||||||
{
|
{
|
||||||
if (t->ir.type)
|
t = t->toBasetype();
|
||||||
return isaArray(t->ir.type->get());
|
|
||||||
|
|
||||||
assert(t->ty == Tsarray);
|
assert(t->ty == Tsarray);
|
||||||
assert(t->next);
|
|
||||||
|
|
||||||
const LLType* at = DtoType(t->next);
|
|
||||||
|
|
||||||
TypeSArray* tsa = (TypeSArray*)t;
|
TypeSArray* tsa = (TypeSArray*)t;
|
||||||
assert(tsa->dim->type->isintegral());
|
Type* tnext = tsa->next;
|
||||||
const LLArrayType* arrty = LLArrayType::get(at,tsa->dim->toUInteger());
|
|
||||||
|
|
||||||
assert(!tsa->ir.type);
|
const LLType* elemty = DtoType(tnext);
|
||||||
tsa->ir.type = new LLPATypeHolder(arrty);
|
if (elemty == LLType::VoidTy)
|
||||||
return arrty;
|
elemty = LLType::Int8Ty;
|
||||||
|
|
||||||
|
return LLArrayType::get(elemty, tsa->dim->toUInteger());
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -974,14 +969,8 @@ DValue* DtoCastArray(DValue* u, Type* to)
|
||||||
}
|
}
|
||||||
else if (totype->ty == Tarray) {
|
else if (totype->ty == Tarray) {
|
||||||
Logger::cout() << "to array" << '\n';
|
Logger::cout() << "to array" << '\n';
|
||||||
const LLType* ptrty = DtoType(totype->next);
|
const LLType* ptrty = DtoArrayType(totype)->getContainedType(1);
|
||||||
if (ptrty == LLType::VoidTy)
|
const LLType* ety = DtoTypeNotVoid(fromtype->next);
|
||||||
ptrty = LLType::Int8Ty;
|
|
||||||
ptrty = getPtrToType(ptrty);
|
|
||||||
|
|
||||||
const LLType* ety = DtoType(fromtype->next);
|
|
||||||
if (ety == LLType::VoidTy)
|
|
||||||
ety = LLType::Int8Ty;
|
|
||||||
|
|
||||||
if (DSliceValue* usl = u->isSlice()) {
|
if (DSliceValue* usl = u->isSlice()) {
|
||||||
Logger::println("from slice");
|
Logger::println("from slice");
|
||||||
|
|
|
@ -1336,46 +1336,6 @@ static LLConstant* build_offti_array(ClassDeclaration* cd, LLConstant* init)
|
||||||
|
|
||||||
static LLConstant* build_class_dtor(ClassDeclaration* cd)
|
static LLConstant* build_class_dtor(ClassDeclaration* cd)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
// construct the function
|
|
||||||
std::vector<const LLType*> paramTypes;
|
|
||||||
paramTypes.push_back(getPtrToType(cd->type->ir.type->get()));
|
|
||||||
|
|
||||||
const llvm::FunctionType* fnTy = llvm::FunctionType::get(LLType::VoidTy, paramTypes, false);
|
|
||||||
|
|
||||||
if (cd->dtors.dim == 0) {
|
|
||||||
return llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty));
|
|
||||||
}
|
|
||||||
else if (cd->dtors.dim == 1) {
|
|
||||||
DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[0];
|
|
||||||
DtoForceDeclareDsymbol(d);
|
|
||||||
assert(d->ir.irFunc->func);
|
|
||||||
return llvm::ConstantExpr::getBitCast(isaConstant(d->ir.irFunc->func), getPtrToType(LLType::Int8Ty));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string gname("_D");
|
|
||||||
gname.append(cd->mangle());
|
|
||||||
gname.append("12__destructorMFZv");
|
|
||||||
|
|
||||||
llvm::Function* func = llvm::Function::Create(fnTy, DtoInternalLinkage(cd), gname, gIR->module);
|
|
||||||
LLValue* thisptr = func->arg_begin();
|
|
||||||
thisptr->setName("this");
|
|
||||||
|
|
||||||
llvm::BasicBlock* bb = llvm::BasicBlock::Create("entry", func);
|
|
||||||
IRBuilder builder(bb);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < cd->dtors.dim; i++)
|
|
||||||
{
|
|
||||||
DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[i];
|
|
||||||
DtoForceDeclareDsymbol(d);
|
|
||||||
assert(d->ir.irFunc->func);
|
|
||||||
gIR->CreateCallOrInvoke(d->ir.irFunc->func, thisptr);
|
|
||||||
}
|
|
||||||
builder.CreateRetVoid();
|
|
||||||
|
|
||||||
return llvm::ConstantExpr::getBitCast(func, getPtrToType(LLType::Int8Ty));
|
|
||||||
#else
|
|
||||||
|
|
||||||
FuncDeclaration* dtor = cd->dtor;
|
FuncDeclaration* dtor = cd->dtor;
|
||||||
|
|
||||||
// if no destructor emit a null
|
// if no destructor emit a null
|
||||||
|
@ -1384,7 +1344,6 @@ static LLConstant* build_class_dtor(ClassDeclaration* cd)
|
||||||
|
|
||||||
DtoForceDeclareDsymbol(dtor);
|
DtoForceDeclareDsymbol(dtor);
|
||||||
return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::Int8Ty));
|
return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::Int8Ty));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned build_classinfo_flags(ClassDeclaration* cd)
|
static unsigned build_classinfo_flags(ClassDeclaration* cd)
|
||||||
|
@ -1556,7 +1515,7 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||||
if (cd->inv) {
|
if (cd->inv) {
|
||||||
DtoForceDeclareDsymbol(cd->inv);
|
DtoForceDeclareDsymbol(cd->inv);
|
||||||
c = cd->inv->ir.irFunc->func;
|
c = cd->inv->ir.irFunc->func;
|
||||||
// c = llvm::ConstantExpr::getBitCast(c, defc->getOperand(8)->getType());
|
c = llvm::ConstantExpr::getBitCast(c, defc->getOperand(8)->getType());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c = defc->getOperand(8);
|
c = defc->getOperand(8);
|
||||||
|
|
|
@ -732,22 +732,9 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
||||||
// if the last block is empty now, it must be unreachable or it's a bug somewhere else
|
// if the last block is empty now, it must be unreachable or it's a bug somewhere else
|
||||||
// would be nice to figure out how to assert that this is correct
|
// would be nice to figure out how to assert that this is correct
|
||||||
llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
|
llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
|
||||||
if (lastbb->empty()) {
|
if (lastbb->empty())
|
||||||
|
{
|
||||||
new llvm::UnreachableInst(lastbb);
|
new llvm::UnreachableInst(lastbb);
|
||||||
// if (llvm::pred_begin(lastbb) != llvm::pred_end(lastbb))
|
|
||||||
// {
|
|
||||||
// Logger::println("Erasing lastbb");
|
|
||||||
// lastbb->eraseFromParent();
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// new llvm::UnreachableInst(lastbb);
|
|
||||||
// // if (func->getReturnType() == LLType::VoidTy) {
|
|
||||||
// // llvm::ReturnInst::Create(lastbb);
|
|
||||||
// // }
|
|
||||||
// // else {
|
|
||||||
// // llvm::ReturnInst::Create(llvm::UndefValue::get(func->getReturnType()), lastbb);
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the last block is not terminated we return a null value or void
|
// if the last block is not terminated we return a null value or void
|
||||||
|
|
|
@ -1210,7 +1210,9 @@ LLConstant* DtoConstFieldInitializer(Type* t, Initializer* init)
|
||||||
|
|
||||||
DValue* DtoInitializer(Initializer* init)
|
DValue* DtoInitializer(Initializer* init)
|
||||||
{
|
{
|
||||||
if (ExpInitializer* ex = init->isExpInitializer())
|
if (!init)
|
||||||
|
return 0;
|
||||||
|
else if (ExpInitializer* ex = init->isExpInitializer())
|
||||||
{
|
{
|
||||||
Logger::println("expression initializer");
|
Logger::println("expression initializer");
|
||||||
assert(ex->exp);
|
assert(ex->exp);
|
||||||
|
|
29
gen/toir.cpp
29
gen/toir.cpp
|
@ -73,12 +73,13 @@ DValue* DeclarationExp::toElem(IRState* p)
|
||||||
else {
|
else {
|
||||||
// allocate storage on the stack
|
// allocate storage on the stack
|
||||||
const LLType* lltype = DtoType(vd->type);
|
const LLType* lltype = DtoType(vd->type);
|
||||||
|
|
||||||
|
llvm::Value* allocainst;
|
||||||
if(gTargetData->getTypeSizeInBits(lltype) == 0)
|
if(gTargetData->getTypeSizeInBits(lltype) == 0)
|
||||||
{
|
allocainst = llvm::ConstantPointerNull::get(getPtrToType(lltype));
|
||||||
error("Allocating a variable of type %s and size zero is not implemented. (the behaviour of alloca with zero size is undefined)", vd->type->toChars());
|
else
|
||||||
fatal();
|
allocainst = new llvm::AllocaInst(lltype, vd->toChars(), p->topallocapoint());
|
||||||
}
|
|
||||||
llvm::AllocaInst* allocainst = new llvm::AllocaInst(lltype, vd->toChars(), p->topallocapoint());
|
|
||||||
//allocainst->setAlignment(vd->type->alignsize()); // TODO
|
//allocainst->setAlignment(vd->type->alignsize()); // TODO
|
||||||
assert(!vd->ir.irLocal);
|
assert(!vd->ir.irLocal);
|
||||||
vd->ir.irLocal = new IrLocal(vd);
|
vd->ir.irLocal = new IrLocal(vd);
|
||||||
|
@ -428,9 +429,7 @@ DValue* StringExp::toElem(IRState* p)
|
||||||
Type* dtype = DtoDType(type);
|
Type* dtype = DtoDType(type);
|
||||||
Type* cty = DtoDType(dtype->next);
|
Type* cty = DtoDType(dtype->next);
|
||||||
|
|
||||||
const LLType* ct = DtoType(cty);
|
const LLType* ct = DtoTypeNotVoid(cty);
|
||||||
if (ct == LLType::VoidTy)
|
|
||||||
ct = LLType::Int8Ty;
|
|
||||||
//printf("ct = %s\n", type->next->toChars());
|
//printf("ct = %s\n", type->next->toChars());
|
||||||
const LLArrayType* at = LLArrayType::get(ct,len+1);
|
const LLArrayType* at = LLArrayType::get(ct,len+1);
|
||||||
|
|
||||||
|
@ -1484,7 +1483,16 @@ DValue* ThisExp::toElem(IRState* p)
|
||||||
Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars());
|
Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
if (VarDeclaration* vd = var->isVarDeclaration()) {
|
// this seems to happen for dmd generated assert statements like:
|
||||||
|
// assert(this, "null this");
|
||||||
|
if (!var)
|
||||||
|
{
|
||||||
|
LLValue* v = p->func()->thisVar;
|
||||||
|
assert(v);
|
||||||
|
return new DImValue(type, v);
|
||||||
|
}
|
||||||
|
// regular this expr
|
||||||
|
else if (VarDeclaration* vd = var->isVarDeclaration()) {
|
||||||
LLValue* v;
|
LLValue* v;
|
||||||
v = p->func()->decl->ir.irFunc->thisVar;
|
v = p->func()->decl->ir.irFunc->thisVar;
|
||||||
if (llvm::isa<llvm::AllocaInst>(v))
|
if (llvm::isa<llvm::AllocaInst>(v))
|
||||||
|
@ -1495,6 +1503,7 @@ DValue* ThisExp::toElem(IRState* p)
|
||||||
return new DThisValue(vd, v);
|
return new DThisValue(vd, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// anything we're not yet handling ?
|
||||||
assert(0);
|
assert(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2005,7 +2014,7 @@ DValue* ArrayLengthExp::toElem(IRState* p)
|
||||||
|
|
||||||
DValue* AssertExp::toElem(IRState* p)
|
DValue* AssertExp::toElem(IRState* p)
|
||||||
{
|
{
|
||||||
Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars());
|
Logger::print("AssertExp::toElem: %s\n", toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
// condition
|
// condition
|
||||||
|
|
|
@ -89,6 +89,7 @@ const LLType* DtoType(Type* t)
|
||||||
|
|
||||||
// pointers
|
// pointers
|
||||||
case Tpointer:
|
case Tpointer:
|
||||||
|
// getPtrToType checks for void itself
|
||||||
return getPtrToType(DtoType(t->next));
|
return getPtrToType(DtoType(t->next));
|
||||||
|
|
||||||
// arrays
|
// arrays
|
||||||
|
@ -152,6 +153,7 @@ const LLType* DtoType(Type* t)
|
||||||
case Taarray:
|
case Taarray:
|
||||||
{
|
{
|
||||||
TypeAArray* taa = (TypeAArray*)t;
|
TypeAArray* taa = (TypeAArray*)t;
|
||||||
|
// aa key/val can't be void
|
||||||
return getPtrToType(LLStructType::get(DtoType(taa->key), DtoType(taa->next), 0));
|
return getPtrToType(LLStructType::get(DtoType(taa->key), DtoType(taa->next), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +166,16 @@ const LLType* DtoType(Type* t)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const LLType* DtoTypeNotVoid(Type* t)
|
||||||
|
{
|
||||||
|
const LLType* lt = DtoType(t);
|
||||||
|
if (lt == LLType::VoidTy)
|
||||||
|
return LLType::Int8Ty;
|
||||||
|
return lt;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const LLStructType* DtoDelegateType(Type* t)
|
const LLStructType* DtoDelegateType(Type* t)
|
||||||
{
|
{
|
||||||
const LLType* i8ptr = getVoidPtrType();
|
const LLType* i8ptr = getVoidPtrType();
|
||||||
|
@ -499,7 +511,7 @@ llvm::ConstantFP* DtoConstFP(Type* t, long double value)
|
||||||
|
|
||||||
LLConstant* DtoConstString(const char* str)
|
LLConstant* DtoConstString(const char* str)
|
||||||
{
|
{
|
||||||
std::string s(str);
|
std::string s(str?str:"");
|
||||||
LLConstant* init = llvm::ConstantArray::get(s, true);
|
LLConstant* init = llvm::ConstantArray::get(s, true);
|
||||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
|
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
|
||||||
init->getType(), true,llvm::GlobalValue::InternalLinkage, init, ".str", gIR->module);
|
init->getType(), true,llvm::GlobalValue::InternalLinkage, init, ".str", gIR->module);
|
||||||
|
|
|
@ -11,7 +11,14 @@
|
||||||
|
|
||||||
// D->LLVM type handling stuff
|
// D->LLVM type handling stuff
|
||||||
const LLType* DtoType(Type* t);
|
const LLType* DtoType(Type* t);
|
||||||
|
|
||||||
|
// same as DtoType except it converts 'void' to 'i8'
|
||||||
|
const LLType* DtoTypeNotVoid(Type* t);
|
||||||
|
|
||||||
|
// returns true is the type must be passed by pointer
|
||||||
bool DtoIsPassedByRef(Type* type);
|
bool DtoIsPassedByRef(Type* type);
|
||||||
|
|
||||||
|
// returns if the type should be returned in a hidden pointer arguement
|
||||||
bool DtoIsReturnedInArg(Type* type);
|
bool DtoIsReturnedInArg(Type* type);
|
||||||
|
|
||||||
// resolve typedefs to their real type.
|
// resolve typedefs to their real type.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue