From 521de1a47eca00c694c89afa5a887e837c656a35 Mon Sep 17 00:00:00 2001 From: Tomas Lindquist Olsen Date: Fri, 11 Jul 2008 00:17:00 +0200 Subject: [PATCH] [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. --- dmd/expression.c | 2 ++ gen/arrays.cpp | 29 +++++++++-------------------- gen/classes.cpp | 43 +------------------------------------------ gen/functions.cpp | 17 ++--------------- gen/llvmhelpers.cpp | 4 +++- gen/toir.cpp | 29 +++++++++++++++++++---------- gen/tollvm.cpp | 14 +++++++++++++- gen/tollvm.h | 7 +++++++ 8 files changed, 56 insertions(+), 89 deletions(-) diff --git a/dmd/expression.c b/dmd/expression.c index 2a6f2b95..e33542c5 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -7682,6 +7682,8 @@ Expression *MinExp::semantic(Scope *sc) typeCombine(sc); // make sure pointer types are compatible type = Type::tptrdiff_t; 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->type = Type::tptrdiff_t; return e; diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 890d39e4..4cb55b7d 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -34,21 +34,16 @@ const LLStructType* DtoArrayType(const LLType* t) const LLArrayType* DtoStaticArrayType(Type* t) { - if (t->ir.type) - return isaArray(t->ir.type->get()); - + t = t->toBasetype(); assert(t->ty == Tsarray); - assert(t->next); - - const LLType* at = DtoType(t->next); - TypeSArray* tsa = (TypeSArray*)t; - assert(tsa->dim->type->isintegral()); - const LLArrayType* arrty = LLArrayType::get(at,tsa->dim->toUInteger()); + Type* tnext = tsa->next; - assert(!tsa->ir.type); - tsa->ir.type = new LLPATypeHolder(arrty); - return arrty; + const LLType* elemty = DtoType(tnext); + if (elemty == LLType::VoidTy) + 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) { Logger::cout() << "to array" << '\n'; - const LLType* ptrty = DtoType(totype->next); - if (ptrty == LLType::VoidTy) - ptrty = LLType::Int8Ty; - ptrty = getPtrToType(ptrty); - - const LLType* ety = DtoType(fromtype->next); - if (ety == LLType::VoidTy) - ety = LLType::Int8Ty; + const LLType* ptrty = DtoArrayType(totype)->getContainedType(1); + const LLType* ety = DtoTypeNotVoid(fromtype->next); if (DSliceValue* usl = u->isSlice()) { Logger::println("from slice"); diff --git a/gen/classes.cpp b/gen/classes.cpp index a2f1bf32..148716b9 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -1336,46 +1336,6 @@ static LLConstant* build_offti_array(ClassDeclaration* cd, LLConstant* init) static LLConstant* build_class_dtor(ClassDeclaration* cd) { -#if 0 - // construct the function - std::vector 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; // if no destructor emit a null @@ -1384,7 +1344,6 @@ static LLConstant* build_class_dtor(ClassDeclaration* cd) DtoForceDeclareDsymbol(dtor); return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::Int8Ty)); -#endif } static unsigned build_classinfo_flags(ClassDeclaration* cd) @@ -1556,7 +1515,7 @@ void DtoDefineClassInfo(ClassDeclaration* cd) if (cd->inv) { DtoForceDeclareDsymbol(cd->inv); 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 { c = defc->getOperand(8); diff --git a/gen/functions.cpp b/gen/functions.cpp index 023970c7..8d641a14 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -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 // would be nice to figure out how to assert that this is correct llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); - if (lastbb->empty()) { + if (lastbb->empty()) + { 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 diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index f9903939..ff460fd9 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1210,7 +1210,9 @@ LLConstant* DtoConstFieldInitializer(Type* t, 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"); assert(ex->exp); diff --git a/gen/toir.cpp b/gen/toir.cpp index da27c45a..127d4656 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -73,12 +73,13 @@ DValue* DeclarationExp::toElem(IRState* p) else { // allocate storage on the stack const LLType* lltype = DtoType(vd->type); + + llvm::Value* allocainst; if(gTargetData->getTypeSizeInBits(lltype) == 0) - { - 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()); - fatal(); - } - llvm::AllocaInst* allocainst = new llvm::AllocaInst(lltype, vd->toChars(), p->topallocapoint()); + allocainst = llvm::ConstantPointerNull::get(getPtrToType(lltype)); + else + allocainst = new llvm::AllocaInst(lltype, vd->toChars(), p->topallocapoint()); + //allocainst->setAlignment(vd->type->alignsize()); // TODO assert(!vd->ir.irLocal); vd->ir.irLocal = new IrLocal(vd); @@ -428,9 +429,7 @@ DValue* StringExp::toElem(IRState* p) Type* dtype = DtoDType(type); Type* cty = DtoDType(dtype->next); - const LLType* ct = DtoType(cty); - if (ct == LLType::VoidTy) - ct = LLType::Int8Ty; + const LLType* ct = DtoTypeNotVoid(cty); //printf("ct = %s\n", type->next->toChars()); 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()); 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; v = p->func()->decl->ir.irFunc->thisVar; if (llvm::isa(v)) @@ -1495,6 +1503,7 @@ DValue* ThisExp::toElem(IRState* p) return new DThisValue(vd, v); } + // anything we're not yet handling ? assert(0); return 0; } @@ -2005,7 +2014,7 @@ DValue* ArrayLengthExp::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; // condition diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 87a47774..336398c3 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -89,6 +89,7 @@ const LLType* DtoType(Type* t) // pointers case Tpointer: + // getPtrToType checks for void itself return getPtrToType(DtoType(t->next)); // arrays @@ -152,6 +153,7 @@ const LLType* DtoType(Type* t) case Taarray: { TypeAArray* taa = (TypeAArray*)t; + // aa key/val can't be void 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 LLType* i8ptr = getVoidPtrType(); @@ -499,7 +511,7 @@ llvm::ConstantFP* DtoConstFP(Type* t, long double value) LLConstant* DtoConstString(const char* str) { - std::string s(str); + std::string s(str?str:""); LLConstant* init = llvm::ConstantArray::get(s, true); llvm::GlobalVariable* gvar = new llvm::GlobalVariable( init->getType(), true,llvm::GlobalValue::InternalLinkage, init, ".str", gIR->module); diff --git a/gen/tollvm.h b/gen/tollvm.h index 5bb43eaf..d97e9648 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -11,7 +11,14 @@ // D->LLVM type handling stuff 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); + +// returns if the type should be returned in a hidden pointer arguement bool DtoIsReturnedInArg(Type* type); // resolve typedefs to their real type.