mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-26 08:33:14 +01:00
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
In particular, assertions has been fixed to include file/line info, and much more!
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
|
||||
[Environment]
|
||||
|
||||
DFLAGS=-I%@P%/../tango -E%@P%/../lib -L-L=%@P%/../lib
|
||||
DFLAGS=-I%@P%/../tango -L-L%@P%/../lib -R%@P%/../lib
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
[Environment]
|
||||
|
||||
DFLAGS=-I%@P%/../lphobos -E%@P%/../lib -L-L=%@P%/../lib
|
||||
DFLAGS=-I%@P%/../lphobos -L-L%@P%/../lib -R%@P%/../lib
|
||||
|
||||
16
dmd/link.c
16
dmd/link.c
@@ -283,14 +283,18 @@ int runLINK()
|
||||
* passed with -l.
|
||||
*/
|
||||
|
||||
//argv.push((void *)"-lphobos"); // turns into /usr/lib/libphobos.a
|
||||
argv.push((void *)"-lpthread");
|
||||
argv.push((void *)"-lm");
|
||||
argv.push((void*)"-ltango-base-c-llvmdc");
|
||||
argv.push((void*)"-lpthread");
|
||||
argv.push((void*)"-ldl");
|
||||
argv.push((void*)"-lm");
|
||||
|
||||
std::string corelibpath = global.params.runtimeImppath;
|
||||
corelibpath.append("/libtango-base-llvmdc.a");
|
||||
argv.append(global.params.objfiles);
|
||||
argv.push((void *)corelibpath.c_str());
|
||||
|
||||
std::string runtime_path(global.params.runtimePath);
|
||||
if (*runtime_path.rbegin() != '/')
|
||||
runtime_path.append("/");
|
||||
runtime_path.append("libtango-base-llvmdc.a");
|
||||
argv.push((void*)runtime_path.c_str());
|
||||
|
||||
if (!global.params.quiet)
|
||||
{
|
||||
|
||||
20
dmd/mars.c
20
dmd/mars.c
@@ -158,7 +158,7 @@ extern void backend_term();
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf("LLVM D Compiler %s (based on DMD %s)\n%s\n%s\n",
|
||||
printf("LLVM D Compiler %s (based on DMD %s and LLVM 2.2)\n%s\n%s\n",
|
||||
global.llvmdc_version, global.version, global.copyright, global.written);
|
||||
printf("\
|
||||
D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\
|
||||
@@ -187,7 +187,6 @@ Usage:\n\
|
||||
-Hf<filename> write 'header' file to <filename>\n\
|
||||
--help print help\n\
|
||||
-I<path> where to look for imports\n\
|
||||
-E<path> where to look for the core runtime\n\
|
||||
-J<path> where to look for string imports\n\
|
||||
-inline do function inlining\n\
|
||||
-Llinkerflag pass linkerflag to link\n\
|
||||
@@ -206,6 +205,7 @@ Usage:\n\
|
||||
-quiet suppress unnecessary messages\n\
|
||||
-release compile release version\n\
|
||||
-run srcfile args... run resulting program, passing args\n\
|
||||
-R<path> provide path to the directory containing the runtime library\n\
|
||||
-unittest compile in unit tests\n\
|
||||
-v verbose\n\
|
||||
-vv very verbose (does not include -v)\n\
|
||||
@@ -386,15 +386,15 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
else if (strcmp(p + 1, "forcebe") == 0)
|
||||
global.params.forceBE = 1;
|
||||
global.params.forceBE = 1;
|
||||
else if (strcmp(p + 1, "noruntime") == 0)
|
||||
global.params.noruntime = 1;
|
||||
global.params.noruntime = 1;
|
||||
else if (strcmp(p + 1, "noverify") == 0)
|
||||
global.params.novalidate = 1;
|
||||
global.params.novalidate = 1;
|
||||
else if (strcmp(p + 1, "dis") == 0)
|
||||
global.params.disassemble = 1;
|
||||
global.params.disassemble = 1;
|
||||
else if (strcmp(p + 1, "annotate") == 0)
|
||||
global.params.llvmAnnotate = 1;
|
||||
global.params.llvmAnnotate = 1;
|
||||
else if (p[1] == 'o')
|
||||
{
|
||||
switch (p[2])
|
||||
@@ -503,9 +503,9 @@ int main(int argc, char *argv[])
|
||||
global.params.fileImppath = new Array();
|
||||
global.params.fileImppath->push(p + 2);
|
||||
}
|
||||
else if (p[1] == 'E')
|
||||
else if (p[1] == 'R')
|
||||
{
|
||||
global.params.runtimeImppath = p+2;
|
||||
global.params.runtimePath = p+2;
|
||||
}
|
||||
else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l')
|
||||
{
|
||||
@@ -671,7 +671,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (global.params.llvmArch == 0) {
|
||||
std::string err_str;
|
||||
const llvm::TargetMachineRegistry::Entry* e = llvm::TargetMachineRegistry::getClosestTargetForJIT(err_str);
|
||||
const llvm::TargetMachineRegistry::entry* e = llvm::TargetMachineRegistry::getClosestTargetForJIT(err_str);
|
||||
if (e == 0) {
|
||||
error("Failed to find a default target machine: %s", err_str.c_str());
|
||||
fatal();
|
||||
|
||||
@@ -131,6 +131,7 @@ struct Param
|
||||
char disassemble;
|
||||
char llvmInline;
|
||||
char llvmAnnotate;
|
||||
char *runtimePath;
|
||||
};
|
||||
|
||||
struct Global
|
||||
|
||||
@@ -86,7 +86,7 @@ DValue* DtoAAIndex(Type* type, DValue* aa, DValue* key)
|
||||
pkey = DtoBitCast(pkey, funcTy->getParamType(2));
|
||||
|
||||
// valuesize param
|
||||
llvm::Value* valsize = DtoConstSize_t(gTargetData->getTypeSize(DtoType(type)));
|
||||
llvm::Value* valsize = DtoConstSize_t(getABITypeSize(DtoType(type)));
|
||||
|
||||
// build arg vector
|
||||
std::vector<llvm::Value*> args;
|
||||
@@ -99,7 +99,7 @@ DValue* DtoAAIndex(Type* type, DValue* aa, DValue* key)
|
||||
llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "aa.index");
|
||||
|
||||
// cast return value
|
||||
const llvm::Type* targettype = llvm::PointerType::get(DtoType(type));
|
||||
const llvm::Type* targettype = getPtrToType(DtoType(type));
|
||||
if (ret->getType() != targettype)
|
||||
ret = DtoBitCast(ret, targettype);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ const llvm::StructType* DtoArrayType(Type* t)
|
||||
if (at == llvm::Type::VoidTy) {
|
||||
at = llvm::Type::Int8Ty;
|
||||
}
|
||||
arrty = llvm::PointerType::get(at);
|
||||
arrty = getPtrToType(at);
|
||||
|
||||
std::vector<const llvm::Type*> members;
|
||||
if (global.params.is64bit)
|
||||
@@ -98,7 +98,7 @@ void DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
|
||||
Logger::cout() << "invalid: " << *src << '\n';
|
||||
assert(0);
|
||||
}
|
||||
llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
|
||||
const llvm::Type* dstty = getPtrToType(arrty->getElementType());
|
||||
|
||||
llvm::Value* dstlen = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
|
||||
llvm::Value* srclen = DtoConstSize_t(arrty->getNumElements());
|
||||
@@ -161,10 +161,10 @@ void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
|
||||
llvm::Constant* c = isaConstant(dim);
|
||||
assert(c);
|
||||
dim = llvm::ConstantExpr::getMul(c, DtoConstSize_t(arrsz));
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp");
|
||||
ptr = gIR->ir->CreateBitCast(ptr, getPtrToType(finalTy), "tmp");
|
||||
}
|
||||
else if (isaStruct(t)) {
|
||||
aggrsz = gTargetData->getTypeSize(t);
|
||||
aggrsz = getABITypeSize(t);
|
||||
llvm::Constant* c = isaConstant(val);
|
||||
if (c && c->isNullValue()) {
|
||||
llvm::Value* nbytes;
|
||||
@@ -176,7 +176,7 @@ void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
|
||||
ptr = gIR->ir->CreateBitCast(ptr, getPtrToType(llvm::Type::Int8Ty), "tmp");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -199,11 +199,11 @@ void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
|
||||
else if (isaPointer(t)) {
|
||||
funcname = "_d_array_init_pointer";
|
||||
|
||||
const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
const llvm::Type* dstty = getPtrToType(getPtrToType(llvm::Type::Int8Ty));
|
||||
if (args[0]->getType() != dstty)
|
||||
args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb());
|
||||
|
||||
const llvm::Type* valty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::Type* valty = getPtrToType(llvm::Type::Int8Ty);
|
||||
if (args[2]->getType() != valty)
|
||||
args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb());
|
||||
}
|
||||
@@ -365,7 +365,7 @@ static llvm::Value* get_slice_ptr(DSliceValue* e, llvm::Value*& sz)
|
||||
// this means it's a real slice
|
||||
ret = e->ptr;
|
||||
|
||||
size_t elembsz = gTargetData->getTypeSize(ret->getType());
|
||||
size_t elembsz = getABITypeSize(ret->getType());
|
||||
llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
|
||||
|
||||
if (isaConstantInt(e->len)) {
|
||||
@@ -378,7 +378,7 @@ static llvm::Value* get_slice_ptr(DSliceValue* e, llvm::Value*& sz)
|
||||
else if (isaArray(t)) {
|
||||
ret = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb());
|
||||
|
||||
size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0));
|
||||
size_t elembsz = getABITypeSize(ret->getType()->getContainedType(0));
|
||||
llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
|
||||
|
||||
size_t numelements = isaArray(t)->getNumElements();
|
||||
@@ -390,7 +390,7 @@ static llvm::Value* get_slice_ptr(DSliceValue* e, llvm::Value*& sz)
|
||||
ret = DtoGEPi(e->ptr, 0, 1, "tmp", gIR->scopebb());
|
||||
ret = new llvm::LoadInst(ret, "tmp", gIR->scopebb());
|
||||
|
||||
size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0));
|
||||
size_t elembsz = getABITypeSize(ret->getType()->getContainedType(0));
|
||||
llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
|
||||
|
||||
llvm::Value* len = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb());
|
||||
@@ -405,7 +405,7 @@ static llvm::Value* get_slice_ptr(DSliceValue* e, llvm::Value*& sz)
|
||||
|
||||
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
|
||||
{
|
||||
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* sz1;
|
||||
llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb());
|
||||
@@ -426,7 +426,7 @@ void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
|
||||
|
||||
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
|
||||
{
|
||||
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* sz1;
|
||||
llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb());
|
||||
@@ -447,10 +447,10 @@ void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
|
||||
void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src)
|
||||
{
|
||||
assert(dst->getType() == src->getType());
|
||||
size_t arrsz = gTargetData->getTypeSize(dst->getType()->getContainedType(0));
|
||||
size_t arrsz = getABITypeSize(dst->getType()->getContainedType(0));
|
||||
llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(), arrsz, false);
|
||||
|
||||
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
|
||||
llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb());
|
||||
|
||||
@@ -483,11 +483,11 @@ llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool
|
||||
{
|
||||
const llvm::Type* ty = DtoType(dty);
|
||||
assert(ty != llvm::Type::VoidTy);
|
||||
size_t sz = gTargetData->getTypeSize(ty);
|
||||
size_t sz = getABITypeSize(ty);
|
||||
llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false);
|
||||
llvm::Value* bytesize = (sz == 1) ? dim : llvm::BinaryOperator::createMul(n,dim,"tmp",gIR->scopebb());
|
||||
|
||||
llvm::Value* nullptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(ty));
|
||||
llvm::Value* nullptr = llvm::ConstantPointerNull::get(getPtrToType(ty));
|
||||
|
||||
llvm::Value* newptr = DtoRealloc(nullptr, bytesize);
|
||||
|
||||
@@ -510,7 +510,7 @@ llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz)
|
||||
llvm::Value* ptr = DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb());
|
||||
llvm::Value* ptrld = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
|
||||
|
||||
size_t isz = gTargetData->getTypeSize(ptrld->getType()->getContainedType(0));
|
||||
size_t isz = getABITypeSize(ptrld->getType()->getContainedType(0));
|
||||
llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), isz, false);
|
||||
llvm::Value* bytesz = (isz == 1) ? sz : llvm::BinaryOperator::createMul(n,sz,"tmp",gIR->scopebb());
|
||||
|
||||
@@ -758,8 +758,8 @@ llvm::Value* DtoArrayCompare(TOK op, DValue* l, DValue* r)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty)
|
||||
{
|
||||
size_t esz = gTargetData->getTypeSize(elemty);
|
||||
size_t nsz = gTargetData->getTypeSize(newelemty);
|
||||
size_t esz = getABITypeSize(elemty);
|
||||
size_t nsz = getABITypeSize(newelemty);
|
||||
if (esz == nsz)
|
||||
return len;
|
||||
|
||||
@@ -898,14 +898,14 @@ DValue* DtoCastArray(DValue* u, Type* to)
|
||||
llvm::Value* ptr = DtoGEPi(u->getRVal(),0,1,"tmp",gIR->scopebb());
|
||||
rval = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
|
||||
if (fromtype->next != totype->next)
|
||||
rval = gIR->ir->CreateBitCast(rval, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
|
||||
rval = gIR->ir->CreateBitCast(rval, getPtrToType(llvm::Type::Int8Ty), "tmp");
|
||||
}
|
||||
else if (totype->ty == Tarray) {
|
||||
Logger::cout() << "to array" << '\n';
|
||||
const llvm::Type* ptrty = DtoType(totype->next);
|
||||
if (ptrty == llvm::Type::VoidTy)
|
||||
ptrty = llvm::Type::Int8Ty;
|
||||
ptrty = llvm::PointerType::get(ptrty);
|
||||
ptrty = getPtrToType(ptrty);
|
||||
|
||||
const llvm::Type* ety = DtoType(fromtype->next);
|
||||
if (ety == llvm::Type::VoidTy)
|
||||
|
||||
594
gen/classes.cpp
594
gen/classes.cpp
@@ -56,7 +56,21 @@ void DtoResolveClass(ClassDeclaration* cd)
|
||||
if (cd->llvmResolved) return;
|
||||
cd->llvmResolved = true;
|
||||
|
||||
// first resolve the base class
|
||||
Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// get the TypeClass
|
||||
assert(cd->type->ty == Tclass);
|
||||
TypeClass* ts = (TypeClass*)cd->type;
|
||||
|
||||
// make sure the IRStruct is created
|
||||
IRStruct* irstruct = cd->llvmIRStruct;
|
||||
if (!irstruct) {
|
||||
irstruct = new IRStruct(ts);
|
||||
cd->llvmIRStruct = irstruct;
|
||||
}
|
||||
|
||||
// resolve the base class
|
||||
if (cd->baseClass) {
|
||||
DtoResolveClass(cd->baseClass);
|
||||
}
|
||||
@@ -72,28 +86,18 @@ void DtoResolveClass(ClassDeclaration* cd)
|
||||
}
|
||||
}
|
||||
|
||||
Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(cd->type->ty == Tclass);
|
||||
TypeClass* ts = (TypeClass*)cd->type;
|
||||
|
||||
assert(!cd->llvmIRStruct);
|
||||
IRStruct* irstruct = new IRStruct(ts);
|
||||
cd->llvmIRStruct = irstruct;
|
||||
|
||||
gIR->structs.push_back(irstruct);
|
||||
gIR->classes.push_back(cd);
|
||||
|
||||
// add vtable
|
||||
ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get());
|
||||
const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get());
|
||||
const llvm::Type* vtabty = getPtrToType(ts->llvmVtblType->get());
|
||||
|
||||
std::vector<const llvm::Type*> fieldtypes;
|
||||
fieldtypes.push_back(vtabty);
|
||||
|
||||
// add monitor
|
||||
fieldtypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
fieldtypes.push_back(getPtrToType(llvm::Type::Int8Ty));
|
||||
|
||||
// add interface vtables
|
||||
if (cd->vtblInterfaces)
|
||||
@@ -103,7 +107,7 @@ void DtoResolveClass(ClassDeclaration* cd)
|
||||
ClassDeclaration *id = b->base;
|
||||
assert(id->type->ty == Tclass);
|
||||
TypeClass* itc = (TypeClass*)id->type;
|
||||
const llvm::Type* ivtblTy = llvm::PointerType::get(itc->llvmVtblType->get());
|
||||
const llvm::Type* ivtblTy = getPtrToType(itc->llvmVtblType->get());
|
||||
fieldtypes.push_back(ivtblTy);
|
||||
|
||||
// add this interface to the map
|
||||
@@ -142,12 +146,12 @@ void DtoResolveClass(ClassDeclaration* cd)
|
||||
lastoffset = i->first;
|
||||
fieldtype = i->second.type;
|
||||
fieldinit = i->second.var;
|
||||
prevsize = gTargetData->getTypeSize(fieldtype);
|
||||
prevsize = getABITypeSize(fieldtype);
|
||||
i->second.var->llvmFieldIndex = idx;
|
||||
}
|
||||
// colliding offset?
|
||||
else if (lastoffset == i->first) {
|
||||
size_t s = gTargetData->getTypeSize(i->second.type);
|
||||
size_t s = getABITypeSize(i->second.type);
|
||||
if (s > prevsize) {
|
||||
fieldpad += s - prevsize;
|
||||
prevsize = s;
|
||||
@@ -157,7 +161,7 @@ void DtoResolveClass(ClassDeclaration* cd)
|
||||
}
|
||||
// intersecting offset?
|
||||
else if (i->first < (lastoffset + prevsize)) {
|
||||
size_t s = gTargetData->getTypeSize(i->second.type);
|
||||
size_t s = getABITypeSize(i->second.type);
|
||||
assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
|
||||
cd->llvmHasUnions = true;
|
||||
i->second.var->llvmFieldIndex = idx;
|
||||
@@ -180,7 +184,7 @@ void DtoResolveClass(ClassDeclaration* cd)
|
||||
lastoffset = i->first;
|
||||
fieldtype = i->second.type;
|
||||
fieldinit = i->second.var;
|
||||
prevsize = gTargetData->getTypeSize(fieldtype);
|
||||
prevsize = getABITypeSize(fieldtype);
|
||||
i->second.var->llvmFieldIndex = idx;
|
||||
fieldpad = 0;
|
||||
}
|
||||
@@ -212,6 +216,7 @@ void DtoResolveClass(ClassDeclaration* cd)
|
||||
ts->llvmType = new llvm::PATypeHolder(structtype);
|
||||
else
|
||||
*ts->llvmType = structtype;
|
||||
spa = *ts->llvmType;
|
||||
|
||||
// name the type
|
||||
gIR->module->addTypeName(cd->mangle(), ts->llvmType->get());
|
||||
@@ -221,11 +226,11 @@ void DtoResolveClass(ClassDeclaration* cd)
|
||||
// ClassInfo classinfo
|
||||
ClassDeclaration* cinfod = ClassDeclaration::classinfo;
|
||||
DtoResolveClass(cinfod);
|
||||
infoTypes.push_back(llvm::PointerType::get(cinfod->type->llvmType->get()));
|
||||
infoTypes.push_back(getPtrToType(cinfod->type->llvmType->get()));
|
||||
// void*[] vtbl
|
||||
std::vector<const llvm::Type*> infoVtbltypes;
|
||||
infoVtbltypes.push_back(DtoSize_t());
|
||||
const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty));
|
||||
infoVtbltypes.push_back(byteptrptrty);
|
||||
infoTypes.push_back(llvm::StructType::get(infoVtbltypes));
|
||||
// int offset
|
||||
@@ -247,9 +252,9 @@ void DtoResolveClass(ClassDeclaration* cd)
|
||||
DtoResolveFunction(fd);
|
||||
//assert(fd->type->ty == Tfunction);
|
||||
//TypeFunction* tf = (TypeFunction*)fd->type;
|
||||
//const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get());
|
||||
//const llvm::Type* fpty = getPtrToType(tf->llvmType->get());
|
||||
const llvm::FunctionType* vfty = DtoBaseFunctionType(fd);
|
||||
const llvm::Type* vfpty = llvm::PointerType::get(vfty);
|
||||
const llvm::Type* vfpty = getPtrToType(vfty);
|
||||
sinits_ty.push_back(vfpty);
|
||||
}
|
||||
else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
|
||||
@@ -266,7 +271,7 @@ void DtoResolveClass(ClassDeclaration* cd)
|
||||
// this is the ClassInfo class, the type is this type
|
||||
cinfoty = ts->llvmType->get();
|
||||
}
|
||||
const llvm::Type* cty = llvm::PointerType::get(cinfoty);
|
||||
const llvm::Type* cty = getPtrToType(cinfoty);
|
||||
sinits_ty.push_back(cty);
|
||||
}
|
||||
else
|
||||
@@ -314,8 +319,9 @@ void DtoDeclareClass(ClassDeclaration* cd)
|
||||
}
|
||||
|
||||
// interface vtables are emitted by the class implementing them
|
||||
// also interfaces have no static initializer
|
||||
if (!cd->isInterfaceDeclaration()) {
|
||||
// also, interfaces have no static initializer
|
||||
// also, abstract classes have no vtable
|
||||
if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) {
|
||||
// vtable
|
||||
std::string varname("_D");
|
||||
varname.append(cd->mangle());
|
||||
@@ -331,11 +337,11 @@ void DtoDeclareClass(ClassDeclaration* cd)
|
||||
// ClassInfo classinfo
|
||||
ClassDeclaration* cd2 = ClassDeclaration::classinfo;
|
||||
DtoResolveClass(cd2);
|
||||
types.push_back(llvm::PointerType::get(cd2->type->llvmType->get()));
|
||||
types.push_back(getPtrToType(cd2->type->llvmType->get()));
|
||||
// void*[] vtbl
|
||||
std::vector<const llvm::Type*> vtbltypes;
|
||||
vtbltypes.push_back(DtoSize_t());
|
||||
const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty));
|
||||
vtbltypes.push_back(byteptrptrty);
|
||||
types.push_back(llvm::StructType::get(vtbltypes));
|
||||
// int offset
|
||||
@@ -418,6 +424,12 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
||||
gIR->structs.push_back(irstruct);
|
||||
gIR->classes.push_back(cd);
|
||||
|
||||
// get the struct (class) type
|
||||
assert(cd->type->ty == Tclass);
|
||||
TypeClass* ts = (TypeClass*)cd->type;
|
||||
const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
|
||||
const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get());
|
||||
|
||||
// make sure each offset knows its default initializer
|
||||
for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i)
|
||||
{
|
||||
@@ -431,11 +443,24 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
||||
std::vector<llvm::Constant*> fieldinits;
|
||||
|
||||
// first field is always the vtable
|
||||
assert(cd->llvmVtbl != 0);
|
||||
fieldinits.push_back(cd->llvmVtbl);
|
||||
if (cd->isAbstract())
|
||||
{
|
||||
fieldinits.push_back(
|
||||
llvm::ConstantPointerNull::get(
|
||||
getPtrToType(
|
||||
ts->llvmVtblType->get()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(cd->llvmVtbl != 0);
|
||||
fieldinits.push_back(cd->llvmVtbl);
|
||||
}
|
||||
|
||||
// then comes monitor
|
||||
fieldinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
fieldinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
|
||||
|
||||
size_t dataoffset = 2;
|
||||
|
||||
@@ -443,9 +468,16 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
||||
for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
|
||||
{
|
||||
IRInterface* iri = i->second;
|
||||
assert(iri->vtbl);
|
||||
fieldinits.push_back(iri->vtbl);
|
||||
++dataoffset;
|
||||
if (cd->isAbstract())
|
||||
{
|
||||
fieldinits.push_back(llvm::Constant::getNullValue(iri->vtblTy));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(iri->vtbl);
|
||||
fieldinits.push_back(iri->vtbl);
|
||||
++dataoffset;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -456,12 +488,6 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
||||
}
|
||||
*/
|
||||
|
||||
// get the struct (class) type
|
||||
assert(cd->type->ty == Tclass);
|
||||
TypeClass* ts = (TypeClass*)cd->type;
|
||||
const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
|
||||
const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get());
|
||||
|
||||
// go through the field inits and build the default initializer
|
||||
size_t nfi = irstruct->defaultFields.size();
|
||||
for (size_t i=0; i<nfi; ++i) {
|
||||
@@ -495,111 +521,115 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
||||
assert(_init);
|
||||
cd->llvmConstInit = _init;
|
||||
|
||||
// generate vtable initializer
|
||||
std::vector<llvm::Constant*> sinits;
|
||||
|
||||
for (int k=0; k < cd->vtbl.dim; k++)
|
||||
// abstract classes have no static vtable
|
||||
if (!cd->isAbstract())
|
||||
{
|
||||
Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k];
|
||||
assert(dsym);
|
||||
//Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
|
||||
// generate vtable initializer
|
||||
std::vector<llvm::Constant*> sinits;
|
||||
|
||||
if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
|
||||
DtoForceDeclareDsymbol(fd);
|
||||
assert(fd->llvmValue);
|
||||
llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
|
||||
// cast if necessary (overridden method)
|
||||
if (c->getType() != vtbltype->getElementType(k))
|
||||
c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k));
|
||||
sinits.push_back(c);
|
||||
}
|
||||
else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
|
||||
assert(cd->llvmClass);
|
||||
llvm::Constant* c = cd->llvmClass;
|
||||
sinits.push_back(c);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
for (int k=0; k < cd->vtbl.dim; k++)
|
||||
{
|
||||
Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k];
|
||||
assert(dsym);
|
||||
//Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
|
||||
|
||||
const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
|
||||
if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
|
||||
DtoForceDeclareDsymbol(fd);
|
||||
assert(fd->llvmValue);
|
||||
llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
|
||||
// cast if necessary (overridden method)
|
||||
if (c->getType() != vtbltype->getElementType(k))
|
||||
c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k));
|
||||
sinits.push_back(c);
|
||||
}
|
||||
else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
|
||||
assert(cd->llvmClass);
|
||||
llvm::Constant* c = cd->llvmClass;
|
||||
sinits.push_back(c);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
|
||||
|
||||
#if 0
|
||||
for (size_t i=0; i< sinits.size(); ++i)
|
||||
{
|
||||
Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n';
|
||||
Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n';
|
||||
assert(svtbl_ty->getElementType(i) == sinits[i]->getType());
|
||||
}
|
||||
#endif
|
||||
|
||||
llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits);
|
||||
cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit);
|
||||
|
||||
// create interface vtable const initalizers
|
||||
int idx = 2;
|
||||
int idxScale = PTRSIZE;
|
||||
for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
|
||||
{
|
||||
ClassDeclaration* id = i->first;
|
||||
assert(id->type->ty == Tclass);
|
||||
TypeClass* its = (TypeClass*)id->type;
|
||||
|
||||
IRInterface* iri = i->second;
|
||||
BaseClass* b = iri->base;
|
||||
|
||||
const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get());
|
||||
|
||||
// generate interface info initializer
|
||||
std::vector<llvm::Constant*> infoInits;
|
||||
// classinfo
|
||||
assert(id->llvmClass);
|
||||
llvm::Constant* c = id->llvmClass;
|
||||
infoInits.push_back(c);
|
||||
// vtbl
|
||||
const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty);
|
||||
c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c);
|
||||
infoInits.push_back(c);
|
||||
// offset
|
||||
infoInits.push_back(DtoConstInt(idx*idxScale));
|
||||
// create interface info initializer constant
|
||||
iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits));
|
||||
|
||||
// generate vtable initializer
|
||||
std::vector<llvm::Constant*> iinits;
|
||||
|
||||
// add interface info
|
||||
iinits.push_back(iri->info);
|
||||
|
||||
for (int k=1; k < b->vtbl.dim; k++)
|
||||
for (size_t i=0; i< sinits.size(); ++i)
|
||||
{
|
||||
Logger::println("interface vtbl const init nr. %d", k);
|
||||
Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k];
|
||||
FuncDeclaration* fd = dsym->isFuncDeclaration();
|
||||
assert(fd);
|
||||
DtoForceDeclareDsymbol(fd);
|
||||
assert(fd->llvmValue);
|
||||
llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
|
||||
// we have to bitcast, as the type created in ResolveClass expects a different this type
|
||||
c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k));
|
||||
iinits.push_back(c);
|
||||
}
|
||||
|
||||
#if 1
|
||||
for (size_t x=0; x< iinits.size(); ++x)
|
||||
{
|
||||
Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n";
|
||||
Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n";
|
||||
assert(ivtbl_ty->getElementType(x) == iinits[x]->getType());
|
||||
Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n';
|
||||
Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n';
|
||||
assert(svtbl_ty->getElementType(i) == sinits[i]->getType());
|
||||
}
|
||||
#endif
|
||||
|
||||
llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits);
|
||||
iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit);
|
||||
llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits);
|
||||
cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit);
|
||||
|
||||
idx++;
|
||||
}
|
||||
// create interface vtable const initalizers
|
||||
int idx = 2;
|
||||
int idxScale = PTRSIZE;
|
||||
for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
|
||||
{
|
||||
ClassDeclaration* id = i->first;
|
||||
assert(id->type->ty == Tclass);
|
||||
TypeClass* its = (TypeClass*)id->type;
|
||||
|
||||
IRInterface* iri = i->second;
|
||||
BaseClass* b = iri->base;
|
||||
|
||||
const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get());
|
||||
|
||||
// generate interface info initializer
|
||||
std::vector<llvm::Constant*> infoInits;
|
||||
// classinfo
|
||||
assert(id->llvmClass);
|
||||
llvm::Constant* c = id->llvmClass;
|
||||
infoInits.push_back(c);
|
||||
// vtbl
|
||||
const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty));
|
||||
c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty);
|
||||
c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c);
|
||||
infoInits.push_back(c);
|
||||
// offset
|
||||
infoInits.push_back(DtoConstInt(idx*idxScale));
|
||||
// create interface info initializer constant
|
||||
iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits));
|
||||
|
||||
// generate vtable initializer
|
||||
std::vector<llvm::Constant*> iinits;
|
||||
|
||||
// add interface info
|
||||
iinits.push_back(iri->info);
|
||||
|
||||
for (int k=1; k < b->vtbl.dim; k++)
|
||||
{
|
||||
Logger::println("interface vtbl const init nr. %d", k);
|
||||
Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k];
|
||||
FuncDeclaration* fd = dsym->isFuncDeclaration();
|
||||
assert(fd);
|
||||
DtoForceDeclareDsymbol(fd);
|
||||
assert(fd->llvmValue);
|
||||
llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
|
||||
// we have to bitcast, as the type created in ResolveClass expects a different this type
|
||||
c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k));
|
||||
iinits.push_back(c);
|
||||
}
|
||||
|
||||
#if 1
|
||||
for (size_t x=0; x< iinits.size(); ++x)
|
||||
{
|
||||
Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n";
|
||||
Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n";
|
||||
assert(ivtbl_ty->getElementType(x) == iinits[x]->getType());
|
||||
}
|
||||
#endif
|
||||
|
||||
llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits);
|
||||
iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit);
|
||||
|
||||
idx++;
|
||||
}
|
||||
} // !abstract
|
||||
|
||||
gIR->classes.pop_back();
|
||||
gIR->structs.pop_back();
|
||||
@@ -621,7 +651,9 @@ void DtoDefineClass(ClassDeclaration* cd)
|
||||
|
||||
if (cd->getModule() == gIR->dmodule) {
|
||||
// interfaces don't have initializers
|
||||
if (!cd->isInterfaceDeclaration()) {
|
||||
// neither do abstract classes
|
||||
if (!cd->isInterfaceDeclaration() && !cd->isAbstract())
|
||||
{
|
||||
cd->llvmInit->setInitializer(cd->llvmConstInit);
|
||||
cd->llvmVtbl->setInitializer(cd->llvmConstVtbl);
|
||||
|
||||
@@ -635,7 +667,8 @@ void DtoDefineClass(ClassDeclaration* cd)
|
||||
infoInits.push_back(iri->infoInit);
|
||||
}
|
||||
// initialize interface info array
|
||||
if (!infoInits.empty()) {
|
||||
if (!infoInits.empty())
|
||||
{
|
||||
llvm::Constant* arrInit = llvm::ConstantArray::get(irstruct->interfaceInfosTy, infoInits);
|
||||
irstruct->interfaceInfos->setInitializer(arrInit);
|
||||
}
|
||||
@@ -648,6 +681,141 @@ void DtoDefineClass(ClassDeclaration* cd)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue* DtoNewClass(TypeClass* tc, NewExp* newexp)
|
||||
{
|
||||
// resolve type
|
||||
DtoForceDeclareDsymbol(tc->sym);
|
||||
|
||||
// allocate
|
||||
llvm::Value* mem;
|
||||
if (newexp->onstack)
|
||||
{
|
||||
mem = new llvm::AllocaInst(DtoType(tc)->getContainedType(0), "newclass_alloca", gIR->topallocapoint());
|
||||
}
|
||||
else
|
||||
{
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_newclass");
|
||||
std::vector<llvm::Value*> args;
|
||||
args.push_back(tc->sym->llvmClass);
|
||||
mem = gIR->ir->CreateCall(fn, args.begin(), args.end(), "newclass_gc_alloc");
|
||||
mem = DtoBitCast(mem, DtoType(tc), "newclass_gc");
|
||||
}
|
||||
|
||||
// init
|
||||
DtoInitClass(tc, mem);
|
||||
|
||||
// init inner-class outer reference
|
||||
if (newexp->thisexp)
|
||||
{
|
||||
Logger::println("Resolving outer class");
|
||||
LOG_SCOPE;
|
||||
DValue* thisval = newexp->thisexp->toElem(gIR);
|
||||
size_t idx = 2;
|
||||
idx += tc->sym->llvmIRStruct->interfaces.size();
|
||||
llvm::Value* dst = thisval->getRVal();
|
||||
llvm::Value* src = DtoGEPi(mem,0,idx,"tmp");
|
||||
Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
|
||||
DtoStore(dst, src);
|
||||
}
|
||||
// set the context for nested classes
|
||||
else if (tc->sym->isNested())
|
||||
{
|
||||
Logger::println("Resolving nested context");
|
||||
LOG_SCOPE;
|
||||
size_t idx = 2;
|
||||
idx += tc->sym->llvmIRStruct->interfaces.size();
|
||||
llvm::Value* nest = gIR->func()->decl->llvmNested;
|
||||
if (!nest)
|
||||
nest = gIR->func()->decl->llvmThisVar;
|
||||
assert(nest);
|
||||
llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp");
|
||||
nest = DtoBitCast(nest, gep->getType()->getContainedType(0));
|
||||
DtoStore(nest, gep);
|
||||
}
|
||||
|
||||
// call constructor
|
||||
if (newexp->arguments)
|
||||
return DtoCallClassCtor(tc, newexp->member, newexp->arguments, mem);
|
||||
|
||||
// return default constructed class
|
||||
return new DImValue(tc, mem, false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoInitClass(TypeClass* tc, llvm::Value* dst)
|
||||
{
|
||||
size_t presz = 2*getABITypeSize(DtoSize_t());
|
||||
uint64_t n = getABITypeSize(tc->llvmType->get()) - presz;
|
||||
|
||||
// set vtable field seperately, this might give better optimization
|
||||
assert(tc->sym->llvmVtbl);
|
||||
DtoStore(tc->sym->llvmVtbl, DtoGEPi(dst,0,0,"vtbl"));
|
||||
|
||||
// monitor always defaults to zero
|
||||
llvm::Value* tmp = DtoGEPi(dst,0,1,"monitor");
|
||||
DtoStore(llvm::Constant::getNullValue(tmp->getType()->getContainedType(0)), tmp);
|
||||
|
||||
// done?
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
// copy the rest from the static initializer
|
||||
assert(tc->sym->llvmInit);
|
||||
assert(dst->getType() == tc->sym->llvmInit->getType());
|
||||
|
||||
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* dstarr = DtoGEPi(dst,0,2,"tmp");
|
||||
dstarr = DtoBitCast(dstarr, arrty);
|
||||
|
||||
llvm::Value* srcarr = DtoGEPi(tc->sym->llvmInit,0,2,"tmp");
|
||||
srcarr = DtoBitCast(srcarr, arrty);
|
||||
|
||||
llvm::Function* fn = LLVM_DeclareMemCpy32();
|
||||
std::vector<llvm::Value*> llargs;
|
||||
llargs.resize(4);
|
||||
llargs[0] = dstarr;
|
||||
llargs[1] = srcarr;
|
||||
llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
|
||||
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
|
||||
new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, llvm::Value* mem)
|
||||
{
|
||||
Logger::println("Calling constructor");
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(ctor);
|
||||
DtoForceDeclareDsymbol(ctor);
|
||||
llvm::Function* fn = llvm::cast<llvm::Function>(ctor->llvmValue);
|
||||
TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type);
|
||||
|
||||
std::vector<llvm::Value*> ctorargs;
|
||||
ctorargs.push_back(mem);
|
||||
for (size_t i=0; i<arguments->dim; ++i)
|
||||
{
|
||||
Expression* ex = (Expression*)arguments->data[i];
|
||||
Argument* fnarg = Argument::getNth(tf->parameters, i);
|
||||
DValue* argval = DtoArgument(fnarg, ex);
|
||||
llvm::Value* a = argval->getRVal();
|
||||
const llvm::Type* aty = fn->getFunctionType()->getParamType(i+1);
|
||||
if (a->getType() != aty)
|
||||
a = DtoBitCast(a, aty);
|
||||
ctorargs.push_back(a);
|
||||
}
|
||||
llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", gIR->scopebb());
|
||||
call->setCallingConv(DtoCallingConv(LINKd));
|
||||
|
||||
return new DImValue(type, call, false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance)
|
||||
{
|
||||
Array* arr = &tc->sym->dtors;
|
||||
@@ -661,46 +829,6 @@ void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoInitClass(TypeClass* tc, llvm::Value* dst)
|
||||
{
|
||||
assert(gIR);
|
||||
|
||||
assert(tc->llvmType);
|
||||
uint64_t size_t_size = gTargetData->getTypeSize(DtoSize_t());
|
||||
uint64_t n = gTargetData->getTypeSize(tc->llvmType->get()) - size_t_size;
|
||||
|
||||
// set vtable field
|
||||
llvm::Value* vtblvar = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
|
||||
assert(tc->sym->llvmVtbl);
|
||||
new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb());
|
||||
|
||||
// copy the static initializer
|
||||
if (n > 0) {
|
||||
assert(tc->sym->llvmInit);
|
||||
assert(dst->getType() == tc->sym->llvmInit->getType());
|
||||
|
||||
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
|
||||
dstarr = DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb());
|
||||
|
||||
llvm::Value* srcarr = new llvm::BitCastInst(tc->sym->llvmInit,arrty,"tmp",gIR->scopebb());
|
||||
srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb());
|
||||
|
||||
llvm::Function* fn = LLVM_DeclareMemCpy32();
|
||||
std::vector<llvm::Value*> llargs;
|
||||
llargs.resize(4);
|
||||
llargs[0] = dstarr;
|
||||
llargs[1] = srcarr;
|
||||
llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
|
||||
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
|
||||
new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue* DtoCastClass(DValue* val, Type* _to)
|
||||
{
|
||||
Type* to = DtoDType(_to);
|
||||
@@ -717,8 +845,12 @@ DValue* DtoCastClass(DValue* val, Type* _to)
|
||||
TypeClass* fc = (TypeClass*)from;
|
||||
|
||||
if (tc->sym->isInterfaceDeclaration()) {
|
||||
assert(!fc->sym->isInterfaceDeclaration());
|
||||
return DtoDynamicCastObject(val, _to);
|
||||
if (fc->sym->isInterfaceDeclaration()) {
|
||||
return DtoDynamicCastInterface(val, _to);
|
||||
}
|
||||
else {
|
||||
return DtoDynamicCastObject(val, _to);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int poffset;
|
||||
@@ -805,6 +937,45 @@ DValue* DtoCastInterfaceToObject(DValue* val, Type* to)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
|
||||
{
|
||||
// call:
|
||||
// Object _d_interface_cast(void* p, ClassInfo c)
|
||||
|
||||
DtoForceDeclareDsymbol(ClassDeclaration::object);
|
||||
DtoForceDeclareDsymbol(ClassDeclaration::classinfo);
|
||||
|
||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast");
|
||||
const llvm::FunctionType* funcTy = func->getFunctionType();
|
||||
|
||||
std::vector<llvm::Value*> args;
|
||||
|
||||
// void* p
|
||||
llvm::Value* tmp = val->getRVal();
|
||||
tmp = DtoBitCast(tmp, funcTy->getParamType(0));
|
||||
args.push_back(tmp);
|
||||
|
||||
// ClassInfo c
|
||||
TypeClass* to = (TypeClass*)DtoDType(_to);
|
||||
DtoForceDeclareDsymbol(to->sym);
|
||||
assert(to->sym->llvmClass);
|
||||
tmp = to->sym->llvmClass;
|
||||
// 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);
|
||||
|
||||
// call it
|
||||
llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp");
|
||||
|
||||
// cast return value
|
||||
ret = DtoBitCast(ret, DtoType(_to));
|
||||
|
||||
return new DImValue(_to, ret);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
|
||||
{
|
||||
// start at the bottom of the inheritance chain
|
||||
@@ -851,7 +1022,7 @@ llvm::Value* DtoIndexClass(llvm::Value* ptr, ClassDeclaration* cd, Type* t, unsi
|
||||
if (idxs.empty())
|
||||
idxs.push_back(0);
|
||||
|
||||
const llvm::Type* llt = llvm::PointerType::get(DtoType(t));
|
||||
const llvm::Type* llt = getPtrToType(DtoType(t));
|
||||
const llvm::Type* st = DtoType(cd->type);
|
||||
if (ptr->getType() != st) {
|
||||
assert(cd->llvmHasUnions);
|
||||
@@ -895,7 +1066,7 @@ llvm::Value* DtoIndexClass(llvm::Value* ptr, ClassDeclaration* cd, Type* t, unsi
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
else {
|
||||
const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type));
|
||||
const llvm::Type* sty = getPtrToType(DtoType(vd->type));
|
||||
if (ptr->getType() != sty) {
|
||||
ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
|
||||
std::vector<unsigned> tmp;
|
||||
@@ -910,7 +1081,7 @@ llvm::Value* DtoIndexClass(llvm::Value* ptr, ClassDeclaration* cd, Type* t, unsi
|
||||
|
||||
assert(0);
|
||||
|
||||
size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
|
||||
size_t llt_sz = getABITypeSize(llt->getContainedType(0));
|
||||
assert(os % llt_sz == 0);
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
|
||||
@@ -918,6 +1089,29 @@ llvm::Value* DtoIndexClass(llvm::Value* ptr, ClassDeclaration* cd, Type* t, unsi
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::Value* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
|
||||
{
|
||||
assert(fdecl->isVirtual());//fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual()));
|
||||
assert(fdecl->vtblIndex > 0);
|
||||
assert(DtoDType(inst->getType())->ty == Tclass);
|
||||
|
||||
llvm::Value* vthis = inst->getRVal();
|
||||
//Logger::cout() << "vthis: " << *vthis << '\n';
|
||||
|
||||
llvm::Value* funcval;
|
||||
funcval = DtoGEPi(vthis, 0, 0, "tmp");
|
||||
funcval = DtoLoad(funcval);
|
||||
funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toPrettyChars());
|
||||
funcval = DtoLoad(funcval);
|
||||
|
||||
//assert(funcval->getType() == DtoType(fdecl->type));
|
||||
//cc = DtoCallingConv(fdecl->linkage);
|
||||
|
||||
return funcval;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDeclareClassInfo(ClassDeclaration* cd)
|
||||
{
|
||||
if (cd->llvmClassDeclared) return;
|
||||
@@ -961,7 +1155,7 @@ static llvm::Constant* build_offti_entry(VarDeclaration* vd)
|
||||
DtoForceDeclareDsymbol(vd->type->vtinfo);
|
||||
llvm::Constant* c = isaConstant(vd->type->vtinfo->llvmValue);
|
||||
|
||||
const llvm::Type* tiTy = llvm::PointerType::get(Type::typeinfo->type->llvmType->get());
|
||||
const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get());
|
||||
//Logger::cout() << "tiTy = " << *tiTy << '\n';
|
||||
|
||||
types.push_back(tiTy);
|
||||
@@ -1002,7 +1196,7 @@ static llvm::Constant* build_offti_array(ClassDeclaration* cd, llvm::Constant* i
|
||||
// OffsetTypeInfo type
|
||||
std::vector<const llvm::Type*> elemtypes;
|
||||
elemtypes.push_back(DtoSize_t());
|
||||
const llvm::Type* tiTy = llvm::PointerType::get(Type::typeinfo->type->llvmType->get());
|
||||
const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get());
|
||||
elemtypes.push_back(tiTy);
|
||||
const llvm::StructType* sTy = llvm::StructType::get(elemtypes);
|
||||
|
||||
@@ -1013,7 +1207,7 @@ static llvm::Constant* build_offti_array(ClassDeclaration* cd, llvm::Constant* i
|
||||
std::string name(cd->type->vtinfo->toChars());
|
||||
name.append("__OffsetTypeInfos");
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,llvm::GlobalValue::InternalLinkage,arrInit,name,gIR->module);
|
||||
ptr = llvm::ConstantExpr::getBitCast(gvar, llvm::PointerType::get(sTy));
|
||||
ptr = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(sTy));
|
||||
}
|
||||
else {
|
||||
ptr = llvm::ConstantPointerNull::get(isaPointer(initTy->getElementType(1)));
|
||||
@@ -1026,18 +1220,18 @@ static llvm::Constant* build_class_dtor(ClassDeclaration* cd)
|
||||
{
|
||||
// construct the function
|
||||
std::vector<const llvm::Type*> paramTypes;
|
||||
paramTypes.push_back(llvm::PointerType::get(cd->type->llvmType->get()));
|
||||
paramTypes.push_back(getPtrToType(cd->type->llvmType->get()));
|
||||
|
||||
const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy, paramTypes, false);
|
||||
|
||||
if (cd->dtors.dim == 0) {
|
||||
return llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
return llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty));
|
||||
}
|
||||
else if (cd->dtors.dim == 1) {
|
||||
DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[0];
|
||||
DtoForceDeclareDsymbol(d);
|
||||
assert(d->llvmValue);
|
||||
return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), getPtrToType(llvm::Type::Int8Ty));
|
||||
}
|
||||
|
||||
std::string gname("_D");
|
||||
@@ -1060,7 +1254,7 @@ static llvm::Constant* build_class_dtor(ClassDeclaration* cd)
|
||||
}
|
||||
builder.CreateRetVoid();
|
||||
|
||||
return llvm::ConstantExpr::getBitCast(func, llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
return llvm::ConstantExpr::getBitCast(func, getPtrToType(llvm::Type::Int8Ty));
|
||||
}
|
||||
|
||||
static uint build_classinfo_flags(ClassDeclaration* cd)
|
||||
@@ -1121,7 +1315,7 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
assert(cd->llvmClass);
|
||||
|
||||
TypeClass* cdty = (TypeClass*)cd->type;
|
||||
if (!cd->isInterfaceDeclaration()) {
|
||||
if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) {
|
||||
assert(cd->llvmInit);
|
||||
assert(cd->llvmConstInit);
|
||||
assert(cd->llvmVtbl);
|
||||
@@ -1147,14 +1341,14 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
inits.push_back(c);
|
||||
|
||||
// byte[] init
|
||||
const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
const llvm::Type* byteptrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
|
||||
c = cinfo->llvmConstInit->getOperand(2);
|
||||
}
|
||||
else {
|
||||
c = llvm::ConstantExpr::getBitCast(cd->llvmInit, byteptrty);
|
||||
assert(!cd->llvmConstInit->getType()->isAbstract());
|
||||
size_t initsz = gTargetData->getTypeSize(cd->llvmConstInit->getType());
|
||||
size_t initsz = getABITypeSize(cd->llvmConstInit->getType());
|
||||
c = DtoConstSlice(DtoConstSize_t(initsz), c);
|
||||
}
|
||||
inits.push_back(c);
|
||||
@@ -1172,11 +1366,11 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
inits.push_back(c);
|
||||
|
||||
// vtbl array
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
|
||||
c = cinfo->llvmConstInit->getOperand(4);
|
||||
}
|
||||
else {
|
||||
const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty);
|
||||
const llvm::Type* byteptrptrty = getPtrToType(byteptrty);
|
||||
assert(!cd->llvmVtbl->getType()->isAbstract());
|
||||
c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty);
|
||||
assert(!cd->llvmConstVtbl->getType()->isAbstract());
|
||||
@@ -1187,7 +1381,7 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
|
||||
// interfaces array
|
||||
IRStruct* irstruct = cd->llvmIRStruct;
|
||||
if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos) {
|
||||
if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) {
|
||||
c = cinfo->llvmConstInit->getOperand(5);
|
||||
}
|
||||
else {
|
||||
@@ -1199,7 +1393,7 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
inits.push_back(c);
|
||||
|
||||
// base classinfo
|
||||
if (cd->baseClass && !cd->isInterfaceDeclaration()) {
|
||||
if (cd->baseClass && !cd->isInterfaceDeclaration() && !cd->isAbstract()) {
|
||||
DtoDeclareClassInfo(cd->baseClass);
|
||||
c = cd->baseClass->llvmClass;
|
||||
assert(c);
|
||||
@@ -1212,7 +1406,7 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
}
|
||||
|
||||
// destructor
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
|
||||
c = cinfo->llvmConstInit->getOperand(7);
|
||||
}
|
||||
else {
|
||||
@@ -1226,7 +1420,7 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
inits.push_back(c);
|
||||
|
||||
// uint flags
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
|
||||
c = cinfo->llvmConstInit->getOperand(9);
|
||||
}
|
||||
else {
|
||||
@@ -1241,7 +1435,7 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
inits.push_back(c);
|
||||
|
||||
// offset typeinfo
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
|
||||
c = cinfo->llvmConstInit->getOperand(11);
|
||||
}
|
||||
else {
|
||||
@@ -1250,7 +1444,7 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
inits.push_back(c);
|
||||
|
||||
// default constructor
|
||||
if (cd->defaultCtor && !cd->isInterfaceDeclaration()) {
|
||||
if (cd->defaultCtor && !cd->isInterfaceDeclaration() && !cd->isAbstract()) {
|
||||
DtoForceDeclareDsymbol(cd->defaultCtor);
|
||||
c = isaConstant(cd->defaultCtor->llvmValue);
|
||||
const llvm::Type* toTy = cinfo->llvmConstInit->getOperand(12)->getType();
|
||||
|
||||
@@ -24,13 +24,19 @@ void DtoDefineClass(ClassDeclaration* cd);
|
||||
void DtoDeclareClassInfo(ClassDeclaration* cd);
|
||||
void DtoDefineClassInfo(ClassDeclaration* cd);
|
||||
|
||||
void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance);
|
||||
DValue* DtoNewClass(TypeClass* type, NewExp* newexp);
|
||||
void DtoInitClass(TypeClass* tc, llvm::Value* dst);
|
||||
DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, llvm::Value* mem);
|
||||
void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance);
|
||||
|
||||
DValue* DtoCastClass(DValue* val, Type* to);
|
||||
DValue* DtoDynamicCastObject(DValue* val, Type* to);
|
||||
|
||||
DValue* DtoCastInterfaceToObject(DValue* val, Type* to);
|
||||
DValue* DtoDynamicCastInterface(DValue* val, Type* to);
|
||||
|
||||
llvm::Value* DtoIndexClass(llvm::Value* ptr, ClassDeclaration* cd, Type* t, unsigned os, std::vector<unsigned>& idxs);
|
||||
|
||||
llvm::Value* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -135,9 +135,9 @@ DValue* DtoComplex(Type* to, DValue* val)
|
||||
llvm::Constant* undef = llvm::UndefValue::get(base);
|
||||
llvm::Constant* zero;
|
||||
if (ty == Tfloat32 || ty == Timaginary32 || ty == Tcomplex32)
|
||||
zero = llvm::ConstantFP::get(llvm::Type::FloatTy, float(0));
|
||||
zero = llvm::ConstantFP::get(llvm::Type::FloatTy, llvm::APFloat(0.0f));
|
||||
else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64 || ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80)
|
||||
zero = llvm::ConstantFP::get(llvm::Type::DoubleTy, double(0));
|
||||
zero = llvm::ConstantFP::get(llvm::Type::DoubleTy, llvm::APFloat(0.0));
|
||||
|
||||
if (t->isimaginary()) {
|
||||
return new DComplexValue(to, zero, val->getRVal());
|
||||
|
||||
@@ -32,10 +32,10 @@ void RegisterDwarfSymbols(llvm::Module* mod) {
|
||||
std::vector<const Type*>StructTy_1_fields;
|
||||
StructType* StructTy_1 = StructType::get(StructTy_1_fields, /*isPacked=*/false);
|
||||
|
||||
PointerType* PointerTy_0 = PointerType::get(StructTy_1);
|
||||
PointerType* PointerTy_0 = PointerType::get(StructTy_1,0);
|
||||
|
||||
StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0);
|
||||
PointerType* PointerTy_2 = PointerType::get(IntegerType::get(8));
|
||||
PointerType* PointerTy_2 = PointerType::get(IntegerType::get(8),0);
|
||||
|
||||
StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_2);
|
||||
StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0);
|
||||
@@ -130,33 +130,27 @@ void RegisterDwarfSymbols(llvm::Module* mod) {
|
||||
|
||||
std::vector<const Type*>FuncTy_3_args;
|
||||
FuncTy_3_args.push_back(PointerTy_0);
|
||||
ParamAttrsList *FuncTy_3_PAL = 0;
|
||||
FunctionType* FuncTy_3 = FunctionType::get(
|
||||
/*Result=*/Type::VoidTy,
|
||||
/*Params=*/FuncTy_3_args,
|
||||
/*isVarArg=*/false,
|
||||
/*ParamAttrs=*/FuncTy_3_PAL);
|
||||
/*isVarArg=*/false);
|
||||
|
||||
std::vector<const Type*>FuncTy_4_args;
|
||||
FuncTy_4_args.push_back(IntegerType::get(32));
|
||||
FuncTy_4_args.push_back(IntegerType::get(32));
|
||||
FuncTy_4_args.push_back(PointerTy_0);
|
||||
ParamAttrsList *FuncTy_4_PAL = 0;
|
||||
FunctionType* FuncTy_4 = FunctionType::get(
|
||||
/*Result=*/Type::VoidTy,
|
||||
/*Params=*/FuncTy_4_args,
|
||||
/*isVarArg=*/false,
|
||||
/*ParamAttrs=*/FuncTy_4_PAL);
|
||||
/*isVarArg=*/false);
|
||||
|
||||
std::vector<const Type*>FuncTy_5_args;
|
||||
FuncTy_5_args.push_back(PointerTy_0);
|
||||
FuncTy_5_args.push_back(PointerTy_0);
|
||||
ParamAttrsList *FuncTy_5_PAL = 0;
|
||||
FunctionType* FuncTy_5 = FunctionType::get(
|
||||
/*Result=*/Type::VoidTy,
|
||||
/*Params=*/FuncTy_5_args,
|
||||
/*isVarArg=*/false,
|
||||
/*ParamAttrs=*/FuncTy_5_PAL);
|
||||
/*isVarArg=*/false);
|
||||
|
||||
|
||||
// Function Declarations
|
||||
|
||||
@@ -47,7 +47,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype
|
||||
assert(rt);
|
||||
Type* rtfin = DtoDType(rt);
|
||||
if (DtoIsPassedByRef(rt)) {
|
||||
rettype = llvm::PointerType::get(DtoType(rt));
|
||||
rettype = getPtrToType(DtoType(rt));
|
||||
actualRettype = llvm::Type::VoidTy;
|
||||
f->llvmRetInPtr = retinptr = true;
|
||||
}
|
||||
@@ -77,10 +77,10 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype
|
||||
assert(ti->llvmConstInit);
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(DtoSize_t());
|
||||
types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmConstInit->getType())));
|
||||
types.push_back(getPtrToType(getPtrToType(ti->llvmConstInit->getType())));
|
||||
const llvm::Type* t1 = llvm::StructType::get(types);
|
||||
paramvec.push_back(llvm::PointerType::get(t1));
|
||||
paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
paramvec.push_back(getPtrToType(t1));
|
||||
paramvec.push_back(getPtrToType(llvm::Type::Int8Ty));
|
||||
}
|
||||
|
||||
size_t n = Argument::dim(f->parameters);
|
||||
@@ -94,23 +94,23 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype
|
||||
const llvm::Type* at = DtoType(argT);
|
||||
if (isaStruct(at)) {
|
||||
Logger::println("struct param");
|
||||
paramvec.push_back(llvm::PointerType::get(at));
|
||||
paramvec.push_back(getPtrToType(at));
|
||||
}
|
||||
else if (isaArray(at)) {
|
||||
Logger::println("sarray param");
|
||||
assert(argT->ty == Tsarray);
|
||||
//paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
|
||||
paramvec.push_back(llvm::PointerType::get(at));
|
||||
//paramvec.push_back(getPtrToType(at->getContainedType(0)));
|
||||
paramvec.push_back(getPtrToType(at));
|
||||
}
|
||||
else if (llvm::isa<llvm::OpaqueType>(at)) {
|
||||
Logger::println("opaque param");
|
||||
assert(argT->ty == Tstruct || argT->ty == Tclass);
|
||||
paramvec.push_back(llvm::PointerType::get(at));
|
||||
paramvec.push_back(getPtrToType(at));
|
||||
}
|
||||
else {
|
||||
if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
|
||||
Logger::println("by ref param");
|
||||
at = llvm::PointerType::get(at);
|
||||
at = getPtrToType(at);
|
||||
}
|
||||
else {
|
||||
Logger::println("in param");
|
||||
@@ -146,7 +146,7 @@ static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
|
||||
TypeFunction* f = (TypeFunction*)fdecl->type;
|
||||
assert(f != 0);
|
||||
|
||||
const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty);
|
||||
std::vector<const llvm::Type*> args;
|
||||
|
||||
if (fdecl->llvmInternal == LLVMva_start) {
|
||||
@@ -194,7 +194,7 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
|
||||
thisty = DtoType(ad->type);
|
||||
//Logger::cout() << "this llvm type: " << *thisty << '\n';
|
||||
if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->recty.get()))
|
||||
thisty = llvm::PointerType::get(thisty);
|
||||
thisty = getPtrToType(thisty);
|
||||
}
|
||||
else {
|
||||
Logger::println("chars: %s type: %s kind: %s", fdecl->toChars(), fdecl->type->toChars(), fdecl->kind());
|
||||
@@ -202,7 +202,7 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
|
||||
}
|
||||
}
|
||||
else if (fdecl->isNested()) {
|
||||
thisty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
thisty = getPtrToType(llvm::Type::Int8Ty);
|
||||
}
|
||||
|
||||
const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
|
||||
@@ -244,6 +244,13 @@ void DtoResolveFunction(FuncDeclaration* fdecl)
|
||||
return; // ignore declaration completely
|
||||
}
|
||||
|
||||
// is imported and we don't have access?
|
||||
if (fdecl->getModule() != gIR->dmodule)
|
||||
{
|
||||
if (fdecl->prot() == PROTprivate)
|
||||
return;
|
||||
}
|
||||
|
||||
if (fdecl->llvmResolved) return;
|
||||
fdecl->llvmResolved = true;
|
||||
|
||||
@@ -427,6 +434,8 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||
|
||||
if (!declareOnly)
|
||||
gIR->defineList.push_back(fdecl);
|
||||
else
|
||||
assert(func->getLinkage() != llvm::GlobalValue::InternalLinkage);
|
||||
|
||||
Logger::cout() << "func decl: " << *func << '\n';
|
||||
}
|
||||
@@ -637,9 +646,9 @@ void DtoMain()
|
||||
// parameter types
|
||||
std::vector<const llvm::Type*> pvec;
|
||||
pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty);
|
||||
const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
|
||||
pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType));
|
||||
const llvm::Type* chPtrType = (const llvm::Type*)getPtrToType(llvm::Type::Int8Ty);
|
||||
pvec.push_back((const llvm::Type*)getPtrToType(chPtrType));
|
||||
pvec.push_back((const llvm::Type*)getPtrToType(chPtrType));
|
||||
const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty;
|
||||
|
||||
llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false);
|
||||
|
||||
@@ -133,7 +133,7 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char*
|
||||
|
||||
static const llvm::Type* rt_ptr(const llvm::Type* t)
|
||||
{
|
||||
return llvm::PointerType::get(t);
|
||||
return getPtrToType(t);
|
||||
}
|
||||
|
||||
static const llvm::Type* rt_array(const llvm::Type* elemty)
|
||||
@@ -197,16 +197,31 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// assert
|
||||
// void _d_assert(bool cond, uint line, char[] msg)
|
||||
// void _d_assert( char[] file, uint line )
|
||||
// void _d_array_bounds( char[] file, uint line )
|
||||
// void _d_switch_error( char[] file, uint line )
|
||||
{
|
||||
std::string fname("_d_assert");
|
||||
std::string fname2("_d_array_bounds");
|
||||
std::string fname3("_d_switch_error");
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(boolTy);
|
||||
types.push_back(intTy);
|
||||
types.push_back(stringTy);
|
||||
types.push_back(intTy);
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname3, M);
|
||||
}
|
||||
|
||||
// void _d_assert_msg( char[] msg, char[] file, uint line )
|
||||
{
|
||||
std::string fname("_d_assert_msg");
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(stringTy);
|
||||
types.push_back(stringTy);
|
||||
types.push_back(intTy);
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -234,6 +249,15 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
|
||||
// Object _d_newclass(ClassInfo ci)
|
||||
{
|
||||
std::string fname("_d_newclass");
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(classInfoTy);
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false);
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -626,6 +650,51 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Object _d_toObject(void* p)
|
||||
{
|
||||
std::string fname("_d_toObject");
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(voidPtrTy);
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false);
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
|
||||
// Object _d_dynamic_cast(Object o, ClassInfo c)
|
||||
{
|
||||
std::string fname("_d_dynamic_cast");
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(objectTy);
|
||||
types.push_back(classInfoTy);
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false);
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
|
||||
// Object _d_interface_cast(void* p, ClassInfo c)
|
||||
{
|
||||
std::string fname("_d_interface_cast");
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(voidPtrTy);
|
||||
types.push_back(classInfoTy);
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false);
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// void _d_throw_exception(Object e)
|
||||
{
|
||||
std::string fname("_d_throw_exception");
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(objectTy);
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
|
||||
new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "gen/llvm.h"
|
||||
#include "llvm/InlineAsm.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "total.h"
|
||||
@@ -488,17 +489,39 @@ void TryCatchStatement::toIR(IRState* p)
|
||||
Logger::println("TryCatchStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
Logger::attention(loc, "try-catch is not yet fully implemented, only the try block will be emitted.");
|
||||
Logger::attention(loc, "try-catch is not yet fully implemented");
|
||||
|
||||
// create basic blocks
|
||||
llvm::BasicBlock* oldend = p->scopeend();
|
||||
|
||||
llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend);
|
||||
llvm::BasicBlock* catchbb = new llvm::BasicBlock("catch", p->topfunc(), oldend);
|
||||
llvm::BasicBlock* endbb = new llvm::BasicBlock("endtrycatch", p->topfunc(), oldend);
|
||||
|
||||
// pass the previous BB into this
|
||||
assert(!gIR->scopereturned());
|
||||
new llvm::BranchInst(trybb, p->scopebb());
|
||||
|
||||
// do the try block
|
||||
p->scope() = IRScope(trybb,catchbb);
|
||||
assert(body);
|
||||
body->toIR(p);
|
||||
|
||||
if (!gIR->scopereturned())
|
||||
new llvm::BranchInst(endbb, p->scopebb());
|
||||
|
||||
// do catch
|
||||
p->scope() = IRScope(catchbb,oldend);
|
||||
new llvm::BranchInst(endbb, p->scopebb());
|
||||
/*assert(catches);
|
||||
for(size_t i=0; i<catches->dim; ++i)
|
||||
{
|
||||
Catch* c = (Catch*)catches->data[i];
|
||||
c->handler->toIR(p);
|
||||
}*/
|
||||
|
||||
// rewrite the scope
|
||||
p->scope() = IRScope(endbb,oldend);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -508,15 +531,16 @@ void ThrowStatement::toIR(IRState* p)
|
||||
Logger::println("ThrowStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
Logger::attention(loc, "throw is not yet implemented, replacing expression with assert(0);");
|
||||
Logger::attention(loc, "throw is not yet fully implemented");
|
||||
|
||||
DtoAssert(NULL, &loc, NULL);
|
||||
|
||||
/*
|
||||
assert(exp);
|
||||
DValue* e = exp->toElem(p);
|
||||
delete e;
|
||||
*/
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_throw_exception");
|
||||
//Logger::cout() << "calling: " << *fn << '\n';
|
||||
llvm::Value* arg = DtoBitCast(e->getRVal(), fn->getFunctionType()->getParamType(0));
|
||||
//Logger::cout() << "arg: " << *arg << '\n';
|
||||
gIR->ir->CreateCall(fn, arg, "");
|
||||
gIR->ir->CreateUnreachable();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -629,7 +653,7 @@ void SwitchStatement::toIR(IRState* p)
|
||||
llvm::Constant* arrInit = llvm::ConstantArray::get(arrTy, inits);
|
||||
llvm::GlobalVariable* arr = new llvm::GlobalVariable(arrTy, true, llvm::GlobalValue::InternalLinkage, arrInit, "string_switch_table_data", gIR->module);
|
||||
|
||||
const llvm::Type* elemPtrTy = llvm::PointerType::get(elemTy);
|
||||
const llvm::Type* elemPtrTy = getPtrToType(elemTy);
|
||||
llvm::Constant* arrPtr = llvm::ConstantExpr::getBitCast(arr, elemPtrTy);
|
||||
|
||||
// build the static table
|
||||
@@ -824,8 +848,8 @@ void ForeachStatement::toIR(IRState* p)
|
||||
|
||||
if (niters->getType() != keytype)
|
||||
{
|
||||
size_t sz1 = gTargetData->getTypeSize(niters->getType());
|
||||
size_t sz2 = gTargetData->getTypeSize(keytype);
|
||||
size_t sz1 = getTypeBitSize(niters->getType());
|
||||
size_t sz2 = getTypeBitSize(keytype);
|
||||
if (sz1 < sz2)
|
||||
niters = gIR->ir->CreateZExt(niters, keytype, "foreachtrunckey");
|
||||
else if (sz1 > sz2)
|
||||
|
||||
@@ -27,11 +27,11 @@ const llvm::Type* DtoStructType(Type* t)
|
||||
llvm::Value* DtoStructZeroInit(llvm::Value* v)
|
||||
{
|
||||
assert(gIR);
|
||||
uint64_t n = gTargetData->getTypeSize(v->getType()->getContainedType(0));
|
||||
//llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
|
||||
llvm::Type* sarrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
uint64_t n = getTypeStoreSize(v->getType()->getContainedType(0));
|
||||
//llvm::Type* sarrty = getPtrToType(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
|
||||
const llvm::Type* sarrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* sarr = new llvm::BitCastInst(v,sarrty,"tmp",gIR->scopebb());
|
||||
llvm::Value* sarr = DtoBitCast(v, sarrty);
|
||||
|
||||
llvm::Function* fn = LLVM_DeclareMemSet32();
|
||||
std::vector<llvm::Value*> llargs;
|
||||
@@ -54,9 +54,9 @@ llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src)
|
||||
assert(dst->getType() == src->getType());
|
||||
assert(gIR);
|
||||
|
||||
uint64_t n = gTargetData->getTypeSize(dst->getType()->getContainedType(0));
|
||||
//llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
|
||||
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
uint64_t n = getTypeStoreSize(dst->getType()->getContainedType(0));
|
||||
//llvm::Type* sarrty = getPtrToType(llvm::ArrayType::get(llvm::Type::Int8Ty, n));
|
||||
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
|
||||
llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb());
|
||||
@@ -110,8 +110,8 @@ llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, un
|
||||
if (idxs.empty())
|
||||
idxs.push_back(0);
|
||||
|
||||
const llvm::Type* llt = llvm::PointerType::get(DtoType(t));
|
||||
const llvm::Type* st = llvm::PointerType::get(DtoType(sd->type));
|
||||
const llvm::Type* llt = getPtrToType(DtoType(t));
|
||||
const llvm::Type* st = getPtrToType(DtoType(sd->type));
|
||||
if (ptr->getType() != st) {
|
||||
assert(sd->llvmHasUnions);
|
||||
ptr = gIR->ir->CreateBitCast(ptr, st, "tmp");
|
||||
@@ -139,15 +139,15 @@ llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, un
|
||||
Logger::println("has union field offset");
|
||||
ptr = DtoGEP(ptr, idxs, "tmp");
|
||||
if (ptr->getType() != llt)
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
ptr = DtoBitCast(ptr, llt);
|
||||
ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
|
||||
std::vector<unsigned> tmp;
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
else {
|
||||
const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type));
|
||||
const llvm::Type* sty = getPtrToType(DtoType(vd->type));
|
||||
if (ptr->getType() != sty) {
|
||||
ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
|
||||
ptr = DtoBitCast(ptr, sty);
|
||||
std::vector<unsigned> tmp;
|
||||
return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
|
||||
}
|
||||
@@ -158,9 +158,9 @@ llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, un
|
||||
}
|
||||
}
|
||||
|
||||
size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
|
||||
size_t llt_sz = getTypeStoreSize(llt->getContainedType(0));
|
||||
assert(os % llt_sz == 0);
|
||||
ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
|
||||
ptr = DtoBitCast(ptr, llt);
|
||||
return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
|
||||
}
|
||||
|
||||
@@ -180,12 +180,34 @@ void DtoResolveStruct(StructDeclaration* sd)
|
||||
sd->llvmIRStruct = irstruct;
|
||||
gIR->structs.push_back(irstruct);
|
||||
|
||||
// fields
|
||||
Array* arr = &sd->fields;
|
||||
for (int k=0; k < arr->dim; k++) {
|
||||
VarDeclaration* v = (VarDeclaration*)(arr->data[k]);
|
||||
VarDeclaration* v = (VarDeclaration*)arr->data[k];
|
||||
v->toObjFile();
|
||||
}
|
||||
|
||||
bool thisModule = false;
|
||||
if (sd->getModule() == gIR->dmodule)
|
||||
thisModule = true;
|
||||
|
||||
// methods
|
||||
arr = sd->members;
|
||||
for (int k=0; k < arr->dim; k++) {
|
||||
Dsymbol* s = (Dsymbol*)arr->data[k];
|
||||
if (FuncDeclaration* fd = s->isFuncDeclaration()) {
|
||||
if (thisModule || (fd->prot() != PROTprivate)) {
|
||||
fd->toObjFile();
|
||||
}
|
||||
}
|
||||
else if (s->isAttribDeclaration()) {
|
||||
s->toObjFile();
|
||||
}
|
||||
else {
|
||||
Logger::println("Ignoring dsymbol '%s' in this->members of kind '%s'", s->toPrettyChars(), s->kind());
|
||||
}
|
||||
}
|
||||
|
||||
/*for (int k=0; k < sd->members->dim; k++) {
|
||||
Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]);
|
||||
dsym->toObjFile();
|
||||
@@ -218,12 +240,12 @@ void DtoResolveStruct(StructDeclaration* sd)
|
||||
assert(lastoffset == 0);
|
||||
fieldtype = i->second.type;
|
||||
fieldinit = i->second.var;
|
||||
prevsize = gTargetData->getTypeSize(fieldtype);
|
||||
prevsize = getABITypeSize(fieldtype);
|
||||
i->second.var->llvmFieldIndex = idx;
|
||||
}
|
||||
// colliding offset?
|
||||
else if (lastoffset == i->first) {
|
||||
size_t s = gTargetData->getTypeSize(i->second.type);
|
||||
size_t s = getABITypeSize(i->second.type);
|
||||
if (s > prevsize) {
|
||||
fieldpad += s - prevsize;
|
||||
prevsize = s;
|
||||
@@ -233,7 +255,7 @@ void DtoResolveStruct(StructDeclaration* sd)
|
||||
}
|
||||
// intersecting offset?
|
||||
else if (i->first < (lastoffset + prevsize)) {
|
||||
size_t s = gTargetData->getTypeSize(i->second.type);
|
||||
size_t s = getABITypeSize(i->second.type);
|
||||
assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
|
||||
sd->llvmHasUnions = true;
|
||||
i->second.var->llvmFieldIndex = idx;
|
||||
@@ -256,7 +278,7 @@ void DtoResolveStruct(StructDeclaration* sd)
|
||||
lastoffset = i->first;
|
||||
fieldtype = i->second.type;
|
||||
fieldinit = i->second.var;
|
||||
prevsize = gTargetData->getTypeSize(fieldtype);
|
||||
prevsize = getABITypeSize(fieldtype);
|
||||
i->second.var->llvmFieldIndex = idx;
|
||||
fieldpad = 0;
|
||||
}
|
||||
@@ -420,7 +442,7 @@ DUnion::DUnion()
|
||||
unsigned o = i->first;
|
||||
IRStruct::Offset* so = &i->second;
|
||||
const llvm::Type* ft = so->init->getType();
|
||||
size_t sz = gTargetData->getTypeSize(ft);
|
||||
size_t sz = getABITypeSize(ft);
|
||||
if (f == NULL) { // new field
|
||||
fields.push_back(DUnionField());
|
||||
f = &fields.back();
|
||||
@@ -495,7 +517,7 @@ llvm::Constant* DUnion::getConst(std::vector<DUnionIdx>& in)
|
||||
|
||||
if (ii < nin && fi == in[ii].idx)
|
||||
{
|
||||
size_t s = gTargetData->getTypeSize(in[ii].c->getType());
|
||||
size_t s = getABITypeSize(in[ii].c->getType());
|
||||
if (in[ii].idx == last)
|
||||
{
|
||||
size_t nos = in[ii].idxos * s;
|
||||
|
||||
@@ -15,7 +15,7 @@ using namespace llvm::dwarf;
|
||||
|
||||
static const llvm::PointerType* ptrTy(const llvm::Type* t)
|
||||
{
|
||||
return llvm::PointerType::get(t);
|
||||
return llvm::PointerType::get(t, 0);
|
||||
}
|
||||
|
||||
static const llvm::PointerType* dbgArrTy()
|
||||
|
||||
247
gen/toir.cpp
247
gen/toir.cpp
@@ -179,7 +179,7 @@ DValue* VarExp::toElem(IRState* p)
|
||||
assert(tid->llvmValue);
|
||||
const llvm::Type* vartype = DtoType(type);
|
||||
llvm::Value* m;
|
||||
if (tid->llvmValue->getType() != llvm::PointerType::get(vartype))
|
||||
if (tid->llvmValue->getType() != getPtrToType(vartype))
|
||||
m = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp");
|
||||
else
|
||||
m = tid->llvmValue;
|
||||
@@ -278,7 +278,7 @@ llvm::Constant* VarExp::toConstElem(IRState* p)
|
||||
const llvm::Type* vartype = DtoType(type);
|
||||
llvm::Constant* m = isaConstant(ti->llvmValue);
|
||||
assert(m);
|
||||
if (ti->llvmValue->getType() != llvm::PointerType::get(vartype))
|
||||
if (ti->llvmValue->getType() != getPtrToType(vartype))
|
||||
m = llvm::ConstantExpr::getBitCast(m, vartype);
|
||||
return m;
|
||||
}
|
||||
@@ -403,11 +403,13 @@ DValue* StringExp::toElem(IRState* p)
|
||||
Type* cty = DtoDType(dtype->next);
|
||||
|
||||
const llvm::Type* ct = DtoType(cty);
|
||||
if (ct == llvm::Type::VoidTy)
|
||||
ct = llvm::Type::Int8Ty;
|
||||
//printf("ct = %s\n", type->next->toChars());
|
||||
const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1);
|
||||
|
||||
llvm::Constant* _init;
|
||||
if (cty->ty == Tchar) {
|
||||
if (cty->ty == Tchar || cty->ty == Tvoid) {
|
||||
uint8_t* str = (uint8_t*)string;
|
||||
std::string cont((char*)str, len);
|
||||
_init = llvm::ConstantArray::get(cont,true);
|
||||
@@ -434,6 +436,7 @@ DValue* StringExp::toElem(IRState* p)
|
||||
assert(0);
|
||||
|
||||
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
|
||||
Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n';
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,"stringliteral",gIR->module);
|
||||
|
||||
llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
@@ -461,7 +464,7 @@ DValue* StringExp::toElem(IRState* p)
|
||||
assert(0);
|
||||
}
|
||||
else if (dtype->ty == Tsarray) {
|
||||
const llvm::Type* dstType = llvm::PointerType::get(llvm::ArrayType::get(ct, len));
|
||||
const llvm::Type* dstType = getPtrToType(llvm::ArrayType::get(ct, len));
|
||||
llvm::Value* emem = (gvar->getType() == dstType) ? gvar : DtoBitCast(gvar, dstType);
|
||||
return new DVarValue(type, emem, true);
|
||||
}
|
||||
@@ -877,7 +880,7 @@ DValue* CallExp::toElem(IRState* p)
|
||||
Type* t = DtoDType(type);
|
||||
const llvm::Type* llt = DtoType(type);
|
||||
if (DtoIsPassedByRef(t))
|
||||
llt = llvm::PointerType::get(llt);
|
||||
llt = getPtrToType(llt);
|
||||
// TODO
|
||||
if (strcmp(global.params.llvmArch, "x86") != 0) {
|
||||
warning("%s: va_arg for C variadic functions is broken for anything but x86", loc.toChars());
|
||||
@@ -972,7 +975,7 @@ DValue* CallExp::toElem(IRState* p)
|
||||
}
|
||||
|
||||
if (dfn && dfn->func && dfn->func->llvmRunTimeHack) {
|
||||
const llvm::Type* rettype = llvm::PointerType::get(DtoType(type));
|
||||
const llvm::Type* rettype = getPtrToType(DtoType(type));
|
||||
if (llargs[j]->getType() != llfnty->getParamType(j)) {
|
||||
Logger::println("llvmRunTimeHack==true - force casting return value param");
|
||||
Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n';
|
||||
@@ -986,9 +989,9 @@ DValue* CallExp::toElem(IRState* p)
|
||||
|
||||
// this arguments
|
||||
if (dfn && dfn->vthis) {
|
||||
Logger::println("This Call");
|
||||
Logger::cout() << "This Call func val:" << *funcval << '\n';
|
||||
if (dfn->vthis->getType() != argiter->get()) {
|
||||
//Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n';
|
||||
//Logger::cout() << "value: " << *dfn->vthis << " totype: " << *argiter->get() << '\n';
|
||||
llargs[j] = DtoBitCast(dfn->vthis, argiter->get());
|
||||
}
|
||||
else {
|
||||
@@ -1010,8 +1013,8 @@ DValue* CallExp::toElem(IRState* p)
|
||||
Logger::println("Nested Call");
|
||||
llvm::Value* contextptr = DtoNestedContext(dfn->func->toParent2()->isFuncDeclaration());
|
||||
if (!contextptr)
|
||||
contextptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
llargs[j] = DtoBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
contextptr = llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty));
|
||||
llargs[j] = DtoBitCast(contextptr, getPtrToType(llvm::Type::Int8Ty));
|
||||
++j;
|
||||
++argiter;
|
||||
}
|
||||
@@ -1025,7 +1028,7 @@ DValue* CallExp::toElem(IRState* p)
|
||||
Argument* fnarg = Argument::getNth(tf->parameters, i);
|
||||
Expression* exp = (Expression*)arguments->data[i];
|
||||
DValue* expelem = exp->toElem(p);
|
||||
llargs[j] = DtoBitCast(expelem->getLVal(), llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
llargs[j] = DtoBitCast(expelem->getLVal(), getPtrToType(llvm::Type::Int8Ty));
|
||||
}
|
||||
}
|
||||
// regular arguments
|
||||
@@ -1062,7 +1065,7 @@ DValue* CallExp::toElem(IRState* p)
|
||||
|
||||
// build type info array
|
||||
assert(Type::typeinfo->llvmConstInit);
|
||||
const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmConstInit->getType());
|
||||
const llvm::Type* typeinfotype = getPtrToType(Type::typeinfo->llvmConstInit->getType());
|
||||
Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n';
|
||||
const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements());
|
||||
|
||||
@@ -1081,13 +1084,13 @@ DValue* CallExp::toElem(IRState* p)
|
||||
// put data in d-array
|
||||
llvm::Value* typeinfoarrayparam = new llvm::AllocaInst(llfnty->getParamType(j)->getContainedType(0),"_arguments_array",p->topallocapoint());
|
||||
p->ir->CreateStore(DtoConstSize_t(vtype->getNumElements()), DtoGEPi(typeinfoarrayparam,0,0,"tmp"));
|
||||
llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, llvm::PointerType::get(typeinfotype), "tmp");
|
||||
llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, getPtrToType(typeinfotype), "tmp");
|
||||
p->ir->CreateStore(casttypeinfomem, DtoGEPi(typeinfoarrayparam,0,1,"tmp"));
|
||||
|
||||
// specify arguments
|
||||
llargs[j] = typeinfoarrayparam;;
|
||||
j++;
|
||||
llargs[j] = p->ir->CreateBitCast(mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
|
||||
llargs[j] = p->ir->CreateBitCast(mem, getPtrToType(llvm::Type::Int8Ty), "tmp");
|
||||
j++;
|
||||
llargs.resize(nimplicit+2);
|
||||
}
|
||||
@@ -1128,14 +1131,14 @@ DValue* CallExp::toElem(IRState* p)
|
||||
if (llfnty->getReturnType() != llvm::Type::VoidTy)
|
||||
varname = "tmp";
|
||||
|
||||
Logger::cout() << "Calling: " << *funcval << '\n';
|
||||
//Logger::cout() << "Calling: " << *funcval << '\n';
|
||||
|
||||
// call the function
|
||||
llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb());
|
||||
llvm::Value* retllval = (retinptr) ? llargs[0] : call;
|
||||
|
||||
if (retinptr && dfn && dfn->func && dfn->func->llvmRunTimeHack) {
|
||||
const llvm::Type* rettype = llvm::PointerType::get(DtoType(type));
|
||||
const llvm::Type* rettype = getPtrToType(DtoType(type));
|
||||
if (retllval->getType() != rettype) {
|
||||
Logger::println("llvmRunTimeHack==true - force casting return value");
|
||||
Logger::cout() << "from: " << *retllval->getType() << " to: " << *rettype << '\n';
|
||||
@@ -1243,7 +1246,7 @@ DValue* SymOffExp::toElem(IRState* p)
|
||||
}
|
||||
else {
|
||||
const llvm::Type* elemtype = llvalue->getType()->getContainedType(0)->getContainedType(0);
|
||||
size_t elemsz = gTargetData->getTypeSize(elemtype);
|
||||
size_t elemsz = getABITypeSize(elemtype);
|
||||
varmem = DtoGEPi(llvalue, 0, offset / elemsz, "tmp");
|
||||
}
|
||||
}
|
||||
@@ -1388,8 +1391,14 @@ DValue* DotVarExp::toElem(IRState* p)
|
||||
if (!vthis2) vthis2 = vthis;
|
||||
//unsigned cc = (unsigned)-1;
|
||||
|
||||
// virtual call
|
||||
if (!fdecl->isFinal() && fdecl->isVirtual()) {
|
||||
// super call
|
||||
if (e1->op == TOKsuper) {
|
||||
DtoForceDeclareDsymbol(fdecl);
|
||||
funcval = fdecl->llvmValue;
|
||||
assert(funcval);
|
||||
}
|
||||
// normal virtual call
|
||||
else if (fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())) {
|
||||
assert(fdecl->vtblIndex > 0);
|
||||
assert(e1type->ty == Tclass);
|
||||
|
||||
@@ -1428,7 +1437,8 @@ DValue* ThisExp::toElem(IRState* p)
|
||||
LOG_SCOPE;
|
||||
|
||||
if (VarDeclaration* vd = var->isVarDeclaration()) {
|
||||
llvm::Value* v = p->func()->decl->llvmThisVar;
|
||||
llvm::Value* v;
|
||||
v = p->func()->decl->llvmThisVar;
|
||||
if (llvm::isa<llvm::AllocaInst>(v))
|
||||
v = new llvm::LoadInst(v, "tmp", p->scopebb());
|
||||
return new DThisValue(vd, v);
|
||||
@@ -1818,7 +1828,7 @@ DValue* PostExp::toElem(IRState* p)
|
||||
else if (e1type->isfloating())
|
||||
{
|
||||
assert(e2type->isfloating());
|
||||
llvm::Value* one = llvm::ConstantFP::get(val->getType(), 1.0f);
|
||||
llvm::Value* one = llvm::ConstantFP::get(val->getType(), llvm::APFloat(1.0f));
|
||||
if (op == TOKplusplus) {
|
||||
post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb());
|
||||
}
|
||||
@@ -1847,113 +1857,47 @@ DValue* NewExp::toElem(IRState* p)
|
||||
|
||||
Type* ntype = DtoDType(newtype);
|
||||
|
||||
if (ntype->ty == Tclass) {
|
||||
return DtoNewClass((TypeClass*)ntype, this);
|
||||
}
|
||||
|
||||
const llvm::Type* t = DtoType(ntype);
|
||||
|
||||
llvm::Value* emem = 0;
|
||||
bool inplace = false;
|
||||
|
||||
{
|
||||
Logger::println("Allocating memory");
|
||||
LOG_SCOPE;
|
||||
if (onstack) {
|
||||
assert(ntype->ty == Tclass);
|
||||
emem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint());
|
||||
}
|
||||
else if (ntype->ty == Tclass) {
|
||||
emem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb());
|
||||
}
|
||||
else if (ntype->ty == Tarray) {
|
||||
assert(arguments);
|
||||
if (arguments->dim == 1) {
|
||||
DValue* sz = ((Expression*)arguments->data[0])->toElem(p);
|
||||
llvm::Value* dimval = sz->getRVal();
|
||||
Type* nnt = DtoDType(ntype->next);
|
||||
if (nnt->ty == Tvoid)
|
||||
nnt = Type::tint8;
|
||||
if (ntype->ty == Tarray) {
|
||||
assert(arguments);
|
||||
if (arguments->dim == 1) {
|
||||
DValue* sz = ((Expression*)arguments->data[0])->toElem(p);
|
||||
llvm::Value* dimval = sz->getRVal();
|
||||
Type* nnt = DtoDType(ntype->next);
|
||||
if (nnt->ty == Tvoid)
|
||||
nnt = Type::tint8;
|
||||
|
||||
if (p->topexp() && p->topexp()->e2 == this) {
|
||||
assert(p->topexp()->v);
|
||||
emem = p->topexp()->v->getLVal();
|
||||
DtoNewDynArray(emem, dimval, nnt);
|
||||
inplace = true;
|
||||
}
|
||||
else {
|
||||
const llvm::Type* restype = DtoType(type);
|
||||
Logger::cout() << "restype = " << *restype << '\n';
|
||||
emem = new llvm::AllocaInst(restype,"newstorage",p->topallocapoint());
|
||||
DtoNewDynArray(emem, dimval, nnt);
|
||||
return new DVarValue(newtype, emem, true);
|
||||
}
|
||||
if (p->topexp() && p->topexp()->e2 == this) {
|
||||
assert(p->topexp()->v);
|
||||
emem = p->topexp()->v->getLVal();
|
||||
DtoNewDynArray(emem, dimval, nnt);
|
||||
inplace = true;
|
||||
}
|
||||
else {
|
||||
assert(0 && "num args to 'new' != 1");
|
||||
const llvm::Type* restype = DtoType(type);
|
||||
Logger::cout() << "restype = " << *restype << '\n';
|
||||
emem = new llvm::AllocaInst(restype,"newstorage",p->topallocapoint());
|
||||
DtoNewDynArray(emem, dimval, nnt);
|
||||
return new DVarValue(newtype, emem, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emem = new llvm::MallocInst(t,"tmp",p->scopebb());
|
||||
assert(0 && "num args to 'new' != 1");
|
||||
}
|
||||
}
|
||||
|
||||
if (ntype->ty == Tclass) {
|
||||
// first apply the static initializer
|
||||
TypeClass* tc = (TypeClass*)ntype;
|
||||
DtoInitClass(tc, emem);
|
||||
|
||||
// set the this var for nested classes
|
||||
if (thisexp) {
|
||||
Logger::println("Resolving 'this' expression");
|
||||
LOG_SCOPE;
|
||||
DValue* thisval = thisexp->toElem(p);
|
||||
size_t idx = 2;
|
||||
idx += tc->sym->llvmIRStruct->interfaces.size();
|
||||
llvm::Value* dst = thisval->getRVal();
|
||||
llvm::Value* src = DtoGEPi(emem,0,idx,"tmp");
|
||||
Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
|
||||
DtoStore(dst, src);
|
||||
}
|
||||
else if (tc->sym->isNested())
|
||||
{
|
||||
Logger::println("Resolving nested context");
|
||||
LOG_SCOPE;
|
||||
size_t idx = 2;
|
||||
idx += tc->sym->llvmIRStruct->interfaces.size();
|
||||
llvm::Value* nest = p->func()->decl->llvmNested;
|
||||
if (!nest)
|
||||
nest = p->func()->decl->llvmThisVar;
|
||||
assert(nest);
|
||||
llvm::Value* gep = DtoGEPi(emem,0,idx,"tmp");
|
||||
nest = DtoBitCast(nest, gep->getType()->getContainedType(0));
|
||||
DtoStore(nest, gep);
|
||||
}
|
||||
|
||||
// then call constructor
|
||||
if (arguments) {
|
||||
Logger::println("Calling constructor");
|
||||
LOG_SCOPE;
|
||||
assert(member);
|
||||
assert(member->llvmValue);
|
||||
llvm::Function* fn = llvm::cast<llvm::Function>(member->llvmValue);
|
||||
TypeFunction* tf = (TypeFunction*)DtoDType(member->type);
|
||||
|
||||
std::vector<llvm::Value*> ctorargs;
|
||||
ctorargs.push_back(emem);
|
||||
for (size_t i=0; i<arguments->dim; ++i)
|
||||
{
|
||||
Expression* ex = (Expression*)arguments->data[i];
|
||||
Argument* fnarg = Argument::getNth(tf->parameters, i);
|
||||
DValue* argval = DtoArgument(fnarg, ex);
|
||||
llvm::Value* a = argval->getRVal();
|
||||
const llvm::Type* aty = fn->getFunctionType()->getParamType(i+1);
|
||||
if (a->getType() != aty) // this param might have type mismatch
|
||||
a = DtoBitCast(a, aty);
|
||||
ctorargs.push_back(a);
|
||||
}
|
||||
llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
|
||||
call->setCallingConv(DtoCallingConv(LINKd));
|
||||
emem = call;
|
||||
}
|
||||
else {
|
||||
emem = new llvm::MallocInst(t,"tmp",p->scopebb());
|
||||
}
|
||||
else if (ntype->ty == Tstruct) {
|
||||
|
||||
if (ntype->ty == Tstruct) {
|
||||
TypeStruct* ts = (TypeStruct*)ntype;
|
||||
if (ts->isZeroInit()) {
|
||||
DtoStructZeroInit(emem);
|
||||
@@ -2053,12 +1997,33 @@ DValue* AssertExp::toElem(IRState* p)
|
||||
Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
DValue* u = e1->toElem(p);
|
||||
DValue* m = msg ? msg->toElem(p) : NULL;
|
||||
// condition
|
||||
DValue* cond = e1->toElem(p);
|
||||
|
||||
DtoAssert(u->getRVal(), &loc, m);
|
||||
// create basic blocks
|
||||
llvm::BasicBlock* oldend = p->scopeend();
|
||||
llvm::BasicBlock* assertbb = new llvm::BasicBlock("assert", p->topfunc(), oldend);
|
||||
llvm::BasicBlock* endbb = new llvm::BasicBlock("endassert", p->topfunc(), oldend);
|
||||
|
||||
return 0;
|
||||
// test condition
|
||||
llvm::Value* condval = cond->getRVal();
|
||||
condval = DtoBoolean(condval);
|
||||
|
||||
// branch
|
||||
new llvm::BranchInst(endbb, assertbb, condval, p->scopebb());
|
||||
|
||||
// call assert runtime functions
|
||||
p->scope() = IRScope(assertbb,endbb);
|
||||
DtoAssert(&loc, msg ? msg->toElem(p) : NULL);
|
||||
|
||||
if (!gIR->scopereturned())
|
||||
new llvm::BranchInst(endbb, p->scopebb());
|
||||
|
||||
// rewrite the scope
|
||||
p->scope() = IRScope(endbb,oldend);
|
||||
|
||||
// no meaningful return value
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -2192,7 +2157,7 @@ DValue* HaltExp::toElem(IRState* p)
|
||||
Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
DtoAssert(DtoConstBool(false), &loc, NULL);
|
||||
DtoAssert(&loc, NULL);
|
||||
|
||||
new llvm::UnreachableInst(p->scopebb());
|
||||
return 0;
|
||||
@@ -2207,10 +2172,7 @@ DValue* DelegateExp::toElem(IRState* p)
|
||||
|
||||
DValue* u = e1->toElem(p);
|
||||
|
||||
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
|
||||
|
||||
const llvm::Type* int8ptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::PointerType* int8ptrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* lval;
|
||||
if (p->topexp() && p->topexp()->e2 == this) {
|
||||
@@ -2229,21 +2191,32 @@ DValue* DelegateExp::toElem(IRState* p)
|
||||
if (nestvar)
|
||||
uval = nestvar;
|
||||
else
|
||||
uval = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
uval = llvm::ConstantPointerNull::get(int8ptrty);
|
||||
}
|
||||
else {
|
||||
uval = u->getRVal();
|
||||
}
|
||||
|
||||
llvm::Value* context = DtoGEP(lval,zero,zero,"tmp",p->scopebb());
|
||||
llvm::Value* castcontext = DtoBitCast(uval,int8ptrty);
|
||||
new llvm::StoreInst(castcontext, context, p->scopebb());
|
||||
llvm::Value* context = DtoGEPi(lval,0,0,"tmp");
|
||||
llvm::Value* castcontext = DtoBitCast(uval, int8ptrty);
|
||||
DtoStore(castcontext, context);
|
||||
|
||||
llvm::Value* fptr = DtoGEP(lval,zero,one,"tmp",p->scopebb());
|
||||
llvm::Value* fptr = DtoGEPi(lval,0,1,"tmp");
|
||||
|
||||
assert(func->llvmValue);
|
||||
llvm::Value* castfptr = DtoBitCast(func->llvmValue,fptr->getType()->getContainedType(0));
|
||||
new llvm::StoreInst(castfptr, fptr, p->scopebb());
|
||||
Logger::println("func: '%s'", func->toPrettyChars());
|
||||
|
||||
llvm::Value* castfptr;
|
||||
if (func->isVirtual())
|
||||
castfptr = DtoVirtualFunctionPointer(u, func);
|
||||
else if (func->isAbstract())
|
||||
assert(0 && "TODO delegate to abstract method");
|
||||
else if (func->toParent()->isInterfaceDeclaration())
|
||||
assert(0 && "TODO delegate to interface method");
|
||||
else
|
||||
castfptr = func->llvmValue;
|
||||
|
||||
castfptr = DtoBitCast(castfptr, fptr->getType()->getContainedType(0));
|
||||
DtoStore(castfptr, fptr);
|
||||
|
||||
return new DVarValue(type, lval, true);
|
||||
}
|
||||
@@ -2279,7 +2252,7 @@ DValue* IdentityExp::toElem(IRState* p)
|
||||
if (t1->ty == Tpointer && v->isNull() && l->getType() != r->getType()) {
|
||||
r = llvm::ConstantPointerNull::get(isaPointer(l->getType()));
|
||||
}
|
||||
Logger::cout() << "l = " << *l << " r = " << *r << '\n';
|
||||
//Logger::cout() << "l = " << *l << " r = " << *r << '\n';
|
||||
eval = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
|
||||
}
|
||||
return new DImValue(type, eval);
|
||||
@@ -2368,9 +2341,9 @@ DValue* NegExp::toElem(IRState* p)
|
||||
zero = llvm::ConstantInt::get(val->getType(), 0, true);
|
||||
else if (t->isfloating()) {
|
||||
if (t->ty == Tfloat32 || t->ty == Timaginary32)
|
||||
zero = llvm::ConstantFP::get(val->getType(), float(0));
|
||||
zero = llvm::ConstantFP::get(val->getType(), llvm::APFloat(0.0f));
|
||||
else if (t->ty == Tfloat64 || t->ty == Tfloat80 || t->ty == Timaginary64 || t->ty == Timaginary80)
|
||||
zero = llvm::ConstantFP::get(val->getType(), double(0));
|
||||
zero = llvm::ConstantFP::get(val->getType(), llvm::APFloat(0.0));
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
@@ -2619,11 +2592,11 @@ DValue* StructLiteralExp::toElem(IRState* p)
|
||||
}
|
||||
const llvm::StructType* t = llvm::StructType::get(tys);
|
||||
if (t != llt) {
|
||||
if (gTargetData->getTypeSize(t) != gTargetData->getTypeSize(llt)) {
|
||||
Logger::cout() << "got size " << gTargetData->getTypeSize(t) << ", expected " << gTargetData->getTypeSize(llt) << '\n';
|
||||
if (getABITypeSize(t) != getABITypeSize(llt)) {
|
||||
Logger::cout() << "got size " << getABITypeSize(t) << ", expected " << getABITypeSize(llt) << '\n';
|
||||
assert(0 && "type size mismatch");
|
||||
}
|
||||
sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp");
|
||||
sptr = DtoBitCast(sptr, getPtrToType(t));
|
||||
Logger::cout() << "sptr type is now: " << *t << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
131
gen/tollvm.cpp
131
gen/tollvm.cpp
@@ -82,9 +82,9 @@ const llvm::Type* DtoType(Type* t)
|
||||
case Tpointer: {
|
||||
assert(t->next);
|
||||
if (t->next->ty == Tvoid)
|
||||
return (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
return (const llvm::Type*)getPtrToType(llvm::Type::Int8Ty);
|
||||
else
|
||||
return (const llvm::Type*)llvm::PointerType::get(DtoType(t->next));
|
||||
return (const llvm::Type*)getPtrToType(DtoType(t->next));
|
||||
}
|
||||
|
||||
// arrays
|
||||
@@ -117,11 +117,11 @@ const llvm::Type* DtoType(Type* t)
|
||||
TypeStruct* ts = (TypeStruct*)t;
|
||||
assert(ts->sym);
|
||||
DtoResolveDsymbol(ts->sym);
|
||||
return t->llvmType->get();
|
||||
return ts->sym->llvmIRStruct->recty.get();//t->llvmType->get();
|
||||
}
|
||||
|
||||
case Tclass: {
|
||||
if (!t->llvmType || *t->llvmType == NULL) {
|
||||
/*if (!t->llvmType || *t->llvmType == NULL) {
|
||||
// recursive or cyclic declaration
|
||||
if (!gIR->structs.empty())
|
||||
{
|
||||
@@ -130,17 +130,17 @@ const llvm::Type* DtoType(Type* t)
|
||||
{
|
||||
if (t == (*i)->type)
|
||||
{
|
||||
return llvm::PointerType::get((*i)->recty.get());
|
||||
return getPtrToType((*i)->recty.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
Logger::println("no type found");
|
||||
}
|
||||
}*/
|
||||
|
||||
TypeClass* tc = (TypeClass*)t;
|
||||
assert(tc->sym);
|
||||
DtoResolveDsymbol(tc->sym);
|
||||
return llvm::PointerType::get(t->llvmType->get());
|
||||
return getPtrToType(tc->sym->llvmIRStruct->recty.get());//t->llvmType->get());
|
||||
}
|
||||
|
||||
// functions
|
||||
@@ -182,7 +182,7 @@ const llvm::Type* DtoType(Type* t)
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(DtoType(taa->key));
|
||||
types.push_back(DtoType(taa->next));
|
||||
return llvm::PointerType::get(llvm::StructType::get(types));
|
||||
return getPtrToType(llvm::StructType::get(types));
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -196,9 +196,9 @@ const llvm::Type* DtoType(Type* t)
|
||||
|
||||
const llvm::StructType* DtoDelegateType(Type* t)
|
||||
{
|
||||
const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::Type* i8ptr = getPtrToType(llvm::Type::Int8Ty);
|
||||
const llvm::Type* func = DtoFunctionType(t->next, i8ptr);
|
||||
const llvm::Type* funcptr = llvm::PointerType::get(func);
|
||||
const llvm::Type* funcptr = getPtrToType(func);
|
||||
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(i8ptr);
|
||||
@@ -214,7 +214,7 @@ static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool
|
||||
const llvm::Type* int8ty = (const llvm::Type*)llvm::Type::Int8Ty;
|
||||
const llvm::Type* int32ty = (const llvm::Type*)llvm::Type::Int32Ty;
|
||||
const llvm::Type* int64ty = (const llvm::Type*)llvm::Type::Int64Ty;
|
||||
const llvm::Type* int8ptrty = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::Type* int8ptrty = (const llvm::Type*)getPtrToType(llvm::Type::Int8Ty);
|
||||
const llvm::Type* voidty = (const llvm::Type*)llvm::Type::VoidTy;
|
||||
|
||||
assert(gIR);
|
||||
@@ -284,7 +284,7 @@ llvm::Value* DtoNullDelegate(llvm::Value* v)
|
||||
assert(gIR);
|
||||
d_uns64 n = (global.params.is64bit) ? 16 : 8;
|
||||
|
||||
llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::Type* i8p_ty = getPtrToType(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* arr = new llvm::BitCastInst(v,i8p_ty,"tmp",gIR->scopebb());
|
||||
|
||||
@@ -310,7 +310,7 @@ llvm::Value* DtoDelegateCopy(llvm::Value* dst, llvm::Value* src)
|
||||
|
||||
d_uns64 n = (global.params.is64bit) ? 16 : 8;
|
||||
|
||||
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
|
||||
llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb());
|
||||
@@ -434,10 +434,8 @@ llvm::Value* DtoBoolean(llvm::Value* val)
|
||||
}
|
||||
}
|
||||
else if (isaPointer(t)) {
|
||||
const llvm::Type* st = DtoSize_t();
|
||||
llvm::Value* ptrasint = new llvm::PtrToIntInst(val,st,"tmp",gIR->scopebb());
|
||||
llvm::Value* zero = llvm::ConstantInt::get(st, 0, false);
|
||||
return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, ptrasint, zero, "tmp", gIR->scopebb());
|
||||
llvm::Value* zero = llvm::Constant::getNullValue(t);
|
||||
return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, val, zero, "tmp", gIR->scopebb());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -615,7 +613,7 @@ llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty)
|
||||
/*size_t sz = gTargetData->getTypeSize(ty);
|
||||
llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false);
|
||||
if (ptr == 0) {
|
||||
llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty);
|
||||
ptr = llvm::ConstantPointerNull::get(i8pty);
|
||||
}
|
||||
return DtoRealloc(ptr, n);*/
|
||||
@@ -634,7 +632,7 @@ llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* n)
|
||||
|
||||
llvm::Value* newptr = ptr;
|
||||
|
||||
llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty);
|
||||
if (ptr->getType() != i8pty) {
|
||||
newptr = new llvm::BitCastInst(ptr,i8pty,"tmp",gIR->scopebb());
|
||||
}
|
||||
@@ -649,30 +647,33 @@ llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* n)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg)
|
||||
void DtoAssert(Loc* loc, DValue* msg)
|
||||
{
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assert");
|
||||
const llvm::FunctionType* fnt = fn->getFunctionType();
|
||||
std::vector<llvm::Value*> args;
|
||||
llvm::Constant* c;
|
||||
|
||||
std::vector<llvm::Value*> llargs;
|
||||
llargs.resize(3);
|
||||
llargs[0] = cond ? DtoBoolean(cond) : llvm::ConstantInt::getFalse();
|
||||
llargs[1] = DtoConstUint(loc->linnum);
|
||||
if (msg)
|
||||
llargs[2] = msg->getRVal();
|
||||
else {
|
||||
llvm::Constant* c = DtoConstSlice(DtoConstSize_t(0), DtoConstNullPtr(llvm::Type::Int8Ty));
|
||||
static llvm::AllocaInst* alloc = 0;
|
||||
if (!alloc || alloc->getParent()->getParent() != gIR->func()->func) {
|
||||
alloc = new llvm::AllocaInst(c->getType(), "assertnullparam", gIR->topallocapoint());
|
||||
DtoSetArrayToNull(alloc);
|
||||
}
|
||||
llargs[2] = alloc;
|
||||
}
|
||||
// func
|
||||
const char* fname = msg ? "_d_assert_msg" : "_d_assert";
|
||||
|
||||
assert(fn);
|
||||
llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
||||
call->setCallingConv(llvm::CallingConv::C);
|
||||
// msg param
|
||||
if (msg) args.push_back(msg->getRVal());
|
||||
|
||||
// file param
|
||||
c = DtoConstString(loc->filename);
|
||||
llvm::AllocaInst* alloc = new llvm::AllocaInst(c->getType(), "srcfile", gIR->topallocapoint());
|
||||
llvm::Value* ptr = DtoGEPi(alloc, 0,0, "tmp");
|
||||
DtoStore(c->getOperand(0), ptr);
|
||||
ptr = DtoGEPi(alloc, 0,1, "tmp");
|
||||
DtoStore(c->getOperand(1), ptr);
|
||||
args.push_back(alloc);
|
||||
|
||||
// line param
|
||||
c = DtoConstUint(loc->linnum);
|
||||
args.push_back(c);
|
||||
|
||||
// call
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
|
||||
llvm::CallInst* call = new llvm::CallInst(fn, args.begin(), args.end(), "", gIR->scopebb());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1191,9 +1192,9 @@ llvm::ConstantFP* DtoConstFP(Type* t, long double value)
|
||||
{
|
||||
TY ty = DtoDType(t)->ty;
|
||||
if (ty == Tfloat32 || ty == Timaginary32)
|
||||
return llvm::ConstantFP::get(llvm::Type::FloatTy, float(value));
|
||||
return llvm::ConstantFP::get(llvm::Type::FloatTy, llvm::APFloat(float(value)));
|
||||
else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tfloat80 || ty == Timaginary80)
|
||||
return llvm::ConstantFP::get(llvm::Type::DoubleTy, double(value));
|
||||
return llvm::ConstantFP::get(llvm::Type::DoubleTy, llvm::APFloat(double(value)));
|
||||
}
|
||||
|
||||
|
||||
@@ -1227,7 +1228,7 @@ llvm::Constant* DtoConstStringPtr(const char* str, const char* section)
|
||||
llvm::Constant* DtoConstNullPtr(const llvm::Type* t)
|
||||
{
|
||||
return llvm::ConstantPointerNull::get(
|
||||
llvm::PointerType::get(t)
|
||||
getPtrToType(t)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1235,7 +1236,7 @@ llvm::Constant* DtoConstNullPtr(const llvm::Type* t)
|
||||
|
||||
void DtoMemSetZero(llvm::Value* dst, llvm::Value* nbytes)
|
||||
{
|
||||
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
llvm::Value *dstarr;
|
||||
if (dst->getType() == arrty)
|
||||
{
|
||||
@@ -1263,7 +1264,7 @@ void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes)
|
||||
{
|
||||
assert(dst->getType() == src->getType());
|
||||
|
||||
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
||||
llvm::Value *dstarr, *srcarr;
|
||||
if (dst->getType() == arrty)
|
||||
{
|
||||
@@ -1309,11 +1310,11 @@ bool DtoCanLoad(llvm::Value* ptr)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t)
|
||||
llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t, const char* name)
|
||||
{
|
||||
if (v->getType() == t)
|
||||
return v;
|
||||
return gIR->ir->CreateBitCast(v, t, "tmp");
|
||||
return gIR->ir->CreateBitCast(v, t, name ? name : "tmp");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1370,6 +1371,36 @@ llvm::GlobalVariable* isaGlobalVar(llvm::Value* v)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const llvm::PointerType* getPtrToType(const llvm::Type* t)
|
||||
{
|
||||
return llvm::PointerType::get(t, 0);
|
||||
}
|
||||
|
||||
llvm::ConstantPointerNull* getNullPtr(const llvm::Type* t)
|
||||
{
|
||||
const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(t);
|
||||
return llvm::ConstantPointerNull::get(pt);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t getTypeBitSize(const llvm::Type* t)
|
||||
{
|
||||
return gTargetData->getTypeSizeInBits(t);
|
||||
}
|
||||
|
||||
size_t getTypeStoreSize(const llvm::Type* t)
|
||||
{
|
||||
return gTargetData->getTypeStoreSize(t);
|
||||
}
|
||||
|
||||
size_t getABITypeSize(const llvm::Type* t)
|
||||
{
|
||||
return gTargetData->getABITypeSize(t);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool DtoIsTemplateInstance(Dsymbol* s)
|
||||
{
|
||||
if (!s) return false;
|
||||
@@ -1656,7 +1687,7 @@ void DtoEmptyAllLists()
|
||||
void DtoForceDeclareDsymbol(Dsymbol* dsym)
|
||||
{
|
||||
if (dsym->llvmDeclared) return;
|
||||
Logger::println("DtoForceDeclareDsymbol(%s)", dsym->toChars());
|
||||
Logger::println("DtoForceDeclareDsymbol(%s)", dsym->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
DtoResolveDsymbol(dsym);
|
||||
|
||||
@@ -1670,7 +1701,7 @@ void DtoForceDeclareDsymbol(Dsymbol* dsym)
|
||||
void DtoForceConstInitDsymbol(Dsymbol* dsym)
|
||||
{
|
||||
if (dsym->llvmInitialized) return;
|
||||
Logger::println("DtoForceConstInitDsymbol(%s)", dsym->toChars());
|
||||
Logger::println("DtoForceConstInitDsymbol(%s)", dsym->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
DtoResolveDsymbol(dsym);
|
||||
|
||||
@@ -1685,7 +1716,7 @@ void DtoForceConstInitDsymbol(Dsymbol* dsym)
|
||||
void DtoForceDefineDsymbol(Dsymbol* dsym)
|
||||
{
|
||||
if (dsym->llvmDefined) return;
|
||||
Logger::println("DtoForceDefineDsymbol(%s)", dsym->toChars());
|
||||
Logger::println("DtoForceDefineDsymbol(%s)", dsym->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
DtoResolveDsymbol(dsym);
|
||||
|
||||
|
||||
13
gen/tollvm.h
13
gen/tollvm.h
@@ -39,7 +39,7 @@ llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::stri
|
||||
llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty);
|
||||
llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* len);
|
||||
|
||||
void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg);
|
||||
void DtoAssert(Loc* loc, DValue* msg);
|
||||
|
||||
llvm::Value* DtoNestedContext(FuncDeclaration* func);
|
||||
llvm::Value* DtoNestedVariable(VarDeclaration* vd);
|
||||
@@ -81,7 +81,7 @@ void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
|
||||
bool DtoCanLoad(llvm::Value* ptr);
|
||||
llvm::Value* DtoLoad(llvm::Value* src);
|
||||
void DtoStore(llvm::Value* src, llvm::Value* dst);
|
||||
llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t);
|
||||
llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t, const char* name=0);
|
||||
|
||||
// llvm::dyn_cast wrappers
|
||||
const llvm::PointerType* isaPointer(llvm::Value* v);
|
||||
@@ -95,6 +95,15 @@ llvm::ConstantInt* isaConstantInt(llvm::Value* v);
|
||||
llvm::Argument* isaArgument(llvm::Value* v);
|
||||
llvm::GlobalVariable* isaGlobalVar(llvm::Value* v);
|
||||
|
||||
// llvm::T::get(...) wrappers
|
||||
const llvm::PointerType* getPtrToType(const llvm::Type* t);
|
||||
llvm::ConstantPointerNull* getNullPtr(const llvm::Type* t);
|
||||
|
||||
// type sizes
|
||||
size_t getTypeBitSize(const llvm::Type* t);
|
||||
size_t getTypeStoreSize(const llvm::Type* t);
|
||||
size_t getABITypeSize(const llvm::Type* t);
|
||||
|
||||
// basic operations
|
||||
void DtoAssign(DValue* lhs, DValue* rhs);
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ void Module::genobjfile()
|
||||
ir.module->setDataLayout(global.params.data_layout);
|
||||
|
||||
// heavily inspired by tools/llc/llc.cpp:200-230
|
||||
const llvm::TargetMachineRegistry::Entry* targetEntry;
|
||||
const llvm::TargetMachineRegistry::entry* targetEntry;
|
||||
std::string targetError;
|
||||
targetEntry = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(*ir.module, targetError);
|
||||
assert(targetEntry && "Failed to find a static target for module");
|
||||
@@ -118,7 +118,7 @@ void Module::genobjfile()
|
||||
|
||||
// emit the llvm main function if necessary
|
||||
if (ir.emitMain) {
|
||||
DtoMain();
|
||||
//DtoMain();
|
||||
}
|
||||
|
||||
// verify the llvm
|
||||
@@ -295,7 +295,7 @@ void Module::genmoduleinfo()
|
||||
initVec.push_back(c);
|
||||
|
||||
// monitor
|
||||
c = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
c = getNullPtr(getPtrToType(llvm::Type::Int8Ty));
|
||||
initVec.push_back(c);
|
||||
|
||||
// name
|
||||
@@ -321,14 +321,15 @@ void Module::genmoduleinfo()
|
||||
}
|
||||
}
|
||||
// has import array?
|
||||
if (!importInits.empty()) {
|
||||
const llvm::ArrayType* importArrTy = llvm::ArrayType::get(llvm::PointerType::get(moduleinfoTy), importInits.size());
|
||||
if (!importInits.empty())
|
||||
{
|
||||
const llvm::ArrayType* importArrTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size());
|
||||
c = llvm::ConstantArray::get(importArrTy, importInits);
|
||||
std::string m_name("_D");
|
||||
m_name.append(mangle());
|
||||
m_name.append("9__importsZ");
|
||||
llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(importArrTy, true, llvm::GlobalValue::InternalLinkage, c, m_name, gIR->module);
|
||||
c = llvm::ConstantExpr::getBitCast(m_gvar, llvm::PointerType::get(importArrTy->getElementType()));
|
||||
c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(importArrTy->getElementType()));
|
||||
c = DtoConstSlice(DtoConstSize_t(importInits.size()), c);
|
||||
}
|
||||
else
|
||||
@@ -351,19 +352,25 @@ void Module::genmoduleinfo()
|
||||
for (size_t i = 0; i < aclasses.dim; i++)
|
||||
{
|
||||
ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i];
|
||||
if (cd->isInterfaceDeclaration())
|
||||
{
|
||||
Logger::println("skipping interface '%s'", cd->toPrettyChars());
|
||||
continue;
|
||||
}
|
||||
Logger::println("class: %s", cd->toPrettyChars());
|
||||
assert(cd->llvmClass);
|
||||
classInits.push_back(cd->llvmClass);
|
||||
}
|
||||
// has class array?
|
||||
if (!classInits.empty()) {
|
||||
const llvm::ArrayType* classArrTy = llvm::ArrayType::get(llvm::PointerType::get(classinfoTy), classInits.size());
|
||||
if (!classInits.empty())
|
||||
{
|
||||
const llvm::ArrayType* classArrTy = llvm::ArrayType::get(getPtrToType(classinfoTy), classInits.size());
|
||||
c = llvm::ConstantArray::get(classArrTy, classInits);
|
||||
std::string m_name("_D");
|
||||
m_name.append(mangle());
|
||||
m_name.append("9__classesZ");
|
||||
llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(classArrTy, true, llvm::GlobalValue::InternalLinkage, c, m_name, gIR->module);
|
||||
c = llvm::ConstantExpr::getBitCast(m_gvar, llvm::PointerType::get(classArrTy->getElementType()));
|
||||
c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(classArrTy->getElementType()));
|
||||
c = DtoConstSlice(DtoConstSize_t(classInits.size()), c);
|
||||
}
|
||||
else
|
||||
@@ -420,9 +427,9 @@ void Module::genmoduleinfo()
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, constMI, MIname, gIR->module);
|
||||
|
||||
// declare the appending array
|
||||
const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(llvm::PointerType::get(llvm::Type::Int8Ty), 1);
|
||||
const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(getPtrToType(llvm::Type::Int8Ty), 1);
|
||||
std::vector<llvm::Constant*> appendInits;
|
||||
appendInits.push_back(llvm::ConstantExpr::getBitCast(gvar, llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
appendInits.push_back(llvm::ConstantExpr::getBitCast(gvar, getPtrToType(llvm::Type::Int8Ty)));
|
||||
llvm::Constant* appendInit = llvm::ConstantArray::get(appendArrTy, appendInits);
|
||||
std::string appendName("_d_moduleinfo_array");
|
||||
llvm::GlobalVariable* appendVar = new llvm::GlobalVariable(appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName, gIR->module);
|
||||
@@ -446,7 +453,8 @@ void Declaration::toObjFile()
|
||||
|
||||
void InterfaceDeclaration::toObjFile()
|
||||
{
|
||||
Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
|
||||
//Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
|
||||
gIR->resolveList.push_back(this);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
@@ -491,7 +499,7 @@ void VarDeclaration::toObjFile()
|
||||
if (isDataseg())
|
||||
{
|
||||
// we don't want to touch private static members at all !!!
|
||||
if ((prot() & PROTprivate) && getModule() != gIR->dmodule)
|
||||
if ((prot() == PROTprivate) && getModule() != gIR->dmodule)
|
||||
return;
|
||||
|
||||
// don't duplicate work
|
||||
|
||||
@@ -371,7 +371,7 @@ void TypeInfoTypedefDeclaration::llvmDefine()
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// monitor
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
sinits.push_back(getNullPtr(getPtrToType(llvm::Type::Int8Ty)));
|
||||
|
||||
assert(tinfo->ty == Ttypedef);
|
||||
TypeTypedef *tc = (TypeTypedef *)tinfo;
|
||||
@@ -400,10 +400,10 @@ void TypeInfoTypedefDeclaration::llvmDefine()
|
||||
assert(sinits.back()->getType() == stype->getElementType(3));
|
||||
|
||||
// void[] init
|
||||
const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::PointerType* initpt = getPtrToType(llvm::Type::Int8Ty);
|
||||
if (tinfo->isZeroInit() || !sd->init) // 0 initializer, or the same as the base type
|
||||
{
|
||||
sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
|
||||
sinits.push_back(DtoConstSlice(DtoConstSize_t(0), getNullPtr(initpt)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -412,7 +412,7 @@ void TypeInfoTypedefDeclaration::llvmDefine()
|
||||
ciname.append("__init");
|
||||
llvm::GlobalVariable* civar = new llvm::GlobalVariable(DtoType(sd->basetype),true,llvm::GlobalValue::InternalLinkage,ci,ciname,gIR->module);
|
||||
llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(civar, initpt);
|
||||
size_t cisize = gTargetData->getTypeSize(DtoType(sd->basetype));
|
||||
size_t cisize = getTypeStoreSize(DtoType(sd->basetype));
|
||||
sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ void TypeInfoEnumDeclaration::llvmDefine()
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// monitor
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
|
||||
|
||||
assert(tinfo->ty == Tenum);
|
||||
TypeEnum *tc = (TypeEnum *)tinfo;
|
||||
@@ -485,7 +485,7 @@ void TypeInfoEnumDeclaration::llvmDefine()
|
||||
assert(sinits.back()->getType() == stype->getElementType(3));
|
||||
|
||||
// void[] init
|
||||
const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::PointerType* initpt = getPtrToType(llvm::Type::Int8Ty);
|
||||
if (tinfo->isZeroInit() || !sd->defaultval) // 0 initializer, or the same as the base type
|
||||
{
|
||||
sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
|
||||
@@ -498,7 +498,7 @@ void TypeInfoEnumDeclaration::llvmDefine()
|
||||
ciname.append("__init");
|
||||
llvm::GlobalVariable* civar = new llvm::GlobalVariable(memty,true,llvm::GlobalValue::InternalLinkage,ci,ciname,gIR->module);
|
||||
llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(civar, initpt);
|
||||
size_t cisize = gTargetData->getTypeSize(memty);
|
||||
size_t cisize = getTypeStoreSize(memty);
|
||||
sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
|
||||
}
|
||||
|
||||
@@ -537,7 +537,7 @@ static llvm::Constant* LLVM_D_Define_TypeInfoBase(Type* basetype, TypeInfoDeclar
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// monitor
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
|
||||
|
||||
// TypeInfo base
|
||||
Logger::println("generating base typeinfo");
|
||||
@@ -649,7 +649,7 @@ void TypeInfoStaticArrayDeclaration::llvmDefine()
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// monitor
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
|
||||
|
||||
// value typeinfo
|
||||
assert(tinfo->ty == Tsarray);
|
||||
@@ -712,7 +712,7 @@ void TypeInfoAssociativeArrayDeclaration::llvmDefine()
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// monitor
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
|
||||
|
||||
// get type
|
||||
assert(tinfo->ty == Taarray);
|
||||
@@ -847,7 +847,7 @@ void TypeInfoStructDeclaration::llvmDefine()
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// monitor
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
|
||||
|
||||
// char[] name
|
||||
char *name = sd->toPrettyChars();
|
||||
@@ -856,14 +856,14 @@ void TypeInfoStructDeclaration::llvmDefine()
|
||||
assert(sinits.back()->getType() == stype->getElementType(2));
|
||||
|
||||
// void[] init
|
||||
const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
const llvm::PointerType* initpt = getPtrToType(llvm::Type::Int8Ty);
|
||||
if (sd->zeroInit) // 0 initializer, or the same as the base type
|
||||
{
|
||||
sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t cisize = gTargetData->getTypeSize(tc->llvmType->get());
|
||||
size_t cisize = getTypeStoreSize(tc->llvmType->get());
|
||||
llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(sd->llvmInit, initpt);
|
||||
sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
|
||||
}
|
||||
@@ -1046,7 +1046,7 @@ void TypeInfoClassDeclaration::llvmDefine()
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// monitor
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
|
||||
|
||||
// get classinfo
|
||||
assert(tinfo->ty == Tclass);
|
||||
@@ -1102,7 +1102,7 @@ void TypeInfoInterfaceDeclaration::llvmDefine()
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// monitor
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
|
||||
|
||||
// get classinfo
|
||||
assert(tinfo->ty == Tclass);
|
||||
@@ -1158,7 +1158,7 @@ void TypeInfoTupleDeclaration::llvmDefine()
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// monitor
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)));
|
||||
|
||||
// create elements array
|
||||
assert(tinfo->ty == Ttuple);
|
||||
@@ -1168,7 +1168,7 @@ void TypeInfoTupleDeclaration::llvmDefine()
|
||||
std::vector<llvm::Constant*> arrInits;
|
||||
|
||||
const llvm::Type* tiTy = Type::typeinfo->type->llvmType->get();
|
||||
tiTy = llvm::PointerType::get(tiTy);
|
||||
tiTy = getPtrToType(tiTy);
|
||||
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ exeext=
|
||||
objext=bc
|
||||
|
||||
|
||||
version=LLVM
|
||||
version=LLVMDC
|
||||
noversion=DigitalMars
|
||||
noversion=GNU
|
||||
testversion=linux
|
||||
|
||||
@@ -120,6 +120,7 @@ gen/functions.h
|
||||
gen/irstate.cpp
|
||||
gen/irstate.h
|
||||
gen/llvm.h
|
||||
gen/llvmd.h
|
||||
gen/logger.cpp
|
||||
gen/logger.h
|
||||
gen/optimizer.cpp
|
||||
@@ -255,187 +256,24 @@ tango/lib/common/tango/stdc/posix
|
||||
tango/lib/common/tango/stdc/posix/pthread_darwin.d
|
||||
tango/lib/common/tango/stdc/wrap.c
|
||||
tango/lib/compiler
|
||||
tango/lib/compiler/dmd
|
||||
tango/lib/compiler/dmd/aApply.d
|
||||
tango/lib/compiler/dmd/aApplyR.d
|
||||
tango/lib/compiler/dmd/aaA.d
|
||||
tango/lib/compiler/dmd/adi.d
|
||||
tango/lib/compiler/dmd/alloca.d
|
||||
tango/lib/compiler/dmd/arraycast.d
|
||||
tango/lib/compiler/dmd/arraycat.d
|
||||
tango/lib/compiler/dmd/cast.d
|
||||
tango/lib/compiler/dmd/cmath2.d
|
||||
tango/lib/compiler/dmd/compiler.d
|
||||
tango/lib/compiler/dmd/complex.c
|
||||
tango/lib/compiler/dmd/cover.d
|
||||
tango/lib/compiler/dmd/critical.c
|
||||
tango/lib/compiler/dmd/deh.c
|
||||
tango/lib/compiler/dmd/deh2.d
|
||||
tango/lib/compiler/dmd/dmain2.d
|
||||
tango/lib/compiler/dmd/genobj.d
|
||||
tango/lib/compiler/dmd/invariant.d
|
||||
tango/lib/compiler/dmd/lifetime.d
|
||||
tango/lib/compiler/dmd/llmath.d
|
||||
tango/lib/compiler/dmd/mars.h
|
||||
tango/lib/compiler/dmd/memory.d
|
||||
tango/lib/compiler/dmd/memset.d
|
||||
tango/lib/compiler/dmd/monitor.c
|
||||
tango/lib/compiler/dmd/obj.d
|
||||
tango/lib/compiler/dmd/qsort.d
|
||||
tango/lib/compiler/dmd/qsort2.d
|
||||
tango/lib/compiler/dmd/switch.d
|
||||
tango/lib/compiler/dmd/trace.d
|
||||
tango/lib/compiler/dmd/typeinfo
|
||||
tango/lib/compiler/dmd/typeinfo/ti_AC.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_Acdouble.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_Acfloat.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_Acreal.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_Adouble.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_Afloat.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_Ag.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_Aint.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_Along.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_Areal.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_Ashort.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_C.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_byte.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_cdouble.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_cfloat.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_char.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_creal.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_dchar.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_delegate.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_double.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_float.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_idouble.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_ifloat.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_int.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_ireal.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_long.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_ptr.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_real.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_short.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_ubyte.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_uint.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_ulong.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_ushort.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_void.d
|
||||
tango/lib/compiler/dmd/typeinfo/ti_wchar.d
|
||||
tango/lib/compiler/dmd/util
|
||||
tango/lib/compiler/dmd/util/console.d
|
||||
tango/lib/compiler/dmd/util/ctype.d
|
||||
tango/lib/compiler/dmd/util/string.d
|
||||
tango/lib/compiler/dmd/util/utf.d
|
||||
tango/lib/compiler/gdc
|
||||
tango/lib/compiler/gdc/aApply.d
|
||||
tango/lib/compiler/gdc/aApplyR.d
|
||||
tango/lib/compiler/gdc/aaA.d
|
||||
tango/lib/compiler/gdc/actest.d
|
||||
tango/lib/compiler/gdc/adi.d
|
||||
tango/lib/compiler/gdc/arraycast.d
|
||||
tango/lib/compiler/gdc/arraycat.d
|
||||
tango/lib/compiler/gdc/cast.d
|
||||
tango/lib/compiler/gdc/cmain.d
|
||||
tango/lib/compiler/gdc/cmath2.d
|
||||
tango/lib/compiler/gdc/compiler.d
|
||||
tango/lib/compiler/gdc/config
|
||||
tango/lib/compiler/gdc/config.h
|
||||
tango/lib/compiler/gdc/config/darwin8
|
||||
tango/lib/compiler/gdc/config/gen_config1.c
|
||||
tango/lib/compiler/gdc/config/gen_math.c
|
||||
tango/lib/compiler/gdc/config/gen_unix.c
|
||||
tango/lib/compiler/gdc/config/makestruct.h
|
||||
tango/lib/compiler/gdc/config/mingw
|
||||
tango/lib/compiler/gdc/config/skyos
|
||||
tango/lib/compiler/gdc/critical.c
|
||||
tango/lib/compiler/gdc/deh.c
|
||||
tango/lib/compiler/gdc/dgccmain2.d
|
||||
tango/lib/compiler/gdc/fpmath.d
|
||||
tango/lib/compiler/gdc/gcc
|
||||
tango/lib/compiler/gdc/gcc/aix_float.h
|
||||
tango/lib/compiler/gdc/gcc/builtins.d
|
||||
tango/lib/compiler/gdc/gcc/cbridge_fdset.c
|
||||
tango/lib/compiler/gdc/gcc/cbridge_math.c
|
||||
tango/lib/compiler/gdc/gcc/cbridge_stdio.c
|
||||
tango/lib/compiler/gdc/gcc/cbridge_time.c
|
||||
tango/lib/compiler/gdc/gcc/configext.d
|
||||
tango/lib/compiler/gdc/gcc/configunix.d
|
||||
tango/lib/compiler/gdc/gcc/deh.d
|
||||
tango/lib/compiler/gdc/gcc/fpmath.d
|
||||
tango/lib/compiler/gdc/gcc/support.d
|
||||
tango/lib/compiler/gdc/gcc/threadsem.d
|
||||
tango/lib/compiler/gdc/gcc/unwind.d
|
||||
tango/lib/compiler/gdc/genobj.d
|
||||
tango/lib/compiler/gdc/invariant.d
|
||||
tango/lib/compiler/gdc/lifetime.d
|
||||
tango/lib/compiler/gdc/mars.h
|
||||
tango/lib/compiler/gdc/memory.d
|
||||
tango/lib/compiler/gdc/memory_dyld.c
|
||||
tango/lib/compiler/gdc/memory_freebsd.c
|
||||
tango/lib/compiler/gdc/memset.d
|
||||
tango/lib/compiler/gdc/minimal.c
|
||||
tango/lib/compiler/gdc/monitor.c
|
||||
tango/lib/compiler/gdc/obj.d
|
||||
tango/lib/compiler/gdc/qsort2.d
|
||||
tango/lib/compiler/gdc/qsortg.d
|
||||
tango/lib/compiler/gdc/rundmain.d
|
||||
tango/lib/compiler/gdc/std
|
||||
tango/lib/compiler/gdc/std/intrinsic.d
|
||||
tango/lib/compiler/gdc/switch.d
|
||||
tango/lib/compiler/gdc/typeinfo
|
||||
tango/lib/compiler/gdc/typeinfo/ti_AC.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_Acdouble.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_Acfloat.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_Acreal.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_Adouble.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_Afloat.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_Ag.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_Aint.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_Along.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_Areal.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_Ashort.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_C.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_byte.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_cdouble.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_cfloat.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_char.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_creal.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_dchar.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_delegate.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_double.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_float.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_idouble.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_ifloat.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_int.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_ireal.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_long.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_ptr.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_real.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_short.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_ubyte.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_uint.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_ulong.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_ushort.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_void.d
|
||||
tango/lib/compiler/gdc/typeinfo/ti_wchar.d
|
||||
tango/lib/compiler/gdc/util
|
||||
tango/lib/compiler/gdc/util/console.d
|
||||
tango/lib/compiler/gdc/util/ctype.d
|
||||
tango/lib/compiler/gdc/util/string.d
|
||||
tango/lib/compiler/gdc/util/utf.d
|
||||
tango/lib/compiler/llvmdc
|
||||
tango/lib/compiler/llvmdc/aApply.d
|
||||
tango/lib/compiler/llvmdc/aApplyR.d
|
||||
tango/lib/compiler/llvmdc/aaA.d
|
||||
tango/lib/compiler/llvmdc/adi.d
|
||||
tango/lib/compiler/llvmdc/arrays.d
|
||||
tango/lib/compiler/llvmdc/build.sh
|
||||
tango/lib/compiler/llvmdc/cast.d
|
||||
tango/lib/compiler/llvmdc/contract.d
|
||||
tango/lib/compiler/llvmdc/critical.c
|
||||
tango/lib/compiler/llvmdc/dmain2.d
|
||||
tango/lib/compiler/llvmdc/eh.d
|
||||
tango/lib/compiler/llvmdc/genobj.d
|
||||
tango/lib/compiler/llvmdc/lifetime.d
|
||||
tango/lib/compiler/llvmdc/llvm
|
||||
tango/lib/compiler/llvmdc/llvm/intrinsic.di
|
||||
tango/lib/compiler/llvmdc/obj
|
||||
tango/lib/compiler/llvmdc/mars.h
|
||||
tango/lib/compiler/llvmdc/mem.d
|
||||
tango/lib/compiler/llvmdc/memory.d
|
||||
tango/lib/compiler/llvmdc/monitor.c
|
||||
tango/lib/compiler/llvmdc/qsort2.d
|
||||
tango/lib/compiler/llvmdc/std
|
||||
tango/lib/compiler/llvmdc/std/intrinsic.d
|
||||
@@ -900,6 +738,17 @@ tangotests/d.d
|
||||
tangotests/e.d
|
||||
tangotests/f.d
|
||||
tangotests/g.d
|
||||
tangotests/h.d
|
||||
tangotests/i.d
|
||||
tangotests/j.d
|
||||
tangotests/k.d
|
||||
tangotests/l.d
|
||||
tangotests/m.d
|
||||
tangotests/n.d
|
||||
tangotests/o.d
|
||||
tangotests/p.d
|
||||
tangotests/q.d
|
||||
tangotests/r.d
|
||||
test
|
||||
test/a.d
|
||||
test/aa1.d
|
||||
|
||||
@@ -481,6 +481,7 @@ void setTraceHandler( traceHandlerType h )
|
||||
// Overridable Callbacks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private extern(C) int printf(char*,...);
|
||||
|
||||
/**
|
||||
* A callback for assert errors in D. The user-supplied assert handler will
|
||||
@@ -493,8 +494,11 @@ void setTraceHandler( traceHandlerType h )
|
||||
*/
|
||||
extern (C) void onAssertError( char[] file, size_t line )
|
||||
{
|
||||
if( assertHandler is null )
|
||||
printf("Assertion failed:\n");
|
||||
printf("%.*s(%lu)\n", file.length, file.ptr, line);
|
||||
if( assertHandler is null ) {
|
||||
throw new AssertException( file, line );
|
||||
}
|
||||
assertHandler( file, line );
|
||||
}
|
||||
|
||||
@@ -511,6 +515,9 @@ extern (C) void onAssertError( char[] file, size_t line )
|
||||
*/
|
||||
extern (C) void onAssertErrorMsg( char[] file, size_t line, char[] msg )
|
||||
{
|
||||
printf("Assertion failed:\n");
|
||||
printf("%.*s(%lu):\n", file.length, file.ptr, line);
|
||||
printf("%.*s\n", msg.length, msg.ptr);
|
||||
if( assertHandler is null )
|
||||
throw new AssertException( msg, file, line );
|
||||
assertHandler( file, line, msg );
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
LIB_TARGET=libtango-cc-tango.a
|
||||
LIB_MASK=libtango-cc-tango*.a
|
||||
LIB_TARGET_C=libtango-cc-c-tango.a
|
||||
LIB_MASK_C=libtango-cc-c-tango*.a
|
||||
|
||||
CP=cp -f
|
||||
RM=rm -f
|
||||
@@ -33,6 +35,7 @@ DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=gcc
|
||||
LC=llvm-ar rsv
|
||||
CLC=ar rsv
|
||||
DC=llvmdc
|
||||
LLC=llvm-as
|
||||
|
||||
@@ -68,7 +71,7 @@ DOC_DEST=../../../doc/tango
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
tango : lib
|
||||
lib : tango.lib
|
||||
lib : tango.lib tango.clib
|
||||
doc : tango.doc
|
||||
|
||||
######################################################
|
||||
@@ -82,14 +85,15 @@ OBJ_CORE= \
|
||||
# core/ThreadASM.o
|
||||
|
||||
OBJ_STDC= \
|
||||
stdc/wrap.bc
|
||||
stdc/wrap.o
|
||||
# stdc/wrap.bc
|
||||
|
||||
OBJ_STDC_POSIX= \
|
||||
stdc/posix/pthread_darwin.o
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_CORE) \
|
||||
$(OBJ_STDC)
|
||||
$(OBJ_CORE)
|
||||
# $(OBJ_STDC)
|
||||
# $(OBJ_STDC_POSIX)
|
||||
|
||||
######################################################
|
||||
@@ -112,6 +116,14 @@ $(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) $@ $(ALL_OBJS)
|
||||
|
||||
|
||||
tango.clib : $(LIB_TARGET_C)
|
||||
|
||||
$(LIB_TARGET_C) : $(OBJ_STDC)
|
||||
$(RM) $@
|
||||
$(CLC) $@ $(OBJ_STDC)
|
||||
|
||||
|
||||
tango.doc : $(ALL_DOCS)
|
||||
echo Documentation generated.
|
||||
|
||||
@@ -127,8 +139,10 @@ tango.doc : $(ALL_DOCS)
|
||||
clean :
|
||||
find . -name "*.di" | xargs $(RM)
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(OBJ_STDC)
|
||||
$(RM) $(ALL_DOCS)
|
||||
find . -name "$(LIB_MASK)" | xargs $(RM)
|
||||
find . -name "$(LIB_MASK_C)" | xargs $(RM)
|
||||
|
||||
install :
|
||||
$(MD) $(INC_DEST)
|
||||
@@ -137,3 +151,4 @@ install :
|
||||
find . -name "*.html" -exec cp -f {} $(DOC_DEST)/{} \;
|
||||
$(MD) $(LIB_DEST)
|
||||
find . -name "$(LIB_MASK)" -exec cp -f {} $(LIB_DEST)/{} \;
|
||||
find . -name "$(LIB_MASK_C)" -exec cp -f {} $(LIB_DEST)/{} \;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; ModuleID = 'wrap.bc'
|
||||
@errno = external global i32 ; <i32*> [#uses=2]
|
||||
@errno = external thread_local global i32 ; <i32*> [#uses=2]
|
||||
|
||||
define i32 @getErrno() {
|
||||
entry:
|
||||
|
||||
@@ -99,7 +99,7 @@ Object _d_dynamic_cast(Object o, ClassInfo c)
|
||||
return o;
|
||||
}
|
||||
|
||||
int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout size_t offset)
|
||||
int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref size_t offset)
|
||||
{ int i;
|
||||
|
||||
if (oc is c)
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
extern(C):
|
||||
|
||||
void exit(int);
|
||||
int printf(char*,...);
|
||||
|
||||
void _d_assert(bool cond, uint line, char[] msg)
|
||||
{
|
||||
if (!cond) {
|
||||
printf("Aborted(%u): %.*s\n", line, msg.length, msg.ptr);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
160
tango/lib/compiler/llvmdc/critical.c
Normal file
160
tango/lib/compiler/llvmdc/critical.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright, Digital Mars
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/* ================================= Win32 ============================ */
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/******************************************
|
||||
* Enter/exit critical section.
|
||||
*/
|
||||
|
||||
/* We don't initialize critical sections unless we actually need them.
|
||||
* So keep a linked list of the ones we do use, and in the static destructor
|
||||
* code, walk the list and release them.
|
||||
*/
|
||||
|
||||
typedef struct D_CRITICAL_SECTION
|
||||
{
|
||||
struct D_CRITICAL_SECTION *next;
|
||||
CRITICAL_SECTION cs;
|
||||
} D_CRITICAL_SECTION;
|
||||
|
||||
static D_CRITICAL_SECTION *dcs_list;
|
||||
static D_CRITICAL_SECTION critical_section;
|
||||
static volatile int inited;
|
||||
|
||||
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
if (!dcs->next)
|
||||
{
|
||||
EnterCriticalSection(&critical_section.cs);
|
||||
if (!dcs->next) // if, in the meantime, another thread didn't set it
|
||||
{
|
||||
dcs->next = dcs_list;
|
||||
dcs_list = dcs;
|
||||
InitializeCriticalSection(&dcs->cs);
|
||||
}
|
||||
LeaveCriticalSection(&critical_section.cs);
|
||||
}
|
||||
EnterCriticalSection(&dcs->cs);
|
||||
}
|
||||
|
||||
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
LeaveCriticalSection(&dcs->cs);
|
||||
}
|
||||
|
||||
void _STI_critical_init()
|
||||
{
|
||||
if (!inited)
|
||||
{ InitializeCriticalSection(&critical_section.cs);
|
||||
dcs_list = &critical_section;
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_critical_term()
|
||||
{
|
||||
if (inited)
|
||||
{ inited = 0;
|
||||
while (dcs_list)
|
||||
{
|
||||
DeleteCriticalSection(&dcs_list->cs);
|
||||
dcs_list = dcs_list->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ================================= linux ============================ */
|
||||
|
||||
#if linux
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/******************************************
|
||||
* Enter/exit critical section.
|
||||
*/
|
||||
|
||||
/* We don't initialize critical sections unless we actually need them.
|
||||
* So keep a linked list of the ones we do use, and in the static destructor
|
||||
* code, walk the list and release them.
|
||||
*/
|
||||
|
||||
typedef struct D_CRITICAL_SECTION
|
||||
{
|
||||
struct D_CRITICAL_SECTION *next;
|
||||
pthread_mutex_t cs;
|
||||
} D_CRITICAL_SECTION;
|
||||
|
||||
static D_CRITICAL_SECTION *dcs_list;
|
||||
static D_CRITICAL_SECTION critical_section;
|
||||
static pthread_mutexattr_t _criticals_attr;
|
||||
|
||||
void _STI_critical_init(void);
|
||||
void _STD_critical_term(void);
|
||||
|
||||
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
if (!dcs_list)
|
||||
{ _STI_critical_init();
|
||||
atexit(_STD_critical_term);
|
||||
}
|
||||
//printf("_d_criticalenter(dcs = x%x)\n", dcs);
|
||||
if (!dcs->next)
|
||||
{
|
||||
pthread_mutex_lock(&critical_section.cs);
|
||||
if (!dcs->next) // if, in the meantime, another thread didn't set it
|
||||
{
|
||||
dcs->next = dcs_list;
|
||||
dcs_list = dcs;
|
||||
pthread_mutex_init(&dcs->cs, &_criticals_attr);
|
||||
}
|
||||
pthread_mutex_unlock(&critical_section.cs);
|
||||
}
|
||||
pthread_mutex_lock(&dcs->cs);
|
||||
}
|
||||
|
||||
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
//printf("_d_criticalexit(dcs = x%x)\n", dcs);
|
||||
pthread_mutex_unlock(&dcs->cs);
|
||||
}
|
||||
|
||||
void _STI_critical_init()
|
||||
{
|
||||
if (!dcs_list)
|
||||
{ //printf("_STI_critical_init()\n");
|
||||
pthread_mutexattr_init(&_criticals_attr);
|
||||
pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
|
||||
// The global critical section doesn't need to be recursive
|
||||
pthread_mutex_init(&critical_section.cs, 0);
|
||||
dcs_list = &critical_section;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_critical_term()
|
||||
{
|
||||
if (dcs_list)
|
||||
{ //printf("_STI_critical_term()\n");
|
||||
while (dcs_list)
|
||||
{
|
||||
//printf("\tlooping... %x\n", dcs_list);
|
||||
pthread_mutex_destroy(&dcs_list->cs);
|
||||
dcs_list = dcs_list->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
303
tango/lib/compiler/llvmdc/dmain2.d
Normal file
303
tango/lib/compiler/llvmdc/dmain2.d
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Placed into the Public Domain.
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
*/
|
||||
|
||||
private
|
||||
{
|
||||
import util.console;
|
||||
|
||||
import tango.stdc.stddef;
|
||||
import tango.stdc.stdlib;
|
||||
import tango.stdc.string;
|
||||
}
|
||||
|
||||
version( Win32 )
|
||||
{
|
||||
extern (Windows) void* LocalFree(void*);
|
||||
extern (Windows) wchar_t* GetCommandLineW();
|
||||
extern (Windows) wchar_t** CommandLineToArgvW(wchar_t*, int*);
|
||||
extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
|
||||
pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW
|
||||
pragma(lib, "tango-win32-dmd.lib"); // links Tango's Win32 library to reduce EXE size
|
||||
}
|
||||
|
||||
extern (C) void _STI_monitor_staticctor();
|
||||
extern (C) void _STD_monitor_staticdtor();
|
||||
extern (C) void _STI_critical_init();
|
||||
extern (C) void _STD_critical_term();
|
||||
extern (C) void gc_init();
|
||||
extern (C) void gc_term();
|
||||
extern (C) void _minit();
|
||||
extern (C) void _moduleCtor();
|
||||
extern (C) void _moduleDtor();
|
||||
extern (C) void thread_joinAll();
|
||||
|
||||
//debug=PRINTF;
|
||||
debug(PRINTF) extern (C) int printf(char*, ...);
|
||||
|
||||
/***********************************
|
||||
* These functions must be defined for any D program linked
|
||||
* against this library.
|
||||
*/
|
||||
extern (C) void onAssertError( char[] file, size_t line );
|
||||
extern (C) void onAssertErrorMsg( char[] file, size_t line, char[] msg );
|
||||
extern (C) void onArrayBoundsError( char[] file, size_t line );
|
||||
extern (C) void onSwitchError( char[] file, size_t line );
|
||||
extern (C) bool runModuleUnitTests();
|
||||
|
||||
// this function is called from the utf module
|
||||
//extern (C) void onUnicodeError( char[] msg, size_t idx );
|
||||
|
||||
/***********************************
|
||||
* These are internal callbacks for various language errors.
|
||||
*/
|
||||
extern (C) void _d_assert( char[] file, uint line )
|
||||
{
|
||||
onAssertError( file, line );
|
||||
}
|
||||
|
||||
extern (C) void _d_assert_msg( char[] msg, char[] file, uint line )
|
||||
{
|
||||
onAssertErrorMsg( file, line, msg );
|
||||
}
|
||||
|
||||
extern (C) void _d_array_bounds( char[] file, uint line )
|
||||
{
|
||||
onArrayBoundsError( file, line );
|
||||
}
|
||||
|
||||
extern (C) void _d_switch_error( char[] file, uint line )
|
||||
{
|
||||
onSwitchError( file, line );
|
||||
}
|
||||
|
||||
bool _d_isHalting = false;
|
||||
|
||||
extern (C) bool rt_isHalting()
|
||||
{
|
||||
return _d_isHalting;
|
||||
}
|
||||
|
||||
extern (C) bool rt_trapExceptions = true;
|
||||
|
||||
void _d_criticalInit()
|
||||
{
|
||||
version (linux)
|
||||
{
|
||||
_STI_monitor_staticctor();
|
||||
_STI_critical_init();
|
||||
}
|
||||
}
|
||||
|
||||
extern (C) bool rt_init( void delegate( Exception ) dg = null )
|
||||
{
|
||||
_d_criticalInit();
|
||||
|
||||
try
|
||||
{
|
||||
gc_init();
|
||||
version (Win32)
|
||||
_minit();
|
||||
_moduleCtor();
|
||||
return true;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
if( dg )
|
||||
dg( e );
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
_d_criticalTerm();
|
||||
return false;
|
||||
}
|
||||
|
||||
void _d_criticalTerm()
|
||||
{
|
||||
version (linux)
|
||||
{
|
||||
_STD_critical_term();
|
||||
_STD_monitor_staticdtor();
|
||||
}
|
||||
}
|
||||
|
||||
extern (C) bool rt_term( void delegate( Exception ) dg = null )
|
||||
{
|
||||
try
|
||||
{
|
||||
thread_joinAll();
|
||||
_d_isHalting = true;
|
||||
_moduleDtor();
|
||||
gc_term();
|
||||
return true;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
if( dg )
|
||||
dg( e );
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
_d_criticalTerm();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* The D main() function supplied by the user's program
|
||||
*/
|
||||
int main(char[][] args);
|
||||
|
||||
/***********************************
|
||||
* Substitutes for the C main() function.
|
||||
* It's purpose is to wrap the call to the D main()
|
||||
* function and catch any unhandled exceptions.
|
||||
*/
|
||||
|
||||
extern (C) int main(int argc, char **argv, char** env)
|
||||
{
|
||||
char[][] args;
|
||||
int result;
|
||||
|
||||
version (linux)
|
||||
{
|
||||
debug(PRINTF) printf("main ctors\n");
|
||||
_STI_monitor_staticctor();
|
||||
_STI_critical_init();
|
||||
}
|
||||
|
||||
debug(PRINTF) printf("main args\n");
|
||||
version (Win32)
|
||||
{
|
||||
wchar_t* wcbuf = GetCommandLineW();
|
||||
size_t wclen = wcslen(wcbuf);
|
||||
int wargc = 0;
|
||||
wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
|
||||
assert(wargc == argc);
|
||||
|
||||
char* cargp = null;
|
||||
size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
|
||||
|
||||
cargp = cast(char*) alloca(cargl);
|
||||
args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
|
||||
|
||||
for (size_t i = 0, p = 0; i < wargc; i++)
|
||||
{
|
||||
int wlen = wcslen( wargs[i] );
|
||||
int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
|
||||
args[i] = cargp[p .. p+clen];
|
||||
p += clen; assert(p <= cargl);
|
||||
WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
|
||||
}
|
||||
LocalFree(wargs);
|
||||
wargs = null;
|
||||
wargc = 0;
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
|
||||
scope(exit) free(am);
|
||||
|
||||
for (size_t i = 0; i < argc; i++)
|
||||
{
|
||||
auto len = strlen(argv[i]);
|
||||
am[i] = argv[i][0 .. len];
|
||||
}
|
||||
args = am[0 .. argc];
|
||||
}
|
||||
|
||||
debug(PRINTF) printf("main trap exceptions\n");
|
||||
bool trapExceptions = rt_trapExceptions;
|
||||
|
||||
void tryExec(void delegate() dg)
|
||||
{
|
||||
debug(PRINTF) printf("main try exec\n");
|
||||
if (trapExceptions)
|
||||
{
|
||||
try
|
||||
{
|
||||
dg();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
while (e)
|
||||
{
|
||||
if (e.file)
|
||||
{
|
||||
debug(PRINTF) printf("%.*s(%u): %.*s\n", e.file.length, e.file.ptr, e.line, e.msg.length, e.msg.ptr);
|
||||
console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// debug(PRINTF) printf("%.*s\n", e.toString());
|
||||
console (e.classinfo.name)(": ")(e.toString)("\n");
|
||||
}
|
||||
e = e.next;
|
||||
}
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
catch (Object o)
|
||||
{
|
||||
// fprintf(stderr, "%.*s\n", o.toString());
|
||||
console (o.toString)("\n");
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dg();
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: The lifetime of a process is much like the lifetime of an object:
|
||||
// it is initialized, then used, then destroyed. If initialization
|
||||
// fails, the successive two steps are never reached. However, if
|
||||
// initialization succeeds, then cleanup will occur even if the use
|
||||
// step fails in some way. Here, the use phase consists of running
|
||||
// the user's main function. If main terminates with an exception,
|
||||
// the exception is handled and then cleanup begins. An exception
|
||||
// thrown during cleanup, however, will abort the cleanup process.
|
||||
|
||||
void runMain()
|
||||
{
|
||||
debug(PRINTF) printf("main runMain\n");
|
||||
result = main(args);
|
||||
}
|
||||
|
||||
void runAll()
|
||||
{
|
||||
debug(PRINTF) printf("main runAll\n");
|
||||
gc_init();
|
||||
version (Win32)
|
||||
_minit();
|
||||
_moduleCtor();
|
||||
if (runModuleUnitTests())
|
||||
tryExec(&runMain);
|
||||
thread_joinAll();
|
||||
_d_isHalting = true;
|
||||
_moduleDtor();
|
||||
gc_term();
|
||||
}
|
||||
|
||||
tryExec(&runAll);
|
||||
|
||||
version (linux)
|
||||
{
|
||||
debug(PRINTF) printf("main dtor\n");
|
||||
_STD_critical_term();
|
||||
_STD_monitor_staticdtor();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
17
tango/lib/compiler/llvmdc/eh.d
Normal file
17
tango/lib/compiler/llvmdc/eh.d
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Temporary exception handling stubs
|
||||
*/
|
||||
|
||||
import util.console;
|
||||
|
||||
private extern(C) void abort();
|
||||
|
||||
extern(C) void _d_throw_exception(Object e)
|
||||
{
|
||||
console("Exception: ");
|
||||
if (e !is null)
|
||||
{
|
||||
console(e.toString())("\n");
|
||||
}
|
||||
abort();
|
||||
}
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
module object;
|
||||
|
||||
//debug=PRINTF;
|
||||
|
||||
private
|
||||
{
|
||||
import tango.stdc.string; // : memcmp, memcpy;
|
||||
@@ -962,19 +964,8 @@ class ModuleInfo
|
||||
// linux: this gets initialized in _moduleCtor()
|
||||
extern (C) ModuleInfo[] _moduleinfo_array;
|
||||
|
||||
|
||||
version (linux)
|
||||
{
|
||||
// This linked list is created by a compiler generated function inserted
|
||||
// into the .ctor list by the compiler.
|
||||
struct ModuleReference
|
||||
{
|
||||
ModuleReference* next;
|
||||
ModuleInfo mod;
|
||||
}
|
||||
|
||||
extern (C) ModuleReference* _Dmodule_ref; // start of linked list
|
||||
}
|
||||
// llvmdc method
|
||||
extern (C) void** _d_get_moduleinfo_array();
|
||||
|
||||
ModuleInfo[] _moduleinfo_dtors;
|
||||
uint _moduleinfo_dtors_i;
|
||||
@@ -989,19 +980,20 @@ extern (C) int _fatexit(void *);
|
||||
extern (C) void _moduleCtor()
|
||||
{
|
||||
debug(PRINTF) printf("_moduleCtor()\n");
|
||||
version (linux)
|
||||
{
|
||||
int len = 0;
|
||||
ModuleReference *mr;
|
||||
|
||||
for (mr = _Dmodule_ref; mr; mr = mr.next)
|
||||
len++;
|
||||
_moduleinfo_array = new ModuleInfo[len];
|
||||
len = 0;
|
||||
for (mr = _Dmodule_ref; mr; mr = mr.next)
|
||||
{ _moduleinfo_array[len] = mr.mod;
|
||||
len++;
|
||||
}
|
||||
ModuleInfo* mrbegin = cast(ModuleInfo*)_d_get_moduleinfo_array();
|
||||
assert(mrbegin !is null);
|
||||
|
||||
int len = 0;
|
||||
ModuleInfo* mr;
|
||||
for (mr = mrbegin; *mr !is null; ++mr)
|
||||
len++;
|
||||
_moduleinfo_array = new ModuleInfo[len];
|
||||
|
||||
len = 0;
|
||||
for (mr = mrbegin; *mr !is null; ++mr)
|
||||
{ _moduleinfo_array[len] = *mr;
|
||||
len++;
|
||||
}
|
||||
|
||||
version (Win32)
|
||||
@@ -1014,6 +1006,7 @@ extern (C) void _moduleCtor()
|
||||
debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
|
||||
_moduleIndependentCtors();
|
||||
_moduleCtor2(_moduleinfo_array, 0);
|
||||
debug(PRINTF) printf("_moduleCtor() DONE\n");
|
||||
}
|
||||
|
||||
extern (C) void _moduleIndependentCtors()
|
||||
@@ -1026,6 +1019,7 @@ extern (C) void _moduleIndependentCtors()
|
||||
(*m.ictor)();
|
||||
}
|
||||
}
|
||||
debug(PRINTF) printf("_moduleIndependentCtors() DONE\n");
|
||||
}
|
||||
|
||||
void _moduleCtor2(ModuleInfo[] mi, int skip)
|
||||
@@ -1038,10 +1032,10 @@ void _moduleCtor2(ModuleInfo[] mi, int skip)
|
||||
debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
|
||||
if (!m)
|
||||
continue;
|
||||
debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
|
||||
debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name.length, m.name.ptr);
|
||||
if (m.flags & MIctordone)
|
||||
continue;
|
||||
debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
|
||||
debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name.length, m.name.ptr, m);
|
||||
|
||||
if (m.ctor || m.dtor)
|
||||
{
|
||||
@@ -1069,6 +1063,7 @@ void _moduleCtor2(ModuleInfo[] mi, int skip)
|
||||
_moduleCtor2(m.importedModules, 1);
|
||||
}
|
||||
}
|
||||
debug(PRINTF) printf("_moduleCtor2() DONE\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
*/
|
||||
module lifetime;
|
||||
|
||||
//debug=PRINTF;
|
||||
debug=PRINTF2;
|
||||
|
||||
private
|
||||
{
|
||||
@@ -33,6 +35,7 @@ private
|
||||
import tango.stdc.string;
|
||||
import tango.stdc.stdarg;
|
||||
debug(PRINTF) import tango.stdc.stdio;
|
||||
else debug(PRINTF2) import tango.stdc.stdio;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +89,8 @@ extern (C) Object _d_newclass(ClassInfo ci)
|
||||
{
|
||||
void* p;
|
||||
|
||||
debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name);
|
||||
debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name.ptr);
|
||||
/+
|
||||
if (ci.flags & 1) // if COM object
|
||||
{ /* COM objects are not garbage collected, they are reference counted
|
||||
* using AddRef() and Release(). They get free'd by C's free()
|
||||
@@ -98,10 +102,11 @@ extern (C) Object _d_newclass(ClassInfo ci)
|
||||
onOutOfMemoryError();
|
||||
}
|
||||
else
|
||||
+/
|
||||
{
|
||||
p = gc_malloc(ci.init.length,
|
||||
BlkAttr.FINALIZE | (ci.flags & 2 ? BlkAttr.NO_SCAN : 0));
|
||||
debug(PRINTF) printf(" p = %p\n", p);
|
||||
debug(PRINTF2) printf(" p = %p\n", p);
|
||||
}
|
||||
|
||||
debug(PRINTF)
|
||||
@@ -119,7 +124,8 @@ extern (C) Object _d_newclass(ClassInfo ci)
|
||||
}
|
||||
|
||||
// initialize it
|
||||
(cast(byte*) p)[0 .. ci.init.length] = ci.init[];
|
||||
// llvmdc does this inline
|
||||
//(cast(byte*) p)[0 .. ci.init.length] = ci.init[];
|
||||
|
||||
debug(PRINTF) printf("initialization done\n");
|
||||
return cast(Object) p;
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
LIB_TARGET=libtango-rt-llvmdc.a
|
||||
LIB_MASK=libtango-rt-llvmdc*.a
|
||||
|
||||
LIB_TARGET_C=libtango-rt-c-llvmdc.a
|
||||
LIB_MASK_C=libtango-rt-c-llvmdc*.a
|
||||
|
||||
CP=cp -f
|
||||
RM=rm -f
|
||||
MD=mkdir -p
|
||||
@@ -30,6 +33,7 @@ DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=gcc
|
||||
LC=llvm-ar rsv
|
||||
CLC=ar rsv
|
||||
DC=llvmdc
|
||||
LLC=llvm-as
|
||||
|
||||
@@ -60,10 +64,13 @@ LIB_DEST=..
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
lib : llvmdc.lib
|
||||
lib : llvmdc.lib llvmdc.clib
|
||||
doc : llvmdc.doc
|
||||
|
||||
######################################################
|
||||
OBJ_C= \
|
||||
monitor.o \
|
||||
critical.o
|
||||
|
||||
OBJ_BASE= \
|
||||
aaA.bc \
|
||||
@@ -72,7 +79,8 @@ OBJ_BASE= \
|
||||
adi.bc \
|
||||
arrays.bc \
|
||||
cast.bc \
|
||||
contract.bc \
|
||||
dmain2.bc \
|
||||
eh.bc \
|
||||
genobj.bc \
|
||||
lifetime.bc \
|
||||
mem.bc \
|
||||
@@ -147,6 +155,12 @@ $(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) $@ $(ALL_OBJS)
|
||||
|
||||
llvmdc.clib : $(LIB_TARGET_C)
|
||||
|
||||
$(LIB_TARGET_C) : $(OBJ_C)
|
||||
$(RM) $@
|
||||
$(CLC) $@ $(OBJ_C)
|
||||
|
||||
llvmdc.doc : $(ALL_DOCS)
|
||||
echo No documentation available.
|
||||
|
||||
@@ -155,9 +169,12 @@ llvmdc.doc : $(ALL_DOCS)
|
||||
clean :
|
||||
find . -name "*.di" | xargs $(RM)
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(OBJ_C)
|
||||
$(RM) $(ALL_DOCS)
|
||||
$(RM) $(LIB_MASK)
|
||||
$(RM) $(LIB_MASK_C)
|
||||
|
||||
install :
|
||||
$(MD) $(LIB_DEST)
|
||||
$(CP) $(LIB_MASK) $(LIB_DEST)/.
|
||||
$(CP) $(LIB_MASK_C) $(LIB_DEST)/.
|
||||
|
||||
104
tango/lib/compiler/llvmdc/mars.h
Normal file
104
tango/lib/compiler/llvmdc/mars.h
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright, Digital Mars
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ClassInfo;
|
||||
struct Vtbl;
|
||||
|
||||
typedef struct Vtbl
|
||||
{
|
||||
size_t len;
|
||||
void **vptr;
|
||||
} Vtbl;
|
||||
|
||||
typedef struct Interface
|
||||
{
|
||||
struct ClassInfo *classinfo;
|
||||
struct Vtbl vtbl;
|
||||
int offset;
|
||||
} Interface;
|
||||
|
||||
typedef struct Object
|
||||
{
|
||||
void **vptr;
|
||||
void *monitor;
|
||||
} Object;
|
||||
|
||||
typedef struct ClassInfo
|
||||
{
|
||||
Object object;
|
||||
|
||||
size_t initlen;
|
||||
void *init;
|
||||
|
||||
size_t namelen;
|
||||
char *name;
|
||||
|
||||
Vtbl vtbl;
|
||||
|
||||
size_t interfacelen;
|
||||
Interface *interfaces;
|
||||
|
||||
struct ClassInfo *baseClass;
|
||||
|
||||
void *destructor;
|
||||
void *invariant;
|
||||
|
||||
int flags;
|
||||
} ClassInfo;
|
||||
|
||||
typedef struct Exception
|
||||
{
|
||||
Object object;
|
||||
|
||||
size_t msglen;
|
||||
char* msg;
|
||||
|
||||
size_t filelen;
|
||||
char* file;
|
||||
|
||||
size_t line;
|
||||
|
||||
struct Exception *next;
|
||||
} Exception;
|
||||
|
||||
typedef struct Array
|
||||
{
|
||||
size_t length;
|
||||
void *ptr;
|
||||
} Array;
|
||||
|
||||
typedef struct Delegate
|
||||
{
|
||||
void *thisptr;
|
||||
void (*funcptr)();
|
||||
} Delegate;
|
||||
|
||||
void _d_monitorenter(Object *h);
|
||||
void _d_monitorexit(Object *h);
|
||||
|
||||
int _d_isbaseof(ClassInfo *b, ClassInfo *c);
|
||||
Object *_d_dynamic_cast(Object *o, ClassInfo *ci);
|
||||
|
||||
Object * _d_newclass(ClassInfo *ci);
|
||||
void _d_delclass(Object **p);
|
||||
|
||||
void _d_OutOfMemory();
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
207
tango/lib/compiler/llvmdc/monitor.c
Normal file
207
tango/lib/compiler/llvmdc/monitor.c
Normal file
@@ -0,0 +1,207 @@
|
||||
// D programming language runtime library
|
||||
// Public Domain
|
||||
// written by Walter Bright, Digital Mars
|
||||
// www.digitalmars.com
|
||||
|
||||
// This is written in C because nobody has written a pthreads interface
|
||||
// to D yet.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _WIN32
|
||||
#elif linux
|
||||
#define USE_PTHREADS 1
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if USE_PTHREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
// This is what the monitor reference in Object points to
|
||||
typedef struct Monitor
|
||||
{
|
||||
void* impl; // for user-level monitors
|
||||
|
||||
#if _WIN32
|
||||
CRITICAL_SECTION mon;
|
||||
#endif
|
||||
|
||||
#if USE_PTHREADS
|
||||
pthread_mutex_t mon;
|
||||
#endif
|
||||
} Monitor;
|
||||
|
||||
#define MONPTR(h) (&((Monitor *)(h)->monitor)->mon)
|
||||
|
||||
static volatile int inited;
|
||||
|
||||
/* =============================== Win32 ============================ */
|
||||
|
||||
#if _WIN32
|
||||
|
||||
static CRITICAL_SECTION _monitor_critsec;
|
||||
|
||||
void _STI_monitor_staticctor()
|
||||
{
|
||||
if (!inited)
|
||||
{ InitializeCriticalSection(&_monitor_critsec);
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_monitor_staticdtor()
|
||||
{
|
||||
if (inited)
|
||||
{ inited = 0;
|
||||
DeleteCriticalSection(&_monitor_critsec);
|
||||
}
|
||||
}
|
||||
|
||||
void _d_monitor_create(Object *h)
|
||||
{
|
||||
/*
|
||||
* NOTE: Assume this is only called when h->monitor is null prior to the
|
||||
* call. However, please note that another thread may call this function
|
||||
* at the same time, so we can not assert this here. Instead, try and
|
||||
* create a lock, and if one already exists then forget about it.
|
||||
*/
|
||||
|
||||
//printf("+_d_monitor_create(%p)\n", h);
|
||||
assert(h);
|
||||
Monitor *cs = NULL;
|
||||
EnterCriticalSection(&_monitor_critsec);
|
||||
if (!h->monitor)
|
||||
{
|
||||
cs = (Monitor *)calloc(sizeof(Monitor), 1);
|
||||
assert(cs);
|
||||
InitializeCriticalSection(&cs->mon);
|
||||
h->monitor = (void *)cs;
|
||||
cs = NULL;
|
||||
}
|
||||
LeaveCriticalSection(&_monitor_critsec);
|
||||
if (cs)
|
||||
free(cs);
|
||||
//printf("-_d_monitor_create(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_destroy(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_destroy(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
DeleteCriticalSection(MONPTR(h));
|
||||
free((void *)h->monitor);
|
||||
h->monitor = NULL;
|
||||
//printf("-_d_monitor_destroy(%p)\n", h);
|
||||
}
|
||||
|
||||
int _d_monitor_lock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_acquire(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
EnterCriticalSection(MONPTR(h));
|
||||
//printf("-_d_monitor_acquire(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_unlock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_release(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
LeaveCriticalSection(MONPTR(h));
|
||||
//printf("-_d_monitor_release(%p)\n", h);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* =============================== linux ============================ */
|
||||
|
||||
#if USE_PTHREADS
|
||||
|
||||
// Includes attribute fixes from David Friedman's GDC port
|
||||
|
||||
static pthread_mutex_t _monitor_critsec;
|
||||
static pthread_mutexattr_t _monitors_attr;
|
||||
|
||||
void _STI_monitor_staticctor()
|
||||
{
|
||||
if (!inited)
|
||||
{
|
||||
pthread_mutexattr_init(&_monitors_attr);
|
||||
pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
pthread_mutex_init(&_monitor_critsec, 0);
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_monitor_staticdtor()
|
||||
{
|
||||
if (inited)
|
||||
{ inited = 0;
|
||||
pthread_mutex_destroy(&_monitor_critsec);
|
||||
pthread_mutexattr_destroy(&_monitors_attr);
|
||||
}
|
||||
}
|
||||
|
||||
void _d_monitor_create(Object *h)
|
||||
{
|
||||
/*
|
||||
* NOTE: Assume this is only called when h->monitor is null prior to the
|
||||
* call. However, please note that another thread may call this function
|
||||
* at the same time, so we can not assert this here. Instead, try and
|
||||
* create a lock, and if one already exists then forget about it.
|
||||
*/
|
||||
|
||||
//printf("+_d_monitor_create(%p)\n", h);
|
||||
assert(h);
|
||||
Monitor *cs = NULL;
|
||||
pthread_mutex_lock(&_monitor_critsec);
|
||||
if (!h->monitor)
|
||||
{
|
||||
cs = (Monitor *)calloc(sizeof(Monitor), 1);
|
||||
assert(cs);
|
||||
pthread_mutex_init(&cs->mon, & _monitors_attr);
|
||||
h->monitor = (void *)cs;
|
||||
cs = NULL;
|
||||
}
|
||||
pthread_mutex_unlock(&_monitor_critsec);
|
||||
if (cs)
|
||||
free(cs);
|
||||
//printf("-_d_monitor_create(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_destroy(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_destroy(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
pthread_mutex_destroy(MONPTR(h));
|
||||
free((void *)h->monitor);
|
||||
h->monitor = NULL;
|
||||
//printf("-_d_monitor_destroy(%p)\n", h);
|
||||
}
|
||||
|
||||
int _d_monitor_lock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_acquire(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
pthread_mutex_lock(MONPTR(h));
|
||||
//printf("-_d_monitor_acquire(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_unlock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_release(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
pthread_mutex_unlock(MONPTR(h));
|
||||
//printf("-_d_monitor_release(%p)\n", h);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -75,9 +75,9 @@ struct Console
|
||||
}
|
||||
|
||||
// emit an integer to the console
|
||||
Console opCall (uint i)
|
||||
Console opCall (size_t i)
|
||||
{
|
||||
char[10] tmp = void;
|
||||
char[20] tmp = void;
|
||||
|
||||
return console (intToUtf8 (tmp, i));
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
LIB_TARGET=libtango-base-llvmdc.a
|
||||
LIB_MASK=libtango-base-llvmdc*.a
|
||||
LIB_TARGET_C=libtango-base-c-llvmdc.a
|
||||
LIB_MASK_C=libtango-base-c-llvmdc*.a
|
||||
|
||||
DIR_CC=./common/tango
|
||||
DIR_RT=./compiler/llvmdc
|
||||
@@ -23,13 +25,14 @@ MD=mkdir -p
|
||||
|
||||
CC=gcc
|
||||
LC=llvm-ar rsv
|
||||
CLC=ar rsv
|
||||
DC=llvmdc
|
||||
|
||||
ADD_CFLAGS=
|
||||
ADD_DFLAGS=
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
targets : lib clib doc
|
||||
all : lib clib doc
|
||||
|
||||
######################################################
|
||||
|
||||
@@ -49,6 +52,8 @@ lib : $(ALL_OBJS)
|
||||
$(LC) $(LIB_TARGET) `find $(DIR_CC) -name "*.bc" | xargs echo`
|
||||
$(LC) $(LIB_TARGET) `find $(DIR_RT) -name "*.bc" | xargs echo`
|
||||
$(LC) $(LIB_TARGET) `find $(DIR_GC) -name "*.bc" | xargs echo`
|
||||
$(CLC) $(LIB_TARGET_C) `find $(DIR_CC) -name "*.o" | xargs echo`
|
||||
$(CLC) $(LIB_TARGET_C) `find $(DIR_RT) -name "*.o" | xargs echo`
|
||||
|
||||
doc : $(ALL_DOCS)
|
||||
make -C $(DIR_CC) -fllvmdc.mak doc
|
||||
@@ -65,9 +70,11 @@ clean :
|
||||
make -C $(DIR_RT) -fllvmdc.mak clean
|
||||
make -C $(DIR_GC) -fllvmdc.mak clean
|
||||
$(RM) $(LIB_MASK)
|
||||
$(RM) $(LIB_MASK_C)
|
||||
|
||||
install :
|
||||
make -C $(DIR_CC) -fllvmdc.mak install
|
||||
make -C $(DIR_RT) -fllvmdc.mak install
|
||||
make -C $(DIR_GC) -fllvmdc.mak install
|
||||
# $(CP) $(LIB_MASK) $(LIB_DEST)/.
|
||||
$(CP) $(LIB_MASK) $(LIB_DEST)/.
|
||||
$(CP) $(LIB_MASK_C) $(LIB_DEST)/.
|
||||
|
||||
@@ -621,14 +621,21 @@ static Console.Output Cout, /// the standard output stream
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
extern(C) int printf(char*, ...);
|
||||
|
||||
static this ()
|
||||
{
|
||||
printf("STATIC INIT FOR CONSOLE\n");
|
||||
printf("Cin\n");
|
||||
auto conduit = new Console.Conduit (0);
|
||||
assert(conduit);
|
||||
Cin = new Console.Input (conduit, conduit.redirected);
|
||||
|
||||
printf("Cout\n");
|
||||
conduit = new Console.Conduit (1);
|
||||
Cout = new Console.Output (conduit, conduit.redirected);
|
||||
|
||||
printf("Cerr\n");
|
||||
conduit = new Console.Conduit (2);
|
||||
Cerr = new Console.Output (conduit, conduit.redirected);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
extern(C) int printf(char*,...);
|
||||
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
printf("Hello World!\n");
|
||||
|
||||
27
tangotests/h.d
Normal file
27
tangotests/h.d
Normal file
@@ -0,0 +1,27 @@
|
||||
interface Iin
|
||||
{
|
||||
void[] read(size_t n);
|
||||
}
|
||||
|
||||
interface Iout
|
||||
{
|
||||
size_t write(void[] d);
|
||||
}
|
||||
|
||||
class C : Iin
|
||||
{
|
||||
void[] read(size_t n)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
size_t write(void[] d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void func()
|
||||
{
|
||||
scope c = new C;
|
||||
}
|
||||
20
tangotests/i.d
Normal file
20
tangotests/i.d
Normal file
@@ -0,0 +1,20 @@
|
||||
interface IN
|
||||
{
|
||||
void func();
|
||||
}
|
||||
abstract class AC
|
||||
{
|
||||
abstract void func();
|
||||
long ll;
|
||||
}
|
||||
class C : AC
|
||||
{
|
||||
void func()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void func()
|
||||
{
|
||||
scope c = new C;
|
||||
}
|
||||
44
tangotests/j.d
Normal file
44
tangotests/j.d
Normal file
@@ -0,0 +1,44 @@
|
||||
module j;
|
||||
|
||||
interface Inter1
|
||||
{
|
||||
int func1();
|
||||
}
|
||||
|
||||
interface Inter2
|
||||
{
|
||||
int func2();
|
||||
}
|
||||
|
||||
class C12 : Inter1, Inter2
|
||||
{
|
||||
int func1()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int func2()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
void func(Object c)
|
||||
{
|
||||
auto i1 = cast(Inter1)c;
|
||||
assert(i1.func1() == 1);
|
||||
auto i2 = cast(Inter2)c;
|
||||
assert(i2.func2() == 2);
|
||||
auto j1 = cast(Inter1)i2;
|
||||
assert(j1.func1() == 1);
|
||||
auto j2 = cast(Inter2)i1;
|
||||
assert(j2.func2() == 2);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
scope c = new C12;
|
||||
func(c);
|
||||
printf("OK\n");
|
||||
}
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
31
tangotests/k.d
Normal file
31
tangotests/k.d
Normal file
@@ -0,0 +1,31 @@
|
||||
interface Inter
|
||||
{
|
||||
int func();
|
||||
}
|
||||
|
||||
extern(C) int printf(char*, ...);
|
||||
|
||||
class InterClass : Inter
|
||||
{
|
||||
int func()
|
||||
{
|
||||
return printf("InterClass.func()\n");
|
||||
}
|
||||
}
|
||||
|
||||
alias int delegate() dg_t;
|
||||
|
||||
void main()
|
||||
{
|
||||
scope c = new InterClass;
|
||||
|
||||
{
|
||||
Inter i = cast(Inter)c;
|
||||
{
|
||||
dg_t dg = &i.func;
|
||||
{
|
||||
int j = dg();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
tangotests/l.d
Normal file
11
tangotests/l.d
Normal file
@@ -0,0 +1,11 @@
|
||||
import tango.io.Console;
|
||||
|
||||
void main()
|
||||
{
|
||||
printf("enter\n");
|
||||
assert(Cout !is null);
|
||||
Cout("Hi, says LLVMDC + Tango").newline;
|
||||
printf("exit\n");
|
||||
}
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
10
tangotests/m.d
Normal file
10
tangotests/m.d
Normal file
@@ -0,0 +1,10 @@
|
||||
void main()
|
||||
{
|
||||
int* e = __errno_location();
|
||||
printf("&errno = %p\n", e);
|
||||
printf("errno = %d\n", *e);
|
||||
}
|
||||
|
||||
extern(C):
|
||||
int* __errno_location();
|
||||
int printf(char*,...);
|
||||
18
tangotests/n.d
Normal file
18
tangotests/n.d
Normal file
@@ -0,0 +1,18 @@
|
||||
struct Structure
|
||||
{
|
||||
static void static_method()
|
||||
{
|
||||
}
|
||||
|
||||
void method()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
//Structure.static_method();
|
||||
|
||||
Structure s;
|
||||
s.method();
|
||||
}
|
||||
24
tangotests/o.d
Normal file
24
tangotests/o.d
Normal file
@@ -0,0 +1,24 @@
|
||||
extern(C) int printf(char*, ...);
|
||||
|
||||
void func()
|
||||
{
|
||||
try
|
||||
{
|
||||
printf("try\n");
|
||||
return 0;
|
||||
}
|
||||
catch
|
||||
{
|
||||
printf("catch\n");
|
||||
}
|
||||
finally
|
||||
{
|
||||
printf("finally\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
func();
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
module interface1;
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
|
||||
interface Inter
|
||||
{
|
||||
void func();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module interface2;
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
|
||||
interface A
|
||||
{
|
||||
void a();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module interface3;
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
|
||||
interface I
|
||||
{
|
||||
void func();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module interface4;
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
|
||||
interface I
|
||||
{
|
||||
void func();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module interface5;
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
|
||||
interface I
|
||||
{
|
||||
void func();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module interface6;
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
|
||||
interface I
|
||||
{
|
||||
void Ifunc();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module interface7;
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
|
||||
interface I
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import llvm.intrinsic;
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
extern(C) int scanf(char*,...);
|
||||
|
||||
void main()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module mainargs1;
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
|
||||
void main(string[] args)
|
||||
{
|
||||
foreach(v; args)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module memory1;
|
||||
|
||||
extern(C) int printf(char*,...);
|
||||
|
||||
void main()
|
||||
{
|
||||
auto a = new int[16];
|
||||
|
||||
Reference in New Issue
Block a user