Mercurial > projects > ldc
diff gen/tollvm.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/tollvm.c Wed Oct 24 22:26:37 2007 +0200 +++ b/gen/tollvm.c Thu Oct 25 02:39:53 2007 +0200 @@ -262,6 +262,14 @@ return llvm::cast<llvm::FunctionType>(f->llvmType); } + bool typesafeVararg = false; + if (f->linkage == LINKd && f->varargs == 1) { + assert(fdecl->v_arguments); + Logger::println("v_arguments = %s", fdecl->v_arguments->toChars()); + assert(fdecl->v_arguments->isParameter()); + typesafeVararg = true; + } + // return value type const llvm::Type* rettype; const llvm::Type* actualRettype; @@ -291,84 +299,92 @@ // parameter types std::vector<const llvm::Type*> paramvec; - if (fdecl->llvmInternal == LLVMva_start) { + if (retinptr) { + Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; + paramvec.push_back(rettype); + } + + if (fdecl->needThis()) { + if (AggregateDeclaration* ad = fdecl->isMember()) { + Logger::print("isMember = this is: %s\n", ad->type->toChars()); + const llvm::Type* thisty = LLVM_DtoType(ad->type); + Logger::cout() << "this llvm type: " << *thisty << '\n'; + if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get()) + thisty = llvm::PointerType::get(thisty); + paramvec.push_back(thisty); + usesthis = true; + } + else + assert(0); + } + else if (fdecl->isNested()) { + paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); + usesthis = true; + } + + if (typesafeVararg) { + ClassDeclaration* ti = Type::typeinfo; + if (!ti->llvmInitZ) + ti->toObjFile(); + assert(ti->llvmInitZ); + std::vector<const llvm::Type*> types; + types.push_back(LLVM_DtoSize_t()); + types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType()))); + const llvm::Type* t1 = llvm::StructType::get(types); + paramvec.push_back(llvm::PointerType::get(t1)); paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); } - else { - if (retinptr) { - Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; - paramvec.push_back(rettype); + + size_t n = Argument::dim(f->parameters); + + for (int i=0; i < n; ++i) { + Argument* arg = Argument::getNth(f->parameters, i); + // ensure scalar + Type* argT = LLVM_DtoDType(arg->type); + assert(argT); + + if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { + //assert(arg->vardecl); + //arg->vardecl->refparam = true; } + else + arg->llvmCopy = true; - if (fdecl->needThis()) { - if (AggregateDeclaration* ad = fdecl->isMember()) { - Logger::print("isMember = this is: %s\n", ad->type->toChars()); - const llvm::Type* thisty = LLVM_DtoType(ad->type); - Logger::cout() << "this llvm type: " << *thisty << '\n'; - if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get()) - thisty = llvm::PointerType::get(thisty); - paramvec.push_back(thisty); - usesthis = true; - } + const llvm::Type* at = LLVM_DtoType(argT); + if (llvm::isa<llvm::StructType>(at)) { + Logger::println("struct param"); + paramvec.push_back(llvm::PointerType::get(at)); + } + else if (llvm::isa<llvm::ArrayType>(at)) { + Logger::println("sarray param"); + assert(argT->ty == Tsarray); + //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); + paramvec.push_back(llvm::PointerType::get(at)); + } + else if (llvm::isa<llvm::OpaqueType>(at)) { + Logger::println("opaque param"); + if (argT->ty == Tstruct || argT->ty == Tclass) + paramvec.push_back(llvm::PointerType::get(at)); else assert(0); } - else if (fdecl->isNested()) { - paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); - usesthis = true; - } - - size_t n = Argument::dim(f->parameters); - - for (int i=0; i < n; ++i) { - Argument* arg = Argument::getNth(f->parameters, i); - // ensure scalar - Type* argT = LLVM_DtoDType(arg->type); - assert(argT); - - if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { - //assert(arg->vardecl); - //arg->vardecl->refparam = true; - } - else - arg->llvmCopy = true; - - const llvm::Type* at = LLVM_DtoType(argT); - if (llvm::isa<llvm::StructType>(at)) { - Logger::println("struct param"); - paramvec.push_back(llvm::PointerType::get(at)); + /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) { + paramvec.push_back(llvm::PointerType::get(at)); + }*/ + else { + if (!arg->llvmCopy) { + Logger::println("ref param"); + at = llvm::PointerType::get(at); } - else if (llvm::isa<llvm::ArrayType>(at)) { - Logger::println("sarray param"); - assert(argT->ty == Tsarray); - //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); - paramvec.push_back(llvm::PointerType::get(at)); - } - else if (llvm::isa<llvm::OpaqueType>(at)) { - Logger::println("opaque param"); - if (argT->ty == Tstruct || argT->ty == Tclass) - paramvec.push_back(llvm::PointerType::get(at)); - else - assert(0); + else { + Logger::println("in param"); } - /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) { - paramvec.push_back(llvm::PointerType::get(at)); - }*/ - else { - if (!arg->llvmCopy) { - Logger::println("ref param"); - at = llvm::PointerType::get(at); - } - else { - Logger::println("in param"); - } - paramvec.push_back(at); - } + paramvec.push_back(at); } } // construct function type - bool isvararg = f->varargs; + bool isvararg = !typesafeVararg && f->varargs; llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); f->llvmType = functype; @@ -1075,18 +1091,33 @@ iarg->setName("this"); ++iarg; } + int varargs = -1; + if (f->linkage == LINKd && f->varargs == 1) + varargs = 0; for (; iarg != func->arg_end(); ++iarg) { Argument* arg = Argument::getNth(f->parameters, k++); - assert(arg != 0); //arg->llvmValue = iarg; //printf("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); - if (arg->ident != 0) { + if (arg && arg->ident != 0) { if (arg->vardecl) { arg->vardecl->llvmValue = iarg; } iarg->setName(arg->ident->toChars()); } + else if (!arg && varargs >= 0) { + if (varargs == 0) { + iarg->setName("_arguments"); + fdecl->llvmArguments = iarg; + } + else if (varargs == 1) { + iarg->setName("_argptr"); + fdecl->llvmArgPtr = iarg; + } + else + assert(0); + varargs++; + } else { iarg->setName("unnamed"); } @@ -1236,7 +1267,7 @@ else { Logger::println("as ptr arg"); retval = arg->mem ? arg->mem : arg->val; - if (retval->getType() != paramtype) + if (paramtype && retval->getType() != paramtype) { assert(retval->getType() == paramtype->getContainedType(0)); LLVM_DtoGiveArgumentStorage(arg); @@ -1247,7 +1278,7 @@ delete arg; - if (fnarg && retval->getType() != paramtype) { + if (fnarg && paramtype && retval->getType() != paramtype) { Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n"; assert(0 && "parameter type that was actually passed is invalid"); }