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

@ -831,7 +831,7 @@ void PragmaDeclaration::semantic(Scope *sc)
// LLVMDC
#if IN_LLVM
// pragma(intrinsic, dotExpS) { funcdecl(s) }
// pragma(intrinsic, string) { funcdecl(s) }
else if (ident == Id::intrinsic)
{
Expression* expr = (Expression *)args->data[0];
@ -844,19 +844,6 @@ void PragmaDeclaration::semantic(Scope *sc)
llvm_internal = LLVMintrinsic;
}
// pragma(va_intrinsic, dotExpS) { funcdecl(s) }
else if (ident == Id::va_intrinsic)
{
Expression* expr = (Expression *)args->data[0];
expr = expr->semantic(sc);
if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
{
error("pragma va_intrinsic requires exactly 1 string literal parameter");
fatal();
}
llvm_internal = LLVMva_intrinsic;
}
// pragma(notypeinfo) { typedecl(s) }
else if (ident == Id::no_typeinfo)
{
@ -880,7 +867,7 @@ void PragmaDeclaration::semantic(Scope *sc)
}
// pragma(alloca) { funcdecl(s) }
else if (ident == Id::alloca)
else if (ident == Id::Alloca)
{
if (args && args->dim > 0)
{
@ -891,7 +878,7 @@ void PragmaDeclaration::semantic(Scope *sc)
}
// pragma(va_start) { templdecl(s) }
else if (ident == Id::va_start)
else if (ident == Id::vastart)
{
if (args && args->dim > 0)
{
@ -901,8 +888,30 @@ void PragmaDeclaration::semantic(Scope *sc)
llvm_internal = LLVMva_start;
}
// pragma(va_copy) { funcdecl(s) }
else if (ident == Id::vacopy)
{
if (args && args->dim > 0)
{
error("pragma va_copy takes no parameters");
fatal();
}
llvm_internal = LLVMva_copy;
}
// pragma(va_end) { funcdecl(s) }
else if (ident == Id::vaend)
{
if (args && args->dim > 0)
{
error("pragma va_end takes no parameters");
fatal();
}
llvm_internal = LLVMva_end;
}
// pragma(va_arg) { templdecl(s) }
else if (ident == Id::va_arg)
else if (ident == Id::vaarg)
{
if (args && args->dim > 0)
{
@ -959,13 +968,12 @@ void PragmaDeclaration::semantic(Scope *sc)
{
if (s->llvmInternal)
{
error("multiple LLVMDC specific pragmas not allowed not affect the same declaration (%s at '%s')", s->toChars(), s->loc.toChars());
error("multiple LLVMDC specific pragmas not allowed not affect the same declaration ('%s' at '%s')", s->toChars(), s->loc.toChars());
fatal();
}
switch(llvm_internal)
{
case LLVMintrinsic:
case LLVMva_intrinsic:
if (FuncDeclaration* fd = s->isFuncDeclaration())
{
fd->llvmInternal = llvm_internal;
@ -973,7 +981,7 @@ void PragmaDeclaration::semantic(Scope *sc)
}
else
{
error("intrinsic pragmas are only allowed to affect function declarations");
error("the intrinsic pragma is only allowed on function declarations");
fatal();
}
break;
@ -984,24 +992,37 @@ void PragmaDeclaration::semantic(Scope *sc)
{
if (td->parameters->dim != 1)
{
error("the %s pragma template must have exactly one template parameter", ident->toChars());
error("the '%s' pragma template must have exactly one template parameter", ident->toChars());
fatal();
}
else if (!td->onemember)
{
error("the %s pragma template must have exactly one member", ident->toChars());
error("the '%s' pragma template must have exactly one member", ident->toChars());
fatal();
}
else if (td->overnext || td->overroot)
{
error("the %s pragma template must not be overloaded", ident->toChars());
error("the '%s' pragma template must not be overloaded", ident->toChars());
fatal();
}
td->llvmInternal = llvm_internal;
}
else
{
error("the %s pragma is only allowed on template declarations", ident->toChars());
error("the '%s' pragma is only allowed on template declarations", ident->toChars());
fatal();
}
break;
case LLVMva_copy:
case LLVMva_end:
if (FuncDeclaration* fd = s->isFuncDeclaration())
{
fd->llvmInternal = llvm_internal;
}
else
{
error("the '%s' pragma is only allowed on function declarations", ident->toChars());
fatal();
}
break;
@ -1017,13 +1038,13 @@ void PragmaDeclaration::semantic(Scope *sc)
}
else
{
error("the %s pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars());
error("the '%s' pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars());
fatal();
}
break;
default:
warning("LLVMDC specific pragma %s not yet implemented, ignoring", ident->toChars());
warning("the LLVMDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars());
}
}

View file

@ -127,8 +127,7 @@ void VersionCondition::checkPredefined(Loc loc, char *ident)
{
static char* reserved[] =
{
"DigitalMars", "LLVM", "LLVMDC",
"LLVM64", "LLVM_X86_FP80",
"DigitalMars", "LLVM", "LLVMDC", "LLVM64",
"X86", "X86_64", "PPC", "PPC64",
"Windows", "Win32", "Win64",
"linux",

View file

@ -642,6 +642,9 @@ struct FuncDeclaration : Declaration
std::set<VarDeclaration*> nestedVars;
std::string intrinsicName;
bool isIntrinsic();
bool isVaIntrinsic();
// we keep our own table of label statements as LabelDsymbolS
// don't always carry their corresponding statement along ...
typedef std::map<const char*, LabelStatement*> LabelMap;

View file

@ -171,9 +171,11 @@ Identifier *Id::intrinsic;
Identifier *Id::va_intrinsic;
Identifier *Id::no_typeinfo;
Identifier *Id::no_moduleinfo;
Identifier *Id::alloca;
Identifier *Id::va_start;
Identifier *Id::va_arg;
Identifier *Id::Alloca;
Identifier *Id::vastart;
Identifier *Id::vacopy;
Identifier *Id::vaend;
Identifier *Id::vaarg;
Identifier *Id::tohash;
Identifier *Id::tostring;
Identifier *Id::main;
@ -350,9 +352,11 @@ void Id::initialize()
va_intrinsic = Lexer::idPool("va_intrinsic");
no_typeinfo = Lexer::idPool("no_typeinfo");
no_moduleinfo = Lexer::idPool("no_moduleinfo");
alloca = Lexer::idPool("alloca");
va_start = Lexer::idPool("va_start");
va_arg = Lexer::idPool("va_arg");
Alloca = Lexer::idPool("alloca");
vastart = Lexer::idPool("va_start");
vacopy = Lexer::idPool("va_copy");
vaend = Lexer::idPool("va_end");
vaarg = Lexer::idPool("va_arg");
tohash = Lexer::idPool("toHash");
tostring = Lexer::idPool("toString");
main = Lexer::idPool("main");

View file

@ -173,9 +173,11 @@ struct Id
static Identifier *va_intrinsic;
static Identifier *no_typeinfo;
static Identifier *no_moduleinfo;
static Identifier *alloca;
static Identifier *va_start;
static Identifier *va_arg;
static Identifier *Alloca;
static Identifier *vastart;
static Identifier *vacopy;
static Identifier *vaend;
static Identifier *vaarg;
static Identifier *tohash;
static Identifier *tostring;
static Identifier *main;

View file

@ -218,9 +218,11 @@ Msgtable msgtable[] =
{ "va_intrinsic" },
{ "no_typeinfo" },
{ "no_moduleinfo" },
{ "alloca" },
{ "va_start" },
{ "va_arg" },
{ "Alloca", "alloca" },
{ "vastart", "va_start" },
{ "vacopy", "va_copy" },
{ "vaend", "va_end" },
{ "vaarg", "va_arg" },
// For toHash/toString
{ "tohash", "toHash" },

View file

@ -178,7 +178,6 @@ Usage:\n\
-debuglib=name set symbolic debug library to name\n\
-defaultlib=name set default library to name\n\
-dis disassemble module after compiling\n\
-fp80 enable 80bit reals on x86 32bit (EXPERIMENTAL)\n\
-g add symbolic debug info\n\
-gc add symbolic debug info, pretend to be C\n\
-H generate 'header' file\n\
@ -407,8 +406,6 @@ int main(int argc, char *argv[])
global.params.disassemble = 1;
else if (strcmp(p + 1, "annotate") == 0)
global.params.llvmAnnotate = 1;
else if (strcmp(p + 1, "fp80") == 0)
global.params.useFP80 = 1;
else if (strcmp(p + 1, "noasm") == 0)
global.params.useInlineAsm = 0;
else if (p[1] == 'o')
@ -697,20 +694,20 @@ int main(int argc, char *argv[])
findDefaultTarget();
}
bool is_x86 = false;
if (strcmp(global.params.llvmArch,"x86")==0) {
VersionCondition::addPredefinedGlobalIdent("X86");
//VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
global.params.isLE = true;
global.params.is64bit = false;
global.params.cpu = ARCHx86;
tt_arch = "i686";
data_layout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-f80:32:32-v64:64:64-v128:128:128-a0:0:64";
is_x86 = true;
if (global.params.useInlineAsm) {
VersionCondition::addPredefinedGlobalIdent("D_InlineAsm");
VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86");
}
}
else if (strcmp(global.params.llvmArch,"x86-64")==0) {
VersionCondition::addPredefinedGlobalIdent("X86_64");
//VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86_64");
global.params.isLE = true;
global.params.is64bit = true;
global.params.cpu = ARCHx86_64;
@ -752,18 +749,6 @@ int main(int argc, char *argv[])
VersionCondition::addPredefinedGlobalIdent("LLVM64");
}
if (global.params.useFP80) {
if (!is_x86) {
error("the -fp80 option is only valid for the x86 32bit architecture");
fatal();
}
VersionCondition::addPredefinedGlobalIdent("LLVM_X86_FP80");
}
if (is_x86 && global.params.useInlineAsm) {
VersionCondition::addPredefinedGlobalIdent("D_InlineAsm");
VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86");
}
assert(tt_arch != 0);
assert(tt_os != 0);
assert(data_layout != 0);

View file

@ -135,7 +135,6 @@ struct Param
char llvmInline;
char llvmAnnotate;
char *runtimePath;
char useFP80;
char useInlineAsm;
char fqnPaths; // use fully qualified object names
};

View file

@ -252,7 +252,7 @@ void Type::init()
}
// set real size and padding
if (global.params.useFP80)
if (global.params.cpu == ARCHx86)
{
REALSIZE = 12;
REALPAD = 2;
@ -2653,6 +2653,7 @@ TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, en
this->inuse = 0;
this->llvmRetInPtr = false;
this->llvmUsesThis = false;
this->llvmRetAttrs = 0;
}
Type *TypeFunction::syntaxCopy()
@ -2662,6 +2663,7 @@ Type *TypeFunction::syntaxCopy()
TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
t->llvmRetInPtr = llvmRetInPtr;
t->llvmUsesThis = llvmUsesThis;
t->llvmRetAttrs = llvmRetAttrs;
return t;
}
@ -5235,7 +5237,7 @@ Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Express
this->ident = ident;
this->storageClass = storageClass;
this->defaultArg = defaultArg;
this->llvmByVal = false;
this->llvmAttrs = 0;
}
Argument *Argument::syntaxCopy()
@ -5244,7 +5246,7 @@ Argument *Argument::syntaxCopy()
type ? type->syntaxCopy() : NULL,
ident,
defaultArg ? defaultArg->syntaxCopy() : NULL);
a->llvmByVal = llvmByVal;
a->llvmAttrs = llvmAttrs;
return a;
}

View file

@ -443,6 +443,7 @@ struct TypeFunction : Type
bool llvmRetInPtr;
bool llvmUsesThis;
unsigned llvmRetAttrs;
};
struct TypeDelegate : Type
@ -701,7 +702,7 @@ struct Argument : Object
static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
// LLVMDC
bool llvmByVal;
unsigned llvmAttrs;
};
extern int PTRSIZE;

View file

@ -35,7 +35,10 @@ const LLType* DtoComplexBaseType(Type* t)
return LLType::DoubleTy;
}
else if (ty == Tcomplex80) {
return (global.params.useFP80) ? LLType::X86_FP80Ty : LLType::DoubleTy;
if (global.params.cpu == ARCHx86)
return LLType::X86_FP80Ty;
else
return LLType::DoubleTy;
}
else {
assert(0);
@ -73,7 +76,7 @@ LLConstant* DtoConstComplex(Type* _ty, long double re, long double im)
base = Type::tfloat64;
}
else if (ty == Tcomplex80) {
base = (global.params.useFP80) ? Type::tfloat80 : Type::tfloat64;
base = Type::tfloat80;
}
std::vector<LLConstant*> inits;
@ -121,8 +124,8 @@ DValue* DtoComplex(Loc& loc, Type* to, DValue* val)
baserety = Type::tfloat64;
baseimty = Type::timaginary64;
} else if (ty == Tcomplex80) {
baserety = global.params.useFP80 ? Type::tfloat80 : Type::tfloat64;
baseimty = global.params.useFP80 ? Type::timaginary80 : Type::timaginary64;
baserety = Type::tfloat80;
baseimty = Type::timaginary80;
}
if (t->isimaginary()) {

View file

@ -2396,10 +2396,7 @@ struct AsmProcessor
case TOKfloat64v:
case TOKfloat80v:
// %% need different types?
if (global.params.useFP80)
e = new RealExp(stmt->loc, token->float80value, Type::tfloat80);
else
e = new RealExp(stmt->loc, token->float80value, Type::tfloat64);
nextToken();
break;
case TOKidentifier:

View file

@ -2,10 +2,11 @@ enum
{
LLVMnone,
LLVMintrinsic,
LLVMva_intrinsic,
LLVMno_typeinfo,
LLVMno_moduleinfo,
LLVMalloca,
LLVMva_start,
LLVMva_copy,
LLVMva_end,
LLVMva_arg
};

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.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);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -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);
}

View file

@ -10,6 +10,7 @@
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/Value.h"
#include "llvm/ParameterAttributes.h"
#include "llvm/Target/TargetData.h"
@ -37,9 +38,12 @@ using llvm::IRBuilder;
#define LLConstantStruct llvm::ConstantStruct
#define LLConstantArray llvm::ConstantArray
#define LLConstantInt llvm::ConstantInt
#define LLConstantFP llvm::ConstantFP
#define LLPATypeHolder llvm::PATypeHolder
#define LLSmallVector llvm::SmallVector
#define APFloat llvm::APFloat
#endif // GEN_LLVM_H

View file

@ -779,11 +779,9 @@ DValue* DtoCastFloat(Loc& loc, DValue* val, Type* to)
return DtoComplex(loc, to, val);
}
else if (totype->isfloating()) {
if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) {
rval = val->getRVal();
}
else if ((fromtype->ty == Timaginary80 || fromtype->ty == Timaginary64) && (totype->ty == Timaginary80 || totype->ty == Timaginary64)) {
if (fromsz == tosz) {
rval = val->getRVal();
assert(rval->getType() == tolltype);
}
else if (fromsz < tosz) {
rval = new llvm::FPExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());

View file

@ -165,7 +165,11 @@ static void LLVM_D_BuildRuntimeModule()
const LLType* longTy = LLType::Int64Ty;
const LLType* floatTy = LLType::FloatTy;
const LLType* doubleTy = LLType::DoubleTy;
const LLType* realTy = (global.params.useFP80) ? LLType::X86_FP80Ty : LLType::DoubleTy;
const LLType* realTy;
if (global.params.cpu == ARCHx86)
realTy = LLType::X86_FP80Ty;
else
realTy = LLType::DoubleTy;
const LLType* sizeTy = DtoSize_t();
const LLType* voidPtrTy = rt_ptr(byteTy);
const LLType* stringTy = rt_array(byteTy);

View file

@ -173,8 +173,8 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args, llvm::PAListPtr& palist, T
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
args.push_back(argval->getRVal());
if (fnarg->llvmByVal)
palist = palist.addAttr(argidx, llvm::ParamAttr::ByVal);
if (fnarg->llvmAttrs)
palist = palist.addAttr(argidx, fnarg->llvmAttrs);
++argidx;
}
@ -189,8 +189,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
// get func value if any
DFuncValue* dfnval = fnval->isFunc();
// handle special va_copy / va_end intrinsics
bool va_intrinsic = (dfnval && dfnval->func && (dfnval->func->llvmInternal == LLVMva_intrinsic));
// handle special vararg intrinsics
bool va_intrinsic = (dfnval && dfnval->func && dfnval->func->isVaIntrinsic());
// get function type info
TypeFunction* tf = DtoTypeFunction(fnval);
@ -263,6 +263,9 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
// handle the rest of the arguments based on param passing style
llvm::PAListPtr palist;
if (tf->llvmRetAttrs)
palist = palist.addAttr(0, tf->llvmRetAttrs);
// variadic instrinsics need some custom casts
if (va_intrinsic)
{
@ -293,10 +296,13 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
Argument* fnarg = Argument::getNth(tf->parameters, i);
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
LLValue* arg = argval->getRVal();
if (fnarg && arg->getType() != callableTy->getParamType(j))
if (fnarg)
{
if (arg->getType() != callableTy->getParamType(j))
arg = DtoBitCast(arg, callableTy->getParamType(j));
if (fnarg && fnarg->llvmByVal)
palist = palist.addAttr(j+1, llvm::ParamAttr::ByVal);
if (fnarg->llvmAttrs)
palist = palist.addAttr(j+1, fnarg->llvmAttrs);
}
++argiter;
args.push_back(arg);
}
@ -327,21 +333,17 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
if (retllval->getType()->isAbstract())
retllval = DtoBitCast(retllval, getPtrToType(DtoType(resulttype)), "retval");
// set calling convention
// set calling convention and parameter attributes
if (dfnval && dfnval->func)
{
int li = dfnval->func->llvmInternal;
if (li != LLVMintrinsic && li != LLVMva_start && li != LLVMva_intrinsic)
{
LLFunction* llfunc = llvm::dyn_cast<LLFunction>(dfnval->val);
if (llfunc && llfunc->isIntrinsic())
palist = llvm::Intrinsic::getParamAttrs((llvm::Intrinsic::ID)llfunc->getIntrinsicID());
else
call->setCallingConv(callconv);
}
}
else
{
call->setCallingConv(callconv);
}
// param attrs
call->setParamAttrs(palist);
return new DImValue(resulttype, retllval, false);

View file

@ -288,8 +288,12 @@ DValue* ComplexExp::toElem(IRState* p)
Type* t = DtoDType(type);
if (t->ty == Tcomplex32)
c = DtoConstFP(Type::tfloat32, 0);
else
else if (t->ty == Tcomplex64)
c = DtoConstFP(Type::tfloat64, 0);
else if (t->ty == Tcomplex80)
c = DtoConstFP(Type::tfloat80, 0);
else
assert(0);
return new DComplexValue(type, c, c);
}

View file

@ -35,6 +35,25 @@ bool DtoIsReturnedInArg(Type* type)
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
}
unsigned DtoShouldExtend(Type* type)
{
type = type->toBasetype();
if (type->isintegral())
{
switch(type->ty)
{
case Tint8:
case Tint16:
return llvm::ParamAttr::SExt;
case Tuns8:
case Tuns16:
return llvm::ParamAttr::ZExt;
}
}
return llvm::ParamAttr::None;
}
Type* DtoDType(Type* t)
{
if (t->ty == Ttypedef) {
@ -79,7 +98,10 @@ const LLType* DtoType(Type* t)
return LLType::DoubleTy;
case Tfloat80:
case Timaginary80:
return (global.params.useFP80) ? LLType::X86_FP80Ty : LLType::DoubleTy;
if (global.params.cpu == ARCHx86)
return LLType::X86_FP80Ty;
else
return LLType::DoubleTy;
// complex
case Tcomplex32:
@ -485,11 +507,9 @@ llvm::ConstantInt* DtoConstUbyte(unsigned char i)
llvm::ConstantFP* DtoConstFP(Type* t, long double value)
{
TY ty = DtoDType(t)->ty;
if (ty == Tfloat32 || ty == Timaginary32)
return llvm::ConstantFP::get(llvm::APFloat(float(value)));
else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tfloat80 || ty == Timaginary80)
return llvm::ConstantFP::get(llvm::APFloat(double(value)));
const LLType* llty = DtoType(t);
assert(llty->isFloatingPoint());
return LLConstantFP::get(llty, value);
}
//////////////////////////////////////////////////////////////////////////////////////////

View file

@ -21,6 +21,8 @@ bool DtoIsPassedByRef(Type* type);
// returns if the type should be returned in a hidden pointer arguement
bool DtoIsReturnedInArg(Type* type);
unsigned DtoShouldExtend(Type* type);
// resolve typedefs to their real type.
// TODO should probably be removed in favor of DMD's Type::toBasetype
Type* DtoDType(Type* t);

View file

@ -22,8 +22,8 @@ pragma(va_start)
pragma(va_arg)
T va_arg(T)(va_list ap);
pragma(va_intrinsic, "llvm.va_end")
pragma(va_end)
void va_end(va_list args);
pragma(va_intrinsic, "llvm.va_copy")
pragma(va_copy)
void va_copy(va_list dst, va_list src);

View file

@ -106,7 +106,7 @@ pragma(intrinsic, "llvm.sqrt.f32")
float llvm_sqrt_f32(float val);
pragma(intrinsic, "llvm.sqrt.f64")
double llvm_sqrt_f64(double val);
version(LLVM_X86_FP80)
version(X86)
{
pragma(intrinsic, "llvm.sqrt.f80")
real llvm_sqrt_f80(real val);
@ -119,7 +119,7 @@ pragma(intrinsic, "llvm.sin.f32")
float llvm_sin_f32(float val);
pragma(intrinsic, "llvm.sin.f64")
double llvm_sin_f64(double val);
version(LLVM_X86_FP80)
version(X86)
{
pragma(intrinsic, "llvm.sin.f80")
real llvm_sin_f80(real val);
@ -132,7 +132,7 @@ pragma(intrinsic, "llvm.cos.f32")
float llvm_cos_f32(float val);
pragma(intrinsic, "llvm.cos.f64")
double llvm_cos_f64(double val);
version(LLVM_X86_FP80)
version(X86)
{
pragma(intrinsic, "llvm.cos.f80")
real llvm_cos_f80(real val);
@ -146,7 +146,7 @@ pragma(intrinsic, "llvm.powi.f32")
pragma(intrinsic, "llvm.powi.f64")
double llvm_powi_f64(double val, int power);
version(LLVM_X86_FP80)
version(X86)
{
pragma(intrinsic, "llvm.powi.f80")
real llvm_powi_f80(real val, int power);
@ -160,7 +160,7 @@ pragma(intrinsic, "llvm.pow.f32")
pragma(intrinsic, "llvm.pow.f64")
double llvm_pow_f64(double val, double power);
version(LLVM_X86_FP80)
version(X86)
{
pragma(intrinsic, "llvm.pow.f80")
real llvm_pow_f80(real val, real power);

View file

@ -29,7 +29,6 @@ testversion=D_InlineAsm_PPC64
testversion=LittleEndian
testversion=BigEndian
testversion=LLVM64
textversion=LLVM_X86_FP80
[compile]

View file

@ -406,6 +406,11 @@
<path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/dmd/monitor.c</path>
<path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/gdc</path>
<path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/gdc/monitor.c</path>
<path>runtime/build.sh</path>
<path>runtime/internal</path>
<path>runtime/internal/critical.c</path>
<path>runtime/internal/mars.h</path>
<path>runtime/internal/monitor.c</path>
</blacklist>
<build>
<buildtool>make</buildtool>

View file

@ -209,96 +209,47 @@ Index: tango/math/Math.d
===================================================================
--- tango/math/Math.d (revision 3831)
+++ tango/math/Math.d (working copy)
@@ -76,7 +76,77 @@
@@ -76,6 +76,14 @@
version = DigitalMars_D_InlineAsm_X86;
}
}
+else version(LLVMDC)
+{
+ private
+ import llvmdc.intrinsics;
+ version(X86)
+ {
+ pragma(intrinsic, "llvm.sqrt.f32")
+ float sqrt(float);
+ pragma(intrinsic, "llvm.sqrt.f64")
+ double sqrt(double);
+
+ version(LLVM_X86_FP80)
+ {
+ alias tango.stdc.math.tanl llvm_tan;
+ alias tango.stdc.math.acosl llvm_acos;
+ alias tango.stdc.math.asinl llvm_asin;
+ alias tango.stdc.math.atanl llvm_atan;
+ alias tango.stdc.math.atan2l llvm_atan2;
+ alias tango.stdc.math.coshl llvm_cosh;
+ alias tango.stdc.math.sinhl llvm_sinh;
+ alias tango.stdc.math.tanhl llvm_tanh;
+ alias tango.stdc.math.cbrtl llvm_cbrt;
+ alias tango.stdc.math.expl llvm_exp;
+ alias tango.stdc.math.expm1l llvm_expm1;
+ alias tango.stdc.math.exp2l llvm_exp2;
+ alias tango.stdc.math.logl llvm_log;
+ alias tango.stdc.math.log1pl llvm_log1p;
+ alias tango.stdc.math.log2l llvm_log2;
+ alias tango.stdc.math.log10l llvm_log10;
+ alias tango.stdc.math.powl llvm_pow;
+ alias tango.stdc.math.lrintl llvm_lrint;
+ alias tango.stdc.math.llrintl llvm_llrint;
+
+ pragma(intrinsic, "llvm.cos.f80")
+ real cos(real);
+ pragma(intrinsic, "llvm.sin.f80")
+ real sin(real);
+ pragma(intrinsic, "llvm.sqrt.f80")
+ real sqrt(real);
+ }
+ else
+ {
+ alias tango.stdc.math.tan llvm_tan;
+ alias tango.stdc.math.acos llvm_acos;
+ alias tango.stdc.math.asin llvm_asin;
+ alias tango.stdc.math.atan llvm_atan;
+ alias tango.stdc.math.atan2 llvm_atan2;
+ alias tango.stdc.math.cosh llvm_cosh;
+ alias tango.stdc.math.sinh llvm_sinh;
+ alias tango.stdc.math.tanh llvm_tanh;
+ alias tango.stdc.math.cbrt llvm_cbrt;
+ alias tango.stdc.math.exp llvm_exp;
+ alias tango.stdc.math.expm1 llvm_expm1;
+ alias tango.stdc.math.exp2 llvm_exp2;
+ alias tango.stdc.math.log llvm_log;
+ alias tango.stdc.math.log1p llvm_log1p;
+ alias tango.stdc.math.log2 llvm_log2;
+ alias tango.stdc.math.log10 llvm_log10;
+ alias tango.stdc.math.pow llvm_pow;
+ alias tango.stdc.math.lrint llvm_lrint;
+ alias tango.stdc.math.llrint llvm_llrint;
+
+ pragma(intrinsic, "llvm.cos.f64")
+ real cos(real);
+ pragma(intrinsic, "llvm.sin.f64")
+ real sin(real);
+ pragma(intrinsic, "llvm.sqrt.f64")
+ real sqrt(real);
+ }
+ version = LLVMDC_X86;
+ }
+}
+
/*
* Constants
*/
@@ -298,6 +368,10 @@
@@ -298,6 +306,24 @@
* Bugs:
* Results are undefined if |x| >= $(POWER 2,64).
*/
+version(LLVMDC)
+{}
+{
+ alias llvm_cos_f32 cos;
+ alias llvm_cos_f64 cos;
+ version(X86)
+ {
+ alias llvm_cos_f80 cos;
+ }
+ else
+ {
+ real cos(real x)
+ {
+ return tango.stdc.math.cosl(x);
+ }
+ }
+}
+else
+{
real cos(real x) /* intrinsic */
{
version(D_InlineAsm_X86)
@@ -313,6 +387,7 @@
@@ -313,6 +339,7 @@
return tango.stdc.math.cosl(x);
}
}
@ -306,18 +257,32 @@ Index: tango/math/Math.d
debug(UnitTest) {
unittest {
@@ -333,6 +408,10 @@
@@ -333,6 +360,24 @@
* Bugs:
* Results are undefined if |x| >= $(POWER 2,64).
*/
+version(LLVMDC)
+{}
+{
+ alias llvm_sin_f32 sin;
+ alias llvm_sin_f64 sin;
+ version(X86)
+ {
+ alias llvm_sin_f80 sin;
+ }
+ else
+ {
+ real sin(real x)
+ {
+ return tango.stdc.math.sinl(x);
+ }
+ }
+}
+else
+{
real sin(real x) /* intrinsic */
{
version(D_InlineAsm_X86)
@@ -348,6 +427,7 @@
@@ -348,6 +393,7 @@
return tango.stdc.math.sinl(x);
}
}
@ -325,283 +290,62 @@ Index: tango/math/Math.d
debug(UnitTest) {
unittest {
@@ -374,6 +454,9 @@
@@ -374,7 +420,11 @@
{
version (GNU) {
return tanl(x);
- } else {
+ }
+ else version(LLVMDC) {
+ return llvm_tan(x);
} else {
+ return tango.stdc.math.tanl(x);
+ }
+ else {
asm
{
@@ -576,7 +659,14 @@
*/
real acos(real x)
{
- return tango.stdc.math.acosl(x);
+ version(LLVMDC)
+ {
+ return llvm_acos(x);
+ }
+ else
+ {
+ return tango.stdc.math.acosl(x);
+ }
}
debug(UnitTest) {
@@ -599,7 +689,14 @@
*/
real asin(real x)
{
- return tango.stdc.math.asinl(x);
+ version(LLVMDC)
+ {
+ return llvm_asin(x);
+ }
+ else
+ {
+ return tango.stdc.math.asinl(x);
+ }
}
debug(UnitTest) {
@@ -621,7 +718,14 @@
*/
real atan(real x)
{
- return tango.stdc.math.atanl(x);
+ version(LLVMDC)
+ {
+ return llvm_atan(x);
+ }
+ else
+ {
+ return tango.stdc.math.atanl(x);
+ }
}
debug(UnitTest) {
@@ -658,7 +762,14 @@
*/
real atan2(real y, real x)
{
- return tango.stdc.math.atan2l(y,x);
+ version(LLVMDC)
+ {
+ return llvm_atan2(y,x);
+ }
+ else
+ {
+ return tango.stdc.math.atan2l(y,x);
+ }
}
debug(UnitTest) {
@@ -707,7 +818,14 @@
*/
real cosh(real x)
{
- return tango.stdc.math.coshl(x);
+ version(LLVMDC)
+ {
+ return llvm_cosh(x);
+ }
+ else
+ {
+ return tango.stdc.math.coshl(x);
+ }
}
debug(UnitTest) {
@@ -728,7 +846,14 @@
*/
real sinh(real x)
{
- return tango.stdc.math.sinhl(x);
+ version(LLVMDC)
+ {
+ return llvm_sinh(x);
+ }
+ else
+ {
+ return tango.stdc.math.sinhl(x);
+ }
}
debug(UnitTest) {
@@ -749,7 +874,14 @@
*/
real tanh(real x)
{
- return tango.stdc.math.tanhl(x);
+ version(LLVMDC)
+ {
+ return llvm_tanh(x);
+ }
+ else
+ {
+ return tango.stdc.math.tanhl(x);
+ }
}
debug(UnitTest) {
@@ -947,6 +1079,10 @@
fld x[EBP] ; // load theta
@@ -947,6 +997,25 @@
* <tr> <td> +&infin; <td> +&infin; <td> no
* )
*/
+version(LLVMDC)
+{}
+{
+ alias llvm_sqrt_f32 sqrt;
+ alias llvm_sqrt_f64 sqrt;
+ version(X86)
+ {
+ alias llvm_sqrt_f80 sqrt;
+ }
+ else
+ {
+ real sqrt(real x)
+ {
+ return tango.stdc.math.sqrtl(x);
+ }
+ }
+}
+else
+{
+
float sqrt(float x) /* intrinsic */
{
version(D_InlineAsm_X86)
@@ -994,6 +1130,7 @@
return tango.stdc.math.sqrtl(x);
@@ -995,6 +1064,8 @@
}
}
+}
+}
+
/** ditto */
creal sqrt(creal z)
@@ -1045,7 +1182,14 @@
*/
real cbrt(real x)
{
- return tango.stdc.math.cbrtl(x);
+ version(LLVMDC)
+ {
+ return llvm_cbrt(x);
+ }
+ else
+ {
+ return tango.stdc.math.cbrtl(x);
+ }
}
@@ -1067,7 +1211,14 @@
*/
real exp(real x)
{
- return tango.stdc.math.expl(x);
+ version(LLVMDC)
+ {
+ return llvm_exp(x);
+ }
+ else
+ {
+ return tango.stdc.math.expl(x);
+ }
}
debug(UnitTest) {
@@ -1093,7 +1244,14 @@
*/
real expm1(real x)
{
- return tango.stdc.math.expm1l(x);
+ version(LLVMDC)
+ {
+ return llvm_expm1(x);
+ }
+ else
+ {
+ return tango.stdc.math.expm1l(x);
+ }
}
debug(UnitTest) {
@@ -1115,7 +1273,14 @@
*/
real exp2(real x)
{
- return tango.stdc.math.exp2l(x);
+ version(LLVMDC)
+ {
+ return llvm_exp2(x);
+ }
+ else
+ {
+ return tango.stdc.math.exp2l(x);
+ }
}
debug(UnitTest) {
@@ -1141,7 +1306,14 @@
*/
real log(real x)
{
- return tango.stdc.math.logl(x);
+ version(LLVMDC)
+ {
+ return llvm_log(x);
+ }
+ else
+ {
+ return tango.stdc.math.logl(x);
+ }
}
debug(UnitTest) {
@@ -1167,7 +1339,14 @@
*/
real log1p(real x)
{
- return tango.stdc.math.log1pl(x);
+ version(LLVMDC)
+ {
+ return llvm_log1p(x);
+ }
+ else
+ {
+ return tango.stdc.math.log1pl(x);
+ }
}
debug(UnitTest) {
@@ -1190,7 +1369,14 @@
*/
real log2(real x)
{
- return tango.stdc.math.log2l(x);
+ version(LLVMDC)
+ {
+ return llvm_log2(x);
+ }
+ else
+ {
+ return tango.stdc.math.log2l(x);
+ }
}
debug(UnitTest) {
@@ -1212,7 +1398,14 @@
*/
real log10(real x)
{
- return tango.stdc.math.log10l(x);
+ version(LLVMDC)
+ {
+ return llvm_log10(x);
+ }
+ else
+ {
+ return tango.stdc.math.log10l(x);
+ }
}
debug(UnitTest) {
@@ -1477,7 +1670,14 @@
@@ -1477,7 +1548,14 @@
}
}
}
- return tango.stdc.math.powl(x, y);
+ version(LLVMDC)
+ version(LLVMDC_X86)
+ {
+ return llvm_pow(x, y);
+ return llvm_pow_f80(x, y);
+ }
+ else
+ {
@ -610,28 +354,6 @@ Index: tango/math/Math.d
}
debug(UnitTest) {
@@ -1823,6 +2023,10 @@
}
return n;
}
+ else version(LLVMDC)
+ {
+ return llvm_lrint(x);
+ }
else
{
return tango.stdc.math.lrintl(x);
@@ -1842,6 +2046,10 @@
}
return n;
}
+ else version(LLVMDC)
+ {
+ return llvm_llrint(x);
+ }
else
{
return tango.stdc.math.llrintl(x);
Index: tango/stdc/stdlib.d
===================================================================
--- tango/stdc/stdlib.d (revision 3831)

View file

@ -23,7 +23,7 @@ void main()
printf("Enter real: ");
//scanf("%lf", &d);
r = 3.2311167891231231234754764576;
version(LLVM_X86_FP80)
version(X86)
{
real sr = llvm_sqrt_f80(r);
printf("sqrt(%llf) = %llf\n", r, sr);
@ -31,6 +31,6 @@ void main()
else
{
real sr = llvm_sqrt_f64(r);
printf("sqrt(%lf) = %lf\n", r, sr);
printf("sqrt(%f) = %lf\n", r, sr);
}
}

View file

@ -14,10 +14,10 @@ void main()
assert(ma[1][1].length == 3);
assert(ma[1][2].length == 3);
assert(ma[1][3].length == 3);
ma[0][3][1] = 32;
ma[1][2][2] = 123;
ma[0][0][3] = 55;
assert(ma[0][3][1] == 32);
assert(ma[1][2][2] == 123);
assert(ma[0][0][3] == 55);
ma[0][3][0] = 32;
ma[1][2][1] = 123;
ma[0][0][2] = 55;
assert(ma[0][3][0] == 32);
assert(ma[1][2][1] == 123);
assert(ma[0][0][2] == 55);
}

24
tests/mini/packed1.d Normal file
View file

@ -0,0 +1,24 @@
module mini.packed1;
extern(C) int printf(char*, ...);
align(1)
struct PackedStruct
{
ubyte ub;
float f;
long l;
short s;
ubyte ub2;
short s2;
}
void main()
{
PackedStruct[2] a = void;
void* begin = a.ptr;
void* end = &a[1];
ptrdiff_t sz = end - begin;
printf("size = 18 = %u = %u\n", PackedStruct.sizeof, sz);
assert(sz == 18);
}

14
tests/mini/real1.d Normal file
View file

@ -0,0 +1,14 @@
module mini.real1;
extern(C)
{
real tanl(real x);
int printf(char*, ...);
}
void main()
{
real ans = tanl(0.785398163398);
printf("%llf\n", ans);
assert(ans > 0.999 && ans < 1.001);
}

68
tests/mini/sextzext.d Normal file
View file

@ -0,0 +1,68 @@
module mini.sextzext;
void main()
{
byte sb = sextreturn1();
short ss = sextreturn2();
assert(ss == -2);
assert(sb == -2);
assert(sextparam1(-42) == -42);
assert(sextparam2(-42) == -42);
ubyte ub = zextreturn1();
ushort us = zextreturn2();
assert(ub == 2);
assert(us == 2);
assert(zextparam1(42) == 42);
assert(zextparam2(42) == 42);
assert(getchar() == 'a');
assert(passchar('z') == 'z');
}
byte sextreturn1()
{
return -2;
}
short sextreturn2()
{
return -2;
}
ubyte zextreturn1()
{
return 2;
}
ushort zextreturn2()
{
return 2;
}
byte sextparam1(byte b)
{
return b;
}
short sextparam2(short s)
{
return s;
}
ubyte zextparam1(ubyte b)
{
return b;
}
ushort zextparam2(ushort s)
{
return s;
}
char getchar()
{
return 'a';
}
char passchar(char ch)
{
return ch;
}

View file

@ -142,13 +142,8 @@ void print(TypeInfo ti, void* arg)
printf("%f", *cast(float*)arg);
else if (ti == typeid(double))
printf("%f", *cast(double*)arg);
else if (ti == typeid(real)) // FIXME: 80bit?
{
version(LLVM_X86_FP80)
else if (ti == typeid(real))
printf("%llf", *cast(real*)arg);
else
printf("%f", *cast(real*)arg);
}
else if (ti == typeid(char))
printf("%.*s", 1, arg);