mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 10:57:35 +03:00
Merge branch 'release-0.11.0'.
Conflicts: gen/llvmhelpers.cpp
This commit is contained in:
commit
005f993982
10 changed files with 308 additions and 148 deletions
|
@ -2567,7 +2567,7 @@ void floatToBuffer(OutBuffer *buf, Type *type, real_t value)
|
||||||
real_t r = strtold(buffer, NULL);
|
real_t r = strtold(buffer, NULL);
|
||||||
__locale_decpoint = save;
|
__locale_decpoint = save;
|
||||||
#else
|
#else
|
||||||
real_t r = strtold(buffer, NULL);
|
real_t r = Port::strtold(buffer, NULL);
|
||||||
#endif
|
#endif
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
if (r == value) // if exact duplication
|
if (r == value) // if exact duplication
|
||||||
|
|
|
@ -2365,7 +2365,7 @@ done:
|
||||||
#ifdef IN_GCC
|
#ifdef IN_GCC
|
||||||
t->float80value = real_t::parse((char *)stringbuffer.data, real_t::LongDouble);
|
t->float80value = real_t::parse((char *)stringbuffer.data, real_t::LongDouble);
|
||||||
#else
|
#else
|
||||||
t->float80value = strtold((char *)stringbuffer.data, NULL);
|
t->float80value = Port::strtold((char *)stringbuffer.data, NULL);
|
||||||
#endif
|
#endif
|
||||||
errno = 0;
|
errno = 0;
|
||||||
float strtofres;
|
float strtofres;
|
||||||
|
|
|
@ -34,6 +34,12 @@ typedef volatile long double volatile_longdouble;
|
||||||
// template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
|
// template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
|
||||||
#define ldouble(x) ((longdouble)(x))
|
#define ldouble(x) ((longdouble)(x))
|
||||||
|
|
||||||
|
#if __MINGW32__
|
||||||
|
// MinGW supports 80 bit reals, but the formatting functions map to versions
|
||||||
|
// from the MSVC runtime by default which don't.
|
||||||
|
#define sprintf __mingw_sprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
inline size_t ld_sprint(char* str, int fmt, longdouble x)
|
inline size_t ld_sprint(char* str, int fmt, longdouble x)
|
||||||
{
|
{
|
||||||
char sfmt[4] = "%Lg";
|
char sfmt[4] = "%Lg";
|
||||||
|
@ -41,6 +47,10 @@ inline size_t ld_sprint(char* str, int fmt, longdouble x)
|
||||||
return sprintf(str, sfmt, x);
|
return sprintf(str, sfmt, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __MINGW32__
|
||||||
|
#undef sprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
210
dmd2/root/port.c
210
dmd2/root/port.c
|
@ -348,9 +348,201 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||||
return ::stricmp(s1, s2);
|
return ::stricmp(s1, s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See vcbuild/strtold.c.
|
||||||
|
longdouble strtold(const char *p, char **endp);
|
||||||
|
|
||||||
|
longdouble Port::strtold(const char *p, char **endp)
|
||||||
|
{
|
||||||
|
return ::strtold(p, endp);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__ || __MINGW32__
|
#if __MINGW32__
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
static double zero = 0;
|
||||||
|
double Port::nan = copysign(NAN, 1.0);
|
||||||
|
double Port::infinity = 1 / zero;
|
||||||
|
double Port::dbl_max = 1.7976931348623157e308;
|
||||||
|
double Port::dbl_min = 5e-324;
|
||||||
|
longdouble Port::ldbl_max = LDBL_MAX;
|
||||||
|
|
||||||
|
struct PortInitializer
|
||||||
|
{
|
||||||
|
PortInitializer();
|
||||||
|
};
|
||||||
|
|
||||||
|
static PortInitializer portinitializer;
|
||||||
|
|
||||||
|
PortInitializer::PortInitializer()
|
||||||
|
{
|
||||||
|
assert(!signbit(Port::nan));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Port::isNan(double r)
|
||||||
|
{
|
||||||
|
return isnan(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Port::isNan(longdouble r)
|
||||||
|
{
|
||||||
|
return isnan(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Port::isSignallingNan(double r)
|
||||||
|
{
|
||||||
|
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||||
|
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||||
|
*/
|
||||||
|
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Port::isSignallingNan(longdouble r)
|
||||||
|
{
|
||||||
|
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||||
|
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||||
|
*/
|
||||||
|
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Port::isFinite(double r)
|
||||||
|
{
|
||||||
|
return ::finite(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Port::isInfinity(double r)
|
||||||
|
{
|
||||||
|
return isinf(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Port::Signbit(double r)
|
||||||
|
{
|
||||||
|
union { double d; long long ll; } u;
|
||||||
|
u.d = r;
|
||||||
|
return u.ll < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Port::floor(double d)
|
||||||
|
{
|
||||||
|
return ::floor(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Port::pow(double x, double y)
|
||||||
|
{
|
||||||
|
return ::pow(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||||
|
{
|
||||||
|
return ::fmodl(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||||
|
{
|
||||||
|
return ::strtoull(p, pend, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||||
|
{
|
||||||
|
sprintf(buffer, "%llu", ull);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||||
|
{
|
||||||
|
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Port::ull_to_double(ulonglong ull)
|
||||||
|
{
|
||||||
|
return (double) ull;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *Port::list_separator()
|
||||||
|
{
|
||||||
|
return ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
const wchar_t *Port::wlist_separator()
|
||||||
|
{
|
||||||
|
return L",";
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Port::strupr(char *s)
|
||||||
|
{
|
||||||
|
char *t = s;
|
||||||
|
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
*s = toupper(*s);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Port::memicmp(const char *s1, const char *s2, int n)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{ char c1 = s1[i];
|
||||||
|
char c2 = s2[i];
|
||||||
|
|
||||||
|
result = c1 - c2;
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
result = toupper(c1) - toupper(c2);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Port::stricmp(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{ char c1 = *s1;
|
||||||
|
char c2 = *s2;
|
||||||
|
|
||||||
|
result = c1 - c2;
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
result = toupper(c1) - toupper(c2);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!c1)
|
||||||
|
break;
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
longdouble Port::strtold(const char *p, char **endp)
|
||||||
|
{
|
||||||
|
return ::__mingw_strtold(p, endp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#if linux
|
#if linux
|
||||||
|
@ -408,7 +600,7 @@ int Port::isNan(double r)
|
||||||
#else
|
#else
|
||||||
return __inline_isnan(r);
|
return __inline_isnan(r);
|
||||||
#endif
|
#endif
|
||||||
#elif __HAIKU__ || __OpenBSD__ || __MINGW32__
|
#elif __HAIKU__ || __OpenBSD__
|
||||||
return isnan(r);
|
return isnan(r);
|
||||||
#else
|
#else
|
||||||
#undef isnan
|
#undef isnan
|
||||||
|
@ -424,7 +616,7 @@ int Port::isNan(longdouble r)
|
||||||
#else
|
#else
|
||||||
return __inline_isnan(r);
|
return __inline_isnan(r);
|
||||||
#endif
|
#endif
|
||||||
#elif __HAIKU__ || __OpenBSD__ || __MINGW32__
|
#elif __HAIKU__ || __OpenBSD__
|
||||||
return isnan(r);
|
return isnan(r);
|
||||||
#else
|
#else
|
||||||
#undef isnan
|
#undef isnan
|
||||||
|
@ -460,7 +652,7 @@ int Port::isInfinity(double r)
|
||||||
{
|
{
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
return fpclassify(r) == FP_INFINITE;
|
return fpclassify(r) == FP_INFINITE;
|
||||||
#elif defined __HAIKU__ || __OpenBSD__ || __MINGW32__
|
#elif defined __HAIKU__ || __OpenBSD__
|
||||||
return isinf(r);
|
return isinf(r);
|
||||||
#else
|
#else
|
||||||
#undef isinf
|
#undef isinf
|
||||||
|
@ -586,6 +778,11 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
longdouble Port::strtold(const char *p, char **endp)
|
||||||
|
{
|
||||||
|
return ::strtold(p, endp);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __sun
|
#if __sun
|
||||||
|
@ -731,4 +928,9 @@ char *Port::strupr(char *s)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
longdouble Port::strtold(const char *p, char **endp)
|
||||||
|
{
|
||||||
|
return ::strtold(p, endp);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
#include <float.h> // for _isnan
|
#include <float.h> // for _isnan
|
||||||
#include <malloc.h> // for alloca
|
#include <malloc.h> // for alloca
|
||||||
// According to VC 8.0 docs, long double is the same as double
|
|
||||||
longdouble strtold(const char *p,char **endp);
|
|
||||||
#define strtof strtod
|
#define strtof strtod
|
||||||
#define isnan _isnan
|
#define isnan _isnan
|
||||||
|
|
||||||
|
@ -41,14 +39,6 @@ struct Port
|
||||||
static double dbl_min;
|
static double dbl_min;
|
||||||
static longdouble ldbl_max;
|
static longdouble ldbl_max;
|
||||||
|
|
||||||
#if !defined __HAIKU__ || __OpenBSD__
|
|
||||||
#elif __GNUC__
|
|
||||||
// These conflict with macros in math.h, should rename them
|
|
||||||
#undef isnan
|
|
||||||
#undef isfinite
|
|
||||||
#undef isinfinity
|
|
||||||
#undef signbit
|
|
||||||
#endif
|
|
||||||
static int isNan(double);
|
static int isNan(double);
|
||||||
static int isNan(longdouble);
|
static int isNan(longdouble);
|
||||||
|
|
||||||
|
@ -80,6 +70,8 @@ struct Port
|
||||||
|
|
||||||
static int memicmp(const char *s1, const char *s2, int n);
|
static int memicmp(const char *s1, const char *s2, int n);
|
||||||
static int stricmp(const char *s1, const char *s2);
|
static int stricmp(const char *s1, const char *s2);
|
||||||
|
|
||||||
|
static longdouble strtold(const char *p, char **endp);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -717,7 +717,7 @@ Params parseArgs(size_t originalArgc, char** originalArgv, ls::Path ldcPath)
|
||||||
}
|
}
|
||||||
else if (memcmp(p + 1, "man", 3) == 0)
|
else if (memcmp(p + 1, "man", 3) == 0)
|
||||||
{
|
{
|
||||||
browse("http://ldc-developers.github.com");
|
browse("http://wiki.dlang.org/LDC");
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
else if (strcmp(p + 1, "run") == 0)
|
else if (strcmp(p + 1, "run") == 0)
|
||||||
|
|
|
@ -983,51 +983,6 @@ void DtoResolveDsymbol(Dsymbol* dsym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void DtoConstInitGlobal(VarDeclaration* vd)
|
|
||||||
{
|
|
||||||
vd->codegen(Type::sir);
|
|
||||||
|
|
||||||
if (vd->ir.initialized) return;
|
|
||||||
vd->ir.initialized = gIR->dmodule;
|
|
||||||
|
|
||||||
Logger::println("DtoConstInitGlobal(%s) @ %s", vd->toChars(), vd->loc.toChars());
|
|
||||||
LOG_SCOPE;
|
|
||||||
|
|
||||||
// build the initializer
|
|
||||||
LLConstant* initVal = DtoConstInitializer(vd->loc, vd->type, vd->init);
|
|
||||||
|
|
||||||
// set the initializer if appropriate
|
|
||||||
IrGlobal* glob = vd->ir.irGlobal;
|
|
||||||
llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(glob->value);
|
|
||||||
|
|
||||||
//if (LLStructType *st = isaStruct(glob->type)) {
|
|
||||||
// st->setBody(initVal);
|
|
||||||
//}
|
|
||||||
|
|
||||||
assert(!glob->constInit);
|
|
||||||
glob->constInit = initVal;
|
|
||||||
|
|
||||||
// assign the initializer
|
|
||||||
if (!(vd->storage_class & STCextern) && mustDefineSymbol(vd))
|
|
||||||
{
|
|
||||||
if (Logger::enabled())
|
|
||||||
{
|
|
||||||
Logger::println("setting initializer");
|
|
||||||
Logger::cout() << "global: " << *gvar << '\n';
|
|
||||||
#if 0
|
|
||||||
Logger::cout() << "init: " << *initVal << '\n';
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
gvar->setInitializer(initVal);
|
|
||||||
|
|
||||||
// do debug info
|
|
||||||
DtoDwarfGlobalVariable(gvar, vd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
/*////////////////////////////////////////////////////////////////////////////////////////
|
/*////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// DECLARATION EXP HELPER
|
// DECLARATION EXP HELPER
|
||||||
|
@ -1114,7 +1069,15 @@ void DtoVarDeclaration(VarDeclaration* vd)
|
||||||
if (Logger::enabled())
|
if (Logger::enabled())
|
||||||
Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n';
|
Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n';
|
||||||
|
|
||||||
DtoInitializer(vd->ir.irLocal->value, vd->init); // TODO: Remove altogether?
|
if (vd->init)
|
||||||
|
{
|
||||||
|
if (ExpInitializer* ex = vd->init->isExpInitializer())
|
||||||
|
{
|
||||||
|
// TODO: Refactor this so that it doesn't look like toElem has no effect.
|
||||||
|
Logger::println("expression initializer");
|
||||||
|
ex->exp->toElem(gIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Lexit:
|
Lexit:
|
||||||
/* Mark the point of construction of a variable that needs to be destructed.
|
/* Mark the point of construction of a variable that needs to be destructed.
|
||||||
|
@ -1343,51 +1306,11 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DValue* DtoInitializer(LLValue* target, Initializer* init)
|
static LLConstant* expand_to_sarray(Type* targetType, Type* initType, LLConstant* initConst)
|
||||||
{
|
{
|
||||||
if (!init)
|
Type* expbase = stripModifiers(initType);
|
||||||
return 0;
|
IF_LOG Logger::println("expbase: %s", expbase->toChars());
|
||||||
|
Type* t = targetType;
|
||||||
if (ExpInitializer* ex = init->isExpInitializer())
|
|
||||||
{
|
|
||||||
Logger::println("expression initializer");
|
|
||||||
assert(ex->exp);
|
|
||||||
return ex->exp->toElem(gIR);
|
|
||||||
}
|
|
||||||
else if (init->isArrayInitializer())
|
|
||||||
{
|
|
||||||
// TODO: do nothing ?
|
|
||||||
}
|
|
||||||
else if (init->isVoidInitializer())
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
else if (init->isStructInitializer())
|
|
||||||
{
|
|
||||||
// TODO: again nothing ?
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
llvm_unreachable("Unknown initializer type.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static LLConstant* expand_to_sarray(Type *base, Expression* exp)
|
|
||||||
{
|
|
||||||
Logger::println("building type %s from expression (%s) of type %s", base->toChars(), exp->toChars(), exp->type->toChars());
|
|
||||||
LLType* dstTy = DtoType(base);
|
|
||||||
if (Logger::enabled())
|
|
||||||
Logger::cout() << "final llvm type requested: " << *dstTy << '\n';
|
|
||||||
|
|
||||||
LLConstant* val = exp->toConstElem(gIR);
|
|
||||||
|
|
||||||
Type* expbase = stripModifiers(exp->type->toBasetype());
|
|
||||||
Logger::println("expbase: %s", expbase->toChars());
|
|
||||||
Type* t = base->toBasetype();
|
|
||||||
|
|
||||||
LLSmallVector<size_t, 4> dims;
|
LLSmallVector<size_t, 4> dims;
|
||||||
|
|
||||||
|
@ -1409,36 +1332,64 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp)
|
||||||
std::vector<LLConstant*> inits;
|
std::vector<LLConstant*> inits;
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
LLArrayType* arrty = LLArrayType::get(val->getType(), dims[i]);
|
LLArrayType* arrty = LLArrayType::get(initConst->getType(), dims[i]);
|
||||||
inits.clear();
|
inits.clear();
|
||||||
inits.insert(inits.end(), dims[i], val);
|
inits.insert(inits.end(), dims[i], initConst);
|
||||||
val = LLConstantArray::get(arrty, inits);
|
initConst = LLConstantArray::get(arrty, inits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return initConst;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp)
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("DtoConstExpInit(targetType = %s, exp = %s)",
|
||||||
|
targetType->toChars(), exp->toChars());
|
||||||
|
LOG_SCOPE
|
||||||
|
|
||||||
|
LLConstant* val = exp->toConstElem(gIR);
|
||||||
|
|
||||||
|
// The situation here is a bit tricky: In an ideal world, we would always
|
||||||
|
// have val->getType() == DtoType(targetType). But there are two reasons
|
||||||
|
// why this is not true. One is that the LLVM type system cannot represent
|
||||||
|
// all the C types, leading to differences in types being necessary e.g. for
|
||||||
|
// union initializers. The second is that the frontend actually does not
|
||||||
|
// explicitly lowers things like initializing an array/vector with a scalar
|
||||||
|
// constant, or since 2.061 sometimes does not get implicit conversions for
|
||||||
|
// integers right. However, we cannot just rely on the actual Types being
|
||||||
|
// equal if there are no rewrites to do because of – as usual – AST
|
||||||
|
// inconsistency bugs.
|
||||||
|
|
||||||
|
Type* expBase = stripModifiers(exp->type->toBasetype())->merge();
|
||||||
|
Type* targetBase = stripModifiers(targetType->toBasetype())->merge();
|
||||||
|
|
||||||
|
if (expBase->equals(targetBase))
|
||||||
|
{
|
||||||
|
Logger::println("Matching D types, nothing left to do.");
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp)
|
llvm::Type* llType = val->getType();
|
||||||
|
llvm::Type* targetLLType = DtoType(targetBase);
|
||||||
|
if (llType == targetLLType)
|
||||||
{
|
{
|
||||||
Type* expbase = stripModifiers(exp->type->toBasetype())->merge();
|
Logger::println("Matching LLVM types, ignoring frontend glitch.");
|
||||||
Type* base = stripModifiers(type->toBasetype())->merge();
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
// if not the same basetypes, we won't get the same llvm types either
|
if (targetBase->ty == Tsarray)
|
||||||
if (!expbase->equals(base))
|
|
||||||
{
|
{
|
||||||
if (base->ty == Tsarray)
|
if (targetBase->nextOf()->toBasetype()->ty == Tvoid) {
|
||||||
{
|
|
||||||
if (base->nextOf()->toBasetype()->ty == Tvoid) {
|
|
||||||
error(loc, "static arrays of voids have no default initializer");
|
error(loc, "static arrays of voids have no default initializer");
|
||||||
fatal();
|
fatal();
|
||||||
}
|
}
|
||||||
Logger::println("type is a static array, building constant array initializer to single value");
|
Logger::println("Building constant array initializer to single value.");
|
||||||
return expand_to_sarray(base, exp);
|
return expand_to_sarray(targetBase, expBase, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base->ty == Tvector)
|
if (targetBase->ty == Tvector)
|
||||||
{
|
{
|
||||||
LLConstant* val = exp->toConstElem(gIR);
|
Logger::println("Building vector initializer from scalar.");
|
||||||
|
|
||||||
TypeVector* tv = (TypeVector*)base;
|
TypeVector* tv = (TypeVector*)base;
|
||||||
assert(tv->basetype->ty == Tsarray);
|
assert(tv->basetype->ty == Tsarray);
|
||||||
|
@ -1447,12 +1398,21 @@ LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp)
|
||||||
return llvm::ConstantVector::getSplat(elemCount, val);
|
return llvm::ConstantVector::getSplat(elemCount, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
error(loc, "LDC internal error: cannot yet convert default initializer %s of type %s to %s",
|
if (llType->isIntegerTy() && targetLLType->isIntegerTy())
|
||||||
exp->toChars(), exp->type->toChars(), type->toChars());
|
{
|
||||||
llvm_unreachable("Unsupported default initializer.");
|
// This should really be fixed in the frontend.
|
||||||
|
Logger::println("Fixing up unresolved implicit integer conversion.");
|
||||||
|
|
||||||
|
llvm::IntegerType* source = llvm::cast<llvm::IntegerType>(llType);
|
||||||
|
llvm::IntegerType* target = llvm::cast<llvm::IntegerType>(targetLLType);
|
||||||
|
|
||||||
|
assert(target->getBitWidth() > source->getBitWidth() && "On initializer "
|
||||||
|
"integer type mismatch, the target should be wider than the source.");
|
||||||
|
return llvm::ConstantExpr::getZExtOrBitCast(val, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
return exp->toConstElem(gIR);
|
Logger::println("Unhandled type mismatch, giving up.");
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -108,9 +108,6 @@ TemplateInstance* DtoIsTemplateInstance(Dsymbol* s, bool checkLiteralOwner = fal
|
||||||
/// Dispatches as appropriate.
|
/// Dispatches as appropriate.
|
||||||
void DtoResolveDsymbol(Dsymbol* dsym);
|
void DtoResolveDsymbol(Dsymbol* dsym);
|
||||||
|
|
||||||
/// Generates the constant initializer for a global variable.
|
|
||||||
void DtoConstInitGlobal(VarDeclaration* vd);
|
|
||||||
|
|
||||||
// declaration inside a declarationexp
|
// declaration inside a declarationexp
|
||||||
void DtoVarDeclaration(VarDeclaration* var);
|
void DtoVarDeclaration(VarDeclaration* var);
|
||||||
DValue* DtoDeclarationExp(Dsymbol* declaration);
|
DValue* DtoDeclarationExp(Dsymbol* declaration);
|
||||||
|
@ -118,8 +115,7 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr = 0);
|
||||||
|
|
||||||
// initializer helpers
|
// initializer helpers
|
||||||
LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init);
|
LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init);
|
||||||
LLConstant* DtoConstExpInit(Loc loc, Type* t, Expression* exp);
|
LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp);
|
||||||
DValue* DtoInitializer(LLValue* target, Initializer* init);
|
|
||||||
|
|
||||||
// getting typeinfo of type, base=true casts to object.TypeInfo
|
// getting typeinfo of type, base=true casts to object.TypeInfo
|
||||||
LLConstant* DtoTypeInfoOf(Type* ty, bool base=true);
|
LLConstant* DtoTypeInfoOf(Type* ty, bool base=true);
|
||||||
|
|
|
@ -516,7 +516,7 @@ void DtoDwarfCompileUnit(Module* m)
|
||||||
global.params.symdebug == 2 ? DW_LANG_C : DW_LANG_D,
|
global.params.symdebug == 2 ? DW_LANG_C : DW_LANG_D,
|
||||||
srcname,
|
srcname,
|
||||||
srcpath,
|
srcpath,
|
||||||
"LDC (https://github.com/ldc-developers/ldc)",
|
"LDC (https://wiki.dlang.org/LDC)",
|
||||||
false, // isOptimized TODO
|
false, // isOptimized TODO
|
||||||
llvm::StringRef(), // Flags TODO
|
llvm::StringRef(), // Flags TODO
|
||||||
1 // Runtime Version TODO
|
1 // Runtime Version TODO
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7ee870da26b38c32b98b7ca7fafd755f1f43be40
|
Subproject commit 2d8d874e2a33cea9d9fd751f9c2baab5e8ccc992
|
Loading…
Add table
Add a link
Reference in a new issue