mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-16 04:43:14 +01:00
409 lines
9.5 KiB
C
409 lines
9.5 KiB
C
|
|
// Compiler implementation of the D programming language
|
|
// Copyright (c) 1999-2012 by Digital Mars
|
|
// All Rights Reserved
|
|
// written by Walter Bright
|
|
// http://www.digitalmars.com
|
|
// License for redistribution is by either the Artistic License
|
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
|
// See the included readme.txt for details.
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stddef.h>
|
|
|
|
#include "mars.h"
|
|
|
|
#include "cc.h"
|
|
#include "global.h"
|
|
#include "oper.h"
|
|
#include "code.h"
|
|
#include "type.h"
|
|
#include "dt.h"
|
|
#include "cgcv.h"
|
|
|
|
static char __file__[] = __FILE__; /* for tassert.h */
|
|
#include "tassert.h"
|
|
|
|
extern void ph_init();
|
|
|
|
extern Global global;
|
|
extern int REALSIZE;
|
|
|
|
Config config;
|
|
Configv configv;
|
|
|
|
struct Environment;
|
|
|
|
/**************************************
|
|
* Initialize config variables.
|
|
*/
|
|
|
|
void out_config_init()
|
|
{
|
|
//printf("out_config_init()\n");
|
|
Param *params = &global.params;
|
|
|
|
if (!config.target_cpu)
|
|
{ config.target_cpu = TARGET_PentiumPro;
|
|
config.target_scheduler = config.target_cpu;
|
|
}
|
|
config.fulltypes = CVNONE;
|
|
config.fpxmmregs = FALSE;
|
|
config.inline8087 = 1;
|
|
config.memmodel = 0;
|
|
config.flags |= CFGuchar; // make sure TYchar is unsigned
|
|
tytab[TYchar] |= TYFLuns;
|
|
#if TARGET_WINDOS
|
|
if (params->is64bit)
|
|
config.exe = EX_WIN64;
|
|
else
|
|
config.exe = EX_NT;
|
|
|
|
// Win32 eh
|
|
config.flags2 |= CFG2seh;
|
|
|
|
if (params->run)
|
|
config.wflags |= WFexe; // EXE file only optimizations
|
|
else if (params->link && !global.params.deffile)
|
|
config.wflags |= WFexe; // EXE file only optimizations
|
|
else if (params->exefile) // if writing out EXE file
|
|
{ size_t len = strlen(params->exefile);
|
|
if (len >= 4 && stricmp(params->exefile + len - 3, "exe") == 0)
|
|
config.wflags |= WFexe;
|
|
}
|
|
config.flags4 |= CFG4underscore;
|
|
#endif
|
|
#if TARGET_LINUX
|
|
if (params->is64bit)
|
|
{ config.exe = EX_LINUX64;
|
|
config.fpxmmregs = TRUE;
|
|
}
|
|
else
|
|
config.exe = EX_LINUX;
|
|
config.flags |= CFGnoebp;
|
|
config.flags |= CFGalwaysframe;
|
|
if (params->pic)
|
|
config.flags3 |= CFG3pic;
|
|
#endif
|
|
#if TARGET_OSX
|
|
config.fpxmmregs = TRUE;
|
|
if (params->is64bit)
|
|
{ config.exe = EX_OSX64;
|
|
config.fpxmmregs = TRUE;
|
|
}
|
|
else
|
|
config.exe = EX_OSX;
|
|
config.flags |= CFGnoebp;
|
|
config.flags |= CFGalwaysframe;
|
|
if (params->pic)
|
|
config.flags3 |= CFG3pic;
|
|
#endif
|
|
#if TARGET_FREEBSD
|
|
if (params->is64bit)
|
|
{ config.exe = EX_FREEBSD64;
|
|
config.fpxmmregs = TRUE;
|
|
}
|
|
else
|
|
config.exe = EX_FREEBSD;
|
|
config.flags |= CFGnoebp;
|
|
config.flags |= CFGalwaysframe;
|
|
if (params->pic)
|
|
config.flags3 |= CFG3pic;
|
|
#endif
|
|
#if TARGET_OPENBSD
|
|
if (params->is64bit)
|
|
{ config.exe = EX_OPENBSD64;
|
|
config.fpxmmregs = TRUE;
|
|
}
|
|
else
|
|
config.exe = EX_OPENBSD;
|
|
config.flags |= CFGnoebp;
|
|
config.flags |= CFGalwaysframe;
|
|
if (params->pic)
|
|
config.flags3 |= CFG3pic;
|
|
#endif
|
|
#if TARGET_SOLARIS
|
|
if (params->is64bit)
|
|
{ config.exe = EX_SOLARIS64;
|
|
config.fpxmmregs = TRUE;
|
|
}
|
|
else
|
|
config.exe = EX_SOLARIS;
|
|
config.flags |= CFGnoebp;
|
|
config.flags |= CFGalwaysframe;
|
|
if (params->pic)
|
|
config.flags3 |= CFG3pic;
|
|
#endif
|
|
config.flags2 |= CFG2nodeflib; // no default library
|
|
config.flags3 |= CFG3eseqds;
|
|
#if 0
|
|
if (env->getEEcontext()->EEcompile != 2)
|
|
config.flags4 |= CFG4allcomdat;
|
|
if (env->nochecks())
|
|
config.flags4 |= CFG4nochecks; // no runtime checking
|
|
#elif TARGET_OSX
|
|
#else
|
|
config.flags4 |= CFG4allcomdat;
|
|
#endif
|
|
if (params->trace)
|
|
config.flags |= CFGtrace; // turn on profiler
|
|
if (params->nofloat)
|
|
config.flags3 |= CFG3wkfloat;
|
|
|
|
configv.verbose = params->verbose;
|
|
|
|
if (params->optimize)
|
|
go_flag((char *)"-o");
|
|
|
|
if (params->symdebug)
|
|
{
|
|
#if ELFOBJ || MACHOBJ
|
|
configv.addlinenumbers = 1;
|
|
config.fulltypes = (params->symdebug == 1) ? CVDWARF_D : CVDWARF_C;
|
|
#endif
|
|
#if OMFOBJ
|
|
configv.addlinenumbers = 1;
|
|
config.fulltypes = CV4;
|
|
#endif
|
|
if (!params->optimize)
|
|
config.flags |= CFGalwaysframe;
|
|
}
|
|
else
|
|
{
|
|
configv.addlinenumbers = 0;
|
|
config.fulltypes = CVNONE;
|
|
//config.flags &= ~CFGalwaysframe;
|
|
}
|
|
|
|
if (params->alwaysframe)
|
|
config.flags &= ~CFGalwaysframe;
|
|
|
|
#ifdef DEBUG
|
|
debugb = params->debugb;
|
|
debugc = params->debugc;
|
|
debugf = params->debugf;
|
|
debugr = params->debugr;
|
|
debugw = params->debugw;
|
|
debugx = params->debugx;
|
|
debugy = params->debugy;
|
|
#endif
|
|
}
|
|
|
|
/*******************************
|
|
* Redo tables from 8086/286 to ILP32
|
|
*/
|
|
|
|
void util_set32()
|
|
{
|
|
_tyrelax[TYenum] = TYlong;
|
|
_tyrelax[TYint] = TYlong;
|
|
_tyrelax[TYuint] = TYlong;
|
|
|
|
tyequiv[TYint] = TYlong;
|
|
tyequiv[TYuint] = TYulong;
|
|
|
|
for (int i = 0; i < 1; ++i)
|
|
{ tysize[TYenum + i] = LONGSIZE;
|
|
tysize[TYint + i] = LONGSIZE;
|
|
tysize[TYuint + i] = LONGSIZE;
|
|
tysize[TYjhandle + i] = LONGSIZE;
|
|
tysize[TYnptr + i] = LONGSIZE;
|
|
tysize[TYnref + i] = LONGSIZE;
|
|
}
|
|
|
|
for (int i = 0; i < 1; ++i)
|
|
{ tyalignsize[TYenum + i] = LONGSIZE;
|
|
tyalignsize[TYint + i] = LONGSIZE;
|
|
tyalignsize[TYuint + i] = LONGSIZE;
|
|
tyalignsize[TYnullptr + i] = LONGSIZE;
|
|
tyalignsize[TYnptr + i] = LONGSIZE;
|
|
tyalignsize[TYnref + i] = LONGSIZE;
|
|
}
|
|
}
|
|
|
|
/*******************************
|
|
* Redo tables from 8086/286 to LP64.
|
|
*/
|
|
|
|
void util_set64()
|
|
{
|
|
_tyrelax[TYenum] = TYlong;
|
|
_tyrelax[TYint] = TYlong;
|
|
_tyrelax[TYuint] = TYlong;
|
|
|
|
tyequiv[TYint] = TYlong;
|
|
tyequiv[TYuint] = TYulong;
|
|
|
|
for (int i = 0; i < 1; ++i)
|
|
{ tysize[TYenum + i] = LONGSIZE;
|
|
tysize[TYint + i] = LONGSIZE;
|
|
tysize[TYuint + i] = LONGSIZE;
|
|
tysize[TYnptr + i] = 8;
|
|
tysize[TYnref + i] = 8;
|
|
tysize[TYldouble + i] = REALSIZE;
|
|
tysize[TYildouble + i] = REALSIZE;
|
|
tysize[TYcldouble + i] = 2 * REALSIZE;
|
|
|
|
tyalignsize[TYenum + i] = LONGSIZE;
|
|
tyalignsize[TYint + i] = LONGSIZE;
|
|
tyalignsize[TYuint + i] = LONGSIZE;
|
|
tyalignsize[TYnullptr + i] = 8;
|
|
tyalignsize[TYnptr + i] = 8;
|
|
tyalignsize[TYnref + i] = 8;
|
|
#if TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || TARGET_OSX
|
|
tyalignsize[TYldouble + i] = 16;
|
|
tyalignsize[TYildouble + i] = 16;
|
|
tyalignsize[TYcldouble + i] = 16;
|
|
#else
|
|
assert(0);
|
|
#endif
|
|
tytab[TYjfunc + i] &= ~TYFLpascal; // set so caller cleans the stack (as in C)
|
|
}
|
|
|
|
TYptrdiff = TYllong;
|
|
TYsize = TYullong;
|
|
TYsize_t = TYullong;
|
|
}
|
|
|
|
/***********************************
|
|
* Return aligned 'offset' if it is of size 'size'.
|
|
*/
|
|
|
|
targ_size_t align(targ_size_t size, targ_size_t offset)
|
|
{
|
|
switch (size)
|
|
{
|
|
case 1:
|
|
break;
|
|
case 2:
|
|
case 4:
|
|
case 8:
|
|
offset = (offset + size - 1) & ~(size - 1);
|
|
break;
|
|
default:
|
|
if (size >= 16)
|
|
offset = (offset + 15) & ~15;
|
|
else
|
|
offset = (offset + REGSIZE - 1) & ~(REGSIZE - 1);
|
|
break;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
/*******************************
|
|
* Get size of ty
|
|
*/
|
|
|
|
targ_size_t size(tym_t ty)
|
|
{
|
|
int sz = (tybasic(ty) == TYvoid) ? 1 : tysize(ty);
|
|
#ifdef DEBUG
|
|
if (sz == -1)
|
|
WRTYxx(ty);
|
|
#endif
|
|
assert(sz!= -1);
|
|
return sz;
|
|
}
|
|
|
|
/*******************************
|
|
* Replace (e) with ((stmp = e),stmp)
|
|
*/
|
|
|
|
elem *exp2_copytotemp(elem *e)
|
|
{
|
|
//printf("exp2_copytotemp()\n");
|
|
elem_debug(e);
|
|
Symbol *stmp = symbol_genauto(e);
|
|
elem *eeq = el_bin(OPeq,e->Ety,el_var(stmp),e);
|
|
elem *er = el_bin(OPcomma,e->Ety,eeq,el_var(stmp));
|
|
if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray)
|
|
{
|
|
eeq->Eoper = OPstreq;
|
|
eeq->ET = e->ET;
|
|
eeq->E1->ET = e->ET;
|
|
er->ET = e->ET;
|
|
er->E2->ET = e->ET;
|
|
}
|
|
return er;
|
|
}
|
|
|
|
/****************************
|
|
* Generate symbol of type ty at DATA:offset
|
|
*/
|
|
|
|
symbol *symboldata(targ_size_t offset,tym_t ty)
|
|
{
|
|
symbol *s = symbol_generate(SClocstat, type_fake(ty));
|
|
s->Sfl = FLdata;
|
|
s->Soffset = offset;
|
|
s->Sseg = DATA;
|
|
symbol_keep(s); // keep around
|
|
return s;
|
|
}
|
|
|
|
/************************************
|
|
* Add symbol to slist.
|
|
*/
|
|
|
|
static list_t slist;
|
|
|
|
void slist_add(Symbol *s)
|
|
{
|
|
list_prepend(&slist,s);
|
|
}
|
|
|
|
/*************************************
|
|
*/
|
|
|
|
void slist_reset()
|
|
{
|
|
//printf("slist_reset()\n");
|
|
for (list_t sl = slist; sl; sl = list_next(sl))
|
|
{ Symbol *s = list_symbol(sl);
|
|
|
|
#if MACHOBJ
|
|
s->Soffset = 0;
|
|
#endif
|
|
s->Sxtrnnum = 0;
|
|
s->Stypidx = 0;
|
|
s->Sflags &= ~(STRoutdef | SFLweak);
|
|
if (s->Sclass == SCglobal || s->Sclass == SCcomdat ||
|
|
s->Sfl == FLudata || s->Sclass == SCstatic)
|
|
{ s->Sclass = SCextern;
|
|
s->Sfl = FLextern;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**************************************
|
|
*/
|
|
|
|
void backend_init()
|
|
{
|
|
ph_init();
|
|
block_init();
|
|
|
|
if (global.params.is64bit)
|
|
{
|
|
util_set64();
|
|
type_init();
|
|
cod3_set64();
|
|
}
|
|
else
|
|
{
|
|
util_set32();
|
|
type_init();
|
|
cod3_set32();
|
|
}
|
|
|
|
rtlsym_init(); // uses fregsaved, so must be after it's set inside cod3_set*
|
|
|
|
out_config_init();
|
|
}
|
|
|
|
void backend_term()
|
|
{
|
|
}
|