[svn r93] a few fixes, some phobos additions.

some very rough groundwork for moduleinfo and classinfo support
This commit is contained in:
Tomas Lindquist Olsen
2007-11-07 02:45:47 +01:00
parent 34d9e12020
commit e7a17c2744
9 changed files with 569 additions and 7 deletions

View File

@@ -64,6 +64,8 @@ bool DtoIsTemplateInstance(Dsymbol* s);
void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type* t);
void DtoClassInfo(ClassDeclaration* cd);
// llvm wrappers
void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
bool DtoCanLoad(llvm::Value* ptr);

View File

@@ -91,6 +91,9 @@ Module::genobjfile()
dsym->toObjFile();
}
// generate ModuleInfo
genmoduleinfo();
gTargetData = 0;
// emit the llvm main function if necessary
@@ -139,6 +142,152 @@ Module::genobjfile()
void Module::genmoduleinfo()
{
// 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;
// }
if (moduleinfo) {
Logger::println("moduleinfo");
}
if (vmoduleinfo) {
Logger::println("vmoduleinfo");
}
if (needModuleInfo()) {
Logger::println("**** ATTENTION: module info is needed but skipped");
}
/*
Symbol *msym = toSymbol();
unsigned offset;
unsigned sizeof_ModuleInfo = 12 * PTRSIZE;
//////////////////////////////////////////////
csym->Sclass = SCglobal;
csym->Sfl = FLdata;
// 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;
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[]
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);
}
// importedModules[]
int aimports_dim = aimports.dim;
for (i = 0; i < aimports.dim; i++)
{ Module *m = (Module *)aimports.data[i];
if (!m->needModuleInfo())
aimports_dim--;
}
dtdword(&dt, aimports_dim);
if (aimports.dim)
dtxoff(&dt, csym, sizeof_ModuleInfo, TYnptr);
else
dtdword(&dt, 0);
// localClasses[]
dtdword(&dt, aclasses.dim);
if (aclasses.dim)
dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYnptr);
else
dtdword(&dt, 0);
if (needmoduleinfo)
dtdword(&dt, 0); // flags (4 means MIstandalone)
else
dtdword(&dt, 4); // flags (4 means MIstandalone)
if (sctor)
dtxoff(&dt, sctor, 0, TYnptr);
else
dtdword(&dt, 0);
if (sdtor)
dtxoff(&dt, sdtor, 0, TYnptr);
else
dtdword(&dt, 0);
if (stest)
dtxoff(&dt, stest, 0, TYnptr);
else
dtdword(&dt, 0);
//////////////////////////////////////////////
for (i = 0; i < aimports.dim; i++)
{
Module *m;
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);
*/
}
/* ================================================================== */
@@ -553,6 +702,9 @@ void ClassDeclaration::toObjFile()
gIR->structs.pop_back();
llvmInProgress = false;
// if (ClassDeclaration::classinfo != this)
// DtoClassInfo(this);
}
/******************************************

View File

@@ -533,6 +533,7 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
assert(tinfo->ty == Tstruct);
TypeStruct *tc = (TypeStruct *)tinfo;
StructDeclaration *sd = tc->sym;
sd->toObjFile();
ClassDeclaration* base = Type::typeinfostruct;
base->toObjFile();
@@ -773,3 +774,131 @@ void TypeInfoTupleDeclaration::toDt(dt_t **pdt)
dtxoff(pdt, s, 0, TYnptr); // elements.ptr
*/
}
/* ========================================================================= */
/* ========================================================================= */
/* CLASS INFO STUFF */
/* ========================================================================= */
/* ========================================================================= */
void DtoClassInfo(ClassDeclaration* cd)
{
// The layout is:
// {
// void **vptr;
// monitor_t monitor;
// byte[] initializer; // static initialization data
// char[] name; // class name
// void *[] vtbl;
// Interface[] interfaces;
// ClassInfo *base; // base class
// void *destructor;
// void *invariant; // class invariant
// uint flags;
// void *deallocator;
// OffsetTypeInfo[] offTi;
// void *defaultConstructor;
// }
// holds the list of initializers for llvm
std::vector<llvm::Constant*> inits;
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
assert(cinfo);
Logger::println("cinfo toObj");
cinfo->toObjFile();
Logger::println("cinfo toObj done");
assert(cinfo->type->ty == Tclass);
TypeClass* tc = (TypeClass*)cinfo->type;
//assert(tc->llvmInit);
//assert(cinfo->llvmInitZ);
cinfo = ClassDeclaration::classinfo;
assert(cinfo->llvmInitZ);
/*
llvm::Constant* c;
// own vtable
c = cinfo->llvmInitZ->getOperand(0);
assert(c);
inits.push_back(c);
// monitor
// TODO no monitors yet
// initializer
c = cinfo->llvmInitZ->getOperand(1);
inits.push_back(c);
// class name
// from dmd
char *name = cd->ident->toChars();
size_t namelen = strlen(name);
if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
{
name = cd->toPrettyChars();
namelen = strlen(name);
}
c = DtoConstString(name);
inits.push_back(c);
// vtbl array
c = cinfo->llvmInitZ->getOperand(3);
inits.push_back(c);
// interfaces array
c = cinfo->llvmInitZ->getOperand(4);
inits.push_back(c);
// base classinfo
c = cinfo->llvmInitZ->getOperand(5);
inits.push_back(c);
// destructor
c = cinfo->llvmInitZ->getOperand(5);
inits.push_back(c);
// invariant
c = cinfo->llvmInitZ->getOperand(6);
inits.push_back(c);
// flags
c = cinfo->llvmInitZ->getOperand(7);
inits.push_back(c);
// allocator
c = cinfo->llvmInitZ->getOperand(8);
inits.push_back(c);
// offset typeinfo
c = cinfo->llvmInitZ->getOperand(9);
inits.push_back(c);
// default constructor
c = cinfo->llvmInitZ->getOperand(10);
inits.push_back(c);
// build the initializer
const llvm::StructType* st = llvm::cast<llvm::StructType>(cinfo->llvmInitZ->getType());
llvm::Constant* finalinit = llvm::ConstantStruct::get(st, inits);
Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
assert(0);
*/
}

View File

@@ -32,10 +32,13 @@
* distribution.
*/
/*
* This copy is modified to work with LLVMDC by Tomas Lindquist Olsen 2007
*/
module object;
//import std.outofmemory;
import std.outofmemory;
/**
* An unsigned integral type large enough to span the memory space. Use for
@@ -260,6 +263,8 @@ extern (C) void _d_notify_release(Object o)
}
}
+/
/**
* Information about an interface.
* A pointer to this appears as the first entry in the interface's vtbl[].
@@ -272,6 +277,7 @@ struct Interface
}
import std.moduleinit;
/**
* Runtime type information about a class. Can be retrieved for any class type
* or instance by using the .classinfo property.
@@ -287,7 +293,7 @@ class ClassInfo : Object
Interface[] interfaces; /// interfaces this class implements
ClassInfo base; /// base class
void *destructor;
void (*classInvariant)(Object);
void function(Object) classInvariant;
uint flags;
// 1: // IUnknown
// 2: // has no possible pointers into GC memory
@@ -303,7 +309,7 @@ class ClassInfo : Object
*/
static ClassInfo find(char[] classname)
{
foreach (m; ModuleInfo.modules())
/+foreach (m; ModuleInfo.modules())
{
//writefln("module %s, %d", m.name, m.localClasses.length);
foreach (c; m.localClasses)
@@ -312,7 +318,7 @@ class ClassInfo : Object
if (c.name == classname)
return c;
}
}
}+/
return null;
}
@@ -321,7 +327,7 @@ class ClassInfo : Object
*/
Object create()
{
if (flags & 8 && !defaultConstructor)
/+if (flags & 8 && !defaultConstructor)
return null;
Object o = _d_newclass(this);
if (flags & 8 && defaultConstructor)
@@ -329,12 +335,13 @@ class ClassInfo : Object
defaultConstructor(o);
}
return o;
+/
return null;
}
}
private import std.string;
//private import std.string;
+/
/**
* Array of pairs giving the offset and type information for each

View File

@@ -4,6 +4,8 @@ import
std.array,
std.ctype,
std.intrinsic,
std.moduleinit,
std.outofmemory,
std.stdint,
std.stdio,
std.stdarg,

210
lphobos/std/moduleinit.d Normal file
View File

@@ -0,0 +1,210 @@
// Modified for LLVMDC
module std.moduleinit;
//debug = 1;
private
{
import object;
import std.c.stdio;
import std.c.stdlib;
}
enum
{ MIctorstart = 1, // we've started constructing it
MIctordone = 2, // finished construction
MIstandalone = 4, // module ctor does not depend on other module
// 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;
}
}
class ModuleCtorError : Exception
{
this(ModuleInfo m)
{
super("circular initialization dependency with module " ~ m.name);
}
}
// Win32: this gets initialized by minit.asm
// 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
}
ModuleInfo[] _moduleinfo_dtors;
uint _moduleinfo_dtors_i;
// Register termination function pointers
extern (C) int _fatexit(void *);
/*************************************
* Initialize the modules.
*/
extern (C) void _moduleCtor()
{
debug 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++;
}
}
version (Win32)
{
// Ensure module destructors also get called on program termination
//_fatexit(&_STD_moduleDtor);
}
_moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
_moduleCtor2(_moduleinfo_array, 0);
version (none)
{
foreach (m; _moduleinfo_array)
{
writefln("module %s, %d", m.name, m.localClasses.length);
foreach (c; m.localClasses)
{
writefln("\tclass %s", c.name);
}
}
}
}
void _moduleCtor2(ModuleInfo[] mi, int skip)
{
debug printf("_moduleCtor2(): %d modules\n", mi.length);
for (uint i = 0; i < mi.length; i++)
{
ModuleInfo m = mi[i];
debug printf("\tmodule[%d] = '%p'\n", i, m);
if (!m)
continue;
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
if (m.flags & MIctordone)
continue;
debug printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
if (m.ctor || m.dtor)
{
if (m.flags & MIctorstart)
{ if (skip || m.flags & MIstandalone)
continue;
throw new ModuleCtorError(m);
}
m.flags |= MIctorstart;
_moduleCtor2(m.importedModules, 0);
if (m.ctor)
(*m.ctor)();
m.flags &= ~MIctorstart;
m.flags |= MIctordone;
// Now that construction is done, register the destructor
//printf("\tadding module dtor x%x\n", m);
assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
_moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
}
else
{
m.flags |= MIctordone;
_moduleCtor2(m.importedModules, 1);
}
}
}
/**********************************
* Destruct the modules.
*/
// Starting the name with "_STD" means under linux a pointer to the
// function gets put in the .dtors segment.
extern (C) void _moduleDtor()
{
debug printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
for (uint i = _moduleinfo_dtors_i; i-- != 0;)
{
ModuleInfo m = _moduleinfo_dtors[i];
debug printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
if (m.dtor)
{
(*m.dtor)();
}
}
debug printf("_moduleDtor() done\n");
}
/**********************************
* Run unit tests.
*/
extern (C) void _moduleUnitTests()
{
debug printf("_moduleUnitTests()\n");
for (uint i = 0; i < _moduleinfo_array.length; i++)
{
ModuleInfo m = _moduleinfo_array[i];
if (!m)
continue;
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
if (m.unitTest)
{
(*m.unitTest)();
}
}
}

44
lphobos/std/outofmemory.d Normal file
View File

@@ -0,0 +1,44 @@
/**
* Macros:
* WIKI=Phobos/StdOutOfMemory
* Copyright:
* Placed into public domain.
* www.digitalmars.com
*/
module std.outofmemory;
/******
* This exception is thrown when out of memory errors happen.
*/
class OutOfMemoryException : Exception
{
static char[] s = "Out of memory";
/**
* Default constructor
*/
this()
{
super(s);
}
char[] toString()
{
return s;
}
}
extern (C) void _d_OutOfMemory()
{
assert(0);
/*throw cast(OutOfMemoryException)
cast(void *)
OutOfMemoryException.classinfo.init;*/
}
static this()
{
}

5
test/bug52.d Normal file
View File

@@ -0,0 +1,5 @@
module bug52;
struct Vec { double x,y,z; }
struct Pair(T, U) { T first; U second; }
typedef Pair!(double, Vec) Hit;
void main() {}

11
test/moduleinfo1.d Normal file
View File

@@ -0,0 +1,11 @@
module moduleinfo1;
class C
{
}
void main()
{
C c;
}