mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-09 16:33:14 +01:00
Merge branch 'merge-2.064' into merge-2.065
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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()));
|
||||
|
||||
39
gen/toir.cpp
39
gen/toir.cpp
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user