mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 10:57:35 +03:00
[svn r233] Added: -oq command line option for writing fully qualified object names.
Added: started support for x86 80bit floating point. Changed: aggregates passed by value now use the llvm 'byval' parameter attribute, also lays ground work for using other attributes. Changed: eliminated a lot more std::vectorS, these showed up pretty much at the top when profiling! Changed: performed other misc. cleanups. Changed: halt expression now call the new llvm trap intrinsic instead of an assert(0). Changed: dstress suite now passes -O0 by default, this only eliminates unreferenced globals, which speeds up linking quite a bit.
This commit is contained in:
parent
1a41b9ef12
commit
d03c3a7757
23 changed files with 299 additions and 187 deletions
20
dmd/mars.c
20
dmd/mars.c
|
@ -202,6 +202,7 @@ Usage:\n\
|
||||||
-od<objdir> write object files to directory <objdir>\n\
|
-od<objdir> write object files to directory <objdir>\n\
|
||||||
-of<filename> name output file to <filename>\n\
|
-of<filename> name output file to <filename>\n\
|
||||||
-op do not strip paths from source file\n\
|
-op do not strip paths from source file\n\
|
||||||
|
-oq write object files with fully qualified names\n\
|
||||||
-profile profile runtime performance of generated code\n\
|
-profile profile runtime performance of generated code\n\
|
||||||
-quiet suppress unnecessary messages\n\
|
-quiet suppress unnecessary messages\n\
|
||||||
-release compile release version\n\
|
-release compile release version\n\
|
||||||
|
@ -214,6 +215,7 @@ Usage:\n\
|
||||||
-version=level compile in version code >= level\n\
|
-version=level compile in version code >= level\n\
|
||||||
-version=ident compile in version code identified by ident\n\
|
-version=ident compile in version code identified by ident\n\
|
||||||
-w enable warnings\n\
|
-w enable warnings\n\
|
||||||
|
-fp80 enable 80bit reals on x86 32bit (EXPERIMENTAL)\n\
|
||||||
",
|
",
|
||||||
#if WIN32
|
#if WIN32
|
||||||
" @cmdfile read arguments from cmdfile\n"
|
" @cmdfile read arguments from cmdfile\n"
|
||||||
|
@ -397,6 +399,8 @@ 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 (p[1] == 'o')
|
else if (p[1] == 'o')
|
||||||
{
|
{
|
||||||
switch (p[2])
|
switch (p[2])
|
||||||
|
@ -423,6 +427,12 @@ int main(int argc, char *argv[])
|
||||||
global.params.preservePaths = 1;
|
global.params.preservePaths = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
if (p[3])
|
||||||
|
goto Lerror;
|
||||||
|
global.params.fqnPaths = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
error("-o no longer supported, use -of or -od");
|
error("-o no longer supported, use -of or -od");
|
||||||
break;
|
break;
|
||||||
|
@ -691,6 +701,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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");
|
//VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
|
||||||
|
@ -698,6 +709,7 @@ int main(int argc, char *argv[])
|
||||||
global.params.is64bit = false;
|
global.params.is64bit = false;
|
||||||
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-v64:64:64-v128:128:128-a0:0:8";
|
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-v64:64:64-v128:128:128-a0:0:8";
|
||||||
|
is_x86 = true;
|
||||||
}
|
}
|
||||||
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");
|
||||||
|
@ -740,6 +752,14 @@ 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");
|
||||||
|
}
|
||||||
|
|
||||||
assert(tt_arch != 0);
|
assert(tt_arch != 0);
|
||||||
assert(tt_os != 0);
|
assert(tt_os != 0);
|
||||||
assert(data_layout != 0);
|
assert(data_layout != 0);
|
||||||
|
|
|
@ -133,6 +133,8 @@ struct Param
|
||||||
char llvmInline;
|
char llvmInline;
|
||||||
char llvmAnnotate;
|
char llvmAnnotate;
|
||||||
char *runtimePath;
|
char *runtimePath;
|
||||||
|
char useFP80;
|
||||||
|
char fqnPaths; // use fully qualified object names
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Global
|
struct Global
|
||||||
|
|
|
@ -2538,7 +2538,9 @@ Type *TypeFunction::syntaxCopy()
|
||||||
{
|
{
|
||||||
Type *treturn = next ? next->syntaxCopy() : NULL;
|
Type *treturn = next ? next->syntaxCopy() : NULL;
|
||||||
Arguments *params = Argument::arraySyntaxCopy(parameters);
|
Arguments *params = Argument::arraySyntaxCopy(parameters);
|
||||||
Type *t = new TypeFunction(params, treturn, varargs, linkage);
|
TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
|
||||||
|
t->llvmRetInPtr = llvmRetInPtr;
|
||||||
|
t->llvmUsesThis = llvmUsesThis;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5062,6 +5064,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
Argument *Argument::syntaxCopy()
|
Argument *Argument::syntaxCopy()
|
||||||
|
@ -5070,6 +5073,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;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -681,6 +681,9 @@ struct Argument : Object
|
||||||
static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments);
|
static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments);
|
||||||
static size_t dim(Arguments *arguments);
|
static size_t dim(Arguments *arguments);
|
||||||
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
|
||||||
|
bool llvmByVal;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int PTRSIZE;
|
extern int PTRSIZE;
|
||||||
|
|
17
gen/aa.cpp
17
gen/aa.cpp
|
@ -86,15 +86,8 @@ DValue* DtoAAIndex(Type* type, DValue* aa, DValue* key)
|
||||||
LLValue* pkey = to_pkey(key);
|
LLValue* pkey = to_pkey(key);
|
||||||
pkey = DtoBitCast(pkey, funcTy->getParamType(3));
|
pkey = DtoBitCast(pkey, funcTy->getParamType(3));
|
||||||
|
|
||||||
// build arg vector
|
|
||||||
LLSmallVector<LLValue*, 4> args;
|
|
||||||
args.push_back(aaval);
|
|
||||||
args.push_back(keyti);
|
|
||||||
args.push_back(valsize);
|
|
||||||
args.push_back(pkey);
|
|
||||||
|
|
||||||
// call runtime
|
// call runtime
|
||||||
LLValue* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "aa.index");
|
LLValue* ret = gIR->ir->CreateCall4(func, aaval, keyti, valsize, pkey, "aa.index");
|
||||||
|
|
||||||
// cast return value
|
// cast return value
|
||||||
const LLType* targettype = getPtrToType(DtoType(type));
|
const LLType* targettype = getPtrToType(DtoType(type));
|
||||||
|
@ -131,14 +124,8 @@ DValue* DtoAAIn(Type* type, DValue* aa, DValue* key)
|
||||||
LLValue* pkey = to_pkey(key);
|
LLValue* pkey = to_pkey(key);
|
||||||
pkey = DtoBitCast(pkey, funcTy->getParamType(2));
|
pkey = DtoBitCast(pkey, funcTy->getParamType(2));
|
||||||
|
|
||||||
// build arg vector
|
|
||||||
LLSmallVector<LLValue*, 3> args;
|
|
||||||
args.push_back(aaval);
|
|
||||||
args.push_back(keyti);
|
|
||||||
args.push_back(pkey);
|
|
||||||
|
|
||||||
// call runtime
|
// call runtime
|
||||||
LLValue* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "aa.in");
|
LLValue* ret = gIR->ir->CreateCall3(func, aaval, keyti, pkey, "aa.in");
|
||||||
|
|
||||||
// cast return value
|
// cast return value
|
||||||
const LLType* targettype = DtoType(type);
|
const LLType* targettype = DtoType(type);
|
||||||
|
|
|
@ -184,7 +184,7 @@ void DtoArrayInit(LLValue* ptr, LLValue* dim, LLValue* val)
|
||||||
|
|
||||||
Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n';
|
Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n';
|
||||||
|
|
||||||
std::vector<LLValue*> args;
|
LLSmallVector<LLValue*, 4> args;
|
||||||
args.push_back(ptr);
|
args.push_back(ptr);
|
||||||
args.push_back(dim);
|
args.push_back(dim);
|
||||||
args.push_back(val);
|
args.push_back(val);
|
||||||
|
@ -424,12 +424,11 @@ void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
|
||||||
LLValue* srcarr = DtoBitCast(get_slice_ptr(src,sz2),arrty);
|
LLValue* srcarr = DtoBitCast(get_slice_ptr(src,sz2),arrty);
|
||||||
|
|
||||||
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
||||||
std::vector<LLValue*> llargs;
|
LLSmallVector<LLValue*, 4> llargs(4);
|
||||||
llargs.resize(4);
|
|
||||||
llargs[0] = dstarr;
|
llargs[0] = dstarr;
|
||||||
llargs[1] = srcarr;
|
llargs[1] = srcarr;
|
||||||
llargs[2] = sz1;
|
llargs[2] = sz1;
|
||||||
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
llargs[3] = DtoConstInt(0);
|
||||||
|
|
||||||
llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
||||||
}
|
}
|
||||||
|
@ -444,12 +443,11 @@ void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
|
||||||
LLValue* srcarr = DtoBitCast(DtoArrayPtr(src),arrty);
|
LLValue* srcarr = DtoBitCast(DtoArrayPtr(src),arrty);
|
||||||
|
|
||||||
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
||||||
std::vector<LLValue*> llargs;
|
LLSmallVector<LLValue*, 4> llargs(4);
|
||||||
llargs.resize(4);
|
|
||||||
llargs[0] = dstarr;
|
llargs[0] = dstarr;
|
||||||
llargs[1] = srcarr;
|
llargs[1] = srcarr;
|
||||||
llargs[2] = sz1;
|
llargs[2] = sz1;
|
||||||
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
llargs[3] = DtoConstInt(0);
|
||||||
|
|
||||||
llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
||||||
}
|
}
|
||||||
|
@ -467,12 +465,11 @@ void DtoStaticArrayCopy(LLValue* dst, LLValue* src)
|
||||||
LLValue* srcarr = DtoBitCast(src,arrty);
|
LLValue* srcarr = DtoBitCast(src,arrty);
|
||||||
|
|
||||||
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
||||||
std::vector<LLValue*> llargs;
|
LLSmallVector<LLValue*,4> llargs(4);
|
||||||
llargs.resize(4);
|
|
||||||
llargs[0] = dstarr;
|
llargs[0] = dstarr;
|
||||||
llargs[1] = srcarr;
|
llargs[1] = srcarr;
|
||||||
llargs[2] = n;
|
llargs[2] = n;
|
||||||
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
llargs[3] = DtoConstInt(0);
|
||||||
|
|
||||||
llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
||||||
}
|
}
|
||||||
|
@ -480,14 +477,8 @@ void DtoStaticArrayCopy(LLValue* dst, LLValue* src)
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr)
|
LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr)
|
||||||
{
|
{
|
||||||
std::vector<const LLType*> types;
|
LLConstant* values[2] = { dim, ptr };
|
||||||
types.push_back(dim->getType());
|
return llvm::ConstantStruct::get(values, 2);
|
||||||
types.push_back(ptr->getType());
|
|
||||||
const llvm::StructType* type = llvm::StructType::get(types);
|
|
||||||
std::vector<LLConstant*> values;
|
|
||||||
values.push_back(dim);
|
|
||||||
values.push_back(ptr);
|
|
||||||
return llvm::ConstantStruct::get(type,values);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -496,15 +487,21 @@ DSliceValue* DtoNewDynArray(Type* arrayType, DValue* dim, bool defaultInit)
|
||||||
Logger::println("DtoNewDynArray : %s", arrayType->toChars());
|
Logger::println("DtoNewDynArray : %s", arrayType->toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
// typeinfo arg
|
||||||
|
LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType);
|
||||||
|
|
||||||
|
// dim arg
|
||||||
|
assert(DtoType(dim->getType()) == DtoSize_t());
|
||||||
|
LLValue* arrayLen = dim->getRVal();
|
||||||
|
|
||||||
|
// get runtime function
|
||||||
bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
|
bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
|
||||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_newarrayT" : "_d_newarrayiT" );
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_newarrayT" : "_d_newarrayiT" );
|
||||||
|
|
||||||
LLSmallVector<LLValue*,2> args;
|
// call allocator
|
||||||
args.push_back(DtoTypeInfoOf(arrayType));
|
LLValue* newptr = gIR->ir->CreateCall2(fn, arrayTypeInfo, arrayLen, ".gc_mem");
|
||||||
assert(DtoType(dim->getType()) == DtoSize_t());
|
|
||||||
args.push_back(dim->getRVal());
|
|
||||||
|
|
||||||
LLValue* newptr = gIR->ir->CreateCall(fn, args.begin(), args.end(), ".gc_mem");
|
// cast to wanted type
|
||||||
const LLType* dstType = DtoType(arrayType)->getContainedType(1);
|
const LLType* dstType = DtoType(arrayType)->getContainedType(1);
|
||||||
if (newptr->getType() != dstType)
|
if (newptr->getType() != dstType)
|
||||||
newptr = DtoBitCast(newptr, dstType, ".gc_mem");
|
newptr = DtoBitCast(newptr, dstType, ".gc_mem");
|
||||||
|
@ -518,7 +515,7 @@ DSliceValue* DtoNewDynArray(Type* arrayType, DValue* dim, bool defaultInit)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return new DSliceValue(arrayType, args[1], newptr);
|
return new DSliceValue(arrayType, arrayLen, newptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -542,6 +539,7 @@ DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim)
|
||||||
args.push_back(DtoTypeInfoOf(arrayType));
|
args.push_back(DtoTypeInfoOf(arrayType));
|
||||||
args.push_back(newdim->getRVal());
|
args.push_back(newdim->getRVal());
|
||||||
args.push_back(DtoArrayLen(array));
|
args.push_back(DtoArrayLen(array));
|
||||||
|
|
||||||
LLValue* arrPtr = DtoArrayPtr(array);
|
LLValue* arrPtr = DtoArrayPtr(array);
|
||||||
Logger::cout() << "arrPtr = " << *arrPtr << '\n';
|
Logger::cout() << "arrPtr = " << *arrPtr << '\n';
|
||||||
args.push_back(DtoBitCast(arrPtr, fn->getFunctionType()->getParamType(3), "tmp"));
|
args.push_back(DtoBitCast(arrPtr, fn->getFunctionType()->getParamType(3), "tmp"));
|
||||||
|
@ -734,7 +732,7 @@ static LLValue* DtoArrayEqCmp_impl(const char* func, DValue* l, DValue* r, bool
|
||||||
Type* r_ty = DtoDType(r->getType());
|
Type* r_ty = DtoDType(r->getType());
|
||||||
assert(l_ty->next == r_ty->next);
|
assert(l_ty->next == r_ty->next);
|
||||||
if ((l_ty->ty == Tsarray) || (r_ty->ty == Tsarray)) {
|
if ((l_ty->ty == Tsarray) || (r_ty->ty == Tsarray)) {
|
||||||
Type* a_ty = new Type(Tarray, l_ty->next);
|
Type* a_ty = l_ty->next->arrayOf();
|
||||||
if (l_ty->ty == Tsarray)
|
if (l_ty->ty == Tsarray)
|
||||||
l = DtoCastArray(l, a_ty);
|
l = DtoCastArray(l, a_ty);
|
||||||
if (r_ty->ty == Tsarray)
|
if (r_ty->ty == Tsarray)
|
||||||
|
@ -774,7 +772,7 @@ static LLValue* DtoArrayEqCmp_impl(const char* func, DValue* l, DValue* r, bool
|
||||||
|
|
||||||
const LLType* pt = fn->getFunctionType()->getParamType(0);
|
const LLType* pt = fn->getFunctionType()->getParamType(0);
|
||||||
|
|
||||||
std::vector<LLValue*> args;
|
LLSmallVector<LLValue*, 3> args;
|
||||||
Logger::cout() << "bitcasting to " << *pt << '\n';
|
Logger::cout() << "bitcasting to " << *pt << '\n';
|
||||||
Logger::cout() << *lmem << '\n';
|
Logger::cout() << *lmem << '\n';
|
||||||
Logger::cout() << *rmem << '\n';
|
Logger::cout() << *rmem << '\n';
|
||||||
|
@ -799,9 +797,6 @@ static LLValue* DtoArrayEqCmp_impl(const char* func, DValue* l, DValue* r, bool
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
LLValue* DtoArrayEquals(TOK op, DValue* l, DValue* r)
|
LLValue* DtoArrayEquals(TOK op, DValue* l, DValue* r)
|
||||||
{
|
{
|
||||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_adEq");
|
|
||||||
assert(fn);
|
|
||||||
|
|
||||||
LLValue* res = DtoArrayEqCmp_impl("_adEq", l, r, true);
|
LLValue* res = DtoArrayEqCmp_impl("_adEq", l, r, true);
|
||||||
if (op == TOKnotequal)
|
if (op == TOKnotequal)
|
||||||
res = gIR->ir->CreateNot(res, "tmp");
|
res = gIR->ir->CreateNot(res, "tmp");
|
||||||
|
@ -883,7 +878,7 @@ LLValue* DtoArrayCastLength(LLValue* len, const LLType* elemty, const LLType* ne
|
||||||
if (esz == nsz)
|
if (esz == nsz)
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
std::vector<LLValue*> args;
|
LLSmallVector<LLValue*, 3> args;
|
||||||
args.push_back(len);
|
args.push_back(len);
|
||||||
args.push_back(llvm::ConstantInt::get(DtoSize_t(), esz, false));
|
args.push_back(llvm::ConstantInt::get(DtoSize_t(), esz, false));
|
||||||
args.push_back(llvm::ConstantInt::get(DtoSize_t(), nsz, false));
|
args.push_back(llvm::ConstantInt::get(DtoSize_t(), nsz, false));
|
||||||
|
|
|
@ -796,9 +796,7 @@ DValue* DtoNewClass(TypeClass* tc, NewExp* newexp)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_newclass");
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_newclass");
|
||||||
std::vector<LLValue*> args;
|
mem = gIR->ir->CreateCall(fn, tc->sym->ir.irStruct->classInfo, "newclass_gc_alloc");
|
||||||
args.push_back(tc->sym->ir.irStruct->classInfo);
|
|
||||||
mem = gIR->ir->CreateCall(fn, args.begin(), args.end(), "newclass_gc_alloc");
|
|
||||||
mem = DtoBitCast(mem, DtoType(tc), "newclass_gc");
|
mem = DtoBitCast(mem, DtoType(tc), "newclass_gc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,6 +896,8 @@ DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* argument
|
||||||
llvm::Function* fn = ctor->ir.irFunc->func;
|
llvm::Function* fn = ctor->ir.irFunc->func;
|
||||||
TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type);
|
TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type);
|
||||||
|
|
||||||
|
llvm::PAListPtr palist;
|
||||||
|
|
||||||
std::vector<LLValue*> ctorargs;
|
std::vector<LLValue*> ctorargs;
|
||||||
ctorargs.push_back(mem);
|
ctorargs.push_back(mem);
|
||||||
for (size_t i=0; i<arguments->dim; ++i)
|
for (size_t i=0; i<arguments->dim; ++i)
|
||||||
|
@ -910,9 +910,12 @@ DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* argument
|
||||||
if (a->getType() != aty)
|
if (a->getType() != aty)
|
||||||
a = DtoBitCast(a, aty);
|
a = DtoBitCast(a, aty);
|
||||||
ctorargs.push_back(a);
|
ctorargs.push_back(a);
|
||||||
|
if (fnarg && fnarg->llvmByVal)
|
||||||
|
palist = palist.addAttr(i+2, llvm::ParamAttr::ByVal); // return,this is 2
|
||||||
}
|
}
|
||||||
llvm::CallInst* call = llvm::CallInst::Create(fn, ctorargs.begin(), ctorargs.end(), "tmp", gIR->scopebb());
|
llvm::CallInst* call = llvm::CallInst::Create(fn, ctorargs.begin(), ctorargs.end(), "tmp", gIR->scopebb());
|
||||||
call->setCallingConv(DtoCallingConv(LINKd));
|
call->setCallingConv(DtoCallingConv(LINKd));
|
||||||
|
call->setParamAttrs(palist);
|
||||||
|
|
||||||
return new DImValue(type, call, false);
|
return new DImValue(type, call, false);
|
||||||
}
|
}
|
||||||
|
@ -997,24 +1000,22 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to)
|
||||||
std::vector<LLValue*> args;
|
std::vector<LLValue*> args;
|
||||||
|
|
||||||
// Object o
|
// Object o
|
||||||
LLValue* tmp = val->getRVal();
|
LLValue* obj = val->getRVal();
|
||||||
tmp = DtoBitCast(tmp, funcTy->getParamType(0));
|
obj = DtoBitCast(obj, funcTy->getParamType(0));
|
||||||
args.push_back(tmp);
|
assert(funcTy->getParamType(0) == obj->getType());
|
||||||
assert(funcTy->getParamType(0) == tmp->getType());
|
|
||||||
|
|
||||||
// ClassInfo c
|
// ClassInfo c
|
||||||
TypeClass* to = (TypeClass*)DtoDType(_to);
|
TypeClass* to = (TypeClass*)DtoDType(_to);
|
||||||
DtoForceDeclareDsymbol(to->sym);
|
DtoForceDeclareDsymbol(to->sym);
|
||||||
assert(to->sym->ir.irStruct->classInfo);
|
assert(to->sym->ir.irStruct->classInfo);
|
||||||
tmp = to->sym->ir.irStruct->classInfo;
|
LLValue* cinfo = to->sym->ir.irStruct->classInfo;
|
||||||
// unfortunately this is needed as the implementation of object differs somehow from the declaration
|
// unfortunately this is needed as the implementation of object differs somehow from the declaration
|
||||||
// this could happen in user code as well :/
|
// this could happen in user code as well :/
|
||||||
tmp = DtoBitCast(tmp, funcTy->getParamType(1));
|
cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
|
||||||
args.push_back(tmp);
|
assert(funcTy->getParamType(1) == cinfo->getType());
|
||||||
assert(funcTy->getParamType(1) == tmp->getType());
|
|
||||||
|
|
||||||
// call it
|
// call it
|
||||||
LLValue* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp");
|
LLValue* ret = gIR->ir->CreateCall2(func, obj, cinfo, "tmp");
|
||||||
|
|
||||||
// cast return value
|
// cast return value
|
||||||
ret = DtoBitCast(ret, DtoType(_to));
|
ret = DtoBitCast(ret, DtoType(_to));
|
||||||
|
@ -1064,22 +1065,20 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
|
||||||
std::vector<LLValue*> args;
|
std::vector<LLValue*> args;
|
||||||
|
|
||||||
// void* p
|
// void* p
|
||||||
LLValue* tmp = val->getRVal();
|
LLValue* ptr = val->getRVal();
|
||||||
tmp = DtoBitCast(tmp, funcTy->getParamType(0));
|
ptr = DtoBitCast(ptr, funcTy->getParamType(0));
|
||||||
args.push_back(tmp);
|
|
||||||
|
|
||||||
// ClassInfo c
|
// ClassInfo c
|
||||||
TypeClass* to = (TypeClass*)DtoDType(_to);
|
TypeClass* to = (TypeClass*)DtoDType(_to);
|
||||||
DtoForceDeclareDsymbol(to->sym);
|
DtoForceDeclareDsymbol(to->sym);
|
||||||
assert(to->sym->ir.irStruct->classInfo);
|
assert(to->sym->ir.irStruct->classInfo);
|
||||||
tmp = to->sym->ir.irStruct->classInfo;
|
LLValue* cinfo = to->sym->ir.irStruct->classInfo;
|
||||||
// unfortunately this is needed as the implementation of object differs somehow from the declaration
|
// unfortunately this is needed as the implementation of object differs somehow from the declaration
|
||||||
// this could happen in user code as well :/
|
// this could happen in user code as well :/
|
||||||
tmp = DtoBitCast(tmp, funcTy->getParamType(1));
|
cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
|
||||||
args.push_back(tmp);
|
|
||||||
|
|
||||||
// call it
|
// call it
|
||||||
LLValue* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp");
|
LLValue* ret = gIR->ir->CreateCall2(func, ptr, cinfo, "tmp");
|
||||||
|
|
||||||
// cast return value
|
// cast return value
|
||||||
ret = DtoBitCast(ret, DtoType(_to));
|
ret = DtoBitCast(ret, DtoType(_to));
|
||||||
|
@ -1127,7 +1126,7 @@ void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, std::vector<unsigned>& idxs)
|
LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, DStructIndexVector& idxs)
|
||||||
{
|
{
|
||||||
Logger::println("checking for offset %u type %s:", os, t->toChars());
|
Logger::println("checking for offset %u type %s:", os, t->toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
@ -1157,7 +1156,7 @@ LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os,
|
||||||
Logger::println("found %s %s", vdtype->toChars(), vd->toChars());
|
Logger::println("found %s %s", vdtype->toChars(), vd->toChars());
|
||||||
idxs.push_back(vd->ir.irField->index + dataoffset);
|
idxs.push_back(vd->ir.irField->index + dataoffset);
|
||||||
//Logger::cout() << "indexing: " << *ptr << '\n';
|
//Logger::cout() << "indexing: " << *ptr << '\n';
|
||||||
ptr = DtoGEP(ptr, idxs, "tmp");
|
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||||
if (ptr->getType() != llt)
|
if (ptr->getType() != llt)
|
||||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||||
//Logger::cout() << "indexing: " << *ptr << '\n';
|
//Logger::cout() << "indexing: " << *ptr << '\n';
|
||||||
|
@ -1172,18 +1171,18 @@ LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os,
|
||||||
idxs.push_back(vd->ir.irField->index + dataoffset);
|
idxs.push_back(vd->ir.irField->index + dataoffset);
|
||||||
if (vd->ir.irField->indexOffset) {
|
if (vd->ir.irField->indexOffset) {
|
||||||
Logger::println("has union field offset");
|
Logger::println("has union field offset");
|
||||||
ptr = DtoGEP(ptr, idxs, "tmp");
|
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||||
if (ptr->getType() != llt)
|
if (ptr->getType() != llt)
|
||||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||||
ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
|
ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
|
||||||
std::vector<unsigned> tmp;
|
DStructIndexVector tmp;
|
||||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const LLType* sty = getPtrToType(DtoType(vd->type));
|
const LLType* sty = getPtrToType(DtoType(vd->type));
|
||||||
if (ptr->getType() != sty) {
|
if (ptr->getType() != sty) {
|
||||||
ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
|
ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
|
||||||
std::vector<unsigned> tmp;
|
DStructIndexVector tmp;
|
||||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef LLVMDC_GEN_CLASSES_H
|
#ifndef LLVMDC_GEN_CLASSES_H
|
||||||
#define LLVMDC_GEN_CLASSES_H
|
#define LLVMDC_GEN_CLASSES_H
|
||||||
|
|
||||||
|
#include "gen/structs.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the llvm type for a class declaration
|
* Resolves the llvm type for a class declaration
|
||||||
*/
|
*/
|
||||||
|
@ -35,7 +37,7 @@ DValue* DtoDynamicCastObject(DValue* val, Type* to);
|
||||||
DValue* DtoCastInterfaceToObject(DValue* val, Type* to);
|
DValue* DtoCastInterfaceToObject(DValue* val, Type* to);
|
||||||
DValue* DtoDynamicCastInterface(DValue* val, Type* to);
|
DValue* DtoDynamicCastInterface(DValue* val, Type* to);
|
||||||
|
|
||||||
LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, std::vector<unsigned>& idxs);
|
LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, DStructIndexVector& idxs);
|
||||||
|
|
||||||
LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl);
|
LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl);
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,13 @@ const LLType* DtoComplexBaseType(Type* t)
|
||||||
TY ty = DtoDType(t)->ty;
|
TY ty = DtoDType(t)->ty;
|
||||||
const LLType* base;
|
const LLType* base;
|
||||||
if (ty == Tcomplex32) {
|
if (ty == Tcomplex32) {
|
||||||
return llvm::Type::FloatTy;
|
return LLType::FloatTy;
|
||||||
}
|
}
|
||||||
else if (ty == Tcomplex64 || ty == Tcomplex80) {
|
else if (ty == Tcomplex64) {
|
||||||
return llvm::Type::DoubleTy;
|
return LLType::DoubleTy;
|
||||||
|
}
|
||||||
|
else if (ty == Tcomplex80) {
|
||||||
|
return (global.params.useFP80) ? LLType::X86_FP80Ty : LLType::DoubleTy;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -60,49 +63,25 @@ LLConstant* DtoConstComplex(Type* _ty, long double re, long double im)
|
||||||
llvm::ConstantFP* fre;
|
llvm::ConstantFP* fre;
|
||||||
llvm::ConstantFP* fim;
|
llvm::ConstantFP* fim;
|
||||||
|
|
||||||
const LLType* base;
|
Type* base = 0;
|
||||||
|
|
||||||
if (ty == Tcomplex32) {
|
if (ty == Tcomplex32) {
|
||||||
fre = DtoConstFP(Type::tfloat32, re);
|
base = Type::tfloat32;
|
||||||
fim = DtoConstFP(Type::tfloat32, im);
|
|
||||||
base = llvm::Type::FloatTy;
|
|
||||||
}
|
}
|
||||||
else if (ty == Tcomplex64 || ty == Tcomplex80) {
|
else if (ty == Tcomplex64) {
|
||||||
fre = DtoConstFP(Type::tfloat64, re);
|
base = Type::tfloat64;
|
||||||
fim = DtoConstFP(Type::tfloat64, im);
|
}
|
||||||
base = llvm::Type::DoubleTy;
|
else if (ty == Tcomplex80) {
|
||||||
|
base = (global.params.useFP80) ? Type::tfloat80 : Type::tfloat64;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
assert(0);
|
|
||||||
|
|
||||||
std::vector<LLConstant*> inits;
|
std::vector<LLConstant*> inits;
|
||||||
inits.push_back(fre);
|
inits.push_back(DtoConstFP(base, re));
|
||||||
inits.push_back(fim);
|
inits.push_back(DtoConstFP(base, im));
|
||||||
|
|
||||||
return llvm::ConstantStruct::get(DtoComplexType(_ty), inits);
|
return llvm::ConstantStruct::get(DtoComplexType(_ty), inits);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLConstant* DtoUndefComplex(Type* _ty)
|
|
||||||
{
|
|
||||||
assert(0);
|
|
||||||
TY ty = DtoDType(_ty)->ty;
|
|
||||||
const LLType* base;
|
|
||||||
if (ty == Tcomplex32) {
|
|
||||||
base = llvm::Type::FloatTy;
|
|
||||||
}
|
|
||||||
else if (ty == Tcomplex64 || ty == Tcomplex80) {
|
|
||||||
base = llvm::Type::DoubleTy;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
assert(0);
|
|
||||||
|
|
||||||
std::vector<LLConstant*> inits;
|
|
||||||
inits.push_back(llvm::UndefValue::get(base));
|
|
||||||
inits.push_back(llvm::UndefValue::get(base));
|
|
||||||
|
|
||||||
const llvm::VectorType* vt = llvm::VectorType::get(base, 2);
|
|
||||||
return llvm::ConstantVector::get(vt, inits);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLValue* DtoRealPart(DValue* val)
|
LLValue* DtoRealPart(DValue* val)
|
||||||
|
@ -135,9 +114,11 @@ DValue* DtoComplex(Type* to, DValue* val)
|
||||||
LLConstant* undef = llvm::UndefValue::get(base);
|
LLConstant* undef = llvm::UndefValue::get(base);
|
||||||
LLConstant* zero;
|
LLConstant* zero;
|
||||||
if (ty == Tfloat32 || ty == Timaginary32 || ty == Tcomplex32)
|
if (ty == Tfloat32 || ty == Timaginary32 || ty == Tcomplex32)
|
||||||
zero = llvm::ConstantFP::get(llvm::APFloat(0.0f));
|
zero = LLConstant::getNullValue(DtoType(Type::tfloat32)); // llvm::ConstantFP::get(llvm::APFloat(0.0f));
|
||||||
else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64 || ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80)
|
else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64)
|
||||||
zero = llvm::ConstantFP::get(llvm::APFloat(0.0));
|
zero = LLConstant::getNullValue(DtoType(Type::tfloat64));
|
||||||
|
else if (ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80)
|
||||||
|
zero = LLConstant::getNullValue(DtoType((global.params.useFP80)?Type::tfloat80:Type::tfloat64));
|
||||||
|
|
||||||
if (t->isimaginary()) {
|
if (t->isimaginary()) {
|
||||||
return new DComplexValue(to, zero, val->getRVal());
|
return new DComplexValue(to, zero, val->getRVal());
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
#define LLVMDC_GEN_COMPLEX_H
|
#define LLVMDC_GEN_COMPLEX_H
|
||||||
|
|
||||||
const llvm::StructType* DtoComplexType(Type* t);
|
const llvm::StructType* DtoComplexType(Type* t);
|
||||||
const llvm::Type* DtoComplexBaseType(Type* t);
|
const LLType* DtoComplexBaseType(Type* t);
|
||||||
|
|
||||||
LLConstant* DtoConstComplex(Type* t, LLConstant* re, LLConstant* im);
|
LLConstant* DtoConstComplex(Type* t, LLConstant* re, LLConstant* im);
|
||||||
LLConstant* DtoConstComplex(Type* t, long double re, long double im);
|
LLConstant* DtoConstComplex(Type* t, long double re, long double im);
|
||||||
LLConstant* DtoUndefComplex(Type* _ty);
|
|
||||||
|
|
||||||
LLConstant* DtoComplexShuffleMask(unsigned a, unsigned b);
|
LLConstant* DtoComplexShuffleMask(unsigned a, unsigned b);
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
||||||
else {
|
else {
|
||||||
assert(rt);
|
assert(rt);
|
||||||
Type* rtfin = DtoDType(rt);
|
Type* rtfin = DtoDType(rt);
|
||||||
if (DtoIsPassedByRef(rt)) {
|
if (DtoIsReturnedInArg(rt)) {
|
||||||
rettype = getPtrToType(DtoType(rt));
|
rettype = getPtrToType(DtoType(rt));
|
||||||
actualRettype = llvm::Type::VoidTy;
|
actualRettype = llvm::Type::VoidTy;
|
||||||
f->llvmRetInPtr = retinptr = true;
|
f->llvmRetInPtr = retinptr = true;
|
||||||
|
@ -94,22 +94,30 @@ 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;
|
||||||
|
|
||||||
|
llvm::PAListPtr palist;
|
||||||
|
|
||||||
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
|
||||||
Type* argT = DtoDType(arg->type);
|
Type* argT = DtoDType(arg->type);
|
||||||
assert(argT);
|
assert(argT);
|
||||||
|
|
||||||
|
bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
|
||||||
|
|
||||||
const LLType* at = DtoType(argT);
|
const LLType* at = DtoType(argT);
|
||||||
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;
|
||||||
}
|
}
|
||||||
else if (isaArray(at)) {
|
else if (isaArray(at)) {
|
||||||
Logger::println("sarray param");
|
Logger::println("sarray param");
|
||||||
assert(argT->ty == Tsarray);
|
assert(argT->ty == Tsarray);
|
||||||
//paramvec.push_back(getPtrToType(at->getContainedType(0)));
|
//paramvec.push_back(getPtrToType(at->getContainedType(0)));
|
||||||
paramvec.push_back(getPtrToType(at));
|
paramvec.push_back(getPtrToType(at));
|
||||||
|
arg->llvmByVal = !refOrOut;
|
||||||
}
|
}
|
||||||
else if (llvm::isa<llvm::OpaqueType>(at)) {
|
else if (llvm::isa<llvm::OpaqueType>(at)) {
|
||||||
Logger::println("opaque param");
|
Logger::println("opaque param");
|
||||||
|
@ -117,7 +125,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
||||||
paramvec.push_back(getPtrToType(at));
|
paramvec.push_back(getPtrToType(at));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
|
if (refOrOut) {
|
||||||
Logger::println("by ref param");
|
Logger::println("by ref param");
|
||||||
at = getPtrToType(at);
|
at = getPtrToType(at);
|
||||||
}
|
}
|
||||||
|
@ -126,8 +134,13 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
||||||
}
|
}
|
||||||
paramvec.push_back(at);
|
paramvec.push_back(at);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg->llvmByVal)
|
||||||
|
nbyval++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//warning("set %d byval args for type: %s", nbyval, f->toChars());
|
||||||
|
|
||||||
// construct function type
|
// construct function type
|
||||||
bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
|
bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
|
||||||
llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
|
llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
|
||||||
|
@ -135,10 +148,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
||||||
f->llvmRetInPtr = retinptr;
|
f->llvmRetInPtr = retinptr;
|
||||||
f->llvmUsesThis = usesthis;
|
f->llvmUsesThis = usesthis;
|
||||||
|
|
||||||
//if (!f->ir.type)
|
f->ir.type = new llvm::PATypeHolder(functype);
|
||||||
f->ir.type = new llvm::PATypeHolder(functype);
|
|
||||||
//else
|
|
||||||
//assert(functype == f->ir.type->get());
|
|
||||||
|
|
||||||
return functype;
|
return functype;
|
||||||
}
|
}
|
||||||
|
@ -378,6 +388,43 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||||
fdecl->ir.irFunc->func = func;
|
fdecl->ir.irFunc->func = func;
|
||||||
assert(llvm::isa<llvm::FunctionType>(f->ir.type->get()));
|
assert(llvm::isa<llvm::FunctionType>(f->ir.type->get()));
|
||||||
|
|
||||||
|
// parameter attributes
|
||||||
|
if (f->parameters)
|
||||||
|
{
|
||||||
|
int llidx = 1;
|
||||||
|
if (f->llvmRetInPtr) ++llidx;
|
||||||
|
if (f->llvmUsesThis) ++llidx;
|
||||||
|
if (f->linkage == LINKd && f->varargs == 1)
|
||||||
|
llidx += 2;
|
||||||
|
|
||||||
|
int funcNumArgs = func->getArgumentList().size();
|
||||||
|
std::vector<llvm::ParamAttrsWithIndex> attrs;
|
||||||
|
int k = 0;
|
||||||
|
|
||||||
|
int nbyval = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
attrs.push_back(PAWI);
|
||||||
|
nbyval++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//warning("set %d byval args for function: %s", nbyval, func->getName().c_str());
|
||||||
|
|
||||||
|
if (nbyval) {
|
||||||
|
llvm::PAListPtr palist = llvm::PAListPtr::get(attrs.begin(), attrs.end());
|
||||||
|
func->setParamAttrs(palist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// main
|
// main
|
||||||
if (fdecl->isMain()) {
|
if (fdecl->isMain()) {
|
||||||
gIR->mainFunc = func;
|
gIR->mainFunc = func;
|
||||||
|
@ -775,19 +822,14 @@ DValue* DtoArgument(Argument* fnarg, Expression* argexp)
|
||||||
else
|
else
|
||||||
arg = new DImValue(argexp->type, arg->getRVal(), false);
|
arg = new DImValue(argexp->type, arg->getRVal(), false);
|
||||||
}
|
}
|
||||||
// aggregate arg
|
// byval arg, but expr has no storage yet
|
||||||
else if (DtoIsPassedByRef(argexp->type))
|
else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull()))
|
||||||
{
|
{
|
||||||
LLValue* alloc = new llvm::AllocaInst(DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
|
LLValue* alloc = new llvm::AllocaInst(DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
|
||||||
DVarValue* vv = new DVarValue(argexp->type, alloc, true);
|
DVarValue* vv = new DVarValue(argexp->type, alloc, true);
|
||||||
DtoAssign(vv, arg);
|
DtoAssign(vv, arg);
|
||||||
arg = vv;
|
arg = vv;
|
||||||
}
|
}
|
||||||
// normal arg (basic/value type)
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ void ReturnStatement::toIR(IRState* p)
|
||||||
|
|
||||||
emit_finallyblocks(p, enclosingtryfinally, NULL);
|
emit_finallyblocks(p, enclosingtryfinally, NULL);
|
||||||
|
|
||||||
if (gIR->func()->inVolatile) {
|
if (f->inVolatile) {
|
||||||
// store-load barrier
|
// store-load barrier
|
||||||
DtoMemoryBarrier(false, false, true, false);
|
DtoMemoryBarrier(false, false, true, false);
|
||||||
}
|
}
|
||||||
|
@ -128,21 +128,16 @@ void ReturnStatement::toIR(IRState* p)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
|
assert(p->topfunc()->getReturnType() == llvm::Type::VoidTy);
|
||||||
emit_finallyblocks(p, enclosingtryfinally, NULL);
|
emit_finallyblocks(p, enclosingtryfinally, NULL);
|
||||||
|
|
||||||
if (gIR->func()->inVolatile) {
|
if (gIR->func()->inVolatile) {
|
||||||
// store-load barrier
|
// store-load barrier
|
||||||
DtoMemoryBarrier(false, false, true, false);
|
DtoMemoryBarrier(false, false, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
|
if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
|
||||||
llvm::ReturnInst::Create(p->scopebb());
|
llvm::ReturnInst::Create(p->scopebb());
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert(0); // why should this ever happen?
|
|
||||||
new llvm::UnreachableInst(p->scopebb());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,11 +611,10 @@ static LLValue* call_string_switch_runtime(llvm::GlobalVariable* table, Expressi
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
|
||||||
std::vector<LLValue*> args;
|
|
||||||
Logger::cout() << *table->getType() << '\n';
|
Logger::cout() << *table->getType() << '\n';
|
||||||
Logger::cout() << *fn->getFunctionType()->getParamType(0) << '\n';
|
Logger::cout() << *fn->getFunctionType()->getParamType(0) << '\n';
|
||||||
assert(table->getType() == fn->getFunctionType()->getParamType(0));
|
assert(table->getType() == fn->getFunctionType()->getParamType(0));
|
||||||
args.push_back(table);
|
|
||||||
|
|
||||||
DValue* val = e->toElem(gIR);
|
DValue* val = e->toElem(gIR);
|
||||||
LLValue* llval;
|
LLValue* llval;
|
||||||
|
@ -636,9 +630,8 @@ static LLValue* call_string_switch_runtime(llvm::GlobalVariable* table, Expressi
|
||||||
llval = val->getRVal();
|
llval = val->getRVal();
|
||||||
}
|
}
|
||||||
assert(llval->getType() == fn->getFunctionType()->getParamType(1));
|
assert(llval->getType() == fn->getFunctionType()->getParamType(1));
|
||||||
args.push_back(llval);
|
|
||||||
|
|
||||||
return gIR->ir->CreateCall(fn, args.begin(), args.end(), "tmp");
|
return gIR->ir->CreateCall2(fn, table, llval, "tmp");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitchStatement::toIR(IRState* p)
|
void SwitchStatement::toIR(IRState* p)
|
||||||
|
|
|
@ -105,7 +105,7 @@ LLConstant* DtoConstStructInitializer(StructInitializer* si)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs)
|
LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, DStructIndexVector& idxs)
|
||||||
{
|
{
|
||||||
Logger::println("checking for offset %u type %s:", os, t->toChars());
|
Logger::println("checking for offset %u type %s:", os, t->toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
@ -127,7 +127,7 @@ LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned o
|
||||||
assert(vd->ir.irField->index >= 0);
|
assert(vd->ir.irField->index >= 0);
|
||||||
if (os == vd->offset && vdtype == t) {
|
if (os == vd->offset && vdtype == t) {
|
||||||
idxs.push_back(vd->ir.irField->index);
|
idxs.push_back(vd->ir.irField->index);
|
||||||
ptr = DtoGEP(ptr, idxs, "tmp");
|
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||||
if (ptr->getType() != llt)
|
if (ptr->getType() != llt)
|
||||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||||
if (vd->ir.irField->indexOffset)
|
if (vd->ir.irField->indexOffset)
|
||||||
|
@ -140,18 +140,18 @@ LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned o
|
||||||
idxs.push_back(vd->ir.irField->index);
|
idxs.push_back(vd->ir.irField->index);
|
||||||
if (vd->ir.irField->indexOffset) {
|
if (vd->ir.irField->indexOffset) {
|
||||||
Logger::println("has union field offset");
|
Logger::println("has union field offset");
|
||||||
ptr = DtoGEP(ptr, idxs, "tmp");
|
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||||
if (ptr->getType() != llt)
|
if (ptr->getType() != llt)
|
||||||
ptr = DtoBitCast(ptr, llt);
|
ptr = DtoBitCast(ptr, llt);
|
||||||
ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
|
ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
|
||||||
std::vector<unsigned> tmp;
|
DStructIndexVector tmp;
|
||||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const LLType* sty = getPtrToType(DtoType(vd->type));
|
const LLType* sty = getPtrToType(DtoType(vd->type));
|
||||||
if (ptr->getType() != sty) {
|
if (ptr->getType() != sty) {
|
||||||
ptr = DtoBitCast(ptr, sty);
|
ptr = DtoBitCast(ptr, sty);
|
||||||
std::vector<unsigned> tmp;
|
DStructIndexVector tmp;
|
||||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -30,7 +30,8 @@ void DtoConstInitStruct(StructDeclaration* sd);
|
||||||
*/
|
*/
|
||||||
void DtoDefineStruct(StructDeclaration* sd);
|
void DtoDefineStruct(StructDeclaration* sd);
|
||||||
|
|
||||||
LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs);
|
typedef LLSmallVector<unsigned, 3> DStructIndexVector;
|
||||||
|
LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, DStructIndexVector& idxs);
|
||||||
|
|
||||||
struct DUnionField
|
struct DUnionField
|
||||||
{
|
{
|
||||||
|
|
|
@ -196,7 +196,7 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd)
|
||||||
|
|
||||||
void DtoDwarfStopPoint(unsigned ln)
|
void DtoDwarfStopPoint(unsigned ln)
|
||||||
{
|
{
|
||||||
std::vector<LLValue*> args;
|
LLSmallVector<LLValue*,3> args;
|
||||||
args.push_back(DtoConstUint(ln));
|
args.push_back(DtoConstUint(ln));
|
||||||
args.push_back(DtoConstUint(0));
|
args.push_back(DtoConstUint(0));
|
||||||
FuncDeclaration* fd = gIR->func()->decl;
|
FuncDeclaration* fd = gIR->func()->decl;
|
||||||
|
|
27
gen/toir.cpp
27
gen/toir.cpp
|
@ -618,7 +618,7 @@ DValue* AddExp::toElem(IRState* p)
|
||||||
llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
|
llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
|
||||||
|
|
||||||
TypeStruct* ts = (TypeStruct*)e1next;
|
TypeStruct* ts = (TypeStruct*)e1next;
|
||||||
std::vector<unsigned> offsets;
|
DStructIndexVector offsets;
|
||||||
LLValue* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets);
|
LLValue* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets);
|
||||||
return new DFieldValue(type, v, true);
|
return new DFieldValue(type, v, true);
|
||||||
}
|
}
|
||||||
|
@ -1018,7 +1018,11 @@ DValue* CallExp::toElem(IRState* p)
|
||||||
|
|
||||||
bool isInPlace = false;
|
bool isInPlace = false;
|
||||||
|
|
||||||
|
// attrs
|
||||||
|
llvm::PAListPtr palist;
|
||||||
|
|
||||||
// hidden struct return arguments
|
// hidden struct return arguments
|
||||||
|
// TODO: use sret param attr
|
||||||
if (retinptr) {
|
if (retinptr) {
|
||||||
if (topexp && topexp->e2 == this) {
|
if (topexp && topexp->e2 == this) {
|
||||||
assert(topexp->v);
|
assert(topexp->v);
|
||||||
|
@ -1167,6 +1171,10 @@ DValue* CallExp::toElem(IRState* p)
|
||||||
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]);
|
||||||
llargs[j] = argval->getRVal();
|
llargs[j] = argval->getRVal();
|
||||||
|
#if USE_BYVAL
|
||||||
|
if (fnarg->llvmByVal)
|
||||||
|
palist = palist.addAttr(j, llvm::ParamAttr::ByVal);
|
||||||
|
#endif
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1187,6 +1195,11 @@ DValue* CallExp::toElem(IRState* p)
|
||||||
llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
|
llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_BYVAL
|
||||||
|
if (fnarg && fnarg->llvmByVal)
|
||||||
|
palist = palist.addAttr(j+1, llvm::ParamAttr::ByVal);
|
||||||
|
#endif
|
||||||
|
|
||||||
// this hack is necessary :/
|
// this hack is necessary :/
|
||||||
if (dfn && dfn->func && dfn->func->runTimeHack) {
|
if (dfn && dfn->func && dfn->func->runTimeHack) {
|
||||||
if (llfnty->getParamType(j) != NULL) {
|
if (llfnty->getParamType(j) != NULL) {
|
||||||
|
@ -1245,6 +1258,9 @@ DValue* CallExp::toElem(IRState* p)
|
||||||
call->setCallingConv(DtoCallingConv(dlink));
|
call->setCallingConv(DtoCallingConv(dlink));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// param attrs
|
||||||
|
call->setParamAttrs(palist);
|
||||||
|
|
||||||
return new DImValue(type, retllval, isInPlace);
|
return new DImValue(type, retllval, isInPlace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1311,7 +1327,7 @@ DValue* SymOffExp::toElem(IRState* p)
|
||||||
varmem = p->ir->CreateBitCast(llvalue, llt, "tmp");
|
varmem = p->ir->CreateBitCast(llvalue, llt, "tmp");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::vector<unsigned> dst;
|
DStructIndexVector dst;
|
||||||
varmem = DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst);
|
varmem = DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1429,7 +1445,7 @@ DValue* DotVarExp::toElem(IRState* p)
|
||||||
|
|
||||||
LLValue* src = l->getRVal();
|
LLValue* src = l->getRVal();
|
||||||
|
|
||||||
std::vector<unsigned> vdoffsets;
|
DStructIndexVector vdoffsets;
|
||||||
arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
|
arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
|
||||||
}
|
}
|
||||||
else if (e1type->ty == Tclass) {
|
else if (e1type->ty == Tclass) {
|
||||||
|
@ -1438,7 +1454,7 @@ DValue* DotVarExp::toElem(IRState* p)
|
||||||
|
|
||||||
LLValue* src = l->getRVal();
|
LLValue* src = l->getRVal();
|
||||||
|
|
||||||
std::vector<unsigned> vdoffsets;
|
DStructIndexVector vdoffsets;
|
||||||
arrptr = DtoIndexClass(src, tc->sym, vd->type, vd->offset, vdoffsets);
|
arrptr = DtoIndexClass(src, tc->sym, vd->type, vd->offset, vdoffsets);
|
||||||
|
|
||||||
/*std::vector<unsigned> vdoffsets(1,0);
|
/*std::vector<unsigned> vdoffsets(1,0);
|
||||||
|
@ -2255,7 +2271,8 @@ DValue* HaltExp::toElem(IRState* p)
|
||||||
Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars());
|
Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
DtoAssert(&loc, NULL);
|
// call the new (?) trap intrinsic
|
||||||
|
p->ir->CreateCall(GET_INTRINSIC_DECL(trap),"");
|
||||||
|
|
||||||
new llvm::UnreachableInst(p->scopebb());
|
new llvm::UnreachableInst(p->scopebb());
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -26,6 +26,13 @@ bool DtoIsPassedByRef(Type* type)
|
||||||
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
|
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DtoIsReturnedInArg(Type* type)
|
||||||
|
{
|
||||||
|
Type* typ = DtoDType(type);
|
||||||
|
TY t = typ->ty;
|
||||||
|
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
|
||||||
|
}
|
||||||
|
|
||||||
Type* DtoDType(Type* t)
|
Type* DtoDType(Type* t)
|
||||||
{
|
{
|
||||||
if (t->ty == Ttypedef) {
|
if (t->ty == Ttypedef) {
|
||||||
|
@ -67,9 +74,10 @@ const LLType* DtoType(Type* t)
|
||||||
return llvm::Type::FloatTy;
|
return llvm::Type::FloatTy;
|
||||||
case Tfloat64:
|
case Tfloat64:
|
||||||
case Timaginary64:
|
case Timaginary64:
|
||||||
|
return llvm::Type::DoubleTy;
|
||||||
case Tfloat80:
|
case Tfloat80:
|
||||||
case Timaginary80:
|
case Timaginary80:
|
||||||
return llvm::Type::DoubleTy;
|
return (global.params.useFP80) ? llvm::Type::X86_FP80Ty : llvm::Type::DoubleTy;
|
||||||
|
|
||||||
// complex
|
// complex
|
||||||
case Tcomplex32:
|
case Tcomplex32:
|
||||||
|
@ -590,46 +598,42 @@ DValue* DtoInitializer(Initializer* init)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const std::string& var, llvm::BasicBlock* bb)
|
LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const char* var, llvm::BasicBlock* bb)
|
||||||
{
|
{
|
||||||
std::vector<LLValue*> v(2);
|
LLSmallVector<LLValue*,2> v(2);
|
||||||
v[0] = i0;
|
v[0] = i0;
|
||||||
v[1] = i1;
|
v[1] = i1;
|
||||||
Logger::cout() << "DtoGEP: " << *ptr << ", " << *i0 << ", " << *i1 << '\n';
|
|
||||||
return llvm::GetElementPtrInst::Create(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb());
|
return llvm::GetElementPtrInst::Create(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb());
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLValue* DtoGEP(LLValue* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb)
|
LLValue* DtoGEPi(LLValue* ptr, const DStructIndexVector& src, const char* var, llvm::BasicBlock* bb)
|
||||||
{
|
{
|
||||||
size_t n = src.size();
|
size_t n = src.size();
|
||||||
std::vector<LLValue*> dst(n, NULL);
|
LLSmallVector<LLValue*, 3> dst(n);
|
||||||
//std::ostream& ostr = Logger::cout();
|
|
||||||
//ostr << "indices for '" << *ptr << "':";
|
size_t j=0;
|
||||||
for (size_t i=0; i<n; ++i)
|
for (DStructIndexVector::const_iterator i=src.begin(); i!=src.end(); ++i)
|
||||||
{
|
dst[j++] = DtoConstUint(*i);
|
||||||
//ostr << ' ' << i;
|
|
||||||
dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
|
|
||||||
}
|
|
||||||
//ostr << '\n';*/
|
|
||||||
return llvm::GetElementPtrInst::Create(ptr, dst.begin(), dst.end(), var, bb?bb:gIR->scopebb());
|
return llvm::GetElementPtrInst::Create(ptr, dst.begin(), dst.end(), var, bb?bb:gIR->scopebb());
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLValue* DtoGEPi(LLValue* ptr, unsigned i, const std::string& var, llvm::BasicBlock* bb)
|
LLValue* DtoGEPi(LLValue* ptr, unsigned i, const char* var, llvm::BasicBlock* bb)
|
||||||
{
|
{
|
||||||
return llvm::GetElementPtrInst::Create(ptr, llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false), var, bb?bb:gIR->scopebb());
|
return llvm::GetElementPtrInst::Create(ptr, llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false), var, bb?bb:gIR->scopebb());
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb)
|
LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const char* var, llvm::BasicBlock* bb)
|
||||||
{
|
{
|
||||||
std::vector<LLValue*> v(2);
|
LLSmallVector<LLValue*,2> v(2);
|
||||||
v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false);
|
v[0] = DtoConstUint(i0);
|
||||||
v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false);
|
v[1] = DtoConstUint(i1);
|
||||||
return llvm::GetElementPtrInst::Create(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb());
|
return llvm::GetElementPtrInst::Create(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,11 +646,8 @@ LLValue* DtoNew(Type* newtype)
|
||||||
// get type info
|
// get type info
|
||||||
LLConstant* ti = DtoTypeInfoOf(newtype);
|
LLConstant* ti = DtoTypeInfoOf(newtype);
|
||||||
assert(isaPointer(ti));
|
assert(isaPointer(ti));
|
||||||
// call runtime
|
// call runtime allocator
|
||||||
LLSmallVector<LLValue*,1> arg;
|
LLValue* mem = gIR->ir->CreateCall(fn, ti, ".gc_mem");
|
||||||
arg.push_back(ti);
|
|
||||||
// allocate
|
|
||||||
LLValue* mem = gIR->ir->CreateCall(fn, arg.begin(), arg.end(), ".gc_mem");
|
|
||||||
// cast
|
// cast
|
||||||
return DtoBitCast(mem, getPtrToType(DtoType(newtype)), ".gc_mem");
|
return DtoBitCast(mem, getPtrToType(DtoType(newtype)), ".gc_mem");
|
||||||
}
|
}
|
||||||
|
@ -707,6 +708,10 @@ void DtoAssert(Loc* loc, DValue* msg)
|
||||||
const char* fname = msg ? "_d_assert_msg" : "_d_assert";
|
const char* fname = msg ? "_d_assert_msg" : "_d_assert";
|
||||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
|
||||||
|
|
||||||
|
// param attrs
|
||||||
|
llvm::PAListPtr palist;
|
||||||
|
int idx = 1;
|
||||||
|
|
||||||
c = DtoConstString(loc->filename);
|
c = DtoConstString(loc->filename);
|
||||||
|
|
||||||
// msg param
|
// msg param
|
||||||
|
@ -727,6 +732,7 @@ void DtoAssert(Loc* loc, DValue* msg)
|
||||||
{
|
{
|
||||||
args.push_back(msg->getRVal());
|
args.push_back(msg->getRVal());
|
||||||
}
|
}
|
||||||
|
palist = palist.addAttr(idx++, llvm::ParamAttr::ByVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// file param
|
// file param
|
||||||
|
@ -740,7 +746,10 @@ void DtoAssert(Loc* loc, DValue* msg)
|
||||||
DtoStore(c->getOperand(0), ptr);
|
DtoStore(c->getOperand(0), ptr);
|
||||||
ptr = DtoGEPi(alloc, 0,1, "tmp");
|
ptr = DtoGEPi(alloc, 0,1, "tmp");
|
||||||
DtoStore(c->getOperand(1), ptr);
|
DtoStore(c->getOperand(1), ptr);
|
||||||
|
|
||||||
args.push_back(alloc);
|
args.push_back(alloc);
|
||||||
|
palist = palist.addAttr(idx++, llvm::ParamAttr::ByVal);
|
||||||
|
|
||||||
|
|
||||||
// line param
|
// line param
|
||||||
c = DtoConstUint(loc->linnum);
|
c = DtoConstUint(loc->linnum);
|
||||||
|
@ -748,6 +757,7 @@ void DtoAssert(Loc* loc, DValue* msg)
|
||||||
|
|
||||||
// call
|
// call
|
||||||
llvm::CallInst* call = llvm::CallInst::Create(fn, args.begin(), args.end(), "", gIR->scopebb());
|
llvm::CallInst* call = llvm::CallInst::Create(fn, args.begin(), args.end(), "", gIR->scopebb());
|
||||||
|
call->setParamAttrs(palist);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
11
gen/tollvm.h
11
gen/tollvm.h
|
@ -7,9 +7,12 @@
|
||||||
#include "attrib.h"
|
#include "attrib.h"
|
||||||
#include "declaration.h"
|
#include "declaration.h"
|
||||||
|
|
||||||
|
#include "gen/structs.h"
|
||||||
|
|
||||||
// D->LLVM type handling stuff
|
// D->LLVM type handling stuff
|
||||||
const LLType* DtoType(Type* t);
|
const LLType* DtoType(Type* t);
|
||||||
bool DtoIsPassedByRef(Type* type);
|
bool DtoIsPassedByRef(Type* type);
|
||||||
|
bool DtoIsReturnedInArg(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
|
||||||
|
@ -54,10 +57,10 @@ llvm::Function* LLVM_DeclareMemCpy32();
|
||||||
llvm::Function* LLVM_DeclareMemCpy64();
|
llvm::Function* LLVM_DeclareMemCpy64();
|
||||||
|
|
||||||
// getelementptr helpers
|
// getelementptr helpers
|
||||||
LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const std::string& var, llvm::BasicBlock* bb=NULL);
|
LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const char* var, llvm::BasicBlock* bb=NULL);
|
||||||
LLValue* DtoGEP(LLValue* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb=NULL);
|
LLValue* DtoGEPi(LLValue* ptr, const DStructIndexVector& src, const char* var, llvm::BasicBlock* bb=NULL);
|
||||||
LLValue* DtoGEPi(LLValue* ptr, unsigned i0, const std::string& var, llvm::BasicBlock* bb=NULL);
|
LLValue* DtoGEPi(LLValue* ptr, unsigned i0, const char* var, llvm::BasicBlock* bb=NULL);
|
||||||
LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb=NULL);
|
LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const char* var, llvm::BasicBlock* bb=NULL);
|
||||||
|
|
||||||
// dynamic memory helpers
|
// dynamic memory helpers
|
||||||
LLValue* DtoNew(Type* newtype);
|
LLValue* DtoNew(Type* newtype);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "llvm/Bitcode/ReaderWriter.h"
|
#include "llvm/Bitcode/ReaderWriter.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetMachineRegistry.h"
|
#include "llvm/Target/TargetMachineRegistry.h"
|
||||||
|
#include "llvm/System/Path.h"
|
||||||
|
|
||||||
#include "mars.h"
|
#include "mars.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
@ -151,17 +152,36 @@ void Module::genobjfile()
|
||||||
// run optimizer
|
// run optimizer
|
||||||
llvmdc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline);
|
llvmdc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline);
|
||||||
|
|
||||||
|
// eventually do our own path stuff, dmd's is a bit strange.
|
||||||
|
typedef llvm::sys::Path LLPath;
|
||||||
|
LLPath bcpath;
|
||||||
|
LLPath llpath;
|
||||||
|
|
||||||
|
if (global.params.fqnPaths)
|
||||||
|
{
|
||||||
|
bcpath = LLPath(md->toChars());
|
||||||
|
bcpath.appendSuffix("bc");
|
||||||
|
|
||||||
|
llpath = LLPath(md->toChars());
|
||||||
|
llpath.appendSuffix("ll");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bcpath = LLPath(bcfile->name->toChars());
|
||||||
|
llpath = LLPath(llfile->name->toChars());
|
||||||
|
}
|
||||||
|
|
||||||
// write bytecode
|
// write bytecode
|
||||||
{
|
{
|
||||||
Logger::println("Writing LLVM bitcode\n");
|
Logger::println("Writing LLVM bitcode\n");
|
||||||
std::ofstream bos(bcfile->name->toChars(), std::ios::binary);
|
std::ofstream bos(bcpath.c_str(), std::ios::binary);
|
||||||
llvm::WriteBitcodeToFile(ir.module, bos);
|
llvm::WriteBitcodeToFile(ir.module, bos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// disassemble ?
|
// disassemble ?
|
||||||
if (global.params.disassemble) {
|
if (global.params.disassemble) {
|
||||||
Logger::println("Writing LLVM asm to: %s\n", llfile->name->toChars());
|
Logger::println("Writing LLVM asm to: %s\n", llfile->name->toChars());
|
||||||
std::ofstream aos(llfile->name->toChars());
|
std::ofstream aos(llpath.c_str());
|
||||||
ir.module->print(aos);
|
ir.module->print(aos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -749,7 +749,9 @@ tangotests/a.d
|
||||||
tangotests/aa1.d
|
tangotests/aa1.d
|
||||||
tangotests/aa2.d
|
tangotests/aa2.d
|
||||||
tangotests/align1.d
|
tangotests/align1.d
|
||||||
|
tangotests/arrays1.d
|
||||||
tangotests/b.d
|
tangotests/b.d
|
||||||
|
tangotests/byval1.d
|
||||||
tangotests/c.d
|
tangotests/c.d
|
||||||
tangotests/classes1.d
|
tangotests/classes1.d
|
||||||
tangotests/constructors.d
|
tangotests/constructors.d
|
||||||
|
|
|
@ -47,6 +47,7 @@ private
|
||||||
{
|
{
|
||||||
void* llvm_frameaddress(uint level=0);
|
void* llvm_frameaddress(uint level=0);
|
||||||
}
|
}
|
||||||
|
extern(C) int printf(char*, ...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +162,7 @@ extern (C) void rt_scanStaticData( scanFn scan )
|
||||||
}
|
}
|
||||||
else version( linux )
|
else version( linux )
|
||||||
{
|
{
|
||||||
|
//printf("scanning static data from %p to %p\n", &__data_start, &_end);
|
||||||
scan( &__data_start, &_end );
|
scan( &__data_start, &_end );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
30
tangotests/vararg4.d
Normal file
30
tangotests/vararg4.d
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
module tangotests.vararg4;
|
||||||
|
|
||||||
|
extern(C) int printf(char*, ...);
|
||||||
|
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void func(...)
|
||||||
|
{
|
||||||
|
S* sp = cast(S*)_argptr;
|
||||||
|
assert(sp.i == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
printf("1st:\n");
|
||||||
|
{
|
||||||
|
S s = S(42);
|
||||||
|
func(s);
|
||||||
|
}
|
||||||
|
printf("ok\n");
|
||||||
|
|
||||||
|
printf("2nd:\n");
|
||||||
|
{
|
||||||
|
func(S(42));
|
||||||
|
}
|
||||||
|
printf("ok\n");
|
||||||
|
}
|
|
@ -35,7 +35,7 @@ echo
|
||||||
|
|
||||||
if [ -z $DMD ] ; then
|
if [ -z $DMD ] ; then
|
||||||
echo "Testing with llvmdc. Set DMD environment variable to select compiler."
|
echo "Testing with llvmdc. Set DMD environment variable to select compiler."
|
||||||
DMD="llvmdc"
|
DMD="llvmdc -O0"
|
||||||
else
|
else
|
||||||
echo "Using compiler given by DMD environment variable: $DMD"
|
echo "Using compiler given by DMD environment variable: $DMD"
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue