mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 02:45:25 +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\
|
||||
-of<filename> name output file to <filename>\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\
|
||||
-quiet suppress unnecessary messages\n\
|
||||
-release compile release version\n\
|
||||
|
@ -214,6 +215,7 @@ Usage:\n\
|
|||
-version=level compile in version code >= level\n\
|
||||
-version=ident compile in version code identified by ident\n\
|
||||
-w enable warnings\n\
|
||||
-fp80 enable 80bit reals on x86 32bit (EXPERIMENTAL)\n\
|
||||
",
|
||||
#if WIN32
|
||||
" @cmdfile read arguments from cmdfile\n"
|
||||
|
@ -397,6 +399,8 @@ int main(int argc, char *argv[])
|
|||
global.params.disassemble = 1;
|
||||
else if (strcmp(p + 1, "annotate") == 0)
|
||||
global.params.llvmAnnotate = 1;
|
||||
else if (strcmp(p + 1, "fp80") == 0)
|
||||
global.params.useFP80 = 1;
|
||||
else if (p[1] == 'o')
|
||||
{
|
||||
switch (p[2])
|
||||
|
@ -423,6 +427,12 @@ int main(int argc, char *argv[])
|
|||
global.params.preservePaths = 1;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
if (p[3])
|
||||
goto Lerror;
|
||||
global.params.fqnPaths = 1;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
error("-o no longer supported, use -of or -od");
|
||||
break;
|
||||
|
@ -691,6 +701,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
bool is_x86 = false;
|
||||
if (strcmp(global.params.llvmArch,"x86")==0) {
|
||||
VersionCondition::addPredefinedGlobalIdent("X86");
|
||||
//VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
|
||||
|
@ -698,6 +709,7 @@ int main(int argc, char *argv[])
|
|||
global.params.is64bit = false;
|
||||
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";
|
||||
is_x86 = true;
|
||||
}
|
||||
else if (strcmp(global.params.llvmArch,"x86-64")==0) {
|
||||
VersionCondition::addPredefinedGlobalIdent("X86_64");
|
||||
|
@ -740,6 +752,14 @@ int main(int argc, char *argv[])
|
|||
VersionCondition::addPredefinedGlobalIdent("LLVM64");
|
||||
}
|
||||
|
||||
if (global.params.useFP80) {
|
||||
if (!is_x86) {
|
||||
error("the -fp80 option is only valid for the x86 32bit architecture");
|
||||
fatal();
|
||||
}
|
||||
VersionCondition::addPredefinedGlobalIdent("LLVM_X86_FP80");
|
||||
}
|
||||
|
||||
assert(tt_arch != 0);
|
||||
assert(tt_os != 0);
|
||||
assert(data_layout != 0);
|
||||
|
|
|
@ -133,6 +133,8 @@ struct Param
|
|||
char llvmInline;
|
||||
char llvmAnnotate;
|
||||
char *runtimePath;
|
||||
char useFP80;
|
||||
char fqnPaths; // use fully qualified object names
|
||||
};
|
||||
|
||||
struct Global
|
||||
|
|
|
@ -2538,7 +2538,9 @@ Type *TypeFunction::syntaxCopy()
|
|||
{
|
||||
Type *treturn = next ? next->syntaxCopy() : NULL;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -5062,6 +5064,7 @@ Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Express
|
|||
this->ident = ident;
|
||||
this->storageClass = storageClass;
|
||||
this->defaultArg = defaultArg;
|
||||
this->llvmByVal = false;
|
||||
}
|
||||
|
||||
Argument *Argument::syntaxCopy()
|
||||
|
@ -5070,6 +5073,7 @@ Argument *Argument::syntaxCopy()
|
|||
type ? type->syntaxCopy() : NULL,
|
||||
ident,
|
||||
defaultArg ? defaultArg->syntaxCopy() : NULL);
|
||||
a->llvmByVal = llvmByVal;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
|
|
@ -681,6 +681,9 @@ struct Argument : Object
|
|||
static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments);
|
||||
static size_t dim(Arguments *arguments);
|
||||
static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
|
||||
|
||||
// LLVMDC
|
||||
bool llvmByVal;
|
||||
};
|
||||
|
||||
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);
|
||||
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
|
||||
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
|
||||
const LLType* targettype = getPtrToType(DtoType(type));
|
||||
|
@ -131,14 +124,8 @@ DValue* DtoAAIn(Type* type, DValue* aa, DValue* key)
|
|||
LLValue* pkey = to_pkey(key);
|
||||
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
|
||||
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
|
||||
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';
|
||||
|
||||
std::vector<LLValue*> args;
|
||||
LLSmallVector<LLValue*, 4> args;
|
||||
args.push_back(ptr);
|
||||
args.push_back(dim);
|
||||
args.push_back(val);
|
||||
|
@ -424,12 +424,11 @@ void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
|
|||
LLValue* srcarr = DtoBitCast(get_slice_ptr(src,sz2),arrty);
|
||||
|
||||
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
||||
std::vector<LLValue*> llargs;
|
||||
llargs.resize(4);
|
||||
LLSmallVector<LLValue*, 4> llargs(4);
|
||||
llargs[0] = dstarr;
|
||||
llargs[1] = srcarr;
|
||||
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());
|
||||
}
|
||||
|
@ -444,12 +443,11 @@ void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
|
|||
LLValue* srcarr = DtoBitCast(DtoArrayPtr(src),arrty);
|
||||
|
||||
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
||||
std::vector<LLValue*> llargs;
|
||||
llargs.resize(4);
|
||||
LLSmallVector<LLValue*, 4> llargs(4);
|
||||
llargs[0] = dstarr;
|
||||
llargs[1] = srcarr;
|
||||
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());
|
||||
}
|
||||
|
@ -467,12 +465,11 @@ void DtoStaticArrayCopy(LLValue* dst, LLValue* src)
|
|||
LLValue* srcarr = DtoBitCast(src,arrty);
|
||||
|
||||
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
||||
std::vector<LLValue*> llargs;
|
||||
llargs.resize(4);
|
||||
LLSmallVector<LLValue*,4> llargs(4);
|
||||
llargs[0] = dstarr;
|
||||
llargs[1] = srcarr;
|
||||
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());
|
||||
}
|
||||
|
@ -480,14 +477,8 @@ void DtoStaticArrayCopy(LLValue* dst, LLValue* src)
|
|||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr)
|
||||
{
|
||||
std::vector<const LLType*> types;
|
||||
types.push_back(dim->getType());
|
||||
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);
|
||||
LLConstant* values[2] = { dim, ptr };
|
||||
return llvm::ConstantStruct::get(values, 2);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -496,15 +487,21 @@ DSliceValue* DtoNewDynArray(Type* arrayType, DValue* dim, bool defaultInit)
|
|||
Logger::println("DtoNewDynArray : %s", arrayType->toChars());
|
||||
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();
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_newarrayT" : "_d_newarrayiT" );
|
||||
|
||||
LLSmallVector<LLValue*,2> args;
|
||||
args.push_back(DtoTypeInfoOf(arrayType));
|
||||
assert(DtoType(dim->getType()) == DtoSize_t());
|
||||
args.push_back(dim->getRVal());
|
||||
// call allocator
|
||||
LLValue* newptr = gIR->ir->CreateCall2(fn, arrayTypeInfo, arrayLen, ".gc_mem");
|
||||
|
||||
LLValue* newptr = gIR->ir->CreateCall(fn, args.begin(), args.end(), ".gc_mem");
|
||||
// cast to wanted type
|
||||
const LLType* dstType = DtoType(arrayType)->getContainedType(1);
|
||||
if (newptr->getType() != dstType)
|
||||
newptr = DtoBitCast(newptr, dstType, ".gc_mem");
|
||||
|
@ -518,7 +515,7 @@ DSliceValue* DtoNewDynArray(Type* arrayType, DValue* dim, bool defaultInit)
|
|||
}
|
||||
#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(newdim->getRVal());
|
||||
args.push_back(DtoArrayLen(array));
|
||||
|
||||
LLValue* arrPtr = DtoArrayPtr(array);
|
||||
Logger::cout() << "arrPtr = " << *arrPtr << '\n';
|
||||
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());
|
||||
assert(l_ty->next == r_ty->next);
|
||||
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)
|
||||
l = DtoCastArray(l, a_ty);
|
||||
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);
|
||||
|
||||
std::vector<LLValue*> args;
|
||||
LLSmallVector<LLValue*, 3> args;
|
||||
Logger::cout() << "bitcasting to " << *pt << '\n';
|
||||
Logger::cout() << *lmem << '\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)
|
||||
{
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_adEq");
|
||||
assert(fn);
|
||||
|
||||
LLValue* res = DtoArrayEqCmp_impl("_adEq", l, r, true);
|
||||
if (op == TOKnotequal)
|
||||
res = gIR->ir->CreateNot(res, "tmp");
|
||||
|
@ -883,7 +878,7 @@ LLValue* DtoArrayCastLength(LLValue* len, const LLType* elemty, const LLType* ne
|
|||
if (esz == nsz)
|
||||
return len;
|
||||
|
||||
std::vector<LLValue*> args;
|
||||
LLSmallVector<LLValue*, 3> args;
|
||||
args.push_back(len);
|
||||
args.push_back(llvm::ConstantInt::get(DtoSize_t(), esz, false));
|
||||
args.push_back(llvm::ConstantInt::get(DtoSize_t(), nsz, false));
|
||||
|
|
|
@ -796,9 +796,7 @@ DValue* DtoNewClass(TypeClass* tc, NewExp* newexp)
|
|||
else
|
||||
{
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_newclass");
|
||||
std::vector<LLValue*> args;
|
||||
args.push_back(tc->sym->ir.irStruct->classInfo);
|
||||
mem = gIR->ir->CreateCall(fn, args.begin(), args.end(), "newclass_gc_alloc");
|
||||
mem = gIR->ir->CreateCall(fn, tc->sym->ir.irStruct->classInfo, "newclass_gc_alloc");
|
||||
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;
|
||||
TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type);
|
||||
|
||||
llvm::PAListPtr palist;
|
||||
|
||||
std::vector<LLValue*> ctorargs;
|
||||
ctorargs.push_back(mem);
|
||||
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)
|
||||
a = DtoBitCast(a, aty);
|
||||
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());
|
||||
call->setCallingConv(DtoCallingConv(LINKd));
|
||||
call->setParamAttrs(palist);
|
||||
|
||||
return new DImValue(type, call, false);
|
||||
}
|
||||
|
@ -997,24 +1000,22 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to)
|
|||
std::vector<LLValue*> args;
|
||||
|
||||
// Object o
|
||||
LLValue* tmp = val->getRVal();
|
||||
tmp = DtoBitCast(tmp, funcTy->getParamType(0));
|
||||
args.push_back(tmp);
|
||||
assert(funcTy->getParamType(0) == tmp->getType());
|
||||
LLValue* obj = val->getRVal();
|
||||
obj = DtoBitCast(obj, funcTy->getParamType(0));
|
||||
assert(funcTy->getParamType(0) == obj->getType());
|
||||
|
||||
// ClassInfo c
|
||||
TypeClass* to = (TypeClass*)DtoDType(_to);
|
||||
DtoForceDeclareDsymbol(to->sym);
|
||||
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
|
||||
// this could happen in user code as well :/
|
||||
tmp = DtoBitCast(tmp, funcTy->getParamType(1));
|
||||
args.push_back(tmp);
|
||||
assert(funcTy->getParamType(1) == tmp->getType());
|
||||
cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
|
||||
assert(funcTy->getParamType(1) == cinfo->getType());
|
||||
|
||||
// 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
|
||||
ret = DtoBitCast(ret, DtoType(_to));
|
||||
|
@ -1064,22 +1065,20 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
|
|||
std::vector<LLValue*> args;
|
||||
|
||||
// void* p
|
||||
LLValue* tmp = val->getRVal();
|
||||
tmp = DtoBitCast(tmp, funcTy->getParamType(0));
|
||||
args.push_back(tmp);
|
||||
LLValue* ptr = val->getRVal();
|
||||
ptr = DtoBitCast(ptr, funcTy->getParamType(0));
|
||||
|
||||
// ClassInfo c
|
||||
TypeClass* to = (TypeClass*)DtoDType(_to);
|
||||
DtoForceDeclareDsymbol(to->sym);
|
||||
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
|
||||
// this could happen in user code as well :/
|
||||
tmp = DtoBitCast(tmp, funcTy->getParamType(1));
|
||||
args.push_back(tmp);
|
||||
cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
|
||||
|
||||
// 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
|
||||
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());
|
||||
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());
|
||||
idxs.push_back(vd->ir.irField->index + dataoffset);
|
||||
//Logger::cout() << "indexing: " << *ptr << '\n';
|
||||
ptr = DtoGEP(ptr, idxs, "tmp");
|
||||
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
//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);
|
||||
if (vd->ir.irField->indexOffset) {
|
||||
Logger::println("has union field offset");
|
||||
ptr = DtoGEP(ptr, idxs, "tmp");
|
||||
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
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);
|
||||
}
|
||||
else {
|
||||
const LLType* sty = getPtrToType(DtoType(vd->type));
|
||||
if (ptr->getType() != sty) {
|
||||
ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
|
||||
std::vector<unsigned> tmp;
|
||||
DStructIndexVector tmp;
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef LLVMDC_GEN_CLASSES_H
|
||||
#define LLVMDC_GEN_CLASSES_H
|
||||
|
||||
#include "gen/structs.h"
|
||||
|
||||
/**
|
||||
* 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* 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);
|
||||
|
||||
|
|
|
@ -28,10 +28,13 @@ const LLType* DtoComplexBaseType(Type* t)
|
|||
TY ty = DtoDType(t)->ty;
|
||||
const LLType* base;
|
||||
if (ty == Tcomplex32) {
|
||||
return llvm::Type::FloatTy;
|
||||
return LLType::FloatTy;
|
||||
}
|
||||
else if (ty == Tcomplex64 || ty == Tcomplex80) {
|
||||
return llvm::Type::DoubleTy;
|
||||
else if (ty == Tcomplex64) {
|
||||
return LLType::DoubleTy;
|
||||
}
|
||||
else if (ty == Tcomplex80) {
|
||||
return (global.params.useFP80) ? LLType::X86_FP80Ty : LLType::DoubleTy;
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
|
@ -60,49 +63,25 @@ LLConstant* DtoConstComplex(Type* _ty, long double re, long double im)
|
|||
llvm::ConstantFP* fre;
|
||||
llvm::ConstantFP* fim;
|
||||
|
||||
const LLType* base;
|
||||
Type* base = 0;
|
||||
|
||||
if (ty == Tcomplex32) {
|
||||
fre = DtoConstFP(Type::tfloat32, re);
|
||||
fim = DtoConstFP(Type::tfloat32, im);
|
||||
base = llvm::Type::FloatTy;
|
||||
base = Type::tfloat32;
|
||||
}
|
||||
else if (ty == Tcomplex64 || ty == Tcomplex80) {
|
||||
fre = DtoConstFP(Type::tfloat64, re);
|
||||
fim = DtoConstFP(Type::tfloat64, im);
|
||||
base = llvm::Type::DoubleTy;
|
||||
else if (ty == Tcomplex64) {
|
||||
base = Type::tfloat64;
|
||||
}
|
||||
else if (ty == Tcomplex80) {
|
||||
base = (global.params.useFP80) ? Type::tfloat80 : Type::tfloat64;
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
|
||||
std::vector<LLConstant*> inits;
|
||||
inits.push_back(fre);
|
||||
inits.push_back(fim);
|
||||
inits.push_back(DtoConstFP(base, re));
|
||||
inits.push_back(DtoConstFP(base, im));
|
||||
|
||||
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)
|
||||
|
@ -135,9 +114,11 @@ DValue* DtoComplex(Type* to, DValue* val)
|
|||
LLConstant* undef = llvm::UndefValue::get(base);
|
||||
LLConstant* zero;
|
||||
if (ty == Tfloat32 || ty == Timaginary32 || ty == Tcomplex32)
|
||||
zero = llvm::ConstantFP::get(llvm::APFloat(0.0f));
|
||||
else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64 || ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80)
|
||||
zero = llvm::ConstantFP::get(llvm::APFloat(0.0));
|
||||
zero = LLConstant::getNullValue(DtoType(Type::tfloat32)); // llvm::ConstantFP::get(llvm::APFloat(0.0f));
|
||||
else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64)
|
||||
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()) {
|
||||
return new DComplexValue(to, zero, val->getRVal());
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
#define LLVMDC_GEN_COMPLEX_H
|
||||
|
||||
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, long double re, long double im);
|
||||
LLConstant* DtoUndefComplex(Type* _ty);
|
||||
|
||||
LLConstant* DtoComplexShuffleMask(unsigned a, unsigned b);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
|||
else {
|
||||
assert(rt);
|
||||
Type* rtfin = DtoDType(rt);
|
||||
if (DtoIsPassedByRef(rt)) {
|
||||
if (DtoIsReturnedInArg(rt)) {
|
||||
rettype = getPtrToType(DtoType(rt));
|
||||
actualRettype = llvm::Type::VoidTy;
|
||||
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);
|
||||
|
||||
int nbyval = 0;
|
||||
|
||||
llvm::PAListPtr palist;
|
||||
|
||||
for (int i=0; i < n; ++i) {
|
||||
Argument* arg = Argument::getNth(f->parameters, i);
|
||||
// ensure scalar
|
||||
Type* argT = DtoDType(arg->type);
|
||||
assert(argT);
|
||||
|
||||
bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
|
||||
|
||||
const LLType* at = DtoType(argT);
|
||||
if (isaStruct(at)) {
|
||||
Logger::println("struct param");
|
||||
paramvec.push_back(getPtrToType(at));
|
||||
arg->llvmByVal = !refOrOut;
|
||||
}
|
||||
else if (isaArray(at)) {
|
||||
Logger::println("sarray param");
|
||||
assert(argT->ty == Tsarray);
|
||||
//paramvec.push_back(getPtrToType(at->getContainedType(0)));
|
||||
paramvec.push_back(getPtrToType(at));
|
||||
arg->llvmByVal = !refOrOut;
|
||||
}
|
||||
else if (llvm::isa<llvm::OpaqueType>(at)) {
|
||||
Logger::println("opaque param");
|
||||
|
@ -117,7 +125,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
|||
paramvec.push_back(getPtrToType(at));
|
||||
}
|
||||
else {
|
||||
if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
|
||||
if (refOrOut) {
|
||||
Logger::println("by ref param");
|
||||
at = getPtrToType(at);
|
||||
}
|
||||
|
@ -126,8 +134,13 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
|||
}
|
||||
paramvec.push_back(at);
|
||||
}
|
||||
|
||||
if (arg->llvmByVal)
|
||||
nbyval++;
|
||||
}
|
||||
|
||||
//warning("set %d byval args for type: %s", nbyval, f->toChars());
|
||||
|
||||
// construct function type
|
||||
bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
|
||||
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->llvmUsesThis = usesthis;
|
||||
|
||||
//if (!f->ir.type)
|
||||
f->ir.type = new llvm::PATypeHolder(functype);
|
||||
//else
|
||||
//assert(functype == f->ir.type->get());
|
||||
|
||||
return functype;
|
||||
}
|
||||
|
@ -378,6 +388,43 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
|||
fdecl->ir.irFunc->func = func;
|
||||
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
|
||||
if (fdecl->isMain()) {
|
||||
gIR->mainFunc = func;
|
||||
|
@ -775,19 +822,14 @@ DValue* DtoArgument(Argument* fnarg, Expression* argexp)
|
|||
else
|
||||
arg = new DImValue(argexp->type, arg->getRVal(), false);
|
||||
}
|
||||
// aggregate arg
|
||||
else if (DtoIsPassedByRef(argexp->type))
|
||||
// byval arg, but expr has no storage yet
|
||||
else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull()))
|
||||
{
|
||||
LLValue* alloc = new llvm::AllocaInst(DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
|
||||
DVarValue* vv = new DVarValue(argexp->type, alloc, true);
|
||||
DtoAssign(vv, arg);
|
||||
arg = vv;
|
||||
}
|
||||
// normal arg (basic/value type)
|
||||
else
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
|
||||
emit_finallyblocks(p, enclosingtryfinally, NULL);
|
||||
|
||||
if (gIR->func()->inVolatile) {
|
||||
if (f->inVolatile) {
|
||||
// store-load barrier
|
||||
DtoMemoryBarrier(false, false, true, false);
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
|
||||
assert(p->topfunc()->getReturnType() == llvm::Type::VoidTy);
|
||||
emit_finallyblocks(p, enclosingtryfinally, NULL);
|
||||
|
||||
if (gIR->func()->inVolatile) {
|
||||
|
@ -139,11 +139,6 @@ void ReturnStatement::toIR(IRState* p)
|
|||
if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
|
||||
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);
|
||||
std::vector<LLValue*> args;
|
||||
|
||||
Logger::cout() << *table->getType() << '\n';
|
||||
Logger::cout() << *fn->getFunctionType()->getParamType(0) << '\n';
|
||||
assert(table->getType() == fn->getFunctionType()->getParamType(0));
|
||||
args.push_back(table);
|
||||
|
||||
DValue* val = e->toElem(gIR);
|
||||
LLValue* llval;
|
||||
|
@ -636,9 +630,8 @@ static LLValue* call_string_switch_runtime(llvm::GlobalVariable* table, Expressi
|
|||
llval = val->getRVal();
|
||||
}
|
||||
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)
|
||||
|
|
|
@ -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());
|
||||
LOG_SCOPE;
|
||||
|
@ -127,7 +127,7 @@ LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned o
|
|||
assert(vd->ir.irField->index >= 0);
|
||||
if (os == vd->offset && vdtype == t) {
|
||||
idxs.push_back(vd->ir.irField->index);
|
||||
ptr = DtoGEP(ptr, idxs, "tmp");
|
||||
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
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);
|
||||
if (vd->ir.irField->indexOffset) {
|
||||
Logger::println("has union field offset");
|
||||
ptr = DtoGEP(ptr, idxs, "tmp");
|
||||
ptr = DtoGEPi(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = DtoBitCast(ptr, llt);
|
||||
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);
|
||||
}
|
||||
else {
|
||||
const LLType* sty = getPtrToType(DtoType(vd->type));
|
||||
if (ptr->getType() != sty) {
|
||||
ptr = DtoBitCast(ptr, sty);
|
||||
std::vector<unsigned> tmp;
|
||||
DStructIndexVector tmp;
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -30,7 +30,8 @@ void DtoConstInitStruct(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
|
||||
{
|
||||
|
|
|
@ -196,7 +196,7 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd)
|
|||
|
||||
void DtoDwarfStopPoint(unsigned ln)
|
||||
{
|
||||
std::vector<LLValue*> args;
|
||||
LLSmallVector<LLValue*,3> args;
|
||||
args.push_back(DtoConstUint(ln));
|
||||
args.push_back(DtoConstUint(0));
|
||||
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);
|
||||
|
||||
TypeStruct* ts = (TypeStruct*)e1next;
|
||||
std::vector<unsigned> offsets;
|
||||
DStructIndexVector offsets;
|
||||
LLValue* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets);
|
||||
return new DFieldValue(type, v, true);
|
||||
}
|
||||
|
@ -1018,7 +1018,11 @@ DValue* CallExp::toElem(IRState* p)
|
|||
|
||||
bool isInPlace = false;
|
||||
|
||||
// attrs
|
||||
llvm::PAListPtr palist;
|
||||
|
||||
// hidden struct return arguments
|
||||
// TODO: use sret param attr
|
||||
if (retinptr) {
|
||||
if (topexp && topexp->e2 == this) {
|
||||
assert(topexp->v);
|
||||
|
@ -1167,6 +1171,10 @@ DValue* CallExp::toElem(IRState* p)
|
|||
Argument* fnarg = Argument::getNth(tf->parameters, i);
|
||||
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
|
||||
llargs[j] = argval->getRVal();
|
||||
#if USE_BYVAL
|
||||
if (fnarg->llvmByVal)
|
||||
palist = palist.addAttr(j, llvm::ParamAttr::ByVal);
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
|
||||
|
@ -1187,6 +1195,11 @@ DValue* CallExp::toElem(IRState* p)
|
|||
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 :/
|
||||
if (dfn && dfn->func && dfn->func->runTimeHack) {
|
||||
if (llfnty->getParamType(j) != NULL) {
|
||||
|
@ -1245,6 +1258,9 @@ DValue* CallExp::toElem(IRState* p)
|
|||
call->setCallingConv(DtoCallingConv(dlink));
|
||||
}
|
||||
|
||||
// param attrs
|
||||
call->setParamAttrs(palist);
|
||||
|
||||
return new DImValue(type, retllval, isInPlace);
|
||||
}
|
||||
|
||||
|
@ -1311,7 +1327,7 @@ DValue* SymOffExp::toElem(IRState* p)
|
|||
varmem = p->ir->CreateBitCast(llvalue, llt, "tmp");
|
||||
}
|
||||
else {
|
||||
std::vector<unsigned> dst;
|
||||
DStructIndexVector dst;
|
||||
varmem = DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst);
|
||||
}
|
||||
}
|
||||
|
@ -1429,7 +1445,7 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||
|
||||
LLValue* src = l->getRVal();
|
||||
|
||||
std::vector<unsigned> vdoffsets;
|
||||
DStructIndexVector vdoffsets;
|
||||
arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
|
||||
}
|
||||
else if (e1type->ty == Tclass) {
|
||||
|
@ -1438,7 +1454,7 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||
|
||||
LLValue* src = l->getRVal();
|
||||
|
||||
std::vector<unsigned> vdoffsets;
|
||||
DStructIndexVector vdoffsets;
|
||||
arrptr = DtoIndexClass(src, tc->sym, vd->type, vd->offset, vdoffsets);
|
||||
|
||||
/*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());
|
||||
LOG_SCOPE;
|
||||
|
||||
DtoAssert(&loc, NULL);
|
||||
// call the new (?) trap intrinsic
|
||||
p->ir->CreateCall(GET_INTRINSIC_DECL(trap),"");
|
||||
|
||||
new llvm::UnreachableInst(p->scopebb());
|
||||
return 0;
|
||||
|
|
|
@ -26,6 +26,13 @@ bool DtoIsPassedByRef(Type* type)
|
|||
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)
|
||||
{
|
||||
if (t->ty == Ttypedef) {
|
||||
|
@ -67,9 +74,10 @@ const LLType* DtoType(Type* t)
|
|||
return llvm::Type::FloatTy;
|
||||
case Tfloat64:
|
||||
case Timaginary64:
|
||||
return llvm::Type::DoubleTy;
|
||||
case Tfloat80:
|
||||
case Timaginary80:
|
||||
return llvm::Type::DoubleTy;
|
||||
return (global.params.useFP80) ? llvm::Type::X86_FP80Ty : llvm::Type::DoubleTy;
|
||||
|
||||
// complex
|
||||
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[1] = i1;
|
||||
Logger::cout() << "DtoGEP: " << *ptr << ", " << *i0 << ", " << *i1 << '\n';
|
||||
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();
|
||||
std::vector<LLValue*> dst(n, NULL);
|
||||
//std::ostream& ostr = Logger::cout();
|
||||
//ostr << "indices for '" << *ptr << "':";
|
||||
for (size_t i=0; i<n; ++i)
|
||||
{
|
||||
//ostr << ' ' << i;
|
||||
dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
|
||||
}
|
||||
//ostr << '\n';*/
|
||||
LLSmallVector<LLValue*, 3> dst(n);
|
||||
|
||||
size_t j=0;
|
||||
for (DStructIndexVector::const_iterator i=src.begin(); i!=src.end(); ++i)
|
||||
dst[j++] = DtoConstUint(*i);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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);
|
||||
v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false);
|
||||
v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false);
|
||||
LLSmallVector<LLValue*,2> v(2);
|
||||
v[0] = DtoConstUint(i0);
|
||||
v[1] = DtoConstUint(i1);
|
||||
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
|
||||
LLConstant* ti = DtoTypeInfoOf(newtype);
|
||||
assert(isaPointer(ti));
|
||||
// call runtime
|
||||
LLSmallVector<LLValue*,1> arg;
|
||||
arg.push_back(ti);
|
||||
// allocate
|
||||
LLValue* mem = gIR->ir->CreateCall(fn, arg.begin(), arg.end(), ".gc_mem");
|
||||
// call runtime allocator
|
||||
LLValue* mem = gIR->ir->CreateCall(fn, ti, ".gc_mem");
|
||||
// cast
|
||||
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";
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
|
||||
|
||||
// param attrs
|
||||
llvm::PAListPtr palist;
|
||||
int idx = 1;
|
||||
|
||||
c = DtoConstString(loc->filename);
|
||||
|
||||
// msg param
|
||||
|
@ -727,6 +732,7 @@ void DtoAssert(Loc* loc, DValue* msg)
|
|||
{
|
||||
args.push_back(msg->getRVal());
|
||||
}
|
||||
palist = palist.addAttr(idx++, llvm::ParamAttr::ByVal);
|
||||
}
|
||||
|
||||
// file param
|
||||
|
@ -740,7 +746,10 @@ void DtoAssert(Loc* loc, DValue* msg)
|
|||
DtoStore(c->getOperand(0), ptr);
|
||||
ptr = DtoGEPi(alloc, 0,1, "tmp");
|
||||
DtoStore(c->getOperand(1), ptr);
|
||||
|
||||
args.push_back(alloc);
|
||||
palist = palist.addAttr(idx++, llvm::ParamAttr::ByVal);
|
||||
|
||||
|
||||
// line param
|
||||
c = DtoConstUint(loc->linnum);
|
||||
|
@ -748,6 +757,7 @@ void DtoAssert(Loc* loc, DValue* msg)
|
|||
|
||||
// call
|
||||
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 "declaration.h"
|
||||
|
||||
#include "gen/structs.h"
|
||||
|
||||
// D->LLVM type handling stuff
|
||||
const LLType* DtoType(Type* t);
|
||||
bool DtoIsPassedByRef(Type* type);
|
||||
bool DtoIsReturnedInArg(Type* type);
|
||||
|
||||
// resolve typedefs to their real type.
|
||||
// TODO should probably be removed in favor of DMD's Type::toBasetype
|
||||
|
@ -54,10 +57,10 @@ llvm::Function* LLVM_DeclareMemCpy32();
|
|||
llvm::Function* LLVM_DeclareMemCpy64();
|
||||
|
||||
// getelementptr helpers
|
||||
LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const std::string& 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, unsigned i0, const std::string& var, llvm::BasicBlock* bb=NULL);
|
||||
LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned 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* DtoGEPi(LLValue* ptr, const DStructIndexVector& src, const char* 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 char* var, llvm::BasicBlock* bb=NULL);
|
||||
|
||||
// dynamic memory helpers
|
||||
LLValue* DtoNew(Type* newtype);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "llvm/Bitcode/ReaderWriter.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetMachineRegistry.h"
|
||||
#include "llvm/System/Path.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "module.h"
|
||||
|
@ -151,17 +152,36 @@ void Module::genobjfile()
|
|||
// run optimizer
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// disassemble ?
|
||||
if (global.params.disassemble) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -749,7 +749,9 @@ tangotests/a.d
|
|||
tangotests/aa1.d
|
||||
tangotests/aa2.d
|
||||
tangotests/align1.d
|
||||
tangotests/arrays1.d
|
||||
tangotests/b.d
|
||||
tangotests/byval1.d
|
||||
tangotests/c.d
|
||||
tangotests/classes1.d
|
||||
tangotests/constructors.d
|
||||
|
|
|
@ -47,6 +47,7 @@ private
|
|||
{
|
||||
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 )
|
||||
{
|
||||
//printf("scanning static data from %p to %p\n", &__data_start, &_end);
|
||||
scan( &__data_start, &_end );
|
||||
}
|
||||
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
|
||||
echo "Testing with llvmdc. Set DMD environment variable to select compiler."
|
||||
DMD="llvmdc"
|
||||
DMD="llvmdc -O0"
|
||||
else
|
||||
echo "Using compiler given by DMD environment variable: $DMD"
|
||||
fi
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue