mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 16:11:08 +03:00
- Fixed LLVM style CL args for D2.
- Moved main() into its own file gen/main.cpp - Fixed basic cross compilation - removed the option for setting OS - added support for llc's mattr, mcpu and mtriple switches - added basic ABI abstraction for return value rewrites, it's not perfect and will probably be completely rewritten once I get to handling parameter rewrites as well. - x86-64 extern(C) abi for cfloat returns now match (llvm-)gcc.
This commit is contained in:
parent
f61733cb57
commit
57a69e8177
20 changed files with 334 additions and 2264 deletions
10
dmd/cond.h
10
dmd/cond.h
|
@ -55,8 +55,8 @@ struct DVCondition : Condition
|
|||
struct DebugCondition : DVCondition
|
||||
{
|
||||
static void setGlobalLevel(unsigned level);
|
||||
static void addGlobalIdent(char *ident);
|
||||
static void addPredefinedGlobalIdent(char *ident);
|
||||
static void addGlobalIdent(const char *ident);
|
||||
static void addPredefinedGlobalIdent(const char *ident);
|
||||
|
||||
DebugCondition(Module *mod, unsigned level, Identifier *ident);
|
||||
|
||||
|
@ -67,9 +67,9 @@ struct DebugCondition : DVCondition
|
|||
struct VersionCondition : DVCondition
|
||||
{
|
||||
static void setGlobalLevel(unsigned level);
|
||||
static void checkPredefined(Loc loc, char *ident);
|
||||
static void addGlobalIdent(char *ident);
|
||||
static void addPredefinedGlobalIdent(char *ident);
|
||||
static void checkPredefined(Loc loc, const char *ident);
|
||||
static void addGlobalIdent(const char *ident);
|
||||
static void addPredefinedGlobalIdent(const char *ident);
|
||||
|
||||
VersionCondition(Module *mod, unsigned level, Identifier *ident);
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ char *strupr(char *s)
|
|||
* inifile .ini file name
|
||||
*/
|
||||
|
||||
void inifile(char *argv0, char *inifile)
|
||||
void inifile(char *argv0, const char *inifile)
|
||||
{
|
||||
char *path; // need path for @P macro
|
||||
char *filename;
|
||||
|
|
797
dmd/mars.c
797
dmd/mars.c
|
@ -36,48 +36,8 @@
|
|||
#include "expression.h"
|
||||
#include "lexer.h"
|
||||
|
||||
#include "gen/logger.h"
|
||||
#include "gen/linker.h"
|
||||
#include "revisions.h"
|
||||
|
||||
#include "gen/cl_options.h"
|
||||
#include "gen/cl_helpers.h"
|
||||
using namespace opts;
|
||||
|
||||
|
||||
static cl::opt<bool> forceBE("forcebe",
|
||||
cl::desc("Force big-endian"),
|
||||
cl::Hidden,
|
||||
cl::ZeroOrMore);
|
||||
|
||||
static cl::opt<bool> noDefaultLib("nodefaultlib",
|
||||
cl::desc("Don't add a default library for linking implicitly"),
|
||||
cl::ZeroOrMore);
|
||||
|
||||
static ArrayAdapter impPathsStore("I", global.params.imppath);
|
||||
static cl::list<std::string, ArrayAdapter> importPaths("I",
|
||||
cl::desc("Where to look for imports"),
|
||||
cl::value_desc("path"),
|
||||
cl::location(impPathsStore),
|
||||
cl::Prefix);
|
||||
|
||||
static ArrayAdapter defaultLibStore("defaultlib", global.params.defaultlibnames);
|
||||
static cl::list<std::string, ArrayAdapter> defaultlibs("defaultlib",
|
||||
cl::desc("Set default libraries for non-debug build"),
|
||||
cl::value_desc("lib,..."),
|
||||
cl::location(defaultLibStore),
|
||||
cl::CommaSeparated);
|
||||
|
||||
static ArrayAdapter debugLibStore("debuglib", global.params.debuglibnames);
|
||||
static cl::list<std::string, ArrayAdapter> debuglibs("debuglib",
|
||||
cl::desc("Set default libraries for debug build"),
|
||||
cl::value_desc("lib,..."),
|
||||
cl::location(debugLibStore),
|
||||
cl::CommaSeparated);
|
||||
|
||||
|
||||
void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
|
||||
|
||||
Global global;
|
||||
|
||||
Global::Global()
|
||||
|
@ -187,763 +147,6 @@ void halt()
|
|||
#endif
|
||||
}
|
||||
|
||||
extern void backend_init();
|
||||
extern void backend_term();
|
||||
|
||||
void printVersion() {
|
||||
printf("LLVM D Compiler %s\nbased on DMD %s and %s\n%s\n%s\n",
|
||||
global.ldc_version, global.version, global.llvm_version, global.copyright, global.written);
|
||||
printf("D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n"
|
||||
"LDC Homepage: http://www.dsource.org/projects/ldc\n");
|
||||
}
|
||||
|
||||
// Helper function to handle -d-debug=* and -d-version=*
|
||||
static void processVersions(std::vector<std::string>& list, char* type,
|
||||
void (*setLevel)(unsigned), void (*addIdent)(char*)) {
|
||||
typedef std::vector<std::string>::iterator It;
|
||||
|
||||
for(It I = list.begin(), E = list.end(); I != E; ++I) {
|
||||
const char* value = I->c_str();
|
||||
if (isdigit(value[0])) {
|
||||
errno = 0;
|
||||
char* end;
|
||||
long level = strtol(value, &end, 10);
|
||||
if (*end || errno || level > INT_MAX) {
|
||||
error("Invalid %s level: %s", type, I->c_str());
|
||||
} else {
|
||||
setLevel((unsigned)level);
|
||||
}
|
||||
} else {
|
||||
char* cstr = mem.strdup(value);
|
||||
if (Lexer::isValidIdentifier(cstr)) {
|
||||
addIdent(cstr);
|
||||
continue;
|
||||
} else {
|
||||
error("Invalid %s identifier or level: '%s'", type, I->c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to handle -of, -od, etc.
|
||||
static void initFromString(char*& dest, const cl::opt<std::string>& src) {
|
||||
dest = 0;
|
||||
if (src.getNumOccurrences() != 0) {
|
||||
if (src.empty())
|
||||
error("Expected argument to '-%s'", src.ArgStr);
|
||||
dest = mem.strdup(src.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
Array files;
|
||||
char *p, *ext;
|
||||
Module *m;
|
||||
int status = EXIT_SUCCESS;
|
||||
|
||||
// Set default values
|
||||
#if _WIN32
|
||||
char buf[MAX_PATH];
|
||||
GetModuleFileName(NULL, buf, MAX_PATH);
|
||||
global.params.argv0 = buf;
|
||||
#else
|
||||
global.params.argv0 = argv[0];
|
||||
#endif
|
||||
global.params.useSwitchError = 1;
|
||||
|
||||
global.params.linkswitches = new Array();
|
||||
global.params.libfiles = new Array();
|
||||
global.params.objfiles = new Array();
|
||||
global.params.ddocfiles = new Array();
|
||||
|
||||
global.params.is64bit = sizeof(void*) == 8 ? 1 : 0;
|
||||
|
||||
uint16_t endiantest = 0xFF00;
|
||||
uint8_t endianres = ((uint8_t*)&endiantest)[0];
|
||||
if (endianres == 0x00)
|
||||
global.params.isLE = true;
|
||||
else if (endianres == 0xFF)
|
||||
global.params.isLE = false;
|
||||
else {
|
||||
error("Endian test is broken");
|
||||
fatal();
|
||||
}
|
||||
|
||||
// Predefine version identifiers
|
||||
#if IN_LLVM
|
||||
VersionCondition::addPredefinedGlobalIdent("LLVM");
|
||||
VersionCondition::addPredefinedGlobalIdent("LDC");
|
||||
#endif
|
||||
|
||||
// setup default target os to be build os
|
||||
#if _WIN32
|
||||
global.params.os = OSWindows;
|
||||
#elif linux
|
||||
global.params.os = OSLinux;
|
||||
#elif __APPLE__
|
||||
global.params.os = OSMacOSX;
|
||||
#elif __FreeBSD__
|
||||
global.params.os = OSFreeBSD;
|
||||
#elif defined (__SVR4) && defined (__sun)
|
||||
global.params.os = OSSolaris;
|
||||
#else
|
||||
#error Unsupported OS
|
||||
#endif /* linux */
|
||||
|
||||
assert(global.params.os != OSinvalid);
|
||||
|
||||
//VersionCondition::addPredefinedGlobalIdent("D_Bits");
|
||||
VersionCondition::addPredefinedGlobalIdent("all");
|
||||
|
||||
//#if _WIN32
|
||||
// inifile(global.params.argv0, "ldc.ini");
|
||||
//#elif POSIX
|
||||
inifile(global.params.argv0, "ldc.conf");
|
||||
//#else
|
||||
//#error
|
||||
//#endif
|
||||
getenv_setargv("DFLAGS", &argc, &argv);
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
printf("argv[%d] = '%s'\n", i, argv[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
cl::SetVersionPrinter(&printVersion);
|
||||
cl::ParseCommandLineOptions(argc, argv, "LLVM-based D Compiler\n");
|
||||
|
||||
global.params.optimize = (global.params.optimizeLevel >= 0);
|
||||
|
||||
// Negated options
|
||||
global.params.link = !compileOnly;
|
||||
global.params.obj = !dontWriteObj;
|
||||
global.params.useInlineAsm = !noAsm;
|
||||
|
||||
// String options: std::string --> char*
|
||||
initFromString(global.params.objname, objectFile);
|
||||
initFromString(global.params.objdir, objectDir);
|
||||
|
||||
initFromString(global.params.docdir, ddocDir);
|
||||
initFromString(global.params.docname, ddocFile);
|
||||
global.params.doDocComments |=
|
||||
global.params.docdir || global.params.docname;
|
||||
|
||||
#ifdef _DH
|
||||
initFromString(global.params.hdrdir, hdrDir);
|
||||
initFromString(global.params.hdrname, hdrFile);
|
||||
global.params.doHdrGeneration |=
|
||||
global.params.hdrdir || global.params.hdrname;
|
||||
#endif
|
||||
|
||||
processVersions(debugArgs, "debug",
|
||||
DebugCondition::setGlobalLevel,
|
||||
DebugCondition::addGlobalIdent);
|
||||
processVersions(versions, "version",
|
||||
VersionCondition::setGlobalLevel,
|
||||
VersionCondition::addGlobalIdent);
|
||||
|
||||
global.params.output_o =
|
||||
opts::output_o == cl::BOU_UNSET
|
||||
? OUTPUTFLAGdefault
|
||||
: opts::output_o == cl::BOU_TRUE
|
||||
? OUTPUTFLAGset
|
||||
: OUTPUTFLAGno;
|
||||
global.params.output_bc = opts::output_bc ? OUTPUTFLAGset : OUTPUTFLAGno;
|
||||
global.params.output_ll = opts::output_ll ? OUTPUTFLAGset : OUTPUTFLAGno;
|
||||
global.params.output_s = opts::output_s ? OUTPUTFLAGset : OUTPUTFLAGno;
|
||||
|
||||
if (global.params.run || !runargs.empty()) {
|
||||
// FIXME: how to properly detect the presence of a PositionalEatsArgs
|
||||
// option without parameters? We want to emit an error in that case...
|
||||
// You'd think getNumOccurrences would do it, but it just returns the
|
||||
// number of parameters)
|
||||
// NOTE: Hacked around it by detecting -run in getenv_setargv(), where
|
||||
// we're looking for it anyway, and pre-setting the flag...
|
||||
global.params.run = true;
|
||||
if (!runargs.empty()) {
|
||||
files.push(mem.strdup(runargs[0].c_str()));
|
||||
} else {
|
||||
global.params.run = false;
|
||||
error("Expected at least one argument to '-run'\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (mArch)
|
||||
global.params.llvmArch = mArch->Name;
|
||||
|
||||
files.reserve(fileList.size());
|
||||
typedef std::vector<std::string>::iterator It;
|
||||
for(It I = fileList.begin(), E = fileList.end(); I != E; ++I)
|
||||
if (!I->empty())
|
||||
files.push(mem.strdup(I->c_str()));
|
||||
|
||||
if (global.errors)
|
||||
{
|
||||
fatal();
|
||||
}
|
||||
if (files.dim == 0)
|
||||
{
|
||||
cl::PrintHelpMessage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Array* libs;
|
||||
if (global.params.symdebug)
|
||||
libs = global.params.debuglibnames;
|
||||
else
|
||||
libs = global.params.defaultlibnames;
|
||||
|
||||
if (libs)
|
||||
{
|
||||
for (int i = 0; i < libs->dim; i++)
|
||||
{
|
||||
char *arg = (char *)mem.malloc(64);
|
||||
strcpy(arg, "-l");
|
||||
strncat(arg, (char *)libs->data[i], 64);
|
||||
global.params.linkswitches->push(arg);
|
||||
}
|
||||
}
|
||||
else if (!noDefaultLib)
|
||||
{
|
||||
char *arg;
|
||||
arg = (char *)mem.malloc(64);
|
||||
strcpy(arg, "-lldc-runtime");
|
||||
global.params.linkswitches->push(arg);
|
||||
arg = (char *)mem.malloc(64);
|
||||
strcpy(arg, "-ltango-cc-tango");
|
||||
global.params.linkswitches->push(arg);
|
||||
arg = (char *)mem.malloc(64);
|
||||
strcpy(arg, "-ltango-gc-basic");
|
||||
global.params.linkswitches->push(arg);
|
||||
// pass the runtime again to resolve issues
|
||||
// with linking order
|
||||
arg = (char *)mem.malloc(64);
|
||||
strcpy(arg, "-lldc-runtime");
|
||||
global.params.linkswitches->push(arg);
|
||||
}
|
||||
|
||||
if (global.params.run)
|
||||
quiet = 1;
|
||||
|
||||
if (global.params.useUnitTests)
|
||||
global.params.useAssert = 1;
|
||||
|
||||
// LDC output determination
|
||||
|
||||
// if we don't link, autodetect target from extension
|
||||
if(!global.params.link && global.params.objname) {
|
||||
ext = FileName::ext(global.params.objname);
|
||||
bool autofound = false;
|
||||
if (!ext) {
|
||||
// keep things as they are
|
||||
} else if (strcmp(ext, global.ll_ext) == 0) {
|
||||
global.params.output_ll = OUTPUTFLAGset;
|
||||
autofound = true;
|
||||
} else if (strcmp(ext, global.bc_ext) == 0) {
|
||||
global.params.output_bc = OUTPUTFLAGset;
|
||||
autofound = true;
|
||||
} else if (strcmp(ext, global.s_ext) == 0) {
|
||||
global.params.output_s = OUTPUTFLAGset;
|
||||
autofound = true;
|
||||
} else if (strcmp(ext, global.obj_ext) == 0) {
|
||||
global.params.output_o = OUTPUTFLAGset;
|
||||
autofound = true;
|
||||
} else {
|
||||
// append dot, so forceExt won't change existing name even if it contains dots
|
||||
size_t len = strlen(global.params.objname);
|
||||
size_t extlen = strlen(".");
|
||||
char* s = (char *)mem.malloc(len + 1 + extlen + 1);
|
||||
memcpy(s, global.params.objname, len);
|
||||
s[len] = '.';
|
||||
s[len+1+extlen] = 0;
|
||||
global.params.objname = s;
|
||||
|
||||
}
|
||||
if(autofound && global.params.output_o == OUTPUTFLAGdefault)
|
||||
global.params.output_o = OUTPUTFLAGno;
|
||||
}
|
||||
|
||||
// only link if possible
|
||||
if (!global.params.obj || !global.params.output_o)
|
||||
global.params.link = 0;
|
||||
|
||||
if (global.params.link)
|
||||
{
|
||||
global.params.exefile = global.params.objname;
|
||||
if (files.dim > 1)
|
||||
global.params.objname = NULL;
|
||||
}
|
||||
else if (global.params.run)
|
||||
{
|
||||
error("flags conflict with -run");
|
||||
fatal();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (global.params.objname && files.dim > 1)
|
||||
{
|
||||
error("multiple source files, but only one .obj name");
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
|
||||
bool allowForceEndianness = false;
|
||||
|
||||
if (global.params.llvmArch == 0) {
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
global.params.llvmArch = "x86-64";
|
||||
#elif defined(__i386__) || defined(_M_IX86)
|
||||
global.params.llvmArch = "x86";
|
||||
#elif defined(__ppc__) || defined(_M_PPC)
|
||||
if (global.params.is64bit)
|
||||
global.params.llvmArch = "ppc64";
|
||||
else
|
||||
global.params.llvmArch = "ppc32";
|
||||
#elif defined(__arm__)
|
||||
global.params.llvmArch = "arm";
|
||||
#elif defined(__thumb__)
|
||||
global.params.llvmArch = "thumb";
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
}
|
||||
|
||||
if (strcmp(global.params.llvmArch,"x86")==0) {
|
||||
VersionCondition::addPredefinedGlobalIdent("X86");
|
||||
global.params.isLE = true;
|
||||
global.params.is64bit = false;
|
||||
global.params.cpu = ARCHx86;
|
||||
if (global.params.useInlineAsm) {
|
||||
VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
|
||||
}
|
||||
}
|
||||
else if (strcmp(global.params.llvmArch,"x86-64")==0) {
|
||||
VersionCondition::addPredefinedGlobalIdent("X86_64");
|
||||
global.params.isLE = true;
|
||||
global.params.is64bit = true;
|
||||
global.params.cpu = ARCHx86_64;
|
||||
if (global.params.useInlineAsm) {
|
||||
VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86_64");
|
||||
}
|
||||
}
|
||||
else if (strcmp(global.params.llvmArch,"ppc32")==0) {
|
||||
VersionCondition::addPredefinedGlobalIdent("PPC");
|
||||
global.params.isLE = false;
|
||||
global.params.is64bit = false;
|
||||
global.params.cpu = ARCHppc;
|
||||
}
|
||||
else if (strcmp(global.params.llvmArch,"ppc64")==0) {
|
||||
VersionCondition::addPredefinedGlobalIdent("PPC64");
|
||||
global.params.isLE = false;
|
||||
global.params.is64bit = true;
|
||||
global.params.cpu = ARCHppc_64;
|
||||
}
|
||||
else if (strcmp(global.params.llvmArch,"arm")==0) {
|
||||
VersionCondition::addPredefinedGlobalIdent("ARM");
|
||||
global.params.isLE = true;
|
||||
global.params.is64bit = false;
|
||||
global.params.cpu = ARCHarm;
|
||||
}
|
||||
else if (strcmp(global.params.llvmArch,"thumb")==0) {
|
||||
VersionCondition::addPredefinedGlobalIdent("Thumb");
|
||||
global.params.isLE = true;
|
||||
global.params.is64bit = false;
|
||||
global.params.cpu = ARCHthumb;
|
||||
}
|
||||
else {
|
||||
error("invalid cpu architecture specified: %s", global.params.llvmArch);
|
||||
}
|
||||
|
||||
assert(global.params.cpu != ARCHinvalid);
|
||||
|
||||
if (allowForceEndianness && forceBE) {
|
||||
VersionCondition::addPredefinedGlobalIdent("BigEndian");
|
||||
global.params.isLE = false;
|
||||
}
|
||||
else if (global.params.isLE) {
|
||||
VersionCondition::addPredefinedGlobalIdent("LittleEndian");
|
||||
}
|
||||
else {
|
||||
VersionCondition::addPredefinedGlobalIdent("BigEndian");
|
||||
}
|
||||
|
||||
if (global.params.is64bit) {
|
||||
VersionCondition::addPredefinedGlobalIdent("LLVM64");
|
||||
}
|
||||
|
||||
|
||||
// setup version idents and tt_os for chosen target os
|
||||
switch(global.params.os)
|
||||
{
|
||||
case OSWindows:
|
||||
// TODO Win64 stuff!
|
||||
VersionCondition::addPredefinedGlobalIdent("Windows");
|
||||
VersionCondition::addPredefinedGlobalIdent("Win32");
|
||||
VersionCondition::addPredefinedGlobalIdent("mingw32");
|
||||
break;
|
||||
|
||||
case OSLinux:
|
||||
VersionCondition::addPredefinedGlobalIdent("linux");
|
||||
VersionCondition::addPredefinedGlobalIdent("Posix");
|
||||
break;
|
||||
|
||||
case OSMacOSX:
|
||||
VersionCondition::addPredefinedGlobalIdent("OSX");
|
||||
VersionCondition::addPredefinedGlobalIdent("darwin");
|
||||
VersionCondition::addPredefinedGlobalIdent("Posix");
|
||||
break;
|
||||
|
||||
case OSFreeBSD:
|
||||
VersionCondition::addPredefinedGlobalIdent("freebsd");
|
||||
VersionCondition::addPredefinedGlobalIdent("Posix");
|
||||
break;
|
||||
|
||||
case OSSolaris:
|
||||
VersionCondition::addPredefinedGlobalIdent("solaris");
|
||||
VersionCondition::addPredefinedGlobalIdent("Posix");
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false && "Target OS not supported");
|
||||
}
|
||||
|
||||
if (!global.params.targetTriple)
|
||||
global.params.targetTriple = DEFAULT_TARGET_TRIPLE;
|
||||
|
||||
Logger::println("Target triple: %s", global.params.targetTriple);
|
||||
|
||||
// build a minimal data layout so llvm can find the target
|
||||
global.params.dataLayout = global.params.isLE
|
||||
? (char*)(global.params.is64bit ? "e-p:64:64" : "e-p:32:32")
|
||||
: (char*)(global.params.is64bit ? "E-p:64:64" : "E-p:32:32");
|
||||
Logger::println("Layout: %s", global.params.dataLayout);
|
||||
|
||||
// added in 1.039
|
||||
if (global.params.doDocComments)
|
||||
VersionCondition::addPredefinedGlobalIdent("D_Ddoc");
|
||||
|
||||
// Initialization
|
||||
Type::init();
|
||||
Id::initialize();
|
||||
Module::init();
|
||||
initPrecedence();
|
||||
|
||||
backend_init();
|
||||
|
||||
//printf("%d source files\n",files.dim);
|
||||
|
||||
// Build import search path
|
||||
if (global.params.imppath)
|
||||
{
|
||||
for (i = 0; i < global.params.imppath->dim; i++)
|
||||
{
|
||||
char *path = (char *)global.params.imppath->data[i];
|
||||
Array *a = FileName::splitPath(path);
|
||||
|
||||
if (a)
|
||||
{
|
||||
if (!global.path)
|
||||
global.path = new Array();
|
||||
global.path->append(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build string import search path
|
||||
if (global.params.fileImppath)
|
||||
{
|
||||
for (i = 0; i < global.params.fileImppath->dim; i++)
|
||||
{
|
||||
char *path = (char *)global.params.fileImppath->data[i];
|
||||
Array *a = FileName::splitPath(path);
|
||||
|
||||
if (a)
|
||||
{
|
||||
if (!global.filePath)
|
||||
global.filePath = new Array();
|
||||
global.filePath->append(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create Modules
|
||||
Array modules;
|
||||
modules.reserve(files.dim);
|
||||
for (i = 0; i < files.dim; i++)
|
||||
{ Identifier *id;
|
||||
char *ext;
|
||||
char *name;
|
||||
|
||||
p = (char *) files.data[i];
|
||||
|
||||
p = FileName::name(p); // strip path
|
||||
ext = FileName::ext(p);
|
||||
if (ext)
|
||||
{
|
||||
#if POSIX
|
||||
if (strcmp(ext, global.obj_ext) == 0 ||
|
||||
strcmp(ext, global.bc_ext) == 0)
|
||||
#else
|
||||
if (stricmp(ext, global.obj_ext) == 0 ||
|
||||
stricmp(ext, global.bc_ext) == 0)
|
||||
#endif
|
||||
{
|
||||
global.params.objfiles->push(files.data[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
#if POSIX
|
||||
if (strcmp(ext, "a") == 0)
|
||||
#elif __MINGW32__
|
||||
if (stricmp(ext, "a") == 0)
|
||||
#else
|
||||
if (stricmp(ext, "lib") == 0)
|
||||
#endif
|
||||
{
|
||||
global.params.libfiles->push(files.data[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(ext, global.ddoc_ext) == 0)
|
||||
{
|
||||
global.params.ddocfiles->push(files.data[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
#if !POSIX
|
||||
if (stricmp(ext, "res") == 0)
|
||||
{
|
||||
global.params.resfile = (char *)files.data[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stricmp(ext, "def") == 0)
|
||||
{
|
||||
global.params.deffile = (char *)files.data[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stricmp(ext, "exe") == 0)
|
||||
{
|
||||
global.params.exefile = (char *)files.data[i];
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (stricmp(ext, global.mars_ext) == 0 ||
|
||||
stricmp(ext, global.hdr_ext) == 0 ||
|
||||
stricmp(ext, "htm") == 0 ||
|
||||
stricmp(ext, "html") == 0 ||
|
||||
stricmp(ext, "xhtml") == 0)
|
||||
{
|
||||
ext--; // skip onto '.'
|
||||
assert(*ext == '.');
|
||||
name = (char *)mem.malloc((ext - p) + 1);
|
||||
memcpy(name, p, ext - p);
|
||||
name[ext - p] = 0; // strip extension
|
||||
|
||||
if (name[0] == 0 ||
|
||||
strcmp(name, "..") == 0 ||
|
||||
strcmp(name, ".") == 0)
|
||||
{
|
||||
Linvalid:
|
||||
error("invalid file name '%s'", (char *)files.data[i]);
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ error("unrecognized file extension %s\n", ext);
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ name = p;
|
||||
if (!*name)
|
||||
goto Linvalid;
|
||||
}
|
||||
|
||||
id = new Identifier(name, 0);
|
||||
m = new Module((char *) files.data[i], id, global.params.doDocComments, global.params.doHdrGeneration);
|
||||
modules.push(m);
|
||||
}
|
||||
|
||||
// Read files, parse them
|
||||
for (i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = (Module *)modules.data[i];
|
||||
if (global.params.verbose)
|
||||
printf("parse %s\n", m->toChars());
|
||||
if (!Module::rootModule)
|
||||
Module::rootModule = m;
|
||||
m->importedFrom = m;
|
||||
m->read(0);
|
||||
m->parse();
|
||||
m->buildTargetFiles();
|
||||
m->deleteObjFile();
|
||||
if (m->isDocFile)
|
||||
{
|
||||
m->gendocfile();
|
||||
|
||||
// Remove m from list of modules
|
||||
modules.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (global.errors)
|
||||
fatal();
|
||||
#ifdef _DH
|
||||
if (global.params.doHdrGeneration)
|
||||
{
|
||||
/* Generate 'header' import files.
|
||||
* Since 'header' import files must be independent of command
|
||||
* line switches and what else is imported, they are generated
|
||||
* before any semantic analysis.
|
||||
*/
|
||||
for (i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = (Module *)modules.data[i];
|
||||
if (global.params.verbose)
|
||||
printf("import %s\n", m->toChars());
|
||||
m->genhdrfile();
|
||||
}
|
||||
}
|
||||
if (global.errors)
|
||||
fatal();
|
||||
#endif
|
||||
|
||||
// Do semantic analysis
|
||||
for (i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = (Module *)modules.data[i];
|
||||
if (global.params.verbose)
|
||||
printf("semantic %s\n", m->toChars());
|
||||
m->semantic();
|
||||
}
|
||||
if (global.errors)
|
||||
fatal();
|
||||
|
||||
// Do pass 2 semantic analysis
|
||||
for (i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = (Module *)modules.data[i];
|
||||
if (global.params.verbose)
|
||||
printf("semantic2 %s\n", m->toChars());
|
||||
m->semantic2();
|
||||
}
|
||||
if (global.errors)
|
||||
fatal();
|
||||
|
||||
// Do pass 3 semantic analysis
|
||||
for (i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = (Module *)modules.data[i];
|
||||
if (global.params.verbose)
|
||||
printf("semantic3 %s\n", m->toChars());
|
||||
m->semantic3();
|
||||
}
|
||||
if (global.errors)
|
||||
fatal();
|
||||
|
||||
#if !IN_LLVM
|
||||
// Scan for functions to inline
|
||||
if (global.params.useInline)
|
||||
{
|
||||
/* The problem with useArrayBounds and useAssert is that the
|
||||
* module being linked to may not have generated them, so if
|
||||
* we inline functions from those modules, the symbols for them will
|
||||
* not be found at link time.
|
||||
*/
|
||||
if (!global.params.useArrayBounds && !global.params.useAssert)
|
||||
{
|
||||
#endif
|
||||
// Do pass 3 semantic analysis on all imported modules,
|
||||
// since otherwise functions in them cannot be inlined
|
||||
for (i = 0; i < Module::amodules.dim; i++)
|
||||
{
|
||||
m = (Module *)Module::amodules.data[i];
|
||||
if (global.params.verbose)
|
||||
printf("semantic3 %s\n", m->toChars());
|
||||
m->semantic3();
|
||||
}
|
||||
if (global.errors)
|
||||
fatal();
|
||||
#if !IN_LLVM
|
||||
}
|
||||
|
||||
for (i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = (Module *)modules.data[i];
|
||||
if (global.params.verbose)
|
||||
printf("inline scan %s\n", m->toChars());
|
||||
m->inlineScan();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (global.errors)
|
||||
fatal();
|
||||
|
||||
// Generate output files
|
||||
for (i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = (Module *)modules.data[i];
|
||||
if (global.params.verbose)
|
||||
printf("code %s\n", m->toChars());
|
||||
if (global.params.obj)
|
||||
{
|
||||
m->genobjfile(0);
|
||||
global.params.objfiles->push(m->objfile->name->str);
|
||||
}
|
||||
if (global.errors)
|
||||
m->deleteObjFile();
|
||||
else
|
||||
{
|
||||
if (global.params.doDocComments)
|
||||
m->gendocfile();
|
||||
}
|
||||
}
|
||||
|
||||
backend_term();
|
||||
if (global.errors)
|
||||
fatal();
|
||||
|
||||
if (!global.params.objfiles->dim)
|
||||
{
|
||||
if (global.params.link)
|
||||
error("no object files to link");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (global.params.link)
|
||||
//status = runLINK();
|
||||
linkObjToExecutable(global.params.argv0);
|
||||
|
||||
if (global.params.run)
|
||||
{
|
||||
if (!status)
|
||||
{
|
||||
status = runExectuable();
|
||||
|
||||
/* Delete .obj files and .exe file
|
||||
*/
|
||||
for (i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = (Module *)modules.data[i];
|
||||
m->deleteObjFile();
|
||||
}
|
||||
deleteExecutable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************
|
||||
* Parse and append contents of environment variable envvar
|
||||
* to argc and argv[].
|
||||
|
|
|
@ -144,7 +144,6 @@ struct Param
|
|||
char *exefile;
|
||||
|
||||
// LDC stuff
|
||||
const char *llvmArch;
|
||||
OUTPUTFLAG output_ll;
|
||||
OUTPUTFLAG output_bc;
|
||||
OUTPUTFLAG output_s;
|
||||
|
@ -154,8 +153,9 @@ struct Param
|
|||
bool useInlineAsm;
|
||||
|
||||
// target stuff
|
||||
char *targetTriple;
|
||||
char *dataLayout;
|
||||
const char* llvmArch;
|
||||
const char *targetTriple;
|
||||
const char *dataLayout;
|
||||
};
|
||||
|
||||
struct Global
|
||||
|
@ -341,7 +341,7 @@ void error(Loc loc, const char *format, ...);
|
|||
void verror(Loc loc, const char *format, va_list);
|
||||
void fatal();
|
||||
void err_nomem();
|
||||
void inifile(char *argv0, char *inifile);
|
||||
void inifile(char *argv0, const char *inifile);
|
||||
void halt();
|
||||
|
||||
/*** Where to send error messages ***/
|
||||
|
|
|
@ -33,6 +33,15 @@
|
|||
|
||||
#include "../gen/enums.h"
|
||||
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
static llvm::cl::opt<bool> ignoreUnsupportedPragmas("ignore",
|
||||
llvm::cl::desc("Ignore unsupported pragmas"),
|
||||
llvm::cl::ZeroOrMore);
|
||||
|
||||
|
||||
|
||||
extern void obj_includelib(const char *name);
|
||||
void obj_startaddress(Symbol *s);
|
||||
|
||||
|
@ -1001,7 +1010,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||
/////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
else if (global.params.ignoreUnsupportedPragmas)
|
||||
else if (ignoreUnsupportedPragmas)
|
||||
{
|
||||
if (global.params.verbose)
|
||||
{
|
||||
|
|
|
@ -43,7 +43,7 @@ char *strupr(char *s)
|
|||
* inifile .ini file name
|
||||
*/
|
||||
|
||||
void inifile(const char *argv0x, const char *inifilex)
|
||||
void inifile(char *argv0x, const char *inifilex)
|
||||
{
|
||||
char *argv0 = (char *)argv0x;
|
||||
char *inifile = (char *)inifilex; // do const-correct later
|
||||
|
|
1341
dmd2/mars.c
1341
dmd2/mars.c
File diff suppressed because it is too large
Load diff
240
dmd2/mars.h
240
dmd2/mars.h
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -32,8 +33,8 @@
|
|||
/* Changes for the GDC compiler by David Friedman */
|
||||
#endif
|
||||
|
||||
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
|
||||
#define STRUCTTHISREF V2 // if 'this' for struct is a reference, not a pointer
|
||||
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
|
||||
#define STRUCTTHISREF V2 // if 'this' for struct is a reference, not a pointer
|
||||
|
||||
struct Array;
|
||||
|
||||
|
@ -72,83 +73,68 @@ enum OS
|
|||
// Put command line switches in here
|
||||
struct Param
|
||||
{
|
||||
char obj; // write object file
|
||||
char link; // perform link
|
||||
char lib; // write library file instead of object file(s)
|
||||
char multiobj; // break one object file into multiple ones
|
||||
char oneobj; // write one object file instead of multiple ones
|
||||
char trace; // insert profiling hooks
|
||||
char quiet; // suppress non-error messages
|
||||
char verbose; // verbose compile
|
||||
char symdebug; // insert debug symbolic information
|
||||
char optimize; // run optimizer
|
||||
bool obj; // write object file
|
||||
bool link; // perform link
|
||||
bool verbose; // verbose compile
|
||||
char symdebug; // insert debug symbolic information
|
||||
bool optimize; // run optimizer
|
||||
char optimizeLevel; // optimization level
|
||||
ARCH cpu; // target CPU
|
||||
OS os; // target OS
|
||||
char is64bit; // generate 64 bit code
|
||||
char isLE; // generate little endian code
|
||||
char scheduler; // which scheduler to use
|
||||
char useDeprecated; // allow use of deprecated features
|
||||
char useAssert; // generate runtime code for assert()'s
|
||||
char useInvariants; // generate class invariant checks
|
||||
char useIn; // generate precondition checks
|
||||
char useOut; // generate postcondition checks
|
||||
char useArrayBounds; // generate array bounds checks
|
||||
char useSwitchError; // check for switches without a default
|
||||
char useUnitTests; // generate unittest code
|
||||
char useInline; // inline expand functions
|
||||
char release; // build release version
|
||||
char preservePaths; // !=0 means don't strip path from source file
|
||||
char warnings; // enable warnings
|
||||
char pic; // generate position-independent-code for shared libs
|
||||
char noruntime; // code is not allowed to make implicit calls to the runtime
|
||||
char novalidate;// no bitcode validation
|
||||
char Dversion; // D version number
|
||||
char ignoreUnsupportedPragmas; // rather than error on them
|
||||
char safe; // enforce safe memory model
|
||||
ARCH cpu; // target CPU
|
||||
OS os; // target OS
|
||||
bool is64bit; // generate 64 bit code
|
||||
bool isLE; // generate little endian code
|
||||
bool useDeprecated; // allow use of deprecated features
|
||||
bool useAssert; // generate runtime code for assert()'s
|
||||
bool useInvariants; // generate class invariant checks
|
||||
bool useIn; // generate precondition checks
|
||||
bool useOut; // generate postcondition checks
|
||||
bool useArrayBounds; // generate array bounds checks
|
||||
bool useSwitchError; // check for switches without a default
|
||||
bool useUnitTests; // generate unittest code
|
||||
bool useInline; // inline expand functions
|
||||
bool warnings; // enable warnings
|
||||
bool safe; // enforce safe memory model
|
||||
char Dversion; // D version number
|
||||
|
||||
char *argv0; // program name
|
||||
Array *imppath; // array of char*'s of where to look for import modules
|
||||
Array *fileImppath; // array of char*'s of where to look for file import modules
|
||||
char *runtimeImppath; // char* of where to look for the core runtime
|
||||
char *objdir; // .obj file output directory
|
||||
char *objname; // .obj file output name
|
||||
char *argv0; // program name
|
||||
Array *imppath; // array of char*'s of where to look for import modules
|
||||
Array *fileImppath; // array of char*'s of where to look for file import modules
|
||||
char *objdir; // .obj file output directory
|
||||
char *objname; // .obj file output name
|
||||
|
||||
char doDocComments; // process embedded documentation comments
|
||||
char *docdir; // write documentation file to docdir directory
|
||||
char *docname; // write documentation file to docname
|
||||
Array *ddocfiles; // macro include files for Ddoc
|
||||
bool doDocComments; // process embedded documentation comments
|
||||
char *docdir; // write documentation file to docdir directory
|
||||
char *docname; // write documentation file to docname
|
||||
Array *ddocfiles; // macro include files for Ddoc
|
||||
|
||||
char doHdrGeneration; // process embedded documentation comments
|
||||
char *hdrdir; // write 'header' file to docdir directory
|
||||
char *hdrname; // write 'header' file to docname
|
||||
bool doHdrGeneration; // process embedded documentation comments
|
||||
char *hdrdir; // write 'header' file to docdir directory
|
||||
char *hdrname; // write 'header' file to docname
|
||||
|
||||
unsigned debuglevel; // debug level
|
||||
Array *debugids; // debug identifiers
|
||||
unsigned debuglevel; // debug level
|
||||
Array *debugids; // debug identifiers
|
||||
|
||||
unsigned versionlevel; // version level
|
||||
Array *versionids; // version identifiers
|
||||
unsigned versionlevel; // version level
|
||||
Array *versionids; // version identifiers
|
||||
|
||||
bool dump_source;
|
||||
|
||||
Array *defaultlibnames; // default libraries for non-debug builds
|
||||
Array *debuglibnames; // default libraries for debug builds
|
||||
Array *defaultlibnames; // default libraries for non-debug builds
|
||||
Array *debuglibnames; // default libraries for debug builds
|
||||
|
||||
const char *xmlname; // filename for XML output
|
||||
char *xmlname; // filename for XML output
|
||||
|
||||
// Hidden debug switches
|
||||
char debuga;
|
||||
char debugb;
|
||||
char debugc;
|
||||
char debugf;
|
||||
char debugr;
|
||||
char debugw;
|
||||
char debugx;
|
||||
char debugy;
|
||||
bool debuga;
|
||||
bool debugb;
|
||||
bool debugc;
|
||||
bool debugf;
|
||||
bool debugr;
|
||||
bool debugw;
|
||||
bool debugx;
|
||||
bool debugy;
|
||||
|
||||
char run; // run resulting executable
|
||||
size_t runargs_length;
|
||||
char** runargs; // arguments for executable
|
||||
bool run; // run resulting executable
|
||||
|
||||
// Linker stuff
|
||||
Array *objfiles;
|
||||
|
@ -159,50 +145,46 @@ struct Param
|
|||
char *exefile;
|
||||
|
||||
// LDC stuff
|
||||
const char *llvmArch;
|
||||
char forceBE;
|
||||
char output_ll;
|
||||
char output_bc;
|
||||
char output_s;
|
||||
char output_o;
|
||||
char llvmInline;
|
||||
char llvmAnnotate;
|
||||
char useInlineAsm;
|
||||
char fqnNames; // use fully qualified object names
|
||||
char noDefaultLib;
|
||||
OUTPUTFLAG output_ll;
|
||||
OUTPUTFLAG output_bc;
|
||||
OUTPUTFLAG output_s;
|
||||
OUTPUTFLAG output_o;
|
||||
bool llvmInline;
|
||||
bool llvmAnnotate;
|
||||
bool useInlineAsm;
|
||||
|
||||
// target stuff
|
||||
const char* llvmArch;
|
||||
const char *targetTriple;
|
||||
const char *dataLayout;
|
||||
};
|
||||
|
||||
struct Global
|
||||
{
|
||||
const char *mars_ext;
|
||||
const char *sym_ext;
|
||||
const char *obj_ext;
|
||||
char *mars_ext;
|
||||
char *sym_ext;
|
||||
char *obj_ext;
|
||||
#if _WIN32
|
||||
const char *obj_ext_alt;
|
||||
char *obj_ext_alt;
|
||||
#endif
|
||||
const char *ll_ext;
|
||||
const char *bc_ext;
|
||||
const char *s_ext;
|
||||
const char *lib_ext;
|
||||
const char *doc_ext; // for Ddoc generated files
|
||||
const char *ddoc_ext; // for Ddoc macro include files
|
||||
const char *hdr_ext; // for D 'header' import files
|
||||
const char *copyright;
|
||||
const char *written;
|
||||
Array *path; // Array of char*'s which form the import lookup path
|
||||
Array *filePath; // Array of char*'s which form the file import lookup path
|
||||
char *ll_ext;
|
||||
char *bc_ext;
|
||||
char *s_ext;
|
||||
char *doc_ext; // for Ddoc generated files
|
||||
char *ddoc_ext; // for Ddoc macro include files
|
||||
char *hdr_ext; // for D 'header' import files
|
||||
char *copyright;
|
||||
char *written;
|
||||
Array *path; // Array of char*'s which form the import lookup path
|
||||
Array *filePath; // Array of char*'s which form the file import lookup path
|
||||
int structalign;
|
||||
const char *version;
|
||||
const char *ldc_version;
|
||||
const char *llvm_version;
|
||||
char *version;
|
||||
char *ldc_version;
|
||||
char *llvm_version;
|
||||
|
||||
Param params;
|
||||
unsigned errors; // number of errors reported so far
|
||||
unsigned gag; // !=0 means gag reporting of errors
|
||||
unsigned errors; // number of errors reported so far
|
||||
unsigned gag; // !=0 means gag reporting of errors
|
||||
|
||||
Global();
|
||||
};
|
||||
|
@ -212,7 +194,7 @@ extern Global global;
|
|||
/* Set if Windows Structured Exception Handling C extensions are supported.
|
||||
* Apparently, VC has dropped support for these?
|
||||
*/
|
||||
#define WINDOWS_SEH _WIN32 && __DMC__
|
||||
#define WINDOWS_SEH (_WIN32 && __DMC__)
|
||||
|
||||
|
||||
#if __GNUC__
|
||||
|
@ -239,22 +221,22 @@ typedef uint64_t integer_t;
|
|||
typedef int64_t sinteger_t;
|
||||
typedef uint64_t uinteger_t;
|
||||
|
||||
typedef int8_t d_int8;
|
||||
typedef uint8_t d_uns8;
|
||||
typedef int16_t d_int16;
|
||||
typedef uint16_t d_uns16;
|
||||
typedef int32_t d_int32;
|
||||
typedef uint32_t d_uns32;
|
||||
typedef int64_t d_int64;
|
||||
typedef uint64_t d_uns64;
|
||||
typedef int8_t d_int8;
|
||||
typedef uint8_t d_uns8;
|
||||
typedef int16_t d_int16;
|
||||
typedef uint16_t d_uns16;
|
||||
typedef int32_t d_int32;
|
||||
typedef uint32_t d_uns32;
|
||||
typedef int64_t d_int64;
|
||||
typedef uint64_t d_uns64;
|
||||
|
||||
typedef float d_float32;
|
||||
typedef double d_float64;
|
||||
typedef long double d_float80;
|
||||
typedef float d_float32;
|
||||
typedef double d_float64;
|
||||
typedef long double d_float80;
|
||||
|
||||
typedef d_uns8 d_char;
|
||||
typedef d_uns16 d_wchar;
|
||||
typedef d_uns32 d_dchar;
|
||||
typedef d_uns8 d_char;
|
||||
typedef d_uns16 d_wchar;
|
||||
typedef d_uns32 d_dchar;
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
|
@ -289,7 +271,7 @@ typedef long double real_t;
|
|||
|
||||
struct Module;
|
||||
|
||||
//typedef unsigned Loc; // file location
|
||||
//typedef unsigned Loc; // file location
|
||||
struct Loc
|
||||
{
|
||||
char *filename;
|
||||
|
@ -297,14 +279,14 @@ struct Loc
|
|||
|
||||
Loc()
|
||||
{
|
||||
linnum = 0;
|
||||
filename = NULL;
|
||||
linnum = 0;
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
Loc(int x)
|
||||
{
|
||||
linnum = x;
|
||||
filename = NULL;
|
||||
linnum = x;
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
Loc(Module *mod, unsigned linnum);
|
||||
|
@ -313,15 +295,15 @@ struct Loc
|
|||
};
|
||||
|
||||
#ifndef GCC_SAFE_DMD
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
|
||||
// in interface vtbl[]'s
|
||||
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
|
||||
// in the inheritance graph multiple
|
||||
// times, only one is used
|
||||
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
|
||||
// in interface vtbl[]'s
|
||||
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
|
||||
// in the inheritance graph multiple
|
||||
// times, only one is used
|
||||
|
||||
enum LINK
|
||||
{
|
||||
|
@ -348,19 +330,19 @@ enum DYNCAST
|
|||
|
||||
enum MATCH
|
||||
{
|
||||
MATCHnomatch, // no match
|
||||
MATCHconvert, // match with conversions
|
||||
MATCHnomatch, // no match
|
||||
MATCHconvert, // match with conversions
|
||||
#if DMDV2
|
||||
MATCHconst, // match with conversion to const
|
||||
MATCHconst, // match with conversion to const
|
||||
#endif
|
||||
MATCHexact // exact match
|
||||
MATCHexact // exact match
|
||||
};
|
||||
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void verror(Loc loc, const char *format, va_list);
|
||||
void fatal();
|
||||
void err_nomem();
|
||||
void inifile(const char *argv0, const char *inifile);
|
||||
void inifile(char *argv0, const char *inifile);
|
||||
void halt();
|
||||
|
||||
/*** Where to send error messages ***/
|
||||
|
|
|
@ -40,6 +40,19 @@
|
|||
#include "d-dmd-gcc.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
static llvm::cl::opt<bool> preservePaths("op",
|
||||
llvm::cl::desc("Do not strip paths from source file"),
|
||||
llvm::cl::ZeroOrMore);
|
||||
|
||||
static llvm::cl::opt<bool> fqnNames("oq",
|
||||
llvm::cl::desc("Write object files with fully qualified names"),
|
||||
llvm::cl::ZeroOrMore);
|
||||
|
||||
|
||||
|
||||
ClassDeclaration *Module::moduleinfo;
|
||||
|
||||
Module *Module::rootModule;
|
||||
|
@ -139,12 +152,12 @@ File* Module::buildFilePath(char* forcename, const char* path, const char* ext)
|
|||
argobj = forcename;
|
||||
else
|
||||
{
|
||||
if (global.params.preservePaths)
|
||||
if (preservePaths)
|
||||
argobj = (char*)this->arg;
|
||||
else
|
||||
argobj = FileName::name((char*)this->arg);
|
||||
|
||||
if (global.params.fqnNames)
|
||||
if (fqnNames)
|
||||
{
|
||||
if(md)
|
||||
argobj = FileName::replaceName(argobj, md->toChars());
|
||||
|
|
|
@ -230,22 +230,18 @@ static cl::alias m("m",
|
|||
cl::Prefix,
|
||||
cl::aliasopt(mArch));
|
||||
|
||||
cl::opt<std::string> mCPU("mcpu",
|
||||
cl::desc("Target a specific cpu type (-mcpu=help for details)"),
|
||||
cl::value_desc("cpu-name"),
|
||||
cl::init(""));
|
||||
|
||||
static cl::opt<OS, true> os("t",
|
||||
cl::desc("Emit code for the specified OS:"),
|
||||
cl::values(
|
||||
#define ENUMVAL_N(Name, Desc) clEnumValN(OS##Name, #Name, Desc)
|
||||
#define ENUMVAL(Name) ENUMVAL_N(Name, #Name)
|
||||
ENUMVAL(Linux),
|
||||
ENUMVAL(Windows),
|
||||
ENUMVAL_N(MacOSX, "Mac OS X"),
|
||||
ENUMVAL(FreeBSD),
|
||||
ENUMVAL(Solaris),
|
||||
#undef ENUMVAL
|
||||
#undef ENUMVAL_N
|
||||
clEnumValEnd),
|
||||
cl::Prefix,
|
||||
cl::location(global.params.os));
|
||||
cl::list<std::string> mAttrs("mattr",
|
||||
cl::CommaSeparated,
|
||||
cl::desc("Target specific attributes (-mattr=help for details)"),
|
||||
cl::value_desc("a1,+a2,-a3,..."));
|
||||
|
||||
cl::opt<std::string> mTargetTriple("mtriple",
|
||||
cl::desc("Override target triple"));
|
||||
|
||||
|
||||
// "Hidden debug switches"
|
||||
|
|
|
@ -38,6 +38,9 @@ namespace opts {
|
|||
|
||||
extern cl::opt<const llvm::TargetMachineRegistry::entry*, false,
|
||||
llvm::RegistryParser<llvm::TargetMachine> > mArch;
|
||||
extern cl::opt<std::string> mCPU;
|
||||
extern cl::list<std::string> mAttrs;
|
||||
extern cl::opt<std::string> mTargetTriple;
|
||||
|
||||
// Arguments to -d-debug
|
||||
extern std::vector<std::string> debugArgs;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "gen/todebug.h"
|
||||
#include "gen/classes.h"
|
||||
#include "gen/dvalue.h"
|
||||
#include "gen/abi.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -53,40 +54,49 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
|
|||
// parameter types
|
||||
std::vector<const LLType*> paramvec;
|
||||
|
||||
// special case main
|
||||
if (ismain)
|
||||
{
|
||||
rettype = LLType::Int32Ty;
|
||||
actualRettype = rettype;
|
||||
if (Argument::dim(f->parameters) == 0)
|
||||
{
|
||||
const LLType* arrTy = DtoArrayType(LLType::Int8Ty);
|
||||
const LLType* arrArrTy = DtoArrayType(arrTy);
|
||||
paramvec.push_back(arrArrTy);
|
||||
const LLType* arrTy = DtoArrayType(LLType::Int8Ty);
|
||||
const LLType* arrArrTy = DtoArrayType(arrTy);
|
||||
paramvec.push_back(arrArrTy);
|
||||
}
|
||||
}
|
||||
else{
|
||||
// default handling
|
||||
else
|
||||
{
|
||||
assert(rt);
|
||||
if (DtoIsReturnedInArg(rt)) {
|
||||
if (gABI->returnInArg(rt))
|
||||
{
|
||||
rettype = getPtrToType(DtoType(rt));
|
||||
actualRettype = LLType::VoidTy;
|
||||
f->retInPtr = retinptr = true;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
rettype = DtoType(rt);
|
||||
actualRettype = rettype;
|
||||
// do abi specific transformations
|
||||
actualRettype = gABI->getRetType(f, rettype);
|
||||
}
|
||||
|
||||
// FIXME: should probably be part of the abi
|
||||
if (unsigned ea = DtoShouldExtend(rt))
|
||||
{
|
||||
f->retAttrs |= ea;
|
||||
}
|
||||
}
|
||||
|
||||
// build up parameter list
|
||||
if (retinptr) {
|
||||
//Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
|
||||
paramvec.push_back(rettype);
|
||||
}
|
||||
|
||||
// this/context param
|
||||
if (thistype) {
|
||||
paramvec.push_back(thistype);
|
||||
usesthis = true;
|
||||
|
@ -96,6 +106,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
|
|||
usesnest = true;
|
||||
}
|
||||
|
||||
// dstyle vararg
|
||||
if (dVararg) {
|
||||
paramvec.push_back(DtoType(Type::typeinfo->type->arrayOf())); // _arguments
|
||||
paramvec.push_back(getVoidPtrType()); // _argptr
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
#include "tollvm.h"
|
||||
|
||||
IRState* gIR = 0;
|
||||
llvm::TargetMachine* gTargetMachine = 0;
|
||||
const llvm::TargetData* gTargetData = 0;
|
||||
TargetABI* gABI = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRScope::IRScope()
|
||||
|
|
|
@ -13,10 +13,18 @@
|
|||
#include "ir/irstruct.h"
|
||||
#include "ir/irvar.h"
|
||||
|
||||
namespace llvm {
|
||||
class TargetMachine;
|
||||
}
|
||||
|
||||
// global ir state for current module
|
||||
struct IRState;
|
||||
struct TargetABI;
|
||||
|
||||
extern IRState* gIR;
|
||||
extern llvm::TargetMachine* gTargetMachine;
|
||||
extern const llvm::TargetData* gTargetData;
|
||||
extern TargetABI* gABI;
|
||||
|
||||
struct TypeFunction;
|
||||
struct TypeStruct;
|
||||
|
|
|
@ -218,6 +218,8 @@ void emitABIReturnAsmStmt(IRAsmBlock* asmblock, Loc loc, FuncDeclaration* fdecl)
|
|||
// this is to show how to allocate a temporary for the return value
|
||||
// in case the appropriate multi register constraint isn't supported.
|
||||
// this way abi return from inline asm can still be emulated.
|
||||
// note that "$<<out0>>" etc in the asm will translate to the correct
|
||||
// numbered output when the asm block in finalized
|
||||
|
||||
// generate asm
|
||||
as->out_c = "=*m,=*m,";
|
||||
|
@ -231,7 +233,7 @@ void emitABIReturnAsmStmt(IRAsmBlock* asmblock, Loc loc, FuncDeclaration* fdecl)
|
|||
asmblock->retemu = true;
|
||||
asmblock->asmBlock->abiret = tmp;
|
||||
|
||||
// add "ret" stmt
|
||||
// add "ret" stmt at the end of the block
|
||||
asmblock->s.push_back(as);
|
||||
|
||||
// done, we don't want anything pushed in the front of the block
|
||||
|
@ -276,17 +278,9 @@ void emitABIReturnAsmStmt(IRAsmBlock* asmblock, Loc loc, FuncDeclaration* fdecl)
|
|||
// LLVM and GCC disagree on how to return {float, float}.
|
||||
// For compatibility, use the GCC/LLVM-GCC way for extern(C/Windows)
|
||||
// extern(C) cfloat -> %xmm0 (extract two floats)
|
||||
#if 0
|
||||
// Disabled because "regular" extern(C) functions aren't
|
||||
// ABI-compatible with GCC yet.
|
||||
// TODO: enable when "extern(C) cfloat foo();" compiles to "declare { double } @foo();"
|
||||
as->out_c = "={xmm0},";
|
||||
asmblock->retty = LLStructType::get(LLType::DoubleTy, NULL);;
|
||||
asmblock->retfixup = &x86_64_cfloatRetFixup;
|
||||
#else
|
||||
error(loc, "unimplemented return type '%s' for implicit abi return", rt->toChars());
|
||||
fatal();
|
||||
#endif
|
||||
} else if (rt->iscomplex()) {
|
||||
// cdouble and extern(D) cfloat -> re=%xmm0, im=%xmm1
|
||||
as->out_c = "={xmm0},={xmm1},";
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "gen/arrays.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/dvalue.h"
|
||||
#include "gen/abi.h"
|
||||
|
||||
#include "ir/irfunction.h"
|
||||
#include "ir/irmodule.h"
|
||||
|
@ -54,38 +55,47 @@ void ReturnStatement::toIR(IRState* p)
|
|||
Logger::println("ReturnStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// is there a return value expression?
|
||||
if (exp)
|
||||
{
|
||||
if (p->topfunc()->getReturnType() == LLType::VoidTy) {
|
||||
// if the functions return type is void this means that
|
||||
// we are returning through a pointer argument
|
||||
if (p->topfunc()->getReturnType() == LLType::VoidTy)
|
||||
{
|
||||
// sanity check
|
||||
IrFunction* f = p->func();
|
||||
assert(f->type->retInPtr);
|
||||
assert(f->decl->ir.irFunc->retArg);
|
||||
|
||||
// emit dbg line
|
||||
if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
// get return pointer
|
||||
DValue* rvar = new DVarValue(f->type->next, f->decl->ir.irFunc->retArg);
|
||||
|
||||
DValue* e = exp->toElem(p);
|
||||
|
||||
// store return value
|
||||
DtoAssign(loc, rvar, e);
|
||||
|
||||
// emit scopes
|
||||
DtoEnclosingHandlers(enclosinghandler, NULL);
|
||||
|
||||
// emit dbg end function
|
||||
if (global.params.symdebug) DtoDwarfFuncEnd(f->decl);
|
||||
|
||||
// emit ret
|
||||
llvm::ReturnInst::Create(p->scopebb());
|
||||
|
||||
}
|
||||
else {
|
||||
// the return type is not void, so this is a normal "register" return
|
||||
else
|
||||
{
|
||||
if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
|
||||
DValue* e = exp->toElem(p);
|
||||
LLValue* v = e->getRVal();
|
||||
delete e;
|
||||
|
||||
// swap real/imag parts on a x87
|
||||
if (global.params.cpu == ARCHx86 && exp->type->toBasetype()->iscomplex())
|
||||
{
|
||||
v = DtoAggrPairSwap(v);
|
||||
}
|
||||
// do abi specific transformations on the return value
|
||||
v = gABI->putRet(p->func()->type, v);
|
||||
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "return value is '" <<*v << "'\n";
|
||||
|
@ -113,6 +123,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
llvm::ReturnInst::Create(v, p->scopebb());
|
||||
}
|
||||
}
|
||||
// no return value expression means it's a void function
|
||||
else
|
||||
{
|
||||
assert(p->topfunc()->getReturnType() == LLType::VoidTy);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "gen/irstate.h"
|
||||
#include "gen/dvalue.h"
|
||||
#include "gen/functions.h"
|
||||
#include "gen/abi.h"
|
||||
|
||||
#include "gen/logger.h"
|
||||
|
||||
|
@ -463,11 +464,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
// get return value
|
||||
LLValue* retllval = (retinptr) ? args[0] : call->get();
|
||||
|
||||
// swap real/imag parts on a x87
|
||||
if (global.params.cpu == ARCHx86 && tf->nextOf()->toBasetype()->iscomplex())
|
||||
{
|
||||
retllval = DtoAggrPairSwap(retllval);
|
||||
}
|
||||
// do abi specific return value fixups
|
||||
retllval = gABI->getRet(tf, retllval);
|
||||
|
||||
// repaint the type if necessary
|
||||
if (resulttype)
|
||||
|
|
|
@ -28,13 +28,6 @@ bool DtoIsPassedByRef(Type* type)
|
|||
return (t == Tstruct || t == Tsarray);
|
||||
}
|
||||
|
||||
bool DtoIsReturnedInArg(Type* type)
|
||||
{
|
||||
Type* typ = type->toBasetype();
|
||||
TY t = typ->ty;
|
||||
return (t == Tstruct || t == Tsarray);
|
||||
}
|
||||
|
||||
unsigned DtoShouldExtend(Type* type)
|
||||
{
|
||||
type = type->toBasetype();
|
||||
|
|
|
@ -18,9 +18,7 @@ const LLType* DtoTypeNotVoid(Type* t);
|
|||
// returns true is the type must be passed by pointer
|
||||
bool DtoIsPassedByRef(Type* type);
|
||||
|
||||
// returns if the type should be returned in a hidden pointer arguement
|
||||
bool DtoIsReturnedInArg(Type* type);
|
||||
|
||||
// should argument be zero or sign extended
|
||||
unsigned DtoShouldExtend(Type* type);
|
||||
|
||||
// tuple helper
|
||||
|
|
|
@ -14,9 +14,6 @@
|
|||
#include "gen/llvm.h"
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Bitcode/ReaderWriter.h"
|
||||
#include "llvm/Target/SubtargetFeature.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetMachineRegistry.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/ModuleProvider.h"
|
||||
#include "llvm/PassManager.h"
|
||||
|
@ -25,6 +22,7 @@
|
|||
#include "llvm/System/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "module.h"
|
||||
|
@ -50,6 +48,8 @@
|
|||
#include "gen/functions.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/abi.h"
|
||||
#include "gen/cl_options.h"
|
||||
|
||||
#include "ir/irvar.h"
|
||||
#include "ir/irmodule.h"
|
||||
|
@ -110,40 +110,16 @@ void Module::genobjfile(int multiobj)
|
|||
// FIXME: but shouldn't this always get reset between modules? like other IrSymbols
|
||||
this->ir.irModule = new IrModule(this, srcfile->toChars());
|
||||
|
||||
// set target stuff
|
||||
|
||||
// set target triple
|
||||
ir.module->setTargetTriple(global.params.targetTriple);
|
||||
ir.module->setDataLayout(global.params.dataLayout);
|
||||
|
||||
// get the target machine
|
||||
const llvm::TargetMachineRegistry::entry* MArch;
|
||||
|
||||
std::string Err;
|
||||
MArch = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(*ir.module, Err);
|
||||
if (MArch == 0) {
|
||||
error("error auto-selecting target for module '%s'", Err.c_str());
|
||||
fatal();
|
||||
}
|
||||
|
||||
llvm::SubtargetFeatures Features;
|
||||
//TODO: Features?
|
||||
// Features.setCPU(MCPU);
|
||||
// for (unsigned i = 0; i != MAttrs.size(); ++i)
|
||||
// Features.AddFeature(MAttrs[i]);
|
||||
|
||||
// allocate the target machine
|
||||
std::auto_ptr<llvm::TargetMachine> target(MArch->CtorFn(*ir.module, Features.getString()));
|
||||
assert(target.get() && "Could not allocate target machine!");
|
||||
llvm::TargetMachine &Target = *target.get();
|
||||
|
||||
gTargetData = Target.getTargetData();
|
||||
|
||||
// set final data layout
|
||||
std::string datalayout = gTargetData->getStringRepresentation();
|
||||
ir.module->setDataLayout(datalayout);
|
||||
ir.module->setDataLayout(global.params.dataLayout);
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "Final data layout: " << datalayout << '\n';
|
||||
assert(memcmp(global.params.dataLayout, datalayout.c_str(), 9) == 0); // "E-p:xx:xx"
|
||||
Logger::cout() << "Final data layout: " << global.params.dataLayout << '\n';
|
||||
|
||||
// allocate the target abi
|
||||
gABI = TargetABI::getTarget();
|
||||
|
||||
// debug info
|
||||
if (global.params.symdebug) {
|
||||
|
@ -252,7 +228,7 @@ void Module::genobjfile(int multiobj)
|
|||
std::string err;
|
||||
{
|
||||
llvm::raw_fd_ostream out(spath.c_str(), false, err);
|
||||
write_asm_to_file(Target, *ir.module, out);
|
||||
write_asm_to_file(*gTargetMachine, *ir.module, out);
|
||||
}
|
||||
|
||||
// call gcc to convert assembly to object file
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue