Mercurial > projects > ldc
diff gen/toir.c @ 57:a9d29e9f1fed trunk
[svn r61] Added support for D-style variadic functions :)
author | lindquist |
---|---|
date | Thu, 25 Oct 2007 02:39:53 +0200 |
parents | 0ccfae271c45 |
children | 2c3cd3596187 |
line wrap: on
line diff
--- a/gen/toir.c Wed Oct 24 22:26:37 2007 +0200 +++ b/gen/toir.c Thu Oct 25 02:39:53 2007 +0200 @@ -110,12 +110,31 @@ assert(var); if (VarDeclaration* vd = var->isVarDeclaration()) { - Logger::println("VarDeclaration"); + Logger::println("VarDeclaration %s", vd->toChars()); if (vd->nestedref) { Logger::println("has nested ref"); } + // _arguments + if (vd->ident == Id::_arguments) + { + vd->llvmValue = p->func().decl->llvmArguments; + assert(vd->llvmValue); + e->mem = vd->llvmValue; + e->type = elem::VAR; + return e; + } + // _argptr + else if (vd->ident == Id::_argptr) + { + vd->llvmValue = p->func().decl->llvmArgPtr; + assert(vd->llvmValue); + e->mem = vd->llvmValue; + e->type = elem::VAR; + return e; + } + // needed to take care of forward references of global variables if (!vd->llvmTouched && vd->isDataseg()) vd->toObjFile(); @@ -147,8 +166,8 @@ } // global forward ref else { - Logger::println("unsupported: %s\n", vd->toChars()); - assert(0 && "only magic supported is typeinfo"); + Logger::println("unsupported magic: %s\n", vd->toChars()); + assert(0 && "only magic supported is $, _arguments, _argptr"); } return e; } @@ -447,7 +466,7 @@ elem* AssignExp::toElem(IRState* p) { - Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type->toChars()); + Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type ? e2->type->toChars() : 0); LOG_SCOPE; p->exps.push_back(IRExp(e1,e2,NULL)); @@ -1046,6 +1065,7 @@ n = 1; if (fn->arg || delegateCall) n++; if (retinptr) n++; + if (tf->linkage == LINKd && tf->varargs == 1) n+=2; llvm::Value* funcval = fn->getValue(); assert(funcval != 0); @@ -1091,8 +1111,6 @@ llvm::FunctionType::param_iterator argiter = llfnty->param_begin(); int j = 0; - Logger::println("hidden struct return"); - IRExp* topexp = p->topexp(); // hidden struct return arguments @@ -1118,8 +1136,6 @@ e->type = elem::VAL; } - Logger::println("this arguments"); - // this arguments if (fn->arg) { Logger::println("This Call"); @@ -1142,8 +1158,6 @@ ++argiter; } - Logger::println("regular arguments"); - // va arg function special argument passing if (va_magic) { size_t n = va_intrinsic ? arguments->dim : 1; @@ -1159,10 +1173,63 @@ } // regular arguments else { - for (int i=0; i<arguments->dim; i++,j++) + if (tf->linkage == LINKd && tf->varargs == 1) { - Argument* fnarg = Argument::getNth(tf->parameters, i); - llargs[j] = LLVM_DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]); + Logger::println("doing d-style variadic arguments"); + + std::vector<const llvm::Type*> vtypes; + std::vector<llvm::Value*> vvalues; + std::vector<llvm::Value*> vtypeinfos; + + for (int i=0; i<arguments->dim; i++) { + Argument* fnarg = Argument::getNth(tf->parameters, i); + Expression* argexp = (Expression*)arguments->data[i]; + vvalues.push_back(LLVM_DtoArgument(NULL, fnarg, argexp)); + vtypes.push_back(vvalues.back()->getType()); + + TypeInfoDeclaration* tidecl = argexp->type->getTypeInfoDeclaration(); + tidecl->toObjFile(); + assert(tidecl->llvmValue); + vtypeinfos.push_back(tidecl->llvmValue); + } + + const llvm::StructType* vtype = llvm::StructType::get(vtypes); + llvm::Value* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint()); + for (unsigned i=0; i<vtype->getNumElements(); ++i) + p->ir->CreateStore(vvalues[i], LLVM_DtoGEPi(mem,0,i,"tmp")); + + //llvm::Constant* typeinfoparam = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(llfnty->getParamType(j))); + assert(Type::typeinfo->llvmInitZ); + const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmInitZ->getType()); + Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n'; + const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements()); + llvm::Value* typeinfomem = new llvm::AllocaInst(typeinfoarraytype,"_arguments_storage",p->topallocapoint()); + for (unsigned i=0; i<vtype->getNumElements(); ++i) { + llvm::Value* v = p->ir->CreateBitCast(vtypeinfos[i], typeinfotype, "tmp"); + p->ir->CreateStore(v, LLVM_DtoGEPi(typeinfomem,0,i,"tmp")); + } + + llvm::Value* typeinfoarrayparam = new llvm::AllocaInst(llfnty->getParamType(j)->getContainedType(0),"_arguments_array",p->topallocapoint()); + p->ir->CreateStore(LLVM_DtoConstSize_t(vtype->getNumElements()), LLVM_DtoGEPi(typeinfoarrayparam,0,0,"tmp")); + llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, llvm::PointerType::get(typeinfotype), "tmp"); + p->ir->CreateStore(casttypeinfomem, LLVM_DtoGEPi(typeinfoarrayparam,0,1,"tmp")); + + llargs[j] = typeinfoarrayparam;; + j++; + llargs[j] = p->ir->CreateBitCast(mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); + j++; + llargs.resize(2); + } + else { + Logger::println("doing normal arguments"); + for (int i=0; i<arguments->dim; i++,j++) { + Argument* fnarg = Argument::getNth(tf->parameters, i); + llargs[j] = LLVM_DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]); + } + Logger::println("%d params passed", n); + for (int i=0; i<n; ++i) { + Logger::cout() << *llargs[i] << '\n'; + } } } @@ -1171,12 +1238,6 @@ if (llfnty->getReturnType() != llvm::Type::VoidTy) varname = "tmp"; - Logger::println("%d params passed", n); - for (int i=0; i<n; ++i) - { - Logger::cout() << *llargs[i] << '\n'; - } - Logger::cout() << "Calling: " << *funcval->getType() << '\n'; // call the function @@ -1342,7 +1403,7 @@ else if (fromtype->ty == Tpointer) { if (totype->ty == Tpointer || totype->ty == Tclass) { llvm::Value* src = u->getValue(); - //Logger::cout() << *src << '|' << *totype << '\n'; + Logger::cout() << *src << '|' << *tolltype << '\n'; e->val = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb()); } else if (totype->isintegral()) {