Changed the handling of variadic intrinsics a bit.

Removed the -fp80 option and made real be 80bit floats on X86, this is what the D spec really says it should be and fixes a bunch of issues.
Changed the handling of parameter attributes to a bit more generalized approach.
Added sext/zext attributes for byte/short/ubyte/ushort parameters, fixes #60 .
Parameter attribs now properly set for intrinsic calls if necessary.
Made the tango.math.Math patch less intrusive.
Fixed/added some mini tests.
This commit is contained in:
Tomas Lindquist Olsen 2008-08-01 17:59:58 +02:00
parent 858dd3e4fa
commit 9b45fc5533
32 changed files with 417 additions and 531 deletions

View file

@ -1,5 +1,6 @@
#include "gen/llvm.h"
#include "llvm/Support/CFG.h"
#include "llvm/Intrinsics.h"
#include "mtype.h"
#include "aggregate.h"
@ -62,7 +63,6 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
}
else{
assert(rt);
Type* rtfin = DtoDType(rt);
if (DtoIsReturnedInArg(rt)) {
rettype = getPtrToType(DtoType(rt));
actualRettype = LLType::VoidTy;
@ -72,6 +72,11 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
rettype = DtoType(rt);
actualRettype = rettype;
}
if (unsigned ea = DtoShouldExtend(rt))
{
f->llvmRetAttrs |= ea;
}
}
if (retinptr) {
@ -103,8 +108,6 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
size_t n = Argument::dim(f->parameters);
int nbyval = 0;
for (int i=0; i < n; ++i) {
Argument* arg = Argument::getNth(f->parameters, i);
// ensure scalar
@ -117,7 +120,8 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
if (isaStruct(at)) {
Logger::println("struct param");
paramvec.push_back(getPtrToType(at));
arg->llvmByVal = !refOrOut;
if (!refOrOut)
arg->llvmAttrs |= llvm::ParamAttr::ByVal;
}
else if (isaArray(at)) {
// static array are passed by reference
@ -137,6 +141,10 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
}
else {
Logger::println("in param");
if (unsigned ea = DtoShouldExtend(argT))
{
arg->llvmAttrs |= ea;
}
}
paramvec.push_back(at);
}
@ -151,9 +159,6 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
Logger::cout() << "lazy updated to: " << *at << '\n';
paramvec.back() = at;
}
if (arg->llvmByVal)
nbyval++;
}
//warning("set %d byval args for type: %s", nbyval, f->toChars());
@ -180,27 +185,17 @@ static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
}
TypeFunction* f = (TypeFunction*)fdecl->type;
assert(f != 0);
const llvm::FunctionType* fty = 0;
const llvm::PointerType* i8pty = getPtrToType(LLType::Int8Ty);
std::vector<const LLType*> args;
if (fdecl->llvmInternal == LLVMva_start) {
args.push_back(i8pty);
}
else if (fdecl->llvmInternal == LLVMva_intrinsic) {
size_t n = Argument::dim(f->parameters);
for (size_t i=0; i<n; ++i) {
args.push_back(i8pty);
}
}
else
assert(0);
const llvm::FunctionType* fty = llvm::FunctionType::get(LLType::VoidTy, args, false);
if (fdecl->llvmInternal == LLVMva_start)
fty = GET_INTRINSIC_DECL(vastart)->getFunctionType();
else if (fdecl->llvmInternal == LLVMva_copy)
fty = GET_INTRINSIC_DECL(vacopy)->getFunctionType();
else if (fdecl->llvmInternal == LLVMva_end)
fty = GET_INTRINSIC_DECL(vaend)->getFunctionType();
assert(fty);
f->ir.type = new llvm::PATypeHolder(fty);
return fty;
}
@ -208,14 +203,13 @@ static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
{
if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
// handle for C vararg intrinsics
if (fdecl->isVaIntrinsic())
return DtoVaFunctionType(fdecl);
}
// type has already been resolved
if (fdecl->type->ir.type != 0) {
if (fdecl->type->ir.type != 0)
return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get());
}
const LLType* thisty = NULL;
if (fdecl->needThis()) {
@ -246,22 +240,16 @@ static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
{
TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
LLConstant* fn = 0;
llvm::Function* func = 0;
if (fdecl->llvmInternal == LLVMva_start) {
fn = gIR->module->getOrInsertFunction("llvm.va_start", fty);
assert(fn);
}
else if (fdecl->llvmInternal == LLVMva_intrinsic) {
fn = gIR->module->getOrInsertFunction(fdecl->intrinsicName, fty);
assert(fn);
}
else
assert(0);
llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn);
if (fdecl->llvmInternal == LLVMva_start)
func = GET_INTRINSIC_DECL(vastart);
else if (fdecl->llvmInternal == LLVMva_copy)
func = GET_INTRINSIC_DECL(vacopy);
else if (fdecl->llvmInternal == LLVMva_end)
func = GET_INTRINSIC_DECL(vaend);
assert(func);
assert(func->isIntrinsic());
fdecl->ir.irFunc->func = func;
return func;
}
@ -330,36 +318,43 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati
std::vector<llvm::ParamAttrsWithIndex> attrs;
int k = 0;
int nbyval = 0;
llvm::ParamAttrsWithIndex PAWI;
// set zext/sext attr on return value if necessary
if (f->next->isintegral() && f->next->size() < PTRSIZE)
{
PAWI.Index = 0;
if (f->next->isunsigned())
PAWI.Attrs = llvm::ParamAttr::ZExt;
else
PAWI.Attrs = llvm::ParamAttr::SExt;
attrs.push_back(PAWI);
}
// set byval attrs on implicit main arg
if (fdecl->isMain() && Argument::dim(f->parameters) == 0)
{
llvm::ParamAttrsWithIndex PAWI;
PAWI.Index = llidx;
PAWI.Attrs = llvm::ParamAttr::ByVal;
attrs.push_back(PAWI);
llidx++;
nbyval++;
}
// set attrs on the rest of the arguments
for (; llidx <= funcNumArgs && f->parameters->dim > k; ++llidx,++k)
{
Argument* fnarg = (Argument*)f->parameters->data[k];
assert(fnarg);
if (fnarg->llvmByVal)
{
llvm::ParamAttrsWithIndex PAWI;
PAWI.Index = llidx;
PAWI.Attrs = llvm::ParamAttr::ByVal;
PAWI.Index = llidx;
PAWI.Attrs = fnarg->llvmAttrs;
if (PAWI.Attrs)
attrs.push_back(PAWI);
nbyval++;
}
}
if (nbyval) {
llvm::PAListPtr palist = llvm::PAListPtr::get(attrs.begin(), attrs.end());
func->setParamAttrs(palist);
}
llvm::PAListPtr palist = llvm::PAListPtr::get(attrs.begin(), attrs.end());
func->setParamAttrs(palist);
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -412,9 +407,8 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
mangled_name = fdecl->mangle();
llvm::Function* vafunc = 0;
if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
if (fdecl->isVaIntrinsic())
vafunc = DtoDeclareVaFunction(fdecl);
}
// construct function
const llvm::FunctionType* functype = DtoFunctionType(fdecl);
@ -437,7 +431,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
assert(llvm::isa<llvm::FunctionType>(f->ir.type->get()));
// parameter attributes
if (f->parameters) {
if (f->parameters && !fdecl->isIntrinsic()) {
set_param_attrs(f, func, fdecl);
}
@ -812,3 +806,15 @@ void DtoVariadicArgument(Expression* argexp, LLValue* dst)
}
//////////////////////////////////////////////////////////////////////////////////////////
bool FuncDeclaration::isIntrinsic()
{
return (llvmInternal == LLVMintrinsic || isVaIntrinsic());
}
bool FuncDeclaration::isVaIntrinsic()
{
return (llvmInternal == LLVMva_start ||
llvmInternal == LLVMva_copy ||
llvmInternal == LLVMva_end);
}