mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 00:20:40 +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
|
struct DebugCondition : DVCondition
|
||||||
{
|
{
|
||||||
static void setGlobalLevel(unsigned level);
|
static void setGlobalLevel(unsigned level);
|
||||||
static void addGlobalIdent(char *ident);
|
static void addGlobalIdent(const char *ident);
|
||||||
static void addPredefinedGlobalIdent(char *ident);
|
static void addPredefinedGlobalIdent(const char *ident);
|
||||||
|
|
||||||
DebugCondition(Module *mod, unsigned level, Identifier *ident);
|
DebugCondition(Module *mod, unsigned level, Identifier *ident);
|
||||||
|
|
||||||
|
@ -67,9 +67,9 @@ struct DebugCondition : DVCondition
|
||||||
struct VersionCondition : DVCondition
|
struct VersionCondition : DVCondition
|
||||||
{
|
{
|
||||||
static void setGlobalLevel(unsigned level);
|
static void setGlobalLevel(unsigned level);
|
||||||
static void checkPredefined(Loc loc, char *ident);
|
static void checkPredefined(Loc loc, const char *ident);
|
||||||
static void addGlobalIdent(char *ident);
|
static void addGlobalIdent(const char *ident);
|
||||||
static void addPredefinedGlobalIdent(char *ident);
|
static void addPredefinedGlobalIdent(const char *ident);
|
||||||
|
|
||||||
VersionCondition(Module *mod, unsigned level, Identifier *ident);
|
VersionCondition(Module *mod, unsigned level, Identifier *ident);
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ char *strupr(char *s)
|
||||||
* inifile .ini file name
|
* 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 *path; // need path for @P macro
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|
797
dmd/mars.c
797
dmd/mars.c
|
@ -36,48 +36,8 @@
|
||||||
#include "expression.h"
|
#include "expression.h"
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
|
|
||||||
#include "gen/logger.h"
|
|
||||||
#include "gen/linker.h"
|
|
||||||
#include "revisions.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;
|
||||||
|
|
||||||
Global::Global()
|
Global::Global()
|
||||||
|
@ -187,763 +147,6 @@ void halt()
|
||||||
#endif
|
#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
|
* Parse and append contents of environment variable envvar
|
||||||
* to argc and argv[].
|
* to argc and argv[].
|
||||||
|
|
|
@ -144,7 +144,6 @@ struct Param
|
||||||
char *exefile;
|
char *exefile;
|
||||||
|
|
||||||
// LDC stuff
|
// LDC stuff
|
||||||
const char *llvmArch;
|
|
||||||
OUTPUTFLAG output_ll;
|
OUTPUTFLAG output_ll;
|
||||||
OUTPUTFLAG output_bc;
|
OUTPUTFLAG output_bc;
|
||||||
OUTPUTFLAG output_s;
|
OUTPUTFLAG output_s;
|
||||||
|
@ -154,8 +153,9 @@ struct Param
|
||||||
bool useInlineAsm;
|
bool useInlineAsm;
|
||||||
|
|
||||||
// target stuff
|
// target stuff
|
||||||
char *targetTriple;
|
const char* llvmArch;
|
||||||
char *dataLayout;
|
const char *targetTriple;
|
||||||
|
const char *dataLayout;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Global
|
struct Global
|
||||||
|
@ -341,7 +341,7 @@ void error(Loc loc, const char *format, ...);
|
||||||
void verror(Loc loc, const char *format, va_list);
|
void verror(Loc loc, const char *format, va_list);
|
||||||
void fatal();
|
void fatal();
|
||||||
void err_nomem();
|
void err_nomem();
|
||||||
void inifile(char *argv0, char *inifile);
|
void inifile(char *argv0, const char *inifile);
|
||||||
void halt();
|
void halt();
|
||||||
|
|
||||||
/*** Where to send error messages ***/
|
/*** Where to send error messages ***/
|
||||||
|
|
|
@ -33,6 +33,15 @@
|
||||||
|
|
||||||
#include "../gen/enums.h"
|
#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);
|
extern void obj_includelib(const char *name);
|
||||||
void obj_startaddress(Symbol *s);
|
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)
|
if (global.params.verbose)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,7 +43,7 @@ char *strupr(char *s)
|
||||||
* inifile .ini file name
|
* inifile .ini file name
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void inifile(const char *argv0x, const char *inifilex)
|
void inifile(char *argv0x, const char *inifilex)
|
||||||
{
|
{
|
||||||
char *argv0 = (char *)argv0x;
|
char *argv0 = (char *)argv0x;
|
||||||
char *inifile = (char *)inifilex; // do const-correct later
|
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 <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
#define __STDC_FORMAT_MACROS 1
|
#define __STDC_FORMAT_MACROS 1
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -32,8 +33,8 @@
|
||||||
/* Changes for the GDC compiler by David Friedman */
|
/* Changes for the GDC compiler by David Friedman */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
|
#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 STRUCTTHISREF V2 // if 'this' for struct is a reference, not a pointer
|
||||||
|
|
||||||
struct Array;
|
struct Array;
|
||||||
|
|
||||||
|
@ -72,83 +73,68 @@ enum OS
|
||||||
// Put command line switches in here
|
// Put command line switches in here
|
||||||
struct Param
|
struct Param
|
||||||
{
|
{
|
||||||
char obj; // write object file
|
bool obj; // write object file
|
||||||
char link; // perform link
|
bool link; // perform link
|
||||||
char lib; // write library file instead of object file(s)
|
bool verbose; // verbose compile
|
||||||
char multiobj; // break one object file into multiple ones
|
char symdebug; // insert debug symbolic information
|
||||||
char oneobj; // write one object file instead of multiple ones
|
bool optimize; // run optimizer
|
||||||
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
|
|
||||||
char optimizeLevel; // optimization level
|
char optimizeLevel; // optimization level
|
||||||
ARCH cpu; // target CPU
|
ARCH cpu; // target CPU
|
||||||
OS os; // target OS
|
OS os; // target OS
|
||||||
char is64bit; // generate 64 bit code
|
bool is64bit; // generate 64 bit code
|
||||||
char isLE; // generate little endian code
|
bool isLE; // generate little endian code
|
||||||
char scheduler; // which scheduler to use
|
bool useDeprecated; // allow use of deprecated features
|
||||||
char useDeprecated; // allow use of deprecated features
|
bool useAssert; // generate runtime code for assert()'s
|
||||||
char useAssert; // generate runtime code for assert()'s
|
bool useInvariants; // generate class invariant checks
|
||||||
char useInvariants; // generate class invariant checks
|
bool useIn; // generate precondition checks
|
||||||
char useIn; // generate precondition checks
|
bool useOut; // generate postcondition checks
|
||||||
char useOut; // generate postcondition checks
|
bool useArrayBounds; // generate array bounds checks
|
||||||
char useArrayBounds; // generate array bounds checks
|
bool useSwitchError; // check for switches without a default
|
||||||
char useSwitchError; // check for switches without a default
|
bool useUnitTests; // generate unittest code
|
||||||
char useUnitTests; // generate unittest code
|
bool useInline; // inline expand functions
|
||||||
char useInline; // inline expand functions
|
bool warnings; // enable warnings
|
||||||
char release; // build release version
|
bool safe; // enforce safe memory model
|
||||||
char preservePaths; // !=0 means don't strip path from source file
|
char Dversion; // D version number
|
||||||
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
|
|
||||||
|
|
||||||
char *argv0; // program name
|
char *argv0; // program name
|
||||||
Array *imppath; // array of char*'s of where to look for import modules
|
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
|
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 *objdir; // .obj file output directory
|
char *objname; // .obj file output name
|
||||||
char *objname; // .obj file output name
|
|
||||||
|
|
||||||
char doDocComments; // process embedded documentation comments
|
bool doDocComments; // process embedded documentation comments
|
||||||
char *docdir; // write documentation file to docdir directory
|
char *docdir; // write documentation file to docdir directory
|
||||||
char *docname; // write documentation file to docname
|
char *docname; // write documentation file to docname
|
||||||
Array *ddocfiles; // macro include files for Ddoc
|
Array *ddocfiles; // macro include files for Ddoc
|
||||||
|
|
||||||
char doHdrGeneration; // process embedded documentation comments
|
bool doHdrGeneration; // process embedded documentation comments
|
||||||
char *hdrdir; // write 'header' file to docdir directory
|
char *hdrdir; // write 'header' file to docdir directory
|
||||||
char *hdrname; // write 'header' file to docname
|
char *hdrname; // write 'header' file to docname
|
||||||
|
|
||||||
unsigned debuglevel; // debug level
|
unsigned debuglevel; // debug level
|
||||||
Array *debugids; // debug identifiers
|
Array *debugids; // debug identifiers
|
||||||
|
|
||||||
unsigned versionlevel; // version level
|
unsigned versionlevel; // version level
|
||||||
Array *versionids; // version identifiers
|
Array *versionids; // version identifiers
|
||||||
|
|
||||||
bool dump_source;
|
bool dump_source;
|
||||||
|
|
||||||
Array *defaultlibnames; // default libraries for non-debug builds
|
Array *defaultlibnames; // default libraries for non-debug builds
|
||||||
Array *debuglibnames; // default libraries for 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
|
// Hidden debug switches
|
||||||
char debuga;
|
bool debuga;
|
||||||
char debugb;
|
bool debugb;
|
||||||
char debugc;
|
bool debugc;
|
||||||
char debugf;
|
bool debugf;
|
||||||
char debugr;
|
bool debugr;
|
||||||
char debugw;
|
bool debugw;
|
||||||
char debugx;
|
bool debugx;
|
||||||
char debugy;
|
bool debugy;
|
||||||
|
|
||||||
char run; // run resulting executable
|
bool run; // run resulting executable
|
||||||
size_t runargs_length;
|
|
||||||
char** runargs; // arguments for executable
|
|
||||||
|
|
||||||
// Linker stuff
|
// Linker stuff
|
||||||
Array *objfiles;
|
Array *objfiles;
|
||||||
|
@ -159,50 +145,46 @@ struct Param
|
||||||
char *exefile;
|
char *exefile;
|
||||||
|
|
||||||
// LDC stuff
|
// LDC stuff
|
||||||
const char *llvmArch;
|
OUTPUTFLAG output_ll;
|
||||||
char forceBE;
|
OUTPUTFLAG output_bc;
|
||||||
char output_ll;
|
OUTPUTFLAG output_s;
|
||||||
char output_bc;
|
OUTPUTFLAG output_o;
|
||||||
char output_s;
|
bool llvmInline;
|
||||||
char output_o;
|
bool llvmAnnotate;
|
||||||
char llvmInline;
|
bool useInlineAsm;
|
||||||
char llvmAnnotate;
|
|
||||||
char useInlineAsm;
|
|
||||||
char fqnNames; // use fully qualified object names
|
|
||||||
char noDefaultLib;
|
|
||||||
|
|
||||||
// target stuff
|
// target stuff
|
||||||
|
const char* llvmArch;
|
||||||
const char *targetTriple;
|
const char *targetTriple;
|
||||||
const char *dataLayout;
|
const char *dataLayout;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Global
|
struct Global
|
||||||
{
|
{
|
||||||
const char *mars_ext;
|
char *mars_ext;
|
||||||
const char *sym_ext;
|
char *sym_ext;
|
||||||
const char *obj_ext;
|
char *obj_ext;
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
const char *obj_ext_alt;
|
char *obj_ext_alt;
|
||||||
#endif
|
#endif
|
||||||
const char *ll_ext;
|
char *ll_ext;
|
||||||
const char *bc_ext;
|
char *bc_ext;
|
||||||
const char *s_ext;
|
char *s_ext;
|
||||||
const char *lib_ext;
|
char *doc_ext; // for Ddoc generated files
|
||||||
const char *doc_ext; // for Ddoc generated files
|
char *ddoc_ext; // for Ddoc macro include files
|
||||||
const char *ddoc_ext; // for Ddoc macro include files
|
char *hdr_ext; // for D 'header' import files
|
||||||
const char *hdr_ext; // for D 'header' import files
|
char *copyright;
|
||||||
const char *copyright;
|
char *written;
|
||||||
const char *written;
|
Array *path; // Array of char*'s which form the import lookup path
|
||||||
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
|
||||||
Array *filePath; // Array of char*'s which form the file import lookup path
|
|
||||||
int structalign;
|
int structalign;
|
||||||
const char *version;
|
char *version;
|
||||||
const char *ldc_version;
|
char *ldc_version;
|
||||||
const char *llvm_version;
|
char *llvm_version;
|
||||||
|
|
||||||
Param params;
|
Param params;
|
||||||
unsigned errors; // number of errors reported so far
|
unsigned errors; // number of errors reported so far
|
||||||
unsigned gag; // !=0 means gag reporting of errors
|
unsigned gag; // !=0 means gag reporting of errors
|
||||||
|
|
||||||
Global();
|
Global();
|
||||||
};
|
};
|
||||||
|
@ -212,7 +194,7 @@ extern Global global;
|
||||||
/* Set if Windows Structured Exception Handling C extensions are supported.
|
/* Set if Windows Structured Exception Handling C extensions are supported.
|
||||||
* Apparently, VC has dropped support for these?
|
* Apparently, VC has dropped support for these?
|
||||||
*/
|
*/
|
||||||
#define WINDOWS_SEH _WIN32 && __DMC__
|
#define WINDOWS_SEH (_WIN32 && __DMC__)
|
||||||
|
|
||||||
|
|
||||||
#if __GNUC__
|
#if __GNUC__
|
||||||
|
@ -239,22 +221,22 @@ typedef uint64_t integer_t;
|
||||||
typedef int64_t sinteger_t;
|
typedef int64_t sinteger_t;
|
||||||
typedef uint64_t uinteger_t;
|
typedef uint64_t uinteger_t;
|
||||||
|
|
||||||
typedef int8_t d_int8;
|
typedef int8_t d_int8;
|
||||||
typedef uint8_t d_uns8;
|
typedef uint8_t d_uns8;
|
||||||
typedef int16_t d_int16;
|
typedef int16_t d_int16;
|
||||||
typedef uint16_t d_uns16;
|
typedef uint16_t d_uns16;
|
||||||
typedef int32_t d_int32;
|
typedef int32_t d_int32;
|
||||||
typedef uint32_t d_uns32;
|
typedef uint32_t d_uns32;
|
||||||
typedef int64_t d_int64;
|
typedef int64_t d_int64;
|
||||||
typedef uint64_t d_uns64;
|
typedef uint64_t d_uns64;
|
||||||
|
|
||||||
typedef float d_float32;
|
typedef float d_float32;
|
||||||
typedef double d_float64;
|
typedef double d_float64;
|
||||||
typedef long double d_float80;
|
typedef long double d_float80;
|
||||||
|
|
||||||
typedef d_uns8 d_char;
|
typedef d_uns8 d_char;
|
||||||
typedef d_uns16 d_wchar;
|
typedef d_uns16 d_wchar;
|
||||||
typedef d_uns32 d_dchar;
|
typedef d_uns32 d_dchar;
|
||||||
|
|
||||||
#ifdef IN_GCC
|
#ifdef IN_GCC
|
||||||
#include "d-gcc-real.h"
|
#include "d-gcc-real.h"
|
||||||
|
@ -289,7 +271,7 @@ typedef long double real_t;
|
||||||
|
|
||||||
struct Module;
|
struct Module;
|
||||||
|
|
||||||
//typedef unsigned Loc; // file location
|
//typedef unsigned Loc; // file location
|
||||||
struct Loc
|
struct Loc
|
||||||
{
|
{
|
||||||
char *filename;
|
char *filename;
|
||||||
|
@ -297,14 +279,14 @@ struct Loc
|
||||||
|
|
||||||
Loc()
|
Loc()
|
||||||
{
|
{
|
||||||
linnum = 0;
|
linnum = 0;
|
||||||
filename = NULL;
|
filename = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loc(int x)
|
Loc(int x)
|
||||||
{
|
{
|
||||||
linnum = x;
|
linnum = x;
|
||||||
filename = NULL;
|
filename = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loc(Module *mod, unsigned linnum);
|
Loc(Module *mod, unsigned linnum);
|
||||||
|
@ -313,15 +295,15 @@ struct Loc
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef GCC_SAFE_DMD
|
#ifndef GCC_SAFE_DMD
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
|
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
|
||||||
// in interface vtbl[]'s
|
// in interface vtbl[]'s
|
||||||
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
|
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
|
||||||
// in the inheritance graph multiple
|
// in the inheritance graph multiple
|
||||||
// times, only one is used
|
// times, only one is used
|
||||||
|
|
||||||
enum LINK
|
enum LINK
|
||||||
{
|
{
|
||||||
|
@ -348,19 +330,19 @@ enum DYNCAST
|
||||||
|
|
||||||
enum MATCH
|
enum MATCH
|
||||||
{
|
{
|
||||||
MATCHnomatch, // no match
|
MATCHnomatch, // no match
|
||||||
MATCHconvert, // match with conversions
|
MATCHconvert, // match with conversions
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
MATCHconst, // match with conversion to const
|
MATCHconst, // match with conversion to const
|
||||||
#endif
|
#endif
|
||||||
MATCHexact // exact match
|
MATCHexact // exact match
|
||||||
};
|
};
|
||||||
|
|
||||||
void error(Loc loc, const char *format, ...);
|
void error(Loc loc, const char *format, ...);
|
||||||
void verror(Loc loc, const char *format, va_list);
|
void verror(Loc loc, const char *format, va_list);
|
||||||
void fatal();
|
void fatal();
|
||||||
void err_nomem();
|
void err_nomem();
|
||||||
void inifile(const char *argv0, const char *inifile);
|
void inifile(char *argv0, const char *inifile);
|
||||||
void halt();
|
void halt();
|
||||||
|
|
||||||
/*** Where to send error messages ***/
|
/*** Where to send error messages ***/
|
||||||
|
|
|
@ -40,6 +40,19 @@
|
||||||
#include "d-dmd-gcc.h"
|
#include "d-dmd-gcc.h"
|
||||||
#endif
|
#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;
|
ClassDeclaration *Module::moduleinfo;
|
||||||
|
|
||||||
Module *Module::rootModule;
|
Module *Module::rootModule;
|
||||||
|
@ -139,12 +152,12 @@ File* Module::buildFilePath(char* forcename, const char* path, const char* ext)
|
||||||
argobj = forcename;
|
argobj = forcename;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (global.params.preservePaths)
|
if (preservePaths)
|
||||||
argobj = (char*)this->arg;
|
argobj = (char*)this->arg;
|
||||||
else
|
else
|
||||||
argobj = FileName::name((char*)this->arg);
|
argobj = FileName::name((char*)this->arg);
|
||||||
|
|
||||||
if (global.params.fqnNames)
|
if (fqnNames)
|
||||||
{
|
{
|
||||||
if(md)
|
if(md)
|
||||||
argobj = FileName::replaceName(argobj, md->toChars());
|
argobj = FileName::replaceName(argobj, md->toChars());
|
||||||
|
|
|
@ -230,22 +230,18 @@ static cl::alias m("m",
|
||||||
cl::Prefix,
|
cl::Prefix,
|
||||||
cl::aliasopt(mArch));
|
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::list<std::string> mAttrs("mattr",
|
||||||
cl::desc("Emit code for the specified OS:"),
|
cl::CommaSeparated,
|
||||||
cl::values(
|
cl::desc("Target specific attributes (-mattr=help for details)"),
|
||||||
#define ENUMVAL_N(Name, Desc) clEnumValN(OS##Name, #Name, Desc)
|
cl::value_desc("a1,+a2,-a3,..."));
|
||||||
#define ENUMVAL(Name) ENUMVAL_N(Name, #Name)
|
|
||||||
ENUMVAL(Linux),
|
cl::opt<std::string> mTargetTriple("mtriple",
|
||||||
ENUMVAL(Windows),
|
cl::desc("Override target triple"));
|
||||||
ENUMVAL_N(MacOSX, "Mac OS X"),
|
|
||||||
ENUMVAL(FreeBSD),
|
|
||||||
ENUMVAL(Solaris),
|
|
||||||
#undef ENUMVAL
|
|
||||||
#undef ENUMVAL_N
|
|
||||||
clEnumValEnd),
|
|
||||||
cl::Prefix,
|
|
||||||
cl::location(global.params.os));
|
|
||||||
|
|
||||||
|
|
||||||
// "Hidden debug switches"
|
// "Hidden debug switches"
|
||||||
|
|
|
@ -38,6 +38,9 @@ namespace opts {
|
||||||
|
|
||||||
extern cl::opt<const llvm::TargetMachineRegistry::entry*, false,
|
extern cl::opt<const llvm::TargetMachineRegistry::entry*, false,
|
||||||
llvm::RegistryParser<llvm::TargetMachine> > mArch;
|
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
|
// Arguments to -d-debug
|
||||||
extern std::vector<std::string> debugArgs;
|
extern std::vector<std::string> debugArgs;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "gen/todebug.h"
|
#include "gen/todebug.h"
|
||||||
#include "gen/classes.h"
|
#include "gen/classes.h"
|
||||||
#include "gen/dvalue.h"
|
#include "gen/dvalue.h"
|
||||||
|
#include "gen/abi.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -53,40 +54,49 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
|
||||||
// parameter types
|
// parameter types
|
||||||
std::vector<const LLType*> paramvec;
|
std::vector<const LLType*> paramvec;
|
||||||
|
|
||||||
|
// special case main
|
||||||
if (ismain)
|
if (ismain)
|
||||||
{
|
{
|
||||||
rettype = LLType::Int32Ty;
|
rettype = LLType::Int32Ty;
|
||||||
actualRettype = rettype;
|
actualRettype = rettype;
|
||||||
if (Argument::dim(f->parameters) == 0)
|
if (Argument::dim(f->parameters) == 0)
|
||||||
{
|
{
|
||||||
const LLType* arrTy = DtoArrayType(LLType::Int8Ty);
|
const LLType* arrTy = DtoArrayType(LLType::Int8Ty);
|
||||||
const LLType* arrArrTy = DtoArrayType(arrTy);
|
const LLType* arrArrTy = DtoArrayType(arrTy);
|
||||||
paramvec.push_back(arrArrTy);
|
paramvec.push_back(arrArrTy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
// default handling
|
||||||
|
else
|
||||||
|
{
|
||||||
assert(rt);
|
assert(rt);
|
||||||
if (DtoIsReturnedInArg(rt)) {
|
if (gABI->returnInArg(rt))
|
||||||
|
{
|
||||||
rettype = getPtrToType(DtoType(rt));
|
rettype = getPtrToType(DtoType(rt));
|
||||||
actualRettype = LLType::VoidTy;
|
actualRettype = LLType::VoidTy;
|
||||||
f->retInPtr = retinptr = true;
|
f->retInPtr = retinptr = true;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
rettype = DtoType(rt);
|
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))
|
if (unsigned ea = DtoShouldExtend(rt))
|
||||||
{
|
{
|
||||||
f->retAttrs |= ea;
|
f->retAttrs |= ea;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build up parameter list
|
||||||
if (retinptr) {
|
if (retinptr) {
|
||||||
//Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
|
//Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
|
||||||
paramvec.push_back(rettype);
|
paramvec.push_back(rettype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this/context param
|
||||||
if (thistype) {
|
if (thistype) {
|
||||||
paramvec.push_back(thistype);
|
paramvec.push_back(thistype);
|
||||||
usesthis = true;
|
usesthis = true;
|
||||||
|
@ -96,6 +106,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
|
||||||
usesnest = true;
|
usesnest = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dstyle vararg
|
||||||
if (dVararg) {
|
if (dVararg) {
|
||||||
paramvec.push_back(DtoType(Type::typeinfo->type->arrayOf())); // _arguments
|
paramvec.push_back(DtoType(Type::typeinfo->type->arrayOf())); // _arguments
|
||||||
paramvec.push_back(getVoidPtrType()); // _argptr
|
paramvec.push_back(getVoidPtrType()); // _argptr
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
#include "tollvm.h"
|
#include "tollvm.h"
|
||||||
|
|
||||||
IRState* gIR = 0;
|
IRState* gIR = 0;
|
||||||
|
llvm::TargetMachine* gTargetMachine = 0;
|
||||||
const llvm::TargetData* gTargetData = 0;
|
const llvm::TargetData* gTargetData = 0;
|
||||||
|
TargetABI* gABI = 0;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
IRScope::IRScope()
|
IRScope::IRScope()
|
||||||
|
|
|
@ -13,10 +13,18 @@
|
||||||
#include "ir/irstruct.h"
|
#include "ir/irstruct.h"
|
||||||
#include "ir/irvar.h"
|
#include "ir/irvar.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class TargetMachine;
|
||||||
|
}
|
||||||
|
|
||||||
// global ir state for current module
|
// global ir state for current module
|
||||||
struct IRState;
|
struct IRState;
|
||||||
|
struct TargetABI;
|
||||||
|
|
||||||
extern IRState* gIR;
|
extern IRState* gIR;
|
||||||
|
extern llvm::TargetMachine* gTargetMachine;
|
||||||
extern const llvm::TargetData* gTargetData;
|
extern const llvm::TargetData* gTargetData;
|
||||||
|
extern TargetABI* gABI;
|
||||||
|
|
||||||
struct TypeFunction;
|
struct TypeFunction;
|
||||||
struct TypeStruct;
|
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
|
// this is to show how to allocate a temporary for the return value
|
||||||
// in case the appropriate multi register constraint isn't supported.
|
// in case the appropriate multi register constraint isn't supported.
|
||||||
// this way abi return from inline asm can still be emulated.
|
// 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
|
// generate asm
|
||||||
as->out_c = "=*m,=*m,";
|
as->out_c = "=*m,=*m,";
|
||||||
|
@ -231,7 +233,7 @@ void emitABIReturnAsmStmt(IRAsmBlock* asmblock, Loc loc, FuncDeclaration* fdecl)
|
||||||
asmblock->retemu = true;
|
asmblock->retemu = true;
|
||||||
asmblock->asmBlock->abiret = tmp;
|
asmblock->asmBlock->abiret = tmp;
|
||||||
|
|
||||||
// add "ret" stmt
|
// add "ret" stmt at the end of the block
|
||||||
asmblock->s.push_back(as);
|
asmblock->s.push_back(as);
|
||||||
|
|
||||||
// done, we don't want anything pushed in the front of the block
|
// 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}.
|
// LLVM and GCC disagree on how to return {float, float}.
|
||||||
// For compatibility, use the GCC/LLVM-GCC way for extern(C/Windows)
|
// For compatibility, use the GCC/LLVM-GCC way for extern(C/Windows)
|
||||||
// extern(C) cfloat -> %xmm0 (extract two floats)
|
// 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},";
|
as->out_c = "={xmm0},";
|
||||||
asmblock->retty = LLStructType::get(LLType::DoubleTy, NULL);;
|
asmblock->retty = LLStructType::get(LLType::DoubleTy, NULL);;
|
||||||
asmblock->retfixup = &x86_64_cfloatRetFixup;
|
asmblock->retfixup = &x86_64_cfloatRetFixup;
|
||||||
#else
|
|
||||||
error(loc, "unimplemented return type '%s' for implicit abi return", rt->toChars());
|
|
||||||
fatal();
|
|
||||||
#endif
|
|
||||||
} else if (rt->iscomplex()) {
|
} else if (rt->iscomplex()) {
|
||||||
// cdouble and extern(D) cfloat -> re=%xmm0, im=%xmm1
|
// cdouble and extern(D) cfloat -> re=%xmm0, im=%xmm1
|
||||||
as->out_c = "={xmm0},={xmm1},";
|
as->out_c = "={xmm0},={xmm1},";
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "gen/arrays.h"
|
#include "gen/arrays.h"
|
||||||
#include "gen/todebug.h"
|
#include "gen/todebug.h"
|
||||||
#include "gen/dvalue.h"
|
#include "gen/dvalue.h"
|
||||||
|
#include "gen/abi.h"
|
||||||
|
|
||||||
#include "ir/irfunction.h"
|
#include "ir/irfunction.h"
|
||||||
#include "ir/irmodule.h"
|
#include "ir/irmodule.h"
|
||||||
|
@ -54,38 +55,47 @@ void ReturnStatement::toIR(IRState* p)
|
||||||
Logger::println("ReturnStatement::toIR(): %s", loc.toChars());
|
Logger::println("ReturnStatement::toIR(): %s", loc.toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
// is there a return value expression?
|
||||||
if (exp)
|
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();
|
IrFunction* f = p->func();
|
||||||
assert(f->type->retInPtr);
|
assert(f->type->retInPtr);
|
||||||
assert(f->decl->ir.irFunc->retArg);
|
assert(f->decl->ir.irFunc->retArg);
|
||||||
|
|
||||||
|
// emit dbg line
|
||||||
if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
|
if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
|
||||||
|
|
||||||
|
// get return pointer
|
||||||
DValue* rvar = new DVarValue(f->type->next, f->decl->ir.irFunc->retArg);
|
DValue* rvar = new DVarValue(f->type->next, f->decl->ir.irFunc->retArg);
|
||||||
|
|
||||||
DValue* e = exp->toElem(p);
|
DValue* e = exp->toElem(p);
|
||||||
|
// store return value
|
||||||
DtoAssign(loc, rvar, e);
|
DtoAssign(loc, rvar, e);
|
||||||
|
|
||||||
|
// emit scopes
|
||||||
DtoEnclosingHandlers(enclosinghandler, NULL);
|
DtoEnclosingHandlers(enclosinghandler, NULL);
|
||||||
|
|
||||||
|
// emit dbg end function
|
||||||
if (global.params.symdebug) DtoDwarfFuncEnd(f->decl);
|
if (global.params.symdebug) DtoDwarfFuncEnd(f->decl);
|
||||||
|
|
||||||
|
// emit ret
|
||||||
llvm::ReturnInst::Create(p->scopebb());
|
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);
|
if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
|
||||||
DValue* e = exp->toElem(p);
|
DValue* e = exp->toElem(p);
|
||||||
LLValue* v = e->getRVal();
|
LLValue* v = e->getRVal();
|
||||||
delete e;
|
delete e;
|
||||||
|
|
||||||
// swap real/imag parts on a x87
|
// do abi specific transformations on the return value
|
||||||
if (global.params.cpu == ARCHx86 && exp->type->toBasetype()->iscomplex())
|
v = gABI->putRet(p->func()->type, v);
|
||||||
{
|
|
||||||
v = DtoAggrPairSwap(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Logger::enabled())
|
if (Logger::enabled())
|
||||||
Logger::cout() << "return value is '" <<*v << "'\n";
|
Logger::cout() << "return value is '" <<*v << "'\n";
|
||||||
|
@ -113,6 +123,7 @@ void ReturnStatement::toIR(IRState* p)
|
||||||
llvm::ReturnInst::Create(v, p->scopebb());
|
llvm::ReturnInst::Create(v, p->scopebb());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// no return value expression means it's a void function
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(p->topfunc()->getReturnType() == LLType::VoidTy);
|
assert(p->topfunc()->getReturnType() == LLType::VoidTy);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "gen/irstate.h"
|
#include "gen/irstate.h"
|
||||||
#include "gen/dvalue.h"
|
#include "gen/dvalue.h"
|
||||||
#include "gen/functions.h"
|
#include "gen/functions.h"
|
||||||
|
#include "gen/abi.h"
|
||||||
|
|
||||||
#include "gen/logger.h"
|
#include "gen/logger.h"
|
||||||
|
|
||||||
|
@ -463,11 +464,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||||
// get return value
|
// get return value
|
||||||
LLValue* retllval = (retinptr) ? args[0] : call->get();
|
LLValue* retllval = (retinptr) ? args[0] : call->get();
|
||||||
|
|
||||||
// swap real/imag parts on a x87
|
// do abi specific return value fixups
|
||||||
if (global.params.cpu == ARCHx86 && tf->nextOf()->toBasetype()->iscomplex())
|
retllval = gABI->getRet(tf, retllval);
|
||||||
{
|
|
||||||
retllval = DtoAggrPairSwap(retllval);
|
|
||||||
}
|
|
||||||
|
|
||||||
// repaint the type if necessary
|
// repaint the type if necessary
|
||||||
if (resulttype)
|
if (resulttype)
|
||||||
|
|
|
@ -28,13 +28,6 @@ bool DtoIsPassedByRef(Type* type)
|
||||||
return (t == Tstruct || t == Tsarray);
|
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)
|
unsigned DtoShouldExtend(Type* type)
|
||||||
{
|
{
|
||||||
type = type->toBasetype();
|
type = type->toBasetype();
|
||||||
|
|
|
@ -18,9 +18,7 @@ const LLType* DtoTypeNotVoid(Type* t);
|
||||||
// returns true is the type must be passed by pointer
|
// returns true is the type must be passed by pointer
|
||||||
bool DtoIsPassedByRef(Type* type);
|
bool DtoIsPassedByRef(Type* type);
|
||||||
|
|
||||||
// returns if the type should be returned in a hidden pointer arguement
|
// should argument be zero or sign extended
|
||||||
bool DtoIsReturnedInArg(Type* type);
|
|
||||||
|
|
||||||
unsigned DtoShouldExtend(Type* type);
|
unsigned DtoShouldExtend(Type* type);
|
||||||
|
|
||||||
// tuple helper
|
// tuple helper
|
||||||
|
|
|
@ -14,9 +14,6 @@
|
||||||
#include "gen/llvm.h"
|
#include "gen/llvm.h"
|
||||||
#include "llvm/Analysis/Verifier.h"
|
#include "llvm/Analysis/Verifier.h"
|
||||||
#include "llvm/Bitcode/ReaderWriter.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/Module.h"
|
||||||
#include "llvm/ModuleProvider.h"
|
#include "llvm/ModuleProvider.h"
|
||||||
#include "llvm/PassManager.h"
|
#include "llvm/PassManager.h"
|
||||||
|
@ -25,6 +22,7 @@
|
||||||
#include "llvm/System/Path.h"
|
#include "llvm/System/Path.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
#include "mars.h"
|
#include "mars.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
@ -50,6 +48,8 @@
|
||||||
#include "gen/functions.h"
|
#include "gen/functions.h"
|
||||||
#include "gen/todebug.h"
|
#include "gen/todebug.h"
|
||||||
#include "gen/runtime.h"
|
#include "gen/runtime.h"
|
||||||
|
#include "gen/abi.h"
|
||||||
|
#include "gen/cl_options.h"
|
||||||
|
|
||||||
#include "ir/irvar.h"
|
#include "ir/irvar.h"
|
||||||
#include "ir/irmodule.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
|
// FIXME: but shouldn't this always get reset between modules? like other IrSymbols
|
||||||
this->ir.irModule = new IrModule(this, srcfile->toChars());
|
this->ir.irModule = new IrModule(this, srcfile->toChars());
|
||||||
|
|
||||||
// set target stuff
|
// set target triple
|
||||||
|
|
||||||
ir.module->setTargetTriple(global.params.targetTriple);
|
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
|
// set final data layout
|
||||||
std::string datalayout = gTargetData->getStringRepresentation();
|
ir.module->setDataLayout(global.params.dataLayout);
|
||||||
ir.module->setDataLayout(datalayout);
|
|
||||||
if (Logger::enabled())
|
if (Logger::enabled())
|
||||||
Logger::cout() << "Final data layout: " << datalayout << '\n';
|
Logger::cout() << "Final data layout: " << global.params.dataLayout << '\n';
|
||||||
assert(memcmp(global.params.dataLayout, datalayout.c_str(), 9) == 0); // "E-p:xx:xx"
|
|
||||||
|
// allocate the target abi
|
||||||
|
gABI = TargetABI::getTarget();
|
||||||
|
|
||||||
// debug info
|
// debug info
|
||||||
if (global.params.symdebug) {
|
if (global.params.symdebug) {
|
||||||
|
@ -252,7 +228,7 @@ void Module::genobjfile(int multiobj)
|
||||||
std::string err;
|
std::string err;
|
||||||
{
|
{
|
||||||
llvm::raw_fd_ostream out(spath.c_str(), false, 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
|
// call gcc to convert assembly to object file
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue