[svn r121] Finished ModuleInfo implementation.

Static ctors/dtors now work according to spec.
Changed class vtable types slightly in some cases. Overridden functions now always take the the type of the first class declaring the method as this parameter. This helps when using headers (w. implementation somewhere else)
This commit is contained in:
Tomas Lindquist Olsen
2007-11-26 04:49:23 +01:00
parent cb37aab93b
commit e0176785c7
11 changed files with 98 additions and 96 deletions

View File

@@ -167,10 +167,12 @@ void DtoResolveClass(ClassDeclaration* cd)
if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
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);
//assert(fd->type->ty == Tfunction);
//TypeFunction* tf = (TypeFunction*)fd->type;
//const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get());
const llvm::FunctionType* vfty = DtoBaseFunctionType(fd);
const llvm::Type* vfpty = llvm::PointerType::get(vfty);
sinits_ty.push_back(vfpty);
}
else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars());
@@ -375,6 +377,7 @@ void DtoConstInitClass(ClassDeclaration* cd)
assert(cd->type->ty == Tclass);
TypeClass* ts = (TypeClass*)cd->type;
const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get());
// generate initializer
#if 0
@@ -406,6 +409,9 @@ void DtoConstInitClass(ClassDeclaration* cd)
DtoForceDeclareDsymbol(fd);
assert(fd->llvmValue);
llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
// cast if necessary (overridden method)
if (c->getType() != vtbltype->getElementType(k))
c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k));
sinits.push_back(c);
}
else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
@@ -1037,8 +1043,8 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
if (cd->defaultCtor && !cd->isInterfaceDeclaration()) {
DtoForceDeclareDsymbol(cd->defaultCtor);
c = isaConstant(cd->defaultCtor->llvmValue);
//const llvm::Type* toTy = cinfo->llvmInitZ->getOperand(11)->getType();
c = llvm::ConstantExpr::getBitCast(c, llvm::PointerType::get(llvm::Type::Int8Ty)); // toTy);
const llvm::Type* toTy = cinfo->llvmInitZ->getOperand(12)->getType();
c = llvm::ConstantExpr::getBitCast(c, toTy);
}
else {
c = cinfo->llvmInitZ->getOperand(12);

View File

@@ -468,23 +468,6 @@ void DtoDefineFunc(FuncDeclaration* fd)
{
fd->llvmDModule = gIR->dmodule;
// handle static constructor / destructor
if (fd->isStaticCtorDeclaration() || fd->isStaticDtorDeclaration()) {
const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1);
//Logger::cout() << "static ctor type: " << *sctor_type << '\n';
llvm::Constant* sctor_func = llvm::cast<llvm::Constant>(fd->llvmValue);
//Logger::cout() << "static ctor func: " << *sctor_func << '\n';
llvm::Constant* sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1);
//Logger::cout() << "static ctor init: " << *sctor_init << '\n';
// output the llvm.global_ctors array
const char* varname = fd->isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array";
llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module);
}
// function definition
if (fd->fbody != 0)
{
@@ -492,18 +475,6 @@ void DtoDefineFunc(FuncDeclaration* fd)
assert(fd->llvmIRFunc);
gIR->functions.push_back(fd->llvmIRFunc);
/* // moved to declaration
// this handling
if (f->llvmUsesThis) {
Logger::println("uses this");
if (f->llvmRetInPtr)
fd->llvmThisVar = ++func->arg_begin();
else
fd->llvmThisVar = func->arg_begin();
assert(fd->llvmThisVar != 0);
}
*/
if (fd->isMain())
gIR->emitMain = true;
@@ -681,7 +652,7 @@ void DtoMain()
llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func);
// call static ctors
llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_ctors");
llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleCtor");
llvm::Instruction* apt = new llvm::CallInst(fn,"",bb);
// call user main function
@@ -720,7 +691,7 @@ void DtoMain()
call->setCallingConv(ir.mainFunc->getCallingConv());
// call static dtors
fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors");
fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleDtor");
new llvm::CallInst(fn,"",bb);
// return
@@ -728,3 +699,31 @@ void DtoMain()
}
//////////////////////////////////////////////////////////////////////////////////////////
const llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl)
{
Dsymbol* parent = fdecl->toParent();
ClassDeclaration* cd = parent->isClassDeclaration();
assert(cd);
FuncDeclaration* f = fdecl;
while (cd)
{
ClassDeclaration* base = cd->baseClass;
if (!base)
break;
FuncDeclaration* f2 = base->findFunc(fdecl->ident, (TypeFunction*)fdecl->type);
if (f2) {
f = f2;
cd = base;
}
else
break;
}
DtoResolveDsymbol(f);
return llvm::cast<llvm::FunctionType>(DtoType(f->type));
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -4,6 +4,8 @@
const llvm::FunctionType* DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false);
const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl);
const llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl);
void DtoResolveFunction(FuncDeclaration* fdecl);
void DtoDeclareFunction(FuncDeclaration* fdecl);
void DtoDefineFunc(FuncDeclaration* fd);

View File

@@ -123,6 +123,7 @@ Module::genobjfile()
if (!global.params.novalidate) {
std::string verifyErr;
Logger::println("Verifying module...");
LOG_SCOPE;
if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr))
{
error("%s", verifyErr.c_str());
@@ -364,6 +365,14 @@ void Module::genmoduleinfo()
// 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);
// declare the appending array
const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(llvm::PointerType::get(llvm::Type::Int8Ty), 1);
std::vector<llvm::Constant*> appendInits;
appendInits.push_back(llvm::ConstantExpr::getBitCast(gvar, llvm::PointerType::get(llvm::Type::Int8Ty)));
llvm::Constant* appendInit = llvm::ConstantArray::get(appendArrTy, appendInits);
std::string appendName("_d_moduleinfo_array");
llvm::GlobalVariable* appendVar = new llvm::GlobalVariable(appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName, gIR->module);
}
/* ================================================================== */

View File

@@ -151,7 +151,6 @@ lphobos/internal/arrays.d
lphobos/internal/cast.d
lphobos/internal/contract.d
lphobos/internal/mem.d
lphobos/internal/moduleinit.d
lphobos/internal/objectimpl.d
lphobos/internal/qsort2.d
lphobos/llvm
@@ -391,6 +390,7 @@ test/intrinsics.d
test/mainargs1.d
test/memory1.d
test/moduleinfo1.d
test/moduleinfo2.d
test/multiarr1.d
test/multiarr2.d
test/multiarr3.d

View File

@@ -11,14 +11,12 @@ llvmdc internal/contract.d -c -of../lib/llvmdcore.bc -noruntime || exit 1
echo "compiling common runtime"
rebuild internal/arrays.d \
internal/mem.d \
internal/moduleinit.d \
-c -oqobj -dc=llvmdc-posix || exit 1
echo "compiling module init backend"
llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/internal.*.bc` ../lib/llvmdcore.bc obj/moduleinit_backend.bc || exit 1
echo "compiling typeinfo 1"
rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix || exit 1
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo1.*.bc` ../lib/llvmdcore.bc || exit 1

View File

@@ -1,24 +0,0 @@
module internal.moduleinit;
private alias extern(C) void function() fptr_t;
extern(C):
fptr_t* _d_get_module_ctors();
fptr_t* _d_get_module_dtors();
void _d_run_module_ctors()
{
auto p = _d_get_module_ctors();
while(*p) {
(*p++)();
}
}
void _d_run_module_dtors()
{
auto p = _d_get_module_dtors();
while(*p) {
(*p++)();
}
}

View File

@@ -1,15 +1,9 @@
; ModuleID = 'internal.moduleinit_backend'
@_d_module_ctor_array = appending global [1 x void ()*] zeroinitializer
@_d_module_dtor_array = appending global [1 x void ()*] zeroinitializer
define void ()** @_d_get_module_ctors() {
entry:
%tmp = getelementptr [1 x void ()*]* @_d_module_ctor_array, i32 0, i32 0
ret void ()** %tmp
}
@_d_moduleinfo_array = appending constant [1 x i8*] [ i8* null ]
define void ()** @_d_get_module_dtors() {
define i8** @_d_get_moduleinfo_array() {
entry:
%tmp = getelementptr [1 x void ()*]* @_d_module_dtor_array, i32 0, i32 0
ret void ()** %tmp
%tmp = getelementptr [1 x i8*]* @_d_moduleinfo_array, i32 0, i32 0
ret i8** %tmp
}

View File

@@ -30,22 +30,11 @@ class ModuleCtorError : Exception
}
// Win32: this gets initialized by minit.asm
// linux: this gets initialized in _moduleCtor()
// 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
}
// this method returns the linker constructed, null terminated, array of moduleinfos
extern (C) void** _d_get_moduleinfo_array();
ModuleInfo[] _moduleinfo_dtors;
uint _moduleinfo_dtors_i;
@@ -60,20 +49,20 @@ extern (C) int _fatexit(void *);
extern (C) void _moduleCtor()
{
debug printf("_moduleCtor()\n");
version (linux)
{
int len = 0;
ModuleReference *mr;
for (mr = _Dmodule_ref; mr; mr = mr.next)
ModuleInfo* mrbegin = cast(ModuleInfo*)_d_get_moduleinfo_array();
assert(mrbegin !is null);
ModuleInfo* mr;
for (mr = mrbegin; *mr !is null; ++mr)
len++;
_moduleinfo_array = new ModuleInfo[len];
len = 0;
for (mr = _Dmodule_ref; mr; mr = mr.next)
{ _moduleinfo_array[len] = mr.mod;
for (mr = mrbegin; *mr !is null; ++mr)
{ _moduleinfo_array[len] = *mr;
len++;
}
}
version (Win32)
{
@@ -81,7 +70,7 @@ extern (C) void _moduleCtor()
//_fatexit(&_STD_moduleDtor);
}
_moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
_moduleinfo_dtors = new ModuleInfo[len];
debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
_moduleCtor2(_moduleinfo_array, 0);

17
test/classes10.d Normal file
View File

@@ -0,0 +1,17 @@
module classes10;
class C
{
int i;
override char[] toString()
{
return "foobar";
}
}
void main()
{
Object o = new C;
char[] s = o.toString();
assert(s == "foobar");
}

12
test/moduleinfo2.d Normal file
View File

@@ -0,0 +1,12 @@
module moduleinfo2;
import std.stdio;
void main()
{
ModuleInfo[] mi = ModuleInfo.modules();
writefln("listing ",mi.length," modules");
foreach(m; mi)
{
writefln(" ",m.name);
}
assert(mi.length > 50);
}