Skip to content

Commit

Permalink
support alignment in static data
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Jul 6, 2012
1 parent b934254 commit 77e6c75
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 88 deletions.
2 changes: 1 addition & 1 deletion src/backend/cc.h
Expand Up @@ -1084,7 +1084,7 @@ struct Symbol
Symbol *Sl,*Sr; // left, right child
Symbol *Snext; // next in threaded list
dt_t *Sdt; // variables: initializer
int alignment; // variables: alignment, 0 or -1 means default alignment
int Salignment; // variables: alignment, 0 or -1 means default alignment
type *Stype; // type of Symbol
#define ty() Stype->Tty

Expand Down
3 changes: 3 additions & 0 deletions src/backend/cgcod.c
Expand Up @@ -604,6 +604,9 @@ void stackoffsets(int flags)
)
alignsize = sz;

if (s->Salignment > 0)
alignsize = s->Salignment;

//printf("symbol '%s', size = x%lx, align = %d, read = %x\n",s->Sident,(long)sz, (int)alignsize, s->Sflags & SFLread);
assert((int)sz >= 0);

Expand Down
18 changes: 12 additions & 6 deletions src/backend/cgobj.c
Expand Up @@ -761,7 +761,7 @@ void obj_term()
obj_theadr(obj.modname);
objheader(obj.csegname);
mem_free(obj.csegname);
objseggrp(SegData[CODE]->SDoffset,Doffset,0,SegData[UDATA]->SDoffset); // do real sizes
objseggrp(SegData[CODE]->SDoffset,SegData[DATA]->SDoffset,0,SegData[UDATA]->SDoffset); // do real sizes

// Update any out-of-date far segment sizes
for (size_t i = 0; i <= seg_count; i++)
Expand Down Expand Up @@ -1494,15 +1494,17 @@ void objseggrp(targ_size_t codesize,targ_size_t datasize,

#if MARS
dsegattr = SEG_ATTR(SEG_ALIGN16,SEG_C_PUBLIC,0,USE32);
objsegdef(dsegattr,datasize,5,DATACLASS); // [DATA] seg _DATA, class DATA
objsegdef(dsegattr,cdatasize,7,7); // [CDATA] seg CONST, class CONST
objsegdef(dsegattr,udatasize,8,9); // [UDATA] seg _BSS, class BSS
#else
dsegattr = I32
? SEG_ATTR(SEG_ALIGN4,SEG_C_PUBLIC,0,USE32)
: SEG_ATTR(SEG_ALIGN2,SEG_C_PUBLIC,0,USE16);
#endif

objsegdef(dsegattr,datasize,5,DATACLASS); // seg _DATA, class DATA
objsegdef(dsegattr,cdatasize,7,7); // seg CONST, class CONST
objsegdef(dsegattr,udatasize,8,9); // seg _BSS, class BSS
#endif

obj.lnameidx = 10; // next lname index
obj.segidx = 5; // next segment index
Expand Down Expand Up @@ -2333,9 +2335,13 @@ int elf_data_start(Symbol *sdata, targ_size_t datasize, int seg)
else
seg = sdata->Sseg;
targ_size_t offset = SegData[seg]->SDoffset;
alignbytes = align(datasize, offset) - offset;
// if (alignbytes)
// obj_lidata(seg, offset, alignbytes);
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;
sdata->Soffset = offset + alignbytes;
SegData[seg]->SDoffset = sdata->Soffset;
return seg;
Expand Down
2 changes: 2 additions & 0 deletions src/backend/code.h
Expand Up @@ -993,6 +993,7 @@ struct seg_data
{
int SDseg; // index into SegData[]
targ_size_t SDoffset; // starting offset for data
int SDalignment; // power of 2

bool isfarseg;
int segidx; // internal object file segment number
Expand Down Expand Up @@ -1031,6 +1032,7 @@ struct seg_data
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
IDXSYM SDsymidx; // each section is in the symbol table
IDXSEC SDrelidx; // section header for relocation info
Expand Down
66 changes: 28 additions & 38 deletions src/backend/elfobj.c
Expand Up @@ -108,7 +108,7 @@ void obj_tlssections();

static IDXSYM elf_addsym(IDXSTR sym, targ_size_t val, unsigned sz,
unsigned typ,unsigned bind,IDXSEC sec);
static long elf_align(FILE *fd, targ_size_t size, long offset);
static long elf_align(targ_size_t size, long offset);

// The object file is built is several separate pieces

Expand Down Expand Up @@ -1069,33 +1069,35 @@ void obj_term()
//printf("Setup offsets and sizes foffset %d\n\tsection_cnt %d, seg_count %d\n",foffset,section_cnt,seg_count);
for (int i=1; i<= seg_count; i++)
{
seg = SegData[i];
sechdr = MAP_SEG2SEC(i); // corresponding section
foffset = elf_align(fd,sechdr->sh_addralign,foffset);
seg_data *pseg = SegData[i];
Elf32_Shdr *sechdr = MAP_SEG2SEC(i); // corresponding section
if (sechdr->sh_addralign < pseg->SDalignment)
sechdr->sh_addralign = pseg->SDalignment;
foffset = elf_align(sechdr->sh_addralign,foffset);
if (i == UDATA) // 0, BSS never allocated
{ // but foffset as if it has
sechdr->sh_offset = foffset;
sechdr->sh_size = seg->SDoffset;
sechdr->sh_size = pseg->SDoffset;
// accumulated size
continue;
}
else if (sechdr->sh_type == SHT_NOBITS) // .tbss never allocated
{
sechdr->sh_offset = foffset;
sechdr->sh_size = seg->SDoffset;
sechdr->sh_size = pseg->SDoffset;
// accumulated size
continue;
}
else if (!seg->SDbuf)
else if (!pseg->SDbuf)
continue; // For others leave sh_offset as 0

sechdr->sh_offset = foffset;
//printf("\tsection name %d,",sechdr->sh_name);
if (seg->SDbuf && seg->SDbuf->size())
if (pseg->SDbuf && pseg->SDbuf->size())
{
//printf(" - size %d\n",seg->SDbuf->size());
sechdr->sh_size = seg->SDbuf->size();
fobjbuf->write(seg->SDbuf->buf, sechdr->sh_size);
//printf(" - size %d\n",pseg->SDbuf->size());
sechdr->sh_size = pseg->SDbuf->size();
fobjbuf->write(pseg->SDbuf->buf, sechdr->sh_size);
foffset += sechdr->sh_size;
}
//printf(" assigned offset %d, size %d\n",foffset,sechdr->sh_size);
Expand Down Expand Up @@ -1141,7 +1143,7 @@ void obj_term()
sechdr->sh_entsize = I64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
sechdr->sh_link = SHI_STRINGS;
sechdr->sh_info = local_cnt;
foffset = elf_align(fd,4,foffset);
foffset = elf_align(4,foffset);
sechdr->sh_offset = foffset;
fobjbuf->write(symtab, sechdr->sh_size);
foffset += sechdr->sh_size;
Expand All @@ -1157,7 +1159,7 @@ void obj_term()
//
// Now the relocation data for program code and data sections
//
foffset = elf_align(fd,4,foffset);
foffset = elf_align(4,foffset);
//dbg_printf("output relocations size 0x%x, foffset 0x%x\n",section_names->size(),foffset);
for (int i=1; i<= seg_count; i++)
{
Expand Down Expand Up @@ -1633,6 +1635,8 @@ STATIC void setup_comdat(Symbol *s)

s->Sseg = elf_getsegment(prefix, cpp_mangle(s), type, flags, align);
// find or create new segment
if (s->Salignment > align)
SegData[s->Sseg]->SDalignment = s->Salignment;
SegData[s->Sseg]->SDsym = s;
}

Expand Down Expand Up @@ -2002,7 +2006,13 @@ int elf_data_start(Symbol *sdata, targ_size_t datasize, int seg)
else
seg = sdata->Sseg;
targ_size_t offset = Offset(seg);
alignbytes = align(datasize, offset) - offset;
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)
obj_lidata(seg, offset, alignbytes);
sdata->Soffset = offset + alignbytes;
Expand Down Expand Up @@ -2943,31 +2953,11 @@ void objfile_write(FILE *fd, void *buffer, unsigned len)
fobjbuf->write(buffer, len);
}

long elf_align(FILE *fd, targ_size_t size,long foffset)
long elf_align(targ_size_t size,long foffset)
{
long offset;
switch (size)
{
case 0:
case 1:
return foffset;
case 4:
offset = (foffset + 3) & ~3;
break;
case 8:
offset = (foffset + 7) & ~7;
break;
case 16:
offset = (foffset + 15) & ~15;
break;
case 32:
offset = (foffset + 31) & ~31;
break;
default:
dbg_printf("size was %d\n",(int)size);
assert(0);
break;
}
if (size <= 1)
return foffset;
long offset = (foffset + size - 1) & ~(size - 1);
if (offset > foffset)
fobjbuf->writezeros(offset - foffset);
return offset;
Expand Down
55 changes: 25 additions & 30 deletions src/backend/machobj.c
Expand Up @@ -810,6 +810,11 @@ void obj_term()
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)
Expand Down Expand Up @@ -843,6 +848,11 @@ void obj_term()
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)
Expand Down Expand Up @@ -1695,7 +1705,8 @@ int obj_comdat(Symbol *s)
else if ((s->ty() & mTYLINK) == mTYthread)
{
s->Sfl = FLtlsdata;
s->Sseg = mach_getsegment("__tlscoal_nt", "__DATA", 4, S_COALESCED);
align = 4;
s->Sseg = mach_getsegment("__tlscoal_nt", "__DATA", align, S_COALESCED);
elf_data_start(s, 1 << align, s->Sseg);
}
else
Expand All @@ -1704,10 +1715,11 @@ int obj_comdat(Symbol *s)
sectname = "__datacoal_nt";
segname = "__DATA";
align = 4; // 16 byte alignment
flags = S_COALESCED;
s->Sseg = mach_getsegment(sectname, segname, align, flags);
s->Sseg = mach_getsegment(sectname, segname, align, S_COALESCED);
}
// find or create new segment
if (s->Salignment > (1 << 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 elf_func_start()
Expand Down Expand Up @@ -2050,7 +2062,13 @@ int elf_data_start(Symbol *sdata, targ_size_t datasize, int seg)
else
seg = sdata->Sseg;
targ_size_t offset = Offset(seg);
alignbytes = align(datasize, offset) - offset;
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)
obj_lidata(seg, offset, alignbytes);
sdata->Soffset = offset + alignbytes;
Expand Down Expand Up @@ -2658,32 +2676,9 @@ void objfile_write(FILE *fd, void *buffer, unsigned len)

long elf_align(targ_size_t size, long foffset)
{
long offset;
switch (size)
{
case 0:
case 1:
return foffset;
case 2:
offset = (foffset + 1) & ~1;
break;
case 4:
offset = (foffset + 3) & ~3;
break;
case 8:
offset = (foffset + 7) & ~7;
break;
case 16:
offset = (foffset + 15) & ~15;
break;
case 32:
offset = (foffset + 31) & ~31;
break;
default:
dbg_printf("size was %lu\n",(unsigned long)size);
assert(0);
break;
}
if (size <= 1)
return foffset;
long offset = (foffset + size - 1) & ~(size - 1);
if (offset > foffset)
fobjbuf->writezeros(offset - foffset);
return offset;
Expand Down
7 changes: 3 additions & 4 deletions src/backend/out.c
Expand Up @@ -86,7 +86,6 @@ void outdata(symbol *s)
#if HTOD
return;
#endif
dt_t *dtstart,*dt;
targ_size_t datasize,a;
int seg;
targ_size_t offset;
Expand All @@ -103,7 +102,7 @@ void outdata(symbol *s)
// Data segment variables are always live on exit from a function
s->Sflags |= SFLlivexit;

dtstart = s->Sdt;
dt_t *dtstart = s->Sdt;
s->Sdt = NULL; // it will be free'd
#if OMFOBJ
int tls = 0;
Expand All @@ -119,7 +118,7 @@ void outdata(symbol *s)
ty = s->ty();
if (ty & mTYexport && config.wflags & WFexpdef && s->Sclass != SCstatic)
obj_export(s,0); // export data definition
for (dt = dtstart; dt; dt = dt->DTnext)
for (dt_t *dt = dtstart; dt; dt = dt->DTnext)
{
//printf("dt = %p, dt = %d\n",dt,dt->dt);
switch (dt->dt)
Expand Down Expand Up @@ -357,7 +356,7 @@ void outdata(symbol *s)

offset = s->Soffset;

for (dt = dtstart; dt; dt = dt->DTnext)
for (dt_t *dt = dtstart; dt; dt = dt->DTnext)
{
switch (dt->dt)
{ case DT_abytes:
Expand Down
3 changes: 0 additions & 3 deletions src/struct.c
Expand Up @@ -208,9 +208,6 @@ void AggregateDeclaration::alignmember(
//printf("alignment = %d, size = %d, offset = %d\n",alignment,size,offset);
switch (alignment)
{
case 0:
assert(0);

case 1:
// No alignment
break;
Expand Down
11 changes: 6 additions & 5 deletions src/tocsym.c
Expand Up @@ -178,6 +178,7 @@ Symbol *VarDeclaration::toSymbol()
else
id = ident->toChars();
s = symbol_calloc(id);
s->Salignment = alignment;

if (storage_class & (STCout | STCref))
{
Expand Down Expand Up @@ -609,15 +610,15 @@ Symbol *ClassDeclaration::toVtblSymbol()

Symbol *AggregateDeclaration::toInitializer()
{
Symbol *s;
Classsym *stag;

if (!sinit)
{
stag = fake_classsym(Id::ClassInfo);
s = toSymbolX("__init", SCextern, stag->Stype, "Z");
Classsym *stag = fake_classsym(Id::ClassInfo);
Symbol *s = toSymbolX("__init", SCextern, stag->Stype, "Z");
s->Sfl = FLextern;
s->Sflags |= SFLnodebug;
StructDeclaration *sd = isStructDeclaration();
if (sd)
s->Salignment = sd->alignment;
slist_add(s);
sinit = s;
}
Expand Down

0 comments on commit 77e6c75

Please sign in to comment.