From 8dcd67aa8dcbe5953d251cac557fd998ca29598c Mon Sep 17 00:00:00 2001 From: Brad Roberts Date: Fri, 3 Jul 2009 05:35:38 +0000 Subject: [PATCH] dmd 2.014 --- src/aggregate.h | 8 +- src/attrib.c | 8 +- src/attrib.h | 4 +- src/cast.c | 63 +++-- src/declaration.c | 16 +- src/declaration.h | 8 +- src/dsymbol.h | 2 +- src/e2ir.c | 5 +- src/enum.h | 2 +- src/expression.c | 208 ++++++-------- src/init.c | 2 + src/lib.h | 49 ++++ src/libelf.c | 670 +++++++++++++++++++++++++++++++++++++++++++++ src/link.c | 2 - src/man.c | 60 ++++ src/mars.c | 205 ++++++++++++-- src/mars.h | 18 +- src/module.c | 8 +- src/module.h | 6 +- src/mtype.c | 48 +++- src/mtype.h | 1 + src/root.c | 21 +- src/root.h | 1 + src/staticassert.c | 2 +- src/staticassert.h | 2 +- src/stringtable.c | 4 +- src/stringtable.h | 4 +- src/template.c | 44 ++- src/template.h | 6 +- src/toobj.c | 47 ++-- src/total.h | 1 + src/typinf.c | 10 +- 32 files changed, 1272 insertions(+), 263 deletions(-) create mode 100644 src/lib.h create mode 100644 src/libelf.c create mode 100644 src/man.c diff --git a/src/aggregate.h b/src/aggregate.h index 88f4653e15b7..934a2bbd8022 100644 --- a/src/aggregate.h +++ b/src/aggregate.h @@ -107,11 +107,13 @@ struct AnonymousAggregateDeclaration : AggregateDeclaration struct StructDeclaration : AggregateDeclaration { int zeroInit; // !=0 if initialize with 0 fill +#if V2 int hasIdentityAssign; // !=0 if has identity opAssign FuncDeclaration *cpctor; // generated copy-constructor, if any FuncDeclarations postblits; // Array of postblit functions FuncDeclaration *postblit; // aggregate postblit +#endif StructDeclaration(Loc loc, Identifier *id); Dsymbol *syntaxCopy(Dsymbol *s); @@ -127,7 +129,7 @@ struct StructDeclaration : AggregateDeclaration PROT getAccess(Dsymbol *smember); // determine access to smember - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file void toDt(dt_t **pdt); void toDebug(); // to symbolic debug info @@ -236,7 +238,7 @@ struct ClassDeclaration : AggregateDeclaration void addLocalClass(ClassDeclarations *); // Back end - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file void toDebug(); unsigned baseVtblOffset(BaseClass *bc); Symbol *toSymbol(); @@ -266,7 +268,7 @@ struct InterfaceDeclaration : ClassDeclaration #endif virtual int isCOMinterface(); - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file Symbol *toSymbol(); InterfaceDeclaration *isInterfaceDeclaration() { return this; } diff --git a/src/attrib.c b/src/attrib.c index 72de93f24f3c..41d6729ed6e9 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -176,7 +176,7 @@ void AttribDeclaration::emitComment(Scope *sc) } } -void AttribDeclaration::toObjFile() +void AttribDeclaration::toObjFile(int multiobj) { unsigned i; Array *d = include(NULL, NULL); @@ -187,7 +187,7 @@ void AttribDeclaration::toObjFile() { Dsymbol *s; s = (Dsymbol *)d->data[i]; - s->toObjFile(); + s->toObjFile(multiobj); } } } @@ -917,7 +917,7 @@ char *PragmaDeclaration::kind() return "pragma"; } -void PragmaDeclaration::toObjFile() +void PragmaDeclaration::toObjFile(int multiobj) { if (ident == Id::lib) { @@ -943,7 +943,7 @@ void PragmaDeclaration::toObjFile() Symbol *s = f->toSymbol(); obj_startaddress(s); } - AttribDeclaration::toObjFile(); + AttribDeclaration::toObjFile(multiobj); } void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) diff --git a/src/attrib.h b/src/attrib.h index 99f265c88bf7..d23f748cb34e 100644 --- a/src/attrib.h +++ b/src/attrib.h @@ -50,7 +50,7 @@ struct AttribDeclaration : Dsymbol void toCBuffer(OutBuffer *buf, HdrGenState *hgs); AttribDeclaration *isAttribDeclaration() { return this; } - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file int cvMember(unsigned char *p); }; @@ -119,7 +119,7 @@ struct PragmaDeclaration : AttribDeclaration int oneMember(Dsymbol **ps); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); char *kind(); - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file }; struct ConditionalDeclaration : AttribDeclaration diff --git a/src/cast.c b/src/cast.c index 2d9eee67e9c7..48d590fbc02c 100644 --- a/src/cast.c +++ b/src/cast.c @@ -1514,31 +1514,52 @@ Expression *BinExp::typeCombine(Scope *sc) goto Lagain; } else if (t1->ty == Tclass || t2->ty == Tclass) - { int i1; - int i2; + { + while (1) + { + int i1 = e2->implicitConvTo(t1); + int i2 = e1->implicitConvTo(t2); - i1 = e2->implicitConvTo(t1); - i2 = e1->implicitConvTo(t2); + if (i1 && i2) + { + // We have the case of class vs. void*, so pick class + if (t1->ty == Tpointer) + i1 = 0; + else if (t2->ty == Tpointer) + i2 = 0; + } - if (i1 && i2) - { - // We have the case of class vs. void*, so pick class - if (t1->ty == Tpointer) - i1 = 0; - else if (t2->ty == Tpointer) - i2 = 0; - } + if (i2) + { + goto Lt2; + } + else if (i1) + { + goto Lt1; + } + else if (t1->ty == Tclass && t2->ty == Tclass) + { TypeClass *tc1 = (TypeClass *)t1; + TypeClass *tc2 = (TypeClass *)t2; - if (i2) - { - goto Lt2; - } - else if (i1) - { - goto Lt1; + /* Pick 'tightest' type + */ + ClassDeclaration *cd1 = tc1->sym->baseClass; + ClassDeclaration *cd2 = tc1->sym->baseClass; + + if (cd1 && cd2) + { t1 = cd1->type; + t2 = cd2->type; + } + else if (cd1) + t1 = cd1->type; + else if (cd2) + t2 = cd2->type; + else + goto Lincompatible; + } + else + goto Lincompatible; } - else - goto Lincompatible; } else if (t1->ty == Tstruct && t2->ty == Tstruct) { diff --git a/src/declaration.c b/src/declaration.c index fe38a0cc213e..1f34478a8526 100644 --- a/src/declaration.c +++ b/src/declaration.c @@ -947,10 +947,6 @@ void VarDeclaration::semantic(Scope *sc) if (fd && !isStatic() && !(storage_class & STCmanifest) && !init->isVoidInitializer()) { - Expression *e1; - Type *t; - int dim; - //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); if (!ei) { @@ -968,15 +964,15 @@ void VarDeclaration::semantic(Scope *sc) init = ei; } - e1 = new VarExp(loc, this); + Expression *e1 = new VarExp(loc, this); - t = type->toBasetype(); + Type *t = type->toBasetype(); if (t->ty == Tsarray) { ei->exp = ei->exp->semantic(sc); if (!ei->exp->implicitConvTo(type)) { - dim = ((TypeSArray *)t)->dim->toInteger(); + int dim = ((TypeSArray *)t)->dim->toInteger(); // If multidimensional static array, treat as one large array while (1) { @@ -993,7 +989,11 @@ void VarDeclaration::semantic(Scope *sc) { ei->exp = ei->exp->semantic(sc); if (!ei->exp->implicitConvTo(type)) - ei->exp = new CastExp(loc, ei->exp, type); + { Type *ti = ei->exp->type->toBasetype(); + // Don't cast away invariant or mutability in initializer + if (!(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc))) + ei->exp = new CastExp(loc, ei->exp, type); + } } ei->exp = new AssignExp(loc, e1, ei->exp); ei->exp->op = op; diff --git a/src/declaration.h b/src/declaration.h index e3e0a361978a..ba4baf2ac394 100644 --- a/src/declaration.h +++ b/src/declaration.h @@ -178,7 +178,7 @@ struct TypedefDeclaration : Declaration void toDocBuffer(OutBuffer *buf); - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file void toDebug(); int cvMember(unsigned char *p); @@ -257,7 +257,7 @@ struct VarDeclaration : Declaration Dsymbol *toAlias(); Symbol *toSymbol(); - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file int cvMember(unsigned char *p); // Eliminate need for dynamic_cast @@ -319,7 +319,7 @@ struct TypeInfoDeclaration : VarDeclaration void emitComment(Scope *sc); Symbol *toSymbol(); - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file virtual void toDt(dt_t **pdt); }; @@ -568,7 +568,7 @@ struct FuncDeclaration : Declaration Symbol *toSymbol(); Symbol *toThunkSymbol(int offset); // thunk version - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file int cvMember(unsigned char *p); void buildClosure(IRState *irs); diff --git a/src/dsymbol.h b/src/dsymbol.h index fb794fda24cf..71f1c7e5a1c3 100644 --- a/src/dsymbol.h +++ b/src/dsymbol.h @@ -165,7 +165,7 @@ struct Dsymbol : Object // Backend virtual Symbol *toSymbol(); // to backend symbol - virtual void toObjFile(); // compile to .obj file + virtual void toObjFile(int multiobj); // compile to .obj file virtual int cvMember(unsigned char *p); // emit cv debug info for member Symbol *toImport(); // to backend import symbol diff --git a/src/e2ir.c b/src/e2ir.c index e1482615dbae..308d867039e6 100644 --- a/src/e2ir.c +++ b/src/e2ir.c @@ -1054,7 +1054,7 @@ elem *Dsymbol_toElem(Dsymbol *s, IRState *irs) if (s != vd) return Dsymbol_toElem(s, irs); if (vd->isStatic() || vd->storage_class & STCextern) - vd->toObjFile(); + vd->toObjFile(0); else { sp = s->toSymbol(); @@ -1073,18 +1073,15 @@ elem *Dsymbol_toElem(Dsymbol *s, IRState *irs) else if ((cd = s->isClassDeclaration()) != NULL) { irs->deferToObj->push(s); - //sd->toObjFile(); } else if ((sd = s->isStructDeclaration()) != NULL) { irs->deferToObj->push(sd); - //sd->toObjFile(); } else if ((fd = s->isFuncDeclaration()) != NULL) { //printf("function %s\n", fd->toChars()); irs->deferToObj->push(fd); - //fd->toObjFile(); } else if ((tm = s->isTemplateMixin()) != NULL) { diff --git a/src/enum.h b/src/enum.h index 0936cb65d973..7806c1c79a3a 100644 --- a/src/enum.h +++ b/src/enum.h @@ -52,7 +52,7 @@ struct EnumDeclaration : ScopeDsymbol EnumDeclaration *isEnumDeclaration() { return this; } - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file void toDebug(); int cvMember(unsigned char *p); diff --git a/src/expression.c b/src/expression.c index 6b99d8d4d125..a13b18ba51fc 100644 --- a/src/expression.c +++ b/src/expression.c @@ -190,6 +190,79 @@ void initPrecedence() precedence[TOKcomma] = PREC_expr; } +/************************************************************* + * Given var, we need to get the + * right 'this' pointer if var is in an outer class, but our + * existing 'this' pointer is in an inner class. + * Input: + * e1 existing 'this' + * ad struct or class we need the correct 'this' for + * var the specific member of ad we're accessing + */ + +Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, + Expression *e1, Declaration *var) +{ + L1: + Type *t = e1->type->toBasetype(); + + /* If e1 is not the 'this' pointer for ad + */ + if (ad && + !(t->ty == Tpointer && t->nextOf()->ty == Tstruct && + ((TypeStruct *)t->nextOf())->sym == ad) + && + !(t->ty == Tstruct && + ((TypeStruct *)t)->sym == ad) + ) + { + ClassDeclaration *cd = ad->isClassDeclaration(); + ClassDeclaration *tcd = t->isClassHandle(); + + /* e1 is the right this if ad is a base class of e1 + */ + if (!cd || !tcd || + !(tcd == cd || cd->isBaseOf(tcd, NULL)) + ) + { + /* Only classes can be inner classes with an 'outer' + * member pointing to the enclosing class instance + */ + if (tcd && tcd->isNested()) + { /* e1 is the 'this' pointer for an inner class. + * Rewrite it as the 'this' pointer for the outer class. + */ + + e1 = new DotVarExp(loc, e1, tcd->vthis); + e1 = e1->semantic(sc); + + // Skip up over nested functions, and get the enclosing + // class type. + Dsymbol *s; + for (s = tcd->toParent(); + s && s->isFuncDeclaration(); + s = s->toParent()) + { FuncDeclaration *f = s->isFuncDeclaration(); + if (f->vthis) + { + e1 = new VarExp(loc, f->vthis); + } + } + if (s && s->isClassDeclaration()) + e1->type = s->isClassDeclaration()->type; + e1 = e1->semantic(sc); + goto L1; + } + + /* Can't find a path from e1 to ad + */ + error("this for %s needs to be type %s not type %s", + var->toChars(), ad->toChars(), t->toChars()); + } + } + return e1; +} + /***************************************** * Determine if 'this' is available. * If it is, return the FuncDeclaration that has it. @@ -5042,6 +5115,16 @@ Expression *DotIdExp::semantic(Scope *sc) return new TypeExp(loc, t); } + TupleDeclaration *tup = s->isTupleDeclaration(); + if (tup) + { + if (eleft) + error("cannot have e.tuple"); + e = new TupleExp(loc, tup); + e = e->semantic(sc); + return e; + } + ScopeDsymbol *sds = s->isScopeDsymbol(); if (sds) { @@ -5195,54 +5278,7 @@ Expression *DotVarExp::semantic(Scope *sc) type = type->invariantOf(); AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration(); - L1: - Type *t = e1->type->toBasetype(); - - if (ad && - !(t->ty == Tpointer && - ((TypePointer *)t)->next->ty == Tstruct && - ((TypeStruct *)((TypePointer *)t)->next)->sym == ad) - && - !(t->ty == Tstruct && ((TypeStruct *)t)->sym == ad) - ) - { - ClassDeclaration *cd = ad->isClassDeclaration(); - ClassDeclaration *tcd = t->isClassHandle(); - - if (!cd || !tcd || - !(tcd == cd || cd->isBaseOf(tcd, NULL)) - ) - { - if (tcd && tcd->isNested()) - { // Try again with outer scope - - e1 = new DotVarExp(loc, e1, tcd->vthis); - e1 = e1->semantic(sc); - - // Skip over nested functions, and get the enclosing - // class type. - Dsymbol *s = tcd->toParent(); - while (s && s->isFuncDeclaration()) - { FuncDeclaration *f = s->isFuncDeclaration(); - if (f->vthis) - { - e1 = new VarExp(loc, f->vthis); - } - s = s->toParent(); - } - if (s && s->isClassDeclaration()) - e1->type = s->isClassDeclaration()->type; - - e1 = e1->semantic(sc); // get corrected nested refs - goto L1; - } -#ifdef DEBUG - printf("2: "); -#endif - error("%s for %s needs to be type %s not type %s", - e1->toChars(), var->toChars(), ad->toChars(), t->toChars()); - } - } + e1 = getRightThis(loc, sc, ad, e1, var); if (!sc->noaccesscheck) accessCheck(loc, sc, e1, var); } @@ -5485,44 +5521,9 @@ Expression *DelegateExp::semantic(Scope *sc) e1 = e1->semantic(sc); type = new TypeDelegate(func->type); type = type->semantic(loc, sc); -//----------------- - /* For func, we need to get the - * right 'this' pointer if func is in an outer class, but our - * existing 'this' pointer is in an inner class. - * This code is analogous to that used for variables - * in DotVarExp::semantic(). - */ AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration(); - L10: - Type *t = e1->type; - if (func->needThis() && ad && - !(t->ty == Tpointer && ((TypePointer *)t)->next->ty == Tstruct && - ((TypeStruct *)((TypePointer *)t)->next)->sym == ad) && - !(t->ty == Tstruct && ((TypeStruct *)t)->sym == ad) - ) - { - ClassDeclaration *cd = ad->isClassDeclaration(); - ClassDeclaration *tcd = t->isClassHandle(); - - if (!cd || !tcd || - !(tcd == cd || cd->isBaseOf(tcd, NULL)) - ) - { - if (tcd && tcd->isNested()) - { // Try again with outer scope - - e1 = new DotVarExp(loc, e1, tcd->vthis); - e1 = e1->semantic(sc); - goto L10; - } -#ifdef DEBUG - printf("3: "); -#endif - error("this for %s needs to be type %s not type %s", - func->toChars(), ad->toChars(), t->toChars()); - } - } -//----------------- + if (func->needThis()) + e1 = getRightThis(loc, sc, ad, e1, func); } return this; } @@ -5859,41 +5860,8 @@ e1->dump(0); } ad = td->toParent()->isAggregateDeclaration(); } - /* Now that we have the right function f, we need to get the - * right 'this' pointer if f is in an outer class, but our - * existing 'this' pointer is in an inner class. - * This code is analogous to that used for variables - * in DotVarExp::semantic(). - */ - L10: - Type *t = ue->e1->type->toBasetype(); - if (f->needThis() && ad && - !(t->ty == Tpointer && ((TypePointer *)t)->next->ty == Tstruct && - ((TypeStruct *)((TypePointer *)t)->next)->sym == ad) && - !(t->ty == Tstruct && ((TypeStruct *)t)->sym == ad) - ) - { - ClassDeclaration *cd = ad->isClassDeclaration(); - ClassDeclaration *tcd = t->isClassHandle(); - - if (!cd || !tcd || - !(tcd == cd || cd->isBaseOf(tcd, NULL)) - ) - { - if (tcd && tcd->isNested()) - { // Try again with outer scope - - ue->e1 = new DotVarExp(loc, ue->e1, tcd->vthis); - ue->e1 = ue->e1->semantic(sc); - goto L10; - } -#ifdef DEBUG - printf("1: "); -#endif - error("this for %s needs to be type %s not type %s", - f->toChars(), ad->toChars(), t->toChars()); - } - } + if (f->needThis()) + ue->e1 = getRightThis(loc, sc, ad, ue->e1, f); checkDeprecated(sc, f); accessCheck(loc, sc, ue->e1, f); diff --git a/src/init.c b/src/init.c index 6168d1b6f7f6..5ea21962b3ec 100644 --- a/src/init.c +++ b/src/init.c @@ -166,6 +166,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t) { if (fieldi >= ad->fields.dim) { error(loc, "too many initializers for %s", ad->toChars()); + field.remove(i); + i--; continue; } else diff --git a/src/lib.h b/src/lib.h new file mode 100644 index 000000000000..0abf9dc0f08a --- /dev/null +++ b/src/lib.h @@ -0,0 +1,49 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2008 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. + +#ifndef DMD_LIB_H +#define DMD_LIB_H + +#ifdef __DMC__ +#pragma once +#endif /* __DMC__ */ + +struct ObjModule; + +struct ObjSymbol +{ + char *name; + ObjModule *om; +}; + +struct Library +{ + File *libfile; + Array objmodules; // ObjModule[] + Array objsymbols; // ObjSymbol[] + + StringTable tab; + + Library(); + void setFilename(char *dir, char *filename); + void addObject(char *module_name, void *buf, size_t buflen); + void addLibrary(void *buf, size_t buflen); + void write(); + + private: + void addSymbol(ObjModule *om, char *name, int pickAny = 0); + void scanObjModule(ObjModule *om); + unsigned short numDictPages(unsigned padding); + int FillDict(unsigned char *bucketsP, unsigned short uNumPages); + void WriteLibToBuffer(OutBuffer *libbuf); +}; + +#endif /* DMD_LIB_H */ + diff --git a/src/libelf.c b/src/libelf.c new file mode 100644 index 000000000000..c2026a8b2f69 --- /dev/null +++ b/src/libelf.c @@ -0,0 +1,670 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2008 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 +#include +#include +#include +#include +#include +#include + +#include "mem.h" +#include "root.h" +#include "stringtable.h" + +#include "mars.h" +#include "lib.h" +#include "melf.h" + +#define LOG 0 + +Library::Library() +{ + libfile = NULL; +} + +/*********************************** + * Set the library file name based on the output directory + * and the filename. + * Add default library file name extension. + */ + +void Library::setFilename(char *dir, char *filename) +{ +#if LOG + printf("Library::setFilename(dir = '%s', filename = '%s')\n", + dir ? dir : "", filename ? filename : ""); +#endif + char *arg = filename; + if (!arg || !*arg) + { // Generate lib file name from first obj name + char *n = (char *)global.params.objfiles->data[0]; + + n = FileName::name(n); + FileName *fn = FileName::forceExt(n, global.lib_ext); + arg = fn->toChars(); + } + if (!FileName::absolute(arg)) + arg = FileName::combine(dir, arg); + FileName *libfilename = FileName::defaultExt(arg, global.lib_ext); + + libfile = new File(libfilename); +} + +void Library::write() +{ + if (global.params.verbose) + printf("library %s\n", libfile->name->toChars()); + + OutBuffer libbuf; + WriteLibToBuffer(&libbuf); + + // Transfer image to file + libfile->setbuffer(libbuf.data, libbuf.offset); + libbuf.extractData(); + + + char *p = FileName::path(libfile->name->toChars()); + FileName::ensurePathExists(p); + //mem.free(p); + + libfile->writev(); +} + +/*****************************************************************************/ + +void Library::addLibrary(void *buf, size_t buflen) +{ + addObject(NULL, buf, buflen); +} + + +/*****************************************************************************/ +/*****************************************************************************/ + +static char elf[4] = { 0x7F, 'E', 'L', 'F' }; // ELF file signature + +void sputl(int value, void* buffer) +{ + unsigned char *p = (unsigned char*)buffer; + p[0] = (unsigned char)(value >> 24); + p[1] = (unsigned char)(value >> 16); + p[2] = (unsigned char)(value >> 8); + p[3] = (unsigned char)(value); +} + +int sgetl(void* buffer) +{ + unsigned char *p = (unsigned char*)buffer; + return (((((p[0] << 8) | p[1]) << 8) | p[2]) << 8) | p[3]; +} + + +struct ObjModule +{ + unsigned char *base; // where are we holding it in memory + unsigned length; // in bytes + unsigned offset; // offset from start of library + char *name; // module name (file name) + int name_offset; // if not -1, offset into string table of name + long file_time; // file time + unsigned user_id; + unsigned group_id; + unsigned file_mode; + int scan; // 1 means scan for symbols +}; + +struct Header +{ + #define OBJECT_NAME_SIZE 16 + char object_name[OBJECT_NAME_SIZE]; + char file_time[12]; + char user_id[6]; + char group_id[6]; + char file_mode[8]; // in octal + char file_size[10]; + char trailer[2]; +}; + +void OmToHeader(Header *h, ObjModule *om) +{ + size_t len; + if (om->name_offset == -1) + { + len = strlen(om->name); + memcpy(h->object_name, om->name, len); + h->object_name[len] = '/'; + assert(len < OBJECT_NAME_SIZE); + memset(h->object_name + len + 1, ' ', OBJECT_NAME_SIZE - (len + 1)); + } + else + { + len = sprintf(h->object_name, "/%d", om->name_offset); + h->object_name[len] = ' '; + } + + /* In the following sprintf's, don't worry if the trailing 0 + * that sprintf writes goes off the end of the field. It will + * write into the next field, which we will promptly overwrite + * anyway. (So make sure to write the fields in ascending order.) + */ + + len = sprintf(h->file_time, "%lu", om->file_time); + assert(len <= 12); + memset(h->file_time + len, ' ', 12 - len); + + len = sprintf(h->user_id, "%u", om->user_id); + assert(len <= 6); + memset(h->user_id + len, ' ', 6 - len); + + len = sprintf(h->group_id, "%u", om->group_id); + assert(len <= 6); + memset(h->group_id + len, ' ', 6 - len); + + len = sprintf(h->file_mode, "%o", om->file_mode); + assert(len <= 8); + memset(h->file_mode + len, ' ', 8 - len); + + len = sprintf(h->file_size, "%u", om->length); + assert(len <= 10); + memset(h->file_size + len, ' ', 10 - len); + + h->trailer[0] = '`'; + h->trailer[1] = '\n'; +} + +void Library::addSymbol(ObjModule *om, char *name, int pickAny) +{ +#if LOG + printf("Library::addSymbol(%s, %s, %d)\n", om->name, name, pickAny); +#endif + StringValue *s = tab.insert(name, strlen(name)); + if (!s) + { // already in table + if (!pickAny) + { s = tab.lookup(name, strlen(name)); + assert(s); + ObjSymbol *os = (ObjSymbol *)s->ptrvalue; + error("multiple definition of %s: %s and %s: %s", + om->name, name, os->om->name, os->name); + } + } + else + { + ObjSymbol *os = new ObjSymbol(); + os->name = strdup(name); + os->om = om; + s->ptrvalue = (void *)os; + + objsymbols.push(os); + } +} + +/************************************ + * Scan single object module for dictionary symbols. + * Send those symbols to Library::addSymbol(). + */ + +void Library::scanObjModule(ObjModule *om) +{ +#if LOG + printf("Library::scanObjModule(%s)\n", om->name); +#endif + unsigned char *buf = (unsigned char *)om->base; + size_t buflen = om->length; + int reason = 0; + + if (buflen < sizeof(elf_header_f32)) + { + Lcorrupt: + error("corrupt ELF object module %s %d", om->name, reason); + return; + } + + elf_header_f32 *eh = (elf_header_f32 *)buf; + if (memcmp(buf, elf, 4)) + { reason = 1; + goto Lcorrupt; + } + if (eh->EHtype != EH_TYPE_RELFILE) + return; // not relocatable object module + +#if 0 + /* String table section + */ + elf_sht *string_section = (elf_sht *)(buf + eh->EHshtoff + + eh->EHshtentsz * eh->EHshtstrndx); + if (string_section->SHtype != SHT_STRTAB) + { + //printf("buf = %p, EHshtentsz = %d, EHshtstrndx = %d\n", buf, eh->EHshtentsz, eh->EHshtstrndx); + //printf("SHtype = %d, SHT_STRTAB = %d\n", string_section->SHtype, SHT_STRTAB); + reason = 2; + goto Lcorrupt; + } + printf("strtab SHfileoff = x%x\n", string_section->SHfileoff); + char *string_tab = (char *)(buf + string_section->SHfileoff); +#endif + + /* For each Section + */ + for (unsigned u = 0; u < eh->EHshtnum; u++) + { elf_sht *section = (elf_sht *)(buf + eh->EHshtoff + eh->EHshtentsz * u); + + if (section->SHtype == SHT_SYMTAB) + { /* SHoptidx gives the particular string table section + * used for the symbol names. + */ + elf_sht *string_section = (elf_sht *)(buf + eh->EHshtoff + + eh->EHshtentsz * section->SHoptidx); + if (string_section->SHtype != SHT_STRTAB) + { + reason = 3; + goto Lcorrupt; + } + char *string_tab = (char *)(buf + string_section->SHfileoff); + + for (unsigned offset = 0; offset < section->SHsecsz; offset += sizeof(elf_symtab)) + { elf_symtab *sym = (elf_symtab *)(buf + section->SHfileoff + offset); + + if (((sym->STinfo >> 4) == ST_BIND_GLOBAL || + (sym->STinfo >> 4) == ST_BIND_WEAK) && + sym->STdefsht != SHT_UNDEF) // not extern + { + char *name = string_tab + sym->STname; + //printf("sym STname = x%x\n", sym->STname); + addSymbol(om, name, 1); + } + } + } + } +} + +/*************************************** + * Add object module or library to the library. + * Examine the buffer to see which it is. + * If the buffer is NULL, use module_name as the file name + * and load the file. + */ + +void Library::addObject(char *module_name, void *buf, size_t buflen) +{ + if (!module_name) + module_name = ""; +#if LOG + printf("Library::addObject(%s)\n", module_name); +#endif + int fromfile = 0; + if (!buf) + { assert(module_name[0]); + FileName f(module_name, 0); + File file(&f); + file.readv(); + buf = file.buffer; + buflen = file.len; + file.ref = 1; + fromfile = 1; + } + int reason = 0; + + if (buflen < 16) + { + Lcorrupt: + error("corrupt object module %s %d", module_name, reason); + return; + } + + if (memcmp(buf, "!\n", 8) == 0) + { /* Library file. + * Pull each object module out of the library and add it + * to the object module array. + */ + unsigned offset = 8; + char *symtab = NULL; + unsigned symtab_size = 0; + char *filenametab = NULL; + unsigned filenametab_size = 0; + unsigned mstart = objmodules.dim; + while (offset < buflen) + { + if (offset + sizeof(Header) >= buflen) + { reason = 1; + goto Lcorrupt; + } + Header *header = (Header *)((unsigned char *)buf + offset); + offset += sizeof(Header); + char *endptr = NULL; + unsigned long size = strtoul(header->file_size, &endptr, 10); + if (endptr >= &header->file_size[10] || *endptr != ' ') + goto Lcorrupt; + if (offset + size > buflen) + goto Lcorrupt; + + if (header->object_name[0] == '/' && + header->object_name[1] == ' ') + { + /* Instead of rescanning the object modules we pull from a + * library, just use the already created symbol table. + */ + if (symtab) + goto Lcorrupt; + symtab = (char *)buf + offset; + symtab_size = size; + if (size < 4) + goto Lcorrupt; + } + else if (header->object_name[0] == '/' && + header->object_name[1] == '/') + { + /* This is the file name table, save it for later. + */ + if (filenametab) + goto Lcorrupt; + filenametab = (char *)buf + offset; + filenametab_size = size; + } + else + { + ObjModule *om = new ObjModule(); + om->base = (unsigned char *)buf + offset - sizeof(Header); + om->length = size; + om->offset = 0; + if (header->object_name[0] == '/') + { /* Pick long name out of file name table + */ + unsigned foff = strtoul(header->object_name + 1, &endptr, 10); + unsigned i; + for (i = 0; 1; i++) + { if (foff + i >= filenametab_size) + goto Lcorrupt; + char c = filenametab[foff + i]; + if (c == '/') + break; + } + om->name = (char *)malloc(i + 1); + assert(om->name); + memcpy(om->name, filenametab + foff, i); + om->name[i] = 0; + } + else + { /* Pick short name out of header + */ + om->name = (char *)malloc(OBJECT_NAME_SIZE); + assert(om->name); + for (int i = 0; 1; i++) + { if (i == OBJECT_NAME_SIZE) + goto Lcorrupt; + char c = header->object_name[i]; + if (c == '/') + { om->name[i] = 0; + break; + } + om->name[i] = c; + } + } + om->name_offset = -1; + om->file_time = strtoul(header->file_time, &endptr, 10); + om->user_id = strtoul(header->user_id, &endptr, 10); + om->group_id = strtoul(header->group_id, &endptr, 10); + om->file_mode = strtoul(header->file_mode, &endptr, 8); + om->scan = 0; + objmodules.push(om); + } + offset += (size + 1) & ~1; + } + if (offset != buflen) + goto Lcorrupt; + + /* Scan the library's symbol table, and insert it into our own. + * We use this instead of rescanning the object module, because + * the library's creator may have a different idea of what symbols + * go into the symbol table than we do. + * This is also probably faster. + */ + unsigned nsymbols = sgetl(symtab); + char *s = symtab + 4 + nsymbols * 4; + if (4 + nsymbols * (4 + 1) > symtab_size) + goto Lcorrupt; + for (unsigned i = 0; i < nsymbols; i++) + { char *name = s; + s += strlen(name) + 1; + if (s - symtab > symtab_size) + goto Lcorrupt; + unsigned moff = sgetl(symtab + 4 + i * 4); + for (unsigned m = mstart; 1; m++) + { if (m == objmodules.dim) + goto Lcorrupt; // didn't find it + ObjModule *om = (ObjModule *)objmodules.data[m]; + if (moff + sizeof(Header) == (char *)om->base - (char *)buf) + { + addSymbol(om, name, 1); + if (mstart == m) + mstart++; + break; + } + } + } + + return; + } + + if (memcmp(buf, elf, 4) != 0) + { reason = 2; + goto Lcorrupt; + } + + /* It's an ELF object module + */ + ObjModule *om = new ObjModule(); + om->base = (unsigned char *)buf; + om->length = buflen; + om->offset = 0; + om->name = FileName::name(module_name); // remove path, but not extension + om->name_offset = -1; + om->scan = 1; + if (fromfile) + { struct stat statbuf; + int i = stat(module_name, &statbuf); + if (i == -1) // error, errno is set + { reason = 3; + goto Lcorrupt; + } + om->file_time = statbuf.st_ctime; + om->user_id = statbuf.st_uid; + om->group_id = statbuf.st_gid; + om->file_mode = statbuf.st_mode; + } + else + { /* Mock things up for the object module file that never was + * actually written out. + */ + static uid_t uid; + static gid_t gid; + static int init; + if (!init) + { init = 1; + uid = getuid(); + gid = getgid(); + } + time(&om->file_time); + om->user_id = uid; + om->group_id = gid; + om->file_mode = 0100640; + } + objmodules.push(om); +} + + +/*****************************************************************************/ +/*****************************************************************************/ + +/********************************************** + * Create and write library to libbuf. + * The library consists of: + * !\n + * header + * dictionary + * object modules... + */ + +void Library::WriteLibToBuffer(OutBuffer *libbuf) +{ +#if LOG + printf("Library::WriteLibToBuffer()\n"); +#endif + + /************* Scan Object Modules for Symbols ******************/ + + for (int i = 0; i < objmodules.dim; i++) + { ObjModule *om = (ObjModule *)objmodules.data[i]; + if (om->scan) + { + scanObjModule(om); + } + } + + /************* Determine string section ******************/ + + /* The string section is where we store long file names. + */ + unsigned noffset = 0; + for (int i = 0; i < objmodules.dim; i++) + { ObjModule *om = (ObjModule *)objmodules.data[i]; + size_t len = strlen(om->name); + if (len >= OBJECT_NAME_SIZE) + { + om->name_offset = noffset; + noffset += len + 2; + } + else + om->name_offset = -1; + } + +#if LOG + printf("\tnoffset = x%x\n", noffset); +#endif + + /************* Determine module offsets ******************/ + + unsigned moffset = 8 + sizeof(Header) + 4; + + for (int i = 0; i < objsymbols.dim; i++) + { ObjSymbol *os = (ObjSymbol *)objsymbols.data[i]; + + moffset += 4 + strlen(os->name) + 1; + } + unsigned hoffset = moffset; + +#if LOG + printf("\tmoffset = x%x\n", moffset); +#endif + + moffset += moffset & 1; + if (noffset) + moffset += sizeof(Header) + noffset; + + for (int i = 0; i < objmodules.dim; i++) + { ObjModule *om = (ObjModule *)objmodules.data[i]; + + moffset += moffset & 1; + om->offset = moffset; + moffset += sizeof(Header) + om->length; + } + + libbuf->reserve(moffset); + + /************* Write the library ******************/ + libbuf->write("!\n", 8); + + ObjModule om; + om.name_offset = -1; + om.base = NULL; + om.length = hoffset - (8 + sizeof(Header)); + om.offset = 8; + om.name = ""; + ::time(&om.file_time); + om.user_id = 0; + om.group_id = 0; + om.file_mode = 0; + + Header h; + OmToHeader(&h, &om); + libbuf->write(&h, sizeof(h)); + char buf[4]; + sputl(objsymbols.dim, buf); + libbuf->write(buf, 4); + + for (int i = 0; i < objsymbols.dim; i++) + { ObjSymbol *os = (ObjSymbol *)objsymbols.data[i]; + + sputl(os->om->offset, buf); + libbuf->write(buf, 4); + } + + for (int i = 0; i < objsymbols.dim; i++) + { ObjSymbol *os = (ObjSymbol *)objsymbols.data[i]; + + libbuf->writestring(os->name); + libbuf->writeByte(0); + } + +#if LOG + printf("\tlibbuf->moffset = x%x\n", libbuf->offset); +#endif + + /* Write out the string section + */ + if (noffset) + { + if (libbuf->offset & 1) + libbuf->writeByte('\n'); + + // header + memset(&h, ' ', sizeof(Header)); + h.object_name[0] = '/'; + h.object_name[1] = '/'; + size_t len = sprintf(h.file_size, "%u", noffset); + assert(len < 10); + h.file_size[len] = ' '; + h.trailer[0] = '`'; + h.trailer[1] = '\n'; + libbuf->write(&h, sizeof(h)); + + for (int i = 0; i < objmodules.dim; i++) + { ObjModule *om = (ObjModule *)objmodules.data[i]; + if (om->name_offset >= 0) + { libbuf->writestring(om->name); + libbuf->writeByte('/'); + libbuf->writeByte('\n'); + } + } + } + + /* Write out each of the object modules + */ + for (int i = 0; i < objmodules.dim; i++) + { ObjModule *om = (ObjModule *)objmodules.data[i]; + + if (libbuf->offset & 1) + libbuf->writeByte('\n'); // module alignment + + assert(libbuf->offset == om->offset); + + OmToHeader(&h, om); + libbuf->write(&h, sizeof(h)); // module header + + libbuf->write(om->base, om->length); // module contents + } + +#if LOG + printf("moffset = x%x, libbuf->offset = x%x\n", moffset, libbuf->offset); +#endif + assert(libbuf->offset == moffset); +} diff --git a/src/link.c b/src/link.c index 4765ae39e595..abe699728440 100644 --- a/src/link.c +++ b/src/link.c @@ -67,8 +67,6 @@ int runLINK() else { // Generate exe file name from first obj name char *n = (char *)global.params.objfiles->data[0]; - char *ex; - n = FileName::name(n); FileName *fn = FileName::forceExt(n, "exe"); global.params.exefile = fn->toChars(); diff --git a/src/man.c b/src/man.c new file mode 100644 index 000000000000..7d3bacd5d6ca --- /dev/null +++ b/src/man.c @@ -0,0 +1,60 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 2008-2008 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 +#include +#include +#include + +#if _WIN32 + +#include + +#pragma comment(lib,"shell32.lib") + +void browse(const char *url) +{ + ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); +} + +#endif + +#if linux + +#include +#include +#include + +void browse(const char *url) +{ + pid_t childpid; + const char *args[3]; + + char *browser = getenv("BROWSER"); + if (browser) + browser = strdup(browser); + else + browser = "firefox"; + + args[0] = browser; + args[1] = url; + args[2] = NULL; + + childpid = fork(); + if (childpid == 0) + { + execvp(args[0], (char**)args); + perror(args[0]); // failed to execute + return; + } +} + +#endif + diff --git a/src/mars.c b/src/mars.c index 9a53035eee72..610cbf298470 100644 --- a/src/mars.c +++ b/src/mars.c @@ -37,9 +37,14 @@ long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); #include "cond.h" #include "expression.h" #include "lexer.h" +#include "lib.h" +void browse(const char *url); void getenv_setargv(const char *envvar, int *pargc, char** *pargv); +void obj_start(char *srcfile); +void obj_end(Library *library, File *objfile); + Global global; Global::Global() @@ -56,11 +61,19 @@ Global::Global() obj_ext = "o"; #else #error "fix this" +#endif + +#if _WIN32 + lib_ext = "lib"; +#elif linux + lib_ext = "a"; +#else +#error "fix this" #endif copyright = "Copyright (c) 1999-2008 by Digital Mars"; written = "written by Walter Bright"; - version = "v2.013"; + version = "v2.014"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -151,7 +164,7 @@ void usage() printf("Digital Mars D Compiler %s\n%s %s\n", global.version, global.copyright, global.written); printf("\ -Documentation: http://www.digitalmars.com/d/index.html\n\ +Documentation: http://www.digitalmars.com/d/2.0/index.html\n\ Usage:\n\ dmd files.d ... { -switch }\n\ \n\ @@ -178,10 +191,12 @@ Usage:\n\ -inline do function inlining\n\ -Jpath where to look for string imports\n\ -Llinkerflag pass linkerflag to link\n\ + -lib generate library rather than object files\n\ + -man open web browser on manual page\n\ -nofloat do not emit reference to floating point\n\ -O optimize\n\ -o- do not write object file\n\ - -odobjdir write object files to directory objdir\n\ + -odobjdir write object & library files to directory objdir\n\ -offilename name output file to filename\n\ -op do not strip paths from source file\n\ -profile profile runtime performance of generated code\n\ @@ -206,6 +221,7 @@ int main(int argc, char *argv[]) { int i; Array files; + Array libmodules; char *p; Module *m; int status = EXIT_SUCCESS; @@ -273,7 +289,9 @@ int main(int argc, char *argv[]) //VersionCondition::addPredefinedGlobalIdent("D_Bits"); VersionCondition::addPredefinedGlobalIdent("D_InlineAsm"); VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86"); +#if V2 VersionCondition::addPredefinedGlobalIdent("D_Version2"); +#endif VersionCondition::addPredefinedGlobalIdent("all"); #if _WIN32 @@ -304,6 +322,8 @@ int main(int argc, char *argv[]) global.params.cov = 1; else if (strcmp(p + 1, "fPIC") == 0) global.params.pic = 1; + else if (strcmp(p + 1, "multiobj") == 0) + global.params.multiobj = 1; else if (strcmp(p + 1, "g") == 0) global.params.symdebug = 1; else if (strcmp(p + 1, "gc") == 0) @@ -318,9 +338,13 @@ int main(int argc, char *argv[]) global.params.verbose = 1; else if (strcmp(p + 1, "v1") == 0) { +#if V1 + global.params.Dversion = 1; +#else error("use DMD 1.0 series compilers for -v1 switch"); break; - } +#endif + } else if (strcmp(p + 1, "w") == 0) global.params.warnings = 1; else if (strcmp(p + 1, "O") == 0) @@ -410,6 +434,8 @@ int main(int argc, char *argv[]) global.params.ignoreUnsupportedPragmas = 1; else if (strcmp(p + 1, "inline") == 0) global.params.useInline = 1; + else if (strcmp(p + 1, "lib") == 0) + global.params.lib = 1; else if (strcmp(p + 1, "nofloat") == 0) global.params.nofloat = 1; else if (strcmp(p + 1, "quiet") == 0) @@ -509,6 +535,24 @@ int main(int argc, char *argv[]) { global.params.debuglibname = p + 1 + 9; } + else if (memcmp(p + 1, "man", 3) == 0) + { +#if _WIN32 +#if V1 + browse("http://www.digitalmars.com/d/1.0/dmd-windows.html"); +#else + browse("http://www.digitalmars.com/d/2.0/dmd-windows.html"); +#endif +#endif +#if linux +#if V1 + browse("http://www.digitalmars.com/d/1.0/dmd-linux.html"); +#else + browse("http://www.digitalmars.com/d/2.0/dmd-linux.html"); +#endif +#endif + exit(EXIT_SUCCESS); + } else if (strcmp(p + 1, "run") == 0) { global.params.run = 1; global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1; @@ -536,7 +580,17 @@ int main(int argc, char *argv[]) } } else + { +#if !TARGET_LINUX + char *ext = FileName::ext(p); + if (ext && stricmp(ext, "exe") == 0) + { + global.params.objname = p; + continue; + } +#endif files.push(p); + } } if (global.errors) { @@ -562,13 +616,37 @@ int main(int argc, char *argv[]) if (global.params.useUnitTests) global.params.useAssert = 1; - if (!global.params.obj) + if (!global.params.obj || global.params.lib) global.params.link = 0; if (global.params.link) { global.params.exefile = global.params.objname; + global.params.oneobj = 1; + if (global.params.objname) + { + /* Use this to name the one object file with the same + * name as the exe file. + */ + global.params.objname = FileName::forceExt(global.params.objname, global.obj_ext)->toChars(); + + /* If output directory is given, use that path rather than + * the exe file path. + */ + if (global.params.objdir) + { char *name = FileName::name(global.params.objname); + global.params.objname = FileName::combine(global.params.objdir, name); + } + } + } + else if (global.params.lib) + { + global.params.libname = global.params.objname; global.params.objname = NULL; + + // Haven't investigated handling these options with multiobj + if (!global.params.cov && !global.params.trace) + global.params.multiobj = 1; } else if (global.params.run) { @@ -579,14 +657,17 @@ int main(int argc, char *argv[]) { if (global.params.objname && files.dim > 1) { - error("multiple source files, but only one .obj name"); - fatal(); + global.params.oneobj = 1; + //error("multiple source files, but only one .obj name"); + //fatal(); } } if (global.params.cov) VersionCondition::addPredefinedGlobalIdent("D_Coverage"); +#if V2 if (global.params.useUnitTests) VersionCondition::addPredefinedGlobalIdent("unittest"); +#endif // Initialization Type::init(); @@ -635,8 +716,9 @@ int main(int argc, char *argv[]) // Create Modules Array modules; modules.reserve(files.dim); + int firstmodule = 1; for (i = 0; i < files.dim; i++) - { Identifier *id; + { char *ext; char *name; @@ -654,7 +736,8 @@ int main(int argc, char *argv[]) p = FileName::name(p); // strip path ext = FileName::ext(p); if (ext) - { + { /* Deduce what to do with a file based on its extension + */ #if TARGET_LINUX if (strcmp(ext, global.obj_ext) == 0) #else @@ -662,16 +745,18 @@ int main(int argc, char *argv[]) #endif { global.params.objfiles->push(files.data[i]); + libmodules.push(files.data[i]); continue; } #if TARGET_LINUX - if (strcmp(ext, "a") == 0) + if (strcmp(ext, global.lib_ext) == 0) #else - if (stricmp(ext, "lib") == 0) + if (stricmp(ext, global.lib_ext) == 0) #endif { global.params.libfiles->push(files.data[i]); + libmodules.push(files.data[i]); continue; } @@ -696,11 +781,13 @@ int main(int argc, char *argv[]) if (stricmp(ext, "exe") == 0) { - global.params.exefile = (char *)files.data[i]; - continue; + assert(0); // should have already been handled } #endif + /* Examine extension to see if it is a valid + * D source file extension + */ if (stricmp(ext, global.mars_ext) == 0 || stricmp(ext, "dd") == 0 || stricmp(ext, "htm") == 0 || @@ -733,11 +820,18 @@ int main(int argc, char *argv[]) goto Linvalid; } - id = new Identifier(name, 0); + /* At this point, name is the D source file name stripped of + * its path and extension. + */ + + Identifier *id = new Identifier(name, 0); m = new Module((char *) files.data[i], id, global.params.doDocComments, global.params.doHdrGeneration); modules.push(m); - global.params.objfiles->push(m->objfile->name->str); + if (firstmodule) + { global.params.objfiles->push(m->objfile->name->str); + firstmodule = 0; + } } #if _WIN32 @@ -745,6 +839,7 @@ int main(int argc, char *argv[]) { #endif // Read files, parse them + int anydocfiles = 0; for (i = 0; i < modules.dim; i++) { m = (Module *)modules.data[i]; @@ -753,11 +848,13 @@ int main(int argc, char *argv[]) if (!Module::rootModule) Module::rootModule = m; m->importedFrom = m; - m->deleteObjFile(); + if (!global.params.oneobj || i == 0 || m->isDocFile) + m->deleteObjFile(); m->read(0); m->parse(); if (m->isDocFile) { + anydocfiles = 1; m->gendocfile(); // Remove m from list of modules @@ -778,6 +875,12 @@ int main(int argc, char *argv[]) global.params.link = 0; } } + if (anydocfiles && modules.dim && + (global.params.oneobj || global.params.objname)) + { + error("conflicting Ddoc and obj generation options"); + fatal(); + } if (global.errors) fatal(); #ifdef _DH @@ -867,22 +970,68 @@ int main(int argc, char *argv[]) if (global.errors) fatal(); + Library *library = NULL; + if (global.params.lib) + { + library = new Library(); + library->setFilename(global.params.objdir, global.params.libname); + + // Add input object and input library files to output library + for (int i = 0; i < libmodules.dim; i++) + { + char *p = (char *)libmodules.data[i]; + library->addObject(p, NULL, 0); + } + } + // Generate output files - for (i = 0; i < modules.dim; i++) + if (global.params.oneobj) { - m = (Module *)modules.data[i]; - if (global.params.verbose) - printf("code %s\n", m->toChars()); - if (global.params.obj) - m->genobjfile(); - if (global.errors) - m->deleteObjFile(); - else + for (i = 0; i < modules.dim; i++) { - if (global.params.doDocComments) + m = (Module *)modules.data[i]; + if (global.params.verbose) + printf("code %s\n", m->toChars()); + if (i == 0) + obj_start(m->srcfile->toChars()); + m->genobjfile(0); + if (!global.errors && global.params.doDocComments) m->gendocfile(); } + if (!global.errors && modules.dim) + { + obj_end(library, ((Module *)modules.data[0])->objfile); + } + } + else + { + for (i = 0; i < modules.dim; i++) + { + m = (Module *)modules.data[i]; + if (global.params.verbose) + printf("code %s\n", m->toChars()); + if (global.params.obj) + { obj_start(m->srcfile->toChars()); + m->genobjfile(global.params.multiobj); + obj_end(library, m->objfile); + obj_write_deferred(library); + } + if (global.errors) + { + if (!global.params.lib) + m->deleteObjFile(); + } + else + { + if (global.params.doDocComments) + m->gendocfile(); + } + } } + + if (global.params.lib && !global.errors) + library->write(); + #if _WIN32 } __except (__ehfilter(GetExceptionInformation())) @@ -915,8 +1064,10 @@ int main(int argc, char *argv[]) */ for (i = 0; i < modules.dim; i++) { - m = (Module *)modules.data[i]; + Module *m = (Module *)modules.data[i]; m->deleteObjFile(); + if (global.params.oneobj) + break; } deleteExeFile(); } diff --git a/src/mars.h b/src/mars.h index a8cbb8de1de1..10c6a476f2e8 100644 --- a/src/mars.h +++ b/src/mars.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars +// Copyright (c) 1999-2008 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -29,6 +29,7 @@ /* Changes for the GDC compiler by David Friedman */ #endif +#define V1 0 #define V2 1 // Version 2.0 features #define BREAKABI 1 // 0 if not ready to break the ABI just yet @@ -39,6 +40,9 @@ struct Param { char obj; // write object file char link; // perform link + char lib; // write library file instead of object file(s) + char multiobj; // break one object file into multiple ones + char oneobj; // write one object file instead of multiple ones char trace; // insert profiling hooks char quiet; // suppress non-error messages char verbose; // verbose compile @@ -70,8 +74,9 @@ struct Param char *argv0; // program name Array *imppath; // array of char*'s of where to look for import modules Array *fileImppath; // array of char*'s of where to look for file import modules - char *objdir; // .obj file output directory + char *objdir; // .obj/.lib file output directory char *objname; // .obj file output name + char *libname; // .lib file output name char doDocComments; // process embedded documentation comments char *docdir; // write documentation file to docdir directory @@ -123,6 +128,7 @@ struct Global char *mars_ext; char *sym_ext; char *obj_ext; + char *lib_ext; char *doc_ext; // for Ddoc generated files char *ddoc_ext; // for Ddoc macro include files char *hdr_ext; // for D 'header' import files @@ -284,4 +290,12 @@ void halt(); #define stdmsg stdout #endif +struct Dsymbol; +struct Library; +struct File; +void obj_start(char *srcfile); +void obj_end(Library *library, File *objfile); +void obj_append(Dsymbol *s); +void obj_write_deferred(Library *library); + #endif /* DMD_MARS_H */ diff --git a/src/module.c b/src/module.c index aab82a0b63d9..b036ef1fddc2 100644 --- a/src/module.c +++ b/src/module.c @@ -104,6 +104,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen macrotable = NULL; escapetable = NULL; + doppelganger = 0; cov = NULL; covb = NULL; @@ -765,18 +766,15 @@ void Module::gensymfile() { OutBuffer buf; HdrGenState hgs; - int i; //printf("Module::gensymfile()\n"); buf.printf("// Sym file generated from '%s'", srcfile->toChars()); buf.writenl(); - for (i = 0; i < members->dim; i++) - { - Dsymbol *s; + for (int i = 0; i < members->dim; i++) + { Dsymbol *s = (Dsymbol *)members->data[i]; - s = (Dsymbol *)members->data[i]; s->toCBuffer(&buf, &hgs); } diff --git a/src/module.h b/src/module.h index 935d95ecb513..6f58b00363d6 100644 --- a/src/module.h +++ b/src/module.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2005 by Digital Mars +// Copyright (c) 1999-2008 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -24,6 +24,7 @@ struct ModuleDeclaration; struct Macro; struct Escape; struct VarDeclaration; +struct Library; // Back end #if IN_GCC @@ -125,7 +126,7 @@ struct Module : Package #ifdef _DH void genhdrfile(); // generate D import file #endif - void genobjfile(); + void genobjfile(int multiobj); void gensymfile(); void gendocfile(); int needModuleInfo(); @@ -136,6 +137,7 @@ struct Module : Package // Back end + int doppelganger; // sub-module Symbol *cov; // private uint[] __coverage; unsigned *covb; // bit array of valid code line numbers diff --git a/src/mtype.c b/src/mtype.c index bf7ad74fd74e..f93110c994dd 100644 --- a/src/mtype.c +++ b/src/mtype.c @@ -906,9 +906,8 @@ TypeBasic *Type::isTypeBasic() void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) { - Type *t; - - t = semantic(loc, sc); + //printf("Type::resolve() %s, %d\n", toChars(), ty); + Type *t = semantic(loc, sc); *pt = t; *pe = NULL; *ps = NULL; @@ -1919,8 +1918,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); if (*pe) { // It's really an index expression - Expression *e; - e = new IndexExp(loc, *pe, dim); + Expression *e = new IndexExp(loc, *pe, dim); *pe = e; } else if (*ps) @@ -2379,7 +2377,7 @@ MATCH TypeDArray::implicitConvTo(Type *to) if (!(next->mod == ta->next->mod || ta->next->mod == MODconst)) return MATCHnomatch; // not const-compatible - /* Alloc conversion to void[] + /* Allow conversion to void[] */ if (next->ty != Tvoid && ta->next->ty == Tvoid) { @@ -2394,6 +2392,15 @@ MATCH TypeDArray::implicitConvTo(Type *to) return m; } + /* Allow conversions of T[][] to const(T)[][] + */ + if (mod == ta->mod && next->ty == Tarray && ta->next->ty == Tarray) + { + m = next->implicitConvTo(ta->next); + if (m == MATCHconst) + return m; + } + /* Conversion of array of derived to array of base */ if (ta->next->isBaseOf(next, &offset) && offset == 0) @@ -2517,6 +2524,35 @@ Type *TypeAArray::semantic(Loc loc, Scope *sc) return merge(); } +void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) +{ + //printf("TypeAArray::resolve() %s\n", toChars()); + + // Deal with the case where we thought the index was a type, but + // in reality it was an expression. + if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray) + { + Expression *e; + Type *t; + Dsymbol *s; + + index->resolve(loc, sc, &e, &t, &s); + if (e) + { // It was an expression - + // Rewrite as a static array + + TypeSArray *tsa = new TypeSArray(next, e); + return tsa->resolve(loc, sc, pe, pt, ps); + } + else if (t) + index = t; + else + index->error(loc, "index is not a type or an expression"); + } + Type::resolve(loc, sc, pe, pt, ps); +} + + Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident) { #if LOGDOTEXP diff --git a/src/mtype.h b/src/mtype.h index ac8538785ac5..afbf32e6f5eb 100644 --- a/src/mtype.h +++ b/src/mtype.h @@ -392,6 +392,7 @@ struct TypeAArray : TypeArray Type *syntaxCopy(); d_uns64 size(Loc loc); Type *semantic(Loc loc, Scope *sc); + void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); void toDecoBuffer(OutBuffer *buf, int flag); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); diff --git a/src/root.c b/src/root.c index d30666d21360..dff9b9f0be31 100644 --- a/src/root.c +++ b/src/root.c @@ -497,6 +497,7 @@ int FileName::absolute(const char *name) /******************************** * Return filename extension (read-only). + * Points past '.' of extension. * If there isn't one, return NULL. */ @@ -518,6 +519,7 @@ char *FileName::ext(const char *str) #if _WIN32 case '\\': case ':': + case '/': break; #endif default: @@ -535,6 +537,23 @@ char *FileName::ext() return ext(str); } +/******************************** + * Return mem.malloc'd filename with extension removed. + */ + +char *FileName::removeExt(const char *str) +{ + const char *e = ext(str); + if (e) + { size_t len = (e - str) - 1; + char *n = (char *)mem.malloc(len + 1); + memcpy(n, str, len); + n[len] = 0; + return n; + } + return mem.strdup(str); +} + /******************************** * Return filename name excluding path (read-only). */ @@ -1062,7 +1081,7 @@ int File::write() char *name; name = this->name->toChars(); - fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0660); + fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd == -1) goto err; diff --git a/src/root.h b/src/root.h index 964eda5ad12d..b054ea5f2e06 100644 --- a/src/root.h +++ b/src/root.h @@ -125,6 +125,7 @@ struct FileName : String static int absolute(const char *name); static char *ext(const char *); char *ext(); + static char *removeExt(const char *str); static char *name(const char *); char *name(); static char *path(const char *); diff --git a/src/staticassert.c b/src/staticassert.c index fed5121b1f74..97e3a42be8fe 100644 --- a/src/staticassert.c +++ b/src/staticassert.c @@ -86,7 +86,7 @@ void StaticAssert::inlineScan() { } -void StaticAssert::toObjFile() +void StaticAssert::toObjFile(int multiobj) { } diff --git a/src/staticassert.h b/src/staticassert.h index 9b0e124cbbdb..a38078d3f37b 100644 --- a/src/staticassert.h +++ b/src/staticassert.h @@ -35,7 +35,7 @@ struct StaticAssert : Dsymbol void semantic2(Scope *sc); void inlineScan(); int oneMember(Dsymbol **ps); - void toObjFile(); + void toObjFile(int multiobj); char *kind(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; diff --git a/src/stringtable.c b/src/stringtable.c index cd00d9a88d0b..6f60ccdabd4c 100644 --- a/src/stringtable.c +++ b/src/stringtable.c @@ -1,8 +1,8 @@ -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2008 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// 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. diff --git a/src/stringtable.h b/src/stringtable.h index 5a7d72b5d5fd..1d85994d3c5f 100644 --- a/src/stringtable.h +++ b/src/stringtable.h @@ -1,7 +1,7 @@ -// Copyright (c) 1999-2002 by Digital Mars +// Copyright (c) 1999-2008 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// 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. diff --git a/src/template.c b/src/template.c index 8239815c700a..bac37927f453 100644 --- a/src/template.c +++ b/src/template.c @@ -520,7 +520,12 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : ""); #endif +#if V1 + m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam); +#else m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam, (flag & 2) ? 1 : 0); + +#endif //printf("\tm2 = %d\n", m2); if (m2 == MATCHnomatch) @@ -1915,10 +1920,12 @@ TemplateTupleParameter *TemplateParameter::isTemplateTupleParameter() return NULL; } +#if V2 TemplateThisParameter *TemplateParameter::isTemplateThisParameter() { return NULL; } +#endif /* ======================== TemplateTypeParameter =========================== */ @@ -2166,6 +2173,7 @@ Object *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc) /* ======================== TemplateThisParameter =========================== */ +#if V2 // this-parameter TemplateThisParameter::TemplateThisParameter(Loc loc, Identifier *ident, @@ -2195,7 +2203,7 @@ void TemplateThisParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("this "); TemplateTypeParameter::toCBuffer(buf, hgs); } - +#endif /* ======================== TemplateAliasParameter ========================== */ @@ -2627,10 +2635,12 @@ Object *TemplateValueParameter::defaultArg(Loc loc, Scope *sc) { e = e->syntaxCopy(); e = e->semantic(sc); +#if V2 if (e->op == TOKdefault) { DefaultInitExp *de = (DefaultInitExp *)e; e = de->resolve(loc, sc); } +#endif } return e; } @@ -2816,6 +2826,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti assert((size_t)tempdecl->scope > 0x10000); } + Objects *TemplateInstance::arraySyntaxCopy(Objects *objs) { Objects *a = NULL; @@ -3731,8 +3742,7 @@ printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); } void TemplateInstance::semantic3(Scope *sc) -{ int i; - +{ #if LOG printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone); #endif @@ -3745,7 +3755,7 @@ void TemplateInstance::semantic3(Scope *sc) sc = tempdecl->scope; sc = sc->push(argsym); sc = sc->push(this); - for (i = 0; i < members->dim; i++) + for (int i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; s->semantic3(sc); @@ -3755,31 +3765,35 @@ void TemplateInstance::semantic3(Scope *sc) } } -void TemplateInstance::toObjFile() -{ int i; - +void TemplateInstance::toObjFile(int multiobj) +{ #if LOG printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this); #endif if (!errors && members) { - for (i = 0; i < members->dim; i++) + if (multiobj) + // Append to list of object files to be written later + obj_append(this); + else { - Dsymbol *s = (Dsymbol *)members->data[i]; - s->toObjFile(); + for (int i = 0; i < members->dim; i++) + { + Dsymbol *s = (Dsymbol *)members->data[i]; + s->toObjFile(multiobj); + } } } } void TemplateInstance::inlineScan() -{ int i; - +{ #if LOG printf("TemplateInstance::inlineScan('%s')\n", toChars()); #endif if (!errors && members) { - for (i = 0; i < members->dim; i++) + for (int i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; s->inlineScan(); @@ -4300,9 +4314,9 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } -void TemplateMixin::toObjFile() +void TemplateMixin::toObjFile(int multiobj) { //printf("TemplateMixin::toObjFile('%s')\n", toChars()); - TemplateInstance::toObjFile(); + TemplateInstance::toObjFile(multiobj); } diff --git a/src/template.h b/src/template.h index 8c98a8a48aff..e518e267da6c 100644 --- a/src/template.h +++ b/src/template.h @@ -155,6 +155,7 @@ struct TemplateTypeParameter : TemplateParameter void *dummyArg(); }; +#if V2 struct TemplateThisParameter : TemplateTypeParameter { /* Syntax: @@ -169,6 +170,7 @@ struct TemplateThisParameter : TemplateTypeParameter TemplateParameter *syntaxCopy(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; +#endif struct TemplateValueParameter : TemplateParameter { @@ -295,7 +297,7 @@ struct TemplateInstance : ScopeDsymbol char *toChars(); char *mangle(); - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file // Internal static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags); @@ -329,7 +331,7 @@ struct TemplateMixin : TemplateInstance char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - void toObjFile(); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file TemplateMixin *isTemplateMixin() { return this; } }; diff --git a/src/toobj.c b/src/toobj.c index 062984d2c03d..82777dfd608e 100644 --- a/src/toobj.c +++ b/src/toobj.c @@ -44,6 +44,8 @@ void obj_lzext(Symbol *s1,Symbol *s2); void Module::genmoduleinfo() { + //printf("Module::genmoduleinfo() %s\n", toChars()); + Symbol *msym = toSymbol(); unsigned offset; unsigned sizeof_ModuleInfo = 14 * PTRSIZE; @@ -73,7 +75,9 @@ void Module::genmoduleinfo() 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 // name[] @@ -83,21 +87,18 @@ void Module::genmoduleinfo() 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; + for (int i = 0; i < members->dim; i++) + { Dsymbol *member = (Dsymbol *)members->data[i]; - 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++) + for (int i = 0; i < aimports.dim; i++) { Module *m = (Module *)aimports.data[i]; if (!m->needModuleInfo()) aimports_dim--; @@ -148,11 +149,9 @@ void Module::genmoduleinfo() ////////////////////////////////////////////// - for (i = 0; i < aimports.dim; i++) - { - Module *m; + for (int i = 0; i < aimports.dim; i++) + { Module *m = (Module *)aimports.data[i]; - m = (Module *)aimports.data[i]; if (m->needModuleInfo()) { Symbol *s = m->toSymbol(); s->Sflags |= SFLweak; @@ -160,11 +159,9 @@ void Module::genmoduleinfo() } } - for (i = 0; i < aclasses.dim; i++) + for (int i = 0; i < aclasses.dim; i++) { - ClassDeclaration *cd; - - cd = (ClassDeclaration *)aclasses.data[i]; + ClassDeclaration *cd = (ClassDeclaration *)aclasses.data[i]; dtxoff(&dt, cd->toSymbol(), 0, TYnptr); } @@ -182,7 +179,7 @@ void Module::genmoduleinfo() /* ================================================================== */ -void Dsymbol::toObjFile() +void Dsymbol::toObjFile(int multiobj) { //printf("Dsymbol::toObjFile('%s')\n", toChars()); // ignore @@ -190,7 +187,7 @@ void Dsymbol::toObjFile() /* ================================================================== */ -void ClassDeclaration::toObjFile() +void ClassDeclaration::toObjFile(int multiobj) { unsigned i; unsigned offset; Symbol *sinit; @@ -222,7 +219,7 @@ void ClassDeclaration::toObjFile() Dsymbol *member; member = (Dsymbol *)members->data[i]; - member->toObjFile(); + member->toObjFile(0); } #if 0 @@ -720,7 +717,7 @@ unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc) /* ================================================================== */ -void InterfaceDeclaration::toObjFile() +void InterfaceDeclaration::toObjFile(int multiobj) { unsigned i; unsigned offset; Symbol *sinit; @@ -751,7 +748,7 @@ void InterfaceDeclaration::toObjFile() member = (Dsymbol *)members->data[i]; if (!member->isFuncDeclaration()) - member->toObjFile(); + member->toObjFile(0); } // Generate C symbols @@ -873,7 +870,7 @@ void InterfaceDeclaration::toObjFile() /* ================================================================== */ -void StructDeclaration::toObjFile() +void StructDeclaration::toObjFile(int multiobj) { unsigned i; //printf("StructDeclaration::toObjFile('%s')\n", toChars()); @@ -933,14 +930,14 @@ void StructDeclaration::toObjFile() Dsymbol *member; member = (Dsymbol *)members->data[i]; - member->toObjFile(); + member->toObjFile(0); } } } /* ================================================================== */ -void VarDeclaration::toObjFile() +void VarDeclaration::toObjFile(int multiobj) { Symbol *s; unsigned sz; @@ -950,7 +947,7 @@ void VarDeclaration::toObjFile() //printf("\talign = %d\n", type->alignsize()); if (aliassym) - { toAlias()->toObjFile(); + { toAlias()->toObjFile(0); return; } @@ -1073,7 +1070,7 @@ void VarDeclaration::toObjFile() /* ================================================================== */ -void TypedefDeclaration::toObjFile() +void TypedefDeclaration::toObjFile(int multiobj) { //printf("TypedefDeclaration::toObjFile('%s')\n", toChars()); @@ -1111,7 +1108,7 @@ void TypedefDeclaration::toObjFile() /* ================================================================== */ -void EnumDeclaration::toObjFile() +void EnumDeclaration::toObjFile(int multiobj) { //printf("EnumDeclaration::toObjFile('%s')\n", toChars()); diff --git a/src/total.h b/src/total.h index 30c42f2feebe..42f38765e537 100644 --- a/src/total.h +++ b/src/total.h @@ -41,5 +41,6 @@ #include "id.h" #include "cond.h" #include "version.h" +#include "lib.h" #endif /* DMD_TOTAL_H */ diff --git a/src/typinf.c b/src/typinf.c index aa9ba8ed46ac..fcd00f9ec4ba 100644 --- a/src/typinf.c +++ b/src/typinf.c @@ -132,7 +132,7 @@ Expression *Type::getTypeInfo(Scope *sc) } else // if in obj generation pass { - t->vtinfo->toObjFile(); + t->vtinfo->toObjFile(global.params.multiobj); } } } @@ -639,7 +639,7 @@ void TypeInfoTupleDeclaration::toDt(dt_t **pdt) dtxoff(pdt, s, 0, TYnptr); // elements.ptr } -void TypeInfoDeclaration::toObjFile() +void TypeInfoDeclaration::toObjFile(int multiobj) { Symbol *s; unsigned sz; @@ -647,6 +647,12 @@ void TypeInfoDeclaration::toObjFile() //printf("TypeInfoDeclaration::toObjFile(%p '%s') protection %d\n", this, toChars(), protection); + if (multiobj) + { + obj_append(this); + return; + } + s = toSymbol(); sz = type->size();