mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-04 17:11:44 +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
|
// LLVMDC
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
|
|
||||||
// pragma(intrinsic, dotExpS) { funcdecl(s) }
|
// pragma(intrinsic, string) { funcdecl(s) }
|
||||||
else if (ident == Id::intrinsic)
|
else if (ident == Id::intrinsic)
|
||||||
{
|
{
|
||||||
Expression* expr = (Expression *)args->data[0];
|
Expression* expr = (Expression *)args->data[0];
|
||||||
|
@ -844,19 +844,6 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||||
llvm_internal = LLVMintrinsic;
|
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) }
|
// pragma(notypeinfo) { typedecl(s) }
|
||||||
else if (ident == Id::no_typeinfo)
|
else if (ident == Id::no_typeinfo)
|
||||||
{
|
{
|
||||||
|
@ -880,7 +867,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pragma(alloca) { funcdecl(s) }
|
// pragma(alloca) { funcdecl(s) }
|
||||||
else if (ident == Id::alloca)
|
else if (ident == Id::Alloca)
|
||||||
{
|
{
|
||||||
if (args && args->dim > 0)
|
if (args && args->dim > 0)
|
||||||
{
|
{
|
||||||
|
@ -891,7 +878,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pragma(va_start) { templdecl(s) }
|
// pragma(va_start) { templdecl(s) }
|
||||||
else if (ident == Id::va_start)
|
else if (ident == Id::vastart)
|
||||||
{
|
{
|
||||||
if (args && args->dim > 0)
|
if (args && args->dim > 0)
|
||||||
{
|
{
|
||||||
|
@ -901,8 +888,30 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||||
llvm_internal = LLVMva_start;
|
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) }
|
// pragma(va_arg) { templdecl(s) }
|
||||||
else if (ident == Id::va_arg)
|
else if (ident == Id::vaarg)
|
||||||
{
|
{
|
||||||
if (args && args->dim > 0)
|
if (args && args->dim > 0)
|
||||||
{
|
{
|
||||||
|
@ -959,13 +968,12 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||||
{
|
{
|
||||||
if (s->llvmInternal)
|
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();
|
fatal();
|
||||||
}
|
}
|
||||||
switch(llvm_internal)
|
switch(llvm_internal)
|
||||||
{
|
{
|
||||||
case LLVMintrinsic:
|
case LLVMintrinsic:
|
||||||
case LLVMva_intrinsic:
|
|
||||||
if (FuncDeclaration* fd = s->isFuncDeclaration())
|
if (FuncDeclaration* fd = s->isFuncDeclaration())
|
||||||
{
|
{
|
||||||
fd->llvmInternal = llvm_internal;
|
fd->llvmInternal = llvm_internal;
|
||||||
|
@ -973,7 +981,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error("intrinsic pragmas are only allowed to affect function declarations");
|
error("the intrinsic pragma is only allowed on function declarations");
|
||||||
fatal();
|
fatal();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -984,24 +992,37 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||||
{
|
{
|
||||||
if (td->parameters->dim != 1)
|
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();
|
fatal();
|
||||||
}
|
}
|
||||||
else if (!td->onemember)
|
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();
|
fatal();
|
||||||
}
|
}
|
||||||
else if (td->overnext || td->overroot)
|
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();
|
fatal();
|
||||||
}
|
}
|
||||||
td->llvmInternal = llvm_internal;
|
td->llvmInternal = llvm_internal;
|
||||||
}
|
}
|
||||||
else
|
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();
|
fatal();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1017,13 +1038,13 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||||
}
|
}
|
||||||
else
|
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();
|
fatal();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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[] =
|
static char* reserved[] =
|
||||||
{
|
{
|
||||||
"DigitalMars", "LLVM", "LLVMDC",
|
"DigitalMars", "LLVM", "LLVMDC", "LLVM64",
|
||||||
"LLVM64", "LLVM_X86_FP80",
|
|
||||||
"X86", "X86_64", "PPC", "PPC64",
|
"X86", "X86_64", "PPC", "PPC64",
|
||||||
"Windows", "Win32", "Win64",
|
"Windows", "Win32", "Win64",
|
||||||
"linux",
|
"linux",
|
||||||
|
|
|
@ -642,6 +642,9 @@ struct FuncDeclaration : Declaration
|
||||||
std::set<VarDeclaration*> nestedVars;
|
std::set<VarDeclaration*> nestedVars;
|
||||||
std::string intrinsicName;
|
std::string intrinsicName;
|
||||||
|
|
||||||
|
bool isIntrinsic();
|
||||||
|
bool isVaIntrinsic();
|
||||||
|
|
||||||
// we keep our own table of label statements as LabelDsymbolS
|
// we keep our own table of label statements as LabelDsymbolS
|
||||||
// don't always carry their corresponding statement along ...
|
// don't always carry their corresponding statement along ...
|
||||||
typedef std::map<const char*, LabelStatement*> LabelMap;
|
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::va_intrinsic;
|
||||||
Identifier *Id::no_typeinfo;
|
Identifier *Id::no_typeinfo;
|
||||||
Identifier *Id::no_moduleinfo;
|
Identifier *Id::no_moduleinfo;
|
||||||
Identifier *Id::alloca;
|
Identifier *Id::Alloca;
|
||||||
Identifier *Id::va_start;
|
Identifier *Id::vastart;
|
||||||
Identifier *Id::va_arg;
|
Identifier *Id::vacopy;
|
||||||
|
Identifier *Id::vaend;
|
||||||
|
Identifier *Id::vaarg;
|
||||||
Identifier *Id::tohash;
|
Identifier *Id::tohash;
|
||||||
Identifier *Id::tostring;
|
Identifier *Id::tostring;
|
||||||
Identifier *Id::main;
|
Identifier *Id::main;
|
||||||
|
@ -350,9 +352,11 @@ void Id::initialize()
|
||||||
va_intrinsic = Lexer::idPool("va_intrinsic");
|
va_intrinsic = Lexer::idPool("va_intrinsic");
|
||||||
no_typeinfo = Lexer::idPool("no_typeinfo");
|
no_typeinfo = Lexer::idPool("no_typeinfo");
|
||||||
no_moduleinfo = Lexer::idPool("no_moduleinfo");
|
no_moduleinfo = Lexer::idPool("no_moduleinfo");
|
||||||
alloca = Lexer::idPool("alloca");
|
Alloca = Lexer::idPool("alloca");
|
||||||
va_start = Lexer::idPool("va_start");
|
vastart = Lexer::idPool("va_start");
|
||||||
va_arg = Lexer::idPool("va_arg");
|
vacopy = Lexer::idPool("va_copy");
|
||||||
|
vaend = Lexer::idPool("va_end");
|
||||||
|
vaarg = Lexer::idPool("va_arg");
|
||||||
tohash = Lexer::idPool("toHash");
|
tohash = Lexer::idPool("toHash");
|
||||||
tostring = Lexer::idPool("toString");
|
tostring = Lexer::idPool("toString");
|
||||||
main = Lexer::idPool("main");
|
main = Lexer::idPool("main");
|
||||||
|
|
8
dmd/id.h
8
dmd/id.h
|
@ -173,9 +173,11 @@ struct Id
|
||||||
static Identifier *va_intrinsic;
|
static Identifier *va_intrinsic;
|
||||||
static Identifier *no_typeinfo;
|
static Identifier *no_typeinfo;
|
||||||
static Identifier *no_moduleinfo;
|
static Identifier *no_moduleinfo;
|
||||||
static Identifier *alloca;
|
static Identifier *Alloca;
|
||||||
static Identifier *va_start;
|
static Identifier *vastart;
|
||||||
static Identifier *va_arg;
|
static Identifier *vacopy;
|
||||||
|
static Identifier *vaend;
|
||||||
|
static Identifier *vaarg;
|
||||||
static Identifier *tohash;
|
static Identifier *tohash;
|
||||||
static Identifier *tostring;
|
static Identifier *tostring;
|
||||||
static Identifier *main;
|
static Identifier *main;
|
||||||
|
|
|
@ -218,9 +218,11 @@ Msgtable msgtable[] =
|
||||||
{ "va_intrinsic" },
|
{ "va_intrinsic" },
|
||||||
{ "no_typeinfo" },
|
{ "no_typeinfo" },
|
||||||
{ "no_moduleinfo" },
|
{ "no_moduleinfo" },
|
||||||
{ "alloca" },
|
{ "Alloca", "alloca" },
|
||||||
{ "va_start" },
|
{ "vastart", "va_start" },
|
||||||
{ "va_arg" },
|
{ "vacopy", "va_copy" },
|
||||||
|
{ "vaend", "va_end" },
|
||||||
|
{ "vaarg", "va_arg" },
|
||||||
|
|
||||||
// For toHash/toString
|
// For toHash/toString
|
||||||
{ "tohash", "toHash" },
|
{ "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\
|
-debuglib=name set symbolic debug library to name\n\
|
||||||
-defaultlib=name set default library to name\n\
|
-defaultlib=name set default library to name\n\
|
||||||
-dis disassemble module after compiling\n\
|
-dis disassemble module after compiling\n\
|
||||||
-fp80 enable 80bit reals on x86 32bit (EXPERIMENTAL)\n\
|
|
||||||
-g add symbolic debug info\n\
|
-g add symbolic debug info\n\
|
||||||
-gc add symbolic debug info, pretend to be C\n\
|
-gc add symbolic debug info, pretend to be C\n\
|
||||||
-H generate 'header' file\n\
|
-H generate 'header' file\n\
|
||||||
|
@ -407,8 +406,6 @@ int main(int argc, char *argv[])
|
||||||
global.params.disassemble = 1;
|
global.params.disassemble = 1;
|
||||||
else if (strcmp(p + 1, "annotate") == 0)
|
else if (strcmp(p + 1, "annotate") == 0)
|
||||||
global.params.llvmAnnotate = 1;
|
global.params.llvmAnnotate = 1;
|
||||||
else if (strcmp(p + 1, "fp80") == 0)
|
|
||||||
global.params.useFP80 = 1;
|
|
||||||
else if (strcmp(p + 1, "noasm") == 0)
|
else if (strcmp(p + 1, "noasm") == 0)
|
||||||
global.params.useInlineAsm = 0;
|
global.params.useInlineAsm = 0;
|
||||||
else if (p[1] == 'o')
|
else if (p[1] == 'o')
|
||||||
|
@ -697,20 +694,20 @@ int main(int argc, char *argv[])
|
||||||
findDefaultTarget();
|
findDefaultTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_x86 = false;
|
|
||||||
if (strcmp(global.params.llvmArch,"x86")==0) {
|
if (strcmp(global.params.llvmArch,"x86")==0) {
|
||||||
VersionCondition::addPredefinedGlobalIdent("X86");
|
VersionCondition::addPredefinedGlobalIdent("X86");
|
||||||
//VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
|
|
||||||
global.params.isLE = true;
|
global.params.isLE = true;
|
||||||
global.params.is64bit = false;
|
global.params.is64bit = false;
|
||||||
global.params.cpu = ARCHx86;
|
global.params.cpu = ARCHx86;
|
||||||
tt_arch = "i686";
|
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";
|
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) {
|
else if (strcmp(global.params.llvmArch,"x86-64")==0) {
|
||||||
VersionCondition::addPredefinedGlobalIdent("X86_64");
|
VersionCondition::addPredefinedGlobalIdent("X86_64");
|
||||||
//VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86_64");
|
|
||||||
global.params.isLE = true;
|
global.params.isLE = true;
|
||||||
global.params.is64bit = true;
|
global.params.is64bit = true;
|
||||||
global.params.cpu = ARCHx86_64;
|
global.params.cpu = ARCHx86_64;
|
||||||
|
@ -752,18 +749,6 @@ int main(int argc, char *argv[])
|
||||||
VersionCondition::addPredefinedGlobalIdent("LLVM64");
|
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_arch != 0);
|
||||||
assert(tt_os != 0);
|
assert(tt_os != 0);
|
||||||
assert(data_layout != 0);
|
assert(data_layout != 0);
|
||||||
|
|
|
@ -135,7 +135,6 @@ struct Param
|
||||||
char llvmInline;
|
char llvmInline;
|
||||||
char llvmAnnotate;
|
char llvmAnnotate;
|
||||||
char *runtimePath;
|
char *runtimePath;
|
||||||
char useFP80;
|
|
||||||
char useInlineAsm;
|
char useInlineAsm;
|
||||||
char fqnPaths; // use fully qualified object names
|
char fqnPaths; // use fully qualified object names
|
||||||
};
|
};
|
||||||
|
|
|
@ -252,7 +252,7 @@ void Type::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
// set real size and padding
|
// set real size and padding
|
||||||
if (global.params.useFP80)
|
if (global.params.cpu == ARCHx86)
|
||||||
{
|
{
|
||||||
REALSIZE = 12;
|
REALSIZE = 12;
|
||||||
REALPAD = 2;
|
REALPAD = 2;
|
||||||
|
@ -2653,6 +2653,7 @@ TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, en
|
||||||
this->inuse = 0;
|
this->inuse = 0;
|
||||||
this->llvmRetInPtr = false;
|
this->llvmRetInPtr = false;
|
||||||
this->llvmUsesThis = false;
|
this->llvmUsesThis = false;
|
||||||
|
this->llvmRetAttrs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *TypeFunction::syntaxCopy()
|
Type *TypeFunction::syntaxCopy()
|
||||||
|
@ -2662,6 +2663,7 @@ Type *TypeFunction::syntaxCopy()
|
||||||
TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
|
TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
|
||||||
t->llvmRetInPtr = llvmRetInPtr;
|
t->llvmRetInPtr = llvmRetInPtr;
|
||||||
t->llvmUsesThis = llvmUsesThis;
|
t->llvmUsesThis = llvmUsesThis;
|
||||||
|
t->llvmRetAttrs = llvmRetAttrs;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5235,7 +5237,7 @@ Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Express
|
||||||
this->ident = ident;
|
this->ident = ident;
|
||||||
this->storageClass = storageClass;
|
this->storageClass = storageClass;
|
||||||
this->defaultArg = defaultArg;
|
this->defaultArg = defaultArg;
|
||||||
this->llvmByVal = false;
|
this->llvmAttrs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Argument *Argument::syntaxCopy()
|
Argument *Argument::syntaxCopy()
|
||||||
|
@ -5244,7 +5246,7 @@ Argument *Argument::syntaxCopy()
|
||||||
type ? type->syntaxCopy() : NULL,
|
type ? type->syntaxCopy() : NULL,
|
||||||
ident,
|
ident,
|
||||||
defaultArg ? defaultArg->syntaxCopy() : NULL);
|
defaultArg ? defaultArg->syntaxCopy() : NULL);
|
||||||
a->llvmByVal = llvmByVal;
|
a->llvmAttrs = llvmAttrs;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -443,6 +443,7 @@ struct TypeFunction : Type
|
||||||
|
|
||||||
bool llvmRetInPtr;
|
bool llvmRetInPtr;
|
||||||
bool llvmUsesThis;
|
bool llvmUsesThis;
|
||||||
|
unsigned llvmRetAttrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TypeDelegate : Type
|
struct TypeDelegate : Type
|
||||||
|
@ -701,7 +702,7 @@ struct Argument : Object
|
||||||
static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
|
static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
|
||||||
|
|
||||||
// LLVMDC
|
// LLVMDC
|
||||||
bool llvmByVal;
|
unsigned llvmAttrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int PTRSIZE;
|
extern int PTRSIZE;
|
||||||
|
|
|
@ -35,7 +35,10 @@ const LLType* DtoComplexBaseType(Type* t)
|
||||||
return LLType::DoubleTy;
|
return LLType::DoubleTy;
|
||||||
}
|
}
|
||||||
else if (ty == Tcomplex80) {
|
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 {
|
else {
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -73,7 +76,7 @@ LLConstant* DtoConstComplex(Type* _ty, long double re, long double im)
|
||||||
base = Type::tfloat64;
|
base = Type::tfloat64;
|
||||||
}
|
}
|
||||||
else if (ty == Tcomplex80) {
|
else if (ty == Tcomplex80) {
|
||||||
base = (global.params.useFP80) ? Type::tfloat80 : Type::tfloat64;
|
base = Type::tfloat80;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LLConstant*> inits;
|
std::vector<LLConstant*> inits;
|
||||||
|
@ -121,8 +124,8 @@ DValue* DtoComplex(Loc& loc, Type* to, DValue* val)
|
||||||
baserety = Type::tfloat64;
|
baserety = Type::tfloat64;
|
||||||
baseimty = Type::timaginary64;
|
baseimty = Type::timaginary64;
|
||||||
} else if (ty == Tcomplex80) {
|
} else if (ty == Tcomplex80) {
|
||||||
baserety = global.params.useFP80 ? Type::tfloat80 : Type::tfloat64;
|
baserety = Type::tfloat80;
|
||||||
baseimty = global.params.useFP80 ? Type::timaginary80 : Type::timaginary64;
|
baseimty = Type::timaginary80;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->isimaginary()) {
|
if (t->isimaginary()) {
|
||||||
|
|
|
@ -2396,10 +2396,7 @@ struct AsmProcessor
|
||||||
case TOKfloat64v:
|
case TOKfloat64v:
|
||||||
case TOKfloat80v:
|
case TOKfloat80v:
|
||||||
// %% need different types?
|
// %% need different types?
|
||||||
if (global.params.useFP80)
|
e = new RealExp(stmt->loc, token->float80value, Type::tfloat80);
|
||||||
e = new RealExp(stmt->loc, token->float80value, Type::tfloat80);
|
|
||||||
else
|
|
||||||
e = new RealExp(stmt->loc, token->float80value, Type::tfloat64);
|
|
||||||
nextToken();
|
nextToken();
|
||||||
break;
|
break;
|
||||||
case TOKidentifier:
|
case TOKidentifier:
|
||||||
|
|
|
@ -2,10 +2,11 @@ enum
|
||||||
{
|
{
|
||||||
LLVMnone,
|
LLVMnone,
|
||||||
LLVMintrinsic,
|
LLVMintrinsic,
|
||||||
LLVMva_intrinsic,
|
|
||||||
LLVMno_typeinfo,
|
LLVMno_typeinfo,
|
||||||
LLVMno_moduleinfo,
|
LLVMno_moduleinfo,
|
||||||
LLVMalloca,
|
LLVMalloca,
|
||||||
LLVMva_start,
|
LLVMva_start,
|
||||||
|
LLVMva_copy,
|
||||||
|
LLVMva_end,
|
||||||
LLVMva_arg
|
LLVMva_arg
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "gen/llvm.h"
|
#include "gen/llvm.h"
|
||||||
#include "llvm/Support/CFG.h"
|
#include "llvm/Support/CFG.h"
|
||||||
|
#include "llvm/Intrinsics.h"
|
||||||
|
|
||||||
#include "mtype.h"
|
#include "mtype.h"
|
||||||
#include "aggregate.h"
|
#include "aggregate.h"
|
||||||
|
@ -62,7 +63,6 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
assert(rt);
|
assert(rt);
|
||||||
Type* rtfin = DtoDType(rt);
|
|
||||||
if (DtoIsReturnedInArg(rt)) {
|
if (DtoIsReturnedInArg(rt)) {
|
||||||
rettype = getPtrToType(DtoType(rt));
|
rettype = getPtrToType(DtoType(rt));
|
||||||
actualRettype = LLType::VoidTy;
|
actualRettype = LLType::VoidTy;
|
||||||
|
@ -72,6 +72,11 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
||||||
rettype = DtoType(rt);
|
rettype = DtoType(rt);
|
||||||
actualRettype = rettype;
|
actualRettype = rettype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unsigned ea = DtoShouldExtend(rt))
|
||||||
|
{
|
||||||
|
f->llvmRetAttrs |= ea;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retinptr) {
|
if (retinptr) {
|
||||||
|
@ -103,8 +108,6 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
||||||
|
|
||||||
size_t n = Argument::dim(f->parameters);
|
size_t n = Argument::dim(f->parameters);
|
||||||
|
|
||||||
int nbyval = 0;
|
|
||||||
|
|
||||||
for (int i=0; i < n; ++i) {
|
for (int i=0; i < n; ++i) {
|
||||||
Argument* arg = Argument::getNth(f->parameters, i);
|
Argument* arg = Argument::getNth(f->parameters, i);
|
||||||
// ensure scalar
|
// ensure scalar
|
||||||
|
@ -117,7 +120,8 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
||||||
if (isaStruct(at)) {
|
if (isaStruct(at)) {
|
||||||
Logger::println("struct param");
|
Logger::println("struct param");
|
||||||
paramvec.push_back(getPtrToType(at));
|
paramvec.push_back(getPtrToType(at));
|
||||||
arg->llvmByVal = !refOrOut;
|
if (!refOrOut)
|
||||||
|
arg->llvmAttrs |= llvm::ParamAttr::ByVal;
|
||||||
}
|
}
|
||||||
else if (isaArray(at)) {
|
else if (isaArray(at)) {
|
||||||
// static array are passed by reference
|
// static array are passed by reference
|
||||||
|
@ -137,6 +141,10 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Logger::println("in param");
|
Logger::println("in param");
|
||||||
|
if (unsigned ea = DtoShouldExtend(argT))
|
||||||
|
{
|
||||||
|
arg->llvmAttrs |= ea;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
paramvec.push_back(at);
|
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';
|
Logger::cout() << "lazy updated to: " << *at << '\n';
|
||||||
paramvec.back() = at;
|
paramvec.back() = at;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg->llvmByVal)
|
|
||||||
nbyval++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//warning("set %d byval args for type: %s", nbyval, f->toChars());
|
//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;
|
TypeFunction* f = (TypeFunction*)fdecl->type;
|
||||||
assert(f != 0);
|
const llvm::FunctionType* fty = 0;
|
||||||
|
|
||||||
const llvm::PointerType* i8pty = getPtrToType(LLType::Int8Ty);
|
if (fdecl->llvmInternal == LLVMva_start)
|
||||||
std::vector<const LLType*> args;
|
fty = GET_INTRINSIC_DECL(vastart)->getFunctionType();
|
||||||
|
else if (fdecl->llvmInternal == LLVMva_copy)
|
||||||
if (fdecl->llvmInternal == LLVMva_start) {
|
fty = GET_INTRINSIC_DECL(vacopy)->getFunctionType();
|
||||||
args.push_back(i8pty);
|
else if (fdecl->llvmInternal == LLVMva_end)
|
||||||
}
|
fty = GET_INTRINSIC_DECL(vaend)->getFunctionType();
|
||||||
else if (fdecl->llvmInternal == LLVMva_intrinsic) {
|
assert(fty);
|
||||||
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);
|
|
||||||
|
|
||||||
f->ir.type = new llvm::PATypeHolder(fty);
|
f->ir.type = new llvm::PATypeHolder(fty);
|
||||||
|
|
||||||
return fty;
|
return fty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,14 +203,13 @@ static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
|
||||||
|
|
||||||
const llvm::FunctionType* DtoFunctionType(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);
|
return DtoVaFunctionType(fdecl);
|
||||||
}
|
|
||||||
|
|
||||||
// type has already been resolved
|
// 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());
|
return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get());
|
||||||
}
|
|
||||||
|
|
||||||
const LLType* thisty = NULL;
|
const LLType* thisty = NULL;
|
||||||
if (fdecl->needThis()) {
|
if (fdecl->needThis()) {
|
||||||
|
@ -246,22 +240,16 @@ static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
|
||||||
{
|
{
|
||||||
TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
|
TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
|
||||||
const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
|
const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
|
||||||
LLConstant* fn = 0;
|
llvm::Function* func = 0;
|
||||||
|
|
||||||
if (fdecl->llvmInternal == LLVMva_start) {
|
if (fdecl->llvmInternal == LLVMva_start)
|
||||||
fn = gIR->module->getOrInsertFunction("llvm.va_start", fty);
|
func = GET_INTRINSIC_DECL(vastart);
|
||||||
assert(fn);
|
else if (fdecl->llvmInternal == LLVMva_copy)
|
||||||
}
|
func = GET_INTRINSIC_DECL(vacopy);
|
||||||
else if (fdecl->llvmInternal == LLVMva_intrinsic) {
|
else if (fdecl->llvmInternal == LLVMva_end)
|
||||||
fn = gIR->module->getOrInsertFunction(fdecl->intrinsicName, fty);
|
func = GET_INTRINSIC_DECL(vaend);
|
||||||
assert(fn);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
assert(0);
|
|
||||||
|
|
||||||
llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn);
|
|
||||||
assert(func);
|
assert(func);
|
||||||
assert(func->isIntrinsic());
|
|
||||||
fdecl->ir.irFunc->func = func;
|
fdecl->ir.irFunc->func = func;
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
@ -330,36 +318,43 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati
|
||||||
std::vector<llvm::ParamAttrsWithIndex> attrs;
|
std::vector<llvm::ParamAttrsWithIndex> attrs;
|
||||||
int k = 0;
|
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)
|
if (fdecl->isMain() && Argument::dim(f->parameters) == 0)
|
||||||
{
|
{
|
||||||
llvm::ParamAttrsWithIndex PAWI;
|
|
||||||
PAWI.Index = llidx;
|
PAWI.Index = llidx;
|
||||||
PAWI.Attrs = llvm::ParamAttr::ByVal;
|
PAWI.Attrs = llvm::ParamAttr::ByVal;
|
||||||
attrs.push_back(PAWI);
|
attrs.push_back(PAWI);
|
||||||
llidx++;
|
llidx++;
|
||||||
nbyval++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set attrs on the rest of the arguments
|
||||||
for (; llidx <= funcNumArgs && f->parameters->dim > k; ++llidx,++k)
|
for (; llidx <= funcNumArgs && f->parameters->dim > k; ++llidx,++k)
|
||||||
{
|
{
|
||||||
Argument* fnarg = (Argument*)f->parameters->data[k];
|
Argument* fnarg = (Argument*)f->parameters->data[k];
|
||||||
assert(fnarg);
|
assert(fnarg);
|
||||||
if (fnarg->llvmByVal)
|
|
||||||
{
|
PAWI.Index = llidx;
|
||||||
llvm::ParamAttrsWithIndex PAWI;
|
PAWI.Attrs = fnarg->llvmAttrs;
|
||||||
PAWI.Index = llidx;
|
|
||||||
PAWI.Attrs = llvm::ParamAttr::ByVal;
|
if (PAWI.Attrs)
|
||||||
attrs.push_back(PAWI);
|
attrs.push_back(PAWI);
|
||||||
nbyval++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbyval) {
|
llvm::PAListPtr palist = llvm::PAListPtr::get(attrs.begin(), attrs.end());
|
||||||
llvm::PAListPtr palist = llvm::PAListPtr::get(attrs.begin(), attrs.end());
|
func->setParamAttrs(palist);
|
||||||
func->setParamAttrs(palist);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -412,9 +407,8 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||||
mangled_name = fdecl->mangle();
|
mangled_name = fdecl->mangle();
|
||||||
|
|
||||||
llvm::Function* vafunc = 0;
|
llvm::Function* vafunc = 0;
|
||||||
if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
|
if (fdecl->isVaIntrinsic())
|
||||||
vafunc = DtoDeclareVaFunction(fdecl);
|
vafunc = DtoDeclareVaFunction(fdecl);
|
||||||
}
|
|
||||||
|
|
||||||
// construct function
|
// construct function
|
||||||
const llvm::FunctionType* functype = DtoFunctionType(fdecl);
|
const llvm::FunctionType* functype = DtoFunctionType(fdecl);
|
||||||
|
@ -437,7 +431,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||||
assert(llvm::isa<llvm::FunctionType>(f->ir.type->get()));
|
assert(llvm::isa<llvm::FunctionType>(f->ir.type->get()));
|
||||||
|
|
||||||
// parameter attributes
|
// parameter attributes
|
||||||
if (f->parameters) {
|
if (f->parameters && !fdecl->isIntrinsic()) {
|
||||||
set_param_attrs(f, func, fdecl);
|
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/Function.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/Value.h"
|
#include "llvm/Value.h"
|
||||||
|
#include "llvm/ParameterAttributes.h"
|
||||||
|
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
|
|
||||||
|
@ -37,9 +38,12 @@ using llvm::IRBuilder;
|
||||||
#define LLConstantStruct llvm::ConstantStruct
|
#define LLConstantStruct llvm::ConstantStruct
|
||||||
#define LLConstantArray llvm::ConstantArray
|
#define LLConstantArray llvm::ConstantArray
|
||||||
#define LLConstantInt llvm::ConstantInt
|
#define LLConstantInt llvm::ConstantInt
|
||||||
|
#define LLConstantFP llvm::ConstantFP
|
||||||
|
|
||||||
#define LLPATypeHolder llvm::PATypeHolder
|
#define LLPATypeHolder llvm::PATypeHolder
|
||||||
|
|
||||||
#define LLSmallVector llvm::SmallVector
|
#define LLSmallVector llvm::SmallVector
|
||||||
|
|
||||||
|
#define APFloat llvm::APFloat
|
||||||
|
|
||||||
#endif // GEN_LLVM_H
|
#endif // GEN_LLVM_H
|
||||||
|
|
|
@ -779,11 +779,9 @@ DValue* DtoCastFloat(Loc& loc, DValue* val, Type* to)
|
||||||
return DtoComplex(loc, to, val);
|
return DtoComplex(loc, to, val);
|
||||||
}
|
}
|
||||||
else if (totype->isfloating()) {
|
else if (totype->isfloating()) {
|
||||||
if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) {
|
if (fromsz == tosz) {
|
||||||
rval = val->getRVal();
|
|
||||||
}
|
|
||||||
else if ((fromtype->ty == Timaginary80 || fromtype->ty == Timaginary64) && (totype->ty == Timaginary80 || totype->ty == Timaginary64)) {
|
|
||||||
rval = val->getRVal();
|
rval = val->getRVal();
|
||||||
|
assert(rval->getType() == tolltype);
|
||||||
}
|
}
|
||||||
else if (fromsz < tosz) {
|
else if (fromsz < tosz) {
|
||||||
rval = new llvm::FPExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
|
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* longTy = LLType::Int64Ty;
|
||||||
const LLType* floatTy = LLType::FloatTy;
|
const LLType* floatTy = LLType::FloatTy;
|
||||||
const LLType* doubleTy = LLType::DoubleTy;
|
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* sizeTy = DtoSize_t();
|
||||||
const LLType* voidPtrTy = rt_ptr(byteTy);
|
const LLType* voidPtrTy = rt_ptr(byteTy);
|
||||||
const LLType* stringTy = rt_array(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]);
|
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
|
||||||
args.push_back(argval->getRVal());
|
args.push_back(argval->getRVal());
|
||||||
|
|
||||||
if (fnarg->llvmByVal)
|
if (fnarg->llvmAttrs)
|
||||||
palist = palist.addAttr(argidx, llvm::ParamAttr::ByVal);
|
palist = palist.addAttr(argidx, fnarg->llvmAttrs);
|
||||||
|
|
||||||
++argidx;
|
++argidx;
|
||||||
}
|
}
|
||||||
|
@ -189,8 +189,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||||
// get func value if any
|
// get func value if any
|
||||||
DFuncValue* dfnval = fnval->isFunc();
|
DFuncValue* dfnval = fnval->isFunc();
|
||||||
|
|
||||||
// handle special va_copy / va_end intrinsics
|
// handle special vararg intrinsics
|
||||||
bool va_intrinsic = (dfnval && dfnval->func && (dfnval->func->llvmInternal == LLVMva_intrinsic));
|
bool va_intrinsic = (dfnval && dfnval->func && dfnval->func->isVaIntrinsic());
|
||||||
|
|
||||||
// get function type info
|
// get function type info
|
||||||
TypeFunction* tf = DtoTypeFunction(fnval);
|
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
|
// handle the rest of the arguments based on param passing style
|
||||||
llvm::PAListPtr palist;
|
llvm::PAListPtr palist;
|
||||||
|
|
||||||
|
if (tf->llvmRetAttrs)
|
||||||
|
palist = palist.addAttr(0, tf->llvmRetAttrs);
|
||||||
|
|
||||||
// variadic instrinsics need some custom casts
|
// variadic instrinsics need some custom casts
|
||||||
if (va_intrinsic)
|
if (va_intrinsic)
|
||||||
{
|
{
|
||||||
|
@ -293,10 +296,13 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||||
Argument* fnarg = Argument::getNth(tf->parameters, i);
|
Argument* fnarg = Argument::getNth(tf->parameters, i);
|
||||||
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
|
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
|
||||||
LLValue* arg = argval->getRVal();
|
LLValue* arg = argval->getRVal();
|
||||||
if (fnarg && arg->getType() != callableTy->getParamType(j))
|
if (fnarg)
|
||||||
arg = DtoBitCast(arg, callableTy->getParamType(j));
|
{
|
||||||
if (fnarg && fnarg->llvmByVal)
|
if (arg->getType() != callableTy->getParamType(j))
|
||||||
palist = palist.addAttr(j+1, llvm::ParamAttr::ByVal);
|
arg = DtoBitCast(arg, callableTy->getParamType(j));
|
||||||
|
if (fnarg->llvmAttrs)
|
||||||
|
palist = palist.addAttr(j+1, fnarg->llvmAttrs);
|
||||||
|
}
|
||||||
++argiter;
|
++argiter;
|
||||||
args.push_back(arg);
|
args.push_back(arg);
|
||||||
}
|
}
|
||||||
|
@ -327,21 +333,17 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||||
if (retllval->getType()->isAbstract())
|
if (retllval->getType()->isAbstract())
|
||||||
retllval = DtoBitCast(retllval, getPtrToType(DtoType(resulttype)), "retval");
|
retllval = DtoBitCast(retllval, getPtrToType(DtoType(resulttype)), "retval");
|
||||||
|
|
||||||
// set calling convention
|
// set calling convention and parameter attributes
|
||||||
if (dfnval && dfnval->func)
|
if (dfnval && dfnval->func)
|
||||||
{
|
{
|
||||||
int li = dfnval->func->llvmInternal;
|
LLFunction* llfunc = llvm::dyn_cast<LLFunction>(dfnval->val);
|
||||||
if (li != LLVMintrinsic && li != LLVMva_start && li != LLVMva_intrinsic)
|
if (llfunc && llfunc->isIntrinsic())
|
||||||
{
|
palist = llvm::Intrinsic::getParamAttrs((llvm::Intrinsic::ID)llfunc->getIntrinsicID());
|
||||||
|
else
|
||||||
call->setCallingConv(callconv);
|
call->setCallingConv(callconv);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
call->setCallingConv(callconv);
|
call->setCallingConv(callconv);
|
||||||
}
|
|
||||||
|
|
||||||
// param attrs
|
|
||||||
call->setParamAttrs(palist);
|
call->setParamAttrs(palist);
|
||||||
|
|
||||||
return new DImValue(resulttype, retllval, false);
|
return new DImValue(resulttype, retllval, false);
|
||||||
|
|
|
@ -288,8 +288,12 @@ DValue* ComplexExp::toElem(IRState* p)
|
||||||
Type* t = DtoDType(type);
|
Type* t = DtoDType(type);
|
||||||
if (t->ty == Tcomplex32)
|
if (t->ty == Tcomplex32)
|
||||||
c = DtoConstFP(Type::tfloat32, 0);
|
c = DtoConstFP(Type::tfloat32, 0);
|
||||||
else
|
else if (t->ty == Tcomplex64)
|
||||||
c = DtoConstFP(Type::tfloat64, 0);
|
c = DtoConstFP(Type::tfloat64, 0);
|
||||||
|
else if (t->ty == Tcomplex80)
|
||||||
|
c = DtoConstFP(Type::tfloat80, 0);
|
||||||
|
else
|
||||||
|
assert(0);
|
||||||
return new DComplexValue(type, c, c);
|
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());
|
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)
|
Type* DtoDType(Type* t)
|
||||||
{
|
{
|
||||||
if (t->ty == Ttypedef) {
|
if (t->ty == Ttypedef) {
|
||||||
|
@ -79,7 +98,10 @@ const LLType* DtoType(Type* t)
|
||||||
return LLType::DoubleTy;
|
return LLType::DoubleTy;
|
||||||
case Tfloat80:
|
case Tfloat80:
|
||||||
case Timaginary80:
|
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
|
// complex
|
||||||
case Tcomplex32:
|
case Tcomplex32:
|
||||||
|
@ -485,11 +507,9 @@ llvm::ConstantInt* DtoConstUbyte(unsigned char i)
|
||||||
|
|
||||||
llvm::ConstantFP* DtoConstFP(Type* t, long double value)
|
llvm::ConstantFP* DtoConstFP(Type* t, long double value)
|
||||||
{
|
{
|
||||||
TY ty = DtoDType(t)->ty;
|
const LLType* llty = DtoType(t);
|
||||||
if (ty == Tfloat32 || ty == Timaginary32)
|
assert(llty->isFloatingPoint());
|
||||||
return llvm::ConstantFP::get(llvm::APFloat(float(value)));
|
return LLConstantFP::get(llty, value);
|
||||||
else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tfloat80 || ty == Timaginary80)
|
|
||||||
return llvm::ConstantFP::get(llvm::APFloat(double(value)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -21,6 +21,8 @@ bool DtoIsPassedByRef(Type* type);
|
||||||
// returns if the type should be returned in a hidden pointer arguement
|
// returns if the type should be returned in a hidden pointer arguement
|
||||||
bool DtoIsReturnedInArg(Type* type);
|
bool DtoIsReturnedInArg(Type* type);
|
||||||
|
|
||||||
|
unsigned DtoShouldExtend(Type* type);
|
||||||
|
|
||||||
// resolve typedefs to their real type.
|
// resolve typedefs to their real type.
|
||||||
// TODO should probably be removed in favor of DMD's Type::toBasetype
|
// TODO should probably be removed in favor of DMD's Type::toBasetype
|
||||||
Type* DtoDType(Type* t);
|
Type* DtoDType(Type* t);
|
||||||
|
|
|
@ -22,8 +22,8 @@ pragma(va_start)
|
||||||
pragma(va_arg)
|
pragma(va_arg)
|
||||||
T va_arg(T)(va_list ap);
|
T va_arg(T)(va_list ap);
|
||||||
|
|
||||||
pragma(va_intrinsic, "llvm.va_end")
|
pragma(va_end)
|
||||||
void va_end(va_list args);
|
void va_end(va_list args);
|
||||||
|
|
||||||
pragma(va_intrinsic, "llvm.va_copy")
|
pragma(va_copy)
|
||||||
void va_copy(va_list dst, va_list src);
|
void va_copy(va_list dst, va_list src);
|
||||||
|
|
|
@ -106,7 +106,7 @@ pragma(intrinsic, "llvm.sqrt.f32")
|
||||||
float llvm_sqrt_f32(float val);
|
float llvm_sqrt_f32(float val);
|
||||||
pragma(intrinsic, "llvm.sqrt.f64")
|
pragma(intrinsic, "llvm.sqrt.f64")
|
||||||
double llvm_sqrt_f64(double val);
|
double llvm_sqrt_f64(double val);
|
||||||
version(LLVM_X86_FP80)
|
version(X86)
|
||||||
{
|
{
|
||||||
pragma(intrinsic, "llvm.sqrt.f80")
|
pragma(intrinsic, "llvm.sqrt.f80")
|
||||||
real llvm_sqrt_f80(real val);
|
real llvm_sqrt_f80(real val);
|
||||||
|
@ -119,7 +119,7 @@ pragma(intrinsic, "llvm.sin.f32")
|
||||||
float llvm_sin_f32(float val);
|
float llvm_sin_f32(float val);
|
||||||
pragma(intrinsic, "llvm.sin.f64")
|
pragma(intrinsic, "llvm.sin.f64")
|
||||||
double llvm_sin_f64(double val);
|
double llvm_sin_f64(double val);
|
||||||
version(LLVM_X86_FP80)
|
version(X86)
|
||||||
{
|
{
|
||||||
pragma(intrinsic, "llvm.sin.f80")
|
pragma(intrinsic, "llvm.sin.f80")
|
||||||
real llvm_sin_f80(real val);
|
real llvm_sin_f80(real val);
|
||||||
|
@ -132,7 +132,7 @@ pragma(intrinsic, "llvm.cos.f32")
|
||||||
float llvm_cos_f32(float val);
|
float llvm_cos_f32(float val);
|
||||||
pragma(intrinsic, "llvm.cos.f64")
|
pragma(intrinsic, "llvm.cos.f64")
|
||||||
double llvm_cos_f64(double val);
|
double llvm_cos_f64(double val);
|
||||||
version(LLVM_X86_FP80)
|
version(X86)
|
||||||
{
|
{
|
||||||
pragma(intrinsic, "llvm.cos.f80")
|
pragma(intrinsic, "llvm.cos.f80")
|
||||||
real llvm_cos_f80(real val);
|
real llvm_cos_f80(real val);
|
||||||
|
@ -146,7 +146,7 @@ pragma(intrinsic, "llvm.powi.f32")
|
||||||
|
|
||||||
pragma(intrinsic, "llvm.powi.f64")
|
pragma(intrinsic, "llvm.powi.f64")
|
||||||
double llvm_powi_f64(double val, int power);
|
double llvm_powi_f64(double val, int power);
|
||||||
version(LLVM_X86_FP80)
|
version(X86)
|
||||||
{
|
{
|
||||||
pragma(intrinsic, "llvm.powi.f80")
|
pragma(intrinsic, "llvm.powi.f80")
|
||||||
real llvm_powi_f80(real val, int power);
|
real llvm_powi_f80(real val, int power);
|
||||||
|
@ -160,7 +160,7 @@ pragma(intrinsic, "llvm.pow.f32")
|
||||||
|
|
||||||
pragma(intrinsic, "llvm.pow.f64")
|
pragma(intrinsic, "llvm.pow.f64")
|
||||||
double llvm_pow_f64(double val, double power);
|
double llvm_pow_f64(double val, double power);
|
||||||
version(LLVM_X86_FP80)
|
version(X86)
|
||||||
{
|
{
|
||||||
pragma(intrinsic, "llvm.pow.f80")
|
pragma(intrinsic, "llvm.pow.f80")
|
||||||
real llvm_pow_f80(real val, real power);
|
real llvm_pow_f80(real val, real power);
|
||||||
|
|
|
@ -29,7 +29,6 @@ testversion=D_InlineAsm_PPC64
|
||||||
testversion=LittleEndian
|
testversion=LittleEndian
|
||||||
testversion=BigEndian
|
testversion=BigEndian
|
||||||
testversion=LLVM64
|
testversion=LLVM64
|
||||||
textversion=LLVM_X86_FP80
|
|
||||||
|
|
||||||
|
|
||||||
[compile]
|
[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/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</path>
|
||||||
<path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/gdc/monitor.c</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>
|
</blacklist>
|
||||||
<build>
|
<build>
|
||||||
<buildtool>make</buildtool>
|
<buildtool>make</buildtool>
|
||||||
|
|
|
@ -209,96 +209,47 @@ Index: tango/math/Math.d
|
||||||
===================================================================
|
===================================================================
|
||||||
--- tango/math/Math.d (revision 3831)
|
--- tango/math/Math.d (revision 3831)
|
||||||
+++ tango/math/Math.d (working copy)
|
+++ tango/math/Math.d (working copy)
|
||||||
@@ -76,7 +76,77 @@
|
@@ -76,6 +76,14 @@
|
||||||
version = DigitalMars_D_InlineAsm_X86;
|
version = DigitalMars_D_InlineAsm_X86;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+else version(LLVMDC)
|
+else version(LLVMDC)
|
||||||
+{
|
+{
|
||||||
+ private
|
+ import llvmdc.intrinsics;
|
||||||
|
+ version(X86)
|
||||||
+ {
|
+ {
|
||||||
|
+ version = LLVMDC_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);
|
|
||||||
+ }
|
|
||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
+
|
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
@@ -298,6 +306,24 @@
|
||||||
@@ -298,6 +368,10 @@
|
|
||||||
* Bugs:
|
* Bugs:
|
||||||
* Results are undefined if |x| >= $(POWER 2,64).
|
* Results are undefined if |x| >= $(POWER 2,64).
|
||||||
*/
|
*/
|
||||||
+version(LLVMDC)
|
+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
|
+else
|
||||||
+{
|
+{
|
||||||
real cos(real x) /* intrinsic */
|
real cos(real x) /* intrinsic */
|
||||||
{
|
{
|
||||||
version(D_InlineAsm_X86)
|
version(D_InlineAsm_X86)
|
||||||
@@ -313,6 +387,7 @@
|
@@ -313,6 +339,7 @@
|
||||||
return tango.stdc.math.cosl(x);
|
return tango.stdc.math.cosl(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,18 +257,32 @@ Index: tango/math/Math.d
|
||||||
|
|
||||||
debug(UnitTest) {
|
debug(UnitTest) {
|
||||||
unittest {
|
unittest {
|
||||||
@@ -333,6 +408,10 @@
|
@@ -333,6 +360,24 @@
|
||||||
* Bugs:
|
* Bugs:
|
||||||
* Results are undefined if |x| >= $(POWER 2,64).
|
* Results are undefined if |x| >= $(POWER 2,64).
|
||||||
*/
|
*/
|
||||||
+version(LLVMDC)
|
+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
|
+else
|
||||||
+{
|
+{
|
||||||
real sin(real x) /* intrinsic */
|
real sin(real x) /* intrinsic */
|
||||||
{
|
{
|
||||||
version(D_InlineAsm_X86)
|
version(D_InlineAsm_X86)
|
||||||
@@ -348,6 +427,7 @@
|
@@ -348,6 +393,7 @@
|
||||||
return tango.stdc.math.sinl(x);
|
return tango.stdc.math.sinl(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,283 +290,62 @@ Index: tango/math/Math.d
|
||||||
|
|
||||||
debug(UnitTest) {
|
debug(UnitTest) {
|
||||||
unittest {
|
unittest {
|
||||||
@@ -374,6 +454,9 @@
|
@@ -374,7 +420,11 @@
|
||||||
{
|
{
|
||||||
version (GNU) {
|
version (GNU) {
|
||||||
return tanl(x);
|
return tanl(x);
|
||||||
|
- } else {
|
||||||
+ }
|
+ }
|
||||||
+ else version(LLVMDC) {
|
+ else version(LLVMDC) {
|
||||||
+ return llvm_tan(x);
|
+ return tango.stdc.math.tanl(x);
|
||||||
} else {
|
+ }
|
||||||
|
+ else {
|
||||||
asm
|
asm
|
||||||
{
|
{
|
||||||
@@ -576,7 +659,14 @@
|
fld x[EBP] ; // load theta
|
||||||
*/
|
@@ -947,6 +997,25 @@
|
||||||
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 @@
|
|
||||||
* <tr> <td> +∞ <td> +∞ <td> no
|
* <tr> <td> +∞ <td> +∞ <td> no
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
+version(LLVMDC)
|
+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
|
+else
|
||||||
+{
|
+{
|
||||||
|
+
|
||||||
float sqrt(float x) /* intrinsic */
|
float sqrt(float x) /* intrinsic */
|
||||||
{
|
{
|
||||||
version(D_InlineAsm_X86)
|
version(D_InlineAsm_X86)
|
||||||
@@ -994,6 +1130,7 @@
|
@@ -995,6 +1064,8 @@
|
||||||
return tango.stdc.math.sqrtl(x);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+}
|
|
||||||
|
|
||||||
|
+}
|
||||||
|
+
|
||||||
/** ditto */
|
/** ditto */
|
||||||
creal sqrt(creal z)
|
creal sqrt(creal z)
|
||||||
@@ -1045,7 +1182,14 @@
|
|
||||||
*/
|
|
||||||
real cbrt(real x)
|
|
||||||
{
|
{
|
||||||
- return tango.stdc.math.cbrtl(x);
|
@@ -1477,7 +1548,14 @@
|
||||||
+ 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 @@
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
- return tango.stdc.math.powl(x, y);
|
- return tango.stdc.math.powl(x, y);
|
||||||
+ version(LLVMDC)
|
+ version(LLVMDC_X86)
|
||||||
+ {
|
+ {
|
||||||
+ return llvm_pow(x, y);
|
+ return llvm_pow_f80(x, y);
|
||||||
+ }
|
+ }
|
||||||
+ else
|
+ else
|
||||||
+ {
|
+ {
|
||||||
|
@ -610,28 +354,6 @@ Index: tango/math/Math.d
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(UnitTest) {
|
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
|
Index: tango/stdc/stdlib.d
|
||||||
===================================================================
|
===================================================================
|
||||||
--- tango/stdc/stdlib.d (revision 3831)
|
--- tango/stdc/stdlib.d (revision 3831)
|
||||||
|
|
|
@ -23,7 +23,7 @@ void main()
|
||||||
printf("Enter real: ");
|
printf("Enter real: ");
|
||||||
//scanf("%lf", &d);
|
//scanf("%lf", &d);
|
||||||
r = 3.2311167891231231234754764576;
|
r = 3.2311167891231231234754764576;
|
||||||
version(LLVM_X86_FP80)
|
version(X86)
|
||||||
{
|
{
|
||||||
real sr = llvm_sqrt_f80(r);
|
real sr = llvm_sqrt_f80(r);
|
||||||
printf("sqrt(%llf) = %llf\n", r, sr);
|
printf("sqrt(%llf) = %llf\n", r, sr);
|
||||||
|
@ -31,6 +31,6 @@ void main()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
real sr = llvm_sqrt_f64(r);
|
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][1].length == 3);
|
||||||
assert(ma[1][2].length == 3);
|
assert(ma[1][2].length == 3);
|
||||||
assert(ma[1][3].length == 3);
|
assert(ma[1][3].length == 3);
|
||||||
ma[0][3][1] = 32;
|
ma[0][3][0] = 32;
|
||||||
ma[1][2][2] = 123;
|
ma[1][2][1] = 123;
|
||||||
ma[0][0][3] = 55;
|
ma[0][0][2] = 55;
|
||||||
assert(ma[0][3][1] == 32);
|
assert(ma[0][3][0] == 32);
|
||||||
assert(ma[1][2][2] == 123);
|
assert(ma[1][2][1] == 123);
|
||||||
assert(ma[0][0][3] == 55);
|
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);
|
printf("%f", *cast(float*)arg);
|
||||||
else if (ti == typeid(double))
|
else if (ti == typeid(double))
|
||||||
printf("%f", *cast(double*)arg);
|
printf("%f", *cast(double*)arg);
|
||||||
else if (ti == typeid(real)) // FIXME: 80bit?
|
else if (ti == typeid(real))
|
||||||
{
|
printf("%llf", *cast(real*)arg);
|
||||||
version(LLVM_X86_FP80)
|
|
||||||
printf("%llf", *cast(real*)arg);
|
|
||||||
else
|
|
||||||
printf("%f", *cast(real*)arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (ti == typeid(char))
|
else if (ti == typeid(char))
|
||||||
printf("%.*s", 1, arg);
|
printf("%.*s", 1, arg);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue