diff --git a/src/backend/cc.h b/src/backend/cc.h index 008097c9b7c9..57a5cad44e0d 100644 --- a/src/backend/cc.h +++ b/src/backend/cc.h @@ -717,9 +717,7 @@ typedef struct FUNC_S // of SCftexpspec explicit specializations Funcsym *Fsurrogatesym; // Fsurrogate: surrogate cast function -#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS char *Fredirect; // redirect function name to this name in object -#endif } func_t; #define func_calloc() ((func_t *) mem_fcalloc(sizeof(func_t))) diff --git a/src/backend/cgobj.c b/src/backend/cgobj.c index 7d700217c8af..3570716976de 100644 --- a/src/backend/cgobj.c +++ b/src/backend/cgobj.c @@ -554,8 +554,10 @@ int Obj::data_readonly(char *p, int len) * csegname code segment name (can be NULL) */ -void Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname) +Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname) { + Obj *mobj = new Obj(); + memset(&obj,0,sizeof(obj)); obj.buf = objbuf; @@ -649,6 +651,8 @@ void Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname) ledata_new(cseg,0); // so ledata is never NULL if (config.fulltypes) // if full typing information cv_init(); // initialize debug output code + + return mobj; } /************************** @@ -2365,6 +2369,22 @@ int Obj::data_start(Symbol *sdata, targ_size_t datasize, int seg) return seg; } +void Obj::func_start(Symbol *sfunc) +{ + //printf("Obj::func_start(%s)\n",sfunc->Sident); + symbol_debug(sfunc); + sfunc->Sseg = cseg; // current code seg + sfunc->Soffset = Coffset; // offset of start of function +} + +/******************************* + * Update function info after codgen + */ + +void Obj::func_term(Symbol *sfunc) +{ +} + /******************************** * Output a public definition. * Input: diff --git a/src/backend/code.h b/src/backend/code.h index 64513f237490..87120a265498 100644 --- a/src/backend/code.h +++ b/src/backend/code.h @@ -985,9 +985,13 @@ void cgsched_block(block *b); // Generalize the Windows platform concept of CODE,DATA,UDATA,etc // into multiple segments -#if OMFOBJ +struct Ledatarec; // OMF +struct linnum_data; // Elf, Mach + -struct Ledatarec; +typedef unsigned int IDXSTR; +typedef unsigned int IDXSEC; +typedef unsigned int IDXSYM; struct seg_data { @@ -995,6 +999,7 @@ struct seg_data targ_size_t SDoffset; // starting offset for data int SDalignment; // power of 2 +#if OMFOBJ bool isfarseg; int segidx; // internal object file segment number int lnameidx; // lname idx of segment name @@ -1003,37 +1008,13 @@ struct seg_data targ_size_t origsize; // original size long seek; // seek position in output file Ledatarec *ledata; // current one we're filling in -}; - -//extern targ_size_t Coffset; - #endif -#if ELFOBJ || MACHOBJ - -typedef unsigned int IDXSTR; -typedef unsigned int IDXSEC; -typedef unsigned int IDXSYM; - -struct linnum_data -{ - const char *filename; - unsigned filenumber; // corresponding file number for DW_LNS_set_file - - unsigned linoff_count; - unsigned linoff_max; - unsigned (*linoff)[2]; // [0] = line number, [1] = offset -}; - -struct seg_data -{ - int SDseg; // segment index into SegData[] +#if 1 //ELFOBJ || MACHOBJ IDXSEC SDshtidx; // section header table index - targ_size_t SDoffset; // starting offset for data Outbuffer *SDbuf; // buffer to hold data Outbuffer *SDrel; // buffer to hold relocation info - int SDalignment; // power of 2 -#if ELFOBJ +#if 1 //ELFOBJ IDXSYM SDsymidx; // each section is in the symbol table IDXSEC SDrelidx; // section header for relocation info targ_size_t SDrelmaxoff; // maximum offset encountered @@ -1050,9 +1031,23 @@ struct seg_data linnum_data *SDlinnum_data; // array of line number / offset data int isCode(); +#endif }; + +#if 1 //ELFOBJ || MACHOBJ + +struct linnum_data +{ + const char *filename; + unsigned filenumber; // corresponding file number for DW_LNS_set_file + + unsigned linoff_count; + unsigned linoff_max; + unsigned (*linoff)[2]; // [0] = line number, [1] = offset +}; + #endif extern seg_data **SegData; diff --git a/src/backend/elfobj.c b/src/backend/elfobj.c index 6bb4e7ebdf4b..3c6ee474f0f1 100644 --- a/src/backend/elfobj.c +++ b/src/backend/elfobj.c @@ -631,9 +631,10 @@ int Obj::data_readonly(char *p, int len) * Called before any other obj_xxx routines */ -void Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname) +Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname) { //printf("Obj::init()\n"); + ElfObj *obj = new ElfObj(); cseg = CODE; fobjbuf = objbuf; @@ -804,6 +805,7 @@ void Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname) if (config.fulltypes) dwarf_initfile(filename); + return obj; } /************************** diff --git a/src/backend/machobj.c b/src/backend/machobj.c index e91fbf45c2d9..95f7f54e162a 100644 --- a/src/backend/machobj.c +++ b/src/backend/machobj.c @@ -426,9 +426,11 @@ int Obj::data_readonly(char *p, int len) * Called before any other obj_xxx routines */ -void Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname) +Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname) { //printf("Obj::init()\n"); + MachObj *obj = new MachObj(); + cseg = CODE; fobjbuf = objbuf; @@ -496,6 +498,8 @@ void Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname) if (config.fulltypes) dwarf_initfile(filename); + + return obj; } /************************** diff --git a/src/backend/mscoffobj.c b/src/backend/mscoffobj.c index d9ee41855b33..ff70c1c4925a 100644 --- a/src/backend/mscoffobj.c +++ b/src/backend/mscoffobj.c @@ -1,2 +1,2521 @@ -#include "mscoff.h" +// Copyright (c) 2009-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 gpl.txt. +// See the included readme.txt for details. + + +#if SCPP || MARS +#include +#include +#include +#include +#include +#include +#include + +#if _WIN32 || linux +#include +#endif + +#include "cc.h" +#include "global.h" +#include "code.h" +#include "type.h" +#include "mach.h" +#include "outbuf.h" +#include "filespec.h" +#include "cv4.h" +#include "cgcv.h" +#include "dt.h" + +#include "aa.h" +#include "tinfo.h" + +#if OMFOBJ + +#if MARS +#include "mars.h" +#endif + +#include "mscoff.h" + +static Outbuffer *fobjbuf; + +//regm_t BYTEREGS = BYTEREGS_INIT; +//regm_t ALLREGS = ALLREGS_INIT; + +static char __file__[] = __FILE__; // for tassert.h +#include "tassert.h" + +#define DEST_LEN (IDMAX + IDOHD + 1) +char *obj_mangle2(Symbol *s,char *dest); + +#if MARS +// C++ name mangling is handled by front end +#define cpp_mangle(s) ((s)->Sident) +#endif + + +/****************************************** + */ + +static long elf_align(targ_size_t size, long offset); + +// The object file is built ib several separate pieces + + +// String Table - String table for all other names +static Outbuffer *symtab_strings; + +// Section Headers +Outbuffer *SECbuf; // Buffer to build section table in +#define SecHdrTab ((struct scnhdr *)SECbuf->buf) + +// The relocation for text and data seems to get lost. +// Try matching the order gcc output them +// This means defining the sections and then removing them if they are +// not used. +static int section_cnt; // Number of sections in table +#define SEC_TAB_INIT 16 // Initial number of sections in buffer +#define SEC_TAB_INC 4 // Number of sections to increment buffer by + +#define SYM_TAB_INIT 100 // Initial number of symbol entries in buffer +#define SYM_TAB_INC 50 // Number of symbols to increment buffer by + +/* Three symbol tables, because the different types of symbols + * are grouped into 3 different types (and a 4th for comdef's). + */ + +static Outbuffer *local_symbuf; +static Outbuffer *public_symbuf; +static Outbuffer *extern_symbuf; + +struct Comdef { symbol *sym; targ_size_t size; int count; }; +static Outbuffer *comdef_symbuf; // Comdef's are stored here + +static Outbuffer *indirectsymbuf1; // indirect symbol table of Symbol*'s +static int jumpTableSeg; // segment index for __jump_table + +static Outbuffer *indirectsymbuf2; // indirect symbol table of Symbol*'s +static int pointersSeg; // segment index for __pointers + +/* If an MsCoffObj::external_def() happens, set this to the string index, + * to be added last to the symbol table. + * Obviously, there can be only one. + */ +static IDXSTR extdef; + +// Each compiler segment is a section +// Predefined compiler segments CODE,DATA,CDATA,UDATA map to indexes +// into SegData[] +// New compiler segments are added to end. + +/****************************** + * Returns !=0 if this segment is a code segment. + */ + +int seg_data::isCode() +{ + return (SecHdrTab[SDshtidx].s_flags & IMAGE_SCN_CNT_CODE) != 0; +} + + +seg_data **SegData; +int seg_count; +int seg_max; +int seg_tlsseg = UNKNOWN; +int seg_tlsseg_bss = UNKNOWN; + +/******************************************************* + * Because the mscoff relocations cannot be computed until after + * all the segments are written out, and we need more information + * than the mscoff relocations provide, make our own relocation + * type. Later, translate to mscoff relocation structure. + */ + +struct Relocation +{ // Relocations are attached to the struct seg_data they refer to + targ_size_t offset; // location in segment to be fixed up + symbol *funcsym; // function in which offset lies, if any + symbol *targsym; // if !=NULL, then location is to be fixed up + // to address of this symbol + unsigned targseg; // if !=0, then location is to be fixed up + // to address of start of this segment + unsigned char rtype; // RELxxxx +#define RELaddr 0 // straight address +#define RELrel 1 // relative to location to be fixed up + short val; // 0, -1, -2, -4 +}; + + +/******************************* + * Output a string into a string table + * Input: + * strtab = string table for entry + * str = string to add + * + * Returns index into the specified string table. + */ + +IDXSTR MsCoffObj::addstr(Outbuffer *strtab, const char *str) +{ + //printf("MsCoffObj::addstr(strtab = %p str = '%s')\n",strtab,str); + IDXSTR idx = strtab->size(); // remember starting offset + strtab->writeString(str); + //printf("\tidx %d, new size %d\n",idx,strtab->size()); + return idx; +} + +/******************************* + * Find a string in a string table + * Input: + * strtab = string table for entry + * str = string to find + * + * Returns index into the specified string table or 0. + */ + +static IDXSTR elf_findstr(Outbuffer *strtab, const char *str, const char *suffix) +{ + const char *ent = (char *)strtab->buf+1; + const char *pend = ent+strtab->size() - 1; + const char *s = str; + const char *sx = suffix; + int len = strlen(str); + + if (suffix) + len += strlen(suffix); + + while(ent < pend) + { + if(*ent == 0) // end of table entry + { + if(*s == 0 && !sx) // end of string - found a match + { + return ent - (const char *)strtab->buf - len; + } + else // table entry too short + { + s = str; // back to beginning of string + sx = suffix; + ent++; // start of next table entry + } + } + else if (*s == 0 && sx && *sx == *ent) + { // matched first string + s = sx+1; // switch to suffix + ent++; + sx = NULL; + } + else // continue comparing + { + if (*ent == *s) + { // Have a match going + ent++; + s++; + } + else // no match + { + while(*ent != 0) // skip to end of entry + ent++; + ent++; // start of next table entry + s = str; // back to beginning of string + sx = suffix; + } + } + } + return 0; // never found match +} + +/******************************* + * Output a mangled string into the symbol string table + * Input: + * str = string to add + * + * Returns index into the table. + */ + +static IDXSTR elf_addmangled(Symbol *s) +{ + //printf("elf_addmangled(%s)\n", s->Sident); + char dest[DEST_LEN]; + + IDXSTR namidx = symtab_strings->size(); + char *destr = obj_mangle2(s, dest); + const char *name = destr; + if (CPP && name[0] == '_' && name[1] == '_') + { + if (strncmp(name,"__ct__",6) == 0) + name += 4; +#if 0 + switch(name[2]) + { + case 'c': + if (strncmp(name,"__ct__",6) == 0) + name += 4; + break; + case 'd': + if (strcmp(name,"__dl__FvP") == 0) + name = "__builtin_delete"; + break; + case 'v': + //if (strcmp(name,"__vec_delete__FvPiUIPi") == 0) + //name = "__builtin_vec_del"; + //else + //if (strcmp(name,"__vn__FPUI") == 0) + //name = "__builtin_vec_new"; + break; + case 'n': + if (strcmp(name,"__nw__FPUI") == 0) + name = "__builtin_new"; + break; + } +#endif + } + else if (tyfunc(s->ty()) && s->Sfunc && s->Sfunc->Fredirect) + name = s->Sfunc->Fredirect; + size_t len = strlen(name); + symtab_strings->reserve(len+1); + strcpy((char *)symtab_strings->p,name); + symtab_strings->setsize(namidx+len+1); + if (destr != dest) // if we resized result + mem_free(destr); + //dbg_printf("\telf_addmagled symtab_strings %s namidx %d len %d size %d\n",name, namidx,len,symtab_strings->size()); + return namidx; +} + +/************************** + * Ouput read only data and generate a symbol for it. + * + */ + +symbol * MsCoffObj::sym_cdata(tym_t ty,char *p,int len) +{ + symbol *s; + +#if 0 + if (I64) + { + alignOffset(DATA, tysize(ty)); + s = symboldata(Doffset, ty); + SegData[DATA]->SDbuf->write(p,len); + s->Sseg = DATA; + s->Soffset = Doffset; // Remember its offset into DATA section + Doffset += len; + } + else +#endif + { + //printf("MsCoffObj::sym_cdata(ty = %x, p = %x, len = %d, CDoffset = %x)\n", ty, p, len, CDoffset); + alignOffset(CDATA, tysize(ty)); + s = symboldata(CDoffset, ty); + s->Sseg = CDATA; + //MsCoffObj::pubdef(CDATA, s, CDoffset); + MsCoffObj::bytes(CDATA, CDoffset, len, p); + } + + s->Sfl = FLextern; + return s; +} + +/************************** + * Ouput read only data for data + * + */ + +int MsCoffObj::data_readonly(char *p, int len, int *pseg) +{ + int oldoff; + if (I64) + { + oldoff = Doffset; + SegData[DATA]->SDbuf->reserve(len); + SegData[DATA]->SDbuf->writen(p,len); + Doffset += len; + *pseg = DATA; + } + else + { + oldoff = CDoffset; + SegData[CDATA]->SDbuf->reserve(len); + SegData[CDATA]->SDbuf->writen(p,len); + CDoffset += len; + *pseg = CDATA; + } + return oldoff; +} + +int MsCoffObj::data_readonly(char *p, int len) +{ + int pseg; + + return MsCoffObj::data_readonly(p, len, &pseg); +} + +/****************************** + * Perform initialization that applies to all .o output files. + * Called before any other obj_xxx routines + */ + +MsCoffObj *MsCoffObj::init(Outbuffer *objbuf, const char *filename, const char *csegname) +{ + //printf("MsCoffObj::init()\n"); + MsCoffObj *obj = new MsCoffObj(); + + cseg = CODE; + fobjbuf = objbuf; + + seg_tlsseg = UNKNOWN; + seg_tlsseg_bss = UNKNOWN; + + // Initialize buffers + + if (symtab_strings) + symtab_strings->setsize(1); + else + { symtab_strings = new Outbuffer(1024); + symtab_strings->reserve(2048); + symtab_strings->writeByte(0); + } + + if (!local_symbuf) + local_symbuf = new Outbuffer(sizeof(symbol *) * SYM_TAB_INIT); + local_symbuf->setsize(0); + + if (!public_symbuf) + public_symbuf = new Outbuffer(sizeof(symbol *) * SYM_TAB_INIT); + public_symbuf->setsize(0); + + if (!extern_symbuf) + extern_symbuf = new Outbuffer(sizeof(symbol *) * SYM_TAB_INIT); + extern_symbuf->setsize(0); + + if (!comdef_symbuf) + comdef_symbuf = new Outbuffer(sizeof(symbol *) * SYM_TAB_INIT); + comdef_symbuf->setsize(0); + + extdef = 0; + + if (indirectsymbuf1) + indirectsymbuf1->setsize(0); + jumpTableSeg = 0; + + if (indirectsymbuf2) + indirectsymbuf2->setsize(0); + pointersSeg = 0; + + // Initialize segments for CODE, DATA, UDATA and CDATA + size_t struct_section_size = sizeof(struct scnhdr); + if (SECbuf) + { + SECbuf->setsize(struct_section_size); + } + else + { + SECbuf = new Outbuffer(SYM_TAB_INC * struct_section_size); + SECbuf->reserve(SEC_TAB_INIT * struct_section_size); + // Ignore the first section - section numbers start at 1 + SECbuf->writezeros(struct_section_size); + } + section_cnt = 1; + + seg_count = 0; + int align = I64 ? IMAGE_SCN_ALIGN_16BYTES : IMAGE_SCN_ALIGN_8BYTES; + MsCoffObj::getsegment(".text", IMAGE_SCN_CNT_CODE | + align | + IMAGE_SCN_MEM_EXECUTE | + IMAGE_SCN_MEM_READ); // CODE + MsCoffObj::getsegment(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | + IMAGE_SCN_ALIGN_4BYTES | + IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE); // DATA + MsCoffObj::getsegment(".rdata", IMAGE_SCN_CNT_INITIALIZED_DATA | + IMAGE_SCN_ALIGN_4BYTES | + IMAGE_SCN_MEM_READ); // CDATA + MsCoffObj::getsegment(".bss", IMAGE_SCN_CNT_UNINITIALIZED_DATA | + IMAGE_SCN_ALIGN_4BYTES | + IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE); // UDATA + +// if (config.fulltypes) +// dwarf_initfile(filename); + return obj; +} + +/************************** + * Initialize the start of object output for this particular .o file. + * + * Input: + * filename: Name of source file + * csegname: User specified default code segment name + */ + +void MsCoffObj::initfile(const char *filename, const char *csegname, const char *modname) +{ + //dbg_printf("MsCoffObj::initfile(filename = %s, modname = %s)\n",filename,modname); +#if SCPP + if (csegname && *csegname && strcmp(csegname,".text")) + { // Define new section and make it the default for cseg segment + // NOTE: cseg is initialized to CODE + IDXSEC newsecidx; + Elf32_Shdr *newtextsec; + IDXSYM newsymidx; + assert(!I64); // fix later + SegData[cseg]->SDshtidx = newsecidx = + elf_newsection(csegname,0,SHT_PROGDEF,SHF_ALLOC|SHF_EXECINSTR); + newtextsec = &SecHdrTab[newsecidx]; + newtextsec->sh_addralign = 4; + SegData[cseg]->SDsymidx = + elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, newsecidx); + } +#endif +// if (config.fulltypes) +// dwarf_initmodule(filename, modname); +} + +/************************************ + * Patch pseg/offset by adding in the vmaddr difference from + * pseg/offset to start of seg. + */ + +int32_t *patchAddr(int seg, targ_size_t offset) +{ + return(int32_t *)(fobjbuf->buf + SecHdrTab[SegData[seg]->SDshtidx].s_scnptr + offset); +} + +int32_t *patchAddr64(int seg, targ_size_t offset) +{ + return(int32_t *)(fobjbuf->buf + SecHdrTab[SegData[seg]->SDshtidx].s_scnptr + offset); +} + +void patch(seg_data *pseg, targ_size_t offset, int seg, targ_size_t value) +{ + //printf("patch(offset = x%04x, seg = %d, value = x%llx)\n", (unsigned)offset, seg, value); + if (I64) + { + int32_t *p = (int32_t *)(fobjbuf->buf + SecHdrTab[pseg->SDshtidx].s_scnptr + offset); +#if 0 + printf("\taddr1 = x%llx\n\taddr2 = x%llx\n\t*p = x%llx\n\tdelta = x%llx\n", + SecHdrTab[pseg->SDshtidx].s_vaddr, + SecHdrTab[SegData[seg]->SDshtidx].s_vaddr, + *p, + SecHdrTab[SegData[seg]->SDshtidx].s_vaddr - + (SecHdrTab[pseg->SDshtidx].s_vaddr + offset)); +#endif + *p += SecHdrTab[SegData[seg]->SDshtidx].s_vaddr - + (SecHdrTab[pseg->SDshtidx].s_vaddr - value); + } + else + { + int32_t *p = (int32_t *)(fobjbuf->buf + SecHdrTab[pseg->SDshtidx].s_scnptr + offset); +#if 0 + printf("\taddr1 = x%x\n\taddr2 = x%x\n\t*p = x%x\n\tdelta = x%x\n", + SecHdrTab[pseg->SDshtidx].s_vaddr, + SecHdrTab[SegData[seg]->SDshtidx].s_vaddr, + *p, + SecHdrTab[SegData[seg]->SDshtidx].s_vaddr - + (SecHdrTab[pseg->SDshtidx].s_vaddr + offset)); +#endif + *p += SecHdrTab[SegData[seg]->SDshtidx].s_vaddr - + (SecHdrTab[pseg->SDshtidx].s_vaddr - value); + } +} + +/*************************** + * Number symbols so they are + * ordered as locals, public and then extern/comdef + */ + +void mach_numbersyms() +{ + //printf("mach_numbersyms()\n"); + int n = 0; + + int dim; + dim = local_symbuf->size() / sizeof(symbol *); + for (int i = 0; i < dim; i++) + { symbol *s = ((symbol **)local_symbuf->buf)[i]; + s->Sxtrnnum = n; + n++; + } + + dim = public_symbuf->size() / sizeof(symbol *); + for (int i = 0; i < dim; i++) + { symbol *s = ((symbol **)public_symbuf->buf)[i]; + s->Sxtrnnum = n; + n++; + } + + dim = extern_symbuf->size() / sizeof(symbol *); + for (int i = 0; i < dim; i++) + { symbol *s = ((symbol **)extern_symbuf->buf)[i]; + s->Sxtrnnum = n; + n++; + } + + dim = comdef_symbuf->size() / sizeof(Comdef); + for (int i = 0; i < dim; i++) + { Comdef *c = ((Comdef *)comdef_symbuf->buf) + i; + c->sym->Sxtrnnum = n; + n++; + } +} + + +/*************************** + * Fixup and terminate object file. + */ + +void MsCoffObj::termfile() +{ + //dbg_printf("MsCoffObj::termfile\n"); + if (configv.addlinenumbers) + { + //dwarf_termmodule(); + } +} + +/********************************* + * Terminate package. + */ + +void MsCoffObj::term() +{ + //printf("MsCoffObj::term()\n"); +#if SCPP + if (!errcnt) +#endif + { + outfixlist(); // backpatches + } + + if (configv.addlinenumbers) + { + //dwarf_termfile(); + } + +#if SCPP + if (errcnt) + return; +#endif + + /* Write out the object file in the following order: + * header + * commands + * segment_command + * { sections } + * symtab_command + * dysymtab_command + * { segment contents } + * { relocations } + * symbol table + * string table + * indirect symbol table + */ + + unsigned foffset; + unsigned headersize; + unsigned sizeofcmds; + + // Write out the bytes for the header + if (I64) + { + struct filehdr header; + + header.f_magic = IMAGE_FILE_MACHINE_AMD64; + header.f_nscns = section_cnt - 1; + header.f_timdat = 0; + header.f_symptr = 0; + header.f_nsyms = 0; + header.f_opthdr = 0; + header.f_flags = 0; + fobjbuf->write(&header, sizeof(header)); + + foffset = sizeof(header); // start after header + headersize = sizeof(header); +// sizeofcmds = header.sizeofcmds; + + // Write the actual data later +// fobjbuf->writezeros(header.sizeofcmds); +// foffset += header.sizeofcmds; + } + else + { + struct filehdr header; + + header.f_magic = IMAGE_FILE_MACHINE_I386; + header.f_nscns = section_cnt - 1; + header.f_timdat = 0; + header.f_symptr = 0; + header.f_nsyms = 0; + header.f_opthdr = 0; + header.f_flags = 0; + fobjbuf->write(&header, sizeof(header)); + + fobjbuf->write(&header, sizeof(header)); + foffset = sizeof(header); // start after header + headersize = sizeof(header); +// sizeofcmds = header.sizeofcmds; + + // Write the actual data later +// fobjbuf->writezeros(header.sizeofcmds); +// foffset += header.sizeofcmds; + } + + struct syment segment_cmd; + struct symtab_command symtab_cmd; + struct dysymtab_command dysymtab_cmd; + + memset(&segment_cmd, 0, sizeof(segment_cmd)); + memset(&symtab_cmd, 0, sizeof(symtab_cmd)); + memset(&dysymtab_cmd, 0, sizeof(dysymtab_cmd)); + +#if 0 + segment_cmd.cmd = LC_SEGMENT; + segment_cmd.cmdsize = sizeof(segment_cmd) + + (section_cnt - 1) * sizeof(struct section); + segment_cmd.nsects = section_cnt - 1; + segment_cmd.maxprot = 7; + segment_cmd.initprot = 7; + + symtab_cmd.cmd = LC_SYMTAB; + symtab_cmd.cmdsize = sizeof(symtab_cmd); + + dysymtab_cmd.cmd = LC_DYSYMTAB; + dysymtab_cmd.cmdsize = sizeof(dysymtab_cmd); + + /* If a __pointers section was emitted, need to set the .reserved1 + * field to the symbol index in the indirect symbol table of the + * start of the __pointers symbols. + */ + if (pointersSeg) + { + seg_data *pseg = SegData[pointersSeg]; + if (I64) + { + struct section_64 *psechdr = &SecHdrTab64[pseg->SDshtidx]; // corresponding section + psechdr->reserved1 = indirectsymbuf1 + ? indirectsymbuf1->size() / sizeof(Symbol *) + : 0; + } + else + { + struct section *psechdr = &SecHdrTab[pseg->SDshtidx]; // corresponding section + psechdr->reserved1 = indirectsymbuf1 + ? indirectsymbuf1->size() / sizeof(Symbol *) + : 0; + } + } + + // Walk through sections determining size and file offsets + + // + // First output individual section data associate with program + // code and data + // + foffset = elf_align(I64 ? 8 : 4, foffset); + segment_cmd.fileoff = foffset; + unsigned vmaddr = 0; + + //printf("Setup offsets and sizes foffset %d\n\tsection_cnt %d, seg_count %d\n",foffset,section_cnt,seg_count); + // Zero filled segments go at the end, so go through segments twice + for (int i = 0; i < 2; i++) + { + for (int seg = 1; seg <= seg_count; seg++) + { + seg_data *pseg = SegData[seg]; + if (I64) + { + struct section_64 *psechdr = &SecHdrTab64[pseg->SDshtidx]; // corresponding section + + // Do zero-fill the second time through this loop + if (i ^ (psechdr->flags == S_ZEROFILL)) + continue; + + int align = 1 << psechdr->align; + while (align < pseg->SDalignment) + { + psechdr->align += 1; + align <<= 1; + } + foffset = elf_align(align, foffset); + vmaddr = (vmaddr + align - 1) & ~(align - 1); + if (psechdr->flags == S_ZEROFILL) + { + psechdr->offset = 0; + psechdr->size = pseg->SDoffset; // accumulated size + } + else + { + psechdr->offset = foffset; + psechdr->size = 0; + //printf("\tsection name %s,", psechdr->sectname); + if (pseg->SDbuf && pseg->SDbuf->size()) + { + //printf("\tsize %d\n", pseg->SDbuf->size()); + psechdr->size = pseg->SDbuf->size(); + fobjbuf->write(pseg->SDbuf->buf, psechdr->size); + foffset += psechdr->size; + } + } + psechdr->addr = vmaddr; + vmaddr += psechdr->size; + //printf(" assigned offset %d, size %d\n", foffset, psechdr->sh_size); + } + else + { + struct section *psechdr = &SecHdrTab[pseg->SDshtidx]; // corresponding section + + // Do zero-fill the second time through this loop + if (i ^ (psechdr->flags == S_ZEROFILL)) + continue; + + int align = 1 << psechdr->align; + while (align < pseg->SDalignment) + { + psechdr->align += 1; + align <<= 1; + } + foffset = elf_align(align, foffset); + vmaddr = (vmaddr + align - 1) & ~(align - 1); + if (psechdr->flags == S_ZEROFILL) + { + psechdr->offset = 0; + psechdr->size = pseg->SDoffset; // accumulated size + } + else + { + psechdr->offset = foffset; + psechdr->size = 0; + //printf("\tsection name %s,", psechdr->sectname); + if (pseg->SDbuf && pseg->SDbuf->size()) + { + //printf("\tsize %d\n", pseg->SDbuf->size()); + psechdr->size = pseg->SDbuf->size(); + fobjbuf->write(pseg->SDbuf->buf, psechdr->size); + foffset += psechdr->size; + } + } + psechdr->addr = vmaddr; + vmaddr += psechdr->size; + //printf(" assigned offset %d, size %d\n", foffset, psechdr->sh_size); + } + } + } + + if (I64) + { + segment_cmd64.vmsize = vmaddr; + segment_cmd64.filesize = foffset - segment_cmd64.fileoff; + /* Bugzilla 5331: Apparently having the filesize field greater than the vmsize field is an + * error, and is happening sometimes. + */ + if (segment_cmd64.filesize > vmaddr) + segment_cmd64.vmsize = segment_cmd64.filesize; + } + else + { + segment_cmd.vmsize = vmaddr; + segment_cmd.filesize = foffset - segment_cmd.fileoff; + /* Bugzilla 5331: Apparently having the filesize field greater than the vmsize field is an + * error, and is happening sometimes. + */ + if (segment_cmd.filesize > vmaddr) + segment_cmd.vmsize = segment_cmd.filesize; + } + + // Put out relocation data + mach_numbersyms(); + for (int seg = 1; seg <= seg_count; seg++) + { + seg_data *pseg = SegData[seg]; + scnhdr *psechdr = &SecHdrTab[pseg->SDshtidx]; // corresponding section + //printf("psechdr->addr = x%x\n", psechdr->addr); + + foffset = elf_align(I64 ? 8 : 4, foffset); + unsigned reloff = foffset; + unsigned nreloc = 0; + if (pseg->SDrel) + { Relocation *r = (Relocation *)pseg->SDrel->buf; + Relocation *rend = (Relocation *)(pseg->SDrel->buf + pseg->SDrel->size()); + for (; r != rend; r++) + { symbol *s = r->targsym; + const char *rs = r->rtype == RELaddr ? "addr" : "rel"; + //printf("%d:x%04llx : tseg %d tsym %s REL%s\n", seg, r->offset, r->targseg, s ? s->Sident : "0", rs); + relocation_info rel; + scattered_relocation_info srel; + if (s) + { + //printf("Relocation\n"); + //symbol_print(s); + if (pseg->isCode()) + { + if (I64) + { + rel.r_type = (r->rtype == RELrel) + ? IMAGE_REL_AMD64_REL32 + : IMAGE_REL_AMD64_SREL32; + if (r->val == -1) + rel.r_type = IMAGE_REL_AMD64_SREL32_1; + else if (r->val == -2) + rel.r_type = IMAGE_REL_AMD64_SREL32_2; + if (r->val == -4) + rel.r_type = IMAGE_REL_AMD64_SREL32_4; + + if (s->Sclass == SCextern || + s->Sclass == SCcomdef || + s->Sclass == SCcomdat || + s->Sclass == SCglobal) + { + if ((s->Sfl == FLfunc || + s->Sfl == FLextern || + s->Sclass == SCglobal || + s->Sclass == SCcomdat || + s->Sclass == SCcomdef) && r->rtype == RELaddr) + rel.r_type = IMAGE_REL_AMD64_GOT_LOAD; + rel.r_address = r->offset; + rel.r_symbolnum = s->Sxtrnnum; + rel.r_pcrel = 1; + rel.r_length = 2; + rel.r_extern = 1; + fobjbuf->write(&rel, sizeof(rel)); + foffset += sizeof(rel); + nreloc++; + continue; + } + else + { + rel.r_address = r->offset; + rel.r_symbolnum = s->Sseg; + rel.r_pcrel = 1; + rel.r_length = 2; + rel.r_extern = 0; + fobjbuf->write(&rel, sizeof(rel)); + foffset += sizeof(rel); + nreloc++; + + int32_t *p = patchAddr64(seg, r->offset); + // Absolute address; add in addr of start of targ seg +//printf("*p = x%x, .s_vaddr = x%x, Soffset = x%x\n", *p, (int)SecHdrTab64[SegData[s->Sseg]->SDshtidx].s_vaddr, (int)s->Soffset); +//printf("pseg = x%x, r->offset = x%x\n", (int)SecHdrTab64[pseg->SDshtidx].s_vaddr, (int)r->offset); + *p += SecHdrTab64[SegData[s->Sseg]->SDshtidx].s_vaddr; + *p += s->Soffset; + *p -= SecHdrTab64[pseg->SDshtidx].s_vaddr + r->offset + 4; + //patch(pseg, r->offset, s->Sseg, s->Soffset); + continue; + } + } + } + else + { + if (s->Sclass == SCextern || + s->Sclass == SCcomdef || + s->Sclass == SCcomdat) + { + rel.r_address = r->offset; + rel.r_symbolnum = s->Sxtrnnum; + rel.r_pcrel = 0; + rel.r_length = 2; + rel.r_extern = 1; + rel.r_type = IMAGE_REL_I386_DIR32; + if (I64) + { + rel.r_type = IMAGE_REL_AMD64_ADDR32; + rel.r_length = 3; + } + fobjbuf->write(&rel, sizeof(rel)); + foffset += sizeof(rel); + nreloc++; + continue; + } + else + { + rel.r_address = r->offset; + rel.r_symbolnum = s->Sseg; + rel.r_pcrel = 0; + rel.r_length = 2; + rel.r_extern = 0; + rel.r_type = IMAGE_REL_I386_DIR32; + if (I64) + { + rel.r_type = IMAGE_REL_AMD64_ADDR32; + rel.r_length = 3; + if (0 && s->Sseg != seg) + rel.r_type = IMAGE_REL_AMD64_REL32; + } + fobjbuf->write(&rel, sizeof(rel)); + foffset += sizeof(rel); + nreloc++; + if (I64) + { + rel.r_length = 3; + int32_t *p = patchAddr64(seg, r->offset); + // Absolute address; add in addr of start of targ seg + *p += SecHdrTab64[SegData[s->Sseg]->SDshtidx].s_vaddr + s->Soffset; + //patch(pseg, r->offset, s->Sseg, s->Soffset); + } + else + { + int32_t *p = patchAddr(seg, r->offset); + // Absolute address; add in addr of start of targ seg + *p += SecHdrTab[SegData[s->Sseg]->SDshtidx].s_vaddr + s->Soffset; + //patch(pseg, r->offset, s->Sseg, s->Soffset); + } + continue; + } + } + } + else if (r->rtype == RELaddr && pseg->isCode()) + { + int32_t *p = NULL; + int32_t *p64 = NULL; + if (I64) + p64 = patchAddr64(seg, r->offset); + else + p = patchAddr(seg, r->offset); + srel.r_scattered = 1; + + srel.r_address = r->offset; + srel.r_length = 2; + if (I64) + { + srel.r_type = IMAGE_REL_AMD64_SSPAN32; + srel.r_value = SecHdrTab64[SegData[r->targseg]->SDshtidx].s_vaddr + *p64; + //printf("SECTDIFF: x%llx + x%llx = x%x\n", SecHdrTab[SegData[r->targseg]->SDshtidx].s_vaddr, *p, srel.r_value); + } + else + { + srel.r_type = IMAGE_REL_I386_SECREL; + srel.r_value = SecHdrTab[SegData[r->targseg]->SDshtidx].s_vaddr + *p; + //printf("SECTDIFF: x%x + x%x = x%x\n", SecHdrTab[SegData[r->targseg]->SDshtidx].s_vaddr, *p, srel.r_value); + } + srel.r_pcrel = 0; + fobjbuf->write(&srel, sizeof(srel)); + foffset += sizeof(srel); + nreloc++; + + srel.r_address = 0; + //srel.r_type = GENERIC_RELOC_PAIR; + srel.r_length = 2; + if (I64) + srel.r_value = SecHdrTab64[pseg->SDshtidx].s_vaddr + + r->funcsym->Slocalgotoffset + NPTRSIZE; + else + srel.r_value = SecHdrTab[pseg->SDshtidx].s_vaddr + + r->funcsym->Slocalgotoffset + NPTRSIZE; + srel.r_pcrel = 0; + fobjbuf->write(&srel, sizeof(srel)); + foffset += sizeof(srel); + nreloc++; + + // Recalc due to possible realloc of fobjbuf->buf + if (I64) + { + p64 = patchAddr64(seg, r->offset); + //printf("address = x%x, p64 = %p *p64 = x%llx\n", r->offset, p64, *p64); + *p64 += SecHdrTab64[SegData[r->targseg]->SDshtidx].s_vaddr - + (SecHdrTab64[pseg->SDshtidx].s_vaddr + r->funcsym->Slocalgotoffset + NPTRSIZE); + } + else + { + p = patchAddr(seg, r->offset); + //printf("address = x%x, p = %p *p = x%x\n", r->offset, p, *p); + *p += SecHdrTab[SegData[r->targseg]->SDshtidx].s_vaddr - + (SecHdrTab[pseg->SDshtidx].s_vaddr + r->funcsym->Slocalgotoffset + NPTRSIZE); + } + continue; + } + else + { + rel.r_address = r->offset; + rel.r_symbolnum = r->targseg; + rel.r_pcrel = (r->rtype == RELaddr) ? 0 : 1; + rel.r_length = 2; + rel.r_extern = 0; + rel.r_type = GENERIC_RELOC_VANILLA; + if (I64) + { + rel.r_type = IMAGE_REL_AMD64_SECREL; + rel.r_length = 3; + if (0 && r->targseg != seg) + rel.r_type = IMAGE_REL_AMD64_REL32; + } + fobjbuf->write(&rel, sizeof(rel)); + foffset += sizeof(rel); + nreloc++; + if (I64) + { + int32_t *p64 = patchAddr64(seg, r->offset); + //int64_t before = *p64; + if (rel.r_pcrel) + // Relative address + patch(pseg, r->offset, r->targseg, 0); + else + { // Absolute address; add in addr of start of targ seg +//printf("*p = x%x, targ.s_vaddr = x%x\n", *p64, (int)SecHdrTab64[SegData[r->targseg]->SDshtidx].s_vaddr); +//printf("pseg = x%x, r->offset = x%x\n", (int)SecHdrTab64[pseg->SDshtidx].s_vaddr, (int)r->offset); + *p64 += SecHdrTab64[SegData[r->targseg]->SDshtidx].s_vaddr; + //*p64 -= SecHdrTab64[pseg->SDshtidx].s_vaddr; + } + //printf("%d:x%04x before = x%04llx, after = x%04llx pcrel = %d\n", seg, r->offset, before, *p64, rel.r_pcrel); + } + else + { + int32_t *p = patchAddr(seg, r->offset); + //int32_t before = *p; + if (rel.r_pcrel) + // Relative address + patch(pseg, r->offset, r->targseg, 0); + else + // Absolute address; add in addr of start of targ seg + *p += SecHdrTab[SegData[r->targseg]->SDshtidx].s_vaddr; + //printf("%d:x%04x before = x%04x, after = x%04x pcrel = %d\n", seg, r->offset, before, *p, rel.r_pcrel); + } + continue; + } + } + } + if (nreloc) + { + if (I64) + { + psechdr64->reloff = reloff; + psechdr64->nreloc = nreloc; + } + else + { + psechdr->reloff = reloff; + psechdr->nreloc = nreloc; + } + } + } + + // Put out symbol table + foffset = elf_align(I64 ? 8 : 4, foffset); + symtab_cmd.symoff = foffset; + dysymtab_cmd.ilocalsym = 0; + dysymtab_cmd.nlocalsym = local_symbuf->size() / sizeof(symbol *); + dysymtab_cmd.iextdefsym = dysymtab_cmd.nlocalsym; + dysymtab_cmd.nextdefsym = public_symbuf->size() / sizeof(symbol *); + dysymtab_cmd.iundefsym = dysymtab_cmd.iextdefsym + dysymtab_cmd.nextdefsym; + int nexterns = extern_symbuf->size() / sizeof(symbol *); + int ncomdefs = comdef_symbuf->size() / sizeof(Comdef); + dysymtab_cmd.nundefsym = nexterns + ncomdefs; + symtab_cmd.nsyms = dysymtab_cmd.nlocalsym + + dysymtab_cmd.nextdefsym + + dysymtab_cmd.nundefsym; + fobjbuf->reserve(symtab_cmd.nsyms * sizeof(struct nlist)); + for (int i = 0; i < dysymtab_cmd.nlocalsym; i++) + { symbol *s = ((symbol **)local_symbuf->buf)[i]; + struct nlist sym; + sym.n_un.n_strx = elf_addmangled(s); + sym.n_type = N_SECT; + sym.n_desc = 0; + if (s->Sclass == SCcomdat) + sym.n_desc = N_WEAK_DEF; + sym.n_sect = s->Sseg; + sym.n_value = s->Soffset + SecHdrTab[SegData[s->Sseg]->SDshtidx].s_vaddr; + fobjbuf->write(&sym, sizeof(sym)); + } + for (int i = 0; i < dysymtab_cmd.nextdefsym; i++) + { symbol *s = ((symbol **)public_symbuf->buf)[i]; + + //printf("Writing public symbol %d:x%x %s\n", s->Sseg, s->Soffset, s->Sident); + struct nlist sym; + sym.n_un.n_strx = elf_addmangled(s); + sym.n_type = N_EXT | N_SECT; + sym.n_desc = 0; + if (s->Sclass == SCcomdat) + sym.n_desc = N_WEAK_DEF; + sym.n_sect = s->Sseg; + sym.n_value = s->Soffset + SecHdrTab[SegData[s->Sseg]->SDshtidx].s_vaddr; + fobjbuf->write(&sym, sizeof(sym)); + } + for (int i = 0; i < nexterns; i++) + { symbol *s = ((symbol **)extern_symbuf->buf)[i]; + struct nlist sym; + sym.n_un.n_strx = elf_addmangled(s); + sym.n_value = s->Soffset; + sym.n_type = N_EXT | N_UNDF; + sym.n_desc = tyfunc(s->ty()) ? REFERENCE_FLAG_UNDEFINED_LAZY + : REFERENCE_FLAG_UNDEFINED_NON_LAZY; + sym.n_sect = 0; + fobjbuf->write(&sym, sizeof(sym)); + } + for (int i = 0; i < ncomdefs; i++) + { Comdef *c = ((Comdef *)comdef_symbuf->buf) + i; + struct nlist sym; + sym.n_un.n_strx = elf_addmangled(c->sym); + sym.n_value = c->size * c->count; + sym.n_scnum = IMAGE_SYM_UNDEFINED; + sym.n_type = 0; + sym.n_sclass = IMAGE_SYM_CLASS_EXTERNAL; + sym.n_numaux = 0; + + fobjbuf->write(&sym, sizeof(sym)); + } + if (extdef) + { + struct nlist_64 sym; + sym.n_un.n_strx = extdef; + sym.n_value = 0; + sym.n_type = N_EXT | N_UNDF; + sym.n_desc = 0; + sym.n_sect = 0; + sym.n_numaux = 0; + + fobjbuf->write(&sym, sizeof(sym)); + symtab_cmd.nsyms++; + } + foffset += symtab_cmd.nsyms * sizeof(struct nlist); + + // Put out string table + foffset = elf_align(I64 ? 8 : 4, foffset); + symtab_cmd.stroff = foffset; + symtab_cmd.strsize = symtab_strings->size(); + fobjbuf->write(symtab_strings->buf, symtab_cmd.strsize); + foffset += symtab_cmd.strsize; + + // Put out indirectsym table, which is in two parts + foffset = elf_align(I64 ? 8 : 4, foffset); + dysymtab_cmd.indirectsymoff = foffset; + if (indirectsymbuf1) + { dysymtab_cmd.nindirectsyms += indirectsymbuf1->size() / sizeof(Symbol *); + for (int i = 0; i < dysymtab_cmd.nindirectsyms; i++) + { Symbol *s = ((Symbol **)indirectsymbuf1->buf)[i]; + fobjbuf->write32(s->Sxtrnnum); + } + } + if (indirectsymbuf2) + { int n = indirectsymbuf2->size() / sizeof(Symbol *); + dysymtab_cmd.nindirectsyms += n; + for (int i = 0; i < n; i++) + { Symbol *s = ((Symbol **)indirectsymbuf2->buf)[i]; + fobjbuf->write32(s->Sxtrnnum); + } + } + foffset += dysymtab_cmd.nindirectsyms * 4; + + /* The correct offsets are now determined, so + * rewind and fix the header. + */ + fobjbuf->position(headersize, sizeofcmds); + if (I64) + { + fobjbuf->write(&segment_cmd64, sizeof(segment_cmd64)); + fobjbuf->write(SECbuf->buf + sizeof(struct section_64), (section_cnt - 1) * sizeof(struct section_64)); + } + else + { + fobjbuf->write(&segment_cmd, sizeof(segment_cmd)); + fobjbuf->write(SECbuf->buf + sizeof(struct section), (section_cnt - 1) * sizeof(struct section)); + } + fobjbuf->write(&symtab_cmd, sizeof(symtab_cmd)); + fobjbuf->write(&dysymtab_cmd, sizeof(dysymtab_cmd)); + fobjbuf->position(foffset, 0); + fobjbuf->flush(); +#endif +} + +/***************************** + * Line number support. + */ + +/*************************** + * Record file and line number at segment and offset. + * The actual .debug_line segment is put out by dwarf_termfile(). + * Input: + * cseg current code segment + */ + +void MsCoffObj::linnum(Srcpos srcpos, targ_size_t offset) +{ + if (srcpos.Slinnum == 0) + return; + +#if 0 +#if MARS || SCPP + printf("MsCoffObj::linnum(cseg=%d, offset=x%lx) ", cseg, offset); +#endif + srcpos.print(""); +#endif + +#if MARS + if (!srcpos.Sfilename) + return; +#endif +#if SCPP + if (!srcpos.Sfilptr) + return; + sfile_debug(&srcpos_sfile(srcpos)); + Sfile *sf = *srcpos.Sfilptr; +#endif + + size_t i; + seg_data *seg = SegData[cseg]; + + // Find entry i in SDlinnum_data[] that corresponds to srcpos filename + for (i = 0; 1; i++) + { + if (i == seg->SDlinnum_count) + { // Create new entry + if (seg->SDlinnum_count == seg->SDlinnum_max) + { // Enlarge array + unsigned newmax = seg->SDlinnum_max * 2 + 1; + //printf("realloc %d\n", newmax * sizeof(linnum_data)); + seg->SDlinnum_data = (linnum_data *)mem_realloc( + seg->SDlinnum_data, newmax * sizeof(linnum_data)); + memset(seg->SDlinnum_data + seg->SDlinnum_max, 0, + (newmax - seg->SDlinnum_max) * sizeof(linnum_data)); + seg->SDlinnum_max = newmax; + } + seg->SDlinnum_count++; +#if MARS + seg->SDlinnum_data[i].filename = srcpos.Sfilename; +#endif +#if SCPP + seg->SDlinnum_data[i].filptr = sf; +#endif + break; + } +#if MARS + if (seg->SDlinnum_data[i].filename == srcpos.Sfilename) +#endif +#if SCPP + if (seg->SDlinnum_data[i].filptr == sf) +#endif + break; + } + + linnum_data *ld = &seg->SDlinnum_data[i]; +// printf("i = %d, ld = x%x\n", i, ld); + if (ld->linoff_count == ld->linoff_max) + { + if (!ld->linoff_max) + ld->linoff_max = 8; + ld->linoff_max *= 2; + ld->linoff = (unsigned (*)[2])mem_realloc(ld->linoff, ld->linoff_max * sizeof(unsigned) * 2); + } + ld->linoff[ld->linoff_count][0] = srcpos.Slinnum; + ld->linoff[ld->linoff_count][1] = offset; + ld->linoff_count++; +} + + +/******************************* + * Set start address + */ + +void MsCoffObj::startaddress(Symbol *s) +{ + //dbg_printf("MsCoffObj::startaddress(Symbol *%s)\n",s->Sident); + //obj.startaddress = s; +} + +/******************************* + * Output library name. + */ + +bool MsCoffObj::includelib(const char *name) +{ + //dbg_printf("MsCoffObj::includelib(name *%s)\n",name); + return false; +} + +/********************************** + * Do we allow zero sized objects? + */ + +bool MsCoffObj::allowZeroSize() +{ + return true; +} + +/************************** + * Embed string in executable. + */ + +void MsCoffObj::exestr(const char *p) +{ + //dbg_printf("MsCoffObj::exestr(char *%s)\n",p); +} + +/************************** + * Embed string in obj. + */ + +void MsCoffObj::user(const char *p) +{ + //dbg_printf("MsCoffObj::user(char *%s)\n",p); +} + +/******************************* + * Output a weak extern record. + */ + +void MsCoffObj::wkext(Symbol *s1,Symbol *s2) +{ + //dbg_printf("MsCoffObj::wkext(Symbol *%s,Symbol *s2)\n",s1->Sident,s2->Sident); +} + +/******************************* + * Output file name record. + * + * Currently assumes that obj_filename will not be called + * twice for the same file. + */ + +void obj_filename(const char *modname) +{ + //dbg_printf("obj_filename(char *%s)\n",modname); + // Not supported by mscoff +} + +/******************************* + * Embed compiler version in .obj file. + */ + +void MsCoffObj::compiler() +{ + //dbg_printf("MsCoffObj::compiler\n"); +} + +//#if NEWSTATICDTOR + +/************************************** + * Symbol is the function that calls the static constructors. + * Put a pointer to it into a special segment that the startup code + * looks at. + * Input: + * s static constructor function + * dtor !=0 if leave space for static destructor + * seg 1: user + * 2: lib + * 3: compiler + */ + +void MsCoffObj::staticctor(Symbol *s,int dtor,int none) +{ +#if 0 + IDXSEC seg; + Outbuffer *buf; + + //dbg_printf("MsCoffObj::staticctor(%s) offset %x\n",s->Sident,s->Soffset); + //symbol_print(s); + s->Sseg = seg = + MsCoffObj::getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, 4); + buf = SegData[seg]->SDbuf; + if (I64) + buf->write64(s->Soffset); + else + buf->write32(s->Soffset); + MsCoffObj::addrel(seg, SegData[seg]->SDoffset, s, RELaddr); + SegData[seg]->SDoffset = buf->size(); +#endif +} + +/************************************** + * Symbol is the function that calls the static destructors. + * Put a pointer to it into a special segment that the exit code + * looks at. + * Input: + * s static destructor function + */ + +void MsCoffObj::staticdtor(Symbol *s) +{ +#if 0 + IDXSEC seg; + Outbuffer *buf; + + //dbg_printf("MsCoffObj::staticdtor(%s) offset %x\n",s->Sident,s->Soffset); + //symbol_print(s); + seg = MsCoffObj::getsegment(".dtors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, 4); + buf = SegData[seg]->SDbuf; + if (I64) + buf->write64(s->Soffset); + else + buf->write32(s->Soffset); + MsCoffObj::addrel(seg, SegData[seg]->SDoffset, s, RELaddr); + SegData[seg]->SDoffset = buf->size(); +#endif +} + +//#else + +/*************************************** + * Stuff pointer to function in its own segment. + * Used for static ctor and dtor lists. + */ + +void MsCoffObj::funcptr(Symbol *s) +{ + //dbg_printf("MsCoffObj::funcptr(%s) \n",s->Sident); +} + +//#endif + +/*************************************** + * Stuff the following data (instance of struct FuncTable) in a separate segment: + * pointer to function + * pointer to ehsym + * length of function + */ + +void MsCoffObj::ehtables(Symbol *sfunc,targ_size_t size,Symbol *ehsym) +{ + //dbg_printf("MsCoffObj::ehtables(%s) \n",sfunc->Sident); + + /* BUG: this should go into a COMDAT if sfunc is in a COMDAT + * otherwise the duplicates aren't removed. + */ + + int align = I64 ? IMAGE_SCN_ALIGN_8BYTES : IMAGE_SCN_ALIGN_4BYTES; // align to NPTRSIZE + // The size is sizeof(struct FuncTable) in deh2.d + int seg = MsCoffObj::getsegment("._deh_eh", IMAGE_SCN_CNT_INITIALIZED_DATA | + align | + IMAGE_SCN_MEM_READ); + + Outbuffer *buf = SegData[seg]->SDbuf; + if (I64) + { MsCoffObj::reftoident(seg, buf->size(), sfunc, 0, CFoff | CFoffset64); + MsCoffObj::reftoident(seg, buf->size(), ehsym, 0, CFoff | CFoffset64); + buf->write64(sfunc->Ssize); + } + else + { MsCoffObj::reftoident(seg, buf->size(), sfunc, 0, CFoff); + MsCoffObj::reftoident(seg, buf->size(), ehsym, 0, CFoff); + buf->write32(sfunc->Ssize); + } +} + +/********************************************* + * Put out symbols that define the beginning/end of the .deh_eh section. + * This gets called if this is the module with "main()" in it. + */ + +void MsCoffObj::ehsections() +{ + //printf("MsCoffObj::ehsections()\n"); +#if 0 + /* Determine Mac OSX version, and put out the sections slightly differently for each. + * This is needed because the linker on OSX 10.5 behaves differently than + * the linker on 10.6. + * See Bugzilla 3502 for more information. + */ + static SInt32 MacVersion; + if (!MacVersion) + Gestalt(gestaltSystemVersion, &MacVersion); + + /* Exception handling sections + */ + // 12 is size of struct FuncTable in D runtime + MsCoffObj::getsegment("__deh_beg", "__DATA", 2, S_COALESCED, 12); + int seg = MsCoffObj::getsegment("__deh_eh", "__DATA", 2, S_REGULAR); + Outbuffer *buf = SegData[seg]->SDbuf; + buf->writezeros(12); // 12 is size of struct FuncTable in D runtime, + // this entry gets skipped over by __eh_finddata() + + MsCoffObj::getsegment("__deh_end", "__DATA", 2, S_COALESCED, 4); + + /* Thread local storage sections + */ + MsCoffObj::getsegment("__tls_beg", "__DATA", 2, S_COALESCED, 4); + MsCoffObj::getsegment("__tls_data", "__DATA", 2, S_REGULAR, 4); + MsCoffObj::getsegment("__tlscoal_nt", "__DATA", 4, S_COALESCED, 4); + MsCoffObj::getsegment("__tls_end", "__DATA", 2, S_COALESCED, 4); + + /* Module info sections + */ + MsCoffObj::getsegment("__minfo_beg", "__DATA", 2, S_COALESCED, 4); + MsCoffObj::getsegment("__minfodata", "__DATA", 2, S_REGULAR, 4); + MsCoffObj::getsegment("__minfo_end", "__DATA", 2, S_COALESCED, 4); +#endif +} + +/********************************* + * Setup for Symbol s to go into a COMDAT segment. + * Output (if s is a function): + * cseg segment index of new current code segment + * Coffset starting offset in cseg + * Returns: + * "segment index" of COMDAT + */ + +int MsCoffObj::comdatsize(Symbol *s, targ_size_t symsize) +{ + return MsCoffObj::comdat(s); +} + +int MsCoffObj::comdat(Symbol *s) +{ + unsigned align; + + //printf("MsCoffObj::comdat(Symbol* %s)\n",s->Sident); + //symbol_print(s); + symbol_debug(s); + + if (tyfunc(s->ty())) + { + align = I64 ? 16 : 4; + s->Sseg = MsCoffObj::getsegment(".text", IMAGE_SCN_CNT_CODE | + IMAGE_SCN_LNK_COMDAT | + (I64 ? IMAGE_SCN_ALIGN_16BYTES : IMAGE_SCN_ALIGN_4BYTES) | + IMAGE_SCN_MEM_EXECUTE | + IMAGE_SCN_MEM_READ); + } + else if ((s->ty() & mTYLINK) == mTYthread) + { + s->Sfl = FLtlsdata; + align = 16; + s->Sseg = MsCoffObj::getsegment(".tls$", IMAGE_SCN_CNT_INITIALIZED_DATA | + IMAGE_SCN_LNK_COMDAT | + IMAGE_SCN_ALIGN_16BYTES | + IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE); + MsCoffObj::data_start(s, align, s->Sseg); + } + else + { + s->Sfl = FLdata; + align = 16; + s->Sseg = MsCoffObj::getsegment(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | + IMAGE_SCN_LNK_COMDAT | + IMAGE_SCN_ALIGN_16BYTES | + IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE); + } + // find or create new segment + if (s->Salignment > align) + SegData[s->Sseg]->SDalignment = s->Salignment; + s->Soffset = SegData[s->Sseg]->SDoffset; + if (s->Sfl == FLdata || s->Sfl == FLtlsdata) + { // Code symbols are 'published' by MsCoffObj::func_start() + + MsCoffObj::pubdef(s->Sseg,s,s->Soffset); + searchfixlist(s); // backpatch any refs to this symbol + } + return s->Sseg; +} + +/********************************** + * Get segment. + * Input: + * flags2 put out some data for this, so the linker will keep things in order + * align segment alignment as power of 2 + * Returns: + * segment index of found or newly created segment + */ + +int MsCoffObj::getsegment(const char *sectname, unsigned long flags) +{ + assert(strlen(sectname) <= 16); + for (int seg = 1; seg <= seg_count; seg++) + { seg_data *pseg = SegData[seg]; + if (!(flags & IMAGE_SCN_LNK_COMDAT) && + strncmp(SecHdrTab[pseg->SDshtidx].s_name, sectname, 8) == 0) + return seg; // return existing segment + } + + int seg = ++seg_count; + if (seg_count >= seg_max) + { // need more room in segment table + seg_max += 10; + SegData = (seg_data **)mem_realloc(SegData,seg_max * sizeof(seg_data *)); + memset(&SegData[seg_count], 0, (seg_max - seg_count) * sizeof(seg_data *)); + } + assert(seg_count < seg_max); + if (SegData[seg]) + { seg_data *pseg = SegData[seg]; + Outbuffer *b1 = pseg->SDbuf; + Outbuffer *b2 = pseg->SDrel; + memset(pseg, 0, sizeof(seg_data)); + if (b1) + b1->setsize(0); + if (b2) + b2->setsize(0); + pseg->SDbuf = b1; + pseg->SDrel = b2; + } + else + { + seg_data *pseg = (seg_data *)mem_calloc(sizeof(seg_data)); + SegData[seg] = pseg; + if (!(flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA)) + { pseg->SDbuf = new Outbuffer(4096); + pseg->SDbuf->reserve(4096); + } + } + + //dbg_printf("\tNew segment - %d size %d\n", seg,SegData[seg]->SDbuf); + seg_data *pseg = SegData[seg]; + + pseg->SDseg = seg; + pseg->SDoffset = 0; + + struct scnhdr *sec = (struct scnhdr *) + SECbuf->writezeros(sizeof(struct section)); + strncpy(sec->s_name, sectname, 8); + sec->s_flags = flags; + + pseg->SDshtidx = section_cnt++; + pseg->SDaranges_offset = 0; + pseg->SDlinnum_count = 0; + + //printf("seg_count = %d\n", seg_count); + return seg; +} + +/******************************** + * Define a new code segment. + * Input: + * name name of segment, if NULL then revert to default + * suffix 0 use name as is + * 1 append "_TEXT" to name + * Output: + * cseg segment index of new current code segment + * Coffset starting offset in cseg + * Returns: + * segment index of newly created code segment + */ + +int MsCoffObj::codeseg(char *name,int suffix) +{ + //dbg_printf("MsCoffObj::codeseg(%s,%x)\n",name,suffix); + return 0; +} + +/********************************* + * Define segments for Thread Local Storage. + * Output: + * seg_tlsseg set to segment number for TLS segment. + * Returns: + * segment for TLS segment + */ + +seg_data *MsCoffObj::tlsseg() +{ + //printf("MsCoffObj::tlsseg(\n"); + + if (seg_tlsseg == UNKNOWN) + { + int align = I64 ? IMAGE_SCN_ALIGN_16BYTES : IMAGE_SCN_ALIGN_8BYTES; + seg_tlsseg = MsCoffObj::getsegment(".tls$", IMAGE_SCN_CNT_INITIALIZED_DATA | + align | + IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE); + } + return SegData[seg_tlsseg]; +} + + +/********************************* + * Define segments for Thread Local Storage. + * Output: + * seg_tlsseg_bss set to segment number for TLS segment. + * Returns: + * segment for TLS segment + */ + +seg_data *MsCoffObj::tlsseg_bss() +{ + /* No thread local bss for MS-COFF + */ + return MsCoffObj::tlsseg(); +} + + +/******************************* + * Output an alias definition record. + */ + +void MsCoffObj::alias(const char *n1,const char *n2) +{ + //printf("MsCoffObj::alias(%s,%s)\n",n1,n2); + assert(0); +#if NOT_DONE + unsigned len; + char *buffer; + + buffer = (char *) alloca(strlen(n1) + strlen(n2) + 2 * ONS_OHD); + len = obj_namestring(buffer,n1); + len += obj_namestring(buffer + len,n2); + objrecord(ALIAS,buffer,len); +#endif +} + +char *unsstr(unsigned value) +{ + static char buffer [64]; + + sprintf (buffer, "%d", value); + return buffer; +} + +/******************************* + * Mangle a name. + * Returns: + * mangled name + */ + +char *obj_mangle2(Symbol *s,char *dest) +{ + size_t len; + char *name; + + //printf("MsCoffObj::mangle(s = %p, '%s'), mangle = x%x\n",s,s->Sident,type_mangle(s->Stype)); + symbol_debug(s); + assert(dest); +#if SCPP + name = CPP ? cpp_mangle(s) : s->Sident; +#elif MARS + name = cpp_mangle(s); +#else + name = s->Sident; +#endif + len = strlen(name); // # of bytes in name + //dbg_printf("len %d\n",len); + switch (type_mangle(s->Stype)) + { + case mTYman_pas: // if upper case + case mTYman_for: + if (len >= DEST_LEN) + dest = (char *)mem_malloc(len + 1); + memcpy(dest,name,len + 1); // copy in name and ending 0 + strupr(dest); // to upper case + break; + case mTYman_std: +#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS + if (tyfunc(s->ty()) && !variadic(s->Stype)) +#else + if (!(config.flags4 & CFG4oldstdmangle) && + config.exe == EX_NT && tyfunc(s->ty()) && + !variadic(s->Stype)) +#endif + { + char *pstr = unsstr(type_paramsize(s->Stype)); + size_t pstrlen = strlen(pstr); + size_t destlen = len + 1 + pstrlen + 1; + + if (destlen > DEST_LEN) + dest = (char *)mem_malloc(destlen); + memcpy(dest,name,len); + dest[len] = '@'; + memcpy(dest + 1 + len, pstr, pstrlen + 1); + break; + } + case mTYman_cpp: + case mTYman_d: + case mTYman_sys: + case 0: + if (len >= DEST_LEN) + dest = (char *)mem_malloc(len + 1); + memcpy(dest,name,len+1);// copy in name and trailing 0 + break; + + case mTYman_c: + if (len >= DEST_LEN - 1) + dest = (char *)mem_malloc(1 + len + 1); + dest[0] = '_'; + memcpy(dest + 1,name,len+1);// copy in name and trailing 0 + break; + + + default: +#ifdef DEBUG + printf("mangling %x\n",type_mangle(s->Stype)); + symbol_print(s); +#endif + printf("%d\n", type_mangle(s->Stype)); + assert(0); + } + //dbg_printf("\t %s\n",dest); + return dest; +} + +/******************************* + * Export a function name. + */ + +void MsCoffObj::export_symbol(Symbol *s,unsigned argsize) +{ + //dbg_printf("MsCoffObj::export_symbol(%s,%d)\n",s->Sident,argsize); +} + +/******************************* + * Update data information about symbol + * align for output and assign segment + * if not already specified. + * + * Input: + * sdata data symbol + * datasize output size + * seg default seg if not known + * Returns: + * actual seg + */ + +int MsCoffObj::data_start(Symbol *sdata, targ_size_t datasize, int seg) +{ + targ_size_t alignbytes; + + //printf("MsCoffObj::data_start(%s,size %d,seg %d)\n",sdata->Sident,datasize,seg); + //symbol_print(sdata); + + assert(sdata->Sseg); + if (sdata->Sseg == UNKNOWN) // if we don't know then there + sdata->Sseg = seg; // wasn't any segment override + else + seg = sdata->Sseg; + targ_size_t offset = Offset(seg); + if (sdata->Salignment > 0) + { if (SegData[seg]->SDalignment < sdata->Salignment) + SegData[seg]->SDalignment = sdata->Salignment; + alignbytes = (offset + sdata->Salignment - 1) & ~(sdata->Salignment - 1); + } + else + alignbytes = align(datasize, offset) - offset; + if (alignbytes) + MsCoffObj::lidata(seg, offset, alignbytes); + sdata->Soffset = offset + alignbytes; + return seg; +} + +/******************************* + * Update function info before codgen + * + * If code for this function is in a different segment + * than the current default in cseg, switch cseg to new segment. + */ + +void MsCoffObj::func_start(Symbol *sfunc) +{ + //printf("MsCoffObj::func_start(%s)\n",sfunc->Sident); + symbol_debug(sfunc); + + assert(sfunc->Sseg); + if (sfunc->Sseg == UNKNOWN) + sfunc->Sseg = CODE; + //printf("sfunc->Sseg %d CODE %d cseg %d Coffset x%x\n",sfunc->Sseg,CODE,cseg,Coffset); + cseg = sfunc->Sseg; + assert(cseg == CODE || cseg > UDATA); + MsCoffObj::pubdef(cseg, sfunc, Coffset); + sfunc->Soffset = Coffset; + +// if (config.fulltypes) +// dwarf_func_start(sfunc); +} + +/******************************* + * Update function info after codgen + */ + +void MsCoffObj::func_term(Symbol *sfunc) +{ + //dbg_printf("MsCoffObj::func_term(%s) offset %x, Coffset %x symidx %d\n", +// sfunc->Sident, sfunc->Soffset,Coffset,sfunc->Sxtrnnum); + +#if 0 + // fill in the function size + if (I64) + SymbolTable64[sfunc->Sxtrnnum].st_size = Coffset - sfunc->Soffset; + else + SymbolTable[sfunc->Sxtrnnum].st_size = Coffset - sfunc->Soffset; +#endif +// if (config.fulltypes) +// dwarf_func_term(sfunc); +} + +/******************************** + * Output a public definition. + * Input: + * seg = segment index that symbol is defined in + * s -> symbol + * offset = offset of name within segment + */ + +void MsCoffObj::pubdef(int seg, Symbol *s, targ_size_t offset) +{ +#if 0 + printf("MsCoffObj::pubdef(%d:x%x s=%p, %s)\n", seg, offset, s, s->Sident); + //symbol_print(s); +#endif + symbol_debug(s); + + s->Soffset = offset; + s->Sseg = seg; + switch (s->Sclass) + { + case SCglobal: + case SCinline: + public_symbuf->write(&s, sizeof(s)); + break; + case SCcomdat: + case SCcomdef: + public_symbuf->write(&s, sizeof(s)); + break; + default: + local_symbuf->write(&s, sizeof(s)); + break; + } + //printf("%p\n", *(void**)public_symbuf->buf); + s->Sxtrnnum = 1; +} + +/******************************* + * Output an external symbol for name. + * Input: + * name Name to do EXTDEF on + * (Not to be mangled) + * Returns: + * Symbol table index of the definition + * NOTE: Numbers will not be linear. + */ + +int MsCoffObj::external(const char *name) +{ + //printf("MsCoffObj::external_def('%s')\n",name); + assert(name); + assert(extdef == 0); + extdef = MsCoffObj::addstr(symtab_strings, name); + return 0; +} + +int MsCoffObj::external_def(const char *name) +{ + return MsCoffObj::external(name); +} + +/******************************* + * Output an external for existing symbol. + * Input: + * s Symbol to do EXTDEF on + * (Name is to be mangled) + * Returns: + * Symbol table index of the definition + * NOTE: Numbers will not be linear. + */ + +int MsCoffObj::external(Symbol *s) +{ + //printf("MsCoffObj::external('%s') %x\n",s->Sident,s->Svalue); + symbol_debug(s); + extern_symbuf->write(&s, sizeof(s)); + s->Sxtrnnum = 1; + return 1; +} + +/******************************* + * Output a common block definition. + * Input: + * p -> external identifier + * size size in bytes of each elem + * count number of elems + * Returns: + * Symbol table index for symbol + */ + +int MsCoffObj::common_block(Symbol *s,targ_size_t size,targ_size_t count) +{ + //printf("MsCoffObj::common_block('%s', size=%d, count=%d)\n",s->Sident,size,count); + symbol_debug(s); + + // can't have code or thread local comdef's + assert(!(s->ty() & mTYthread)); + + struct Comdef comdef; + comdef.sym = s; + comdef.size = size; + comdef.count = count; + comdef_symbuf->write(&comdef, sizeof(comdef)); + s->Sxtrnnum = 1; + if (!s->Sseg) + s->Sseg = UDATA; + return 0; // should return void +} + +int MsCoffObj::common_block(Symbol *s, int flag, targ_size_t size, targ_size_t count) +{ + return MsCoffObj::common_block(s, size, count); +} + +/*************************************** + * Append an iterated data block of 0s. + * (uninitialized data only) + */ + +void MsCoffObj::write_zeros(seg_data *pseg, targ_size_t count) +{ + MsCoffObj::lidata(pseg->SDseg, pseg->SDoffset, count); +} + +/*************************************** + * Output an iterated data block of 0s. + * + * For boundary alignment and initialization + */ + +void MsCoffObj::lidata(int seg,targ_size_t offset,targ_size_t count) +{ + //printf("MsCoffObj::lidata(%d,%x,%d)\n",seg,offset,count); + size_t idx = SegData[seg]->SDshtidx; + if ((SecHdrTab[idx].s_flags) & IMAGE_SCN_CNT_UNINITIALIZED_DATA) + { // Use SDoffset to record size of bss section + SegData[seg]->SDoffset += count; + } + else + { + MsCoffObj::bytes(seg, offset, count, NULL); + } +} + +/*********************************** + * Append byte to segment. + */ + +void MsCoffObj::write_byte(seg_data *pseg, unsigned byte) +{ + MsCoffObj::byte(pseg->SDseg, pseg->SDoffset, byte); +} + +/************************************ + * Output byte to object file. + */ + +void MsCoffObj::byte(int seg,targ_size_t offset,unsigned byte) +{ + Outbuffer *buf = SegData[seg]->SDbuf; + int save = buf->size(); + //dbg_printf("MsCoffObj::byte(seg=%d, offset=x%lx, byte=x%x)\n",seg,offset,byte); + buf->setsize(offset); + buf->writeByte(byte); + if (save > offset+1) + buf->setsize(save); + else + SegData[seg]->SDoffset = offset+1; + //dbg_printf("\tsize now %d\n",buf->size()); +} + +/*********************************** + * Append bytes to segment. + */ + +void MsCoffObj::write_bytes(seg_data *pseg, unsigned nbytes, void *p) +{ + MsCoffObj::bytes(pseg->SDseg, pseg->SDoffset, nbytes, p); +} + +/************************************ + * Output bytes to object file. + * Returns: + * nbytes + */ + +unsigned MsCoffObj::bytes(int seg, targ_size_t offset, unsigned nbytes, void *p) +{ +#if 0 + if (!(seg >= 0 && seg <= seg_count)) + { printf("MsCoffObj::bytes: seg = %d, seg_count = %d\n", seg, seg_count); + *(char*)0=0; + } +#endif + assert(seg >= 0 && seg <= seg_count); + Outbuffer *buf = SegData[seg]->SDbuf; + if (buf == NULL) + { + //dbg_printf("MsCoffObj::bytes(seg=%d, offset=x%lx, nbytes=%d, p=x%x)\n", seg, offset, nbytes, p); + //raise(SIGSEGV); +if (!buf) halt(); + assert(buf != NULL); + } + int save = buf->size(); + //dbg_printf("MsCoffObj::bytes(seg=%d, offset=x%lx, nbytes=%d, p=x%x)\n", + //seg,offset,nbytes,p); + buf->setsize(offset); + buf->reserve(nbytes); + if (p) + { + buf->writen(p,nbytes); + } + else + { // Zero out the bytes + buf->clearn(nbytes); + } + if (save > offset+nbytes) + buf->setsize(save); + else + SegData[seg]->SDoffset = offset+nbytes; + return nbytes; +} + +/********************************************* + * Add a relocation entry for seg/offset. + */ + +void MsCoffObj::addrel(int seg, targ_size_t offset, symbol *targsym, + unsigned targseg, int rtype, int val) +{ + Relocation rel; + rel.offset = offset; + rel.targsym = targsym; + rel.targseg = targseg; + rel.rtype = rtype; + rel.funcsym = funcsym_p; + rel.val = val; + seg_data *pseg = SegData[seg]; + if (!pseg->SDrel) + pseg->SDrel = new Outbuffer(); + pseg->SDrel->write(&rel, sizeof(rel)); +} + +/**************************************** + * Sort the relocation entry buffer. + */ + +#if __DMC__ +static int __cdecl rel_fp(const void *e1, const void *e2) +{ Relocation *r1 = (Relocation *)e1; + Relocation *r2 = (Relocation *)e2; + + return r1->offset - r2->offset; +} +#else +extern "C" { +static int rel_fp(const void *e1, const void *e2) +{ Relocation *r1 = (Relocation *)e1; + Relocation *r2 = (Relocation *)e2; + + return r1->offset - r2->offset; +} +} +#endif + +void mach_relsort(Outbuffer *buf) +{ + qsort(buf->buf, buf->size() / sizeof(Relocation), sizeof(Relocation), &rel_fp); +} + +/******************************* + * Output a relocation entry for a segment + * Input: + * seg = where the address is going + * offset = offset within seg + * type = ELF relocation type + * index = Related symbol table index + * val = addend or displacement from address + */ + +void MsCoffObj::addrel(int seg, targ_size_t offset, unsigned type, + IDXSYM symidx, targ_size_t val) +{ +} + +/******************************* + * Refer to address that is in the data segment. + * Input: + * seg:offset = the address being fixed up + * val = displacement from start of target segment + * targetdatum = target segment number (DATA, CDATA or UDATA, etc.) + * flags = CFoff, CFseg + * Example: + * int *abc = &def[3]; + * to allocate storage: + * MsCoffObj::reftodatseg(DATA,offset,3 * sizeof(int *),UDATA); + */ + +void MsCoffObj::reftodatseg(int seg,targ_size_t offset,targ_size_t val, + unsigned targetdatum,int flags) +{ + Outbuffer *buf = SegData[seg]->SDbuf; + int save = buf->size(); + buf->setsize(offset); +#if 0 + printf("MsCoffObj::reftodatseg(seg:offset=%d:x%llx, val=x%llx, targetdatum %x, flags %x )\n", + seg,offset,val,targetdatum,flags); +#endif + assert(seg != 0); + if (SegData[seg]->isCode() && SegData[targetdatum]->isCode()) + { + assert(0); + } + MsCoffObj::addrel(seg, offset, NULL, targetdatum, RELaddr); + if (I64) + { + if (flags & CFoffset64) + { + buf->write64(val); + if (save > offset + 8) + buf->setsize(save); + return; + } + } + buf->write32(val); + if (save > offset + 4) + buf->setsize(save); +} + +/******************************* + * Refer to address that is in the current function code (funcsym_p). + * Only offsets are output, regardless of the memory model. + * Used to put values in switch address tables. + * Input: + * seg = where the address is going (CODE or DATA) + * offset = offset within seg + * val = displacement from start of this module + */ + +void MsCoffObj::reftocodeseg(int seg,targ_size_t offset,targ_size_t val) +{ + //printf("MsCoffObj::reftocodeseg(seg=%d, offset=x%lx, val=x%lx )\n",seg,(unsigned long)offset,(unsigned long)val); + assert(seg > 0); + Outbuffer *buf = SegData[seg]->SDbuf; + int save = buf->size(); + buf->setsize(offset); + val -= funcsym_p->Soffset; +// MsCoffObj::addrel(seg, offset, funcsym_p, 0, RELaddr); +// if (I64) +// buf->write64(val); +// else + buf->write32(val); + if (save > offset + 4) + buf->setsize(save); +} + +/******************************* + * Refer to an identifier. + * Input: + * seg = where the address is going (CODE or DATA) + * offset = offset within seg + * s -> Symbol table entry for identifier + * val = displacement from identifier + * flags = CFselfrel: self-relative + * CFseg: get segment + * CFoff: get offset + * CFpc32: [RIP] addressing, val is 0, -1, -2 or -4 + * CFoffset64: 8 byte offset for 64 bit builds + * Returns: + * number of bytes in reference (4 or 8) + */ + +int MsCoffObj::reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, + int flags) +{ + int retsize = (flags & CFoffset64) ? 8 : 4; +#if 0 + dbg_printf("\nMsCoffObj::reftoident('%s' seg %d, offset x%llx, val x%llx, flags x%x)\n", + s->Sident,seg,(unsigned long long)offset,(unsigned long long)val,flags); + printf("retsize = %d\n", retsize); + //dbg_printf("Sseg = %d, Sxtrnnum = %d\n",s->Sseg,s->Sxtrnnum); + symbol_print(s); +#endif + assert(seg > 0); + if (s->Sclass != SClocstat && !s->Sxtrnnum) + { // It may get defined later as public or local, so defer + addtofixlist(s, offset, seg, val, flags); + } + else + { + if (I64) + { + //if (s->Sclass != SCcomdat) + //val += s->Soffset; + int v = 0; + if (flags & CFpc32) + v = (int)val; + if (flags & CFselfrel) + { + MsCoffObj::addrel(seg, offset, s, 0, RELrel, v); + } + else + { + MsCoffObj::addrel(seg, offset, s, 0, RELaddr, v); + } + } + else + { + if (SegData[seg]->isCode() && flags & CFselfrel) + { +#if 0 + if (!jumpTableSeg) + { + jumpTableSeg = + MsCoffObj::getsegment("__jump_table", "__IMPORT", 0, S_SYMBOL_STUBS | S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE); + } +#endif + seg_data *pseg = SegData[jumpTableSeg]; +// SecHdrTab[pseg->SDshtidx].reserved2 = 5; + + if (!indirectsymbuf1) + indirectsymbuf1 = new Outbuffer(); + else + { // Look through indirectsym to see if it is already there + int n = indirectsymbuf1->size() / sizeof(Symbol *); + Symbol **psym = (Symbol **)indirectsymbuf1->buf; + for (int i = 0; i < n; i++) + { // Linear search, pretty pathetic + if (s == psym[i]) + { val = i * 5; + goto L1; + } + } + } + + val = pseg->SDbuf->size(); + static char halts[5] = { 0xF4,0xF4,0xF4,0xF4,0xF4 }; + pseg->SDbuf->write(halts, 5); + + // Add symbol s to indirectsymbuf1 + indirectsymbuf1->write(&s, sizeof(Symbol *)); + L1: + val -= offset + 4; + MsCoffObj::addrel(seg, offset, NULL, jumpTableSeg, RELrel); + } + else if (SegData[seg]->isCode() && + ((s->Sclass != SCextern && SegData[s->Sseg]->isCode()) || s->Sclass == SClocstat || s->Sclass == SCstatic)) + { + val += s->Soffset; + MsCoffObj::addrel(seg, offset, NULL, s->Sseg, RELaddr); + } + else if (SegData[seg]->isCode() && !tyfunc(s->ty())) + { + if (!pointersSeg) + { +// pointersSeg = +// MsCoffObj::getsegment("__pointers", "__IMPORT", 0, S_NON_LAZY_SYMBOL_POINTERS); + } + seg_data *pseg = SegData[pointersSeg]; + + if (!indirectsymbuf2) + indirectsymbuf2 = new Outbuffer(); + else + { // Look through indirectsym to see if it is already there + int n = indirectsymbuf2->size() / sizeof(Symbol *); + Symbol **psym = (Symbol **)indirectsymbuf2->buf; + for (int i = 0; i < n; i++) + { // Linear search, pretty pathetic + if (s == psym[i]) + { val = i * 4; + goto L2; + } + } + } + + val = pseg->SDbuf->size(); + pseg->SDbuf->writezeros(NPTRSIZE); + + // Add symbol s to indirectsymbuf2 + indirectsymbuf2->write(&s, sizeof(Symbol *)); + + L2: + //printf("MsCoffObj::reftoident: seg = %d, offset = x%x, s = %s, val = x%x, pointersSeg = %d\n", seg, offset, s->Sident, val, pointersSeg); + MsCoffObj::addrel(seg, offset, NULL, pointersSeg, RELaddr); + } + else + { //val -= s->Soffset; +// MsCoffObj::addrel(seg, offset, s, 0, RELaddr); + } + } + + Outbuffer *buf = SegData[seg]->SDbuf; + int save = buf->size(); + buf->setsize(offset); + //printf("offset = x%llx, val = x%llx\n", offset, val); + if (retsize == 8) + buf->write64(val); + else + buf->write32(val); + if (save > offset + retsize) + buf->setsize(save); + } + return retsize; +} + +/***************************************** + * Generate far16 thunk. + * Input: + * s Symbol to generate a thunk for + */ + +void MsCoffObj::far16thunk(Symbol *s) +{ + //dbg_printf("MsCoffObj::far16thunk('%s')\n", s->Sident); + assert(0); +} + +/************************************** + * Mark object file as using floating point. + */ + +void MsCoffObj::fltused() +{ + //dbg_printf("MsCoffObj::fltused()\n"); +} + + +long elf_align(targ_size_t size, long foffset) +{ + if (size <= 1) + return foffset; + long offset = (foffset + size - 1) & ~(size - 1); + if (offset > foffset) + fobjbuf->writezeros(offset - foffset); + return offset; +} + +/*************************************** + * Stuff pointer to ModuleInfo in its own segment. + */ + +#if MARS + +void MsCoffObj::moduleinfo(Symbol *scc) +{ + int align = I64 ? IMAGE_SCN_ALIGN_16BYTES : IMAGE_SCN_ALIGN_4BYTES; + + int seg = MsCoffObj::getsegment("._minfodata", IMAGE_SCN_CNT_INITIALIZED_DATA | + align | + IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE); + //printf("MsCoffObj::moduleinfo(%s) seg = %d:x%x\n", scc->Sident, seg, Offset(seg)); + + int flags = CFoff; + if (I64) + flags |= CFoffset64; + SegData[seg]->SDoffset += MsCoffObj::reftoident(seg, Offset(seg), scc, 0, flags); +} + +#endif + +/************************************* + */ + +#if 0 +void MsCoffObj::gotref(symbol *s) +{ + //printf("MsCoffObj::gotref(%x '%s', %d)\n",s,s->Sident, s->Sclass); + switch(s->Sclass) + { + case SCstatic: + case SClocstat: + s->Sfl = FLgotoff; + break; + + case SCextern: + case SCglobal: + case SCcomdat: + case SCcomdef: + s->Sfl = FLgot; + break; + + default: + break; + } +} +#endif + +#endif +#endif diff --git a/src/backend/obj.h b/src/backend/obj.h index 40007762d1f8..450c7108a858 100644 --- a/src/backend/obj.h +++ b/src/backend/obj.h @@ -18,9 +18,10 @@ struct seg_data; + struct Obj { - static void init(Outbuffer *, const char *filename, const char *csegname); + static Obj *init(Outbuffer *, const char *filename, const char *csegname); static void initfile(const char *filename, const char *csegname, const char *modname); static void termfile(); static void term(); @@ -109,4 +110,81 @@ struct MachObj : Obj unsigned targseg, int rtype, int val = 0); }; +struct MsCoffObj : Obj +{ + static MsCoffObj *init(Outbuffer *, const char *filename, const char *csegname); + static void initfile(const char *filename, const char *csegname, const char *modname); + static void termfile(); + static void term(); + + static size_t mangle(Symbol *s,char *dest); + static void import(elem *e); + static void linnum(Srcpos srcpos, targ_size_t offset); + static int codeseg(char *name,int suffix); + static void dosseg(void); + static void startaddress(Symbol *); + static bool includelib(const char *); + static bool allowZeroSize(); + static void exestr(const char *p); + static void user(const char *p); + static void compiler(); + static void wkext(Symbol *,Symbol *); + static void lzext(Symbol *,Symbol *); + static void alias(const char *n1,const char *n2); + static void theadr(const char *modname); + static void segment_group(targ_size_t codesize, targ_size_t datasize, targ_size_t cdatasize, targ_size_t udatasize); + static void staticctor(Symbol *s,int dtor,int seg); + static void staticdtor(Symbol *s); + static void funcptr(Symbol *s); + static void ehtables(Symbol *sfunc,targ_size_t size,Symbol *ehsym); + static void ehsections(); + static void moduleinfo(Symbol *scc); + static int comdat(Symbol *); + static int comdatsize(Symbol *, targ_size_t symsize); + static void setcodeseg(int seg); + static seg_data *tlsseg(); + static seg_data *tlsseg_bss(); + static int fardata(char *name, targ_size_t size, targ_size_t *poffset); + static void browse(char *, unsigned); + static void end(void); + static void export_symbol(Symbol *s, unsigned argsize); + static void pubdef(int seg, Symbol *s, targ_size_t offset); + static void pubdefsize(int seg, Symbol *s, targ_size_t offset, targ_size_t symsize); + static int external(const char *); + static int external_def(const char *); + static int data_start(Symbol *sdata, targ_size_t datasize, int seg); + static int external(Symbol *); + static int common_block(Symbol *s, targ_size_t size, targ_size_t count); + static int common_block(Symbol *s, int flag, targ_size_t size, targ_size_t count); + static void lidata(int seg, targ_size_t offset, targ_size_t count); + static void write_zeros(seg_data *pseg, targ_size_t count); + static void write_byte(seg_data *pseg, unsigned byte); + static void write_bytes(seg_data *pseg, unsigned nbytes, void *p); + static void byte(int seg, targ_size_t offset, unsigned byte); + static unsigned bytes(int seg, targ_size_t offset, unsigned nbytes, void *p); + static void ledata(int seg, targ_size_t offset, targ_size_t data, unsigned lcfd, unsigned idx1, unsigned idx2); + static void write_long(int seg, targ_size_t offset, unsigned long data, unsigned lcfd, unsigned idx1, unsigned idx2); + static void reftodatseg(int seg, targ_size_t offset, targ_size_t val, unsigned targetdatum, int flags); + static void reftofarseg(int seg, targ_size_t offset, targ_size_t val, int farseg, int flags); + static void reftocodeseg(int seg, targ_size_t offset, targ_size_t val); + static int reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, int flags); + static void far16thunk(Symbol *s); + static void fltused(); + static int data_readonly(char *p, int len, int *pseg); + static int data_readonly(char *p, int len); + static symbol *sym_cdata(tym_t, char *, int); + static unsigned addstr(Outbuffer *strtab, const char *); + static void func_start(Symbol *sfunc); + static void func_term(Symbol *sfunc); + + static int getsegment(const char *sectname, unsigned long flags); + + static void addrel(int seg, targ_size_t offset, symbol *targsym, + unsigned targseg, int rtype, int val); + static void addrel(int seg, targ_size_t offset, unsigned type, + unsigned symidx, targ_size_t val); +}; + +extern Obj *objmod; + #endif diff --git a/src/backend/out.c b/src/backend/out.c index e570d02d7f03..c8ac66bf1b8a 100644 --- a/src/backend/out.c +++ b/src/backend/out.c @@ -1221,13 +1221,7 @@ STATIC void writefunc2(symbol *sfunc) // generate new code segment } cod3_align(); // align start of function -#if ELFOBJ || MACHOBJ - Obj::func_start(sfunc); -#endif -#if OMFOBJ - sfunc->Sseg = cseg; // current code seg -#endif - sfunc->Soffset = Coffset; // offset of start of function + objmod->func_start(sfunc); searchfixlist(sfunc); // backpatch any refs to this function } @@ -1241,9 +1235,7 @@ STATIC void writefunc2(symbol *sfunc) #if SCPP PARSER = 1; #endif -#if ELFOBJ || MACHOBJ - Obj::func_term(sfunc); -#endif + objmod->func_term(sfunc); #if MARS /* This is to make uplevel references to SCfastpar variables * from nested functions work. diff --git a/src/backend/var.c b/src/backend/var.c index fb38064437f0..f6b1039d426a 100644 --- a/src/backend/var.c +++ b/src/backend/var.c @@ -234,3 +234,4 @@ const char *regstring[32] = {"AX","CX","DX","BX","SP","BP","SI","DI", type *chartype; /* default 'char' type */ +Obj *objmod = NULL; diff --git a/src/eh.c b/src/eh.c index 31923420f7f2..6f38232f420d 100644 --- a/src/eh.c +++ b/src/eh.c @@ -62,7 +62,7 @@ symbol *except_gentables() outdata(s); // output the scope table - Obj::ehtables(funcsym_p,funcsym_p->Ssize,s); + objmod->ehtables(funcsym_p,funcsym_p->Ssize,s); #endif return NULL; } diff --git a/src/glue.c b/src/glue.c index 30e6d098faff..f34d7585f97f 100644 --- a/src/glue.c +++ b/src/glue.c @@ -222,7 +222,13 @@ void obj_start(char *srcfile) slist_reset(); clearStringTab(); - Obj::init(&objbuf, srcfile, NULL); +#if TARGET_WINDOWS + // Produce Ms COFF files for 64 bit code, OMF for 32 bit code + objmod = I64 ? MsCoffObj::init(&objbuf, srcfile, NULL) + : Obj::init(&objbuf, srcfile, NULL); +#else + objmod = Obj::init(&objbuf, srcfile, NULL); +#endif el_reset(); #if TX86 @@ -233,7 +239,9 @@ void obj_start(char *srcfile) void obj_end(Library *library, File *objfile) { - Obj::term(); + objmod->term(); + delete objmod; + objmod = NULL; if (library) { @@ -262,12 +270,12 @@ void obj_end(Library *library, File *objfile) bool obj_includelib(const char *name) { - return Obj::includelib(name); + return objmod->includelib(name); } void obj_startaddress(Symbol *s) { - return Obj::startaddress(s); + return objmod->startaddress(s); } @@ -283,7 +291,7 @@ void Module::genobjfile(int multiobj) lastmname = srcfile->toChars(); - Obj::initfile(lastmname, NULL, toPrettyChars()); + objmod->initfile(lastmname, NULL, toPrettyChars()); eictor = NULL; ictorlocalgot = NULL; @@ -423,7 +431,7 @@ void Module::genobjfile(int multiobj) if (doppelganger) { - Obj::termfile(); + objmod->termfile(); return; } @@ -500,7 +508,7 @@ void Module::genobjfile(int multiobj) } } - Obj::termfile(); + objmod->termfile(); } @@ -622,37 +630,37 @@ void FuncDeclaration::toObjFile(int multiobj) // Pull in RTL startup code (but only once) if (func->isMain() && onlyOneMain(loc)) { - Obj::external_def("_main"); + objmod->external_def("_main"); #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS - Obj::ehsections(); // initialize exception handling sections + objmod->ehsections(); // initialize exception handling sections #endif #if TARGET_WINDOS - Obj::external_def("__acrtused_con"); + objmod->external_def("__acrtused_con"); #endif - Obj::includelib(libname); + objmod->includelib(libname); s->Sclass = SCglobal; } else if (strcmp(s->Sident, "main") == 0 && linkage == LINKc) { #if TARGET_WINDOS - Obj::external_def("__acrtused_con"); // bring in C startup code - Obj::includelib("snn.lib"); // bring in C runtime library + objmod->external_def("__acrtused_con"); // bring in C startup code + objmod->includelib("snn.lib"); // bring in C runtime library #endif s->Sclass = SCglobal; } #if TARGET_WINDOS else if (func->isWinMain() && onlyOneMain(loc)) { - Obj::external_def("__acrtused"); - Obj::includelib(libname); + objmod->external_def("__acrtused"); + objmod->includelib(libname); s->Sclass = SCglobal; } // Pull in RTL startup code else if (func->isDllMain() && onlyOneMain(loc)) { - Obj::external_def("__acrtused_dll"); - Obj::includelib(libname); + objmod->external_def("__acrtused_dll"); + objmod->includelib(libname); s->Sclass = SCglobal; } #endif @@ -969,7 +977,7 @@ void FuncDeclaration::toObjFile(int multiobj) writefunc(s); if (isExport()) - Obj::export_symbol(s, Poffset); + objmod->export_symbol(s, Poffset); for (size_t i = 0; i < irs.deferToObj->dim; i++) { @@ -1002,13 +1010,13 @@ void FuncDeclaration::toObjFile(int multiobj) #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS // A hack to get a pointer to this function put in the .dtors segment if (ident && memcmp(ident->toChars(), "_STD", 4) == 0) - Obj::staticdtor(s); + objmod->staticdtor(s); #endif #if DMDV2 if (irs.startaddress) { //printf("Setting start address\n"); - Obj::startaddress(irs.startaddress); + objmod->startaddress(irs.startaddress); } #endif } diff --git a/src/posix.mak b/src/posix.mak index 772c81a15790..bbacf7e42c40 100644 --- a/src/posix.mak +++ b/src/posix.mak @@ -84,11 +84,11 @@ DMD_OBJS = \ parse.o ph.o ptrntab.o root.o rtlsym.o s2ir.o scope.o statement.o \ stringtable.o struct.o csymbol.o template.o tk.o tocsym.o todt.o \ type.o typinf.o util.o var.o version.o strtold.o utf.o staticassert.o \ - toobj.o toctype.o toelfdebug.o entity.o doc.o macro.o \ + unialpha.o toobj.o toctype.o toelfdebug.o entity.o doc.o macro.o \ hdrgen.o delegatize.o aa.o ti_achar.o toir.o interpret.o traits.o \ - builtin.o clone.o aliasthis.o intrange.o \ + builtin.o clone.o aliasthis.o \ man.o arrayop.o port.o response.o async.o json.o speller.o aav.o unittests.o \ - imphint.o argtypes.o ti_pvoid.o apply.o canthrow.o sideeffect.o + imphint.o argtypes.o ti_pvoid.o apply.o sideeffect.o ifeq (OSX,$(TARGET)) DMD_OBJS += libmach.o machobj.o @@ -104,17 +104,16 @@ SRC = win32.mak posix.mak \ inifile.c iasm.c module.c scope.c dump.c init.h init.c attrib.h \ attrib.c opover.c class.c mangle.c tocsym.c func.c inline.c \ access.c complex_t.h irstate.h irstate.c glue.c msc.c ph.c tk.c \ - s2ir.c todt.c e2ir.c util.c identifier.h parse.h intrange.h \ + s2ir.c todt.c e2ir.c util.c identifier.h parse.h \ scope.h enum.h import.h mars.h module.h mtype.h dsymbol.h \ declaration.h lexer.h expression.h irstate.h statement.h eh.c \ - utf.h utf.c staticassert.h staticassert.c \ + utf.h utf.c staticassert.h staticassert.c unialpha.c \ typinf.c toobj.c toctype.c tocvdebug.c toelfdebug.c entity.c \ doc.h doc.c macro.h macro.c hdrgen.h hdrgen.c arraytypes.h \ delegatize.c toir.h toir.c interpret.c traits.c cppmangle.c \ builtin.c clone.c lib.h libomf.c libelf.c libmach.c arrayop.c \ aliasthis.h aliasthis.c json.h json.c unittests.c imphint.c \ - argtypes.c intrange.c apply.c canthrow.c sideeffect.c \ - scanmscoff.c \ + argtypes.c apply.c sideeffect.c \ $C/cdef.h $C/cc.h $C/oper.h $C/ty.h $C/optabgen.c \ $C/global.h $C/code.h $C/type.h $C/dt.h $C/cgcv.h \ $C/el.h $C/iasm.h $C/rtlsym.h $C/html.h \ @@ -126,12 +125,12 @@ SRC = win32.mak posix.mak \ $C/evalu8.c $C/go.c $C/gflow.c $C/gdag.c \ $C/gother.c $C/glocal.c $C/gloop.c $C/html.c $C/newman.c \ $C/nteh.c $C/os.c $C/out.c $C/outbuf.c $C/ptrntab.c $C/rtlsym.c \ - $C/type.c $C/melf.h $C/mach.h $C/mscoff.h $C/bcomplex.h \ + $C/type.c $C/melf.h $C/mach.h $C/bcomplex.h \ $C/cdeflnx.h $C/outbuf.h $C/token.h $C/tassert.h \ $C/elfobj.c $C/cv4.h $C/dwarf2.h $C/exh.h $C/go.h \ $C/dwarf.c $C/dwarf.h $C/aa.h $C/aa.c $C/tinfo.h $C/ti_achar.c \ $C/ti_pvoid.c \ - $C/machobj.c $C/mscoffobj.c \ + $C/machobj.c \ $C/xmm.h $C/obj.h \ $(TK)/filespec.h $(TK)/mem.h $(TK)/list.h $(TK)/vec.h \ $(TK)/filespec.c $(TK)/mem.c $(TK)/vec.c $(TK)/list.c \ @@ -226,9 +225,6 @@ blockopt.o: $C/blockopt.c builtin.o: builtin.c $(CC) -c $(CFLAGS) $< -canthrow.o: canthrow.c - $(CC) -c $(CFLAGS) $< - cast.o: cast.c $(CC) -c $(CFLAGS) $< @@ -392,7 +388,7 @@ html.o: $C/html.c $(CH) $C/html.h $(CC) -c $(MFLAGS) -I$(ROOT) $< iasm.o: iasm.c $(CH) $C/iasm.h - $(CC) -c $(MFLAGS) -I$(ROOT) -fexceptions $< + $(CC) -c $(MFLAGS) -I$(ROOT) $< id.o: id.c id.h $(CC) -c $(CFLAGS) $< @@ -421,9 +417,6 @@ inline.o: inline.c interpret.o: interpret.c $(CC) -c $(CFLAGS) $< -intrange.o: intrange.h intrange.c - $(CC) -c $(CFLAGS) intrange.c - json.o: json.c $(CC) -c $(CFLAGS) $< @@ -436,9 +429,6 @@ libelf.o: libelf.c $C/melf.h libmach.o: libmach.c $C/mach.h $(CC) -c $(CFLAGS) -I$C $< -libmscoff.o: libmscoff.c $C/mscoff.h - $(CC) -c $(CFLAGS) -I$C $< - link.o: link.c $(CC) -c $(CFLAGS) $< @@ -463,9 +453,6 @@ rmem.o: $(ROOT)/rmem.c module.o: module.c $C/html.h $(CC) -c $(CFLAGS) -I$C $< -mscoffobj.o: $C/mscoffobj.c $C/mscoff.h - $(CC) -c $(MFLAGS) $< - msc.o: msc.c $(CH) mars.h $(CC) -c $(MFLAGS) $< @@ -583,6 +570,9 @@ util.o: util.c utf.o: utf.c utf.h $(CC) -c $(CFLAGS) $< +unialpha.o: unialpha.c + $(CC) -c $(CFLAGS) $< + unittests.o: unittests.c $(CC) -c $(CFLAGS) $< @@ -601,7 +591,6 @@ gcov: gcov arrayop.c gcov attrib.c gcov builtin.c - gcov canthrow.c gcov cast.c gcov class.c gcov clone.c @@ -660,10 +649,10 @@ endif gcov toctype.c gcov toelfdebug.c gcov typinf.c + gcov unialpha.c gcov utf.c gcov util.c gcov version.c - gcov intrange.c # gcov hdrgen.c # gcov tocvdebug.c diff --git a/src/tocvdebug.c b/src/tocvdebug.c index 96aabe928a0e..a1f11240d506 100644 --- a/src/tocvdebug.c +++ b/src/tocvdebug.c @@ -249,7 +249,7 @@ void TypedefDeclaration::toDebug() TOWORD(debsym,length - 2); assert(length <= 40 + len); - Obj::write_bytes(SegData[DEBSYM],length,debsym); + objmod->write_bytes(SegData[DEBSYM],length,debsym); } } @@ -277,7 +277,7 @@ void EnumDeclaration::toDebug() TOWORD(debsym,length - 2); assert(length <= 40 + len); - Obj::write_bytes(SegData[DEBSYM],length,debsym); + objmod->write_bytes(SegData[DEBSYM],length,debsym); } } @@ -429,7 +429,7 @@ void StructDeclaration::toDebug() TOWORD(debsym,length - 2); assert(length <= 40 + len); - Obj::write_bytes(SegData[DEBSYM],length,debsym); + objmod->write_bytes(SegData[DEBSYM],length,debsym); // return typidx; } @@ -611,7 +611,7 @@ void ClassDeclaration::toDebug() TOWORD(debsym,length - 2); assert(length <= 40 + len); - Obj::write_bytes(SegData[DEBSYM],length,debsym); + objmod->write_bytes(SegData[DEBSYM],length,debsym); // return typidx; } diff --git a/src/toobj.c b/src/toobj.c index d0d6a1c64886..79d2c768866a 100644 --- a/src/toobj.c +++ b/src/toobj.c @@ -318,7 +318,7 @@ void Module::genmoduleinfo() ////////////////////////////////////////////// - Obj::moduleinfo(msym); + objmod->moduleinfo(msym); } /* ================================================================== */ @@ -771,7 +771,7 @@ void ClassDeclaration::toObjFile(int multiobj) // ClassInfo cannot be const data, because we use the monitor on it outdata(csym); if (isExport()) - Obj::export_symbol(csym,0); + objmod->export_symbol(csym,0); ////////////////////////////////////////////// @@ -834,7 +834,7 @@ void ClassDeclaration::toObjFile(int multiobj) out_readonly(vtblsym); outdata(vtblsym); if (isExport()) - Obj::export_symbol(vtblsym,0); + objmod->export_symbol(vtblsym,0); } /****************************************** @@ -1075,7 +1075,7 @@ void InterfaceDeclaration::toObjFile(int multiobj) out_readonly(csym); outdata(csym); if (isExport()) - Obj::export_symbol(csym,0); + objmod->export_symbol(csym,0); } /* ================================================================== */ @@ -1264,11 +1264,11 @@ void VarDeclaration::toObjFile(int multiobj) if (!sz && type->toBasetype()->ty != Tsarray) assert(0); // this shouldn't be possible - if (sz || Obj::allowZeroSize()) + if (sz || objmod->allowZeroSize()) { outdata(s); if (isExport()) - Obj::export_symbol(s,0); + objmod->export_symbol(s,0); } } } diff --git a/src/typinf.c b/src/typinf.c index 81a85ccc9f74..7d835b8746ce 100644 --- a/src/typinf.c +++ b/src/typinf.c @@ -816,7 +816,7 @@ void TypeInfoDeclaration::toObjFile(int multiobj) outdata(s); if (isExport()) - Obj::export_symbol(s,0); + objmod->export_symbol(s,0); } #endif diff --git a/src/win32.mak b/src/win32.mak index 6af6c4bffc3d..65cfe6a9cfc9 100644 --- a/src/win32.mak +++ b/src/win32.mak @@ -1,162 +1,95 @@ #_ win32.mak -# -# Copyright (c) 1999-2012 by Digital Mars +# Copyright (C) 1999-2011 by Digital Mars, http://www.digitalmars.com +# Written by Walter Bright # 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. -# -# Dependencies: -# -# Digital Mars C++ toolset -# http://www.digitalmars.com/download/freecompiler.html -# -# win32.mak (this file) - requires Digital Mars Make ($DM_HOME\dm\bin\make.exe) -# http://www.digitalmars.com/ctg/make.html -# -# $(CC) - requires Digital Mars C++ Compiler ($DM_HOME\dm\bin\dmc.exe) +# Build dmd with Digital Mars C++ compiler # http://www.digitalmars.com/ctg/sc.html -# -# cppunit target - requires STLport 4.5.3 ($DM_HOME\dm\stlport\stlport) -# http://www.digitalmars.com/download/freecompiler.html -# -# detab, tolf, install targets - require the D Language Tools (detab.exe, tolf.exe) -# https://github.com/D-Programming-Language/tools. -# -# install target - requires Phobos (.\phobos.lib) -# https://github.com/D-Programming-Language/phobos -# -# zip target - requires Info-ZIP or equivalent (zip32.exe) -# http://www.info-zip.org/Zip.html#Downloads -# -# Configuration: -# -# The easiest and recommended way to configure this makefile is to set DM_HOME -# in your environment to the location where DMC is installed (the parent of -# \dm and/or \dmd). By default, the install target will place the build -# targets under $DM_HOME\dmd2. -# -# Custom CFLAGS may be set in the User configuration section, along with custom -# LFLAGS. The difference between CFLAGS and OPT is that CFLAGS primarily -# applies to front-end files, while OPT applies to essentially all C++ sources. -# -# Pre-compiled headers may be enabled via the PREC variable. This configuration -# has not been tested recently. If you enable pre-compiled headers, you should -# update the TOTALH variable as mentioned in the accompanying comment. -# -# Targets: -# -# defaulttarget - debug dmd -# release - release dmd (with clean) -# trace - release dmd with tracing options enabled -# dmdtest - compiler unit tests -# clean - delete all generated files except target binary -# install - copy build targets to install directory -# install-clean - delete all files in the install directory -# zip - create ZIP archive of source code -# -# dmd - release dmd (legacy target) -# debdmd - debug dmd -# reldmd - release dmd -# detab - replace hard tabs with spaces -# tolf - convert to Unix line endings -# cppunit - cppunit library - -############################### Configuration ################################ - -##### Directories - -# DMC directory -DMCROOT=$(DM_HOME)\dm -# STLPort directory -STLPORT=$(DMCROOT)\stlport\stlport -# DMD source directories -C=backend -TK=tk -ROOT=root -# CPPUnit directory -CPPUNIT=cppunit-1.12.1 -# Include directories -INCLUDE=$(ROOT);$(DMCROOT)\include -# Install directory -INSTALL=..\install - -##### Tools +# This makefile is designed to be used with Digital Mars make.exe +# http://www.digitalmars.com/ctg/make.html +# which should be in \dm\bin or in \dmd\windows\bin -# C++ compiler +D= +#DMDSVN=\svnproj\dmd\trunk\src +DMDSVN=\svnproj\dmd\branches\dmd-1.x\src +SCROOT=$D\dm +INCLUDE=$(SCROOT)\include CC=dmc -# Make program -MAKE=make -# Librarian -LIB=lib -# Delete file(s) -DEL=del -# Make directory -MD=mkdir -# Remove directory -RD=rmdir -# File copy +LIBNT=$(SCROOT)\lib +SNN=$(SCROOT)\lib\snn +DIR=\dmd1 CP=cp -# De-tabify -DETAB=detab -# Convert line endings to Unix -TOLF=tolf -# Zip -ZIP=zip32 -##### User configuration switches +C=backend +TK=tk +ROOT=root + +MAKE=make -fwin32.mak C=$C TK=$(TK) ROOT=$(ROOT) -# Target name TARGET=dmd -TARGETEXE=$(TARGET).exe -# Custom compile flags -CFLAGS= -# Custom compile flags for all modules +XFLG= +MODEL=n OPT= -# Custom compile flags for compiler unit tests -TFLAGS= -# Debug flags DEBUG=-gl -D -DUNITTEST -# Precompiled Header support -# To enable, use: PREC=-H -HItotal.h -HO +#PREC=-H -HItotal.h -HO PREC= -# Linker flags (prefix with -L) LFLAGS= -# Librarian flags -BFLAGS= -##### Implementation variables (do not modify) +LINKN=$(SCROOT)\bin\link /de -# Compile flags -CFLAGS=-I$(INCLUDE) $(OPT) $(CFLAGS) $(DEBUG) -cpp -# Compile flags for modules with backend/toolkit dependencies +CFLAGS=-I$(ROOT);$(INCLUDE) $(XFLG) $(OPT) $(DEBUG) -cpp MFLAGS=-I$C;$(TK) $(OPT) -DMARS -cpp $(DEBUG) -e -wx -# Compile flags for compiler unit tests -TFLAGS=-I$(STLPORT);$(CPPUNIT)\include;$(INCLUDE) $(TFLAGS) -DDISABLE_MAIN=1 -cpp -Aa -Ab -Ae -Ar -# Recursive make -DMDMAKE=$(MAKE) -fwin32.mak C=$C TK=$(TK) ROOT=$(ROOT) -############################### Rule Variables ############################### +# Makerules: +.c.obj: + $(CC) -c $(CFLAGS) $(PREC) $* + +.asm.obj: + $(CC) -c $(CFLAGS) $* + +defaulttarget: debdmd + +################ RELEASES ######################### + +release: + $(MAKE) clean + $(MAKE) dmd + $(MAKE) clean + +################ NT COMMAND LINE RELEASE ######################### + +trace: + $(MAKE) OPT=-o "DEBUG=-gt -Nc" LFLAGS=-L/ma/co/delexe dmd.exe + +dmd: + $(MAKE) OPT=-o "DEBUG=" LFLAGS=-L/delexe dmd.exe +# $(MAKE) OPT=-o "DEBUG=" LFLAGS=-L/ma/co/delexe dmd.exe + +################ NT COMMAND LINE DEBUG ######################### + +debdmd: + $(MAKE) OPT= "DEBUG=-D -g -DUNITTEST" LFLAGS=-L/ma/co dmd.exe + +######################################### # D front end + OBJ1= mars.obj enum.obj struct.obj dsymbol.obj import.obj id.obj \ staticassert.obj identifier.obj mtype.obj expression.obj \ optimize.obj template.obj lexer.obj declaration.obj cast.obj \ - init.obj func.obj utf.obj parse.obj statement.obj \ + init.obj func.obj utf.obj unialpha.obj parse.obj statement.obj \ constfold.obj version.obj inifile.obj typinf.obj \ module.obj scope.obj dump.obj cond.obj inline.obj opover.obj \ entity.obj class.obj mangle.obj attrib.obj impcnvtab.obj \ link.obj access.obj doc.obj macro.obj hdrgen.obj delegatize.obj \ - interpret.obj traits.obj aliasthis.obj intrange.obj \ + interpret.obj traits.obj aliasthis.obj \ builtin.obj clone.obj libomf.obj arrayop.obj irstate.obj \ glue.obj msc.obj ph.obj tk.obj s2ir.obj todt.obj e2ir.obj tocsym.obj \ util.obj eh.obj toobj.obj toctype.obj tocvdebug.obj toir.obj \ - json.obj unittests.obj imphint.obj argtypes.obj apply.obj canthrow.obj \ - sideeffect.obj libmscoff.obj scanmscoff.obj + json.obj unittests.obj imphint.obj argtypes.obj apply.obj \ + sideeffect.obj + +# from C/C++ compiler optimizer and back end -# D back end OBJ8= go.obj gdag.obj gother.obj gflow.obj gloop.obj var.obj el.obj \ newman.obj glocal.obj os.obj nteh.obj evalu8.obj cgcs.obj \ rtlsym.obj html.obj cgelem.obj cgen.obj cgreg.obj out.obj \ @@ -164,20 +97,19 @@ OBJ8= go.obj gdag.obj gother.obj gflow.obj gloop.obj var.obj el.obj \ debug.obj code.obj cg87.obj cgxmm.obj cgsched.obj ee.obj csymbol.obj \ cgcod.obj cod1.obj cod2.obj cod3.obj cod4.obj cod5.obj outbuf.obj \ bcomplex.obj iasm.obj ptrntab.obj aa.obj ti_achar.obj md5.obj \ - ti_pvoid.obj mscoffobj.obj + ti_pvoid.obj + +# from ROOT -# Root package GCOBJS=rmem.obj -# Removed garbage collector (look in history) #GCOBJS=dmgcmem.obj bits.obj win32.obj gc.obj + ROOTOBJS= array.obj gnuc.obj man.obj root.obj port.obj \ stringtable.obj response.obj async.obj speller.obj aav.obj \ $(GCOBJS) -# All objects OBJS= $(OBJ1) $(OBJ8) $(ROOTOBJS) -# D front end SRCS= mars.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c utf.h \ utf.c entity.c identifier.c mtype.c expression.c optimize.c \ template.h template.c lexer.c declaration.c cast.c \ @@ -185,18 +117,19 @@ SRCS= mars.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c utf.h \ constfold.c version.h version.c inifile.c iasm.c staticassert.c \ module.c scope.c dump.c init.h init.c attrib.h attrib.c opover.c \ eh.c toctype.c class.c mangle.c tocsym.c func.c inline.c \ - access.c complex_t.h irstate.h irstate.c glue.c msc.c \ + access.c complex_t.h unialpha.c irstate.h irstate.c glue.c msc.c \ ph.c tk.c s2ir.c todt.c e2ir.c util.c toobj.c cppmangle.c \ - identifier.h parse.h scope.h enum.h import.h intrange.h \ + identifier.h parse.h scope.h enum.h import.h \ typinf.c tocvdebug.c toelfdebug.c mars.h module.h mtype.h dsymbol.h \ declaration.h lexer.h expression.h statement.h doc.h doc.c \ macro.h macro.c hdrgen.h hdrgen.c arraytypes.h \ delegatize.c toir.h toir.c interpret.c traits.c builtin.c \ - clone.c lib.h libomf.c libelf.c libmach.c arrayop.c intrange.c \ + clone.c lib.h libomf.c libelf.c libmach.c arrayop.c \ aliasthis.h aliasthis.c json.h json.c unittests.c imphint.c argtypes.c \ - apply.c canthrow.c sideeffect.c libmscoff.c scanmscoff.c + apply.c sideeffect.c + +# From C++ compiler -# D back end BACKSRC= $C\cdef.h $C\cc.h $C\oper.h $C\ty.h $C\optabgen.c \ $C\global.h $C\code.h $C\type.h $C\dt.h $C\cgcv.h \ $C\el.h $C\iasm.h $C\rtlsym.h $C\html.h \ @@ -208,21 +141,24 @@ BACKSRC= $C\cdef.h $C\cc.h $C\oper.h $C\ty.h $C\optabgen.c \ $C\evalu8.c $C\go.c $C\gflow.c $C\gdag.c \ $C\gother.c $C\glocal.c $C\gloop.c $C\html.c $C\newman.c \ $C\nteh.c $C\os.c $C\out.c $C\outbuf.c $C\ptrntab.c $C\rtlsym.c \ - $C\type.c $C\melf.h $C\mach.h $C\mscoff.h $C\bcomplex.h \ + $C\type.c $C\melf.h $C\mach.h $C\bcomplex.h \ $C\cdeflnx.h $C\outbuf.h $C\token.h $C\tassert.h \ $C\elfobj.c $C\cv4.h $C\dwarf2.h $C\exh.h $C\go.h \ $C\dwarf.c $C\dwarf.h $C\cppman.c $C\machobj.c \ $C\strtold.c $C\aa.h $C\aa.c $C\tinfo.h $C\ti_achar.c \ $C\md5.h $C\md5.c $C\ti_pvoid.c $C\xmm.h \ - $C\mscoffobj.c $C\obj.h \ + $C\obj.h \ $C\backend.txt -# Toolkit +# From TK + TKSRC= $(TK)\filespec.h $(TK)\mem.h $(TK)\list.h $(TK)\vec.h \ $(TK)\filespec.c $(TK)\mem.c $(TK)\vec.c $(TK)\list.c -# Root package -ROOTSRC= $(ROOT)\root.h $(ROOT)\root.c $(ROOT)\array.c \ +# From root + +ROOTSRC= \ + $(ROOT)\root.h $(ROOT)\root.c $(ROOT)\array.c \ $(ROOT)\rmem.h $(ROOT)\rmem.c $(ROOT)\port.h \ $(ROOT)\stringtable.h $(ROOT)\stringtable.c \ $(ROOT)\gnuc.h $(ROOT)\gnuc.c $(ROOT)\man.c $(ROOT)\port.c \ @@ -231,118 +167,36 @@ ROOTSRC= $(ROOT)\root.h $(ROOT)\root.c $(ROOT)\array.c \ $(ROOT)\aav.h $(ROOT)\aav.c \ $(ROOT)\longdouble.h $(ROOT)\longdouble.c \ $(ROOT)\dmgcmem.c -# Removed garbage collector bits (look in history) # $(ROOT)\gc\bits.c $(ROOT)\gc\gc.c $(ROOT)\gc\gc.h $(ROOT)\gc\mscbitops.h \ # $(ROOT)\gc\bits.h $(ROOT)\gc\gccbitops.h $(ROOT)\gc\linux.c $(ROOT)\gc\os.h \ # $(ROOT)\gc\win32.c -# Header files -#TOTALH=total.sym # Use with pre-compiled headers -TOTALH=id.h -CH= $C\cc.h $C\global.h $C\oper.h $C\code.h $C\type.h $C\dt.h $C\cgcv.h \ - $C\el.h $C\iasm.h $C\obj.h - -# Makefiles MAKEFILES=win32.mak posix.mak -# Unit tests -TESTS=UTFTest.exe # LexerTest.exe - -############################## Release Targets ############################### - -defaulttarget: debdmd - -dmd: reldmd - -release: - $(DMDMAKE) clean - $(DMDMAKE) reldmd - $(DMDMAKE) clean - -debdmd: - $(DMDMAKE) "OPT=" "DEBUG=-D -g -DUNITTEST" "LFLAGS=-L/ma/co" $(TARGETEXE) - -reldmd: - $(DMDMAKE) "OPT=-o" "DEBUG=" "LFLAGS=-L/delexe" $(TARGETEXE) - -trace: - $(DMDMAKE) "OPT=-o" "DEBUG=-gt -Nc" "LFLAGS=-L/ma/co/delexe" $(TARGETEXE) - -$(TARGETEXE): $(OBJS) win32.mak - $(CC) -o$(TARGETEXE) $(OBJS) -cpp -mn -Ar $(LFLAGS) - -################################ Unit Tests ################################## - -cppunit: $(CPPUNIT)\lib\cppunit.lib - -$(CPPUNIT)\lib\cppunit.lib: - cd $(CPPUNIT)\src\cppunit - $(MAKE) CC=$(CC) LIB=$(LIB) "TFLAGS=$(TFLAGS)" "BFLAGS=$(BFLAGS)" - cd ..\..\.. +######################################### -dmdtest: cppunit $(TESTS) +$(TARGET).exe : $(OBJS) win32.mak + dmc -o$(TARGET).exe $(OBJS) -cpp -mn -Ar $(LFLAGS) -UTFTest.exe: test\UTFTest.cpp utf.obj - $(CC) -o $@ $(TFLAGS) test\UTFTest.cpp utf.obj $(CPPUNIT)\lib\cppunit.lib -# TODO: Work in progress! -#LexerTest.exe: test\LexerTest.cpp $(OBJS) -# $(CC) -o $@ $(TFLAGS) test\LexerTest.cpp $(OBJS) $(CPPUNIT)\lib\cppunit.lib +##################### INCLUDE MACROS ##################### -############################ Maintenance Targets ############################# +CCH= +#TOTALH=$(CCH) total.sym +TOTALH=$(CCH) id.h +CH= $C\cc.h $C\global.h $C\oper.h $C\code.h $C\type.h $C\dt.h $C\cgcv.h $C\el.h $C\iasm.h $C\obj.h -clean: - $(DEL) *.obj - $(DEL) total.sym - $(DEL) msgs.h msgs.c - $(DEL) elxxx.c cdxxx.c optab.c debtab.c fltables.c tytab.c - $(DEL) impcnvtab.c - cd $(CPPUNIT)\src\cppunit - $(MAKE) clean - -install: detab install-copy - -install-copy: - $(MD) $(INSTALL)\windows\bin - $(MD) $(INSTALL)\windows\lib - $(MD) $(INSTALL)\src\dmd\root - $(MD) $(INSTALL)\src\dmd\tk - $(MD) $(INSTALL)\src\dmd\backend - $(CP) $(TARGETEXE) $(INSTALL)\windows\bin\$(TARGETEXE) - $(CP) phobos\phobos.lib $(INSTALL)\windows\lib\phobos.lib - $(CP) $(SRCS) $(INSTALL)\src\dmd - $(CP) $(ROOTSRC) $(INSTALL)\src\dmd\root - $(CP) $(TKSRC) $(INSTALL)\src\dmd\tk - $(CP) $(BACKSRC) $(INSTALL)\src\dmd\backend - $(CP) $(MAKEFILES) $(INSTALL)\src\dmd - $(CP) gpl.txt $(INSTALL)\src\dmd\gpl.txt - $(CP) readme.txt $(INSTALL)\src\dmd\readme.txt - $(CP) artistic.txt $(INSTALL)\src\dmd\artistic.txt - $(CP) backendlicense.txt $(INSTALL)\src\dmd\backendlicense.txt - -install-clean: - $(DEL) /s/q $(INSTALL)\* - $(RD) /s/q $(INSTALL) - -detab: - $(DETAB) $(SRCS) $(ROOTSRC) $(TKSRC) $(BACKSRC) - -tolf: - $(TOLF) $(SRCS) $(ROOTSRC) $(TKSRC) $(BACKSRC) $(MAKEFILES) +##################### GENERATED SOURCE ##################### -zip: detab tolf $(MAKEFILES) - $(DEL) dmdsrc.zip - $(ZIP) dmdsrc $(MAKEFILES) - $(ZIP) dmdsrc $(SRCS) - $(ZIP) dmdsrc $(BACKSRC) - $(ZIP) dmdsrc $(TKSRC) - $(ZIP) dmdsrc $(ROOTSRC) +msgs.h msgs.c sj1041.msg sj1036.msg sj1031.msg : msgsx.exe + msgsx -############################## Generated Source ############################## +msgsx.exe : msgsx.c + dmc msgsx -mn -D$(TARGET) $(DEFINES) $(WINLIBS) elxxx.c cdxxx.c optab.c debtab.c fltables.c tytab.c : \ $C\cdef.h $C\cc.h $C\oper.h $C\ty.h $C\optabgen.c - $(CC) -cpp -ooptabgen.exe $C\optabgen -DMARS -I$(TK) + dmc -cpp -ooptabgen.exe $C\optabgen -DMARS -I$(TK) $(WINLIBS) #-L$(LINKS) optabgen impcnvtab.c : impcnvgen.c @@ -350,33 +204,23 @@ impcnvtab.c : impcnvgen.c impcnvgen id.h id.c : idgen.c - $(CC) -cpp idgen + dmc -cpp idgen idgen -############################# Intermediate Rules ############################ - -# Default rules -.c.obj: - $(CC) -c $(CFLAGS) $(PREC) $* +##################### SPECIAL BUILDS ##################### -.asm.obj: - $(CC) -c $(CFLAGS) $* - -# Pre-compiled header total.sym : $(ROOT)\root.h mars.h lexer.h parse.h enum.h dsymbol.h \ mtype.h expression.h attrib.h init.h cond.h version.h \ declaration.h statement.h scope.h import.h module.h id.h \ template.h aggregate.h arraytypes.h lib.h total.h $(CC) -c $(CFLAGS) -HFtotal.sym total.h -# Generated source impcnvtab.obj : mtype.h impcnvtab.c $(CC) -c -I$(ROOT) -cpp impcnvtab iasm.obj : $(CH) $(TOTALH) $C\iasm.h iasm.c - $(CC) -c $(MFLAGS) -I$(ROOT) -Ae iasm + $(CC) -c $(MFLAGS) -I$(ROOT) iasm -# D front/back end bcomplex.obj : $C\bcomplex.c $(CC) -c $(MFLAGS) $C\bcomplex @@ -500,9 +344,6 @@ module.obj : $(TOTALH) $C\html.h module.c msc.obj : $(CH) mars.h msc.c $(CC) -c $(MFLAGS) -I$(ROOT) msc -mscoffobj.obj : $C\mscoff.h $C\mscoffobj.c - $(CC) -c $(MFLAGS) $C\mscoffobj - newman.obj : $(CH) $C\newman.c $(CC) -c $(MFLAGS) $C\newman @@ -527,9 +368,6 @@ ptrntab.obj : $C\iasm.h $C\ptrntab.c rtlsym.obj : $C\rtlsym.h $C\rtlsym.c $(CC) -c $(MFLAGS) $C\rtlsym -scanmscoff.obj : $(TOTALH) $C\mscoff.h scanmscoff.c - $(CC) -c $(CFLAGS) -I.;$(ROOT);$C scanmscoff.c - ti_achar.obj : $C\tinfo.h $C\ti_achar.c $(CC) -c $(MFLAGS) -I. $C\ti_achar @@ -579,7 +417,8 @@ var.obj : $C\var.c optab.c tk.obj : tk.c $(CC) -c $(MFLAGS) tk.c -# Root +# ROOT + aav.obj : $(ROOT)\aav.h $(ROOT)\aav.c $(CC) -c $(CFLAGS) $(ROOT)\aav.c @@ -616,7 +455,7 @@ speller.obj : $(ROOT)\speller.h $(ROOT)\speller.c stringtable.obj : $(ROOT)\stringtable.c $(CC) -c $(CFLAGS) $(ROOT)\stringtable.c -# Root/GC -- Removed (look in history) +# ROOT/GC # #bits.obj : $(ROOT)\gc\bits.h $(ROOT)\gc\bits.c # $(CC) -c $(CFLAGS) -I$(ROOT)\gc $(ROOT)\gc\bits.c @@ -627,18 +466,16 @@ stringtable.obj : $(ROOT)\stringtable.c #win32.obj : $(ROOT)\gc\os.h $(ROOT)\gc\win32.c # $(CC) -c $(CFLAGS) -I$(ROOT)\gc $(ROOT)\gc\win32.c -############################## Generated Rules ############################### -# These rules were generated by makedep, but are not currently maintained +################# Source file dependencies ############### access.obj : $(TOTALH) enum.h aggregate.h init.h attrib.h access.c aliasthis.obj : $(TOTALH) aliasthis.h aliasthis.c apply.obj : $(TOTALH) apply.c argtypes.obj : $(TOTALH) mtype.h argtypes.c arrayop.obj : $(TOTALH) identifier.h declaration.h arrayop.c -attrib.obj : $(TOTALH) dsymbol.h identifier.h declaration.h attrib.h attrib.c +attrib.obj : $(TOTALH) identifier.h declaration.h attrib.h attrib.c builtin.obj : $(TOTALH) builtin.c -canthrow.obj : $(TOTALH) canthrow.c cast.obj : $(TOTALH) expression.h mtype.h cast.c class.obj : $(TOTALH) enum.h class.c clone.obj : $(TOTALH) clone.c @@ -647,7 +484,7 @@ cond.obj : $(TOTALH) identifier.h declaration.h cond.h cond.c declaration.obj : $(TOTALH) identifier.h attrib.h declaration.h declaration.c expression.h delegatize.obj : $(TOTALH) delegatize.c doc.obj : $(TOTALH) doc.h doc.c -enum.obj : $(TOTALH) dsymbol.h identifier.h enum.h enum.c +enum.obj : $(TOTALH) identifier.h enum.h enum.c expression.obj : $(TOTALH) expression.h expression.c func.obj : $(TOTALH) identifier.h attrib.h declaration.h func.c hdrgen.obj : $(TOTALH) hdrgen.h hdrgen.c @@ -658,14 +495,13 @@ inifile.obj : $(TOTALH) inifile.c init.obj : $(TOTALH) init.h init.c inline.obj : $(TOTALH) inline.c interpret.obj : $(TOTALH) interpret.c declaration.h expression.h -intrange.obj : $(TOTALH) intrange.h intrange.c json.obj : $(TOTALH) json.h json.c lexer.obj : $(TOTALH) lexer.c -libmscoff.obj : $(TOTALH) lib.h libmscoff.c libomf.obj : $(TOTALH) lib.h libomf.c link.obj : $(TOTALH) link.c macro.obj : $(TOTALH) macro.h macro.c mangle.obj : $(TOTALH) dsymbol.h declaration.h mangle.c +#module.obj : $(TOTALH) mars.h $C\html.h module.h module.c opover.obj : $(TOTALH) expression.h opover.c optimize.obj : $(TOTALH) expression.h optimize.c parse.obj : $(TOTALH) attrib.h lexer.h parse.h parse.c @@ -677,6 +513,66 @@ struct.obj : $(TOTALH) identifier.h enum.h struct.c traits.obj : $(TOTALH) traits.c dsymbol.obj : $(TOTALH) identifier.h dsymbol.h dsymbol.c mtype.obj : $(TOTALH) mtype.h mtype.c +#typinf.obj : $(TOTALH) mtype.h typinf.c utf.obj : utf.h utf.c template.obj : $(TOTALH) template.h template.c version.obj : $(TOTALH) identifier.h dsymbol.h cond.h version.h version.c + +################### Utilities ################ + +clean: + del *.obj + del total.sym + del msgs.h msgs.c + del elxxx.c cdxxx.c optab.c debtab.c fltables.c tytab.c + del impcnvtab.c + +zip : detab tolf $(MAKEFILES) + del dmdsrc.zip + zip32 dmdsrc $(MAKEFILES) + zip32 dmdsrc $(SRCS) + zip32 dmdsrc $(BACKSRC) + zip32 dmdsrc $(TKSRC) + zip32 dmdsrc $(ROOTSRC) + +################### Detab ################ + +detab: + detab $(SRCS) $(ROOTSRC) $(TKSRC) $(BACKSRC) + +tolf: + tolf $(SRCS) $(ROOTSRC) $(TKSRC) $(BACKSRC) $(MAKEFILES) + +################### Install ################ + +install: detab install2 + +install2: + copy dmd.exe $(DIR)\windows\bin\ + copy phobos\phobos.lib $(DIR)\windows\lib + $(CP) $(SRCS) $(DIR)\src\dmd\ + $(CP) $(ROOTSRC) $(DIR)\src\dmd\root\ + $(CP) $(TKSRC) $(DIR)\src\dmd\tk\ + $(CP) $(BACKSRC) $(DIR)\src\dmd\backend\ + $(CP) $(MAKEFILES) $(DIR)\src\dmd\ + copy gpl.txt $(DIR)\src\dmd\ + copy readme.txt $(DIR)\src\dmd\ + copy artistic.txt $(DIR)\src\dmd\ + copy backendlicense.txt $(DIR)\src\dmd\ + +################### Write to SVN ################ + +svn: detab tolf svn2 + +svn2: + $(CP) $(SRCS) $(DMDSVN)\ + $(CP) $(ROOTSRC) $(DMDSVN)\root\ + $(CP) $(TKSRC) $(DMDSVN)\tk\ + $(CP) $(BACKSRC) $(DMDSVN)\backend\ + $(CP) $(MAKEFILES) $(DMDSVN)\ + copy gpl.txt $(DMDSVN)\ + copy readme.txt $(DMDSVN)\ + copy artistic.txt $(DMDSVN)\ + copy backendlicense.txt $(DMDSVN)\ + +###################################