mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-23 07:03:13 +01:00
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
Basically it tries to do the following in order: Resolve types, Declare symbols, Create constant initializers, Apply initializers, Generate functions bodies. ClassInfo is now has the most useful(biased?) members working. Probably other stuf...
This commit is contained in:
@@ -110,6 +110,8 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
bool llvmHasUnions;
|
||||
DUnion* llvmUnion;
|
||||
IRStruct* llvmIRStruct;
|
||||
bool llvmClassDeclared;
|
||||
bool llvmClassDefined;
|
||||
|
||||
AggregateDeclaration *isAggregateDeclaration() { return this; }
|
||||
};
|
||||
|
||||
@@ -48,7 +48,11 @@ Dsymbol::Dsymbol()
|
||||
this->llvmInternal2 = NULL;
|
||||
this->llvmValue = NULL;
|
||||
this->llvmDModule = NULL;
|
||||
this->llvmTouched = false;
|
||||
|
||||
this->llvmResolved = false;
|
||||
this->llvmDeclared = false;
|
||||
this->llvmInitialized = false;
|
||||
this->llvmDefined = false;
|
||||
}
|
||||
|
||||
Dsymbol::Dsymbol(Identifier *ident)
|
||||
@@ -66,7 +70,11 @@ Dsymbol::Dsymbol(Identifier *ident)
|
||||
this->llvmInternal2 = NULL;
|
||||
this->llvmValue = NULL;
|
||||
this->llvmDModule = NULL;
|
||||
this->llvmTouched = false;
|
||||
|
||||
this->llvmResolved = false;
|
||||
this->llvmDeclared = false;
|
||||
this->llvmInitialized = false;
|
||||
this->llvmDefined = false;
|
||||
}
|
||||
|
||||
int Dsymbol::equals(Object *o)
|
||||
|
||||
@@ -223,7 +223,10 @@ struct Dsymbol : Object
|
||||
llvm::Value* llvmValue;
|
||||
Module* llvmDModule;
|
||||
|
||||
bool llvmTouched;
|
||||
bool llvmResolved;
|
||||
bool llvmDeclared;
|
||||
bool llvmInitialized;
|
||||
bool llvmDefined;
|
||||
};
|
||||
|
||||
// Dsymbol that generates a scope
|
||||
|
||||
@@ -4374,6 +4374,7 @@ TypeClass::TypeClass(ClassDeclaration *sym)
|
||||
{
|
||||
this->sym = sym;
|
||||
llvmInit = 0;
|
||||
llvmVtblType = 0;
|
||||
}
|
||||
|
||||
char *TypeClass::toChars()
|
||||
|
||||
@@ -642,6 +642,7 @@ struct TypeClass : Type
|
||||
Symbol *toSymbol();
|
||||
|
||||
llvm::GlobalVariable* llvmInit;
|
||||
llvm::PATypeHolder* llvmVtblType;
|
||||
};
|
||||
|
||||
struct TypeTuple : Type
|
||||
|
||||
@@ -54,6 +54,8 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
llvmHasUnions = false;
|
||||
llvmUnion = NULL;
|
||||
llvmIRStruct = NULL;
|
||||
llvmClassDeclared = false;
|
||||
llvmClassDefined = false;
|
||||
}
|
||||
|
||||
enum PROT AggregateDeclaration::prot()
|
||||
|
||||
@@ -60,10 +60,8 @@ const llvm::ArrayType* DtoStaticArrayType(Type* t)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoNullArray(llvm::Value* v)
|
||||
void DtoSetArrayToNull(llvm::Value* v)
|
||||
{
|
||||
assert(gIR);
|
||||
|
||||
llvm::Value* len = DtoGEPi(v,0,0,"tmp",gIR->scopebb());
|
||||
llvm::Value* zerolen = llvm::ConstantInt::get(len->getType()->getContainedType(0), 0, false);
|
||||
new llvm::StoreInst(zerolen, len, gIR->scopebb());
|
||||
@@ -593,7 +591,7 @@ static llvm::Value* DtoArrayEqCmp_impl(const char* func, DValue* l, DValue* r, b
|
||||
if (useti) {
|
||||
TypeInfoDeclaration* ti = DtoDType(l->getType())->next->getTypeInfoDeclaration();
|
||||
if (!ti->llvmValue) {
|
||||
ti->toObjFile();
|
||||
DtoForceConstInitDsymbol(ti);
|
||||
}
|
||||
Logger::cout() << "typeinfo decl: " << *ti->llvmValue << '\n';
|
||||
|
||||
@@ -786,3 +784,85 @@ llvm::Value* DtoArrayPtr(DValue* v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
DValue* DtoCastArray(DValue* u, Type* to)
|
||||
{
|
||||
const llvm::Type* tolltype = DtoType(to);
|
||||
|
||||
Type* totype = DtoDType(to);
|
||||
Type* fromtype = DtoDType(u->getType());
|
||||
assert(fromtype->ty == Tarray || fromtype->ty == Tsarray);
|
||||
|
||||
llvm::Value* rval;
|
||||
llvm::Value* rval2;
|
||||
bool isslice = false;
|
||||
|
||||
Logger::cout() << "from array or sarray" << '\n';
|
||||
if (totype->ty == Tpointer) {
|
||||
Logger::cout() << "to pointer" << '\n';
|
||||
assert(fromtype->next == totype->next || totype->next->ty == Tvoid);
|
||||
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");
|
||||
}
|
||||
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);
|
||||
|
||||
const llvm::Type* ety = DtoType(fromtype->next);
|
||||
if (ety == llvm::Type::VoidTy)
|
||||
ety = llvm::Type::Int8Ty;
|
||||
|
||||
if (DSliceValue* usl = u->isSlice()) {
|
||||
Logger::println("from slice");
|
||||
Logger::cout() << "from: " << *usl->ptr << " to: " << *ptrty << '\n';
|
||||
rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", gIR->scopebb());
|
||||
if (fromtype->next->size() == totype->next->size())
|
||||
rval2 = usl->len;
|
||||
else
|
||||
rval2 = DtoArrayCastLength(usl->len, ety, ptrty->getContainedType(0));
|
||||
}
|
||||
else {
|
||||
llvm::Value* uval = u->getRVal();
|
||||
if (fromtype->ty == Tsarray) {
|
||||
Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
|
||||
assert(isaPointer(uval->getType()));
|
||||
const llvm::ArrayType* arrty = isaArray(uval->getType()->getContainedType(0));
|
||||
rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
|
||||
rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
|
||||
rval = new llvm::BitCastInst(uval, ptrty, "tmp", gIR->scopebb());
|
||||
}
|
||||
else {
|
||||
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
|
||||
rval2 = DtoGEP(uval,zero,zero,"tmp",gIR->scopebb());
|
||||
rval2 = new llvm::LoadInst(rval2, "tmp", gIR->scopebb());
|
||||
rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
|
||||
|
||||
rval = DtoGEP(uval,zero,one,"tmp",gIR->scopebb());
|
||||
rval = new llvm::LoadInst(rval, "tmp", gIR->scopebb());
|
||||
//Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n';
|
||||
rval = new llvm::BitCastInst(rval, ptrty, "tmp", gIR->scopebb());
|
||||
}
|
||||
}
|
||||
isslice = true;
|
||||
}
|
||||
else if (totype->ty == Tsarray) {
|
||||
Logger::cout() << "to sarray" << '\n';
|
||||
assert(0);
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (isslice) {
|
||||
Logger::println("isslice");
|
||||
return new DSliceValue(to, rval2, rval);
|
||||
}
|
||||
|
||||
return new DImValue(to, rval);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ void DtoArrayInit(llvm::Value* l, llvm::Value* r);
|
||||
void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val);
|
||||
void DtoArrayAssign(llvm::Value* l, llvm::Value* r);
|
||||
void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr);
|
||||
void DtoNullArray(llvm::Value* v);
|
||||
void DtoSetArrayToNull(llvm::Value* v);
|
||||
|
||||
llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit=true);
|
||||
llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz);
|
||||
@@ -37,4 +37,6 @@ llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, cons
|
||||
llvm::Value* DtoArrayLen(DValue* v);
|
||||
llvm::Value* DtoArrayPtr(DValue* v);
|
||||
|
||||
DValue* DtoCastArray(DValue* val, Type* to);
|
||||
|
||||
#endif // LLVMC_GEN_ARRAYS_H
|
||||
|
||||
267
gen/classes.cpp
267
gen/classes.cpp
@@ -10,6 +10,7 @@
|
||||
#include "gen/arrays.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/classes.h"
|
||||
#include "gen/functions.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -23,8 +24,6 @@ static void LLVM_AddBaseClassData(BaseClasses* bcs)
|
||||
Logger::println("Adding base class members of %s", bc->base->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
bc->base->toObjFile();
|
||||
|
||||
LLVM_AddBaseClassData(&bc->base->baseclasses);
|
||||
for (int k=0; k < bc->base->members->dim; k++) {
|
||||
Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
|
||||
@@ -38,12 +37,17 @@ static void LLVM_AddBaseClassData(BaseClasses* bcs)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDeclareClass(ClassDeclaration* cd)
|
||||
void DtoResolveClass(ClassDeclaration* cd)
|
||||
{
|
||||
if (cd->llvmTouched) return;
|
||||
cd->llvmTouched = true;
|
||||
if (cd->llvmResolved) return;
|
||||
cd->llvmResolved = true;
|
||||
|
||||
Logger::println("DtoDeclareClass(%s)\n", cd->toPrettyChars());
|
||||
// first resolve the base class
|
||||
if (cd->baseClass) {
|
||||
DtoResolveClass(cd->baseClass);
|
||||
}
|
||||
|
||||
Logger::println("DtoResolveClass(%s)", cd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(cd->type->ty == Tclass);
|
||||
@@ -57,8 +61,8 @@ void DtoDeclareClass(ClassDeclaration* cd)
|
||||
gIR->classes.push_back(cd);
|
||||
|
||||
// add vtable
|
||||
llvm::PATypeHolder pa = llvm::OpaqueType::get();
|
||||
const llvm::Type* vtabty = llvm::PointerType::get(pa);
|
||||
ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get());
|
||||
const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get());
|
||||
|
||||
std::vector<const llvm::Type*> fieldtypes;
|
||||
fieldtypes.push_back(vtabty);
|
||||
@@ -80,13 +84,11 @@ void DtoDeclareClass(ClassDeclaration* cd)
|
||||
const llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
|
||||
// refine abstract types for stuff like: class C {C next;}
|
||||
assert(irstruct->recty != 0);
|
||||
{
|
||||
|
||||
llvm::PATypeHolder& spa = irstruct->recty;
|
||||
llvm::cast<llvm::OpaqueType>(spa.get())->refineAbstractTypeTo(structtype);
|
||||
structtype = isaStruct(spa.get());
|
||||
}
|
||||
|
||||
// create the type
|
||||
ts->llvmType = new llvm::PATypeHolder(structtype);
|
||||
|
||||
bool needs_definition = false;
|
||||
@@ -100,10 +102,7 @@ void DtoDeclareClass(ClassDeclaration* cd)
|
||||
|
||||
// generate vtable
|
||||
llvm::GlobalVariable* svtblVar = 0;
|
||||
std::vector<llvm::Constant*> sinits;
|
||||
std::vector<const llvm::Type*> sinits_ty;
|
||||
sinits.reserve(cd->vtbl.dim);
|
||||
sinits_ty.reserve(cd->vtbl.dim);
|
||||
|
||||
for (int k=0; k < cd->vtbl.dim; k++)
|
||||
{
|
||||
@@ -112,73 +111,100 @@ void DtoDeclareClass(ClassDeclaration* cd)
|
||||
//Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
|
||||
|
||||
if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
|
||||
fd->toObjFile();
|
||||
assert(fd->llvmValue);
|
||||
llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
|
||||
sinits.push_back(c);
|
||||
sinits_ty.push_back(c->getType());
|
||||
DtoResolveFunction(fd);
|
||||
assert(fd->type->ty == Tfunction);
|
||||
TypeFunction* tf = (TypeFunction*)fd->type;
|
||||
const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get());
|
||||
sinits_ty.push_back(fpty);
|
||||
}
|
||||
else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
|
||||
const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
llvm::Constant* c = llvm::Constant::getNullValue(cty);
|
||||
sinits.push_back(c);
|
||||
sinits_ty.push_back(cty);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
const llvm::StructType* svtbl_ty = 0;
|
||||
if (!sinits.empty())
|
||||
{
|
||||
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
|
||||
assert(!sinits_ty.empty());
|
||||
const llvm::StructType* svtbl_ty = llvm::StructType::get(sinits_ty);
|
||||
|
||||
std::string varname("_D");
|
||||
varname.append(cd->mangle());
|
||||
varname.append("6__vtblZ");
|
||||
|
||||
std::string styname(cd->mangle());
|
||||
styname.append("__vtblTy");
|
||||
|
||||
svtbl_ty = llvm::StructType::get(sinits_ty);
|
||||
gIR->module->addTypeName(styname, svtbl_ty);
|
||||
svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
|
||||
|
||||
cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
|
||||
if (needs_definition)
|
||||
svtblVar->setInitializer(cd->llvmConstVtbl);
|
||||
cd->llvmVtbl = svtblVar;
|
||||
}
|
||||
std::string styname(cd->mangle());
|
||||
styname.append("__vtblType");
|
||||
gIR->module->addTypeName(styname, svtbl_ty);
|
||||
|
||||
// refine for final vtable type
|
||||
llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
|
||||
llvm::cast<llvm::OpaqueType>(ts->llvmVtblType->get())->refineAbstractTypeTo(svtbl_ty);
|
||||
|
||||
gIR->classes.pop_back();
|
||||
gIR->structs.pop_back();
|
||||
|
||||
gIR->declareList.push_back(cd);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDeclareClass(ClassDeclaration* cd)
|
||||
{
|
||||
if (cd->llvmDeclared) return;
|
||||
cd->llvmDeclared = true;
|
||||
|
||||
Logger::println("DtoDeclareClass(%s)", cd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(cd->type->ty == Tclass);
|
||||
TypeClass* ts = (TypeClass*)cd->type;
|
||||
|
||||
assert(cd->llvmIRStruct);
|
||||
IRStruct* irstruct = cd->llvmIRStruct;
|
||||
|
||||
gIR->structs.push_back(irstruct);
|
||||
gIR->classes.push_back(cd);
|
||||
|
||||
bool needs_definition = false;
|
||||
if (cd->parent->isModule()) {
|
||||
needs_definition = (cd->getModule() == gIR->dmodule);
|
||||
}
|
||||
|
||||
// vtable
|
||||
std::string varname("_D");
|
||||
varname.append(cd->mangle());
|
||||
varname.append("6__vtblZ");
|
||||
|
||||
std::string styname(cd->mangle());
|
||||
styname.append("__vtblTy");
|
||||
|
||||
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
|
||||
|
||||
const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
|
||||
cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
|
||||
|
||||
// init
|
||||
std::string initname("_D");
|
||||
initname.append(cd->mangle());
|
||||
initname.append("6__initZ");
|
||||
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
|
||||
|
||||
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
|
||||
ts->llvmInit = initvar;
|
||||
|
||||
gIR->classes.pop_back();
|
||||
gIR->structs.pop_back();
|
||||
|
||||
gIR->constInitQueue.push_back(cd);
|
||||
gIR->constInitList.push_back(cd);
|
||||
if (needs_definition)
|
||||
gIR->defineQueue.push_back(cd);
|
||||
gIR->defineList.push_back(cd);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoConstInitClass(ClassDeclaration* cd)
|
||||
{
|
||||
IRStruct* irstruct = cd->llvmIRStruct;
|
||||
if (irstruct->constinited) return;
|
||||
irstruct->constinited = true;
|
||||
if (cd->llvmInitialized) return;
|
||||
cd->llvmInitialized = true;
|
||||
|
||||
Logger::println("DtoConstInitClass(%s)\n", cd->toPrettyChars());
|
||||
Logger::println("DtoConstInitClass(%s)", cd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
IRStruct* irstruct = cd->llvmIRStruct;
|
||||
gIR->structs.push_back(irstruct);
|
||||
gIR->classes.push_back(cd);
|
||||
|
||||
@@ -200,6 +226,7 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
||||
|
||||
// rest
|
||||
for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
|
||||
Logger::println("adding fieldinit for: %s", i->second.var->toChars());
|
||||
fieldinits.push_back(i->second.init);
|
||||
}
|
||||
|
||||
@@ -210,24 +237,69 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
||||
|
||||
// generate initializer
|
||||
Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n';
|
||||
Logger::println("%u %u fields", structtype->getNumElements(), fieldinits.size());
|
||||
|
||||
for(size_t i=0; i<structtype->getNumElements(); ++i) {
|
||||
Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n';
|
||||
}
|
||||
|
||||
for(size_t i=0; i<fieldinits.size(); ++i) {
|
||||
Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n';
|
||||
}
|
||||
|
||||
llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits);
|
||||
assert(_init);
|
||||
cd->llvmInitZ = _init;
|
||||
|
||||
// generate vtable initializer
|
||||
std::vector<llvm::Constant*> sinits;
|
||||
|
||||
for (int k=0; k < cd->vtbl.dim; k++)
|
||||
{
|
||||
Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k];
|
||||
assert(dsym);
|
||||
//Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
|
||||
|
||||
if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
|
||||
DtoForceDeclareDsymbol(fd);
|
||||
assert(fd->llvmValue);
|
||||
llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
|
||||
sinits.push_back(c);
|
||||
}
|
||||
else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
|
||||
const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
llvm::Constant* c = llvm::Constant::getNullValue(cty);
|
||||
sinits.push_back(c);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
|
||||
|
||||
/*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());
|
||||
}*/
|
||||
|
||||
llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits);
|
||||
cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit);
|
||||
|
||||
gIR->classes.pop_back();
|
||||
gIR->structs.pop_back();
|
||||
|
||||
DtoDeclareClassInfo(cd);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDefineClass(ClassDeclaration* cd)
|
||||
{
|
||||
IRStruct* irstruct = cd->llvmIRStruct;
|
||||
if (irstruct->defined) return;
|
||||
irstruct->defined = true;
|
||||
if (cd->llvmDefined) return;
|
||||
cd->llvmDefined = true;
|
||||
|
||||
Logger::println("DtoDefineClass(%s)\n", cd->toPrettyChars());
|
||||
Logger::println("DtoDefineClass(%s)", cd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// get the struct (class) type
|
||||
@@ -237,11 +309,11 @@ void DtoDefineClass(ClassDeclaration* cd)
|
||||
bool def = false;
|
||||
if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) {
|
||||
ts->llvmInit->setInitializer(cd->llvmInitZ);
|
||||
cd->llvmVtbl->setInitializer(cd->llvmConstVtbl);
|
||||
def = true;
|
||||
}
|
||||
|
||||
// generate classinfo
|
||||
DtoDeclareClassInfo(cd);
|
||||
if (def) DtoDefineClassInfo(cd);
|
||||
}
|
||||
|
||||
@@ -302,21 +374,21 @@ void DtoInitClass(TypeClass* tc, llvm::Value* dst)
|
||||
|
||||
void DtoDeclareClassInfo(ClassDeclaration* cd)
|
||||
{
|
||||
if (cd->llvmClass)
|
||||
return;
|
||||
if (cd->llvmClassDeclared) return;
|
||||
cd->llvmClassDeclared = true;
|
||||
|
||||
Logger::println("CLASS INFO DECLARATION: %s", cd->toChars());
|
||||
Logger::println("DtoDeclareClassInfo(%s)", cd->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
|
||||
cinfo->toObjFile();
|
||||
|
||||
const llvm::Type* st = cinfo->type->llvmType->get();
|
||||
DtoResolveClass(cinfo);
|
||||
|
||||
std::string gname("_D");
|
||||
gname.append(cd->mangle());
|
||||
gname.append("7__ClassZ");
|
||||
|
||||
const llvm::Type* st = cinfo->type->llvmType->get();
|
||||
|
||||
cd->llvmClass = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module);
|
||||
}
|
||||
|
||||
@@ -339,18 +411,26 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
// void *defaultConstructor;
|
||||
// }
|
||||
|
||||
if (cd->llvmClassZ)
|
||||
return;
|
||||
if (cd->llvmClassDefined) return;
|
||||
cd->llvmClassDefined = true;
|
||||
|
||||
Logger::println("CLASS INFO DEFINITION: %s", cd->toChars());
|
||||
Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(cd->type->ty == Tclass);
|
||||
assert(cd->llvmClass);
|
||||
assert(cd->llvmInitZ);
|
||||
assert(cd->llvmVtbl);
|
||||
assert(cd->llvmConstVtbl);
|
||||
|
||||
TypeClass* cdty = (TypeClass*)cd->type;
|
||||
assert(cdty->llvmInit);
|
||||
|
||||
// holds the list of initializers for llvm
|
||||
std::vector<llvm::Constant*> inits;
|
||||
|
||||
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
|
||||
DtoConstInitClass(cinfo);
|
||||
DtoForceConstInitDsymbol(cinfo);
|
||||
assert(cinfo->llvmInitZ);
|
||||
|
||||
llvm::Constant* c;
|
||||
@@ -363,8 +443,12 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
// monitor
|
||||
// TODO no monitors yet
|
||||
|
||||
// initializer
|
||||
c = cinfo->llvmInitZ->getOperand(1);
|
||||
// byte[] init
|
||||
const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
c = llvm::ConstantExpr::getBitCast(cdty->llvmInit, byteptrty);
|
||||
assert(!cd->llvmInitZ->getType()->isAbstract());
|
||||
size_t initsz = gTargetData->getTypeSize(cd->llvmInitZ->getType());
|
||||
c = DtoConstSlice(DtoConstSize_t(initsz), c);
|
||||
inits.push_back(c);
|
||||
|
||||
// class name
|
||||
@@ -380,38 +464,77 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||
inits.push_back(c);
|
||||
|
||||
// vtbl array
|
||||
c = cinfo->llvmInitZ->getOperand(3);
|
||||
const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty);
|
||||
assert(!cd->llvmVtbl->getType()->isAbstract());
|
||||
c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty);
|
||||
assert(!cd->llvmConstVtbl->getType()->isAbstract());
|
||||
size_t vtblsz = gTargetData->getTypeSize(cd->llvmConstVtbl->getType());
|
||||
c = DtoConstSlice(DtoConstSize_t(vtblsz), c);
|
||||
inits.push_back(c);
|
||||
|
||||
// interfaces array
|
||||
// TODO
|
||||
c = cinfo->llvmInitZ->getOperand(4);
|
||||
inits.push_back(c);
|
||||
|
||||
// base classinfo
|
||||
c = cinfo->llvmInitZ->getOperand(5);
|
||||
inits.push_back(c);
|
||||
if (cd->baseClass) {
|
||||
DtoDeclareClassInfo(cd->baseClass);
|
||||
c = cd->baseClass->llvmClass;
|
||||
assert(c);
|
||||
inits.push_back(c);
|
||||
}
|
||||
else {
|
||||
// null
|
||||
c = cinfo->llvmInitZ->getOperand(5);
|
||||
inits.push_back(c);
|
||||
}
|
||||
|
||||
// destructor
|
||||
// TODO
|
||||
c = cinfo->llvmInitZ->getOperand(6);
|
||||
inits.push_back(c);
|
||||
|
||||
// invariant
|
||||
// TODO
|
||||
c = cinfo->llvmInitZ->getOperand(7);
|
||||
inits.push_back(c);
|
||||
|
||||
// flags
|
||||
c = cinfo->llvmInitZ->getOperand(8);
|
||||
// uint flags, adapted from original dmd code
|
||||
uint flags = 0;
|
||||
//flags |= 4; // has offTi
|
||||
//flags |= isCOMclass(); // IUnknown
|
||||
if (cd->ctor) flags |= 8;
|
||||
for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass)
|
||||
{
|
||||
if (cd2->members)
|
||||
{
|
||||
for (size_t i = 0; i < cd2->members->dim; i++)
|
||||
{
|
||||
Dsymbol *sm = (Dsymbol *)cd2->members->data[i];
|
||||
//printf("sm = %s %s\n", sm->kind(), sm->toChars());
|
||||
if (sm->hasPointers())
|
||||
goto L2;
|
||||
}
|
||||
}
|
||||
}
|
||||
flags |= 2; // no pointers
|
||||
L2:
|
||||
c = DtoConstUint(flags);
|
||||
inits.push_back(c);
|
||||
|
||||
// allocator
|
||||
// TODO
|
||||
c = cinfo->llvmInitZ->getOperand(9);
|
||||
inits.push_back(c);
|
||||
|
||||
// offset typeinfo
|
||||
// TODO
|
||||
c = cinfo->llvmInitZ->getOperand(10);
|
||||
inits.push_back(c);
|
||||
|
||||
// default constructor
|
||||
// TODO
|
||||
c = cinfo->llvmInitZ->getOperand(11);
|
||||
inits.push_back(c);
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#ifndef LLVMDC_GEN_CLASSES_H
|
||||
#define LLVMDC_GEN_CLASSES_H
|
||||
|
||||
/**
|
||||
* Resolves the llvm type for a class declaration
|
||||
*/
|
||||
void DtoResolveClass(ClassDeclaration* cd);
|
||||
|
||||
/**
|
||||
* Provides the llvm declaration for a class declaration
|
||||
*/
|
||||
|
||||
@@ -71,7 +71,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype
|
||||
if (typesafeVararg) {
|
||||
ClassDeclaration* ti = Type::typeinfo;
|
||||
ti->toObjFile();
|
||||
DtoConstInitClass(ti);
|
||||
DtoForceConstInitDsymbol(ti);
|
||||
assert(ti->llvmInitZ);
|
||||
std::vector<const llvm::Type*> types;
|
||||
types.push_back(DtoSize_t());
|
||||
@@ -131,10 +131,10 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype
|
||||
f->llvmRetInPtr = retinptr;
|
||||
f->llvmUsesThis = usesthis;
|
||||
|
||||
if (!f->llvmType)
|
||||
//if (!f->llvmType)
|
||||
f->llvmType = new llvm::PATypeHolder(functype);
|
||||
else
|
||||
assert(functype == f->llvmType->get());
|
||||
//else
|
||||
//assert(functype == f->llvmType->get());
|
||||
|
||||
return functype;
|
||||
}
|
||||
@@ -143,6 +143,11 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype
|
||||
|
||||
static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
|
||||
{
|
||||
// type has already been resolved
|
||||
if (fdecl->type->llvmType != 0) {
|
||||
return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType->get());
|
||||
}
|
||||
|
||||
TypeFunction* f = (TypeFunction*)fdecl->type;
|
||||
assert(f != 0);
|
||||
|
||||
@@ -163,10 +168,7 @@ static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
|
||||
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
|
||||
|
||||
if (!f->llvmType)
|
||||
f->llvmType = new llvm::PATypeHolder(fty);
|
||||
else
|
||||
assert(fty == f->llvmType->get());
|
||||
f->llvmType = new llvm::PATypeHolder(fty);
|
||||
|
||||
return fty;
|
||||
}
|
||||
@@ -190,7 +192,7 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
|
||||
Logger::print("isMember = this is: %s\n", ad->type->toChars());
|
||||
thisty = DtoType(ad->type);
|
||||
Logger::cout() << "this llvm type: " << *thisty << '\n';
|
||||
if (isaStruct(thisty) || thisty == gIR->topstruct()->recty.get())
|
||||
if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->recty.get()))
|
||||
thisty = llvm::PointerType::get(thisty);
|
||||
}
|
||||
else
|
||||
@@ -233,8 +235,57 @@ static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoResolveFunction(FuncDeclaration* fdecl)
|
||||
{
|
||||
if (fdecl->llvmResolved) return;
|
||||
fdecl->llvmResolved = true;
|
||||
|
||||
Logger::println("DtoResolveFunction(%s)", fdecl->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (fdecl->llvmRunTimeHack) {
|
||||
gIR->declareList.push_back(fdecl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fdecl->isUnitTestDeclaration()) {
|
||||
Logger::attention("ignoring unittest declaration: %s", fdecl->toChars());
|
||||
return;
|
||||
}
|
||||
|
||||
if (fdecl->parent)
|
||||
if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance())
|
||||
{
|
||||
TemplateDeclaration* tempdecl = tinst->tempdecl;
|
||||
if (tempdecl->llvmInternal == LLVMva_arg)
|
||||
{
|
||||
Logger::println("magic va_arg found");
|
||||
fdecl->llvmInternal = LLVMva_arg;
|
||||
fdecl->llvmDeclared = true;
|
||||
fdecl->llvmInitialized = true;
|
||||
fdecl->llvmDefined = true;
|
||||
return; // this gets mapped to an instruction so a declaration makes no sence
|
||||
}
|
||||
else if (tempdecl->llvmInternal == LLVMva_start)
|
||||
{
|
||||
Logger::println("magic va_start found");
|
||||
fdecl->llvmInternal = LLVMva_start;
|
||||
}
|
||||
}
|
||||
|
||||
DtoFunctionType(fdecl);
|
||||
|
||||
// queue declaration
|
||||
gIR->declareList.push_back(fdecl);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||
{
|
||||
if (fdecl->llvmDeclared) return;
|
||||
fdecl->llvmDeclared = true;
|
||||
|
||||
Logger::println("DtoDeclareFunction(%s)", fdecl->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
@@ -245,34 +296,12 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||
return;
|
||||
}
|
||||
|
||||
if (fdecl->isUnitTestDeclaration()) {
|
||||
Logger::attention("ignoring unittest declaration: %s", fdecl->toChars());
|
||||
return;
|
||||
}
|
||||
|
||||
bool declareOnly = false;
|
||||
if (fdecl->parent)
|
||||
{
|
||||
if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance())
|
||||
{
|
||||
TemplateDeclaration* tempdecl = tinst->tempdecl;
|
||||
if (tempdecl->llvmInternal == LLVMva_start)
|
||||
{
|
||||
Logger::println("magic va_start found");
|
||||
fdecl->llvmInternal = LLVMva_start;
|
||||
declareOnly = true;
|
||||
}
|
||||
else if (tempdecl->llvmInternal == LLVMva_arg)
|
||||
{
|
||||
Logger::println("magic va_arg found");
|
||||
fdecl->llvmInternal = LLVMva_arg;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fdecl->llvmTouched) return;
|
||||
fdecl->llvmTouched = true;
|
||||
bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent);
|
||||
if (!templInst && fdecl->getModule() != gIR->dmodule)
|
||||
declareOnly = true;
|
||||
else if (fdecl->llvmInternal == LLVMva_start)
|
||||
declareOnly = true;
|
||||
|
||||
if (!fdecl->llvmIRFunc) {
|
||||
fdecl->llvmIRFunc = new IRFunction(fdecl);
|
||||
@@ -384,7 +413,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||
}
|
||||
|
||||
if (!declareOnly)
|
||||
gIR->defineQueue.push_back(fdecl);
|
||||
gIR->defineList.push_back(fdecl);
|
||||
|
||||
Logger::cout() << "func decl: " << *func << '\n';
|
||||
}
|
||||
@@ -394,6 +423,12 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||
// TODO split this monster up
|
||||
void DtoDefineFunc(FuncDeclaration* fd)
|
||||
{
|
||||
if (fd->llvmDefined) return;
|
||||
fd->llvmDefined = true;
|
||||
|
||||
Logger::println("DtoDefineFunc(%s)", fd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// debug info
|
||||
if (global.params.symdebug) {
|
||||
Module* mo = fd->getModule();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
const llvm::FunctionType* DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false);
|
||||
const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl);
|
||||
|
||||
void DtoResolveFunction(FuncDeclaration* fdecl);
|
||||
void DtoDeclareFunction(FuncDeclaration* fdecl);
|
||||
void DtoDefineFunc(FuncDeclaration* fd);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#include "root.h"
|
||||
|
||||
@@ -176,11 +177,15 @@ struct IRState
|
||||
// builder helper
|
||||
IRBuilderHelper ir;
|
||||
|
||||
typedef std::vector<Dsymbol*> DsymbolVector;
|
||||
typedef std::list<Dsymbol*> DsymbolList;
|
||||
// dsymbols that need to be resolved
|
||||
DsymbolList resolveList;
|
||||
// dsymbols that need to be declared
|
||||
DsymbolList declareList;
|
||||
// dsymbols that need constant initializers constructed
|
||||
DsymbolVector constInitQueue;
|
||||
// dsymbols that need definitions (symbols in current module)
|
||||
DsymbolVector defineQueue;
|
||||
DsymbolList constInitList;
|
||||
// dsymbols that need definitions
|
||||
DsymbolList defineList;
|
||||
};
|
||||
|
||||
#endif // LLVMDC_GEN_IRSTATE_H
|
||||
|
||||
@@ -16,8 +16,9 @@ namespace Logger
|
||||
static bool enabled = false;
|
||||
void indent()
|
||||
{
|
||||
if (enabled)
|
||||
indent_str += " ";
|
||||
if (enabled) {
|
||||
indent_str += "* ";
|
||||
}
|
||||
}
|
||||
void undent()
|
||||
{
|
||||
|
||||
@@ -96,6 +96,7 @@ llvm::Constant* DtoConstStructInitializer(StructInitializer* si)
|
||||
inits.push_back(DUnionIdx(vd->llvmFieldIndex, vd->llvmFieldIndexOffset, v));
|
||||
}
|
||||
|
||||
DtoConstInitStruct((StructDeclaration*)si->ad);
|
||||
return si->ad->llvmUnion->getConst(inits);
|
||||
}
|
||||
|
||||
@@ -165,12 +166,12 @@ llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, un
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDeclareStruct(StructDeclaration* sd)
|
||||
void DtoResolveStruct(StructDeclaration* sd)
|
||||
{
|
||||
if (sd->llvmTouched) return;
|
||||
sd->llvmTouched = true;
|
||||
if (sd->llvmResolved) return;
|
||||
sd->llvmResolved = true;
|
||||
|
||||
Logger::println("DtoDeclareStruct(%s)", sd->toChars());
|
||||
Logger::println("DtoResolveStruct(%s)", sd->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
TypeStruct* ts = (TypeStruct*)DtoDType(sd->type);
|
||||
@@ -280,6 +281,23 @@ void DtoDeclareStruct(StructDeclaration* sd)
|
||||
gIR->module->addTypeName(sd->mangle(),structtype);
|
||||
}
|
||||
|
||||
gIR->structs.pop_back();
|
||||
|
||||
gIR->declareList.push_back(sd);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDeclareStruct(StructDeclaration* sd)
|
||||
{
|
||||
if (sd->llvmDeclared) return;
|
||||
sd->llvmDeclared = true;
|
||||
|
||||
Logger::println("DtoDeclareStruct(%s)", sd->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
TypeStruct* ts = (TypeStruct*)DtoDType(sd->type);
|
||||
|
||||
std::string initname("_D");
|
||||
initname.append(sd->mangle());
|
||||
initname.append("6__initZ");
|
||||
@@ -288,28 +306,22 @@ void DtoDeclareStruct(StructDeclaration* sd)
|
||||
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
|
||||
ts->llvmInit = initvar;
|
||||
|
||||
gIR->structs.pop_back();
|
||||
|
||||
gIR->constInitQueue.push_back(sd);
|
||||
gIR->constInitList.push_back(sd);
|
||||
if (sd->getModule() == gIR->dmodule)
|
||||
gIR->defineQueue.push_back(sd);
|
||||
|
||||
// declare typeinfo
|
||||
if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMnotypeinfo)
|
||||
sd->type->getTypeInfo(NULL);
|
||||
gIR->defineList.push_back(sd);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoConstInitStruct(StructDeclaration* sd)
|
||||
{
|
||||
IRStruct* irstruct = sd->llvmIRStruct;
|
||||
if (irstruct->constinited) return;
|
||||
irstruct->constinited = true;
|
||||
if (sd->llvmInitialized) return;
|
||||
sd->llvmInitialized = true;
|
||||
|
||||
Logger::println("DtoConstInitStruct(%s)", sd->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
IRStruct* irstruct = sd->llvmIRStruct;
|
||||
gIR->structs.push_back(irstruct);
|
||||
|
||||
// make sure each offset knows its default initializer
|
||||
@@ -365,17 +377,18 @@ void DtoConstInitStruct(StructDeclaration* sd)
|
||||
}
|
||||
|
||||
gIR->structs.pop_back();
|
||||
|
||||
// emit typeinfo
|
||||
if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMnotypeinfo)
|
||||
sd->type->getTypeInfo(NULL);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDefineStruct(StructDeclaration* sd)
|
||||
{
|
||||
IRStruct* irstruct = sd->llvmIRStruct;
|
||||
if (irstruct->defined) return;
|
||||
irstruct->defined = true;
|
||||
|
||||
DtoConstInitStruct(sd);
|
||||
if (sd->llvmDefined) return;
|
||||
sd->llvmDefined = true;
|
||||
|
||||
Logger::println("DtoDefineStruct(%s)", sd->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
@@ -10,6 +10,11 @@ llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src);
|
||||
|
||||
llvm::Constant* DtoConstStructInitializer(StructInitializer* si);
|
||||
|
||||
/**
|
||||
* Resolves the llvm type for a struct
|
||||
*/
|
||||
void DtoResolveStruct(StructDeclaration* sd);
|
||||
|
||||
/**
|
||||
* Provides the llvm declaration for a struct
|
||||
*/
|
||||
|
||||
49
gen/toir.cpp
49
gen/toir.cpp
@@ -27,6 +27,7 @@
|
||||
#include "gen/arrays.h"
|
||||
#include "gen/structs.h"
|
||||
#include "gen/classes.h"
|
||||
#include "gen/typeinf.h"
|
||||
|
||||
#include "gen/dvalue.h"
|
||||
|
||||
@@ -45,7 +46,7 @@ DValue* DeclarationExp::toElem(IRState* p)
|
||||
// static
|
||||
if (vd->isDataseg())
|
||||
{
|
||||
vd->toObjFile();
|
||||
vd->toObjFile(); // TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -75,13 +76,13 @@ DValue* DeclarationExp::toElem(IRState* p)
|
||||
else if (StructDeclaration* s = declaration->isStructDeclaration())
|
||||
{
|
||||
Logger::println("StructDeclaration");
|
||||
s->toObjFile();
|
||||
DtoForceConstInitDsymbol(s);
|
||||
}
|
||||
// function declaration
|
||||
else if (FuncDeclaration* f = declaration->isFuncDeclaration())
|
||||
{
|
||||
Logger::println("FuncDeclaration");
|
||||
f->toObjFile();
|
||||
DtoForceDeclareDsymbol(f);
|
||||
}
|
||||
// alias declaration
|
||||
else if (AliasDeclaration* a = declaration->isAliasDeclaration())
|
||||
@@ -145,7 +146,7 @@ DValue* VarExp::toElem(IRState* p)
|
||||
else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
|
||||
{
|
||||
Logger::println("TypeInfoDeclaration");
|
||||
tid->toObjFile();
|
||||
DtoForceDeclareDsymbol(tid);
|
||||
assert(tid->llvmValue);
|
||||
const llvm::Type* vartype = DtoType(type);
|
||||
llvm::Value* m;
|
||||
@@ -159,6 +160,7 @@ DValue* VarExp::toElem(IRState* p)
|
||||
else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration())
|
||||
{
|
||||
Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
|
||||
DtoDeclareClassInfo(cid->cd);
|
||||
assert(cid->cd->llvmClass);
|
||||
return new DVarValue(vd, cid->cd->llvmClass, true);
|
||||
}
|
||||
@@ -199,8 +201,9 @@ DValue* VarExp::toElem(IRState* p)
|
||||
else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
|
||||
{
|
||||
Logger::println("FuncDeclaration");
|
||||
if (fdecl->llvmInternal != LLVMva_arg)// && fdecl->llvmValue == 0)
|
||||
fdecl->toObjFile();
|
||||
if (fdecl->llvmInternal != LLVMva_arg) {// && fdecl->llvmValue == 0)
|
||||
DtoForceDeclareDsymbol(fdecl);
|
||||
}
|
||||
return new DFuncValue(fdecl, fdecl->llvmValue);
|
||||
}
|
||||
else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
|
||||
@@ -234,8 +237,7 @@ llvm::Constant* VarExp::toConstElem(IRState* p)
|
||||
Logger::print("Sym: type=%s\n", sdecltype->toChars());
|
||||
assert(sdecltype->ty == Tstruct);
|
||||
TypeStruct* ts = (TypeStruct*)sdecltype;
|
||||
ts->sym->toObjFile();
|
||||
DtoConstInitStruct(ts->sym);
|
||||
DtoForceConstInitDsymbol(ts->sym);
|
||||
assert(ts->sym->llvmInitZ);
|
||||
return ts->sym->llvmInitZ;
|
||||
}
|
||||
@@ -1063,7 +1065,7 @@ DValue* CallExp::toElem(IRState* p)
|
||||
bool delegateCall = false;
|
||||
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false);
|
||||
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty,1,false);
|
||||
LINK dlink = LINKdefault;
|
||||
LINK dlink = LINKd;
|
||||
|
||||
// hidden struct return parameter handling
|
||||
bool retinptr = false;
|
||||
@@ -1117,7 +1119,7 @@ DValue* CallExp::toElem(IRState* p)
|
||||
llt = llvm::PointerType::get(llt);
|
||||
// TODO
|
||||
if (strcmp(global.params.llvmArch, "x86") != 0) {
|
||||
warning("va_arg for C variadic functions is broken for anything but x86");
|
||||
warning("%s: va_arg for C variadic functions is broken for anything but x86", loc.toChars());
|
||||
}
|
||||
return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp"));
|
||||
}
|
||||
@@ -1267,7 +1269,7 @@ DValue* CallExp::toElem(IRState* p)
|
||||
vtypes.push_back(vvalues.back()->getType());
|
||||
|
||||
TypeInfoDeclaration* tidecl = argexp->type->getTypeInfoDeclaration();
|
||||
tidecl->toObjFile();
|
||||
DtoForceDeclareDsymbol(tidecl);
|
||||
assert(tidecl->llvmValue);
|
||||
vtypeinfos.push_back(tidecl->llvmValue);
|
||||
}
|
||||
@@ -1306,8 +1308,10 @@ DValue* CallExp::toElem(IRState* p)
|
||||
llargs[j] = DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]);
|
||||
// this hack is necessary :/
|
||||
if (dfn && dfn->func && dfn->func->llvmRunTimeHack) {
|
||||
if (llargs[j]->getType() != llfnty->getParamType(j))
|
||||
Logger::println("llvmRunTimeHack==true");
|
||||
if (llargs[j]->getType() != llfnty->getParamType(j)) {
|
||||
llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
Logger::println("%d params passed", n);
|
||||
@@ -1336,13 +1340,13 @@ DValue* CallExp::toElem(IRState* p)
|
||||
call->setCallingConv(DtoCallingConv(dlink));
|
||||
}
|
||||
}
|
||||
else if (delegateCall) {
|
||||
/*else if (delegateCall) {
|
||||
call->setCallingConv(DtoCallingConv(dlink));
|
||||
}
|
||||
}*/
|
||||
else if (dfn && dfn->cc != (unsigned)-1) {
|
||||
call->setCallingConv(dfn->cc);
|
||||
}
|
||||
else if (llvm::isa<llvm::LoadInst>(funcval)) {
|
||||
else {
|
||||
call->setCallingConv(DtoCallingConv(dlink));
|
||||
}
|
||||
|
||||
@@ -1385,8 +1389,11 @@ DValue* SymOffExp::toElem(IRState* p)
|
||||
if (VarDeclaration* vd = var->isVarDeclaration())
|
||||
{
|
||||
Logger::println("VarDeclaration");
|
||||
if (!vd->llvmTouched && vd->isDataseg())
|
||||
vd->toObjFile();
|
||||
|
||||
// handle forward reference
|
||||
if (!vd->llvmDeclared && vd->isDataseg()) {
|
||||
vd->toObjFile(); // TODO
|
||||
}
|
||||
|
||||
assert(vd->llvmValue);
|
||||
Type* t = DtoDType(type);
|
||||
@@ -1465,7 +1472,7 @@ DValue* AddrExp::toElem(IRState* p)
|
||||
FuncDeclaration* fd = fv->func;
|
||||
assert(fd);
|
||||
if (fd->llvmValue == 0)
|
||||
fd->toObjFile();
|
||||
DtoForceDeclareDsymbol(fd);
|
||||
return new DFuncValue(fd, fd->llvmValue);
|
||||
}
|
||||
else if (DImValue* im = v->isIm()) {
|
||||
@@ -1539,7 +1546,7 @@ DValue* DotVarExp::toElem(IRState* p)
|
||||
{
|
||||
if (fdecl->llvmValue == 0)
|
||||
{
|
||||
fdecl->toObjFile();
|
||||
DtoForceDeclareDsymbol(fdecl);
|
||||
}
|
||||
|
||||
llvm::Value* funcval = fdecl->llvmValue;
|
||||
@@ -2099,7 +2106,7 @@ DValue* DeleteExp::toElem(IRState* p)
|
||||
llvm::Value* ptr = DtoGEP(val,zero,one,"tmp",p->scopebb());
|
||||
ptr = new llvm::LoadInst(ptr,"tmp",p->scopebb());
|
||||
new llvm::FreeInst(ptr, p->scopebb());
|
||||
DtoNullArray(val);
|
||||
DtoSetArrayToNull(val);
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
@@ -2507,7 +2514,7 @@ DValue* FuncExp::toElem(IRState* p)
|
||||
if (fd->isNested()) Logger::println("nested");
|
||||
Logger::println("kind = %s\n", fd->kind());
|
||||
|
||||
fd->toObjFile();
|
||||
DtoForceDeclareDsymbol(fd);
|
||||
|
||||
bool temp = false;
|
||||
llvm::Value* lval = NULL;
|
||||
|
||||
276
gen/tollvm.cpp
276
gen/tollvm.cpp
@@ -17,6 +17,7 @@
|
||||
#include "gen/functions.h"
|
||||
#include "gen/structs.h"
|
||||
#include "gen/classes.h"
|
||||
#include "gen/typeinf.h"
|
||||
|
||||
bool DtoIsPassedByRef(Type* type)
|
||||
{
|
||||
@@ -114,7 +115,7 @@ const llvm::Type* DtoType(Type* t)
|
||||
// forward declaration
|
||||
TypeStruct* ts = (TypeStruct*)t;
|
||||
assert(ts->sym);
|
||||
ts->sym->toObjFile();
|
||||
DtoResolveDsymbol(ts->sym);
|
||||
}
|
||||
return t->llvmType->get();
|
||||
}
|
||||
@@ -137,7 +138,7 @@ const llvm::Type* DtoType(Type* t)
|
||||
// forward declaration
|
||||
TypeClass* tc = (TypeClass*)t;
|
||||
assert(tc->sym);
|
||||
tc->sym->toObjFile();
|
||||
DtoResolveDsymbol(tc->sym);
|
||||
}
|
||||
return llvm::PointerType::get(t->llvmType->get());
|
||||
}
|
||||
@@ -654,7 +655,17 @@ void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg)
|
||||
llargs.resize(3);
|
||||
llargs[0] = cond ? DtoBoolean(cond) : llvm::ConstantInt::getFalse();
|
||||
llargs[1] = DtoConstUint(loc->linnum);
|
||||
llargs[2] = msg ? msg->getRVal() : llvm::Constant::getNullValue(fnt->getParamType(2));
|
||||
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;
|
||||
}
|
||||
|
||||
assert(fn);
|
||||
llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
||||
@@ -861,7 +872,7 @@ void DtoAssign(DValue* lhs, DValue* rhs)
|
||||
}
|
||||
// null
|
||||
else if (rhs->isNull()) {
|
||||
DtoNullArray(lhs->getLVal());
|
||||
DtoSetArrayToNull(lhs->getLVal());
|
||||
}
|
||||
// reference assignment
|
||||
else {
|
||||
@@ -1030,87 +1041,6 @@ DValue* DtoCastClass(DValue* val, Type* _to)
|
||||
return new DImValue(_to, rval);
|
||||
}
|
||||
|
||||
DValue* DtoCastArray(DValue* u, Type* to)
|
||||
{
|
||||
const llvm::Type* tolltype = DtoType(to);
|
||||
|
||||
Type* totype = DtoDType(to);
|
||||
Type* fromtype = DtoDType(u->getType());
|
||||
assert(fromtype->ty == Tarray || fromtype->ty == Tsarray);
|
||||
|
||||
llvm::Value* rval;
|
||||
llvm::Value* rval2;
|
||||
bool isslice = false;
|
||||
|
||||
Logger::cout() << "from array or sarray" << '\n';
|
||||
if (totype->ty == Tpointer) {
|
||||
Logger::cout() << "to pointer" << '\n';
|
||||
assert(fromtype->next == totype->next || totype->next->ty == Tvoid);
|
||||
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");
|
||||
}
|
||||
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);
|
||||
|
||||
const llvm::Type* ety = DtoType(fromtype->next);
|
||||
if (ety == llvm::Type::VoidTy)
|
||||
ety = llvm::Type::Int8Ty;
|
||||
|
||||
if (DSliceValue* usl = u->isSlice()) {
|
||||
Logger::println("from slice");
|
||||
rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", gIR->scopebb());
|
||||
if (fromtype->next->size() == totype->next->size())
|
||||
rval2 = usl->len;
|
||||
else
|
||||
rval2 = DtoArrayCastLength(usl->len, ety, ptrty->getContainedType(0));
|
||||
}
|
||||
else {
|
||||
llvm::Value* uval = u->getRVal();
|
||||
if (fromtype->ty == Tsarray) {
|
||||
Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
|
||||
assert(isaPointer(uval->getType()));
|
||||
const llvm::ArrayType* arrty = isaArray(uval->getType()->getContainedType(0));
|
||||
rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
|
||||
rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
|
||||
rval = new llvm::BitCastInst(uval, ptrty, "tmp", gIR->scopebb());
|
||||
}
|
||||
else {
|
||||
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
|
||||
rval2 = DtoGEP(uval,zero,zero,"tmp",gIR->scopebb());
|
||||
rval2 = new llvm::LoadInst(rval2, "tmp", gIR->scopebb());
|
||||
rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
|
||||
|
||||
rval = DtoGEP(uval,zero,one,"tmp",gIR->scopebb());
|
||||
rval = new llvm::LoadInst(rval, "tmp", gIR->scopebb());
|
||||
//Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n';
|
||||
rval = new llvm::BitCastInst(rval, ptrty, "tmp", gIR->scopebb());
|
||||
}
|
||||
}
|
||||
isslice = true;
|
||||
}
|
||||
else if (totype->ty == Tsarray) {
|
||||
Logger::cout() << "to sarray" << '\n';
|
||||
assert(0);
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (isslice) {
|
||||
Logger::println("isslice");
|
||||
return new DSliceValue(to, rval2, rval);
|
||||
}
|
||||
|
||||
return new DImValue(to, rval);
|
||||
}
|
||||
|
||||
DValue* DtoCast(DValue* val, Type* to)
|
||||
{
|
||||
Type* fromtype = DtoDType(val->getType());
|
||||
@@ -1180,6 +1110,15 @@ llvm::Constant* DtoConstStringPtr(const char* str, const char* section)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::Constant* DtoConstNullPtr(const llvm::Type* t)
|
||||
{
|
||||
return llvm::ConstantPointerNull::get(
|
||||
llvm::PointerType::get(t)
|
||||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes)
|
||||
{
|
||||
assert(dst->getType() == src->getType());
|
||||
@@ -1321,20 +1260,45 @@ void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type*
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDefineDsymbol(Dsymbol* dsym)
|
||||
void DtoResolveDsymbol(Dsymbol* dsym)
|
||||
{
|
||||
if (StructDeclaration* sd = dsym->isStructDeclaration()) {
|
||||
DtoDefineStruct(sd);
|
||||
DtoResolveStruct(sd);
|
||||
}
|
||||
else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
|
||||
DtoDefineClass(cd);
|
||||
DtoResolveClass(cd);
|
||||
}
|
||||
else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
|
||||
DtoDefineFunc(fd);
|
||||
DtoResolveFunction(fd);
|
||||
}
|
||||
else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
|
||||
DtoResolveTypeInfo(fd);
|
||||
}
|
||||
else {
|
||||
error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
|
||||
assert(0 && "unsupported dsymbol for DtoDefineDsymbol");
|
||||
assert(0 && "unsupported dsymbol for DtoResolveDsymbol");
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDeclareDsymbol(Dsymbol* dsym)
|
||||
{
|
||||
if (StructDeclaration* sd = dsym->isStructDeclaration()) {
|
||||
DtoDeclareStruct(sd);
|
||||
}
|
||||
else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
|
||||
DtoDeclareClass(cd);
|
||||
}
|
||||
else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
|
||||
DtoDeclareFunction(fd);
|
||||
}
|
||||
else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
|
||||
DtoDeclareTypeInfo(fd);
|
||||
}
|
||||
else {
|
||||
error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
|
||||
assert(0 && "unsupported dsymbol for DtoDeclareDsymbol");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1348,12 +1312,37 @@ void DtoConstInitDsymbol(Dsymbol* dsym)
|
||||
else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
|
||||
DtoConstInitClass(cd);
|
||||
}
|
||||
else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
|
||||
DtoConstInitTypeInfo(fd);
|
||||
}
|
||||
else if (VarDeclaration* vd = dsym->isVarDeclaration()) {
|
||||
DtoConstInitGlobal(vd);
|
||||
}
|
||||
else {
|
||||
error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
|
||||
assert(0 && "unsupported dsymbol for DtoInitDsymbol");
|
||||
assert(0 && "unsupported dsymbol for DtoConstInitDsymbol");
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDefineDsymbol(Dsymbol* dsym)
|
||||
{
|
||||
if (StructDeclaration* sd = dsym->isStructDeclaration()) {
|
||||
DtoDefineStruct(sd);
|
||||
}
|
||||
else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
|
||||
DtoDefineClass(cd);
|
||||
}
|
||||
else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
|
||||
DtoDefineFunc(fd);
|
||||
}
|
||||
else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
|
||||
DtoDefineTypeInfo(fd);
|
||||
}
|
||||
else {
|
||||
error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars());
|
||||
assert(0 && "unsupported dsymbol for DtoDefineDsymbol");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1361,11 +1350,11 @@ void DtoConstInitDsymbol(Dsymbol* dsym)
|
||||
|
||||
void DtoConstInitGlobal(VarDeclaration* vd)
|
||||
{
|
||||
Logger::println("DtoConstInitGlobal(%s)", vd->toChars());
|
||||
LOG_SCOPE;
|
||||
if (vd->llvmInitialized) return;
|
||||
vd->llvmInitialized = gIR->dmodule;
|
||||
|
||||
if (vd->llvmDModule) return;
|
||||
vd->llvmDModule = gIR->dmodule;
|
||||
Logger::println("* DtoConstInitGlobal(%s)", vd->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
bool emitRTstaticInit = false;
|
||||
|
||||
@@ -1428,3 +1417,100 @@ void DtoConstInitGlobal(VarDeclaration* vd)
|
||||
if (emitRTstaticInit)
|
||||
DtoLazyStaticInit(istempl, gvar, vd->init, t);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoEmptyResolveList()
|
||||
{
|
||||
//Logger::println("DtoEmptyResolveList()");
|
||||
Dsymbol* dsym;
|
||||
while (!gIR->resolveList.empty()) {
|
||||
dsym = gIR->resolveList.front();
|
||||
gIR->resolveList.pop_front();
|
||||
DtoResolveDsymbol(dsym);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoEmptyDeclareList()
|
||||
{
|
||||
//Logger::println("DtoEmptyDeclareList()");
|
||||
Dsymbol* dsym;
|
||||
while (!gIR->declareList.empty()) {
|
||||
dsym = gIR->declareList.front();
|
||||
gIR->declareList.pop_front();
|
||||
DtoDeclareDsymbol(dsym);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoEmptyConstInitList()
|
||||
{
|
||||
//Logger::println("DtoEmptyConstInitList()");
|
||||
Dsymbol* dsym;
|
||||
while (!gIR->constInitList.empty()) {
|
||||
dsym = gIR->constInitList.front();
|
||||
gIR->constInitList.pop_front();
|
||||
DtoConstInitDsymbol(dsym);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoEmptyDefineList()
|
||||
{
|
||||
//Logger::println("DtoEmptyDefineList()");
|
||||
Dsymbol* dsym;
|
||||
while (!gIR->defineList.empty()) {
|
||||
dsym = gIR->defineList.front();
|
||||
gIR->defineList.pop_front();
|
||||
DtoDefineDsymbol(dsym);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoForceDeclareDsymbol(Dsymbol* dsym)
|
||||
{
|
||||
if (dsym->llvmDeclared) return;
|
||||
Logger::println("DtoForceDeclareDsymbol(%s)", dsym->toChars());
|
||||
LOG_SCOPE;
|
||||
DtoResolveDsymbol(dsym);
|
||||
|
||||
DtoEmptyResolveList();
|
||||
|
||||
DtoDeclareDsymbol(dsym);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoForceConstInitDsymbol(Dsymbol* dsym)
|
||||
{
|
||||
if (dsym->llvmInitialized) return;
|
||||
Logger::println("DtoForceConstInitDsymbol(%s)", dsym->toChars());
|
||||
LOG_SCOPE;
|
||||
DtoResolveDsymbol(dsym);
|
||||
|
||||
DtoEmptyResolveList();
|
||||
DtoEmptyDeclareList();
|
||||
|
||||
DtoConstInitDsymbol(dsym);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoForceDefineDsymbol(Dsymbol* dsym)
|
||||
{
|
||||
if (dsym->llvmDefined) return;
|
||||
Logger::println("DtoForceDefineDsymbol(%s)", dsym->toChars());
|
||||
LOG_SCOPE;
|
||||
DtoResolveDsymbol(dsym);
|
||||
|
||||
DtoEmptyResolveList();
|
||||
DtoEmptyDeclareList();
|
||||
DtoEmptyConstInitList();
|
||||
|
||||
DtoDefineDsymbol(dsym);
|
||||
}
|
||||
|
||||
12
gen/tollvm.h
12
gen/tollvm.h
@@ -53,15 +53,26 @@ llvm::ConstantInt* DtoConstInt(int i);
|
||||
llvm::Constant* DtoConstString(const char*);
|
||||
llvm::Constant* DtoConstStringPtr(const char* str, const char* section = 0);
|
||||
llvm::Constant* DtoConstBool(bool);
|
||||
llvm::Constant* DtoConstNullPtr(const llvm::Type* t);
|
||||
|
||||
bool DtoIsTemplateInstance(Dsymbol* s);
|
||||
|
||||
void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type* t);
|
||||
|
||||
void DtoResolveDsymbol(Dsymbol* dsym);
|
||||
void DtoDeclareDsymbol(Dsymbol* dsym);
|
||||
void DtoDefineDsymbol(Dsymbol* dsym);
|
||||
void DtoConstInitDsymbol(Dsymbol* dsym);
|
||||
|
||||
void DtoConstInitGlobal(VarDeclaration* vd);
|
||||
|
||||
void DtoEmptyResolveList();
|
||||
void DtoEmptyDeclareList();
|
||||
void DtoEmptyConstInitList();
|
||||
void DtoForceDeclareDsymbol(Dsymbol* dsym);
|
||||
void DtoForceConstInitDsymbol(Dsymbol* dsym);
|
||||
void DtoForceDefineDsymbol(Dsymbol* dsym);
|
||||
|
||||
// llvm wrappers
|
||||
void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
|
||||
bool DtoCanLoad(llvm::Value* ptr);
|
||||
@@ -87,7 +98,6 @@ void DtoAssign(DValue* lhs, DValue* rhs);
|
||||
DValue* DtoCastInt(DValue* val, Type* to);
|
||||
DValue* DtoCastPtr(DValue* val, Type* to);
|
||||
DValue* DtoCastFloat(DValue* val, Type* to);
|
||||
DValue* DtoCastArray(DValue* val, Type* to);
|
||||
DValue* DtoCastClass(DValue* val, Type* to);
|
||||
DValue* DtoCast(DValue* val, Type* to);
|
||||
|
||||
|
||||
@@ -92,14 +92,33 @@ Module::genobjfile()
|
||||
dsym->toObjFile();
|
||||
}
|
||||
|
||||
// process deferred const initializers
|
||||
for (size_t i=0; i<ir.constInitQueue.size(); ++i) {
|
||||
DtoConstInitDsymbol(ir.constInitQueue[i]);
|
||||
}
|
||||
|
||||
// process deferred definitions
|
||||
for (size_t i=0; i<ir.defineQueue.size(); ++i) {
|
||||
DtoDefineDsymbol(ir.defineQueue[i]);
|
||||
// main driver loop
|
||||
for(;;)
|
||||
{
|
||||
Dsymbol* dsym;
|
||||
if (!ir.resolveList.empty()) {
|
||||
dsym = ir.resolveList.front();
|
||||
ir.resolveList.pop_front();
|
||||
DtoResolveDsymbol(dsym);
|
||||
}
|
||||
else if (!ir.declareList.empty()) {
|
||||
dsym = ir.declareList.front();
|
||||
ir.declareList.pop_front();
|
||||
DtoDeclareDsymbol(dsym);
|
||||
}
|
||||
else if (!ir.constInitList.empty()) {
|
||||
dsym = ir.constInitList.front();
|
||||
ir.constInitList.pop_front();
|
||||
DtoConstInitDsymbol(dsym);
|
||||
}
|
||||
else if (!ir.defineList.empty()) {
|
||||
dsym = ir.defineList.front();
|
||||
ir.defineList.pop_front();
|
||||
DtoDefineDsymbol(dsym);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// generate ModuleInfo
|
||||
@@ -326,7 +345,7 @@ void InterfaceDeclaration::toObjFile()
|
||||
|
||||
void StructDeclaration::toObjFile()
|
||||
{
|
||||
DtoDeclareStruct(this);
|
||||
gIR->resolveList.push_back(this);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
@@ -364,7 +383,7 @@ void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>
|
||||
|
||||
void ClassDeclaration::toObjFile()
|
||||
{
|
||||
DtoDeclareClass(this);
|
||||
gIR->resolveList.push_back(this);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
@@ -394,8 +413,9 @@ void VarDeclaration::toObjFile()
|
||||
// global variable or magic
|
||||
if (isDataseg())
|
||||
{
|
||||
if (llvmTouched) return;
|
||||
else llvmTouched = true;
|
||||
if (llvmResolved) return;
|
||||
llvmResolved = true;
|
||||
llvmDeclared = true;
|
||||
|
||||
llvmIRGlobal = new IRGlobal(this);
|
||||
|
||||
@@ -430,7 +450,7 @@ void VarDeclaration::toObjFile()
|
||||
if (static_local)
|
||||
DtoConstInitGlobal(this);
|
||||
else
|
||||
gIR->constInitQueue.push_back(this);
|
||||
gIR->constInitList.push_back(this);
|
||||
|
||||
//if (storage_class & STCprivate)
|
||||
// gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility);
|
||||
@@ -473,5 +493,5 @@ void EnumDeclaration::toObjFile()
|
||||
|
||||
void FuncDeclaration::toObjFile()
|
||||
{
|
||||
DtoDeclareFunction(this);
|
||||
gIR->resolveList.push_back(this);
|
||||
}
|
||||
|
||||
9
gen/typeinf.h
Normal file
9
gen/typeinf.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef LLVMDC_GEN_TYPEINF_H
|
||||
#define LLVMDC_GEN_TYPEINF_H
|
||||
|
||||
void DtoResolveTypeInfo(TypeInfoDeclaration* tid);
|
||||
void DtoDeclareTypeInfo(TypeInfoDeclaration* tid);
|
||||
void DtoConstInitTypeInfo(TypeInfoDeclaration* tid);
|
||||
void DtoDefineTypeInfo(TypeInfoDeclaration* tid);
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,10 @@
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
// Modifications for LLVMDC:
|
||||
// Copyright (c) 2007 by Tomas Lindquist Olsen
|
||||
// tomas at famolsen dk
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
@@ -238,32 +242,76 @@ Expression *createTypeInfoArray(Scope *sc, Expression *exps[], int dim)
|
||||
|
||||
void TypeInfoDeclaration::toObjFile()
|
||||
{
|
||||
if (llvmTouched) return;
|
||||
else llvmTouched = true;
|
||||
gIR->resolveList.push_back(this);
|
||||
}
|
||||
|
||||
Logger::println("TypeInfoDeclaration::toObjFile()");
|
||||
void DtoResolveTypeInfo(TypeInfoDeclaration* tid)
|
||||
{
|
||||
if (tid->llvmResolved) return;
|
||||
tid->llvmResolved = true;
|
||||
|
||||
Logger::println("* DtoResolveTypeInfo(%s)", tid->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
std::string mangled(mangle());
|
||||
tid->llvmIRGlobal = new IRGlobal(tid);
|
||||
|
||||
Logger::println("type = '%s'", tinfo->toChars());
|
||||
gIR->declareList.push_back(tid);
|
||||
}
|
||||
|
||||
void DtoDeclareTypeInfo(TypeInfoDeclaration* tid)
|
||||
{
|
||||
if (tid->llvmDeclared) return;
|
||||
tid->llvmDeclared = true;
|
||||
|
||||
Logger::println("* DtoDeclareTypeInfo(%s)", tid->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
std::string mangled(tid->mangle());
|
||||
|
||||
Logger::println("type = '%s'", tid->tinfo->toChars());
|
||||
Logger::println("typeinfo mangle: %s", mangled.c_str());
|
||||
|
||||
// this is a declaration of a builtin __initZ var
|
||||
if (tinfo->builtinTypeInfo()) {
|
||||
llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangled.c_str());
|
||||
assert(llvmValue);
|
||||
if (tid->tinfo->builtinTypeInfo()) {
|
||||
tid->llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangled.c_str());
|
||||
assert(tid->llvmValue);
|
||||
mangled.append("__TYPE");
|
||||
gIR->module->addTypeName(mangled, llvmValue->getType()->getContainedType(0));
|
||||
Logger::println("Got typeinfo var: %s", llvmValue->getName().c_str());
|
||||
gIR->module->addTypeName(mangled, tid->llvmValue->getType()->getContainedType(0));
|
||||
Logger::println("Got typeinfo var: %s", tid->llvmValue->getName().c_str());
|
||||
tid->llvmInitialized = true;
|
||||
tid->llvmDefined = true;
|
||||
}
|
||||
// custom typedef
|
||||
else {
|
||||
// emit globals
|
||||
toDt(NULL);
|
||||
gIR->constInitList.push_back(tid);
|
||||
}
|
||||
}
|
||||
|
||||
void DtoConstInitTypeInfo(TypeInfoDeclaration* tid)
|
||||
{
|
||||
if (tid->llvmInitialized) return;
|
||||
tid->llvmInitialized = true;
|
||||
|
||||
Logger::println("* DtoConstInitTypeInfo(%s)", tid->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
tid->toDt(NULL);
|
||||
|
||||
tid->llvmDefined = true;
|
||||
//gIR->defineList.push_back(tid);
|
||||
}
|
||||
|
||||
void DtoDefineTypeInfo(TypeInfoDeclaration* tid)
|
||||
{
|
||||
if (tid->llvmDefined) return;
|
||||
tid->llvmDefined = true;
|
||||
|
||||
Logger::println("* DtoDefineTypeInfo(%s)", tid->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
void TypeInfoDeclaration::toDt(dt_t **pdt)
|
||||
@@ -279,9 +327,10 @@ void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
|
||||
LOG_SCOPE;
|
||||
|
||||
ClassDeclaration* base = Type::typeinfotypedef;
|
||||
base->toObjFile();
|
||||
DtoForceConstInitDsymbol(base);
|
||||
|
||||
const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
|
||||
Logger::cout() << "got stype: " << *stype << '\n';
|
||||
|
||||
std::vector<llvm::Constant*> sinits;
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
@@ -295,10 +344,13 @@ void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
|
||||
//sinits.push_back(llvm::ConstantPointerNull::get(basept));
|
||||
Logger::println("generating base typeinfo");
|
||||
//sd->basetype = sd->basetype->merge();
|
||||
|
||||
sd->basetype->getTypeInfo(NULL); // generate vtinfo
|
||||
assert(sd->basetype->vtinfo);
|
||||
if (!sd->basetype->vtinfo->llvmValue)
|
||||
sd->basetype->vtinfo->toObjFile();
|
||||
DtoForceConstInitDsymbol(sd->basetype->vtinfo);
|
||||
|
||||
assert(sd->basetype->vtinfo->llvmValue);
|
||||
assert(llvm::isa<llvm::Constant>(sd->basetype->vtinfo->llvmValue));
|
||||
llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->basetype->vtinfo->llvmValue);
|
||||
castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1));
|
||||
@@ -341,7 +393,7 @@ void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
|
||||
LOG_SCOPE;
|
||||
|
||||
ClassDeclaration* base = Type::typeinfoenum;
|
||||
base->toObjFile();
|
||||
DtoForceConstInitDsymbol(base);
|
||||
|
||||
const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
|
||||
|
||||
@@ -357,10 +409,12 @@ void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
|
||||
//sinits.push_back(llvm::ConstantPointerNull::get(basept));
|
||||
Logger::println("generating base typeinfo");
|
||||
//sd->basetype = sd->basetype->merge();
|
||||
|
||||
sd->memtype->getTypeInfo(NULL); // generate vtinfo
|
||||
assert(sd->memtype->vtinfo);
|
||||
if (!sd->memtype->vtinfo->llvmValue)
|
||||
sd->memtype->vtinfo->toObjFile();
|
||||
DtoForceConstInitDsymbol(sd->memtype->vtinfo);
|
||||
|
||||
assert(llvm::isa<llvm::Constant>(sd->memtype->vtinfo->llvmValue));
|
||||
llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->memtype->vtinfo->llvmValue);
|
||||
castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1));
|
||||
@@ -401,7 +455,7 @@ void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
|
||||
static llvm::Constant* LLVM_D_Create_TypeInfoBase(Type* basetype, TypeInfoDeclaration* tid, ClassDeclaration* cd)
|
||||
{
|
||||
ClassDeclaration* base = cd;
|
||||
base->toObjFile();
|
||||
DtoForceConstInitDsymbol(base);
|
||||
|
||||
const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
|
||||
|
||||
@@ -413,7 +467,7 @@ static llvm::Constant* LLVM_D_Create_TypeInfoBase(Type* basetype, TypeInfoDeclar
|
||||
basetype->getTypeInfo(NULL);
|
||||
assert(basetype->vtinfo);
|
||||
if (!basetype->vtinfo->llvmValue)
|
||||
basetype->vtinfo->toObjFile();
|
||||
DtoForceConstInitDsymbol(basetype->vtinfo);
|
||||
assert(llvm::isa<llvm::Constant>(basetype->vtinfo->llvmValue));
|
||||
llvm::Constant* castbase = llvm::cast<llvm::Constant>(basetype->vtinfo->llvmValue);
|
||||
castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1));
|
||||
@@ -533,11 +587,10 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
assert(tinfo->ty == Tstruct);
|
||||
TypeStruct *tc = (TypeStruct *)tinfo;
|
||||
StructDeclaration *sd = tc->sym;
|
||||
sd->toObjFile();
|
||||
DtoConstInitStruct(sd);
|
||||
DtoForceConstInitDsymbol(sd);
|
||||
|
||||
ClassDeclaration* base = Type::typeinfostruct;
|
||||
base->toObjFile();
|
||||
DtoForceConstInitDsymbol(base);
|
||||
|
||||
const llvm::StructType* stype = isaStruct(((TypeClass*)base->type)->llvmType->get());
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
<hidenonlocation>false</hidenonlocation>
|
||||
</groups>
|
||||
<tree>
|
||||
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
|
||||
<hidepatterns>*.bc</hidepatterns>
|
||||
<hidenonprojectfiles>false</hidenonprojectfiles>
|
||||
</tree>
|
||||
</kdevfileview>
|
||||
@@ -394,6 +394,7 @@
|
||||
<path>obj/Debug/unialpha.d</path>
|
||||
<path>obj/Debug/utf.d</path>
|
||||
<path>obj/Debug/version.d</path>
|
||||
<path>obj</path>
|
||||
</blacklist>
|
||||
<build>
|
||||
<buildtool>make</buildtool>
|
||||
|
||||
@@ -129,6 +129,7 @@ gen/toir.cpp
|
||||
gen/tollvm.cpp
|
||||
gen/tollvm.h
|
||||
gen/toobj.cpp
|
||||
gen/typeinf.h
|
||||
gen/typinf.cpp
|
||||
lphobos
|
||||
lphobos/crc32.d
|
||||
@@ -299,7 +300,7 @@ test/bug62.d
|
||||
test/bug63.d
|
||||
test/bug64.d
|
||||
test/bug66.d
|
||||
test/bug67.d
|
||||
test/bug69.d
|
||||
test/bug7.d
|
||||
test/bug8.d
|
||||
test/bug9.d
|
||||
|
||||
@@ -20,7 +20,7 @@ llvm-link -f -o=../lib/llvmdcore.bc `ls obj/internal.*.bc` ../lib/llvmdcore.bc o
|
||||
|
||||
|
||||
echo "compiling typeinfo 1"
|
||||
rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix || exit 1
|
||||
rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix -v || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo1.*.bc` ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling typeinfo 2"
|
||||
@@ -52,7 +52,7 @@ llvmdc gc/gcstub.d -c -odobj -Igc || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcstub.bc ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling phobos"
|
||||
rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1
|
||||
rebuild phobos.d -c -oqobj -dc=llvmdc-posix -v || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "optimizing"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module bug51;
|
||||
const ubyte[3] arr1 = 0;
|
||||
const ubyte[3] arr2 = [0];
|
||||
const ubyte[3] arr3 = [0:1];
|
||||
void main() {}
|
||||
const ubyte[3] arr3 = [1:1];
|
||||
void main()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
module classinfo1;
|
||||
|
||||
class C
|
||||
class NoPtrs
|
||||
{
|
||||
}
|
||||
|
||||
class HasPtrs
|
||||
{
|
||||
void* p;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ClassInfo ci = C.classinfo;
|
||||
{
|
||||
ClassInfo ci = NoPtrs.classinfo;
|
||||
char[] name = ci.name;
|
||||
printf("%.*s\n", name.length, name.ptr);
|
||||
assert(ci.name == "classinfo1.NoPtrs");
|
||||
assert(ci.flags == 2);
|
||||
}
|
||||
{
|
||||
ClassInfo ci = HasPtrs.classinfo;
|
||||
char[] name = ci.name;
|
||||
printf("%.*s\n", name.length, name.ptr);
|
||||
assert(ci.name == "classinfo1.HasPtrs");
|
||||
assert(ci.flags == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,14 +42,14 @@ void function_pointers()
|
||||
|
||||
binfn_t binfn = &add_int;
|
||||
assert(binfn(4,1045) == 1049);
|
||||
|
||||
|
||||
assert(binop_int(binfn, 10,656) == 666);
|
||||
|
||||
|
||||
binfn = get_binop_int('+');
|
||||
assert(binop_int(binfn, 10,100) == 110);
|
||||
binfn = get_binop_int('-');
|
||||
assert(binop_int(binfn, 10,100) == -90);
|
||||
|
||||
|
||||
{
|
||||
auto ffn = &mul_float;
|
||||
float ftmp = mul_float(2.5,5);
|
||||
|
||||
Reference in New Issue
Block a user