Merge branch 'merge-2.064' into merge-2.065

This commit is contained in:
Kai Nacke
2013-12-08 19:30:00 +01:00
8 changed files with 96 additions and 107 deletions

View File

@@ -914,11 +914,6 @@ public:
/// Codegen traversal
void codegen(IRState* ir);
// vars declared in this function that nested funcs reference
// is this is not empty, nestedFrameRef is set and these VarDecls
// probably have nestedref set too, see VarDeclaration::checkNestedReference
std::set<VarDeclaration*> nestedVars;
std::string intrinsicName;
uint32_t priority;

View File

@@ -570,14 +570,17 @@ static void registerPredefinedTargetVersions() {
VersionCondition::addPredefinedGlobalIdent("Cygwin");
break;
case llvm::Triple::Linux:
VersionCondition::addPredefinedGlobalIdent("linux");
VersionCondition::addPredefinedGlobalIdent("Posix");
#if LDC_LLVM_VER >= 302
if (global.params.targetTriple.getEnvironment() == llvm::Triple::Android)
{
VersionCondition::addPredefinedGlobalIdent("Android");
}
else
#endif
{
VersionCondition::addPredefinedGlobalIdent("linux");
VersionCondition::addPredefinedGlobalIdent("Posix");
}
break;
case llvm::Triple::Haiku:
VersionCondition::addPredefinedGlobalIdent("Haiku");
@@ -622,8 +625,6 @@ static void registerPredefinedTargetVersions() {
#if LDC_LLVM_VER >= 302
case llvm::Triple::Android:
VersionCondition::addPredefinedGlobalIdent("Android");
VersionCondition::addPredefinedGlobalIdent("linux");
VersionCondition::addPredefinedGlobalIdent("Posix");
break;
#endif
default:

View File

@@ -576,14 +576,6 @@ DValue* DtoCastInt(Loc& loc, DValue* val, Type* _to)
return new DImValue(_to, rval);
}
// Check for special DMD hack to avoid "has no effect" error.
// See expression.c, method AssignExp::semantic(), around line 11499
llvm::ConstantInt* isConstInt = isaConstantInt(rval);
if (from == Type::tint32 && to == Type::tvoid && isConstInt->isNullValue())
{
return val;
}
size_t fromsz = from->size();
size_t tosz = to->size();

View File

@@ -15,6 +15,7 @@
#include "gen/llvmhelpers.h"
#include "gen/logger.h"
#include "gen/tollvm.h"
#include "gen/utils.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Support/CommandLine.h"
namespace cl = llvm::cl;
@@ -223,7 +224,7 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
return llvm::ConstantPointerNull::get(getVoidPtrType());
}
struct FuncDeclaration* frameToPass = 0;
FuncDeclaration* frameToPass = 0;
if (AggregateDeclaration *ad = sym->isAggregateDeclaration()) {
// If sym is a nested struct or a nested class, pass the frame
// of the function where sym is declared.
@@ -285,17 +286,8 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) {
return;
fd->ir.irFunc->nestedContextCreated = true;
// fill nestedVars
assert(fd->nestedVars.empty() && "nestedVars should only be filled here");
size_t nnest = fd->closureVars.dim;
for (size_t i = 0; i < nnest; ++i)
{
VarDeclaration* vd = static_cast<VarDeclaration*>(fd->closureVars.data[i]);
fd->nestedVars.insert(vd);
}
// construct nested variables array
if (!fd->nestedVars.empty())
if (fd->closureVars.dim != 0)
{
Logger::println("has nested frame");
// start with adding all enclosing parent frames until a static parent is reached
@@ -345,9 +337,9 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) {
// Add the direct nested variables of this function, and update their indices to match.
// TODO: optimize ordering for minimal space usage?
for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
{
VarDeclaration* vd = *i;
VarDeclarationIter closureVarsIter(fd->closureVars);
for (; closureVarsIter.more(); closureVarsIter.next()) {
VarDeclaration* vd = *closureVarsIter;
if (!vd->ir.irLocal)
vd->ir.irLocal = new IrLocal(vd);
@@ -404,7 +396,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
DtoCreateNestedContextType(fd);
// construct nested variables array
if (!fd->nestedVars.empty())
if (fd->closureVars.dim != 0)
{
IrFunction* irfunction = fd->ir.irFunc;
unsigned depth = irfunction->depth;
@@ -451,9 +443,9 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
irfunction->nestedVar = frame;
// go through all nested vars and assign addresses where possible.
for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
{
VarDeclaration* vd = *i;
VarDeclarationIter closureVarsIter(fd->closureVars);
for (; closureVarsIter.more(); closureVarsIter.next()) {
VarDeclaration* vd = *closureVarsIter;
LLValue* gep = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
if (vd->isParameter()) {

View File

@@ -168,6 +168,18 @@ static LLType* rt_dg2()
return LLStructType::get(gIR->context(), types, false);
}
template<typename DECL>
static void ensureDecl(DECL *decl, const char *msg)
{
if (!decl || !decl->type)
{
Logger::println("Missing class declaration: %s\n", msg);
error(Loc(), "Missing class declaration: %s", msg);
errorSupplemental(Loc(), "Please check that object.di is included and valid");
fatal();
}
}
static void LLVM_D_BuildRuntimeModule()
{
Logger::println("building runtime module");
@@ -187,10 +199,15 @@ static void LLVM_D_BuildRuntimeModule()
LLType* wstringTy = DtoType(Type::twchar->arrayOf());
LLType* dstringTy = DtoType(Type::tdchar->arrayOf());
ensureDecl(ClassDeclaration::object, "Object");
LLType* objectTy = DtoType(ClassDeclaration::object->type);
ensureDecl(Type::typeinfoclass, "TypeInfo_Class");
LLType* classInfoTy = DtoType(Type::typeinfoclass->type);
ensureDecl(Type::dtypeinfo, "DTypeInfo");
LLType* typeInfoTy = DtoType(Type::dtypeinfo->type);
ensureDecl(Type::typeinfoassociativearray, "TypeInfo_AssociativeArray");
LLType* aaTypeInfoTy = DtoType(Type::typeinfoassociativearray->type);
ensureDecl(Module::moduleinfo, "ModuleInfo");
LLType* moduleInfoPtrTy = getPtrToType(DtoType(Module::moduleinfo->type));
LLType* aaTy = rt_ptr(LLStructType::get(gIR->context()));

View File

@@ -520,6 +520,7 @@ DValue* AssignExp::toElem(IRState* p)
if (se->lwr == NULL && ta->ty == Tsarray &&
e2->op == TOKarrayliteral &&
op == TOKconstruct && // DMD Bugzilla 11238: avoid aliasing issue
t2->nextOf()->mutableOf()->implicitConvTo(ta->nextOf()))
{
ArrayLiteralExp * const ale = static_cast<ArrayLiteralExp *>(e2);
@@ -1140,13 +1141,9 @@ DValue* CastExp::toElem(IRState* p)
// get the value to cast
DValue* u = e1->toElem(p);
// a constructor expression is casted to void in order to mark
// the value as unused. See expression.d, method AssignExp::semantic(),
// around line 11681
if (to == Type::tvoid && e1->op == TOKconstruct)
{
return new DNullValue(Type::tvoid, 0);
}
// handle cast to void (usually created by frontend to avoid "has no effect" error)
if (to == Type::tvoid)
return new DImValue(Type::tvoid, llvm::UndefValue::get(voidToI8(DtoType(Type::tvoid))));
// cast it to the 'to' type, if necessary
DValue* v = u;
@@ -2294,7 +2291,7 @@ DValue* AssertExp::toElem(IRState* p)
// call assert runtime functions
p->scope() = IRScope(assertbb,endbb);
DtoAssert(p->func()->decl->getModule(), loc, msg ? msg->toElem(p) : NULL);
DtoAssert(p->func()->decl->getModule(), loc, msg ? msg->toElemDtor(p) : NULL);
// rewrite the scope
p->scope() = IRScope(endbb,oldend);
@@ -3184,9 +3181,7 @@ DValue* ClassReferenceExp::toElem(IRState* p)
toChars(), type->toChars());
LOG_SCOPE;
error("ClassReferenceExp::toElem is not yet implemented");
fatal();
return 0;
return new DImValue(type, toConstElem(p));
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -3261,21 +3256,23 @@ llvm::Constant* ClassReferenceExp::toConstElem(IRState *p)
llvm::Constant* result = value->globalVar;
assert(type->ty == Tclass);
ClassDeclaration* targetClass = static_cast<TypeClass*>(type)->sym;
if (InterfaceDeclaration* it = targetClass->isInterfaceDeclaration()) {
assert(it->isBaseOf(origClass, NULL));
if (type->ty == Tclass) {
ClassDeclaration* targetClass = static_cast<TypeClass*>(type)->sym;
if (InterfaceDeclaration* it = targetClass->isInterfaceDeclaration()) {
assert(it->isBaseOf(origClass, NULL));
IrTypeClass* typeclass = origClass->type->irtype->isClass();
IrTypeClass* typeclass = origClass->type->irtype->isClass();
// find interface impl
size_t i_index = typeclass->getInterfaceIndex(it);
assert(i_index != ~0UL);
// find interface impl
size_t i_index = typeclass->getInterfaceIndex(it);
assert(i_index != ~0UL);
// offset pointer
result = DtoGEPi(result, 0, i_index);
// offset pointer
result = DtoGEPi(result, 0, i_index);
}
}
assert(type->ty == Tclass || type->ty == Tenum);
return DtoBitCast(result, DtoType(type));
}

View File

@@ -109,6 +109,11 @@ Expression *Type::getInternalTypeInfo(Scope *sc)
return t->getTypeInfo(sc);
}
bool inNonRoot(Dsymbol *s);
FuncDeclaration *search_toHash(StructDeclaration *sd);
FuncDeclaration *search_toString(StructDeclaration *sd);
/****************************************************
* Get the exact TypeInfo.
*/
@@ -146,9 +151,23 @@ Expression *Type::getTypeInfo(Scope *sc)
if (!t->builtinTypeInfo())
{ // Generate COMDAT
if (sc) // if in semantic() pass
{ // Find module that will go all the way to an object file
{
// Find module that will go all the way to an object file
Module *m = sc->module->importedFrom;
m->members->push(t->vtinfo);
if (ty == Tstruct)
{
StructDeclaration *sd = ((TypeStruct *)this)->sym;
if ((sd->xeq && sd->xeq != sd->xerreq ||
sd->xcmp && sd->xcmp != sd->xerrcmp ||
search_toHash(sd) ||
search_toString(sd)
) && inNonRoot(sd))
{
Module::addDeferredSemantic3(sd);
}
}
}
else // if in obj generation pass
{
@@ -572,21 +591,6 @@ void TypeInfoDelegateDeclaration::llvmDefine()
/* ========================================================================= */
static FuncDeclaration* find_method_overload(AggregateDeclaration* ad, Identifier* id, TypeFunction* tf)
{
Dsymbol *s = search_function(ad, id);
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
if (fdx)
{
FuncDeclaration *fd = fdx->overloadExactMatch(tf);
if (fd)
{
return fd;
}
}
return NULL;
}
void TypeInfoStructDeclaration::llvmDefine()
{
Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", toChars());
@@ -597,6 +601,13 @@ void TypeInfoStructDeclaration::llvmDefine()
TypeStruct *tc = static_cast<TypeStruct *>(tinfo);
StructDeclaration *sd = tc->sym;
// handle opaque structs
if (!sd->members) {
RTTIBuilder b(Type::typeinfostruct);
b.finalize(ir.irGlobal);
return;
}
// can't emit typeinfo for forward declarations
if (sd->sizeok != SIZEOKdone)
{
@@ -622,41 +633,10 @@ void TypeInfoStructDeclaration::llvmDefine()
initPtr = iraggr->getInitSymbol();
b.push_void_array(getTypeStoreSize(DtoType(tc)), initPtr);
// toX functions ground work
static TypeFunction *tftohash;
static TypeFunction *tftostring;
if (!tftohash)
{
Scope sc;
tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
tftohash ->mod = MODconst;
tftohash = static_cast<TypeFunction *>(tftohash->semantic(Loc(), &sc));
Type *retType = Type::tchar->immutableOf()->arrayOf();
tftostring = new TypeFunction(NULL, retType, 0, LINKd);
tftostring = static_cast<TypeFunction *>(tftostring->semantic(Loc(), &sc));
}
// this one takes a parameter, so we need to build a new one each time
// to get the right type. can we avoid this?
TypeFunction *tfcmpptr;
{
Scope sc;
Parameters *arguments = new Parameters;
// arg type is ref const T
Parameter *arg = new Parameter(STCref, tc->constOf(), NULL, NULL);
arguments->push(arg);
tfcmpptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfcmpptr->mod = MODconst;
tfcmpptr = static_cast<TypeFunction *>(tfcmpptr->semantic(Loc(), &sc));
}
// well use this module for all overload lookups
// toHash
FuncDeclaration* fd = find_method_overload(sd, Id::tohash, tftohash);
FuncDeclaration* fd = search_toHash(sd);
b.push_funcptr(fd);
// opEquals
@@ -664,11 +644,11 @@ void TypeInfoStructDeclaration::llvmDefine()
b.push_funcptr(fd);
// opCmp
fd = find_method_overload(sd, Id::cmp, tfcmpptr);
fd = sd->xcmp;
b.push_funcptr(fd);
// toString
fd = find_method_overload(sd, Id::tostring, tftostring);
fd = search_toString(sd);
b.push_funcptr(fd);
// uint m_flags;

View File

@@ -89,6 +89,7 @@ if(APPLE)
endif()
file(GLOB_RECURSE CORE_D_UNIX ${RUNTIME_DIR}/src/core/sys/posix/*.d)
file(GLOB_RECURSE CORE_D_FREEBSD ${RUNTIME_DIR}/src/core/sys/freebsd/*.d)
file(GLOB_RECURSE CORE_D_LINUX ${RUNTIME_DIR}/src/core/sys/linux/*.d)
file(GLOB_RECURSE CORE_D_OSX ${RUNTIME_DIR}/src/core/sys/osx/*.d)
file(GLOB_RECURSE CORE_D_WIN ${RUNTIME_DIR}/src/core/sys/windows/*.d)
set(CORE_D_SYS)
@@ -98,7 +99,21 @@ if(UNIX)
if(${CMAKE_SYSTEM} MATCHES "FreeBSD")
list(APPEND CORE_D_SYS ${CORE_D_FREEBSD})
endif()
list(APPEND DCRT_ASM ${RUNTIME_DIR}/src/core/threadasm.S)
if(${CMAKE_SYSTEM} MATCHES "Linux")
list(APPEND CORE_D_SYS ${CORE_D_LINUX})
endif()
# Assembler support was rewritten in CMake 2.8.5.
# The assembler file must be passed to gcc but prior to this
# version it is passed to as. This results in a bunch of
# error message. This is only critical for non-x86 platforms.
# On x86/x86-64 the file can safely be ignored.
if("${CMAKE_VERSION}" MATCHES "^2\\.8\\.[01234]($|\\..*)")
message(WARNING "Excluding core/threadasm.S from build because of missing CMake support.")
message(WARNING "This file is required for certain non-x86 platforms.")
message(WARNING "Please consider updating CMake to at least 2.8.5.")
else()
list(APPEND DCRT_ASM ${RUNTIME_DIR}/src/core/threadasm.S)
endif()
if(APPLE)
list(APPEND CORE_D_SYS ${CORE_D_OSX})
endif()