From 7ab407da3842655f509147f72463abbdf7a88e9c Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 26 May 2013 18:53:09 +0200 Subject: [PATCH 1/9] Separate out MinGW Port implementation. This explicit style is generally preferred in DMD for platform- specific code, and makes sense here as long doubles are tricky on MinGW. --- dmd2/root/port.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 183 insertions(+), 4 deletions(-) diff --git a/dmd2/root/port.c b/dmd2/root/port.c index 820a36e8..e486523c 100644 --- a/dmd2/root/port.c +++ b/dmd2/root/port.c @@ -350,7 +350,186 @@ int Port::stricmp(const char *s1, const char *s2) #endif -#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__ || __MINGW32__ +#if __MINGW32__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} + +#endif + +#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__ #include #if linux @@ -408,7 +587,7 @@ int Port::isNan(double r) #else return __inline_isnan(r); #endif -#elif __HAIKU__ || __OpenBSD__ || __MINGW32__ +#elif __HAIKU__ || __OpenBSD__ return isnan(r); #else #undef isnan @@ -424,7 +603,7 @@ int Port::isNan(longdouble r) #else return __inline_isnan(r); #endif -#elif __HAIKU__ || __OpenBSD__ || __MINGW32__ +#elif __HAIKU__ || __OpenBSD__ return isnan(r); #else #undef isnan @@ -460,7 +639,7 @@ int Port::isInfinity(double r) { #if __APPLE__ return fpclassify(r) == FP_INFINITE; -#elif defined __HAIKU__ || __OpenBSD__ || __MINGW32__ +#elif defined __HAIKU__ || __OpenBSD__ return isinf(r); #else #undef isinf From bf4df5fcc4a1fd1e3e34a51f9324fb4fb6bb5a5f Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 26 May 2013 19:08:51 +0200 Subject: [PATCH 2/9] Remove unnecessary #undefs in Port header. The Port function names are actually camel-cased and as such do not collide with the math macros, and undefining the names in the header is just annoying on platforms where you want to use the system macros in the implementation. --- dmd2/root/port.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/dmd2/root/port.h b/dmd2/root/port.h index c02675d0..770181ca 100644 --- a/dmd2/root/port.h +++ b/dmd2/root/port.h @@ -41,14 +41,6 @@ struct Port static double dbl_min; 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(longdouble); From 0b5989c51a8bf2d5fb0eb574a31bc6b72af99949 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 26 May 2013 19:10:08 +0200 Subject: [PATCH 3/9] MinGW: Use actually working strtold. Like their whole runtime in general, the MSVC version does not handle 80 bit reals/long doubles. --- dmd2/expression.c | 2 +- dmd2/lexer.c | 2 +- dmd2/root/port.c | 23 +++++++++++++++++++++++ dmd2/root/port.h | 4 ++-- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/dmd2/expression.c b/dmd2/expression.c index 9fd2eb1c..2e7aeeb6 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -2567,7 +2567,7 @@ void floatToBuffer(OutBuffer *buf, Type *type, real_t value) real_t r = strtold(buffer, NULL); __locale_decpoint = save; #else - real_t r = strtold(buffer, NULL); + real_t r = Port::strtold(buffer, NULL); #endif #if IN_LLVM if (r == value) // if exact duplication diff --git a/dmd2/lexer.c b/dmd2/lexer.c index 2e53a992..4d92e357 100644 --- a/dmd2/lexer.c +++ b/dmd2/lexer.c @@ -2365,7 +2365,7 @@ done: #ifdef IN_GCC t->float80value = real_t::parse((char *)stringbuffer.data, real_t::LongDouble); #else - t->float80value = strtold((char *)stringbuffer.data, NULL); + t->float80value = Port::strtold((char *)stringbuffer.data, NULL); #endif errno = 0; float strtofres; diff --git a/dmd2/root/port.c b/dmd2/root/port.c index e486523c..4422809a 100644 --- a/dmd2/root/port.c +++ b/dmd2/root/port.c @@ -348,6 +348,14 @@ int Port::stricmp(const char *s1, const char *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 #if __MINGW32__ @@ -527,6 +535,11 @@ int Port::stricmp(const char *s1, const char *s2) return result; } +longdouble Port::strtold(const char *p, char **endp) +{ + return ::__mingw_strtold(p, endp); +} + #endif #if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__ @@ -765,6 +778,11 @@ int Port::stricmp(const char *s1, const char *s2) return result; } +longdouble Port::strtold(const char *p, char **endp) +{ + return ::strtold(p, endp); +} + #endif #if __sun @@ -910,4 +928,9 @@ char *Port::strupr(char *s) return t; } +longdouble Port::strtold(const char *p, char **endp) +{ + return ::strtold(p, endp); +} + #endif diff --git a/dmd2/root/port.h b/dmd2/root/port.h index 770181ca..41c2aaff 100644 --- a/dmd2/root/port.h +++ b/dmd2/root/port.h @@ -19,8 +19,6 @@ #if _MSC_VER #include // for _isnan #include // 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 isnan _isnan @@ -72,6 +70,8 @@ struct Port static int memicmp(const char *s1, const char *s2, int n); static int stricmp(const char *s1, const char *s2); + + static longdouble strtold(const char *p, char **endp); }; #endif From 798a8e7822d0a33661053a96e41d4d40f065e945 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Wed, 29 May 2013 22:17:50 +0200 Subject: [PATCH 4/9] MinGW: Fixed long double formatting. --- dmd2/root/longdouble.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dmd2/root/longdouble.h b/dmd2/root/longdouble.h index 99f91f4d..0e8e4498 100644 --- a/dmd2/root/longdouble.h +++ b/dmd2/root/longdouble.h @@ -34,6 +34,12 @@ typedef volatile long double volatile_longdouble; // template longdouble ldouble(T x) { return (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) { char sfmt[4] = "%Lg"; @@ -41,6 +47,10 @@ inline size_t ld_sprint(char* str, int fmt, longdouble x) return sprintf(str, sfmt, x); } +#if __MINGW32__ +#undef sprintf +#endif + #else #include From 0a7eec400ff070b43dd4e46e216e67d7c339b867 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 2 Jun 2013 18:41:59 +0200 Subject: [PATCH 5/9] Removed dead global initializer code. --- gen/llvmhelpers.cpp | 45 --------------------------------------------- gen/llvmhelpers.h | 3 --- 2 files changed, 48 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index c36d5641..cfd88b63 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -985,51 +985,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(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 diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index efd37be2..f5b89f8a 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -108,9 +108,6 @@ TemplateInstance* DtoIsTemplateInstance(Dsymbol* s, bool checkLiteralOwner = fal /// Dispatches as appropriate. void DtoResolveDsymbol(Dsymbol* dsym); -/// Generates the constant initializer for a global variable. -void DtoConstInitGlobal(VarDeclaration* vd); - // declaration inside a declarationexp void DtoVarDeclaration(VarDeclaration* var); DValue* DtoDeclarationExp(Dsymbol* declaration); From d9ce9ce67b99a86afb5fc503c66bb6ba73ad2d24 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 2 Jun 2013 19:49:44 +0200 Subject: [PATCH 6/9] Removed TODO-riddled DtoInitializer only used in DtoVarDeclaration. --- gen/llvmhelpers.cpp | 43 +++++++++---------------------------------- gen/llvmhelpers.h | 1 - 2 files changed, 9 insertions(+), 35 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index cfd88b63..bee487f1 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1071,7 +1071,15 @@ void DtoVarDeclaration(VarDeclaration* vd) if (Logger::enabled()) 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: /* Mark the point of construction of a variable that needs to be destructed. @@ -1300,39 +1308,6 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init) ////////////////////////////////////////////////////////////////////////////////////////// -DValue* DtoInitializer(LLValue* target, Initializer* init) -{ - if (!init) - return 0; - - 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()); diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index f5b89f8a..483e24c7 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -116,7 +116,6 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr = 0); // initializer helpers LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init); LLConstant* DtoConstExpInit(Loc loc, Type* t, Expression* exp); -DValue* DtoInitializer(LLValue* target, Initializer* init); // getting typeinfo of type, base=true casts to object.TypeInfo LLConstant* DtoTypeInfoOf(Type* ty, bool base=true); From ae48a1925125b3c1efa512b10637e85cb0e5621c Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 2 Jun 2013 20:08:09 +0200 Subject: [PATCH 7/9] Refactoring-only part of DtoConstExpInit fix. --- gen/llvmhelpers.cpp | 37 ++++++++++++++++--------------------- gen/llvmhelpers.h | 2 +- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index bee487f1..b548960d 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1308,18 +1308,11 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init) ////////////////////////////////////////////////////////////////////////////////////////// -static LLConstant* expand_to_sarray(Type *base, Expression* exp) +static LLConstant* expand_to_sarray(Type* targetType, Type* initType, LLConstant* initConst) { - 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(); + Type* expbase = stripModifiers(initType); + IF_LOG Logger::println("expbase: %s", expbase->toChars()); + Type* t = targetType; LLSmallVector dims; @@ -1341,19 +1334,21 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp) std::vector inits; while (i--) { - LLArrayType* arrty = LLArrayType::get(val->getType(), dims[i]); + LLArrayType* arrty = LLArrayType::get(initConst->getType(), dims[i]); inits.clear(); - inits.insert(inits.end(), dims[i], val); - val = LLConstantArray::get(arrty, inits); + inits.insert(inits.end(), dims[i], initConst); + initConst = LLConstantArray::get(arrty, inits); } - return val; + return initConst; } -LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp) +LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp) { + LLConstant* val = exp->toConstElem(gIR); + Type* expbase = stripModifiers(exp->type->toBasetype())->merge(); - Type* base = stripModifiers(type->toBasetype())->merge(); + Type* base = stripModifiers(targetType->toBasetype())->merge(); // if not the same basetypes, we won't get the same llvm types either if (!expbase->equals(base)) @@ -1365,12 +1360,12 @@ LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp) fatal(); } Logger::println("type is a static array, building constant array initializer to single value"); - return expand_to_sarray(base, exp); + return expand_to_sarray(base, expbase, val); } if (base->ty == Tvector) { - LLConstant* val = exp->toConstElem(gIR); + TypeVector* tv = (TypeVector*)base; assert(tv->basetype->ty == Tsarray); @@ -1386,11 +1381,11 @@ LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp) } error(loc, "LDC internal error: cannot yet convert default initializer %s of type %s to %s", - exp->toChars(), exp->type->toChars(), type->toChars()); + exp->toChars(), exp->type->toChars(), targetType->toChars()); llvm_unreachable("Unsupported default initializer."); } - return exp->toConstElem(gIR); + return val; } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 483e24c7..fc807b7d 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -115,7 +115,7 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr = 0); // initializer helpers LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init); -LLConstant* DtoConstExpInit(Loc loc, Type* t, Expression* exp); +LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp); // getting typeinfo of type, base=true casts to object.TypeInfo LLConstant* DtoTypeInfoOf(Type* ty, bool base=true); From c89d4809d6b2f19d48b0a0c289f34cb2e5a94db2 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 2 Jun 2013 20:57:59 +0200 Subject: [PATCH 8/9] Be more lenient with initializer type mismatch; zext as necessary. The integer initializer width mismatch issue should really be fixed in the frontend, but is related to forward referencing and thus hard to track down. Also fixes an unlisted regression since the 2.061 merge, where there would be a const(char*) vs. immutable(char*) mismatch reported for some string constants. GitHub: Fixes #378. --- gen/llvmhelpers.cpp | 103 +++++++++++++++++++++++++++-------------- tests/d2/dmd-testsuite | 2 +- 2 files changed, 70 insertions(+), 35 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index b548960d..ad4a1849 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1345,46 +1345,81 @@ static LLConstant* expand_to_sarray(Type* targetType, Type* initType, LLConstant 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); - Type* expbase = stripModifiers(exp->type->toBasetype())->merge(); - Type* base = stripModifiers(targetType->toBasetype())->merge(); + // 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. - // if not the same basetypes, we won't get the same llvm types either - if (!expbase->equals(base)) + Type* expBase = stripModifiers(exp->type->toBasetype())->merge(); + Type* targetBase = stripModifiers(targetType->toBasetype())->merge(); + + if (expBase->equals(targetBase)) { - if (base->ty == Tsarray) - { - if (base->nextOf()->toBasetype()->ty == Tvoid) { - error(loc, "static arrays of voids have no default initializer"); - fatal(); - } - Logger::println("type is a static array, building constant array initializer to single value"); - return expand_to_sarray(base, expbase, val); - } - - if (base->ty == Tvector) - { - - - TypeVector* tv = (TypeVector*)base; - assert(tv->basetype->ty == Tsarray); - dinteger_t elemCount = - static_cast(tv->basetype)->dim->toInteger(); - -#if LDC_LLVM_VER == 300 - std::vector Elts(elemCount, val); - return llvm::ConstantVector::get(Elts); -#else - return llvm::ConstantVector::getSplat(elemCount, val); -#endif - } - - error(loc, "LDC internal error: cannot yet convert default initializer %s of type %s to %s", - exp->toChars(), exp->type->toChars(), targetType->toChars()); - llvm_unreachable("Unsupported default initializer."); + Logger::println("Matching D types, nothing left to do."); + return val; } + llvm::Type* llType = val->getType(); + llvm::Type* targetLLType = DtoType(targetBase); + if (llType == targetLLType) + { + Logger::println("Matching LLVM types, ignoring frontend glitch."); + return val; + } + + if (targetBase->ty == Tsarray) + { + if (targetBase->nextOf()->toBasetype()->ty == Tvoid) { + error(loc, "static arrays of voids have no default initializer"); + fatal(); + } + Logger::println("Building constant array initializer to single value."); + return expand_to_sarray(targetBase, expBase, val); + } + + if (targetBase->ty == Tvector) + { + Logger::println("Building vector initializer from scalar."); + + TypeVector* tv = static_cast(targetBase); + assert(tv->basetype->ty == Tsarray); + dinteger_t elemCount = + static_cast(tv->basetype)->dim->toInteger(); + +#if LDC_LLVM_VER == 300 + std::vector Elts(elemCount, val); + return llvm::ConstantVector::get(Elts); +#else + return llvm::ConstantVector::getSplat(elemCount, val); +#endif + } + + if (llType->isIntegerTy() && targetLLType->isIntegerTy()) + { + // This should really be fixed in the frontend. + Logger::println("Fixing up unresolved implicit integer conversion."); + + llvm::IntegerType* source = llvm::cast(llType); + llvm::IntegerType* target = llvm::cast(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); + } + + Logger::println("Unhandled type mismatch, giving up."); return val; } diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 7ee870da..2d8d874e 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 7ee870da26b38c32b98b7ca7fafd755f1f43be40 +Subproject commit 2d8d874e2a33cea9d9fd751f9c2baab5e8ccc992 From ec59399e2156fb0fa097ed9216b7a8a84f50bc0d Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 2 Jun 2013 21:27:02 +0200 Subject: [PATCH 9/9] Change all URLs to point to wiki.dlang.org for the time being. --- driver/ldmd.cpp | 2 +- gen/todebug.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/driver/ldmd.cpp b/driver/ldmd.cpp index f918d61a..310ec784 100644 --- a/driver/ldmd.cpp +++ b/driver/ldmd.cpp @@ -717,7 +717,7 @@ Params parseArgs(size_t originalArgc, char** originalArgv, ls::Path ldcPath) } else if (memcmp(p + 1, "man", 3) == 0) { - browse("http://ldc-developers.github.com"); + browse("http://wiki.dlang.org/LDC"); exit(EXIT_SUCCESS); } else if (strcmp(p + 1, "run") == 0) diff --git a/gen/todebug.cpp b/gen/todebug.cpp index 662cedd9..839a714b 100644 --- a/gen/todebug.cpp +++ b/gen/todebug.cpp @@ -520,7 +520,7 @@ void DtoDwarfCompileUnit(Module* m) global.params.symdebug == 2 ? DW_LANG_C : DW_LANG_D, srcname, srcpath, - "LDC (https://github.com/ldc-developers/ldc)", + "LDC (https://wiki.dlang.org/LDC)", false, // isOptimized TODO llvm::StringRef(), // Flags TODO 1 // Runtime Version TODO