mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-04 00:55:49 +03:00
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:
parent
858dd3e4fa
commit
9b45fc5533
32 changed files with 417 additions and 531 deletions
73
dmd/attrib.c
73
dmd/attrib.c
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
16
dmd/id.c
16
dmd/id.c
|
@ -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");
|
||||
|
|
8
dmd/id.h
8
dmd/id.h
|
@ -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;
|
||||
|
|
|
@ -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" },
|
||||
|
|
23
dmd/mars.c
23
dmd/mars.c
|
@ -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);
|
||||
|
|
|
@ -135,7 +135,6 @@ struct Param
|
|||
char llvmInline;
|
||||
char llvmAnnotate;
|
||||
char *runtimePath;
|
||||
char useFP80;
|
||||
char useInlineAsm;
|
||||
char fqnPaths; // use fully qualified object names
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -2,10 +2,11 @@ enum
|
|||
{
|
||||
LLVMnone,
|
||||
LLVMintrinsic,
|
||||
LLVMva_intrinsic,
|
||||
LLVMno_typeinfo,
|
||||
LLVMno_moduleinfo,
|
||||
LLVMalloca,
|
||||
LLVMva_start,
|
||||
LLVMva_copy,
|
||||
LLVMva_end,
|
||||
LLVMva_arg
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -29,7 +29,6 @@ testversion=D_InlineAsm_PPC64
|
|||
testversion=LittleEndian
|
||||
testversion=BigEndian
|
||||
testversion=LLVM64
|
||||
textversion=LLVM_X86_FP80
|
||||
|
||||
|
||||
[compile]
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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> +∞ <td> +∞ <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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
24
tests/mini/packed1.d
Normal 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
14
tests/mini/real1.d
Normal 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
68
tests/mini/sextzext.d
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue