[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:
Tomas Lindquist Olsen
2008-01-14 05:11:54 +01:00
parent b15b3484c8
commit 4505b9b006
58 changed files with 1986 additions and 754 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -131,6 +131,7 @@ struct Param
char disassemble;
char llvmInline;
char llvmAnnotate;
char *runtimePath;
};
struct Global

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -8,7 +8,7 @@ exeext=
objext=bc
version=LLVM
version=LLVMDC
noversion=DigitalMars
noversion=GNU
testversion=linux

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

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

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

View File

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

View File

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

View File

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

View 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

View 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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,7 @@
extern(C) int printf(char*,...);
void main()
{
printf("Hello World!\n");

27
tangotests/h.d Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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();
}

View File

@@ -1,5 +1,7 @@
module interface1;
extern(C) int printf(char*,...);
interface Inter
{
void func();

View File

@@ -1,5 +1,7 @@
module interface2;
extern(C) int printf(char*,...);
interface A
{
void a();

View File

@@ -1,5 +1,7 @@
module interface3;
extern(C) int printf(char*,...);
interface I
{
void func();

View File

@@ -1,5 +1,7 @@
module interface4;
extern(C) int printf(char*,...);
interface I
{
void func();

View File

@@ -1,5 +1,7 @@
module interface5;
extern(C) int printf(char*,...);
interface I
{
void func();

View File

@@ -1,5 +1,7 @@
module interface6;
extern(C) int printf(char*,...);
interface I
{
void Ifunc();

View File

@@ -1,5 +1,7 @@
module interface7;
extern(C) int printf(char*,...);
interface I
{
}

View File

@@ -1,5 +1,6 @@
import llvm.intrinsic;
extern(C) int printf(char*,...);
extern(C) int scanf(char*,...);
void main()

View File

@@ -1,5 +1,7 @@
module mainargs1;
extern(C) int printf(char*,...);
void main(string[] args)
{
foreach(v; args)

View File

@@ -1,5 +1,7 @@
module memory1;
extern(C) int printf(char*,...);
void main()
{
auto a = new int[16];