Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2089968

Browse files
committedOct 13, 2013
Use Module::members -> Dsymbol::codegen to define symbols.
This commit fundamentally changes the way symbol emission in LDC works: Previously, whenever a declaration was used in some way, the compiler would check whether it actually needs to be defined in the currently processed module, based only on the symbol itself. This lack of contextual information proved to be a major problem in correctly handling emission of templates (see e.g. ldc-developers#454). Now, the DtoResolve…() family of functions and similar only ever declare the symbols, and definition is handled by doing a single pass over Module::members for the root module. This is the same strategy that DMD uses as well, which should also reduce the maintainance burden down the road (which is important as during the last few releases, there was pretty much always a symbol emission related problem slowing us down). Our old approach might have been a bit better tuned w.r.t. avoiding emission of unneeded template instances, but 2.064 will bring improvements here (DMD: FuncDeclaration::toObjFile). Barring such issues, the change shoud also marginally improve compile times because of declarations no longer being emitted when they are not needed. In the future, we should also consider refactoring the code so that it no longer directly accesses Dsymbol::ir but uses wrapper functions that ensure that the appropriate DtoResolve…() function has been called. GitHub: Fixes ldc-developers#454.
1 parent b556ad9 commit 2089968

21 files changed

+378
-498
lines changed
 

‎dmd2/declaration.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,6 @@ struct TypeInfoClassDeclaration : TypeInfoDeclaration
478478
#endif
479479

480480
#if IN_LLVM
481-
void codegen(Ir*);
482481
void llvmDefine();
483482
#endif
484483
};
@@ -814,7 +813,9 @@ struct FuncDeclaration : Declaration
814813
// functions
815814
FuncDeclarations siblingCallers; // Sibling nested functions which
816815
// called this one
816+
#if IN_DMD
817817
FuncDeclarations deferred; // toObjFile() these functions after this one
818+
#endif
818819

819820
unsigned flags;
820821
#define FUNCFLAGpurityInprocess 1 // working on determining purity

‎dmd2/func.c

-4
Original file line numberDiff line numberDiff line change
@@ -4735,11 +4735,7 @@ void UnitTestDeclaration::semantic(Scope *sc)
47354735
{ sc = scope;
47364736
scope = NULL;
47374737
}
4738-
#if IN_LLVM
4739-
if (global.params.useUnitTests && sc->module->isRoot)
4740-
#else
47414738
if (global.params.useUnitTests)
4742-
#endif
47434739
{
47444740
if (!type)
47454741
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);

‎gen/arrays.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -867,14 +867,6 @@ static LLValue* DtoArrayEqCmp_impl(Loc& loc, const char* func, DValue* l, DValue
867867
if (useti) {
868868
Type* t = l->getType();
869869
LLValue* tival = DtoTypeInfoOf(t);
870-
// DtoTypeInfoOf only does declare, not enough in this case :/
871-
t->vtinfo->codegen(Type::sir);
872-
873-
#if 0
874-
if (Logger::enabled())
875-
Logger::cout() << "typeinfo decl: " << *tival << '\n';
876-
#endif
877-
878870
args.push_back(DtoBitCast(tival, fn->getFunctionType()->getParamType(2)));
879871
}
880872

‎gen/classes.cpp

+18-63
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,21 @@
3535

3636
void DtoResolveClass(ClassDeclaration* cd)
3737
{
38+
if (cd->ir.resolved) return;
39+
cd->ir.resolved = true;
40+
41+
Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
42+
LOG_SCOPE;
43+
3844
// make sure the base classes are processed first
3945
ArrayIter<BaseClass> base_iter(cd->baseclasses);
4046
while (base_iter.more())
4147
{
4248
BaseClass* bc = base_iter.get();
43-
if (bc)
44-
{
45-
bc->base->codegen(Type::sir);
46-
}
49+
DtoResolveClass(bc->base);
4750
base_iter.next();
4851
}
4952

50-
if (cd->ir.resolved) return;
51-
cd->ir.resolved = true;
52-
53-
Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
54-
LOG_SCOPE;
55-
5653
// make sure type exists
5754
DtoType(cd->type);
5855

@@ -73,11 +70,6 @@ void DtoResolveClass(ClassDeclaration* cd)
7370
}
7471
}
7572

76-
bool needs_def = mustDefineSymbol(cd);
77-
78-
// emit the ClassZ symbol
79-
LLGlobalVariable* ClassZ = irAggr->getClassInfoSymbol();
80-
8173
// emit the interfaceInfosZ symbol if necessary
8274
if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0)
8375
irAggr->getInterfaceArraySymbol(); // initializer is applied when it's built
@@ -87,51 +79,14 @@ void DtoResolveClass(ClassDeclaration* cd)
8779
{
8880
irAggr->initializeInterface();
8981
}
90-
else
91-
{
92-
// emit the initZ symbol
93-
LLGlobalVariable* initZ = irAggr->getInitSymbol();
94-
// emit the vtblZ symbol
95-
LLGlobalVariable* vtblZ = irAggr->getVtblSymbol();
96-
97-
// perform definition
98-
if (needs_def)
99-
{
100-
// set symbol initializers
101-
initZ->setInitializer(irAggr->getDefaultInit());
102-
vtblZ->setInitializer(irAggr->getVtblInit());
103-
}
104-
}
105-
106-
// emit members
107-
if (cd->members)
108-
{
109-
ArrayIter<Dsymbol> it(*cd->members);
110-
while (!it.done())
111-
{
112-
Dsymbol* member = it.get();
113-
if (member)
114-
member->codegen(Type::sir);
115-
it.next();
116-
}
117-
}
118-
119-
if (needs_def)
120-
{
121-
// emit typeinfo
122-
DtoTypeInfoOf(cd->type);
123-
124-
// define classinfo
125-
ClassZ->setInitializer(irAggr->getClassInfoInit());
126-
}
12782
}
12883

12984
//////////////////////////////////////////////////////////////////////////////////////////
13085

13186
DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
13287
{
13388
// resolve type
134-
tc->sym->codegen(Type::sir);
89+
DtoResolveClass(tc->sym);
13590

13691
// allocate
13792
LLValue* mem;
@@ -143,7 +98,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
14398
// custom allocator
14499
else if (newexp->allocator)
145100
{
146-
newexp->allocator->codegen(Type::sir);
101+
DtoResolveDsymbol(newexp->allocator);
147102
DFuncValue dfn(newexp->allocator, newexp->allocator->ir.irFunc->func);
148103
DValue* res = DtoCallFunction(newexp->loc, NULL, &dfn, newexp->newargs);
149104
mem = DtoBitCast(res->getRVal(), DtoType(tc), ".newclass_custom");
@@ -184,7 +139,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
184139
{
185140
Logger::println("Calling constructor");
186141
assert(newexp->arguments != NULL);
187-
newexp->member->codegen(Type::sir);
142+
DtoResolveDsymbol(newexp->member);
188143
DFuncValue dfn(newexp->member, newexp->member->ir.irFunc->func, mem);
189144
return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments);
190145
}
@@ -197,7 +152,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
197152

198153
void DtoInitClass(TypeClass* tc, LLValue* dst)
199154
{
200-
tc->sym->codegen(Type::sir);
155+
DtoResolveClass(tc->sym);
201156

202157
uint64_t n = tc->sym->structsize - Target::ptrsize * 2;
203158

@@ -365,8 +320,8 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to)
365320
// call:
366321
// Object _d_dynamic_cast(Object o, ClassInfo c)
367322

368-
ClassDeclaration::object->codegen(Type::sir);
369-
ClassDeclaration::classinfo->codegen(Type::sir);
323+
DtoResolveClass(ClassDeclaration::object);
324+
DtoResolveClass(ClassDeclaration::classinfo);
370325

371326
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
372327
LLFunctionType* funcTy = func->getFunctionType();
@@ -378,7 +333,7 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to)
378333

379334
// ClassInfo c
380335
TypeClass* to = static_cast<TypeClass*>(_to->toBasetype());
381-
to->sym->codegen(Type::sir);
336+
DtoResolveClass(to->sym);
382337

383338
LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol();
384339
// unfortunately this is needed as the implementation of object differs somehow from the declaration
@@ -428,8 +383,8 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
428383
// call:
429384
// Object _d_interface_cast(void* p, ClassInfo c)
430385

431-
ClassDeclaration::object->codegen(Type::sir);
432-
ClassDeclaration::classinfo->codegen(Type::sir);
386+
DtoResolveClass(ClassDeclaration::object);
387+
DtoResolveClass(ClassDeclaration::classinfo);
433388

434389
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast");
435390
LLFunctionType* funcTy = func->getFunctionType();
@@ -440,7 +395,7 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
440395

441396
// ClassInfo c
442397
TypeClass* to = static_cast<TypeClass*>(_to->toBasetype());
443-
to->sym->codegen(Type::sir);
398+
DtoResolveClass(to->sym);
444399
LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol();
445400
// unfortunately this is needed as the implementation of object differs somehow from the declaration
446401
// this could happen in user code as well :/
@@ -623,7 +578,7 @@ static LLConstant* build_class_dtor(ClassDeclaration* cd)
623578
if (!dtor)
624579
return getNullPtr(getVoidPtrType());
625580

626-
dtor->codegen(Type::sir);
581+
DtoResolveDsymbol(dtor);
627582
return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::getInt8Ty(gIR->context())));
628583
}
629584

0 commit comments

Comments
 (0)
Please sign in to comment.