ldc/LDC-DMD2.068.2 WIP.diff
Johan Engelen 29ce4012af dmd2 --> ddmd. Merge (almost all of) our changes to dmd source into the new D source of dmd 2.069.2.
Also adds the CMake infrastructure to compile and link the D source files.

The build is partially broken:
- A few files in Phobos and druntime do not build
- MSVC build is broken because of unresolved symbols involving reals
2016-01-28 19:03:58 +01:00

1052 lines
31 KiB
Diff

diff --git a/src/aggregate.h b/src/aggregate.h
index 299b59a..8bf0763 100644
--- a/src/aggregate.h
+++ b/src/aggregate.h
@@ -130,10 +130,12 @@ public:
Prot prot();
Type *handleType() { return type; } // 'this' type
+#if IN_DMD UNNECESSARY DIFF ?
// Back end
Symbol *stag; // tag symbol for debug data
Symbol *sinit;
+#endif
AggregateDeclaration *isAggregateDeclaration() { return this; }
void accept(Visitor *v) { v->visit(this); }
@@ -297,8 +299,10 @@ public:
void addLocalClass(ClassDeclarations *);
+#if IN_DMD UNNECESSARY DIFF ?
// Back end
Symbol *vtblsym;
+#endif
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
void accept(Visitor *v) { v->visit(this); }
diff --git a/src/builtin.c b/src/builtin.c
index 32f158e..9375f8d 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -26,6 +26,10 @@
#include "module.h"
#include "root/port.h"
#include "tokens.h"
+#if IN_LLVM UNNECESSARY DIFF ?
+#include "template.h"
+#include "gen/pragma.h"
+#endif
StringTable builtins;
diff --git a/src/class.c b/src/class.c
index 48187ce..34fe842 100644
--- a/src/class.c
+++ b/src/class.c
@@ -65,7 +65,9 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
staticCtor = NULL;
staticDtor = NULL;
+#if IN_DMD UNNECESSARY DIFF ? (see src/aggregate.h)
vtblsym = NULL;
+#endif
vclassinfo = NULL;
if (id)
diff --git a/src/declaration.h b/src/declaration.h
index ee4ffba..1c9c08d 100644
--- a/src/declaration.h
+++ b/src/declaration.h
@@ -16,6 +16,10 @@
#pragma once
#endif /* __DMC__ */
+#if IN_LLVM
+#include <string>
+#endif
+
#include "dsymbol.h"
#include "mtype.h"
@@ -564,7 +579,9 @@ public:
// Support for NRVO (named return value optimization)
bool nrvo_can; // true means we can do it
VarDeclaration *nrvo_var; // variable to replace with shidden
+#if IN_DMD UNNECESSARY DIFF ?
Symbol *shidden; // hidden pointer passed to function
+#endif
ReturnStatements *returns;
diff --git a/src/dsymbol.c b/src/dsymbol.c
index d75f676..6279ab6 100644
--- a/src/dsymbol.c
+++ b/src/dsymbol.c
@@ -35,6 +35,10 @@
#include "enum.h"
#include "lexer.h"
+#if IN_LLVM UNNECESSARY DIFF ?
+#include "../gen/pragma.h"
+#endif
+const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"};
/****************************** Dsymbol ******************************/
diff --git a/src/dsymbol.h b/src/dsymbol.h
index 4bf5427..49c6676 100644
--- a/src/dsymbol.h
+++ b/src/dsymbol.h
@@ -53,7 +61,9 @@ class UnitTestDeclaration;
class NewDeclaration;
class VarDeclaration;
class AttribDeclaration;
+#if IN_DMD UNNECESSARY DIFF ?
struct Symbol;
+#endif
class Package;
class Module;
class Import;
@@ -147,8 +157,10 @@ class Dsymbol : public RootObject
public:
Identifier *ident;
Dsymbol *parent;
+#if IN_DMD UNNECESSARY DIFF ?
Symbol *csym; // symbol for code generator
Symbol *isym; // import version of csym
+#endif
const utf8_t *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Scope *scope; // !=NULL means context to use for semantic()
diff --git a/src/enum.c b/src/enum.c
index 7cba57f..2ff3418 100644
--- a/src/enum.c
+++ b/src/enum.c
@@ -34,7 +34,9 @@ EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
maxval = NULL;
minval = NULL;
defaultval = NULL;
+#if IN_DMD UNNECESSARY DIFF ?
sinit = NULL;
+#endif
isdeprecated = false;
protection = Prot(PROTundefined);
parent = NULL;
diff --git a/src/enum.h b/src/enum.h
index 30bd800..01a71a5 100644
--- a/src/enum.h
+++ b/src/enum.h
@@ -65,7 +65,10 @@ public:
EnumDeclaration *isEnumDeclaration() { return this; }
+#if IN_DMD UNNECESSARY DIFF ?
Symbol *sinit;
+#endif
+
void accept(Visitor *v) { v->visit(this); }
};
diff --git a/src/expression.c b/src/expression.c
index a5742a1..65c3c2e 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -4315,10 +4336,16 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *
this->elements = elements;
this->stype = stype;
this->sinit = NULL;
+#if IN_DMD NOT NEEDED ?
this->sym = NULL;
+#endif
this->soffset = 0;
this->fillHoles = 1;
this->ownedByCtfe = OWNEDcode;
@@ -8459,7 +8500,11 @@ Lagain:
* otherwise the literals expressed as code get excessively large.
*/
if (sd->size(loc) > Target::ptrsize * 4 && !t1->needsNested())
+#if IN_LLVM THE CODE AROUND HERE HAS CHANGED, PERHAPS RESOLVED THE NEED FOR DIFF
+ {} // FIXME!!!
+#else
sle->sinit = toInitializer(sd);
+#endif
Expression *e = sle;
if (CtorDeclaration *cf = sd->ctor->isCtorDeclaration())
diff --git a/src/expression.h b/src/expression.h
index c23cc53..96240dd 100644
--- a/src/expression.h
+++ b/src/expression.h
@@ -41,14 +41,29 @@ class TemplateInstance;
class TemplateDeclaration;
class ClassDeclaration;
class BinExp;
+#if IN_DMD UNNECESSARY DIFF ?
struct Symbol; // back end symbol
+#endif
class OverloadSet;
class Initializer;
class StringExp;
class ArrayExp;
@@ -461,8 +479,10 @@ public:
// NULL entries for fields to skip
Type *stype; // final type of result (can be different from sd's type)
+#if IN_DMD UNNECESSARY DIFF for sym?
Symbol *sinit; // if this is a defaultInitLiteral, this symbol contains the default initializer
Symbol *sym; // back end symbol to initialize with literal
+#endif
size_t soffset; // offset from start of s
int fillHoles; // fill alignment 'holes' with zero
OwnedBy ownedByCtfe;
diff --git a/src/func.c b/src/func.c
index 8814237..f0903e4 100644
--- a/src/func.c
+++ b/src/func.c
@@ -327,13 +331,22 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
hasReturnExp = 0;
nrvo_can = 1;
nrvo_var = NULL;
+#if IN_DMD UNNECESSARY DIFF ?
shidden = NULL;
+#endif
builtin = BUILTINunknown;
tookAddressOf = 0;
requiresClosure = false;
flags = 0;
returns = NULL;
gotos = NULL;
diff --git a/src/globals.c b/src/globals.c
index 217828e..1749340 100644
--- a/src/globals.c
+++ b/src/globals.c
@@ -59,19 +66,32 @@ void Global::init()
stdmsg = stdout;
main_d = "__main.d";
+ HAS BECOME UNNECESSARY I THINK (and init is done before any code execution, so it won't bug either)
+ // This should only be used as a global, so the other fields are
+ // automatically initialized to zero when the program is loaded.
+ // In particular, DO NOT zero-initialize .params here (like DMD
+ // does) because command-line options initialize some of those
+ // fields to non-zero defaults, and do so from constructors that
+ // may run before this one.
+#if !IN_LLVM
memset(&params, 0, sizeof(Param));
+#endif
errorLimit = 20;
}
diff --git a/src/globals.h b/src/globals.h
index 5851f36..2ff4b19 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -32,33 +45,47 @@ enum BOUNDSCHECK
BOUNDSCHECKsafeonly // do bounds checking only in @safe functions
};
-
// Put command line switches in here
struct Param
{
bool obj; // write object file
bool link; // perform link
+#if !IN_LLVM UNNECESSARY DIFF?
bool dll; // generate shared dynamic library
bool lib; // write library file instead of object file(s)
bool multiobj; // break one object file into multiple ones
bool oneobj; // write one object file instead of multiple ones
+#endif
bool trace; // insert profiling hooks
bool tracegc; // instrument calls to 'new'
bool verbose; // verbose compile
bool showColumns; // print character (column) numbers in diagnostics
bool vtls; // identify thread local variables
#if !IN_LLVM
char vgc; // identify gc usage
#else
bool vgc; // identify gc usage
#endif
bool vfield; // identify non-mutable field variables
bool vcomplex; // identify complex/imaginary type usage
#if !IN_LLVM
char symdebug; // insert debug symbolic information
#else
ubyte symdebug; // insert debug symbolic information
#endif
bool alwaysframe; // always emit standard stack frame
bool optimize; // run optimizer
+#if !IN_LLVM UNNECESSARY DIFF?
bool map; // generate linker .map file
+#endif
bool is64bit; // generate 64 bit code
bool isLP64; // generate code for LP64
+#if !IN_LLVM UNNECESSARY DIFF?
bool isLinux; // generate code for linux
bool isOSX; // generate code for Mac OSX
+#endif
bool isWindows; // generate code for Windows
+#if !IN_LLVM UNNECESSARY DIFF?
bool isFreeBSD; // generate code for FreeBSD
bool isOpenBSD; // generate code for OpenBSD
bool isSolaris; // generate code for Solaris
@@ -75,11 +107,28 @@ struct Param
bool useUnitTests; // generate unittest code
bool useInline; // inline expand functions
bool useDIP25; // implement http://wiki.dlang.org/DIP25
+#if !IN_LLVM UNNECESSARY DIFF? CHECK THAT "warnings" variable works well (ubyte <-> byte)
bool release; // build release version
bool preservePaths; // true means don't strip path from source file
char warnings; // 0: disable warnings
// 1: warnings as errors
// 2: informational warnings (no errors)
@@ -118,12 +168,15 @@ struct Param
unsigned versionlevel; // version level
Array<const char *> *versionids; // version identifiers
+#if !IN_LLVM UNNECESSARY DIFF?
const char *defaultlibname; // default library for non-debug builds
const char *debuglibname; // default library for debug builds
+#endif
const char *moduleDepsFile; // filename for deps output
OutBuffer *moduleDeps; // contents to be written to deps file
+#if !IN_LLVM UNNECESSARY DIFF?
// Hidden debug switches
bool debugb;
bool debugc;
@@ -131,9 +184,12 @@ struct Param
bool debugr;
bool debugx;
bool debugy;
+#endif
bool run; // run resulting executable
+#if !IN_LLVM UNNECESSARY DIFF?
Strings runargs; // arguments for executable
+#endif
// Linker stuff
Array<const char *> *objfiles;
diff --git a/src/inline.c b/src/inline.c
index 6fdaf59..53b45c0 100644
--- a/src/inline.c
+++ b/src/inline.c
@@ -865,8 +868,10 @@ Expression *doInline(Expression *e, InlineDoState *ids)
VarDeclaration *vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
memcpy((void *)vto, (void *)vd, sizeof(VarDeclaration));
vto->parent = ids->parent;
+#if IN_DMD
vto->csym = NULL;
vto->isym = NULL;
+#endif
ids->from.push(vd);
ids->to.push(vto);
@@ -1022,8 +1027,10 @@ Expression *doInline(Expression *e, InlineDoState *ids)
VarDeclaration *vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
memcpy((void*)vto, (void*)vd, sizeof(VarDeclaration));
vto->parent = ids->parent;
+#if IN_DMD
vto->csym = NULL;
vto->isym = NULL;
+#endif
ids->from.push(vd);
ids->to.push(vto);
@@ -1055,8 +1062,10 @@ Expression *doInline(Expression *e, InlineDoState *ids)
VarDeclaration *vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
memcpy((void*)vto, (void*)vd, sizeof(VarDeclaration));
vto->parent = ids->parent;
+#if IN_DMD
vto->csym = NULL;
vto->isym = NULL;
+#endif
ids->from.push(vd);
ids->to.push(vto);
diff --git a/src/lexer.c b/src/lexer.c
index 8f26026..af6c729 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -9,6 +9,12 @@
* https://github.com/D-Programming-Language/dmd/blob/master/src/lexer.c
*/
+#if IN_LLVM NOT NEEDED IN D SOURCE ?
+#include <cmath>
+#endif
+
+#include <sstream>
+
/* Lexical Analyzer */
#include <stdio.h>
@@ -17,7 +23,11 @@
#include <stdarg.h>
#include <errno.h>
#include <wchar.h>
+#if IN_LLVM NOT NEEDED IN D SOURCE ?
+#include <cstdlib>
+#else
#include <stdlib.h>
+#endif
#include <assert.h>
#include <time.h> // for time() and ctime()
diff --git a/src/mars.h b/src/mars.h
index 897e394..0935813 100644
--- a/src/mars.h
+++ b/src/mars.h
@@ -63,6 +63,12 @@ the target object file format:
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdarg.h>
+#if IN_LLVM UNNECESSARY DIFF ?
+#include "llvm/ADT/Triple.h"
+#endif
#ifdef __DMC__
#ifdef DEBUG
@@ -83,13 +89,17 @@ struct OutBuffer;
#include "errors.h"
+#if !IN_LLVM UNNECESSARY DIFF ?
class Dsymbol;
class Library;
+#endif
struct File;
+#if !IN_LLVM UNNECESSARY DIFF ?
void obj_start(char *srcfile);
void obj_end(Library *library, File *objfile);
void obj_append(Dsymbol *s);
void obj_write_deferred(Library *library);
+#endif
void readFile(Loc loc, File *f);
void writeFile(Loc loc, File *f);
diff --git a/src/module.c b/src/module.c
index 7758b32..9a3ff6a 100644
--- a/src/module.c
+++ b/src/module.c
@@ -64,6 +64,7 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do
searchCacheSymbol = NULL;
searchCacheFlags = 0;
decldefs = NULL;
+#if IN_DMD UNNECESSARY DIFF?
massert = NULL;
munittest = NULL;
marray = NULL;
@@ -74,9 +75,12 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do
sshareddtor = NULL;
stest = NULL;
sfilename = NULL;
+#endif UNNECESSARY DIFF?
importedFrom = NULL;
srcfile = NULL;
@@ -87,9 +91,11 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do
macrotable = NULL;
escapetable = NULL;
+#if IN_DMD UNNECESSARY DIFF?
doppelganger = 0;
cov = NULL;
covb = NULL;
+#endif
nameoffset = 0;
namelen = 0;
@@ -129,6 +147,7 @@ Module *Module::create(const char *filename, Identifier *ident, int doDocComment
return new Module(filename, ident, doDocComment, doHdrGen);
}
+#if IN_DMD UNNECESSARY DIFF?
void Module::setDocfile()
{
docfile = setOutfile(global.params.docname, global.params.docdir, arg, global.doc_ext);
@@ -177,12 +196,15 @@ File *Module::setOutfile(const char *name, const char *dir, const char *arg, con
return new File(docfilename);
}
+#endif
void Module::deleteObjFile()
{
if (global.params.obj)
objfile->remove();
- if (docfile)
+ //if (global.params.llvmBC)
+ //bcfile->remove(); UNNECESSARY DIFF?
if (doDocComment && docfile)
docfile->remove();
}
diff --git a/src/module.h b/src/module.h
index f297cc4..1df914d 100644
--- a/src/module.h
+++ b/src/module.h
@@ -114,17 +124,32 @@ public:
Module(const char *arg, Identifier *ident, int doDocComment, int doHdrGen);
static Module* create(const char *arg, Identifier *ident, int doDocComment, int doHdrGen);
+ ~Module(); HOPE THIS IS NOT NEEDED
static Module *load(Loc loc, Identifiers *packages, Identifier *ident);
const char *kind();
+#if !IN_LLVM UNNECESSARY DIFF ?
File *setOutfile(const char *name, const char *dir, const char *arg, const char *ext);
- void setDocfile();
+ void setDocfile(); // set docfile member
+#endif
bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise.
#if IN_LLVM
Module *parse(bool gen_docs = false); // syntactic parse
#else
Module *parse(); // syntactic parse
#endif
void importAll(Scope *sc);
+#if IN_LLVM UNNECESSARY DIFF ?
+ using Package::semantic;
+ using Dsymbol::semantic2;
+ using Dsymbol::semantic3;
+#endif
void semantic(); // semantic analysis
void semantic2(); // pass 2 semantic analysis
void semantic3(); // pass 3 semantic analysis
@@ -144,7 +169,7 @@ public:
// listed in command line.
// Back end
-
+#if IN_DMD UNNECESSARY DIFF ?
int doppelganger; // sub-module
Symbol *cov; // private uint[] __coverage;
unsigned *covb; // bit array of valid code line numbers
@@ -161,6 +186,25 @@ public:
Symbol *massert; // module assert function
Symbol *munittest; // module unittest failure function
Symbol *marray; // module array bounds function
+#endif
#if IN_LLVM
// LDC
llvm::Module* genLLVMModule(llvm::LLVMContext& context);
diff --git a/src/mtype.c b/src/mtype.c
index 92319ea..d4f05b0 100644
--- a/src/mtype.c
+++ b/src/mtype.c
@@ -12,7 +12,11 @@
#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more
#define __USE_ISOC99 1 // so signbit() gets defined
+#ifdef __DMC__ UNNECESSARY DIFF ?
#include <math.h>
+#else
+#include <cmath>
+#endif
#include <stdio.h>
#include <assert.h>
#include <float.h>
diff --git a/src/mtype.h b/src/mtype.h
index 344c1f6..a7db978 100644
--- a/src/opover.c
+++ b/src/opover.c
@@ -14,6 +14,15 @@
#include <ctype.h>
#include <assert.h>
#include <string.h> // memset()
I THINK THIS IS NO LONGER NEEDED IN D SOURCE?
+#if _MSC_VER || IN_LLVM // complex.h breaks LLVM headers.
+#include <complex>
+#else
+#include <complex.h>
+#endif
+
+#ifdef __APPLE__
+#define integer_t dmd_integer_t
+#endif
#include "rmem.h"
diff --git a/src/root/array.h b/src/root/array.h
index 840afb0..d86b308 100644
--- a/src/root/array.h
+++ b/src/root/array.h
@@ -169,8 +174,13 @@ struct Array
#endif
Array_sort_compare(const void *x, const void *y)
{
+#if IN_LLVM NOT NEEDED I THINK?
+ RootObject *ox = *static_cast<RootObject **>(const_cast<void *>(x));
+ RootObject *oy = *static_cast<RootObject **>(const_cast<void *>(y));
+#else
RootObject *ox = *(RootObject **)x;
RootObject *oy = *(RootObject **)y;
+#endif
return ox->compare(oy);
}
diff --git a/src/root/newdelete.c b/src/root/newdelete.c
index 8f62b88..2ab5faf 100644
--- a/src/root/newdelete.c
+++ b/src/root/newdelete.c
@@ -17,9 +17,9 @@
#endif
#endif
-#if !defined(USE_ASAN_NEW_DELETE)
+#if !defined(USE_ASAN_NEW_DELETE) && !defined(IN_LLVM) THIS IS DONE
-#if 1
+#if IN_DMD I DON'T THINK THIS IS NECESSARY BECAUSE OF IN_LLVM ABOVE
void *allocmemory(size_t m_size);
diff --git a/src/root/port.c b/src/root/port.c
index dc80fa3..a2a32cd 100644
--- a/src/root/port.c
+++ b/src/root/port.c
@@ -160,6 +160,8 @@ longdouble Port::strtold(const char *buffer, char **endp)
// Disable useless warnings about unreferenced functions
#pragma warning (disable : 4514)
+#include <llvm/ADT/APFloat.h>
+#include <llvm/ADT/StringRef.h>
#include <math.h>
#include <float.h> // for _isnan
#include <time.h>
@@ -169,6 +171,11 @@ longdouble Port::strtold(const char *buffer, char **endp)
#include <wchar.h>
#include <stdlib.h>
#include <limits> // for std::numeric_limits
+#include "target.h"
+
+#if IN_LLVM
+#include "llvm/Support/ErrorHandling.h"
+#endif
double Port::nan;
longdouble Port::ldbl_nan;
@@ -198,28 +210,52 @@ static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
+#if IN_LLVM PORTINITIALIZER IS GONE?
union {
unsigned long ul[2];
double d;
- } nan = {{ 0, 0x7FF80000 }};
+ }
+ nan = { { 0, 0x7FF80000 } },
+ snan = { { 0, 0x7FFC0000 } },
+ inf = { { 0, 0x7FF00000 } };
+
+ Port::nan = nan.d;
+ Port::ldbl_nan = nan.d;
+ Port::snan = snan.d;
+ Port::infinity = inf.d;
+ Port::ldbl_infinity = inf.d;
+#else
+ union {
+ unsigned long ul[2];
+ double d;
+ } nan = { { 0, 0x7FF80000 } };
Port::nan = nan.d;
Port::ldbl_nan = ld_qnan;
Port::snan = ld_snan;
Port::infinity = std::numeric_limits<double>::infinity();
Port::ldbl_infinity = ld_inf;
+#endif
_set_abort_behavior(_WRITE_ABORT_MSG, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // disable crash report
}
int Port::isNan(double r)
{
+#if _MSC_VER >= 1900
+ return ::isnan(r);
+#else
return ::_isnan(r);
+#endif
}
int Port::isNan(longdouble r)
{
+#if IN_LLVM
+ return ::isnan(r);
+#else
return ::_isnan(r);
+#endif
}
int Port::isSignallingNan(double r)
@@ -239,7 +275,11 @@ int Port::isSignallingNan(longdouble r)
int Port::isInfinity(double r)
{
+#if _MSC_VER >= 1900
+ return ::isinf(r);
+#else
return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
+#endif
}
longdouble Port::sqrt(longdouble x)
@@ -257,9 +297,20 @@ int Port::fequal(longdouble x, longdouble y)
/* In some cases, the REALPAD bytes get garbage in them,
* so be sure and ignore them.
*/
- return memcmp(&x, &y, 10) == 0;
+ return memcmp(&x, &y, Target::realsize - Target::realpad) == 0;
+}
@@ -337,6 +389,9 @@ int Port::stricmp(const char *s1, const char *s2)
float Port::strtof(const char *p, char **endp)
{
+#if _MSC_VER >= 1900
+ return ::strtof(p, endp); // C99 conformant since VS 2015
+#else
if(endp)
return static_cast<float>(::strtod(p, endp)); // does not set errno for underflows, but unused
@@ -345,10 +400,14 @@ float Port::strtof(const char *p, char **endp)
if (res == _UNDERFLOW)
errno = ERANGE;
return flt.f;
+#endif
}
double Port::strtod(const char *p, char **endp)
{
+#if _MSC_VER >= 1900
+ return ::strtod(p, endp); // C99 conformant since VS 2015
+#else
if(endp)
return ::strtod(p, endp); // does not set errno for underflows, but unused
@@ -357,6 +416,7 @@ double Port::strtod(const char *p, char **endp)
if (res == _UNDERFLOW)
errno = ERANGE;
return dbl.x;
+#endif
}
// from backend/strtold.c, renamed to avoid clash with decl in stdlib.h
@@ -364,7 +424,19 @@ longdouble strtold_dm(const char *p,char **endp);
longdouble Port::strtold(const char *p, char **endp)
{
+#if IN_LLVM
+#if _MSC_VER >= 1900
+ return ::strtold(p, endp); // C99 conformant since VS 2015
+#else
+ // MSVC strtold() before VS 2015 does not support hex float strings. Just
+ // use the function provided by LLVM because we going to use it anyway.
+ llvm::APFloat val(llvm::APFloat::IEEEdouble, llvm::APFloat::uninitialized);
+ val.convertFromString(llvm::StringRef(p), llvm::APFloat::rmNearestTiesToEven);
+ return val.convertToDouble();
+#endif
+#else
return ::strtold_dm(p, endp);
+#endif
}
#endif
@@ -579,7 +651,7 @@ longdouble Port::strtold(const char *p, char **endp)
#endif
-#if __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__
+#if __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __DragonFly__ || __HAIKU__
#include <math.h>
#if __linux__
@@ -599,6 +671,7 @@ longdouble Port::strtold(const char *p, char **endp)
#include <wchar.h>
#include <float.h>
#include <assert.h>
+#include "target.h"
double Port::nan;
longdouble Port::ldbl_nan;
@@ -629,28 +702,91 @@ static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
+#if IN_LLVM
+ union
+ { unsigned int ui[2];
+ double d;
+ } nan =
+#if __LITTLE_ENDIAN__
+ {{ 0, 0x7FF80000 }};
+#else
+ {{ 0x7FF80000, 0 }};
+#endif
+#else
union
{ unsigned int ui[2];
double d;
} nan = {{ 0, 0x7FF80000 }};
-
+#endif
Port::nan = nan.d;
assert(!signbit(Port::nan));
+#if IN_LLVM
+ if (sizeof(double) == sizeof(longdouble))
+ {
+ // double and longdouble are same type.
+ // E.g. on ARM.
+ Port::ldbl_nan = Port::nan;
+ }
+ else
+ {
+ union
+ { unsigned int ui[4];
+ longdouble ld;
+ } ldbl_nan =
+#if __LITTLE_ENDIAN__
+ {{ 0, 0xC0000000, 0x7FFF, 0}};
+#else
+ {{ 0, 0x7FFF, 0xC0000000, 0}};
+#endif
+ Port::ldbl_nan = ldbl_nan.ld;
+ }
+#else
union
{ unsigned int ui[4];
longdouble ld;
} ldbl_nan = {{ 0, 0xC0000000, 0x7FFF, 0}};
-
Port::ldbl_nan = ldbl_nan.ld;
+#endif
+
assert(!signbit(Port::ldbl_nan));
+#if IN_LLVM
+ if (sizeof(double) == sizeof(longdouble))
+ {
+ // double and longdouble are same type.
+ // E.g. on ARM.
+ union
+ { unsigned int ui[2];
+ double d;
+ } snan =
+#if __LITTLE_ENDIAN__
+ {{ 0, 0x7FFC0000 }};
+#else
+ {{ 0x7FFC0000, 0 }};
+#endif
+ Port::snan = snan.d;
+ }
+ else
+ {
+ union
+ { unsigned int ui[4];
+ longdouble ld;
+ } snan =
+ #if __LITTLE_ENDIAN__
+ {{ 0, 0xA0000000, 0x7FFF, 0 }};
+ #else
+ {{ 0, 0x7FFF, 0xA0000000, 0 }};
+ #endif
+ Port::snan = snan.ld;
+ }
+#else
union
{ unsigned int ui[4];
longdouble ld;
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
-
Port::snan = snan.ld;
+#endif
#if __FreeBSD__ && __i386__
// LDBL_MAX comes out as infinity. Fix.
@@ -670,7 +806,7 @@ int Port::isNan(double r)
#else
return __inline_isnan(r);
#endif
-#elif __FreeBSD__ || __OpenBSD__
+#elif __HAIKU__ || __FreeBSD__ || __OpenBSD__ || __DragonFly__
return isnan(r);
#else
#undef isnan
@@ -686,7 +822,7 @@ int Port::isNan(longdouble r)
#else
return __inline_isnan(r);
#endif
-#elif __FreeBSD__ || __OpenBSD__
+#elif __HAIKU__ || __FreeBSD__ || __OpenBSD__ || __DragonFly__
return isnan(r);
#else
#undef isnan
@@ -714,7 +850,7 @@ int Port::isInfinity(double r)
{
#if __APPLE__
return fpclassify(r) == FP_INFINITE;
-#elif __FreeBSD__ || __OpenBSD__
+#elif __HAIKU__ || __FreeBSD__ || __OpenBSD__ || __DragonFly__
return isinf(r);
#else
#undef isinf
@@ -729,7 +865,7 @@ longdouble Port::sqrt(longdouble x)
longdouble Port::fmodl(longdouble x, longdouble y)
{
-#if __FreeBSD__ && __FreeBSD_version < 800000 || __OpenBSD__
+#if __FreeBSD__ && __FreeBSD_version < 800000 || __OpenBSD__ || __DragonFly__
return ::fmod(x, y); // hack for now, fix later
#else
return ::fmodl(x, y);
@@ -741,7 +877,7 @@ int Port::fequal(longdouble x, longdouble y)
/* In some cases, the REALPAD bytes get garbage in them,
* so be sure and ignore them.
*/
- return memcmp(&x, &y, 10) == 0;
+ return memcmp(&x, &y, Target::realsize - Target::realpad) == 0;
}
#if __i386 || __x86_64__
@@ -956,6 +1092,36 @@ int Port::fequal(longdouble x, longdouble y)
return memcmp(&x, &y, 10) == 0;
}
#if __i386
+#if IN_LLVM
+// There seems to be an issue with register usage if compiled as PIC.
+void Port::yl2x_impl(long double* x, long double* y, long double* res)
+{
+ __asm__ volatile("movl %0, %%eax;" // move x, y, res to registers
+ "movl %1, %%ecx;"
+ "fldt (%%edx);" // push *y and *x to the FPU stack
+ "fldt (%%eax);" // "t" suffix means tbyte
+ "movl %2, %%eax;"
+ "fyl2x;" // do operation and wait
+ "fstpt (%%eax)" // pop result to a *res
+ : // output: empty
+ :"r"(x), "r"(y), "r"(res) // input: x => %0, y => %1, res => %2
+ :"%eax", "%ecx", "%eax"); // clobbered register: eax, ecx, eax
+}
+
+void Port::yl2xp1_impl(long double* x, long double* y, long double* res)
+{
+ __asm__ volatile("movl %0, %%eax;" // move x, y, res to registers
+ "movl %1, %%ecx;"
+ "fldt (%%ecx);" // push *y and *x to the FPU stack
+ "fldt (%%eax);" // "t" suffix means tbyte
+ "movl %2, %%eax;"
+ "fyl2xp1;" // do operation and wait
+ "fstpt (%%eax)" // pop result to a *res
+ : // output: empty
+ :"r"(x), "r"(y), "r"(res) // input: x => %0, y => %1, res => %2
+ :"%eax", "%ecx", "%eax"); // clobbered register: eax, ecx, eax
+}
+#else
void Port::yl2x_impl(long double* x, long double* y, long double* res)
{
__asm__ volatile("movl %0, %%eax;" // move x, y, res to registers
@@ -983,7 +1149,7 @@ void Port::yl2xp1_impl(long double* x, long double* y, long double* res)
:"r"(x), "r"(y), "r"(res) // input: x => %0, y => %1, res => %2
:"%eax", "%ebx", "%ecx"); // clobbered register: eax, ebc, ecx
}
-
+#endif
#elif __x86_64__
void Port::yl2x_impl(long double* x, long double* y, long double* res)
{
diff --git a/src/root/speller.c b/src/root/speller.c
index eba4e9b..aecf16f 100644
--- a/src/root/speller.c
+++ b/src/root/speller.c
@@ -15,6 +15,8 @@
#if __sun || _MSC_VER
#include <alloca.h>
+#elif __MINGW32__ UNNECESSARY DIFF ?
+#include <malloc.h>
#endif
#include "speller.h"
diff --git a/src/scope.h b/src/scope.h
index 5bdea22..953ba78 100644
--- a/src/scope.h
+++ b/src/scope.h
@@ -35,6 +35,11 @@ class TemplateInstance;
#include "dsymbol.h"
+#if IN_LLVM UNNECESSARY DIFF ?
+struct EnclosingHandler;
+class AnonDeclaration;
+#endif
+
#if __GNUC__
// Requires a full definition for LINK
#include "mars.h"
diff --git a/src/statement.c b/src/statement.c
index d02bcca..ac5acf3 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -240,10 +240,16 @@ int Statement::blockExit(FuncDeclaration *func, bool mustNotThrow)
void visit(Statement *s)
{
+#if IN_LLVM THIS IS UNNECESSARY I THINK
+ std::string msg("Statement::blockExit: ");
+ msg.append(s->toChars());
+ llvm_unreachable(msg.c_str());
+#else
printf("Statement::blockExit(%p)\n", s);
printf("%s\n", s->toChars());
assert(0);
result = BEany;
+#endif
}
void visit(ErrorStatement *s)
@@ -5210,6 +5286,7 @@ LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()?
return this;
}
+#if !IN_LLVM
/************************ AsmStatement ***************************************/
@@ -5229,12 +5306,17 @@ Statement *AsmStatement::syntaxCopy()
return new AsmStatement(loc, tokens);
}
+#endif
+
/************************ CompoundAsmStatement ***************************************/
diff --git a/src/statement.h b/src/statement.h
index ce4a2f6..d8691aa 100644
--- a/src/statement.h
+++ b/src/statement.h
@@ -80,6 +100,7 @@ class Statement : public RootObject
{
public:
Loc loc;
+ virtual ~Statement() {} SCARY, NOT NEEDED I HOPE?
Statement(Loc loc);
virtual Statement *syntaxCopy();
diff --git a/src/template.c b/src/template.c
index 3ec65c7..92c6852 100644