[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:
Tomas Lindquist Olsen 2008-06-05 06:38:36 +02:00
parent 1a41b9ef12
commit d03c3a7757
23 changed files with 299 additions and 187 deletions

View file

@ -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);

View file

@ -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

View file

@ -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;
} }

View file

@ -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;

View file

@ -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);

View file

@ -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));

View file

@ -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 {

View file

@ -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);

View file

@ -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());

View file

@ -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);

View file

@ -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;
} }

View file

@ -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)

View file

@ -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 {

View file

@ -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
{ {

View file

@ -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;

View file

@ -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;

View file

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

View file

@ -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);

View file

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

View file

@ -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

View file

@ -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
View 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");
}

View file

@ -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