# HG changeset patch # User lindquist # Date 1212493869 -7200 # Node ID a58d8f4b84dfc13729a5a59e72e21dd0bcd2212c # Parent 629cfc1e7b77a6d9e8e8cd839067a400027eca7c [svn r231] Changed: warnings are no longer treated as an error. Added some comments and cleaned up CallExp::toElem a tiny bit. Fixed: struct literals always reported inplace assignment even if they allocated a temporary. Fixed: passing stuff to a D-style vararg which did inplace assignment was generated suboptimal code. diff -r 629cfc1e7b77 -r a58d8f4b84df dmd/cast.c --- a/dmd/cast.c Fri May 30 19:32:56 2008 +0200 +++ b/dmd/cast.c Tue Jun 03 13:51:09 2008 +0200 @@ -43,9 +43,8 @@ if (e->op == TOKint64) return e->implicitCastTo(sc, t); - fprintf(stdmsg, "warning - "); - error("implicit conversion of expression (%s) of type %s to %s can cause loss of data", - toChars(), type->toChars(), t->toChars()); + warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data", + loc.toChars(), toChars(), type->toChars(), t->toChars()); } return castTo(sc, t); } diff -r 629cfc1e7b77 -r a58d8f4b84df dmd/func.c --- a/dmd/func.c Fri May 30 19:32:56 2008 +0200 +++ b/dmd/func.c Tue Jun 03 13:51:09 2008 +0200 @@ -308,7 +308,7 @@ #if V2 if (!isOverride() && global.params.warnings) - error("overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars()); + warning("%s: overrides base class function %s, but is not marked with 'override'", locToChars() fdv->toPrettyChars()); #endif if (fdv->toParent() == parent) @@ -1056,8 +1056,7 @@ { Expression *e; if (global.params.warnings) - { fprintf(stdmsg, "warning - "); - error("no return at end of function"); + { warning("%s: no return at end of function", locToChars()); } if (global.params.useAssert && diff -r 629cfc1e7b77 -r a58d8f4b84df dmd/scope.c --- a/dmd/scope.c Fri May 30 19:32:56 2008 +0200 +++ b/dmd/scope.c Tue Jun 03 13:51:09 2008 +0200 @@ -255,6 +255,7 @@ sc->enclosing && sc->enclosing->search(loc, ident, NULL)) { + // WTF ? if (global.params.warnings) fprintf(stdmsg, "warning - "); error(s->loc, "array 'length' hides other 'length' name in outer scope"); diff -r 629cfc1e7b77 -r a58d8f4b84df dmd/statement.c --- a/dmd/statement.c Fri May 30 19:32:56 2008 +0200 +++ b/dmd/statement.c Tue Jun 03 13:51:09 2008 +0200 @@ -531,8 +531,7 @@ if (!falloff && global.params.warnings && !s->comeFrom()) { - fprintf(stdmsg, "warning - "); - s->error("statement is not reachable"); + warning("%s: statement is not reachable", s->loc.toChars()); } falloff = s->fallOffEnd(); } @@ -2049,8 +2048,7 @@ { hasNoDefault = 1; if (global.params.warnings) - { fprintf(stdmsg, "warning - "); - error("switch statement has no default"); + { warning("%s: switch statement has no default", loc.toChars()); } // Generate runtime error if the default is hit diff -r 629cfc1e7b77 -r a58d8f4b84df gen/functions.cpp --- a/gen/functions.cpp Fri May 30 19:32:56 2008 +0200 +++ b/gen/functions.cpp Tue Jun 03 13:51:09 2008 +0200 @@ -799,7 +799,9 @@ Logger::println("DtoVariadicArgument"); LOG_SCOPE; DVarValue* vv = new DVarValue(argexp->type, dst, true); + gIR->exps.push_back(IRExp(NULL, argexp, vv)); DtoAssign(vv, argexp->toElem(gIR)); + gIR->exps.pop_back(); } ////////////////////////////////////////////////////////////////////////////////////////// diff -r 629cfc1e7b77 -r a58d8f4b84df gen/toir.cpp --- a/gen/toir.cpp Fri May 30 19:32:56 2008 +0200 +++ b/gen/toir.cpp Tue Jun 03 13:51:09 2008 +0200 @@ -867,6 +867,8 @@ ////////////////////////////////////////////////////////////////////////////////////////// +// TODO: the method below could really use a cleanup/splitup + DValue* CallExp::toElem(IRState* p) { Logger::print("CallExp::toElem: %s | %s\n", toChars(), type->toChars()); @@ -911,19 +913,22 @@ assert(tf); } - // magic stuff + // handling of special intrinsics bool va_magic = false; bool va_intrinsic = false; DFuncValue* dfv = fn->isFunc(); if (dfv && dfv->func) { FuncDeclaration* fndecl = dfv->func; + // vararg intrinsic if (fndecl->llvmInternal == LLVMva_intrinsic) { va_magic = true; va_intrinsic = true; } + // va_start instruction else if (fndecl->llvmInternal == LLVMva_start) { va_magic = true; } + // va_arg instruction else if (fndecl->llvmInternal == LLVMva_arg) { //Argument* fnarg = Argument::getNth(tf->parameters, 0); Expression* exp = (Expression*)arguments->data[0]; @@ -933,11 +938,14 @@ if (DtoIsPassedByRef(t)) llt = getPtrToType(llt); // TODO + // issue a warning for broken va_arg instruction. if (strcmp(global.params.llvmArch, "x86") != 0) { - warning("%s: va_arg for C variadic functions is broken for anything but x86", loc.toChars()); + warning("%s: va_arg for C variadic functions is probably broken for anything but x86", loc.toChars()); } + // done return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp")); } + // alloca else if (fndecl->llvmInternal == LLVMalloca) { //Argument* fnarg = Argument::getNth(tf->parameters, 0); Expression* exp = (Expression*)arguments->data[0]; @@ -945,6 +953,7 @@ if (expv->getType()->toBasetype()->ty != Tint32) expv = DtoCast(expv, Type::tint32); LLValue* alloc = new llvm::AllocaInst(llvm::Type::Int8Ty, expv->getRVal(), "alloca", p->scopebb()); + // done return new DImValue(type, alloc); } } @@ -965,6 +974,8 @@ const llvm::FunctionType* llfnty = 0; + // TODO: review the stuff below, using the llvm type to choose seem like a bad idea. the D type should be used. + // // normal function call if (llvm::isa(funcval->getType())) { llfnty = llvm::cast(funcval->getType()); @@ -1082,110 +1093,107 @@ llargs[j] = DtoBitCast(expelem->getLVal(), getPtrToType(llvm::Type::Int8Ty)); } } - // regular arguments + // d variadic function + else if (tf->linkage == LINKd && tf->varargs == 1) + { + Logger::println("doing d-style variadic arguments"); + + size_t nimplicit = j; + + std::vector vtypes; + + // number of non variadic args + int begin = tf->parameters->dim; + Logger::println("num non vararg params = %d", begin); + + // build struct with argument types + for (int i=begin; idim; i++) + { + Argument* argu = Argument::getNth(tf->parameters, i); + Expression* argexp = (Expression*)arguments->data[i]; + vtypes.push_back(DtoType(argexp->type)); + } + const llvm::StructType* vtype = llvm::StructType::get(vtypes); + Logger::cout() << "d-variadic argument struct type:\n" << *vtype << '\n'; + LLValue* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint()); + + // store arguments in the struct + for (int i=begin,k=0; idim; i++,k++) + { + Expression* argexp = (Expression*)arguments->data[i]; + if (global.params.llvmAnnotate) + DtoAnnotation(argexp->toChars()); + DtoVariadicArgument(argexp, DtoGEPi(mem,0,k,"tmp")); + } + + // build type info array + assert(Type::typeinfo->ir.irStruct->constInit); + const LLType* typeinfotype = DtoType(Type::typeinfo->type); + const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements()); + + llvm::GlobalVariable* typeinfomem = + new llvm::GlobalVariable(typeinfoarraytype, true, llvm::GlobalValue::InternalLinkage, NULL, "._arguments.storage", gIR->module); + Logger::cout() << "_arguments storage: " << *typeinfomem << '\n'; + + std::vector vtypeinfos; + for (int i=begin,k=0; idim; i++,k++) + { + Expression* argexp = (Expression*)arguments->data[i]; + vtypeinfos.push_back(DtoTypeInfoOf(argexp->type)); + } + + // apply initializer + LLConstant* tiinits = llvm::ConstantArray::get(typeinfoarraytype, vtypeinfos); + typeinfomem->setInitializer(tiinits); + + // put data in d-array + std::vector pinits; + pinits.push_back(DtoConstSize_t(vtype->getNumElements())); + pinits.push_back(llvm::ConstantExpr::getBitCast(typeinfomem, getPtrToType(typeinfotype))); + const LLType* tiarrty = llfnty->getParamType(j)->getContainedType(0); + tiinits = llvm::ConstantStruct::get(pinits); + LLValue* typeinfoarrayparam = new llvm::GlobalVariable(tiarrty, + true, llvm::GlobalValue::InternalLinkage, tiinits, "._arguments.array", gIR->module); + + // specify arguments + llargs[j] = typeinfoarrayparam;; + j++; + llargs[j] = p->ir->CreateBitCast(mem, getPtrToType(llvm::Type::Int8Ty), "tmp"); + j++; + + // pass non variadic args + for (int i=0; iparameters, i); + DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); + llargs[j] = argval->getRVal(); + j++; + } + + // make sure arg vector has the right size + llargs.resize(nimplicit+begin+2); + } + // normal function call else { - // d variadic function? - if (tf->linkage == LINKd && tf->varargs == 1) - { - Logger::println("doing d-style variadic arguments"); - - size_t nimplicit = j; - - std::vector vtypes; - - // number of non variadic args - int begin = tf->parameters->dim; - Logger::println("num non vararg params = %d", begin); - - // build struct with argument types - for (int i=begin; idim; i++) - { - Argument* argu = Argument::getNth(tf->parameters, i); - Expression* argexp = (Expression*)arguments->data[i]; - vtypes.push_back(DtoType(argexp->type)); - } - const llvm::StructType* vtype = llvm::StructType::get(vtypes); - Logger::cout() << "d-variadic argument struct type:\n" << *vtype << '\n'; - LLValue* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint()); - - // store arguments in the struct - for (int i=begin,k=0; idim; i++,k++) - { - Expression* argexp = (Expression*)arguments->data[i]; - if (global.params.llvmAnnotate) - DtoAnnotation(argexp->toChars()); - DtoVariadicArgument(argexp, DtoGEPi(mem,0,k,"tmp")); - } - - // build type info array - assert(Type::typeinfo->ir.irStruct->constInit); - const LLType* typeinfotype = DtoType(Type::typeinfo->type); - const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements()); - - llvm::GlobalVariable* typeinfomem = - new llvm::GlobalVariable(typeinfoarraytype, true, llvm::GlobalValue::InternalLinkage, NULL, "._arguments.storage", gIR->module); - Logger::cout() << "_arguments storage: " << *typeinfomem << '\n'; - - std::vector vtypeinfos; - for (int i=begin,k=0; idim; i++,k++) - { - Expression* argexp = (Expression*)arguments->data[i]; - vtypeinfos.push_back(DtoTypeInfoOf(argexp->type)); + Logger::println("doing normal arguments"); + for (int i=0; idim; i++,j++) { + Argument* fnarg = Argument::getNth(tf->parameters, i); + if (global.params.llvmAnnotate) + DtoAnnotation(((Expression*)arguments->data[i])->toChars()); + DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); + llargs[j] = argval->getRVal(); + if (fnarg && llargs[j]->getType() != llfnty->getParamType(j)) { + llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); } - // apply initializer - LLConstant* tiinits = llvm::ConstantArray::get(typeinfoarraytype, vtypeinfos); - typeinfomem->setInitializer(tiinits); - - // put data in d-array - std::vector pinits; - pinits.push_back(DtoConstSize_t(vtype->getNumElements())); - pinits.push_back(llvm::ConstantExpr::getBitCast(typeinfomem, getPtrToType(typeinfotype))); - const LLType* tiarrty = llfnty->getParamType(j)->getContainedType(0); - tiinits = llvm::ConstantStruct::get(pinits); - LLValue* typeinfoarrayparam = new llvm::GlobalVariable(tiarrty, - true, llvm::GlobalValue::InternalLinkage, tiinits, "._arguments.array", gIR->module); - - // specify arguments - llargs[j] = typeinfoarrayparam;; - j++; - llargs[j] = p->ir->CreateBitCast(mem, getPtrToType(llvm::Type::Int8Ty), "tmp"); - j++; - - // pass non variadic args - for (int i=0; iparameters, i); - DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); - llargs[j] = argval->getRVal(); - j++; - } - - // make sure arg vector has the right size - llargs.resize(nimplicit+begin+2); - } - // normal function - else { - Logger::println("doing normal arguments"); - for (int i=0; idim; i++,j++) { - Argument* fnarg = Argument::getNth(tf->parameters, i); - if (global.params.llvmAnnotate) - DtoAnnotation(((Expression*)arguments->data[i])->toChars()); - DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); - llargs[j] = argval->getRVal(); - if (fnarg && llargs[j]->getType() != llfnty->getParamType(j)) { - llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); - } - - // this hack is necessary :/ - if (dfn && dfn->func && dfn->func->runTimeHack) { - if (llfnty->getParamType(j) != NULL) { - if (llargs[j]->getType() != llfnty->getParamType(j)) { - Logger::println("llvmRunTimeHack==true - force casting argument"); - Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n'; - llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); - } + // this hack is necessary :/ + if (dfn && dfn->func && dfn->func->runTimeHack) { + if (llfnty->getParamType(j) != NULL) { + if (llargs[j]->getType() != llfnty->getParamType(j)) { + Logger::println("llvmRunTimeHack==true - force casting argument"); + Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n'; + llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); } } } @@ -2720,11 +2728,13 @@ const LLType* llt = DtoType(type); LLValue* mem = 0; + bool isinplace = true; // temporary struct literal if (!p->topexp() || p->topexp()->e2 != this) { sptr = new llvm::AllocaInst(llt,"tmpstructliteral",p->topallocapoint()); + isinplace = false; } // already has memory else @@ -2777,7 +2787,7 @@ j++; } - return new DImValue(type, sptr, true); + return new DImValue(type, sptr, isinplace); } ////////////////////////////////////////////////////////////////////////////////////////// diff -r 629cfc1e7b77 -r a58d8f4b84df llvmdc.kdevelop.filelist --- a/llvmdc.kdevelop.filelist Fri May 30 19:32:56 2008 +0200 +++ b/llvmdc.kdevelop.filelist Tue Jun 03 13:51:09 2008 +0200 @@ -748,6 +748,7 @@ tangotests/a.d tangotests/aa1.d tangotests/aa2.d +tangotests/align1.d tangotests/b.d tangotests/c.d tangotests/classes1.d @@ -757,6 +758,7 @@ tangotests/files1.d tangotests/h.d tangotests/i.d +tangotests/ina1.d tangotests/j.d tangotests/k.d tangotests/l.d @@ -777,6 +779,7 @@ tangotests/vararg1.d tangotests/vararg2.d tangotests/vararg3.d +tangotests/vararg4.d test test/a.d test/aa1.d diff -r 629cfc1e7b77 -r a58d8f4b84df tangotests/vararg3.d --- a/tangotests/vararg3.d Fri May 30 19:32:56 2008 +0200 +++ b/tangotests/vararg3.d Tue Jun 03 13:51:09 2008 +0200 @@ -35,6 +35,16 @@ } } + struct TLA + { + char[3] acronym; + + char[] toString() + { + return acronym; + } +} + void main() { User user = User("Bob Doe", "bd", 47); @@ -81,6 +91,24 @@ print("Mixed:\n"); print(123, ' ', 42.536f, " foobar ", ia1, ' ', user, '\n'); print(42, ' ', cast(byte)12, ' ', user, ' ', cast(short)1445, " foo\n"); + + print("International:\n"); + print('æ','ø','å','\n'); + print('Æ','Ø','Å','\n'); + print("rød grød med fløde\n"); + print("Heiße\n"); + + print("TLAs:\n"); + TLA tla1 = TLA("FBI"); + TLA tla2 = TLA("CIA"); + TLA tla3 = TLA("TLA"); + print(tla1); + print(tla2); + print(tla3, '\n'); + print(tla1, tla2, tla3, '\n'); + print(TLA("FBI"), TLA("CIA"), TLA("TLA"), '\n'); + + print("Done!\n"); } private void* get_va_arg(TypeInfo ti, ref void* vp)