[svn r120] ModuleInfo implementation is now almost complete.

Fixed some nasty static array-initializer bugs.
Fixed bug in DtoArrayLen and DtoArrayPtr for full slices of static arrays.
This commit is contained in:
Tomas Lindquist Olsen
2007-11-25 18:55:52 +01:00
parent c08b0918cc
commit cb37aab93b
12 changed files with 331 additions and 176 deletions

View File

@@ -285,22 +285,32 @@ llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
std::vector<llvm::Constant*> inits(tdim, NULL);
Type* arrnext = arrinittype->next;
const llvm::Type* elemty = DtoType(arrinittype->next);
assert(arrinit->index.dim == arrinit->value.dim);
for (unsigned i=0,j=0; i < tdim; ++i)
{
Initializer* init = 0;
Expression* idx = (Expression*)arrinit->index.data[j];
Expression* idx;
if (j < arrinit->index.dim)
idx = (Expression*)arrinit->index.data[j];
else
idx = NULL;
llvm::Constant* v = NULL;
if (idx)
{
Logger::println("%d has idx", i);
// this is pretty weird :/ idx->type turned out NULL for the initializer:
// const in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
// in std.c.linux.socket
if (idx->type) {
Logger::println("has idx->type", i);
//integer_t k = idx->toInteger();
Logger::println("getting value for exp: %s | %s", idx->toChars(), idx->type->toChars());
//Logger::println("getting value for exp: %s | %s", idx->toChars(), arrnext->toChars());
llvm::Constant* cc = idx->toConstElem(gIR);
Logger::println("value gotten");
assert(cc != NULL);
@@ -317,11 +327,16 @@ llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
}
else
{
init = (Initializer*)arrinit->value.data[j];
++j;
if (j < arrinit->value.dim) {
init = (Initializer*)arrinit->value.data[j];
++j;
}
else
v = arrnext->defaultInit()->toConstElem(gIR);
}
llvm::Constant* v = DtoConstInitializer(t->next, init);
if (!v)
v = DtoConstInitializer(t->next, init);
assert(v);
inits[i] = v;
@@ -784,16 +799,22 @@ llvm::Constant* DtoConstStaticArray(const llvm::Type* t, llvm::Constant* c)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* DtoArrayLen(DValue* v)
{
Logger::println("DtoArrayLen");
LOG_SCOPE;
Type* t = DtoDType(v->getType());
if (t->ty == Tarray) {
if (DSliceValue* s = v->isSlice()) {
if (s->len) return s->len;
DValue* next = new DVarValue(t,s->ptr,true);
return DtoArrayLen(next);
if (s->len) {
return s->len;
}
const llvm::ArrayType* arrTy = isaArray(s->ptr->getType()->getContainedType(0));
assert(arrTy);
return DtoConstSize_t(arrTy->getNumElements());
}
return DtoLoad(DtoGEPi(v->getRVal(), 0,0, "tmp"));
}
else if (t->ty == Tsarray) {
assert(!v->isSlice());
llvm::Value* rv = v->getRVal();
Logger::cout() << "casting: " << *rv << '\n';
const llvm::ArrayType* t = isaArray(rv->getType()->getContainedType(0));
@@ -810,8 +831,9 @@ llvm::Value* DtoArrayPtr(DValue* v)
if (t->ty == Tarray) {
if (DSliceValue* s = v->isSlice()) {
if (s->len) return s->ptr;
DValue* next = new DVarValue(t,s->ptr,true);
return DtoArrayPtr(next);
const llvm::ArrayType* arrTy = isaArray(s->ptr->getType()->getContainedType(0));
assert(arrTy);
return DtoGEPi(s->ptr, 0,0, "tmp");
}
return DtoLoad(DtoGEPi(v->getRVal(), 0,1, "tmp"));
}

View File

@@ -368,10 +368,20 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
fdecl->llvmValue = func;
assert(llvm::isa<llvm::FunctionType>(f->llvmType->get()));
// main
if (fdecl->isMain()) {
gIR->mainFunc = func;
}
// static ctor
if (fdecl->isStaticCtorDeclaration()) {
gIR->ctors.push_back(fdecl);
}
// static dtor
else if (fdecl->isStaticDtorDeclaration()) {
gIR->dtors.push_back(fdecl);
}
// name parameters
llvm::Function::arg_iterator iarg = func->arg_begin();
int k = 0;

View File

@@ -218,6 +218,12 @@ struct IRState
DsymbolList constInitList;
// dsymbols that need definitions
DsymbolList defineList;
// static ctors/dtors/unittests
typedef std::vector<FuncDeclaration*> FuncDeclVector;
FuncDeclVector ctors;
FuncDeclVector dtors;
FuncDeclVector unitTests;
};
#endif // LLVMDC_GEN_IRSTATE_H

View File

@@ -1491,6 +1491,9 @@ DValue* SliceExp::toElem(IRState* p)
emem = vmem;
}
if (earg) Logger::cout() << "slice exp result, length = " << *earg << '\n';
Logger::cout() << "slice exp result, ptr = " << *emem << '\n';
return new DSliceValue(type,earg,emem);
}

View File

@@ -1616,6 +1616,38 @@ void DtoEmptyDefineList()
}
}
//////////////////////////////////////////////////////////////////////////////////////////
void DtoEmptyAllLists()
{
for(;;)
{
Dsymbol* dsym;
if (!gIR->resolveList.empty()) {
dsym = gIR->resolveList.front();
gIR->resolveList.pop_front();
DtoResolveDsymbol(dsym);
}
else if (!gIR->declareList.empty()) {
dsym = gIR->declareList.front();
gIR->declareList.pop_front();
DtoDeclareDsymbol(dsym);
}
else if (!gIR->constInitList.empty()) {
dsym = gIR->constInitList.front();
gIR->constInitList.pop_front();
DtoConstInitDsymbol(dsym);
}
else if (!gIR->defineList.empty()) {
dsym = gIR->defineList.front();
gIR->defineList.pop_front();
DtoDefineDsymbol(dsym);
}
else {
break;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////
void DtoForceDeclareDsymbol(Dsymbol* dsym)

View File

@@ -69,6 +69,7 @@ void DtoConstInitGlobal(VarDeclaration* vd);
void DtoEmptyResolveList();
void DtoEmptyDeclareList();
void DtoEmptyConstInitList();
void DtoEmptyAllLists();
void DtoForceDeclareDsymbol(Dsymbol* dsym);
void DtoForceConstInitDsymbol(Dsymbol* dsym);
void DtoForceDefineDsymbol(Dsymbol* dsym);

View File

@@ -106,36 +106,11 @@ Module::genobjfile()
}
// 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;
}
}
DtoEmptyAllLists();
// generate ModuleInfo
genmoduleinfo();
// do this again as moduleinfo might have pulled something in!
DtoEmptyAllLists();
gTargetData = 0;
@@ -181,6 +156,72 @@ Module::genobjfile()
/* ================================================================== */
// build module ctor
static llvm::Function* build_module_ctor()
{
if (gIR->ctors.empty())
return NULL;
size_t n = gIR->ctors.size();
if (n == 1)
return llvm::cast<llvm::Function>(gIR->ctors[0]->llvmValue);
std::string name("_D");
name.append(gIR->dmodule->mangle());
name.append("6__ctorZ");
std::vector<const llvm::Type*> argsTy;
const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy,argsTy,false);
llvm::Function* fn = new llvm::Function(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module);
fn->setCallingConv(llvm::CallingConv::Fast);
llvm::BasicBlock* bb = new llvm::BasicBlock("entry", fn);
LLVMBuilder builder(bb);
for (size_t i=0; i<n; i++) {
llvm::Function* f = llvm::cast<llvm::Function>(gIR->ctors[i]->llvmValue);
llvm::CallInst* call = builder.CreateCall(f,"");
call->setCallingConv(llvm::CallingConv::Fast);
}
builder.CreateRetVoid();
return fn;
}
// build module dtor
static llvm::Function* build_module_dtor()
{
if (gIR->dtors.empty())
return NULL;
size_t n = gIR->dtors.size();
if (n == 1)
return llvm::cast<llvm::Function>(gIR->dtors[0]->llvmValue);
std::string name("_D");
name.append(gIR->dmodule->mangle());
name.append("6__dtorZ");
std::vector<const llvm::Type*> argsTy;
const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy,argsTy,false);
llvm::Function* fn = new llvm::Function(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module);
fn->setCallingConv(llvm::CallingConv::Fast);
llvm::BasicBlock* bb = new llvm::BasicBlock("entry", fn);
LLVMBuilder builder(bb);
for (size_t i=0; i<n; i++) {
llvm::Function* f = llvm::cast<llvm::Function>(gIR->dtors[i]->llvmValue);
llvm::CallInst* call = builder.CreateCall(f,"");
call->setCallingConv(llvm::CallingConv::Fast);
}
builder.CreateRetVoid();
return fn;
}
// Put out instance of ModuleInfo for this Module
void Module::genmoduleinfo()
@@ -198,139 +239,131 @@ void Module::genmoduleinfo()
// void *unitTest;
// }
if (moduleinfo) {
Logger::println("moduleinfo");
}
if (vmoduleinfo) {
Logger::println("vmoduleinfo");
}
if (needModuleInfo()) {
Logger::attention("module info is needed but skipped");
}
// resolve ModuleInfo
assert(moduleinfo);
DtoForceConstInitDsymbol(moduleinfo);
// moduleinfo llvm struct type
const llvm::StructType* moduleinfoTy = isaStruct(moduleinfo->type->llvmType->get());
/*
Symbol *msym = toSymbol();
unsigned offset;
unsigned sizeof_ModuleInfo = 12 * PTRSIZE;
// classinfo llvm struct type
const llvm::StructType* classinfoTy = isaStruct(ClassDeclaration::classinfo->type->llvmType->get());
//////////////////////////////////////////////
// initializer vector
std::vector<llvm::Constant*> initVec;
llvm::Constant* c = 0;
csym->Sclass = SCglobal;
csym->Sfl = FLdata;
// vtable
c = moduleinfo->llvmVtbl;
initVec.push_back(c);
// The layout is:
// {
// void **vptr;
// monitor_t monitor;
// char[] name; // class name
// ModuleInfo importedModules[];
// ClassInfo localClasses[];
// uint flags; // initialization state
// void *ctor;
// void *dtor;
// void *unitTest;
// }
dt_t *dt = NULL;
// monitor
c = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
initVec.push_back(c);
if (moduleinfo)
dtxoff(&dt, moduleinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ModuleInfo
else
dtdword(&dt, 0); // BUG: should be an assert()
dtdword(&dt, 0); // monitor
// name[]
// name
char *name = toPrettyChars();
size_t namelen = strlen(name);
dtdword(&dt, namelen);
dtabytes(&dt, TYnptr, 0, namelen + 1, name);
ClassDeclarations aclasses;
int i;
//printf("members->dim = %d\n", members->dim);
for (i = 0; i < members->dim; i++)
{
Dsymbol *member;
member = (Dsymbol *)members->data[i];
//printf("\tmember '%s'\n", member->toChars());
member->addLocalClass(&aclasses);
}
c = DtoConstString(name);
initVec.push_back(c);
// importedModules[]
int aimports_dim = aimports.dim;
for (i = 0; i < aimports.dim; i++)
{ Module *m = (Module *)aimports.data[i];
if (!m->needModuleInfo())
aimports_dim--;
std::vector<llvm::Constant*> importInits;
for (size_t i = 0; i < aimports.dim; i++)
{
Module *m = (Module *)aimports.data[i];
if (!m->needModuleInfo())
aimports_dim--;
else { // declare
// create name
std::string m_name("_D");
m_name.append(m->mangle());
m_name.append("8__ModuleZ");
llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name, gIR->module);
importInits.push_back(m_gvar);
}
}
// has import array?
if (!importInits.empty()) {
const llvm::ArrayType* importArrTy = llvm::ArrayType::get(llvm::PointerType::get(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 = DtoConstSlice(DtoConstSize_t(importInits.size()), c);
}
dtdword(&dt, aimports_dim);
if (aimports.dim)
dtxoff(&dt, csym, sizeof_ModuleInfo, TYnptr);
else
dtdword(&dt, 0);
c = moduleinfo->llvmInitZ->getOperand(3);
initVec.push_back(c);
// localClasses[]
dtdword(&dt, aclasses.dim);
if (aclasses.dim)
dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYnptr);
else
dtdword(&dt, 0);
ClassDeclarations aclasses;
//printf("members->dim = %d\n", members->dim);
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *member;
member = (Dsymbol *)members->data[i];
//printf("\tmember '%s'\n", member->toChars());
member->addLocalClass(&aclasses);
}
// fill inits
std::vector<llvm::Constant*> classInits;
for (size_t i = 0; i < aclasses.dim; i++)
{
ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i];
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());
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 = DtoConstSlice(DtoConstSize_t(classInits.size()), c);
}
else
c = moduleinfo->llvmInitZ->getOperand(4);
initVec.push_back(c);
// flags
if (needmoduleinfo)
dtdword(&dt, 0); // flags (4 means MIstandalone)
c = DtoConstUint(0); // flags (4 means MIstandalone)
else
dtdword(&dt, 4); // flags (4 means MIstandalone)
c = DtoConstUint(4); // flags (4 means MIstandalone)
initVec.push_back(c);
if (sctor)
dtxoff(&dt, sctor, 0, TYnptr);
else
dtdword(&dt, 0);
// ctor
llvm::Function* fctor = build_module_ctor();
c = fctor ? fctor : moduleinfo->llvmInitZ->getOperand(6);
initVec.push_back(c);
if (sdtor)
dtxoff(&dt, sdtor, 0, TYnptr);
else
dtdword(&dt, 0);
// dtor
llvm::Function* fdtor = build_module_dtor();
c = fdtor ? fdtor : moduleinfo->llvmInitZ->getOperand(7);
initVec.push_back(c);
if (stest)
dtxoff(&dt, stest, 0, TYnptr);
else
dtdword(&dt, 0);
// unitTest
c = moduleinfo->llvmInitZ->getOperand(8);
initVec.push_back(c);
//////////////////////////////////////////////
// create initializer
llvm::Constant* constMI = llvm::ConstantStruct::get(moduleinfoTy, initVec);
for (i = 0; i < aimports.dim; i++)
{
Module *m;
// create name
std::string MIname("_D");
MIname.append(mangle());
MIname.append("8__ModuleZ");
m = (Module *)aimports.data[i];
if (m->needModuleInfo())
{ Symbol *s = m->toSymbol();
s->Sflags |= SFLweak;
dtxoff(&dt, s, 0, TYnptr);
}
}
for (i = 0; i < aclasses.dim; i++)
{
ClassDeclaration *cd;
cd = (ClassDeclaration *)aclasses.data[i];
dtxoff(&dt, cd->toSymbol(), 0, TYnptr);
}
csym->Sdt = dt;
#if ELFOBJ
// Cannot be CONST because the startup code sets flag bits in it
csym->Sseg = DATA;
#endif
outdata(csym);
//////////////////////////////////////////////
obj_moduleinfo(msym);
*/
// declare
// flags will be modified at runtime so can't make it constant
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, constMI, MIname, gIR->module);
}
/* ================================================================== */

View File

@@ -33,7 +33,8 @@
*/
/*
* This copy is modified to work with LLVMDC by Tomas Lindquist Olsen 2007
* This copy is modified to work with LLVMDC
* by Tomas Lindquist Olsen, September 2007
*/
module object;
@@ -1119,6 +1120,30 @@ class TypeInfo_Invariant : TypeInfo_Const
char[] toString() { return "invariant " ~ base.toString(); }
}
/**
* Information about each module.
*/
class ModuleInfo
{
char[] name;
ModuleInfo[] importedModules;
ClassInfo[] localClasses;
uint flags; // initialization state
void function() ctor;
void function() dtor;
void function() unitTest;
/******************
* Return collection of all modules in the program.
*/
static ModuleInfo[] modules()
{
return std.moduleinit._moduleinfo_array;
}
}
/**
* All recoverable exceptions should be derived from class Exception.
*/

View File

@@ -162,6 +162,22 @@ class TypeInfo_Invariant : TypeInfo_Const
{
}
class ModuleInfo
{
char[] name;
ModuleInfo[] importedModules;
ClassInfo[] localClasses;
uint flags; // initialization state
void function() ctor;
void function() dtor;
void function() unitTest;
// Return collection of all modules in the program.
static ModuleInfo[] modules();
}
// Recoverable errors
class Exception : Object

View File

@@ -18,29 +18,8 @@ enum
// ctors being done first
}
/***********************
* Information about each module.
*/
class ModuleInfo
{
char[] name;
ModuleInfo[] importedModules;
ClassInfo[] localClasses;
uint flags; // initialization state
void function() ctor;
void function() dtor;
void function() unitTest;
/******************
* Return collection of all modules in the program.
*/
static ModuleInfo[] modules()
{
return _moduleinfo_array;
}
}
// had to move the class to object.d, as its declaration is needed in the compiler code,
// otherwise the DMDFE Module::moduleinfo member is NULL
class ModuleCtorError : Exception
{

View File

@@ -1,7 +1,10 @@
module bug51;
const ubyte[3] arr1 = 0;
const ubyte[3] arr2 = [0];
const ubyte[3] arr1 = 1;
const ubyte[3] arr2 = [1];
const ubyte[3] arr3 = [1:1];
void main()
{
assert(arr1 == [cast(ubyte)1,1,1][]);
assert(arr2 == [cast(ubyte)1,0,0][]);
assert(arr3 == [cast(ubyte)0,1,0][]);
}

View File

@@ -1,11 +1,36 @@
module moduleinfo1;
// has static this
import std.outofmemory;
static this()
{
}
static this()
{
}
static ~this()
{
}
static ~this()
{
}
unittest
{
}
class C
{
}
void main()
class D : C
{
C c;
}
void main()
{
}