mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 02:43:14 +01:00
1409 lines
38 KiB
C
1409 lines
38 KiB
C
|
|
// Copyright (c) 1999-2012 by Digital Mars
|
|
// All Rights Reserved
|
|
// written by Walter Bright
|
|
// http://www.digitalmars.com
|
|
// License for redistribution is by either the Artistic License
|
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
|
// See the included readme.txt for details.
|
|
|
|
#include <stdio.h>
|
|
#include <stddef.h>
|
|
#include <time.h>
|
|
#include <assert.h>
|
|
|
|
#include "mars.h"
|
|
#include "module.h"
|
|
#include "mtype.h"
|
|
#include "declaration.h"
|
|
#include "statement.h"
|
|
#include "enum.h"
|
|
#include "aggregate.h"
|
|
#include "init.h"
|
|
#include "attrib.h"
|
|
#include "id.h"
|
|
#include "import.h"
|
|
#include "template.h"
|
|
|
|
#include "rmem.h"
|
|
#include "cc.h"
|
|
#include "global.h"
|
|
#include "oper.h"
|
|
#include "code.h"
|
|
#include "type.h"
|
|
#include "dt.h"
|
|
#include "cgcv.h"
|
|
#include "outbuf.h"
|
|
#include "irstate.h"
|
|
|
|
void obj_lzext(Symbol *s1,Symbol *s2);
|
|
|
|
/* ================================================================== */
|
|
|
|
// Put out instance of ModuleInfo for this Module
|
|
|
|
void Module::genmoduleinfo()
|
|
{
|
|
//printf("Module::genmoduleinfo() %s\n", toChars());
|
|
|
|
Symbol *msym = toSymbol();
|
|
#if DMDV2
|
|
unsigned sizeof_ModuleInfo = 16 * PTRSIZE;
|
|
#else
|
|
unsigned sizeof_ModuleInfo = 14 * PTRSIZE;
|
|
#endif
|
|
#if !MODULEINFO_IS_STRUCT
|
|
sizeof_ModuleInfo -= 2 * PTRSIZE;
|
|
#endif
|
|
//printf("moduleinfo size = x%x\n", sizeof_ModuleInfo);
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
csym->Sclass = SCglobal;
|
|
csym->Sfl = FLdata;
|
|
|
|
#if 1
|
|
dt_t *dt = NULL;
|
|
ClassDeclarations aclasses;
|
|
|
|
//printf("members->dim = %d\n", members->dim);
|
|
for (size_t i = 0; i < members->dim; i++)
|
|
{ Dsymbol *member = members->tdata()[i];
|
|
|
|
//printf("\tmember '%s'\n", member->toChars());
|
|
member->addLocalClass(&aclasses);
|
|
}
|
|
|
|
// importedModules[]
|
|
size_t aimports_dim = aimports.dim;
|
|
for (size_t i = 0; i < aimports.dim; i++)
|
|
{ Module *m = aimports.tdata()[i];
|
|
if (!m->needmoduleinfo)
|
|
aimports_dim--;
|
|
}
|
|
|
|
FuncDeclaration *sgetmembers = findGetMembers();
|
|
|
|
// These must match the values in druntime/src/object_.d
|
|
#define MIstandalone 4
|
|
#define MItlsctor 8
|
|
#define MItlsdtor 0x10
|
|
#define MIctor 0x20
|
|
#define MIdtor 0x40
|
|
#define MIxgetMembers 0x80
|
|
#define MIictor 0x100
|
|
#define MIunitTest 0x200
|
|
#define MIimportedModules 0x400
|
|
#define MIlocalClasses 0x800
|
|
#define MInew 0x80000000 // it's the "new" layout
|
|
|
|
unsigned flags = MInew;
|
|
if (sctor)
|
|
flags |= MItlsctor;
|
|
if (sdtor)
|
|
flags |= MItlsdtor;
|
|
if (ssharedctor)
|
|
flags |= MIctor;
|
|
if (sshareddtor)
|
|
flags |= MIdtor;
|
|
if (sgetmembers)
|
|
flags |= MIxgetMembers;
|
|
if (sictor)
|
|
flags |= MIictor;
|
|
if (stest)
|
|
flags |= MIunitTest;
|
|
if (aimports_dim)
|
|
flags |= MIimportedModules;
|
|
if (aclasses.dim)
|
|
flags |= MIlocalClasses;
|
|
|
|
if (!needmoduleinfo)
|
|
flags |= MIstandalone;
|
|
|
|
dtdword(&dt, flags); // n.flags
|
|
dtdword(&dt, 0); // n.index
|
|
|
|
if (flags & MItlsctor)
|
|
dtxoff(&dt, sctor, 0, TYnptr);
|
|
if (flags & MItlsdtor)
|
|
dtxoff(&dt, sdtor, 0, TYnptr);
|
|
if (flags & MIctor)
|
|
dtxoff(&dt, ssharedctor, 0, TYnptr);
|
|
if (flags & MIdtor)
|
|
dtxoff(&dt, sshareddtor, 0, TYnptr);
|
|
if (flags & MIxgetMembers)
|
|
dtxoff(&dt, sgetmembers->toSymbol(), 0, TYnptr);
|
|
if (flags & MIictor)
|
|
dtxoff(&dt, sictor, 0, TYnptr);
|
|
if (flags & MIunitTest)
|
|
dtxoff(&dt, stest, 0, TYnptr);
|
|
if (flags & MIimportedModules)
|
|
{
|
|
dtsize_t(&dt, aimports_dim);
|
|
for (size_t i = 0; i < aimports.dim; i++)
|
|
{ Module *m = aimports[i];
|
|
|
|
if (m->needmoduleinfo)
|
|
{ Symbol *s = m->toSymbol();
|
|
|
|
/* Weak references don't pull objects in from the library,
|
|
* they resolve to 0 if not pulled in by something else.
|
|
* Don't pull in a module just because it was imported.
|
|
*/
|
|
#if !OMFOBJ // Optlink crashes with weak symbols at EIP 41AFE7, 402000
|
|
s->Sflags |= SFLweak;
|
|
#endif
|
|
dtxoff(&dt, s, 0, TYnptr);
|
|
}
|
|
}
|
|
}
|
|
if (flags & MIlocalClasses)
|
|
{
|
|
dtsize_t(&dt, aclasses.dim);
|
|
for (size_t i = 0; i < aclasses.dim; i++)
|
|
{
|
|
ClassDeclaration *cd = aclasses.tdata()[i];
|
|
dtxoff(&dt, cd->toSymbol(), 0, TYnptr);
|
|
}
|
|
}
|
|
|
|
// Put out module name as a 0-terminated string, to save bytes
|
|
nameoffset = dt_size(dt);
|
|
const char *name = toPrettyChars();
|
|
namelen = strlen(name);
|
|
dtnbytes(&dt, namelen + 1, name);
|
|
//printf("nameoffset = x%x\n", nameoffset);
|
|
#else
|
|
/* 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;
|
|
const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function
|
|
void *ictor;
|
|
void *sharedctor;
|
|
void *shareddtor;
|
|
uint index;
|
|
void*[1] reserved;
|
|
}
|
|
*/
|
|
dt_t *dt = NULL;
|
|
|
|
#if !MODULEINFO_IS_STRUCT
|
|
if (moduleinfo)
|
|
dtxoff(&dt, moduleinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ModuleInfo
|
|
else
|
|
{ //printf("moduleinfo is null\n");
|
|
dtdword(&dt, 0); // BUG: should be an assert()
|
|
}
|
|
dtdword(&dt, 0); // monitor
|
|
#endif
|
|
|
|
// name[]
|
|
const char *name = toPrettyChars();
|
|
size_t namelen = strlen(name);
|
|
dtdword(&dt, namelen);
|
|
dtabytes(&dt, TYnptr, 0, namelen + 1, name);
|
|
|
|
ClassDeclarations aclasses;
|
|
|
|
//printf("members->dim = %d\n", members->dim);
|
|
for (size_t i = 0; i < members->dim; i++)
|
|
{ Dsymbol *member = members->tdata()[i];
|
|
|
|
//printf("\tmember '%s'\n", member->toChars());
|
|
member->addLocalClass(&aclasses);
|
|
}
|
|
|
|
// importedModules[]
|
|
int aimports_dim = aimports.dim;
|
|
for (size_t i = 0; i < aimports.dim; i++)
|
|
{ Module *m = aimports.tdata()[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, 8); // flags
|
|
else
|
|
dtdword(&dt, 8 | MIstandalone); // flags
|
|
|
|
if (ssharedctor)
|
|
dtxoff(&dt, ssharedctor, 0, TYnptr);
|
|
else
|
|
dtdword(&dt, 0);
|
|
|
|
if (sshareddtor)
|
|
dtxoff(&dt, sshareddtor, 0, TYnptr);
|
|
else
|
|
dtdword(&dt, 0);
|
|
|
|
if (stest)
|
|
dtxoff(&dt, stest, 0, TYnptr);
|
|
else
|
|
dtdword(&dt, 0);
|
|
|
|
#if DMDV2
|
|
FuncDeclaration *sgetmembers = findGetMembers();
|
|
if (sgetmembers)
|
|
dtxoff(&dt, sgetmembers->toSymbol(), 0, TYnptr);
|
|
else
|
|
#endif
|
|
dtdword(&dt, 0); // xgetMembers
|
|
|
|
if (sictor)
|
|
dtxoff(&dt, sictor, 0, TYnptr);
|
|
else
|
|
dtdword(&dt, 0);
|
|
|
|
#if DMDV2
|
|
if (sctor)
|
|
dtxoff(&dt, sctor, 0, TYnptr);
|
|
else
|
|
dtdword(&dt, 0);
|
|
|
|
if (sdtor)
|
|
dtxoff(&dt, sdtor, 0, TYnptr);
|
|
else
|
|
dtdword(&dt, 0);
|
|
|
|
dtdword(&dt, 0); // index
|
|
|
|
// void*[1] reserved;
|
|
dtdword(&dt, 0);
|
|
#endif
|
|
//////////////////////////////////////////////
|
|
|
|
for (size_t i = 0; i < aimports.dim; i++)
|
|
{ Module *m = aimports.tdata()[i];
|
|
|
|
if (m->needModuleInfo())
|
|
{ Symbol *s = m->toSymbol();
|
|
|
|
/* Weak references don't pull objects in from the library,
|
|
* they resolve to 0 if not pulled in by something else.
|
|
* Don't pull in a module just because it was imported.
|
|
*/
|
|
#if !OMFOBJ // Optlink crashes with weak symbols at EIP 41AFE7, 402000
|
|
s->Sflags |= SFLweak;
|
|
#endif
|
|
dtxoff(&dt, s, 0, TYnptr);
|
|
}
|
|
}
|
|
|
|
for (size_t i = 0; i < aclasses.dim; i++)
|
|
{
|
|
ClassDeclaration *cd = aclasses.data()[i];
|
|
dtxoff(&dt, cd->toSymbol(), 0, TYnptr);
|
|
}
|
|
#endif
|
|
|
|
csym->Sdt = dt;
|
|
#if ELFOBJ || MACHOBJ
|
|
// Cannot be CONST because the startup code sets flag bits in it
|
|
csym->Sseg = DATA;
|
|
#endif
|
|
outdata(csym);
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
obj_moduleinfo(msym);
|
|
}
|
|
|
|
/* ================================================================== */
|
|
|
|
void Dsymbol::toObjFile(int multiobj)
|
|
{
|
|
//printf("Dsymbol::toObjFile('%s')\n", toChars());
|
|
// ignore
|
|
}
|
|
|
|
/* ================================================================== */
|
|
|
|
void ClassDeclaration::toObjFile(int multiobj)
|
|
{
|
|
unsigned offset;
|
|
Symbol *sinit;
|
|
enum_SC scclass;
|
|
|
|
//printf("ClassDeclaration::toObjFile('%s')\n", toChars());
|
|
|
|
if (type->ty == Terror)
|
|
{ error("had semantic errors when compiling");
|
|
return;
|
|
}
|
|
|
|
if (!members)
|
|
return;
|
|
|
|
if (multiobj && !hasStaticCtorOrDtor())
|
|
{ obj_append(this);
|
|
return;
|
|
}
|
|
|
|
if (global.params.symdebug)
|
|
toDebug();
|
|
|
|
assert(!scope); // semantic() should have been run to completion
|
|
|
|
scclass = SCglobal;
|
|
if (inTemplateInstance())
|
|
scclass = SCcomdat;
|
|
|
|
// Put out the members
|
|
for (size_t i = 0; i < members->dim; i++)
|
|
{
|
|
Dsymbol *member = (*members)[i];
|
|
/* There might be static ctors in the members, and they cannot
|
|
* be put in separate obj files.
|
|
*/
|
|
member->toObjFile(multiobj);
|
|
}
|
|
|
|
#if 0
|
|
// Build destructor by aggregating dtors[]
|
|
Symbol *sdtor;
|
|
switch (dtors.dim)
|
|
{ case 0:
|
|
// No destructors for this class
|
|
sdtor = NULL;
|
|
break;
|
|
|
|
case 1:
|
|
// One destructor, just use it directly
|
|
sdtor = dtors[0]->toSymbol();
|
|
break;
|
|
|
|
default:
|
|
{ /* Build a destructor that calls all the
|
|
* other destructors in dtors[].
|
|
*/
|
|
|
|
elem *edtor = NULL;
|
|
|
|
// Declare 'this' pointer for our new destructor
|
|
Symbol *sthis = symbol_calloc("this");
|
|
sthis->Stype = type_fake(TYnptr);
|
|
sthis->Stype->Tcount++;
|
|
sthis->Sclass = SCfastpar;
|
|
sthis->Spreg = AX;
|
|
sthis->Sfl = FLauto;
|
|
|
|
// Call each of the destructors in dtors[]
|
|
// in reverse order
|
|
for (size_t i = 0; i < dtors.dim; i++)
|
|
{ DtorDeclaration *d = dtors[i];
|
|
Symbol *s = d->toSymbol();
|
|
elem *e = el_bin(OPcall, TYvoid, el_var(s), el_var(sthis));
|
|
edtor = el_combine(e, edtor);
|
|
}
|
|
|
|
// Create type for the function
|
|
::type *t = type_alloc(TYjfunc);
|
|
t->Tflags |= TFprototype | TFfixed;
|
|
t->Tmangle = mTYman_d;
|
|
t->Tnext = tsvoid;
|
|
tsvoid->Tcount++;
|
|
|
|
// Create the function, sdtor, and write it out
|
|
localgot = NULL;
|
|
sdtor = toSymbolX("__dtor", SCglobal, t, "FZv");
|
|
block *b = block_calloc();
|
|
b->BC = BCret;
|
|
b->Belem = edtor;
|
|
sdtor->Sfunc->Fstartblock = b;
|
|
cstate.CSpsymtab = &sdtor->Sfunc->Flocsym;
|
|
symbol_add(sthis);
|
|
writefunc(sdtor);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Generate C symbols
|
|
toSymbol();
|
|
toVtblSymbol();
|
|
sinit = toInitializer();
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Generate static initializer
|
|
sinit->Sclass = scclass;
|
|
sinit->Sfl = FLdata;
|
|
#if ELFOBJ // Burton
|
|
sinit->Sseg = CDATA;
|
|
#endif
|
|
#if MACHOBJ
|
|
sinit->Sseg = DATA;
|
|
#endif
|
|
toDt(&sinit->Sdt);
|
|
outdata(sinit);
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Put out the TypeInfo
|
|
type->getTypeInfo(NULL);
|
|
//type->vtinfo->toObjFile(multiobj);
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Put out the ClassInfo
|
|
csym->Sclass = scclass;
|
|
csym->Sfl = FLdata;
|
|
|
|
/* 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;
|
|
const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function
|
|
//TypeInfo typeinfo;
|
|
}
|
|
*/
|
|
dt_t *dt = NULL;
|
|
unsigned classinfo_size = global.params.is64bit ? CLASSINFO_SIZE_64 : CLASSINFO_SIZE; // must be ClassInfo.size
|
|
offset = classinfo_size;
|
|
if (classinfo)
|
|
{
|
|
if (classinfo->structsize != classinfo_size)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("CLASSINFO_SIZE = x%x, classinfo->structsize = x%x\n", offset, classinfo->structsize);
|
|
#endif
|
|
error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch.");
|
|
fatal();
|
|
}
|
|
}
|
|
|
|
if (classinfo)
|
|
dtxoff(&dt, classinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo
|
|
else
|
|
dtsize_t(&dt, 0); // BUG: should be an assert()
|
|
dtsize_t(&dt, 0); // monitor
|
|
|
|
// initializer[]
|
|
assert(structsize >= 8);
|
|
dtsize_t(&dt, structsize); // size
|
|
dtxoff(&dt, sinit, 0, TYnptr); // initializer
|
|
|
|
// name[]
|
|
const char *name = ident->toChars();
|
|
size_t namelen = strlen(name);
|
|
if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
|
|
{ name = toPrettyChars();
|
|
namelen = strlen(name);
|
|
}
|
|
dtsize_t(&dt, namelen);
|
|
dtabytes(&dt, TYnptr, 0, namelen + 1, name);
|
|
|
|
// vtbl[]
|
|
dtsize_t(&dt, vtbl.dim);
|
|
dtxoff(&dt, vtblsym, 0, TYnptr);
|
|
|
|
// interfaces[]
|
|
dtsize_t(&dt, vtblInterfaces->dim);
|
|
if (vtblInterfaces->dim)
|
|
dtxoff(&dt, csym, offset, TYnptr); // (*)
|
|
else
|
|
dtsize_t(&dt, 0);
|
|
|
|
// base
|
|
if (baseClass)
|
|
dtxoff(&dt, baseClass->toSymbol(), 0, TYnptr);
|
|
else
|
|
dtsize_t(&dt, 0);
|
|
|
|
// destructor
|
|
if (dtor)
|
|
dtxoff(&dt, dtor->toSymbol(), 0, TYnptr);
|
|
else
|
|
dtsize_t(&dt, 0);
|
|
|
|
// invariant
|
|
if (inv)
|
|
dtxoff(&dt, inv->toSymbol(), 0, TYnptr);
|
|
else
|
|
dtsize_t(&dt, 0);
|
|
|
|
// flags
|
|
int flags = 4 | isCOMclass();
|
|
#if DMDV2
|
|
flags |= 16;
|
|
#endif
|
|
flags |= 32;
|
|
if (ctor)
|
|
flags |= 8;
|
|
if (isabstract)
|
|
flags |= 64;
|
|
for (ClassDeclaration *cd = this; cd; cd = cd->baseClass)
|
|
{
|
|
if (cd->members)
|
|
{
|
|
for (size_t i = 0; i < cd->members->dim; i++)
|
|
{
|
|
Dsymbol *sm = cd->members->tdata()[i];
|
|
//printf("sm = %s %s\n", sm->kind(), sm->toChars());
|
|
if (sm->hasPointers())
|
|
goto L2;
|
|
}
|
|
}
|
|
}
|
|
flags |= 2; // no pointers
|
|
L2:
|
|
dtsize_t(&dt, flags);
|
|
|
|
|
|
// deallocator
|
|
if (aggDelete)
|
|
dtxoff(&dt, aggDelete->toSymbol(), 0, TYnptr);
|
|
else
|
|
dtsize_t(&dt, 0);
|
|
|
|
// offTi[]
|
|
dtsize_t(&dt, 0);
|
|
dtsize_t(&dt, 0); // null for now, fix later
|
|
|
|
// defaultConstructor
|
|
if (defaultCtor)
|
|
dtxoff(&dt, defaultCtor->toSymbol(), 0, TYnptr);
|
|
else
|
|
dtsize_t(&dt, 0);
|
|
|
|
#if DMDV2
|
|
FuncDeclaration *sgetmembers = findGetMembers();
|
|
if (sgetmembers)
|
|
dtxoff(&dt, sgetmembers->toSymbol(), 0, TYnptr);
|
|
else
|
|
dtsize_t(&dt, 0); // module getMembers() function
|
|
#endif
|
|
|
|
//dtxoff(&dt, type->vtinfo->toSymbol(), 0, TYnptr); // typeinfo
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Put out vtblInterfaces->tdata()[]. Must immediately follow csym, because
|
|
// of the fixup (*)
|
|
|
|
offset += vtblInterfaces->dim * (4 * PTRSIZE);
|
|
for (size_t i = 0; i < vtblInterfaces->dim; i++)
|
|
{ BaseClass *b = vtblInterfaces->tdata()[i];
|
|
ClassDeclaration *id = b->base;
|
|
|
|
/* The layout is:
|
|
* struct Interface
|
|
* {
|
|
* ClassInfo *interface;
|
|
* void *[] vtbl;
|
|
* ptrdiff_t offset;
|
|
* }
|
|
*/
|
|
|
|
// Fill in vtbl[]
|
|
b->fillVtbl(this, &b->vtbl, 1);
|
|
|
|
dtxoff(&dt, id->toSymbol(), 0, TYnptr); // ClassInfo
|
|
|
|
// vtbl[]
|
|
dtsize_t(&dt, id->vtbl.dim);
|
|
dtxoff(&dt, csym, offset, TYnptr);
|
|
|
|
dtsize_t(&dt, b->offset); // this offset
|
|
|
|
offset += id->vtbl.dim * PTRSIZE;
|
|
}
|
|
|
|
// Put out the vtblInterfaces->tdata()[].vtbl[]
|
|
// This must be mirrored with ClassDeclaration::baseVtblOffset()
|
|
//printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces->dim, toChars());
|
|
for (size_t i = 0; i < vtblInterfaces->dim; i++)
|
|
{ BaseClass *b = vtblInterfaces->tdata()[i];
|
|
ClassDeclaration *id = b->base;
|
|
|
|
//printf(" interface[%d] is '%s'\n", i, id->toChars());
|
|
size_t j = 0;
|
|
if (id->vtblOffset())
|
|
{
|
|
// First entry is ClassInfo reference
|
|
//dtxoff(&dt, id->toSymbol(), 0, TYnptr);
|
|
|
|
// First entry is struct Interface reference
|
|
dtxoff(&dt, csym, classinfo_size + i * (4 * PTRSIZE), TYnptr);
|
|
j = 1;
|
|
}
|
|
assert(id->vtbl.dim == b->vtbl.dim);
|
|
for (; j < id->vtbl.dim; j++)
|
|
{
|
|
assert(j < b->vtbl.dim);
|
|
#if 0
|
|
Object *o = b->vtbl.tdata()[j];
|
|
if (o)
|
|
{
|
|
printf("o = %p\n", o);
|
|
assert(o->dyncast() == DYNCAST_DSYMBOL);
|
|
Dsymbol *s = (Dsymbol *)o;
|
|
printf("s->kind() = '%s'\n", s->kind());
|
|
}
|
|
#endif
|
|
FuncDeclaration *fd = b->vtbl.tdata()[j];
|
|
if (fd)
|
|
dtxoff(&dt, fd->toThunkSymbol(b->offset), 0, TYnptr);
|
|
else
|
|
dtsize_t(&dt, 0);
|
|
}
|
|
}
|
|
|
|
#if 1
|
|
// Put out the overriding interface vtbl[]s.
|
|
// This must be mirrored with ClassDeclaration::baseVtblOffset()
|
|
//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
|
|
ClassDeclaration *cd;
|
|
FuncDeclarations bvtbl;
|
|
|
|
for (cd = this->baseClass; cd; cd = cd->baseClass)
|
|
{
|
|
for (size_t k = 0; k < cd->vtblInterfaces->dim; k++)
|
|
{ BaseClass *bs = cd->vtblInterfaces->tdata()[k];
|
|
|
|
if (bs->fillVtbl(this, &bvtbl, 0))
|
|
{
|
|
//printf("\toverriding vtbl[] for %s\n", bs->base->toChars());
|
|
ClassDeclaration *id = bs->base;
|
|
|
|
size_t j = 0;
|
|
if (id->vtblOffset())
|
|
{
|
|
// First entry is ClassInfo reference
|
|
//dtxoff(&dt, id->toSymbol(), 0, TYnptr);
|
|
|
|
// First entry is struct Interface reference
|
|
dtxoff(&dt, cd->toSymbol(), classinfo_size + k * (4 * PTRSIZE), TYnptr);
|
|
j = 1;
|
|
}
|
|
|
|
for (; j < id->vtbl.dim; j++)
|
|
{
|
|
FuncDeclaration *fd;
|
|
|
|
assert(j < bvtbl.dim);
|
|
fd = bvtbl.tdata()[j];
|
|
if (fd)
|
|
dtxoff(&dt, fd->toThunkSymbol(bs->offset), 0, TYnptr);
|
|
else
|
|
dtsize_t(&dt, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#if INTERFACE_VIRTUAL
|
|
// Put out the overriding interface vtbl[]s.
|
|
// This must be mirrored with ClassDeclaration::baseVtblOffset()
|
|
//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
|
|
for (size_t i = 0; i < vtblInterfaces->dim; i++)
|
|
{ BaseClass *b = vtblInterfaces->tdata()[i];
|
|
ClassDeclaration *cd;
|
|
|
|
for (cd = this->baseClass; cd; cd = cd->baseClass)
|
|
{
|
|
for (size_t k = 0; k < cd->vtblInterfaces->dim; k++)
|
|
{ BaseClass *bs = cd->vtblInterfaces->tdata()[k];
|
|
|
|
if (b->base == bs->base)
|
|
{
|
|
//printf("\toverriding vtbl[] for %s\n", b->base->toChars());
|
|
ClassDeclaration *id = b->base;
|
|
|
|
size_t j = 0;
|
|
if (id->vtblOffset())
|
|
{
|
|
// First entry is ClassInfo reference
|
|
//dtxoff(&dt, id->toSymbol(), 0, TYnptr);
|
|
|
|
// First entry is struct Interface reference
|
|
dtxoff(&dt, cd->toSymbol(), classinfo_size + k * (4 * PTRSIZE), TYnptr);
|
|
j = 1;
|
|
}
|
|
|
|
for (; j < id->vtbl.dim; j++)
|
|
{
|
|
assert(j < b->vtbl.dim);
|
|
FuncDeclaration *fd = b->vtbl.tdata()[j];
|
|
if (fd)
|
|
dtxoff(&dt, fd->toThunkSymbol(bs->offset), 0, TYnptr);
|
|
else
|
|
dtsize_t(&dt, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
csym->Sdt = dt;
|
|
#if ELFOBJ || MACHOBJ // Burton
|
|
// ClassInfo cannot be const data, because we use the monitor on it
|
|
csym->Sseg = DATA;
|
|
#endif
|
|
outdata(csym);
|
|
if (isExport())
|
|
obj_export(csym,0);
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Put out the vtbl[]
|
|
//printf("putting out %s.vtbl[]\n", toChars());
|
|
dt = NULL;
|
|
dtxoff(&dt, csym, 0, TYnptr); // first entry is ClassInfo reference
|
|
for (size_t i = 1; i < vtbl.dim; i++)
|
|
{
|
|
FuncDeclaration *fd = vtbl.tdata()[i]->isFuncDeclaration();
|
|
|
|
//printf("\tvtbl[%d] = %p\n", i, fd);
|
|
if (fd && (fd->fbody || !isAbstract()))
|
|
{
|
|
// Ensure function has a return value (Bugzilla 4869)
|
|
if (fd->type->ty == Tfunction && !((TypeFunction *)fd->type)->next)
|
|
{
|
|
assert(fd->scope);
|
|
fd->semantic3(fd->scope);
|
|
}
|
|
|
|
Symbol *s = fd->toSymbol();
|
|
|
|
#if DMDV2
|
|
if (isFuncHidden(fd))
|
|
{ /* fd is hidden from the view of this class.
|
|
* If fd overlaps with any function in the vtbl[], then
|
|
* issue 'hidden' error.
|
|
*/
|
|
for (size_t j = 1; j < vtbl.dim; j++)
|
|
{ if (j == i)
|
|
continue;
|
|
FuncDeclaration *fd2 = vtbl.tdata()[j]->isFuncDeclaration();
|
|
if (!fd2->ident->equals(fd->ident))
|
|
continue;
|
|
if (fd->leastAsSpecialized(fd2) || fd2->leastAsSpecialized(fd))
|
|
{
|
|
if (!global.params.useDeprecated)
|
|
{
|
|
TypeFunction *tf = (TypeFunction *)fd->type;
|
|
if (tf->ty == Tfunction)
|
|
error("use of %s%s hidden by %s is deprecated\n", fd->toPrettyChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs), toChars());
|
|
else
|
|
error("use of %s hidden by %s is deprecated\n", fd->toPrettyChars(), toChars());
|
|
}
|
|
s = rtlsym[RTLSYM_DHIDDENFUNC];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
dtxoff(&dt, s, 0, TYnptr);
|
|
}
|
|
else
|
|
dtsize_t(&dt, 0);
|
|
}
|
|
vtblsym->Sdt = dt;
|
|
vtblsym->Sclass = scclass;
|
|
vtblsym->Sfl = FLdata;
|
|
#if ELFOBJ
|
|
vtblsym->Sseg = CDATA;
|
|
#endif
|
|
#if MACHOBJ
|
|
vtblsym->Sseg = DATA;
|
|
#endif
|
|
outdata(vtblsym);
|
|
if (isExport())
|
|
obj_export(vtblsym,0);
|
|
}
|
|
|
|
/******************************************
|
|
* Get offset of base class's vtbl[] initializer from start of csym.
|
|
* Returns ~0 if not this csym.
|
|
*/
|
|
|
|
unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc)
|
|
{
|
|
unsigned csymoffset;
|
|
|
|
//printf("ClassDeclaration::baseVtblOffset('%s', bc = %p)\n", toChars(), bc);
|
|
csymoffset = global.params.is64bit ? CLASSINFO_SIZE_64 : CLASSINFO_SIZE; // must be ClassInfo.size
|
|
csymoffset += vtblInterfaces->dim * (4 * PTRSIZE);
|
|
|
|
for (size_t i = 0; i < vtblInterfaces->dim; i++)
|
|
{
|
|
BaseClass *b = vtblInterfaces->tdata()[i];
|
|
|
|
if (b == bc)
|
|
return csymoffset;
|
|
csymoffset += b->base->vtbl.dim * PTRSIZE;
|
|
}
|
|
|
|
#if 1
|
|
// Put out the overriding interface vtbl[]s.
|
|
// This must be mirrored with ClassDeclaration::baseVtblOffset()
|
|
//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
|
|
ClassDeclaration *cd;
|
|
FuncDeclarations bvtbl;
|
|
|
|
for (cd = this->baseClass; cd; cd = cd->baseClass)
|
|
{
|
|
for (size_t k = 0; k < cd->vtblInterfaces->dim; k++)
|
|
{ BaseClass *bs = cd->vtblInterfaces->tdata()[k];
|
|
|
|
if (bs->fillVtbl(this, NULL, 0))
|
|
{
|
|
if (bc == bs)
|
|
{ //printf("\tcsymoffset = x%x\n", csymoffset);
|
|
return csymoffset;
|
|
}
|
|
csymoffset += bs->base->vtbl.dim * PTRSIZE;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#if INTERFACE_VIRTUAL
|
|
for (size_t i = 0; i < vtblInterfaces->dim; i++)
|
|
{ BaseClass *b = vtblInterfaces->tdata()[i];
|
|
ClassDeclaration *cd;
|
|
|
|
for (cd = this->baseClass; cd; cd = cd->baseClass)
|
|
{
|
|
//printf("\tbase class %s\n", cd->toChars());
|
|
for (size_t k = 0; k < cd->vtblInterfaces->dim; k++)
|
|
{ BaseClass *bs = cd->vtblInterfaces->tdata()[k];
|
|
|
|
if (bc == bs)
|
|
{ //printf("\tcsymoffset = x%x\n", csymoffset);
|
|
return csymoffset;
|
|
}
|
|
if (b->base == bs->base)
|
|
csymoffset += bs->base->vtbl.dim * PTRSIZE;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return ~0;
|
|
}
|
|
|
|
/* ================================================================== */
|
|
|
|
void InterfaceDeclaration::toObjFile(int multiobj)
|
|
{
|
|
enum_SC scclass;
|
|
|
|
//printf("InterfaceDeclaration::toObjFile('%s')\n", toChars());
|
|
|
|
if (type->ty == Terror)
|
|
{ error("had semantic errors when compiling");
|
|
return;
|
|
}
|
|
|
|
if (!members)
|
|
return;
|
|
|
|
if (global.params.symdebug)
|
|
toDebug();
|
|
|
|
scclass = SCglobal;
|
|
if (inTemplateInstance())
|
|
scclass = SCcomdat;
|
|
|
|
// Put out the members
|
|
for (size_t i = 0; i < members->dim; i++)
|
|
{ Dsymbol *member = members->tdata()[i];
|
|
|
|
member->toObjFile(0);
|
|
}
|
|
|
|
// Generate C symbols
|
|
toSymbol();
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Put out the TypeInfo
|
|
type->getTypeInfo(NULL);
|
|
type->vtinfo->toObjFile(multiobj);
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Put out the ClassInfo
|
|
csym->Sclass = scclass;
|
|
csym->Sfl = FLdata;
|
|
|
|
/* The layout is:
|
|
{
|
|
void **vptr;
|
|
monitor_t monitor;
|
|
byte[] initializer; // static initialization data
|
|
char[] name; // class name
|
|
void *[] vtbl;
|
|
Interface[] interfaces;
|
|
Object *base; // base class
|
|
void *destructor;
|
|
void *invariant; // class invariant
|
|
uint flags;
|
|
void *deallocator;
|
|
OffsetTypeInfo[] offTi;
|
|
void *defaultConstructor;
|
|
#if DMDV2
|
|
const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function
|
|
#endif
|
|
//TypeInfo typeinfo;
|
|
}
|
|
*/
|
|
dt_t *dt = NULL;
|
|
|
|
if (classinfo)
|
|
dtxoff(&dt, classinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo
|
|
else
|
|
dtsize_t(&dt, 0); // BUG: should be an assert()
|
|
dtsize_t(&dt, 0); // monitor
|
|
|
|
// initializer[]
|
|
dtsize_t(&dt, 0); // size
|
|
dtsize_t(&dt, 0); // initializer
|
|
|
|
// name[]
|
|
const char *name = toPrettyChars();
|
|
size_t namelen = strlen(name);
|
|
dtsize_t(&dt, namelen);
|
|
dtabytes(&dt, TYnptr, 0, namelen + 1, name);
|
|
|
|
// vtbl[]
|
|
dtsize_t(&dt, 0);
|
|
dtsize_t(&dt, 0);
|
|
|
|
// vtblInterfaces->tdata()[]
|
|
unsigned offset;
|
|
dtsize_t(&dt, vtblInterfaces->dim);
|
|
if (vtblInterfaces->dim)
|
|
{
|
|
offset = global.params.is64bit ? CLASSINFO_SIZE_64 : CLASSINFO_SIZE; // must be ClassInfo.size
|
|
if (classinfo)
|
|
{
|
|
if (classinfo->structsize != offset)
|
|
{
|
|
error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch.");
|
|
fatal();
|
|
}
|
|
}
|
|
dtxoff(&dt, csym, offset, TYnptr); // (*)
|
|
}
|
|
else
|
|
{ offset = 0;
|
|
dtsize_t(&dt, 0);
|
|
}
|
|
|
|
// base
|
|
assert(!baseClass);
|
|
dtsize_t(&dt, 0);
|
|
|
|
// dtor
|
|
dtsize_t(&dt, 0);
|
|
|
|
// invariant
|
|
dtsize_t(&dt, 0);
|
|
|
|
// flags
|
|
dtsize_t(&dt, 4 | isCOMinterface() | 32);
|
|
|
|
// deallocator
|
|
dtsize_t(&dt, 0);
|
|
|
|
// offTi[]
|
|
dtsize_t(&dt, 0);
|
|
dtsize_t(&dt, 0); // null for now, fix later
|
|
|
|
// defaultConstructor
|
|
dtsize_t(&dt, 0);
|
|
|
|
#if DMDV2
|
|
// xgetMembers
|
|
dtsize_t(&dt, 0);
|
|
#endif
|
|
|
|
//dtxoff(&dt, type->vtinfo->toSymbol(), 0, TYnptr); // typeinfo
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Put out vtblInterfaces->tdata()[]. Must immediately follow csym, because
|
|
// of the fixup (*)
|
|
|
|
offset += vtblInterfaces->dim * (4 * PTRSIZE);
|
|
for (size_t i = 0; i < vtblInterfaces->dim; i++)
|
|
{ BaseClass *b = vtblInterfaces->tdata()[i];
|
|
ClassDeclaration *id = b->base;
|
|
|
|
// ClassInfo
|
|
dtxoff(&dt, id->toSymbol(), 0, TYnptr);
|
|
|
|
// vtbl[]
|
|
dtsize_t(&dt, 0);
|
|
dtsize_t(&dt, 0);
|
|
|
|
// this offset
|
|
dtsize_t(&dt, b->offset);
|
|
}
|
|
|
|
csym->Sdt = dt;
|
|
#if ELFOBJ
|
|
csym->Sseg = CDATA;
|
|
#endif
|
|
#if MACHOBJ
|
|
csym->Sseg = DATA;
|
|
#endif
|
|
outdata(csym);
|
|
if (isExport())
|
|
obj_export(csym,0);
|
|
}
|
|
|
|
/* ================================================================== */
|
|
|
|
void StructDeclaration::toObjFile(int multiobj)
|
|
{
|
|
//printf("StructDeclaration::toObjFile('%s')\n", toChars());
|
|
|
|
if (type->ty == Terror)
|
|
{ error("had semantic errors when compiling");
|
|
return;
|
|
}
|
|
|
|
if (multiobj && !hasStaticCtorOrDtor())
|
|
{ obj_append(this);
|
|
return;
|
|
}
|
|
|
|
// Anonymous structs/unions only exist as part of others,
|
|
// do not output forward referenced structs's
|
|
if (!isAnonymous() && members)
|
|
{
|
|
if (global.params.symdebug)
|
|
toDebug();
|
|
|
|
type->getTypeInfo(NULL); // generate TypeInfo
|
|
|
|
if (1)
|
|
{
|
|
// Generate static initializer
|
|
toInitializer();
|
|
#if 0
|
|
sinit->Sclass = SCcomdat;
|
|
#else
|
|
if (inTemplateInstance())
|
|
{
|
|
sinit->Sclass = SCcomdat;
|
|
}
|
|
else
|
|
{
|
|
sinit->Sclass = SCglobal;
|
|
}
|
|
#endif
|
|
sinit->Sfl = FLdata;
|
|
toDt(&sinit->Sdt);
|
|
|
|
#if OMFOBJ
|
|
/* For OMF, common blocks aren't pulled in from the library.
|
|
*/
|
|
/* ELF comdef's generate multiple
|
|
* definition errors for them from the gnu linker.
|
|
* Need to figure out how to generate proper comdef's for ELF.
|
|
*/
|
|
// See if we can convert a comdat to a comdef,
|
|
// which saves on exe file space.
|
|
if (0 && // causes multiple def problems with COMMON in one file and COMDAT in library
|
|
sinit->Sclass == SCcomdat &&
|
|
sinit->Sdt &&
|
|
sinit->Sdt->dt == DT_azeros &&
|
|
sinit->Sdt->DTnext == NULL &&
|
|
!global.params.multiobj)
|
|
{
|
|
sinit->Sclass = SCglobal;
|
|
sinit->Sdt->dt = DT_common;
|
|
}
|
|
#endif
|
|
|
|
#if ELFOBJ
|
|
sinit->Sseg = CDATA;
|
|
#endif
|
|
#if MACHOBJ
|
|
sinit->Sseg = DATA;
|
|
#endif
|
|
outdata(sinit);
|
|
}
|
|
|
|
// Put out the members
|
|
for (size_t i = 0; i < members->dim; i++)
|
|
{
|
|
Dsymbol *member = (*members)[i];
|
|
/* There might be static ctors in the members, and they cannot
|
|
* be put in separate obj files.
|
|
*/
|
|
member->toObjFile(multiobj);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ================================================================== */
|
|
|
|
void VarDeclaration::toObjFile(int multiobj)
|
|
{
|
|
Symbol *s;
|
|
unsigned sz;
|
|
Dsymbol *parent;
|
|
|
|
//printf("VarDeclaration::toObjFile(%p '%s' type=%s) protection %d\n", this, toChars(), type->toChars(), protection);
|
|
//printf("\talign = %d\n", type->alignsize());
|
|
|
|
if (type->ty == Terror)
|
|
{ error("had semantic errors when compiling");
|
|
return;
|
|
}
|
|
|
|
if (aliassym)
|
|
{ toAlias()->toObjFile(0);
|
|
return;
|
|
}
|
|
|
|
#if DMDV2
|
|
// Do not store variables we cannot take the address of
|
|
if (!canTakeAddressOf())
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (isDataseg() && !(storage_class & STCextern))
|
|
{
|
|
s = toSymbol();
|
|
sz = type->size();
|
|
|
|
parent = this->toParent();
|
|
#if DMDV1 /* private statics should still get a global symbol, in case
|
|
* another module inlines a function that references it.
|
|
*/
|
|
if (/*protection == PROTprivate ||*/
|
|
!parent || parent->ident == NULL || parent->isFuncDeclaration())
|
|
{
|
|
s->Sclass = SCstatic;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (storage_class & STCcomdat)
|
|
s->Sclass = SCcomdat;
|
|
else
|
|
s->Sclass = SCglobal;
|
|
|
|
do
|
|
{
|
|
/* Global template data members need to be in comdat's
|
|
* in case multiple .obj files instantiate the same
|
|
* template with the same types.
|
|
*/
|
|
if (parent->isTemplateInstance() && !parent->isTemplateMixin())
|
|
{
|
|
#if DMDV1
|
|
/* These symbol constants have already been copied,
|
|
* so no reason to output them.
|
|
* Note that currently there is no way to take
|
|
* the address of such a const.
|
|
*/
|
|
if (isConst() && type->toBasetype()->ty != Tsarray &&
|
|
init && init->isExpInitializer())
|
|
return;
|
|
#endif
|
|
s->Sclass = SCcomdat;
|
|
break;
|
|
}
|
|
parent = parent->parent;
|
|
} while (parent);
|
|
}
|
|
s->Sfl = FLdata;
|
|
|
|
if (init)
|
|
{ s->Sdt = init->toDt();
|
|
|
|
// Look for static array that is block initialized
|
|
Type *tb;
|
|
ExpInitializer *ie = init->isExpInitializer();
|
|
|
|
tb = type->toBasetype();
|
|
if (tb->ty == Tsarray && ie &&
|
|
!tb->nextOf()->equals(ie->exp->type->toBasetype()->nextOf()) &&
|
|
ie->exp->implicitConvTo(tb->nextOf())
|
|
)
|
|
{
|
|
size_t dim = ((TypeSArray *)tb)->dim->toInteger();
|
|
|
|
// Duplicate Sdt 'dim-1' times, as we already have the first one
|
|
dt_t **pdt = &s->Sdt;
|
|
while (--dim > 0)
|
|
{
|
|
pdt = ie->exp->toDt(pdt);
|
|
}
|
|
}
|
|
}
|
|
else if (storage_class & STCextern)
|
|
{
|
|
s->Sclass = SCextern;
|
|
s->Sfl = FLextern;
|
|
s->Sdt = NULL;
|
|
// BUG: if isExport(), shouldn't we make it dllimport?
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
type->toDt(&s->Sdt);
|
|
}
|
|
dt_optimize(s->Sdt);
|
|
|
|
// See if we can convert a comdat to a comdef,
|
|
// which saves on exe file space.
|
|
if (s->Sclass == SCcomdat &&
|
|
s->Sdt &&
|
|
s->Sdt->dt == DT_azeros &&
|
|
s->Sdt->DTnext == NULL &&
|
|
!isThreadlocal())
|
|
{
|
|
s->Sclass = SCglobal;
|
|
s->Sdt->dt = DT_common;
|
|
}
|
|
|
|
#if ELFOBJ || MACHOBJ // Burton
|
|
if (s->Sdt && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL)
|
|
s->Sseg = UDATA;
|
|
else
|
|
s->Sseg = DATA;
|
|
#endif
|
|
if (sz)
|
|
{ outdata(s);
|
|
if (isExport())
|
|
obj_export(s,0);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ================================================================== */
|
|
|
|
void TypedefDeclaration::toObjFile(int multiobj)
|
|
{
|
|
//printf("TypedefDeclaration::toObjFile('%s')\n", toChars());
|
|
|
|
if (type->ty == Terror)
|
|
{ error("had semantic errors when compiling");
|
|
return;
|
|
}
|
|
|
|
if (global.params.symdebug)
|
|
toDebug();
|
|
|
|
type->getTypeInfo(NULL); // generate TypeInfo
|
|
|
|
TypeTypedef *tc = (TypeTypedef *)type;
|
|
if (type->isZeroInit() || !tc->sym->init)
|
|
;
|
|
else
|
|
{
|
|
enum_SC scclass = SCglobal;
|
|
if (inTemplateInstance())
|
|
scclass = SCcomdat;
|
|
|
|
// Generate static initializer
|
|
toInitializer();
|
|
sinit->Sclass = scclass;
|
|
sinit->Sfl = FLdata;
|
|
#if ELFOBJ // Burton
|
|
sinit->Sseg = CDATA;
|
|
#endif
|
|
#if MACHOBJ
|
|
sinit->Sseg = DATA;
|
|
#endif
|
|
sinit->Sdt = tc->sym->init->toDt();
|
|
outdata(sinit);
|
|
}
|
|
}
|
|
|
|
/* ================================================================== */
|
|
|
|
void EnumDeclaration::toObjFile(int multiobj)
|
|
{
|
|
//printf("EnumDeclaration::toObjFile('%s')\n", toChars());
|
|
|
|
if (type->ty == Terror)
|
|
{ error("had semantic errors when compiling");
|
|
return;
|
|
}
|
|
|
|
#if DMDV2
|
|
if (isAnonymous())
|
|
return;
|
|
#endif
|
|
|
|
if (global.params.symdebug)
|
|
toDebug();
|
|
|
|
type->getTypeInfo(NULL); // generate TypeInfo
|
|
|
|
TypeEnum *tc = (TypeEnum *)type;
|
|
if (!tc->sym->defaultval || type->isZeroInit())
|
|
;
|
|
else
|
|
{
|
|
enum_SC scclass = SCglobal;
|
|
if (inTemplateInstance())
|
|
scclass = SCcomdat;
|
|
|
|
// Generate static initializer
|
|
toInitializer();
|
|
sinit->Sclass = scclass;
|
|
sinit->Sfl = FLdata;
|
|
#if ELFOBJ // Burton
|
|
sinit->Sseg = CDATA;
|
|
#endif
|
|
#if MACHOBJ
|
|
sinit->Sseg = DATA;
|
|
#endif
|
|
#if DMDV1
|
|
dtnbytes(&sinit->Sdt, tc->size(0), (char *)&tc->sym->defaultval);
|
|
//sinit->Sdt = tc->sym->init->toDt();
|
|
#endif
|
|
#if DMDV2
|
|
tc->sym->defaultval->toDt(&sinit->Sdt);
|
|
#endif
|
|
outdata(sinit);
|
|
}
|
|
}
|
|
|
|
|
|
|