From 360a99caa915bdb23e3ce970c1ac7d0d8feb8aaa Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 13:21:36 +0300 Subject: [PATCH 01/31] Resolving nested context for structs. * * * Another fix for nested structs * * * Yet another fix for nested structs --- gen/classes.cpp | 11 +---------- gen/llvmhelpers.cpp | 6 ++++++ gen/nested.cpp | 40 ++++++++++++++++++++++++++++++++++++---- gen/nested.h | 12 ++++++++++-- gen/toir.cpp | 4 ++++ gen/tollvm.cpp | 8 ++++---- gen/tollvm.h | 4 ++-- 7 files changed, 63 insertions(+), 22 deletions(-) diff --git a/gen/classes.cpp b/gen/classes.cpp index 7a0b5ab5..8077f723 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -170,16 +170,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp) // set the context for nested classes else if (tc->sym->isNested() && tc->sym->vthis) { - Logger::println("Resolving nested context"); - LOG_SCOPE; - - // get context - LLValue* nest = DtoNestedContext(loc, tc->sym); - - // store into right location - size_t idx = tc->sym->vthis->ir.irField->index; - LLValue* gep = DtoGEPi(mem,0,idx,"tmp"); - DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep); + DtoResolveNestedContext(loc, tc->sym, mem); } // call constructor diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 0ac4e9c1..1bc4a4c8 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -364,10 +364,16 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs) if (!t->equals(t2)) { // FIXME: use 'rhs' for something !?! DtoAggrZeroInit(lhs->getLVal()); +#if DMDV2 + TypeStruct *ts = (TypeStruct*) lhs->getType(); + if (ts->sym->isNested() && ts->sym->vthis) + DtoResolveNestedContext(loc, ts->sym, lhs->getLVal()); +#endif } else { DtoAggrCopy(lhs->getLVal(), rhs->getRVal()); } + } else if (t->ty == Tarray) { // lhs is slice diff --git a/gen/nested.cpp b/gen/nested.cpp index 9b493e3f..1bd252c1 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -213,6 +213,24 @@ void DtoNestedInit(VarDeclaration* vd) } } +#if DMDV2 +LLValue* DtoResolveNestedContext(Loc loc, AggregateDeclaration *decl, LLValue *value) +#else +LLValue* DtoResolveNestedContext(Loc loc, ClassDeclaration *decl, LLValue *value) +#endif +{ + Logger::println("Resolving nested context"); + LOG_SCOPE; + + // get context + LLValue* nest = DtoNestedContext(loc, decl); + + // store into right location + size_t idx = decl->vthis->ir.irField->index; + LLValue* gep = DtoGEPi(value,0,idx,"tmp"); + DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep); +} + LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) { Logger::println("DtoNestedContext for %s", sym->toPrettyChars()); @@ -234,11 +252,16 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) // or just have a this argument else if (irfunc->thisArg) { - ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); - if (!cd || !cd->vthis) - return llvm::UndefValue::get(getVoidPtrType()); +#if DMDV2 + AggregateDeclaration* ad = irfunc->decl->isMember2(); + val = ad->isClassDeclaration() ? DtoLoad(irfunc->thisArg) : irfunc->thisArg; +#else + ClassDeclaration* ad = irfunc->decl->isMember2()->isClassDeclaration(); val = DtoLoad(irfunc->thisArg); - val = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis")); +#endif + if (!ad || !ad->vthis) + return llvm::UndefValue::get(getVoidPtrType()); + val = DtoLoad(DtoGEPi(val, 0,ad->vthis->ir.irField->index, ".vthis")); } else { @@ -477,10 +500,19 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { assert(irfunction->thisArg); assert(fd->isMember2()); LLValue* thisval = DtoLoad(irfunction->thisArg); +#if DMDV2 + AggregateDeclaration* cd = fd->isMember2(); +#else ClassDeclaration* cd = fd->isMember2()->isClassDeclaration(); +#endif assert(cd); assert(cd->vthis); Logger::println("Indexing to 'this'"); +#if DMDV2 + if (cd->isStructDeclaration()) + src = DtoExtractValue(thisval, cd->vthis->ir.irField->index, ".vthis"); + else +#endif src = DtoLoad(DtoGEPi(thisval, 0, cd->vthis->ir.irField->index, ".vthis")); } if (depth > 1) { diff --git a/gen/nested.h b/gen/nested.h index 19d2b92d..088bafa4 100644 --- a/gen/nested.h +++ b/gen/nested.h @@ -4,6 +4,7 @@ #include "declaration.h" #include "mtype.h" #include "gen/dvalue.h" +#include "gen/llvm.h" /////////////////////////////////////////////////////////// // Nested variable and context helpers @@ -15,8 +16,15 @@ void DtoCreateNestedContext(FuncDeclaration* fd); /// Allocate space for variable accessed from nested function. void DtoNestedInit(VarDeclaration* vd); -/// Gets the context value for a call to a nested function or newing a nested -/// class with arbitrary nesting. +/// Resolves the nested context for classes and structs with arbitrary nesting. +#if DMDV2 +LLValue* DtoResolveNestedContext(Loc loc, AggregateDeclaration *decl, LLValue *value); +#else +LLValue* DtoResolveNestedContext(Loc loc, ClassDeclaration *decl, LLValue *value); +#endif + +/// Gets the context value for a call to a nested function or creating a nested +/// class or struct with arbitrary nesting. llvm::Value* DtoNestedContext(Loc loc, Dsymbol* sym); /// Gets the DValue of a nested variable with arbitrary nesting. diff --git a/gen/toir.cpp b/gen/toir.cpp index 519e2aab..a12021ff 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1694,6 +1694,10 @@ DValue* NewExp::toElem(IRState* p) ts->sym->codegen(Type::sir); DtoAggrCopy(mem, ts->sym->ir.irStruct->getInitSymbol()); } +#if DMDV2 + if (ts->sym->isNested() && ts->sym->vthis) + DtoResolveNestedContext(loc, ts->sym, mem); +#endif return new DImValue(type, mem); } // new basic type diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 4fe8cfd5..7a4b967c 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -657,14 +657,14 @@ LLConstant* DtoBitCast(LLConstant* v, const LLType* t) ////////////////////////////////////////////////////////////////////////////////////////// -LLValue* DtoInsertValue(LLValue* aggr, LLValue* v, unsigned idx) +LLValue* DtoInsertValue(LLValue* aggr, LLValue* v, unsigned idx, const char* name) { - return gIR->ir->CreateInsertValue(aggr, v, idx); + return gIR->ir->CreateInsertValue(aggr, v, idx, name); } -LLValue* DtoExtractValue(LLValue* aggr, unsigned idx) +LLValue* DtoExtractValue(LLValue* aggr, unsigned idx, const char* name) { - return gIR->ir->CreateExtractValue(aggr, idx); + return gIR->ir->CreateExtractValue(aggr, idx, name); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/tollvm.h b/gen/tollvm.h index 6a6fc538..575bb981 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -68,8 +68,8 @@ void DtoStore(LLValue* src, LLValue* dst); void DtoAlignedStore(LLValue* src, LLValue* dst); LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0); LLConstant* DtoBitCast(LLConstant* v, const LLType* t); -LLValue* DtoInsertValue(LLValue* aggr, LLValue* v, unsigned idx); -LLValue* DtoExtractValue(LLValue* aggr, unsigned idx); +LLValue* DtoInsertValue(LLValue* aggr, LLValue* v, unsigned idx, const char* name=0); +LLValue* DtoExtractValue(LLValue* aggr, unsigned idx, const char* name=0); // llvm::dyn_cast wrappers const LLPointerType* isaPointer(LLValue* v); From 2fe8635e5a22c03afaee10c012867c7eab401e41 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 13:22:10 +0300 Subject: [PATCH 02/31] Struct constructors are supported now --- gen/toir.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gen/toir.cpp b/gen/toir.cpp index a12021ff..c2a90d69 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1697,6 +1697,16 @@ DValue* NewExp::toElem(IRState* p) #if DMDV2 if (ts->sym->isNested() && ts->sym->vthis) DtoResolveNestedContext(loc, ts->sym, mem); + + // call constructor + if (member) + { + Logger::println("Calling constructor"); + assert(arguments != NULL); + member->codegen(Type::sir); + DFuncValue dfn(member, member->ir.irFunc->func, mem); + return DtoCallFunction(loc, ts, &dfn, arguments); + } #endif return new DImValue(type, mem); } From 3943b2866ba11a6324ddfcb7accf9b57c07eb05a Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 13:22:19 +0300 Subject: [PATCH 03/31] Fixed nested context for delegates initialized in structs and classes --- gen/toir.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index c2a90d69..aec18094 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2351,10 +2351,30 @@ DValue* FuncExp::toElem(IRState* p) LLValue* cval; IrFunction* irfn = p->func(); - if (irfn->nestedVar) + if (irfn->nestedVar +#if DMDV2 + // We cannot use a frame allocated in one function + // for a delegate created in another function + // (that happens with anonymous functions) + && fd->toParent2() == irfn->decl +#endif + ) cval = irfn->nestedVar; else if (irfn->nestArg) cval = irfn->nestArg; +#if DMDV2 + // TODO: should we enable that for D1 as well? + else if (irfn->thisArg) + { + AggregateDeclaration* ad = irfn->decl->isMember2(); + if (!ad || !ad->vthis) { + cval = getNullPtr(getVoidPtrType()); + } else { + cval = ad->isClassDeclaration() ? DtoLoad(irfn->thisArg) : irfn->thisArg; + cval = DtoLoad(DtoGEPi(cval, 0,ad->vthis->ir.irField->index, ".vthis")); + } + } +#endif else cval = getNullPtr(getVoidPtrType()); cval = DtoBitCast(cval, dgty->getContainedType(0)); From 24e218454648da6a6256a9e6759c04057f742e83 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 14:22:36 +0300 Subject: [PATCH 04/31] Removed hack from DtoAAIn --- gen/aa.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/gen/aa.cpp b/gen/aa.cpp index 7093f33e..0bcd06ed 100644 --- a/gen/aa.cpp +++ b/gen/aa.cpp @@ -129,12 +129,8 @@ DValue* DtoAAIn(Loc& loc, Type* type, DValue* aa, DValue* key) keyti = DtoBitCast(keyti, funcTy->getParamType(1)); // pkey param -#if DMDV1 LLValue* pkey = makeLValue(loc, key); - pkey = DtoBitCast(pkey, funcTy->getParamType(2)); -#else - LLValue* pkey = getNullValue(getVoidPtrType()); -#endif + pkey = DtoBitCast(pkey, getVoidPtrType()); // call runtime LLValue* ret = gIR->CreateCallOrInvoke3(func, aaval, keyti, pkey, "aa.in").getInstruction(); From 9103800334d255fc11c380417a690acf34206024 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 14:53:42 +0300 Subject: [PATCH 05/31] Fixed erroneous assert in _d_array_slice_copy --- druntime.patch | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/druntime.patch b/druntime.patch index ae7bc15f..2ecb3bda 100644 --- a/druntime.patch +++ b/druntime.patch @@ -1200,7 +1200,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/arrayInit.d druntime/src/rt/arrayInit.d --- druntime-orig/src/rt/arrayInit.d 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/src/rt/arrayInit.d 2010-10-30 19:18:05.322555000 +0400 ++++ druntime/src/rt/arrayInit.d 2010-11-02 14:39:21.353360001 +0300 @@ -0,0 +1,150 @@ +private import ldc.intrinsics; + @@ -1343,8 +1343,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +// slice copy when assertions are enabled +void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen) +{ -+ assert(dst); -+ assert(src); ++ if (dstlen != 0) assert(dst); ++ if (dstlen != 0) assert(src); + if (dstlen != srclen) + throw new Exception("lengths don't match for array copy"); + else if (dst+dstlen <= src || src+srclen <= dst) @@ -1786,7 +1786,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/lifetime.d druntime/src/rt/lifetime.d --- druntime-orig/src/rt/lifetime.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/lifetime.d 2010-10-29 10:40:39.533035001 +0400 ++++ druntime/src/rt/lifetime.d 2010-11-02 14:51:10.000000000 +0300 @@ -92,6 +92,18 @@ return gc_malloc(sz); } From 6b1243cec203637f675febaa3928936ba32188da Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 16:38:13 +0300 Subject: [PATCH 06/31] Fixed creating of arrays of immutable types --- gen/arrays.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 66499802..31c9b076 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -442,7 +442,7 @@ DSliceValue* DtoNewDynArray(Loc& loc, Type* arrayType, DValue* dim, bool default LOG_SCOPE; // typeinfo arg - LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType); + LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType->mutableOf()->merge2()); // dim arg assert(DtoType(dim->getType()) == DtoSize_t()); @@ -493,7 +493,7 @@ DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size LOG_SCOPE; // typeinfo arg - LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType); + LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType->mutableOf()->merge2()); // get value type Type* vtype = arrayType->toBasetype(); From 64652b62797cefc4d6f527ee7c45c8f099b6b35e Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 16:40:24 +0300 Subject: [PATCH 07/31] Fixed TypeInfo.next() for immutable types --- druntime.patch | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/druntime.patch b/druntime.patch index 2ecb3bda..c9ad7d28 100644 --- a/druntime.patch +++ b/druntime.patch @@ -907,8 +907,23 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/object_.d druntime/src/object_.d --- druntime-orig/src/object_.d 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/src/object_.d 2010-10-26 19:27:09.224925000 +0400 -@@ -1073,7 +1073,7 @@ ++++ druntime/src/object_.d 2010-11-02 16:35:18.353360002 +0300 +@@ -1040,7 +1040,13 @@ + override size_t tsize() { return base.tsize(); } + override void swap(void *p1, void *p2) { return base.swap(p1, p2); } + +- override TypeInfo next() { return base.next(); } ++ override TypeInfo next() ++ { ++ version(LDC) ++ return base; ++ else ++ return base.next(); ++ } + override uint flags() { return base.flags(); } + override void[] init() { return base.init(); } + +@@ -1073,7 +1079,7 @@ abstract class MemberInfo { @@ -917,7 +932,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } class MemberInfo_field : MemberInfo -@@ -1663,7 +1663,6 @@ +@@ -1663,7 +1669,6 @@ { int len = 0; ModuleReference *mr; @@ -925,7 +940,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. for (mr = _Dmodule_ref; mr; mr = mr.next) len++; _moduleinfo_array = new ModuleInfo*[len]; -@@ -2025,7 +2024,6 @@ +@@ -2025,7 +2030,6 @@ _d_monitor_create(h); m = getMonitor(h); } @@ -933,7 +948,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. IMonitor i = m.impl; if (i is null) -@@ -2124,7 +2122,7 @@ +@@ -2124,7 +2128,7 @@ size_t _aaLen(void* p); void* _aaGet(void** pp, TypeInfo keyti, size_t valuesize, ...); void* _aaGetRvalue(void* p, TypeInfo keyti, size_t valuesize, ...); @@ -942,7 +957,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. void _aaDel(void* p, TypeInfo keyti, ...); void[] _aaValues(void* p, size_t keysize, size_t valuesize); void[] _aaKeys(void* p, size_t keysize, size_t valuesize); -@@ -2169,7 +2167,7 @@ +@@ -2169,7 +2173,7 @@ return *cast(Key[]*) &a; } From 87485d66498c592b9eecfbf83a51949c08eed402 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 18:40:58 +0300 Subject: [PATCH 08/31] Fixed signature of _aaEqual for D2 --- gen/aa.cpp | 10 +++++++++- gen/runtime.cpp | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/gen/aa.cpp b/gen/aa.cpp index 0bcd06ed..384547df 100644 --- a/gen/aa.cpp +++ b/gen/aa.cpp @@ -190,7 +190,15 @@ LLValue* DtoAAEquals(Loc& loc, TOK op, DValue* l, DValue* r) { Type* t = l->getType()->toBasetype(); assert(t == r->getType()->toBasetype() && "aa equality is only defined for aas of same type"); +#if DMDV2 + llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaEqual"); + const llvm::FunctionType* funcTy = func->getFunctionType(); + LLValue* aaval = DtoBitCast(l->getRVal(), funcTy->getParamType(1)); + LLValue* abval = DtoBitCast(r->getRVal(), funcTy->getParamType(2)); + LLValue* aaTypeInfo = DtoTypeInfoOf(t); + LLValue* res = gIR->CreateCallOrInvoke3(func, aaTypeInfo, aaval, abval, "aaEqRes").getInstruction(); +#else llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaEq"); const llvm::FunctionType* funcTy = func->getFunctionType(); @@ -198,7 +206,7 @@ LLValue* DtoAAEquals(Loc& loc, TOK op, DValue* l, DValue* r) LLValue* abval = DtoBitCast(r->getRVal(), funcTy->getParamType(1)); LLValue* aaTypeInfo = DtoTypeInfoOf(t); LLValue* res = gIR->CreateCallOrInvoke3(func, aaval, abval, aaTypeInfo, "aaEqRes").getInstruction(); - +#endif res = gIR->ir->CreateICmpNE(res, DtoConstInt(0), "tmp"); if (op == TOKnotequal) res = gIR->ir->CreateNot(res, "tmp"); diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 30d90899..b9531cde 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -839,6 +839,19 @@ static void LLVM_D_BuildRuntimeModule() ->setAttributes(Attr_1_NoCapture); } +#if DMDV2 + // int _aaEqual(TypeInfo_AssociativeArray ti, AA e1, AA e2) + { + llvm::StringRef fname("_aaEqual"); + std::vector types; + types.push_back(typeInfoTy); + types.push_back(aaTy); + types.push_back(aaTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(intTy, types, false); + llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M) + ->setAttributes(Attr_1_2_NoCapture); + } +#else // int _aaEq(AA aa, AA ab, TypeInfo_AssociativeArray ti) { llvm::StringRef fname("_aaEq"); @@ -850,6 +863,7 @@ static void LLVM_D_BuildRuntimeModule() llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M) ->setAttributes(Attr_1_2_NoCapture); } +#endif ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// From 376c15542988de285e34a7a6b8f29b850298f9b6 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 18:44:38 +0300 Subject: [PATCH 09/31] Added missing files for building --- runtime/CMakeLists.txt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 1c342b00..7e73bada 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -113,8 +113,14 @@ elseif(D_VERSION EQUAL 2) if(WIN32) file(GLOB PHOBOS2_D_WIN ${PHOBOS2_DIR}/std/windows/*.d) endif(WIN32) - list(APPEND PHOBOS2_D ${PHOBOS2_D_MATH} ${PHOBOS2_D_WIN} - ${PHOBOS2_D_C} ${PHOBOS2_D_C_SYS}) + list(APPEND PHOBOS2_D + ${PHOBOS2_D_MATH} + ${PHOBOS2_D_WIN} + ${PHOBOS2_D_C} + ${PHOBOS2_D_C_SYS} + ${PHOBOS2_DIR}/etc/c/zlib.d + ${PHOBOS2_DIR}/crc32.d + ) endif(PHOBOS2_DIR) endif(D_VERSION EQUAL 1) @@ -166,7 +172,11 @@ macro(dc INPUT_D OUTLIST_O OUTLIST_BC INCDIR MOREFLAGS PATH) endif ("${PATH}" STREQUAL "") get_filename_component(name ${output} NAME_WE) get_filename_component(path ${output} PATH) - set(output ${path}/${name}) + if ("${path}" STREQUAL "") + set(output ${name}) + else ("${path}" STREQUAL "") + set(output ${path}/${name}) + endif ("${path}" STREQUAL "") set(OUTPUT_O ${PROJECT_BINARY_DIR}/${output}.o) set(OUTPUT_BC ${PROJECT_BINARY_DIR}/${output}.bc) list(APPEND ${OUTLIST_O} ${OUTPUT_O}) From fd73072371f789cd710f4619bdeef11302abcc10 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 20:10:52 +0300 Subject: [PATCH 10/31] Fixed undefined references to methods without body. --- druntime.patch | 11 +---------- ir/irclass.cpp | 2 +- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/druntime.patch b/druntime.patch index c9ad7d28..ef1e24a8 100644 --- a/druntime.patch +++ b/druntime.patch @@ -907,7 +907,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/object_.d druntime/src/object_.d --- druntime-orig/src/object_.d 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/src/object_.d 2010-11-02 16:35:18.353360002 +0300 ++++ druntime/src/object_.d 2010-11-02 19:34:56.773360001 +0300 @@ -1040,7 +1040,13 @@ override size_t tsize() { return base.tsize(); } override void swap(void *p1, void *p2) { return base.swap(p1, p2); } @@ -923,15 +923,6 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. override uint flags() { return base.flags(); } override void[] init() { return base.init(); } -@@ -1073,7 +1079,7 @@ - - abstract class MemberInfo - { -- string name(); -+ string name() { return ""; }; // LDC: FIXME: - } - - class MemberInfo_field : MemberInfo @@ -1663,7 +1669,6 @@ { int len = 0; diff --git a/ir/irclass.cpp b/ir/irclass.cpp index b92854c0..ea3ff981 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -159,7 +159,7 @@ LLConstant * IrStruct::getVtblInit() FuncDeclaration* fd = dsym->isFuncDeclaration(); assert(fd && "vtbl entry not a function"); - if (fd->isAbstract() && !fd->fbody) + if (cd->isAbstract() || (fd->isAbstract() && !fd->fbody)) { c = getNullValue(DtoType(fd->type->pointerTo())); } From 0cc3dc369a21a4a2c1f2365500c05fd23fcc267f Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 20:30:06 +0300 Subject: [PATCH 11/31] Fixed signature of _d_delarray() --- gen/llvmhelpers.cpp | 5 +++++ gen/runtime.cpp | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 1bc4a4c8..40eb39f3 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -86,10 +86,15 @@ void DtoDeleteArray(DValue* arr) { // get runtime function llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_delarray"); + // build args LLSmallVector arg; +#if DMDV2 + arg.push_back(DtoBitCast(arr->getLVal(), fn->getFunctionType()->getParamType(0))); +#else arg.push_back(DtoArrayLen(arr)); arg.push_back(DtoBitCast(DtoArrayPtr(arr), getVoidPtrType(), ".tmp")); +#endif // call gIR->CreateCallOrInvoke(fn, arg.begin(), arg.end()); } diff --git a/gen/runtime.cpp b/gen/runtime.cpp index b9531cde..30e3f350 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -431,12 +431,17 @@ static void LLVM_D_BuildRuntimeModule() ->setAttributes(Attr_NoAlias); } - // void _d_delarray(size_t plength, void* pdata) + // D1: void _d_delarray(size_t plength, void* pdata) + // D2: void _d_delarray(void[]* array) { llvm::StringRef fname("_d_delarray"); std::vector types; +#if DMDV2 + types.push_back(voidArrayPtrTy); +#else types.push_back(sizeTy); types.push_back(voidPtrTy); +#endif const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); } From e22821702228449895098c26e34061dffbdd1bc8 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 2 Nov 2010 21:37:38 +0300 Subject: [PATCH 12/31] Fixed crash in std.concurrency.spawn() --- phobos.patch | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/phobos.patch b/phobos.patch index a25ed120..ce96d881 100644 --- a/phobos.patch +++ b/phobos.patch @@ -1,3 +1,18 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/concurrency.d phobos/std/concurrency.d +--- phobos-orig/std/concurrency.d 2010-09-17 00:27:48.000000000 +0400 ++++ phobos/std/concurrency.d 2010-11-02 21:33:03.417359999 +0300 +@@ -342,9 +342,10 @@ + owner = ownerTid; + fn( args ); + } +- ++ + // TODO: MessageList and &exec should be shared. + auto t = new Thread( &exec ); t.start(); ++ version(LDC) Thread.sleep(5_000); + links[spawnTid] = linked; + return spawnTid; + } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/conv.d phobos/std/conv.d --- phobos-orig/std/conv.d 2010-09-17 00:27:48.000000000 +0400 +++ phobos/std/conv.d 2010-10-29 12:06:21.221035000 +0400 From d7047f639e4d7200835e666d5a0c779e3ff73651 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Wed, 3 Nov 2010 19:46:19 +0300 Subject: [PATCH 13/31] Rehash associative array right after its creating (DMD seems to be doing the same) --- gen/toir.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/gen/toir.cpp b/gen/toir.cpp index aec18094..9bf81e0a 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2695,6 +2695,25 @@ DValue* AssocArrayLiteralExp::toElem(IRState* p) DtoAssign(loc, mem, val); } +#if DMDV2 + // Rehash array + if (keys->dim) { + // first get the runtime function + llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_aaRehash"); + const llvm::FunctionType* funcTy = fn->getFunctionType(); + + // aa param + LLValue* aaval = DtoBitCast(tmp, funcTy->getParamType(0)); + + // keyti param + LLValue* keyti = DtoTypeInfoOf(((TypeAArray*)aatype)->index, false); + keyti = DtoBitCast(keyti, funcTy->getParamType(1)); + + // Call function + gIR->CreateCallOrInvoke2(fn, aaval, keyti, ".gc_mem").getInstruction(); + } +#endif + return aa; } From 20b2b4b7f5bd6ce289b58c7843788182488bc5ee Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Thu, 4 Nov 2010 12:50:19 +0300 Subject: [PATCH 14/31] Added missing calls of postBlit --- gen/statements.cpp | 17 +++++++++++++++++ gen/toir.cpp | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/gen/statements.cpp b/gen/statements.cpp index 80e32ce1..78e08c87 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -77,6 +77,23 @@ void ReturnStatement::toIR(IRState* p) // store return value DtoAssign(loc, rvar, e); +#if DMDV2 + // Call postBlit() + Type *tb = exp->type->toBasetype(); + if ((exp->op == TOKvar || exp->op == TOKdotvar || exp->op == TOKstar) && + tb->ty == Tstruct) + { StructDeclaration *sd = ((TypeStruct *)tb)->sym; + if (sd->postblit) + { + FuncDeclaration *fd = sd->postblit; + fd->codegen(Type::sir); + Expressions args; + DFuncValue dfn(fd, fd->ir.irFunc->func, e->getLVal()); + DtoCallFunction(loc, Type::basic[Tvoid], &dfn, &args); + } + } +#endif + // emit scopes DtoEnclosingHandlers(loc, NULL); diff --git a/gen/toir.cpp b/gen/toir.cpp index 9bf81e0a..3bea4b55 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2592,6 +2592,24 @@ DValue* StructLiteralExp::toElem(IRState* p) // store the initializer there DtoAssign(loc, &field, val); + +#if DMDV2 + Type *tb = vd->type->toBasetype(); + if (tb->ty == Tstruct) + { + // Call postBlit() + StructDeclaration *sd = ((TypeStruct *)tb)->sym; + if (sd->postblit) + { + FuncDeclaration *fd = sd->postblit; + fd->codegen(Type::sir); + Expressions args; + DFuncValue dfn(fd, fd->ir.irFunc->func, val->getLVal()); + DtoCallFunction(loc, Type::basic[Tvoid], &dfn, &args); + } + } +#endif + } // initialize trailing padding if (sd->structsize != offset) From fbb36404d9cd0cbf6c8631852d3814a102523007 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Thu, 4 Nov 2010 14:14:08 +0300 Subject: [PATCH 15/31] Removed unnecessary temporary variables from getSlice() and DtoCatArrays(). --- gen/arrays.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 31c9b076..00b396cd 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -422,10 +422,8 @@ static bool isInitialized(Type* et) { static DSliceValue *getSlice(Type *arrayType, LLValue *array) { // Get ptr and length of the array - LLValue* newArrayLVal = DtoRawAlloca(array->getType(), 0, "newArray"); - DtoStore(array, newArrayLVal); - LLValue* arrayLen = DtoLoad(DtoGEPi(newArrayLVal,0,0)); - LLValue* newptr = DtoLoad(DtoGEPi(newArrayLVal,0,1)); + LLValue* arrayLen = DtoExtractValue(array, 0, ".ptr"); + LLValue* newptr = DtoExtractValue(array, 1, ".len"); // cast pointer to wanted type const LLType* dstType = DtoType(arrayType)->getContainedType(1); @@ -684,13 +682,13 @@ DSliceValue* DtoCatArrays(Type* arrayType, Expression* exp1, Expression* exp2) // TypeInfo ti args.push_back(DtoTypeInfoOf(arrayType)); // byte[] x - LLValue *val = makeLValue(exp1->loc, exp1->toElem(gIR)); - val = DtoBitCast(val, getPtrToType(fn->getFunctionType()->getParamType(1))); - args.push_back(DtoLoad(val)); + LLValue *val = exp1->toElem(gIR)->getRVal(); + val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(1)); + args.push_back(val); // byte[] y - val = makeLValue(exp2->loc, exp2->toElem(gIR)); - val = DtoBitCast(val, getPtrToType(fn->getFunctionType()->getParamType(2))); - args.push_back(DtoLoad(val)); + val = exp2->toElem(gIR)->getRVal(); + val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(2)); + args.push_back(val); // Call _d_arraycatT LLValue* newArray = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".appendedArray").getInstruction(); From 88d7b955c87574ce72a26536d5b4e49d3187e44b Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Thu, 4 Nov 2010 17:58:27 +0300 Subject: [PATCH 16/31] Reverted rev.1710 and rev.1711 --- druntime.patch | 65 +++++++++++++++++++------------------------------- gen/arrays.cpp | 4 ++-- 2 files changed, 27 insertions(+), 42 deletions(-) diff --git a/druntime.patch b/druntime.patch index ef1e24a8..b2bea94d 100644 --- a/druntime.patch +++ b/druntime.patch @@ -1,6 +1,6 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/ldc/cstdarg.di druntime/import/ldc/cstdarg.di --- druntime-orig/import/ldc/cstdarg.di 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/import/ldc/cstdarg.di 2010-09-30 22:10:37.000000000 +0400 ++++ druntime/import/ldc/cstdarg.di 2010-11-04 17:49:07.000000000 +0300 @@ -0,0 +1,29 @@ +/* + * vararg support for extern(C) functions @@ -33,7 +33,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + void va_copy(va_list dst, va_list src); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/ldc/intrinsics.di druntime/import/ldc/intrinsics.di --- druntime-orig/import/ldc/intrinsics.di 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/import/ldc/intrinsics.di 2010-10-30 19:17:52.538555000 +0400 ++++ druntime/import/ldc/intrinsics.di 2010-11-04 17:49:07.000000000 +0300 @@ -0,0 +1,359 @@ +/* + * This module holds declarations to LLVM intrinsics. @@ -396,7 +396,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + void llvm_trap(); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/ldc/llvmasm.di druntime/import/ldc/llvmasm.di --- druntime-orig/import/ldc/llvmasm.di 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/import/ldc/llvmasm.di 2010-09-30 22:10:37.000000000 +0400 ++++ druntime/import/ldc/llvmasm.di 2010-11-04 17:49:07.000000000 +0300 @@ -0,0 +1,17 @@ +module ldc.llvmasm; + @@ -417,7 +417,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/ldc/vararg.d druntime/import/ldc/vararg.d --- druntime-orig/import/ldc/vararg.d 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/import/ldc/vararg.d 2010-09-30 22:10:37.000000000 +0400 ++++ druntime/import/ldc/vararg.d 2010-11-04 17:49:07.000000000 +0300 @@ -0,0 +1,43 @@ +/* + * This module holds the implementation of special vararg templates for D style var args. @@ -464,7 +464,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/object.di druntime/import/object.di --- druntime-orig/import/object.di 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/import/object.di 2010-10-27 00:22:27.444925001 +0400 ++++ druntime/import/object.di 2010-11-04 17:49:07.000000000 +0300 @@ -130,7 +130,7 @@ Interface[] interfaces; TypeInfo_Class base; @@ -502,7 +502,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. string msg; diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/core/atomic.d druntime/src/core/atomic.d --- druntime-orig/src/core/atomic.d 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/src/core/atomic.d 2010-10-05 15:55:10.893150001 +0400 ++++ druntime/src/core/atomic.d 2010-11-04 17:49:07.000000000 +0300 @@ -89,6 +89,117 @@ return false; } @@ -636,7 +636,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. T atomicOp(string op, T, V1)( ref shared T val, V1 mod ) diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/core/stdc/math.d druntime/src/core/stdc/math.d --- druntime-orig/src/core/stdc/math.d 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/src/core/stdc/math.d 2010-10-26 16:47:04.036925000 +0400 ++++ druntime/src/core/stdc/math.d 2010-11-04 17:49:07.000000000 +0300 @@ -17,6 +17,7 @@ extern (C): @@ -647,7 +647,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. alias double double_t; diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/core/stdc/stdlib.d druntime/src/core/stdc/stdlib.d --- druntime-orig/src/core/stdc/stdlib.d 2010-08-05 05:39:08.000000000 +0400 -+++ druntime/src/core/stdc/stdlib.d 2010-10-26 19:26:03.996925001 +0400 ++++ druntime/src/core/stdc/stdlib.d 2010-11-04 17:49:07.000000000 +0300 @@ -92,3 +92,13 @@ { void* alloca(size_t size); // non-standard @@ -664,7 +664,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/gc/gcbits.d druntime/src/gc/gcbits.d --- druntime-orig/src/gc/gcbits.d 2010-08-08 04:10:24.000000000 +0400 -+++ druntime/src/gc/gcbits.d 2010-10-01 20:49:51.268892001 +0400 ++++ druntime/src/gc/gcbits.d 2010-11-04 17:49:07.000000000 +0300 @@ -26,6 +26,10 @@ { version = bitops; @@ -678,7 +678,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. // use the unoptimized version diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/gc/gcx.d druntime/src/gc/gcx.d --- druntime-orig/src/gc/gcx.d 2010-08-27 01:23:26.000000000 +0400 -+++ druntime/src/gc/gcx.d 2010-10-07 22:27:41.879253001 +0400 ++++ druntime/src/gc/gcx.d 2010-11-04 17:49:07.000000000 +0300 @@ -1464,7 +1464,8 @@ @@ -907,23 +907,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/object_.d druntime/src/object_.d --- druntime-orig/src/object_.d 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/src/object_.d 2010-11-02 19:34:56.773360001 +0300 -@@ -1040,7 +1040,13 @@ - override size_t tsize() { return base.tsize(); } - override void swap(void *p1, void *p2) { return base.swap(p1, p2); } - -- override TypeInfo next() { return base.next(); } -+ override TypeInfo next() -+ { -+ version(LDC) -+ return base; -+ else -+ return base.next(); -+ } - override uint flags() { return base.flags(); } - override void[] init() { return base.init(); } - -@@ -1663,7 +1669,6 @@ ++++ druntime/src/object_.d 2010-11-04 17:52:43.515219002 +0300 +@@ -1663,7 +1663,6 @@ { int len = 0; ModuleReference *mr; @@ -931,7 +916,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. for (mr = _Dmodule_ref; mr; mr = mr.next) len++; _moduleinfo_array = new ModuleInfo*[len]; -@@ -2025,7 +2030,6 @@ +@@ -2025,7 +2024,6 @@ _d_monitor_create(h); m = getMonitor(h); } @@ -939,7 +924,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. IMonitor i = m.impl; if (i is null) -@@ -2124,7 +2128,7 @@ +@@ -2124,7 +2122,7 @@ size_t _aaLen(void* p); void* _aaGet(void** pp, TypeInfo keyti, size_t valuesize, ...); void* _aaGetRvalue(void* p, TypeInfo keyti, size_t valuesize, ...); @@ -948,7 +933,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. void _aaDel(void* p, TypeInfo keyti, ...); void[] _aaValues(void* p, size_t keysize, size_t valuesize); void[] _aaKeys(void* p, size_t keysize, size_t valuesize); -@@ -2169,7 +2173,7 @@ +@@ -2169,7 +2167,7 @@ return *cast(Key[]*) &a; } @@ -959,7 +944,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/aaA.d druntime/src/rt/aaA.d --- druntime-orig/src/rt/aaA.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/aaA.d 2010-10-29 10:48:36.165035001 +0400 ++++ druntime/src/rt/aaA.d 2010-11-04 17:49:07.000000000 +0300 @@ -204,7 +204,7 @@ * Add entry for key if it is not already there. */ @@ -1023,7 +1008,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. if (aa.a && aa.a.b.length) diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/adi.d druntime/src/rt/adi.d --- druntime-orig/src/rt/adi.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/adi.d 2010-10-29 11:49:52.065035002 +0400 ++++ druntime/src/rt/adi.d 2010-11-04 17:49:07.000000000 +0300 @@ -35,6 +35,8 @@ extern (C) void gc_free( void* p ); } @@ -1187,7 +1172,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. int c; diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/alloca.d druntime/src/rt/alloca.d --- druntime-orig/src/rt/alloca.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/alloca.d 2010-10-08 22:31:50.989547000 +0400 ++++ druntime/src/rt/alloca.d 2010-11-04 17:49:07.000000000 +0300 @@ -12,6 +12,9 @@ */ module rt.alloca; @@ -1206,7 +1191,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/arrayInit.d druntime/src/rt/arrayInit.d --- druntime-orig/src/rt/arrayInit.d 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/src/rt/arrayInit.d 2010-11-02 14:39:21.353360001 +0300 ++++ druntime/src/rt/arrayInit.d 2010-11-04 17:49:07.000000000 +0300 @@ -0,0 +1,150 @@ +private import ldc.intrinsics; + @@ -1360,7 +1345,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/ldc_eh.d druntime/src/rt/ldc_eh.d --- druntime-orig/src/rt/ldc_eh.d 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/src/rt/ldc_eh.d 2010-10-29 10:43:18.469035000 +0400 ++++ druntime/src/rt/ldc_eh.d 2010-11-04 17:49:07.000000000 +0300 @@ -0,0 +1,428 @@ +/** + * This module contains functions and structures required for @@ -1792,7 +1777,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/lifetime.d druntime/src/rt/lifetime.d --- druntime-orig/src/rt/lifetime.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/lifetime.d 2010-11-02 14:51:10.000000000 +0300 ++++ druntime/src/rt/lifetime.d 2010-11-04 17:49:07.000000000 +0300 @@ -92,6 +92,18 @@ return gc_malloc(sz); } @@ -1969,7 +1954,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/qsort.d druntime/src/rt/qsort.d --- druntime-orig/src/rt/qsort.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/qsort.d 2010-10-07 13:59:06.815253002 +0400 ++++ druntime/src/rt/qsort.d 2010-11-04 17:49:07.000000000 +0300 @@ -44,7 +44,7 @@ structures. The default value is optimized for a high cost for compares. */ @@ -1990,7 +1975,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/qsort2.d druntime/src/rt/qsort2.d --- druntime-orig/src/rt/qsort2.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/qsort2.d 2010-10-07 14:01:41.359253001 +0400 ++++ druntime/src/rt/qsort2.d 2010-11-04 17:49:07.000000000 +0300 @@ -31,14 +31,14 @@ return tiglobal.compare(p1, p2); } @@ -2010,7 +1995,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/trace.d druntime/src/rt/trace.d --- druntime-orig/src/rt/trace.d 2010-08-07 09:46:06.000000000 +0400 -+++ druntime/src/rt/trace.d 2010-10-01 21:01:58.444892002 +0400 ++++ druntime/src/rt/trace.d 2010-11-04 17:49:07.000000000 +0300 @@ -855,7 +855,7 @@ version (OSX) { // 16 byte align stack @@ -2031,7 +2016,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. trace_epi(); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/std/intrinsic.d druntime/src/std/intrinsic.d --- druntime-orig/src/std/intrinsic.d 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/src/std/intrinsic.d 2010-10-26 20:18:29.668925001 +0400 ++++ druntime/src/std/intrinsic.d 2010-11-04 17:49:07.000000000 +0300 @@ -0,0 +1,212 @@ +/* + * D phobos intrinsics for LDC diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 00b396cd..27043048 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -440,7 +440,7 @@ DSliceValue* DtoNewDynArray(Loc& loc, Type* arrayType, DValue* dim, bool default LOG_SCOPE; // typeinfo arg - LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType->mutableOf()->merge2()); + LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType); // dim arg assert(DtoType(dim->getType()) == DtoSize_t()); @@ -491,7 +491,7 @@ DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size LOG_SCOPE; // typeinfo arg - LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType->mutableOf()->merge2()); + LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType); // get value type Type* vtype = arrayType->toBasetype(); From 45606689c5cf7b3c1bf7d300ea3aa3948f475778 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Thu, 4 Nov 2010 18:22:18 +0300 Subject: [PATCH 17/31] Fixed crash in std.format.doFormat --- phobos.patch | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/phobos.patch b/phobos.patch index ce96d881..d23611ca 100644 --- a/phobos.patch +++ b/phobos.patch @@ -15,7 +15,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/conv.d phobos/std/conv.d --- phobos-orig/std/conv.d 2010-09-17 00:27:48.000000000 +0400 -+++ phobos/std/conv.d 2010-10-29 12:06:21.221035000 +0400 ++++ phobos/std/conv.d 2010-11-04 13:24:59.758325002 +0300 @@ -1395,7 +1395,7 @@ else // not hex { @@ -37,6 +37,63 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. char[20] buffer; int len = sprintf(buffer.ptr, "%g", d); return to!T(buffer[0 .. len].dup); +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/format.d phobos/std/format.d +--- phobos-orig/std/format.d 2010-09-17 00:27:48.000000000 +0400 ++++ phobos/std/format.d 2010-11-04 18:17:53.483219002 +0300 +@@ -2531,20 +2531,42 @@ + FLprecision = 0x80, + } + +- static TypeInfo skipCI(TypeInfo valti) ++ version(LDC) + { +- for (;;) ++ static TypeInfo skipCI(TypeInfo valti) + { +- if (valti.classinfo.name.length == 18 && +- valti.classinfo.name[9..18] == "Invariant") +- valti = (cast(TypeInfo_Invariant)valti).next; +- else if (valti.classinfo.name.length == 14 && +- valti.classinfo.name[9..14] == "Const") +- valti = (cast(TypeInfo_Const)valti).next; +- else +- break; ++ for (;;) ++ { ++ if (valti.classinfo.name.length == 18 && ++ valti.classinfo.name[9..18] == "Invariant") ++ valti = (cast(TypeInfo_Invariant)valti).base; ++ else if (valti.classinfo.name.length == 14 && ++ valti.classinfo.name[9..14] == "Const") ++ valti = (cast(TypeInfo_Const)valti).base; ++ else ++ break; ++ } ++ return valti; ++ } ++ ++ } ++ else ++ { ++ static TypeInfo skipCI(TypeInfo valti) ++ { ++ for (;;) ++ { ++ if (valti.classinfo.name.length == 18 && ++ valti.classinfo.name[9..18] == "Invariant") ++ valti = (cast(TypeInfo_Invariant)valti).next; ++ else if (valti.classinfo.name.length == 14 && ++ valti.classinfo.name[9..14] == "Const") ++ valti = (cast(TypeInfo_Const)valti).next; ++ else ++ break; ++ } ++ return valti; + } +- return valti; + } + + void formatArg(char fc) diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/functional.d phobos/std/functional.d --- phobos-orig/std/functional.d 2010-09-17 00:27:48.000000000 +0400 +++ phobos/std/functional.d 2010-10-29 12:01:35.285035001 +0400 From 59d1ec5e0b19b4e3916e1bc49a21ef766040922f Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Fri, 5 Nov 2010 11:55:23 +0300 Subject: [PATCH 18/31] Another fix for nested context in structs. --- gen/nested.cpp | 4 ++-- gen/nested.h | 2 +- gen/toir.cpp | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/gen/nested.cpp b/gen/nested.cpp index 1bd252c1..27a9d47d 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -68,7 +68,7 @@ static FuncDeclaration* getParentFunc(Dsymbol* sym, bool stopOnStatic) { return (parent ? parent->isFuncDeclaration() : NULL); } -DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd) +DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) { Logger::println("DtoNestedVariable for %s @ %s", vd->toChars(), loc.toChars()); LOG_SCOPE; @@ -150,7 +150,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd) val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars()); Logger::cout() << "Addr: " << *val << '\n'; Logger::cout() << "of type: " << *val->getType() << '\n'; - if (vd->ir.irLocal->byref) { + if (vd->ir.irLocal->byref || byref) { val = DtoAlignedLoad(val); Logger::cout() << "Was byref, now: " << *val << '\n'; Logger::cout() << "of type: " << *val->getType() << '\n'; diff --git a/gen/nested.h b/gen/nested.h index 088bafa4..ea3c6746 100644 --- a/gen/nested.h +++ b/gen/nested.h @@ -28,6 +28,6 @@ LLValue* DtoResolveNestedContext(Loc loc, ClassDeclaration *decl, LLValue *value llvm::Value* DtoNestedContext(Loc loc, Dsymbol* sym); /// Gets the DValue of a nested variable with arbitrary nesting. -DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd); +DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref = false); #endif diff --git a/gen/toir.cpp b/gen/toir.cpp index 3bea4b55..78d4bbf4 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1202,7 +1202,11 @@ DValue* ThisExp::toElem(IRState* p) LLValue* v; if (vd->toParent2() != p->func()->decl) { Logger::println("nested this exp"); +#if STRUCTTHISREF + return DtoNestedVariable(loc, type, vd, type->ty == Tstruct); +#else return DtoNestedVariable(loc, type, vd); +#endif } else { Logger::println("normal this exp"); From 171ef1695cdcfaeff632b71457dc1e5dddf77a80 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Fri, 5 Nov 2010 14:05:27 +0300 Subject: [PATCH 19/31] Fixed crash in std.outbuffer.OutBuffer.printf(). --- phobos.patch | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/phobos.patch b/phobos.patch index d23611ca..ff784f16 100644 --- a/phobos.patch +++ b/phobos.patch @@ -313,3 +313,24 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { result = dg(field); +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/outbuffer.d phobos/std/outbuffer.d +--- phobos-orig/std/outbuffer.d 2010-09-17 00:27:48.000000000 +0400 ++++ phobos/std/outbuffer.d 2010-11-05 13:59:42.227267001 +0300 +@@ -308,8 +308,15 @@ + void printf(string format, ...) + { + va_list ap; +- ap = cast(va_list)&format; +- ap += format.sizeof; ++ version(LDC) ++ { ++ ap = _argptr; ++ } ++ else ++ { ++ ap = cast(va_list)&format; ++ ap += format.sizeof; ++ } + vprintf(format, ap); + } + From 14c6dfb89564dec95cdcd230279a58ad2f032eb8 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Fri, 5 Nov 2010 17:40:29 +0300 Subject: [PATCH 20/31] Added pointers to shared constructors and destructors to ModuleInfo. --- gen/functions.cpp | 12 ++++ gen/irstate.h | 4 ++ gen/toobj.cpp | 142 ++++++++++++++++++----------------------- runtime/CMakeLists.txt | 2 +- 4 files changed, 78 insertions(+), 82 deletions(-) diff --git a/gen/functions.cpp b/gen/functions.cpp index d1671f8c..3b149881 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -513,6 +513,18 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) gIR->dtors.push_back(fdecl); } } + // shared static ctor + else if (fdecl->isSharedStaticCtorDeclaration()) { + if (mustDefineSymbol(fdecl)) { + gIR->sharedCtors.push_back(fdecl); + } + } + // static dtor + else if (fdecl->isSharedStaticDtorDeclaration()) { + if (mustDefineSymbol(fdecl)) { + gIR->sharedDtors.push_back(fdecl); + } + } // we never reference parameters of function prototypes std::string str; diff --git a/gen/irstate.h b/gen/irstate.h index 1ab5a30c..2b2d91b9 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -163,6 +163,10 @@ struct IRState typedef std::vector FuncDeclVector; FuncDeclVector ctors; FuncDeclVector dtors; +#if DMDV2 + FuncDeclVector sharedCtors; + FuncDeclVector sharedDtors; +#endif FuncDeclVector unitTests; // all template instances that had members emitted diff --git a/gen/toobj.cpp b/gen/toobj.cpp index 850fd3e8..b82845a6 100644 --- a/gen/toobj.cpp +++ b/gen/toobj.cpp @@ -387,25 +387,14 @@ void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath) /* ================================================================== */ -// the following code generates functions and needs to output -// debug info. these macros are useful for that -#define DBG_TYPE ( getPtrToType(llvm::StructType::get(gIR->context(),NULL,NULL)) ) -#define DBG_CAST(X) ( llvm::ConstantExpr::getBitCast(X, DBG_TYPE) ) - -// build module ctor - -llvm::Function* build_module_ctor() +static llvm::Function* build_module_function(const std::string &name, const std::vector &funcs) { - if (gIR->ctors.empty()) + if (funcs.empty()) return NULL; - size_t n = gIR->ctors.size(); + size_t n = funcs.size(); if (n == 1) - return gIR->ctors[0]->ir.irFunc->func; - - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("6__ctorZ"); + return funcs[0]->ir.irFunc->func; std::vector argsTy; const llvm::FunctionType* fnTy = llvm::FunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false); @@ -423,7 +412,7 @@ llvm::Function* build_module_ctor() #endif for (size_t i=0; ictors[i]->ir.irFunc->func; + llvm::Function* f = funcs[i]->ir.irFunc->func; llvm::CallInst* call = builder.CreateCall(f,""); call->setCallingConv(DtoCallingConv(0, LINKd)); } @@ -432,87 +421,60 @@ llvm::Function* build_module_ctor() return fn; } +// build module ctor + +llvm::Function* build_module_ctor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("6__ctorZ"); + return build_module_function(name, gIR->ctors); +} + // build module dtor static llvm::Function* build_module_dtor() { - if (gIR->dtors.empty()) - return NULL; - - size_t n = gIR->dtors.size(); - if (n == 1) - return gIR->dtors[0]->ir.irFunc->func; - std::string name("_D"); name.append(gIR->dmodule->mangle()); name.append("6__dtorZ"); - - std::vector argsTy; - const llvm::FunctionType* fnTy = llvm::FunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false); - assert(gIR->module->getFunction(name) == NULL); - llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module); - fn->setCallingConv(DtoCallingConv(0, LINKd)); - - llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); - IRBuilder<> builder(bb); - - #ifndef DISABLE_DEBUG_INFO - // debug info - if(global.params.symdebug) - DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); - #endif - - for (size_t i=0; idtors[i]->ir.irFunc->func; - llvm::CallInst* call = builder.CreateCall(f,""); - call->setCallingConv(DtoCallingConv(0, LINKd)); - } - - builder.CreateRetVoid(); - return fn; + return build_module_function(name, gIR->dtors); } // build module unittest static llvm::Function* build_module_unittest() { - if (gIR->unitTests.empty()) - return NULL; - - size_t n = gIR->unitTests.size(); - if (n == 1) - return gIR->unitTests[0]->ir.irFunc->func; - std::string name("_D"); name.append(gIR->dmodule->mangle()); name.append("10__unittestZ"); - - std::vector argsTy; - const llvm::FunctionType* fnTy = llvm::FunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false); - assert(gIR->module->getFunction(name) == NULL); - llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module); - fn->setCallingConv(DtoCallingConv(0, LINKd)); - - llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); - IRBuilder<> builder(bb); - - #ifndef DISABLE_DEBUG_INFO - // debug info - llvm::DISubprogram subprog; - if(global.params.symdebug) - subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); - #endif - - for (size_t i=0; iunitTests[i]->ir.irFunc->func; - llvm::CallInst* call = builder.CreateCall(f,""); - call->setCallingConv(DtoCallingConv(0, LINKd)); - } - - builder.CreateRetVoid(); - return fn; + return build_module_function(name, gIR->unitTests); } +#if DMDV2 + +// build module shared ctor + +llvm::Function* build_module_shared_ctor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("13__shared_ctorZ"); + return build_module_function(name, gIR->sharedCtors); +} + +// build module shared dtor + +static llvm::Function* build_module_shared_dtor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("13__shared_dtorZ"); + return build_module_function(name, gIR->sharedDtors); +} + +#endif + // build ModuleReference and register function, to register the module info in the global linked list static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) { @@ -722,12 +684,20 @@ void Module::genmoduleinfo() const LLType* fnptrTy = getPtrToType(LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false)); // ctor +#if DMDV2 + llvm::Function* fctor = build_module_shared_ctor(); +#else llvm::Function* fctor = build_module_ctor(); +#endif c = fctor ? fctor : getNullValue(fnptrTy); b.push(c); // dtor +#if DMDV2 + llvm::Function* fdtor = build_module_shared_dtor(); +#else llvm::Function* fdtor = build_module_dtor(); +#endif c = fdtor ? fdtor : getNullValue(fnptrTy); b.push(c); @@ -746,8 +716,18 @@ void Module::genmoduleinfo() #if DMDV2 - // void*[4] reserved :/ - const LLType* AT = llvm::ArrayType::get(getVoidPtrType(), 4); + // tls ctor + fctor = build_module_ctor(); + c = fctor ? fctor : getNullValue(fnptrTy); + b.push(c); + + // tls dtor + fdtor = build_module_dtor(); + c = fdtor ? fdtor : getNullValue(fnptrTy); + b.push(c); + + // index + reserved void*[1] + const LLType* AT = llvm::ArrayType::get(getVoidPtrType(), 2); c = getNullValue(AT); b.push(c); diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 7e73bada..b9da4ca4 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -187,7 +187,7 @@ macro(dc INPUT_D OUTLIST_O OUTLIST_BC INCDIR MOREFLAGS PATH) OUTPUT ${OUTPUT_O} ${OUTPUT_BC} - COMMAND ${LDC_LOC} --output-o --output-bc -c -I${INCDIR} -I${RUNTIME_GC_DIR} ${INPUT_D} -of${OUTPUT_O} ${D_FLAGS} ${MOREFLAGS} + COMMAND ${LDC_LOC} --output-o --output-bc -c -I${INCDIR} -I${RUNTIME_GC_DIR} ${INPUT_D} -of${OUTPUT_O} ${D_FLAGS} ${MOREFLAGS} --unittest DEPENDS ${LDC_LOC} ${INPUT_D} ${LDC_IMPORTS} From 410cb0dc4ec930229e2884564c2c9e0f6406c0b6 Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Fri, 5 Nov 2010 22:40:36 +0000 Subject: [PATCH 21/31] fix building of ldc1 --- gen/functions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gen/functions.cpp b/gen/functions.cpp index 3b149881..a6c84a29 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -513,6 +513,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) gIR->dtors.push_back(fdecl); } } +#if DMDV2 // shared static ctor else if (fdecl->isSharedStaticCtorDeclaration()) { if (mustDefineSymbol(fdecl)) { @@ -525,7 +526,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) gIR->sharedDtors.push_back(fdecl); } } - +#endif // we never reference parameters of function prototypes std::string str; if (!declareOnly) From 81a3a9eb8a66db8e88a378f84e47f2f83d4cf94a Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Fri, 5 Nov 2010 22:41:25 +0000 Subject: [PATCH 22/31] temporary fix for building 32bit druntime on 64bit hosts --- runtime/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index b9da4ca4..9a0ff420 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -254,10 +254,12 @@ if(BUILD_BC_LIBS) endif(BUILD_BC_LIBS) set_target_properties( - ${LIBS} PROPERTIES - LINKER_LANGUAGE C - ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib - LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib + ${LIBS} PROPERTIES + LINKER_LANGUAGE C + ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib + LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib + COMPILE_FLAGS "-m32" + LINK_FLAGS "-m32" ) # BCLIBS is empty if BUILD_BC_LIBS is not selected From 8e0986a682e91a3299ff0bb6b764a8e5dc7d3350 Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Fri, 5 Nov 2010 23:03:58 +0000 Subject: [PATCH 23/31] fix for building 32 bit phobos on a 64 bit host --- runtime/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 9a0ff420..8f0057e8 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -272,4 +272,12 @@ if(PHOBOS2_DIR) add_library(phobos2 ${ZLIB_C} ${PHOBOS2_O}) add_dependencies(phobos2 runtime) + set_target_properties( + phobos2 PROPERTIES + LINKER_LANGUAGE C + ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib + LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib + COMPILE_FLAGS "-m32" + LINK_FLAGS "-m32" + ) endif(PHOBOS2_DIR) From e11d071cdf9b467222e540e8db57be67f090a5ca Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Sat, 6 Nov 2010 19:41:17 +0300 Subject: [PATCH 24/31] Ported rt/memory.d from tango. --- druntime.patch | 642 ++++++++++++++++++++++++++++++++++++++++- runtime/CMakeLists.txt | 2 +- 2 files changed, 637 insertions(+), 7 deletions(-) diff --git a/druntime.patch b/druntime.patch index b2bea94d..9e64e253 100644 --- a/druntime.patch +++ b/druntime.patch @@ -1,6 +1,6 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/ldc/cstdarg.di druntime/import/ldc/cstdarg.di --- druntime-orig/import/ldc/cstdarg.di 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/import/ldc/cstdarg.di 2010-11-04 17:49:07.000000000 +0300 ++++ druntime/import/ldc/cstdarg.di 2010-11-05 13:57:24.315267000 +0300 @@ -0,0 +1,29 @@ +/* + * vararg support for extern(C) functions @@ -417,7 +417,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/ldc/vararg.d druntime/import/ldc/vararg.d --- druntime-orig/import/ldc/vararg.d 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/import/ldc/vararg.d 2010-11-04 17:49:07.000000000 +0300 ++++ druntime/import/ldc/vararg.d 2010-11-05 13:57:12.991267001 +0300 @@ -0,0 +1,43 @@ +/* + * This module holds the implementation of special vararg templates for D style var args. @@ -678,7 +678,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. // use the unoptimized version diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/gc/gcx.d druntime/src/gc/gcx.d --- druntime-orig/src/gc/gcx.d 2010-08-27 01:23:26.000000000 +0400 -+++ druntime/src/gc/gcx.d 2010-11-04 17:49:07.000000000 +0300 ++++ druntime/src/gc/gcx.d 2010-11-06 18:16:41.638720001 +0300 @@ -1464,7 +1464,8 @@ @@ -907,7 +907,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/object_.d druntime/src/object_.d --- druntime-orig/src/object_.d 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/src/object_.d 2010-11-04 17:52:43.515219002 +0300 ++++ druntime/src/object_.d 2010-11-06 19:28:37.000000000 +0300 @@ -1663,7 +1663,6 @@ { int len = 0; @@ -944,7 +944,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/aaA.d druntime/src/rt/aaA.d --- druntime-orig/src/rt/aaA.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/aaA.d 2010-11-04 17:49:07.000000000 +0300 ++++ druntime/src/rt/aaA.d 2010-11-05 11:43:19.831267002 +0300 @@ -204,7 +204,7 @@ * Add entry for key if it is not already there. */ @@ -1777,7 +1777,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/lifetime.d druntime/src/rt/lifetime.d --- druntime-orig/src/rt/lifetime.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/lifetime.d 2010-11-04 17:49:07.000000000 +0300 ++++ druntime/src/rt/lifetime.d 2010-11-05 11:43:02.207267001 +0300 @@ -92,6 +92,18 @@ return gc_malloc(sz); } @@ -1952,6 +1952,636 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/memory.d druntime/src/rt/memory.d +--- druntime-orig/src/rt/memory.d 2010-08-05 09:55:22.000000000 +0400 ++++ druntime/src/rt/memory.d 2010-11-06 19:35:02.518720000 +0300 +@@ -12,6 +12,8 @@ + */ + module rt.memory; + ++version(DMD) ++{ + + private + { +@@ -213,3 +215,616 @@ + static assert( false, "Operating system not supported." ); + } + } ++ ++} ++else version(LDC) ++{ ++ ++version = GC_Use_Dynamic_Ranges; ++ ++version(darwin) ++{ ++ version = GC_Use_Data_Dyld; ++ version = GC_Use_Dynamic_Ranges; ++ import core.stdc.config : c_ulong; ++} ++else version(Posix) ++{ ++ version = GC_Use_Data_Proc_Maps; ++} ++else version(solaris) ++{ ++ version = GC_Use_Data_Proc_Maps; ++} ++else version(freebsd) ++{ ++ version = GC_Use_Data_Proc_Maps; ++} ++ ++ ++version(GC_Use_Data_Proc_Maps) ++{ ++ version(Posix) {} else { ++ static assert(false, "Proc Maps only supported on Posix systems"); ++ } ++ import core.stdc.string : memmove; ++ import core.sys.posix.fcntl : open, O_RDONLY; ++ import core.sys.posix.unistd : close, read; ++ ++ version = GC_Use_Dynamic_Ranges; ++} ++ ++private ++{ ++ version( linux ) ++ { ++ //version = SimpleLibcStackEnd; ++ ++ version( SimpleLibcStackEnd ) ++ { ++ extern (C) extern void* __libc_stack_end; ++ } ++ else ++ { ++ import core.sys.posix.dlfcn; ++ } ++ } ++ else version(freebsd) ++ { ++ //version = SimpleLibcStackEnd; ++ ++ version( SimpleLibcStackEnd ) ++ { ++ extern (C) extern void* __libc_stack_end; ++ } ++ else ++ { ++ import core.sys.posix.dlfcn; ++ } ++ } ++ pragma(intrinsic, "llvm.frameaddress") ++ { ++ void* llvm_frameaddress(uint level=0); ++ } ++ extern (C) void gc_addRange( void* p, size_t sz ); ++ extern (C) void gc_removeRange( void* p ); ++} ++ ++ ++/** ++ * ++ */ ++ ++version( solaris ) { ++ version(X86_64) { ++ extern (C) void* _userlimit; ++ } ++} ++ ++extern (C) void* rt_stackBottom() ++{ ++ version( Win32 ) ++ { ++ void* bottom; ++ asm ++ { ++ mov EAX, FS:4; ++ mov bottom, EAX; ++ } ++ return bottom; ++ } ++ else version( linux ) ++ { ++ version( SimpleLibcStackEnd ) ++ { ++ return __libc_stack_end; ++ } ++ else ++ { ++ // See discussion: http://autopackage.org/forums/viewtopic.php?t=22 ++ static void** libc_stack_end; ++ ++ if( libc_stack_end == libc_stack_end.init ) ++ { ++ void* handle = dlopen( null, RTLD_NOW ); ++ libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" ); ++ dlclose( handle ); ++ } ++ return *libc_stack_end; ++ } ++ } ++ else version( freebsd ) ++ { ++ version( SimpleLibcStackEnd ) ++ { ++ return __libc_stack_end; ++ } ++ else ++ { ++ // See discussion: http://autopackage.org/forums/viewtopic.php?t=22 ++ static void** libc_stack_end; ++ ++ if( libc_stack_end == libc_stack_end.init ) ++ { ++ void* handle = dlopen( null, RTLD_NOW ); ++ libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" ); ++ dlclose( handle ); ++ } ++ return *libc_stack_end; ++ } ++ } ++ else version( darwin ) ++ { ++ // darwin has a fixed stack bottom ++ version( D_LP64 ) ++ return cast(void*) 0x7fff5fc00000; ++ else ++ return cast(void*) 0xc0000000; ++ } ++ else version( solaris ) ++ { ++ version(X86_64) { ++ return _userlimit; ++ } ++ else { ++ // ++ return cast(void*) 0x8048000; ++ } ++ } ++ else ++ { ++ static assert( false, "Operating system not supported." ); ++ } ++} ++ ++ ++/** ++ * ++ */ ++extern (C) void* rt_stackTop() ++{ ++ version( D_InlineAsm_X86 ) ++ { ++ asm ++ { ++ naked; ++ mov EAX, ESP; ++ ret; ++ } ++ } ++ else ++ { ++ return llvm_frameaddress(); ++ } ++} ++ ++ ++private ++{ ++ version( Win32 ) ++ { ++ extern (C) ++ { ++ extern __gshared int _data_start__; ++ extern __gshared int _bss_end__; ++ } ++ ++ alias _data_start__ Data_Start; ++ alias _bss_end__ Data_End; ++ } ++ else version( linux ) ++ { ++ extern (C) ++ { ++ extern __gshared int _data; ++ extern __gshared int __data_start; ++ extern __gshared int _end; ++ extern __gshared int _data_start__; ++ extern __gshared int _data_end__; ++ extern __gshared int _bss_start__; ++ extern __gshared int _bss_end__; ++ extern __gshared int __fini_array_end; ++ } ++ ++ alias __data_start Data_Start; ++ alias _end Data_End; ++ } ++ else version( freebsd ) ++ { ++ extern (C) ++ { ++ extern __gshared char etext; ++ extern __gshared int _end; ++ } ++ ++ alias etext Data_Start; ++ alias _end Data_End; ++ } ++ else version( solaris ) ++ { ++ extern(C) ++ { ++ extern __gshared int _environ; ++ extern __gshared int _end; ++ } ++ ++ alias _environ Data_Start; ++ alias _end Data_End; ++ } ++ ++ version( GC_Use_Dynamic_Ranges ) ++ { ++ private import core.stdc.stdlib; ++ } ++ ++ void* dataStart, dataEnd; ++} ++ ++ ++void initStaticDataGC() ++{ ++ ++ static const int S = (void*).sizeof; ++ ++ // Can't assume the input addresses are word-aligned ++ static void* adjust_up( void* p ) ++ { ++ return p + ((S - (cast(size_t)p & (S-1))) & (S-1)); // cast ok even if 64-bit ++ } ++ ++ static void * adjust_down( void* p ) ++ { ++ return p - (cast(size_t) p & (S-1)); ++ } ++ ++ version( Win32 ) ++ { ++ dataStart = adjust_up( &Data_Start ); ++ dataEnd = adjust_down( &Data_End ); ++ } ++ else version(linux) ++ { ++ dataStart = adjust_up( &Data_Start ); ++ dataEnd = adjust_down( &Data_End ); ++ } ++ else version( freebsd ) ++ { ++ dataStart = adjust_up( &Data_Start ); ++ dataEnd = adjust_down( &Data_End ); ++ } ++ else version(solaris) ++ { ++ dataStart = adjust_up( &Data_Start ); ++ dataEnd = adjust_down( &Data_End ); ++ } ++ else version(GC_Use_Data_Dyld) ++ { ++ _d_dyld_start(); ++ } ++ else ++ { ++ static assert( false, "Operating system not supported." ); ++ } ++ ++ version( GC_Use_Data_Proc_Maps ) ++ { ++ parseDataProcMaps(); ++ } ++ gc_addRange(dataStart, dataEnd - dataStart); ++} ++ ++version( GC_Use_Data_Proc_Maps ) ++{ ++version(solaris) ++{ ++ typedef long offset_t; ++ enum : uint { PRMAPSZ = 64, MA_WRITE = 0x02 } ++ extern(C) ++ { ++ struct prmap { ++ uintptr_t pr_vaddr; /* virtual address of mapping */ ++ size_t pr_size; /* size of mapping in bytes */ ++ char[PRMAPSZ] pr_mapname; /* name in /proc//object */ ++ private offset_t pr_offset; /* offset into mapped object, if any */ ++ int pr_mflags; /* protection and attribute flags (see below) */ ++ int pr_pagesize; /* pagesize (bytes) for this mapping */ ++ int pr_shmid; /* SysV shmid, -1 if not SysV shared memory */ ++ ++ private int[1] pr_filler; ++ } ++ } ++ ++ debug (ProcMaps) extern (C) int printf(char*, ...); ++ ++ void parseDataProcMaps() ++ { ++ debug (ProcMaps) printf("initStaticDataPtrs()\n"); ++ // http://docs.sun.com/app/docs/doc/816-5174/proc-4 ++ prmap pr; ++ ++ int fd = open("/proc/self/map", O_RDONLY); ++ scope (exit) close(fd); ++ ++ while (prmap.sizeof == read(fd, &pr, prmap.sizeof)) ++ if (pr.pr_mflags & MA_WRITE) ++ { ++ void* start = cast(void*) pr.pr_vaddr; ++ void* end = cast(void*)(pr.pr_vaddr + pr.pr_size); ++ debug (ProcMaps) printf(" vmem at %p - %p with size %d bytes\n", start, end, pr.pr_size); ++ ++ // Exclude stack and dataStart..dataEnd ++ if ( ( !dataEnd || ++ !( dataStart >= start && dataEnd <= end ) ) && ++ !( &pr >= start && &pr < end ) ) ++ { ++ // we already have static data from this region. anything else ++ // is heap (%% check) ++ debug (ProcMaps) printf(" Adding map range %p - %p\n", start, end); ++ gc_addRange(start, end - start); ++ } ++ } ++ } ++} ++else ++{ ++ const int S = (void*).sizeof; ++ ++ // TODO: This could use cleanup! ++ void parseDataProcMaps() ++ { ++ // TODO: Exclude zero-mapped regions ++ ++ int fd = open("/proc/self/maps", O_RDONLY); ++ ptrdiff_t count; // %% need to configure ret for read.. ++ char buf[2024]; ++ char* p; ++ char* e; ++ char* s; ++ void* start; ++ void* end; ++ ++ p = buf.ptr; ++ if (fd != -1) ++ { ++ while ( (count = read(fd, p, buf.sizeof - (p - buf.ptr))) > 0 ) ++ { ++ e = p + count; ++ p = buf.ptr; ++ while (true) ++ { ++ s = p; ++ while (p < e && *p != '\n') ++ p++; ++ if (p < e) ++ { ++ // parse the entry in [s, p) ++ static if( S == 4 ) ++ { ++ enum Ofs ++ { ++ Write_Prot = 19, ++ Start_Addr = 0, ++ End_Addr = 9, ++ Addr_Len = 8, ++ } ++ } ++ else static if( S == 8 ) ++ { ++ //X86-64 only has 12 bytes address space(in PAE mode) - not 16 ++ //We also need the 32 bit offsets for 32 bit apps ++ version(X86_64) { ++ enum Ofs ++ { ++ Write_Prot = 27, ++ Start_Addr = 0, ++ End_Addr = 13, ++ Addr_Len = 12, ++ Write_Prot_32 = 19, ++ Start_Addr_32 = 0, ++ End_Addr_32 = 9, ++ Addr_Len_32 = 8, ++ } ++ } ++ else ++ { ++ enum Ofs ++ { ++ Write_Prot = 35, ++ Start_Addr = 0, ++ End_Addr = 9, ++ Addr_Len = 17, ++ } ++ } ++ } ++ else ++ { ++ static assert( false ); ++ } ++ ++ // %% this is wrong for 64-bit: ++ // long strtoul(const char*,char**,int); ++ // but seems to work on x86-64: ++ // probably because C's long is 64 bit there ++ ++ if( s[Ofs.Write_Prot] == 'w' ) ++ { ++ s[Ofs.Start_Addr + Ofs.Addr_Len] = '\0'; ++ s[Ofs.End_Addr + Ofs.Addr_Len] = '\0'; ++ start = cast(void*) strtoul(s + Ofs.Start_Addr, null, 16); ++ end = cast(void*) strtoul(s + Ofs.End_Addr, null, 16); ++ ++ // 1. Exclude anything overlapping [dataStart, dataEnd) ++ // 2. Exclude stack ++ if ( ( !dataEnd || ++ !( dataStart >= start && dataEnd <= end ) ) && ++ !( &buf[0] >= start && &buf[0] < end ) ) ++ { ++ // we already have static data from this region. anything else ++ // is heap (%% check) ++ debug (ProcMaps) printf("Adding map range %p 0%p\n", start, end); ++ gc_addRange(start, end - start); ++ } ++ } ++ version(X86_64) ++ { ++ //We need to check here for 32 bit apps like ldc produces ++ //and add them to the gc scan range ++ if( s[Ofs.Write_Prot_32] == 'w' ) ++ { ++ s[Ofs.Start_Addr_32 + Ofs.Addr_Len_32] = '\0'; ++ s[Ofs.End_Addr_32 + Ofs.Addr_Len_32] = '\0'; ++ start = cast(void*) strtoul(s + Ofs.Start_Addr_32, null, 16); ++ end = cast(void*) strtoul(s + Ofs.End_Addr_32, null, 16); ++ if ( ( !dataEnd || ++ !( dataStart >= start && dataEnd <= end ) ) && ++ !( &buf[0] >= start && &buf[0] < end ) ) ++ { ++ gc_addRange(start, end - start); ++ } ++ } ++ } ++ ++ p++; ++ } ++ else ++ { ++ count = p - s; ++ memmove(buf.ptr, s, cast(size_t)count); ++ p = buf.ptr + count; ++ break; ++ } ++ } ++ } ++ close(fd); ++ } ++ } ++} ++} ++ ++/* ++ * GDC dyld memory module: ++ * http://www.dsource.org/projects/tango/browser/trunk/lib/compiler/gdc/memory_dyld.c ++ * Port to the D programming language: Jacob Carlborg ++ */ ++version (GC_Use_Data_Dyld) ++{ ++ private ++ { ++ const char* SEG_DATA = "__DATA".ptr; ++ const char* SECT_DATA = "__data".ptr; ++ const char* SECT_BSS = "__bss".ptr; ++ const char* SECT_COMMON = "__common".ptr; ++ ++ struct SegmentSection ++ { ++ const char* segment; ++ const char* section; ++ } ++ ++ struct mach_header ++ { ++ uint magic; ++ int cputype; ++ int cpusubtype; ++ uint filetype; ++ uint ncmds; ++ uint sizeofcmds; ++ uint flags; ++ version (D_LP64) ++ uint reserved; ++ } ++ ++ struct section ++ { ++ char[16] sectname; ++ char[16] segname; ++ c_ulong addr; ++ c_ulong size; ++ uint offset; ++ uint align_; ++ uint reloff; ++ uint nreloc; ++ uint flags; ++ uint reserved1; ++ uint reserved2; ++ version (D_LP64) ++ uint reserved3; ++ } ++ ++ alias extern (C) void function (mach_header* mh, ptrdiff_t vmaddr_slide) DyldFuncPointer; ++ ++ version (D_LP64) ++ extern (C) /*const*/ section* getsectbynamefromheader_64(/*const*/ mach_header* mhp, /*const*/ char* segname, /*const*/ char* sectname); ++ else ++ extern (C) /*const*/ section* getsectbynamefromheader(/*const*/ mach_header* mhp, /*const*/ char* segname, /*const*/ char* sectname); ++ extern (C) void _dyld_register_func_for_add_image(DyldFuncPointer func); ++ extern (C) void _dyld_register_func_for_remove_image(DyldFuncPointer func); ++ ++ const SegmentSection[3] GC_dyld_sections = [SegmentSection(SEG_DATA, SECT_DATA), SegmentSection(SEG_DATA, SECT_BSS), SegmentSection(SEG_DATA, SECT_COMMON)]; ++ ++ extern (C) void on_dyld_add_image (/*const*/ mach_header* hdr, ptrdiff_t slide) ++ { ++ void* start; ++ void* end; ++ /*const*/ section* sec; ++ ++ foreach (s ; GC_dyld_sections) ++ { ++ version (D_LP64) ++ sec = getsectbynamefromheader_64(hdr, s.segment, s.section); ++ else ++ sec = getsectbynamefromheader(hdr, s.segment, s.section); ++ ++ if (sec == null || sec.size == 0) ++ continue; ++ ++ start = cast(void*) (sec.addr + slide); ++ end = cast(void*) (start + sec.size); ++ ++ gc_addRange(start, end - start); ++ } ++ } ++ ++ extern (C) void on_dyld_remove_image (/*const*/ mach_header* hdr, ptrdiff_t slide) ++ { ++ void* start; ++ void* end; ++ /*const*/ section* sec; ++ ++ foreach (s ; GC_dyld_sections) ++ { ++ version (D_LP64) ++ sec = getsectbynamefromheader_64(hdr, s.segment, s.section); ++ else ++ sec = getsectbynamefromheader(hdr, s.segment, s.section); ++ ++ if (sec == null || sec.size == 0) ++ continue; ++ ++ start = cast(void*) (sec.addr + slide); ++ end = cast(void*) (start + sec.size); ++ ++ gc_removeRange(start); ++ } ++ } ++ ++ void _d_dyld_start () ++ { ++ static bool started; ++ ++ if (!started) ++ { ++ started = true; ++ ++ _dyld_register_func_for_add_image(&on_dyld_add_image); ++ _dyld_register_func_for_remove_image(&on_dyld_remove_image); ++ } ++ } ++ } ++} ++ ++} ++else ++{ ++ static assert( false, "Compiler not supported." ); ++} +\ No newline at end of file diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/qsort.d druntime/src/rt/qsort.d --- druntime-orig/src/rt/qsort.d 2010-08-05 05:39:06.000000000 +0400 +++ druntime/src/rt/qsort.d 2010-11-04 17:49:07.000000000 +0300 diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 8f0057e8..dec1453d 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -80,7 +80,7 @@ elseif(D_VERSION EQUAL 2) ${RUNTIME_DC_DIR}/deh2.d ) file(GLOB DCRT_C ${RUNTIME_DC_DIR}/*.c) - list(REMOVE_ITEM DCRT_C ${RUNTIME_DC_DIR}/deh.c) + list(REMOVE_ITEM DCRT_C ${RUNTIME_DC_DIR}/deh.c ${RUNTIME_DC_DIR}/memory_osx.c) if(UNIX) file(GLOB_RECURSE CORE_D_SYS ${RUNTIME_DIR}/src/core/sys/posix/*.d) elseif(WIN32) From d8e1d1feac281366cabfc30d6dcaeee0bf90903b Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Sun, 7 Nov 2010 18:02:43 +0300 Subject: [PATCH 25/31] Fixed a few unittests in math.d --- phobos.patch | 48 +++++++++++++++++++++++++++++++++++++----- runtime/CMakeLists.txt | 2 +- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/phobos.patch b/phobos.patch index ff784f16..751759e3 100644 --- a/phobos.patch +++ b/phobos.patch @@ -157,7 +157,16 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/math.d phobos/std/math.d --- phobos-orig/std/math.d 2010-09-17 00:27:48.000000000 +0400 -+++ phobos/std/math.d 2010-10-29 12:08:18.925035001 +0400 ++++ phobos/std/math.d 2010-11-07 17:42:39.390374001 +0300 +@@ -276,7 +276,7 @@ + assert(abs(71.6Li) == 71.6L); + assert(abs(-56) == 56); + assert(abs(2321312L) == 2321312L); +- assert(abs(-1+1i) == sqrt(2.0)); ++ assert(abs(-1+1i) == sqrt(2.0L)); + } + + /*********************************** @@ -318,7 +318,10 @@ * Results are undefined if |x| >= $(POWER 2,64). */ @@ -182,7 +191,18 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. /*********************************** -@@ -831,6 +837,20 @@ +@@ -400,7 +406,9 @@ + + @trusted pure nothrow real tan(real x) + { +- version(Naked_D_InlineAsm_X86) { ++ version(LDC) { ++ return core.stdc.math.tanl(x); ++ } else version(Naked_D_InlineAsm_X86) { + asm + { + fld x[EBP] ; // load theta +@@ -831,6 +839,20 @@ * ) */ @@ -203,7 +223,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. @safe pure nothrow { float sqrt(float x); /* intrinsic */ -@@ -838,6 +858,8 @@ +@@ -838,6 +860,8 @@ real sqrt(real x); /* intrinsic */ /// ditto } @@ -212,7 +232,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. @trusted pure nothrow { // Should be @safe. See bugs 4628, 4630. // Create explicit overloads for integer sqrts. No ddoc for these because // hopefully a more elegant solution will eventually be found, so we don't -@@ -1413,9 +1435,22 @@ +@@ -1413,9 +1437,22 @@ * Compute n * 2$(SUP exp) * References: frexp */ @@ -235,7 +255,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. unittest { assert(ldexp(1, -16384) == 0x1p-16384L); assert(ldexp(1, -16382) == 0x1p-16382L); -@@ -1608,7 +1643,31 @@ +@@ -1608,7 +1645,31 @@ * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) ) * ) */ @@ -268,6 +288,24 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. /*********************************************************************** +@@ -2993,9 +3054,15 @@ + assert(pow(x,eight) == (x * x) * (x * x) * (x * x) * (x * x)); + + assert(pow(x, neg1) == 1 / x); +- assert(pow(xd, neg2) == 1 / (x * x)); ++ version(LDC) // FIXME: ++ assert(pow(xd, neg2) == 1 / (xd * xd)); ++ else ++ assert(pow(xd, neg2) == 1 / (x * x)); + assert(pow(x, neg3) == 1 / (x * x * x)); +- assert(pow(xf, neg8) == 1 / ((x * x) * (x * x) * (x * x) * (x * x))); ++ version(LDC) ++ assert(pow(xf, neg8) == 1 / ((xf * xf) * (xf * xf) * (xf * xf) * (xf * xf))); ++ else ++ assert(pow(xf, neg8) == 1 / ((x * x) * (x * x) * (x * x) * (x * x))); + } + + /** Compute the value of an integer x, raised to the power of a positive diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/openrj.d phobos/std/openrj.d --- phobos-orig/std/openrj.d 2009-09-03 12:01:40.000000000 +0400 +++ phobos/std/openrj.d 2010-10-26 13:17:37.480925001 +0400 diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index dec1453d..67ca541c 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -187,7 +187,7 @@ macro(dc INPUT_D OUTLIST_O OUTLIST_BC INCDIR MOREFLAGS PATH) OUTPUT ${OUTPUT_O} ${OUTPUT_BC} - COMMAND ${LDC_LOC} --output-o --output-bc -c -I${INCDIR} -I${RUNTIME_GC_DIR} ${INPUT_D} -of${OUTPUT_O} ${D_FLAGS} ${MOREFLAGS} --unittest + COMMAND ${LDC_LOC} --output-o --output-bc -c -I${INCDIR} -I${RUNTIME_GC_DIR} ${INPUT_D} -of${OUTPUT_O} ${D_FLAGS} ${MOREFLAGS} DEPENDS ${LDC_LOC} ${INPUT_D} ${LDC_IMPORTS} From 6d22dd799905a309de951eab1720e93c917df142 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Mon, 8 Nov 2010 16:55:35 +0300 Subject: [PATCH 26/31] Updated to 2.050 --- dmd2/arrayop.c | 25 ++++++++++ dmd2/declaration.c | 32 +++++++----- dmd2/declaration.h | 4 +- dmd2/expression.c | 52 ++++++++++++++++--- dmd2/expression.h | 1 + dmd2/func.c | 57 ++++++++++++++++++--- dmd2/idgen.c | 7 ++- dmd2/interpret.c | 29 +++++++---- dmd2/mars.c | 5 +- dmd2/mtype.c | 111 +++++++++++++++++++++++++++++++++++------ dmd2/mtype.h | 12 ++++- dmd2/opover.c | 35 +++++++------ dmd2/optimize.c | 10 +++- dmd2/parse.c | 78 +++++++++++++++++++---------- dmd2/statement.c | 10 +++- dmd2/staticassert.c | 5 +- dmd2/struct.c | 7 ++- dmd2/template.c | 1 + druntime.patch | 97 ++++++++++------------------------- gen/toir.cpp | 11 ++-- gen/tollvm.cpp | 4 ++ gen/typinf.cpp | 5 +- ir/irstruct.cpp | 3 +- phobos.patch | 46 ++++++++--------- runtime/CMakeLists.txt | 1 + 25 files changed, 447 insertions(+), 201 deletions(-) diff --git a/dmd2/arrayop.c b/dmd2/arrayop.c index e794070b..92985f39 100644 --- a/dmd2/arrayop.c +++ b/dmd2/arrayop.c @@ -55,7 +55,19 @@ bool isArrayOpValid(Expression *e) case TOKxor: case TOKand: case TOKor: + case TOKassign: + case TOKaddass: + case TOKminass: + case TOKmulass: + case TOKdivass: + case TOKmodass: + case TOKxorass: + case TOKandass: + case TOKorass: +#if DMDV2 case TOKpow: + case TOKpowass: +#endif return isArrayOpValid(((BinExp *)e)->e1) && isArrayOpValid(((BinExp *)e)->e2); case TOKcall: @@ -607,6 +619,19 @@ int Expression::isArrayOperand() case TOKxor: case TOKand: case TOKor: + case TOKassign: + case TOKaddass: + case TOKminass: + case TOKmulass: + case TOKdivass: + case TOKmodass: + case TOKxorass: + case TOKandass: + case TOKorass: +#if DMDV2 + case TOKpow: + case TOKpowass: +#endif case TOKneg: case TOKtilde: return 1; diff --git a/dmd2/declaration.c b/dmd2/declaration.c index 4cb6c42e..9a143da3 100644 --- a/dmd2/declaration.c +++ b/dmd2/declaration.c @@ -1321,25 +1321,31 @@ Lagain: } else if (ei) { - if (isDataseg()) - /* static const/invariant does CTFE - */ + if (isDataseg() || (storage_class & STCmanifest)) e = e->optimize(WANTvalue | WANTinterpret); else e = e->optimize(WANTvalue); - if (e->op == TOKint64 || e->op == TOKstring || e->op == TOKfloat64) + switch (e->op) { - ei->exp = e; // no errors, keep result - } + case TOKint64: + case TOKfloat64: + case TOKstring: + case TOKarrayliteral: + case TOKassocarrayliteral: + case TOKstructliteral: + case TOKnull: + ei->exp = e; // no errors, keep result + break; + + default: #if DMDV2 - else - { - /* Save scope for later use, to try again - */ - scope = new Scope(*sc); - scope->setNoFree(); - } + /* Save scope for later use, to try again + */ + scope = new Scope(*sc); + scope->setNoFree(); #endif + break; + } } else init = i2; // no errors, keep result diff --git a/dmd2/declaration.h b/dmd2/declaration.h index 0362d15d..e7c8f920 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -49,6 +49,7 @@ enum PROT; enum LINK; enum TOK; enum MATCH; +enum PURE; #define STCundefined 0LL #define STCstatic 1LL @@ -697,6 +698,7 @@ struct FuncDeclaration : Declaration #if IN_GCC VarDeclaration *v_argptr; // '_argptr' variable #endif + VarDeclaration *v_argsave; // save area for args passed in registers for variadic functions Dsymbols *parameters; // Array of VarDeclaration's for parameters DsymbolTable *labtab; // statement label symbol table Declaration *overnext; // next in overload list @@ -776,7 +778,7 @@ struct FuncDeclaration : Declaration int isAbstract(); int isCodeseg(); int isOverloadable(); - int isPure(); + enum PURE isPure(); int isSafe(); int isTrusted(); virtual int isNested(); diff --git a/dmd2/expression.c b/dmd2/expression.c index a9074925..86f7f5d5 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -5619,6 +5619,11 @@ Expression *CompileExp::semantic(Scope *sc) #endif UnaExp::semantic(sc); e1 = resolveProperties(sc, e1); + if (!e1->type->isString()) + { + error("argument to mixin must be a string type, not %s\n", e1->type->toChars()); + return new ErrorExp(); + } e1 = e1->optimize(WANTvalue | WANTinterpret); if (e1->op != TOKstring) { error("argument to mixin must be a string, not (%s)", e1->toChars()); @@ -5749,7 +5754,8 @@ Expression *AssertExp::semantic(Scope *sc) if (e1->isBool(FALSE)) { FuncDeclaration *fd = sc->parent->isFuncDeclaration(); - fd->hasReturnExp |= 4; + if (fd) + fd->hasReturnExp |= 4; if (!global.params.useAssert) { Expression *e = new HaltExp(loc); @@ -7135,7 +7141,7 @@ Lagain: { TypeDelegate *td = (TypeDelegate *)t1; assert(td->next->ty == Tfunction); tf = (TypeFunction *)(td->next); - if (sc->func && sc->func->isPure() && !tf->ispure) + if (sc->func && sc->func->isPure() && !tf->purity) { error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars()); } @@ -7149,7 +7155,7 @@ Lagain: { Expression *e = new PtrExp(loc, e1); t1 = ((TypePointer *)t1)->next; - if (sc->func && sc->func->isPure() && !((TypeFunction *)t1)->ispure) + if (sc->func && sc->func->isPure() && !((TypeFunction *)t1)->purity) { error("pure function '%s' cannot call impure function pointer '%s'", sc->func->toChars(), e1->toChars()); } @@ -7272,9 +7278,9 @@ int CallExp::checkSideEffect(int flag) * then this expression has no side effects. */ Type *t = e1->type->toBasetype(); - if (t->ty == Tfunction && ((TypeFunction *)t)->ispure) + if (t->ty == Tfunction && ((TypeFunction *)t)->purity) return 0; - if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->ispure) + if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity) return 0; #endif return 1; @@ -8111,6 +8117,8 @@ Expression *SliceExp::semantic(Scope *sc) goto Lerror; } } + else if (t == Type::terror) + goto Lerr; else goto Lerror; @@ -8145,8 +8153,8 @@ Expression *SliceExp::semantic(Scope *sc) if (t->ty == Ttuple) { - lwr = lwr->optimize(WANTvalue); - upr = upr->optimize(WANTvalue); + lwr = lwr->optimize(WANTvalue | WANTinterpret); + upr = upr->optimize(WANTvalue | WANTinterpret); uinteger_t i1 = lwr->toUInteger(); uinteger_t i2 = upr->toUInteger(); @@ -9033,7 +9041,26 @@ Expression *AssignExp::semantic(Scope *sc) if (op == TOKassign) { Expression *e = op_overload(sc); - if (e) + if (e && e1->op == TOKindex && + ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) + { + // Deal with AAs (Bugzilla 2451) + // Rewrite as: + // e1 = (typeof(e2) tmp = void, tmp = e2, tmp); + Identifier *id = Lexer::uniqueId("__aatmp"); + VarDeclaration *v = new VarDeclaration(loc, e2->type, + id, new VoidInitializer(NULL)); + v->storage_class |= STCctfe; + + Expression *de = new DeclarationExp(loc, v); + VarExp *ve = new VarExp(loc, v); + + AssignExp *ae = new AssignExp(loc, ve, e2); + e = ae->op_overload(sc); + e2 = new CommaExp(loc, new CommaExp(loc, de, e), ve); + e2 = e2->semantic(sc); + } + else if (e) return e; } else if (op == TOKconstruct && !refinit) @@ -9355,6 +9382,7 @@ CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) Expression *CatAssignExp::semantic(Scope *sc) { Expression *e; + //printf("CatAssignExp::semantic() %s\n", toChars()); e = op_overload(sc); if (e) return e; @@ -10747,6 +10775,14 @@ RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2) type = Type::tvoid; } +void RemoveExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + expToCBuffer(buf, hgs, e1, PREC_primary); + buf->writestring(".remove("); + expToCBuffer(buf, hgs, e2, PREC_assign); + buf->writestring(")"); +} + /************************************************************/ CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) diff --git a/dmd2/expression.h b/dmd2/expression.h index 6e8ea740..2bbbc38e 100644 --- a/dmd2/expression.h +++ b/dmd2/expression.h @@ -1912,6 +1912,7 @@ struct InExp : BinExp struct RemoveExp : BinExp { RemoveExp(Loc loc, Expression *e1, Expression *e2); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); #if IN_DMD elem *toElem(IRState *irs); #endif diff --git a/dmd2/func.c b/dmd2/func.c index f6020c1f..9f581356 100644 --- a/dmd2/func.c +++ b/dmd2/func.c @@ -55,6 +55,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla #if IN_GCC v_argptr = NULL; #endif + v_argsave = NULL; parameters = NULL; labtab = NULL; overnext = NULL; @@ -805,6 +806,7 @@ void FuncDeclaration::semantic3(Scope *sc) { TypeFunction *f; VarDeclaration *argptr = NULL; VarDeclaration *_arguments = NULL; + int nerrors = global.errors; if (!parent) { @@ -903,8 +905,8 @@ void FuncDeclaration::semantic3(Scope *sc) #if STRUCTTHISREF thandle = thandle->addMod(type->mod); thandle = thandle->addStorageClass(storage_class); - if (isPure()) - thandle = thandle->addMod(MODconst); + //if (isPure()) + //thandle = thandle->addMod(MODconst); #else if (storage_class & STCconst || type->isConst()) { @@ -1005,6 +1007,20 @@ void FuncDeclaration::semantic3(Scope *sc) } #endif } + if (global.params.is64bit && f->varargs && f->linkage == LINKc) + { // Declare save area for varargs registers + Type *t = new TypeIdentifier(loc, Id::va_argsave_t); + t = t->semantic(loc, sc); + if (t == Type::terror) + error("must import std.c.stdarg to use variadic functions"); + else + { + v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL); + v_argsave->semantic(sc2); + sc2->insert(v_argsave); + v_argsave->parent = this; + } + } #if IN_LLVM // LDC make sure argument type is semanticed. @@ -1072,8 +1088,8 @@ void FuncDeclaration::semantic3(Scope *sc) arg->ident = id = Identifier::generateId("_param_", i); } Type *vtype = arg->type; - if (isPure()) - vtype = vtype->addMod(MODconst); + //if (isPure()) + //vtype = vtype->addMod(MODconst); VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL); //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars()); v->storage_class |= STCparameter; @@ -1716,7 +1732,11 @@ void FuncDeclaration::semantic3(Scope *sc) sc2->callSuper = 0; sc2->pop(); } - semanticRun = PASSsemantic3done; + + if (global.gag && global.errors != nerrors) + semanticRun = PASSsemanticdone; // Ensure errors get reported again + else + semanticRun = PASSsemantic3done; } void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -1798,6 +1818,16 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf) for (int i = 0; i < foverrides.dim; i++) { FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i]; + + /* The semantic pass on the contracts of the overridden functions must + * be completed before code generation occurs (bug 3602). + */ + if (fdv->fdrequire && fdv->fdrequire->semanticRun != PASSsemantic3done) + { + assert(fdv->scope); + fdv->semantic3(fdv->scope); + } + sf = fdv->mergeFrequire(sf); if (fdv->fdrequire) { @@ -2674,11 +2704,24 @@ int FuncDeclaration::isOverloadable() return 1; // functions can be overloaded } -int FuncDeclaration::isPure() +enum PURE FuncDeclaration::isPure() { //printf("FuncDeclaration::isPure() '%s'\n", toChars()); assert(type->ty == Tfunction); - return ((TypeFunction *)this->type)->ispure; + TypeFunction *tf = (TypeFunction *)type; + enum PURE purity = tf->purity; + if (purity == PUREfwdref) + tf->purityLevel(); + if (purity > PUREweak && needThis()) + { // The attribute of the 'this' reference affects purity strength + if (type->mod & (MODimmutable | MODwild)) + ; + else if (type->mod & MODconst && purity >= PUREconst) + purity = PUREconst; + else + purity = PUREweak; + } + return purity; } int FuncDeclaration::isSafe() diff --git a/dmd2/idgen.c b/dmd2/idgen.c index 1691da58..bbd3213e 100644 --- a/dmd2/idgen.c +++ b/dmd2/idgen.c @@ -1,9 +1,10 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com +// http://www.dsource.org/projects/dmd/browser/trunk/src/idgen.c // License for redistribution is by either the Artistic License // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. @@ -295,6 +296,10 @@ Msgtable msgtable[] = { "DllMain" }, { "tls_get_addr", "___tls_get_addr" }, + // varargs implementation + { "va_argsave_t", "__va_argsave_t" }, + { "va_argsave", "__va_argsave" }, + // Builtin functions { "std" }, { "math" }, diff --git a/dmd2/interpret.c b/dmd2/interpret.c index 41ae5335..250be4a8 100644 --- a/dmd2/interpret.c +++ b/dmd2/interpret.c @@ -564,13 +564,13 @@ Expression *ReturnStatement::interpret(InterState *istate) } #endif -#if LOG Expression *e = exp->interpret(istate); - printf("e = %p\n", e); + if (e == EXP_CANT_INTERPRET) + return e; + // Convert lvalues into rvalues (See Bugzilla 4825 for rationale) + if (e->op == TOKvar) + e = e->interpret(istate); return e; -#else - return exp->interpret(istate); -#endif } Expression *BreakStatement::interpret(InterState *istate) @@ -2710,21 +2710,32 @@ Expression *CallExp::interpret(InterState *istate) Expression * pe = ((PtrExp*)ecall)->e1; if (pe->op == TOKvar) { VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration(); - if (vd && vd->value && vd->value->op==TOKsymoff) + if (vd && vd->value && vd->value->op == TOKsymoff) fd = ((SymOffExp *)vd->value)->var->isFuncDeclaration(); else { ecall = vd->value->interpret(istate); - if (ecall->op==TOKsymoff) + if (ecall->op == TOKsymoff) fd = ((SymOffExp *)ecall)->var->isFuncDeclaration(); } } else ecall = ((PtrExp*)ecall)->e1->interpret(istate); + } + if (ecall == EXP_CANT_INTERPRET) + return ecall; + if (ecall->op == TOKindex) - ecall = e1->interpret(istate); + { ecall = e1->interpret(istate); + if (ecall == EXP_CANT_INTERPRET) + return ecall; + } + if (ecall->op == TOKdotvar && !((DotVarExp*)ecall)->var->isFuncDeclaration()) - ecall = e1->interpret(istate); + { ecall = e1->interpret(istate); + if (ecall == EXP_CANT_INTERPRET) + return ecall; + } if (ecall->op == TOKdotvar) { // Calling a member function diff --git a/dmd2/mars.c b/dmd2/mars.c index 2333c7fb..a9908b5e 100644 --- a/dmd2/mars.c +++ b/dmd2/mars.c @@ -4,6 +4,7 @@ // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com +// http://www.dsource.org/projects/dmd/browser/trunk/src/mars.c // License for redistribution is by either the Artistic License // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. @@ -99,7 +100,7 @@ Global::Global() "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates."; #endif ; - version = "v2.049"; + version = "v2.050"; #if IN_LLVM ldc_version = "LDC trunk"; llvm_version = "LLVM 2.8"; @@ -237,6 +238,8 @@ void halt() #endif } + +extern signed char tyalignsize[]; /*********************************** * Parse and append contents of environment variable envvar * to argc and argv[]. diff --git a/dmd2/mtype.c b/dmd2/mtype.c index 685477f9..0e2d4afe 100644 --- a/dmd2/mtype.c +++ b/dmd2/mtype.c @@ -4,6 +4,7 @@ // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com +// http://www.dsource.org/projects/dmd/browser/trunk/src/mtype.c // License for redistribution is by either the Artistic License // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. @@ -3480,7 +3481,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) return this; } dinteger_t d1 = dim->toInteger(); - dim = dim->castTo(sc, tsize_t); + dim = dim->implicitCastTo(sc, tsize_t); dim = dim->optimize(WANTvalue); dinteger_t d2 = dim->toInteger(); @@ -4585,7 +4586,7 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, e this->linkage = linkage; this->inuse = 0; this->isnothrow = false; - this->ispure = false; + this->purity = PUREimpure; this->isproperty = false; this->isref = false; this->fargs = NULL; @@ -4594,7 +4595,7 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, e this->funcdecl = NULL; #endif if (stc & STCpure) - this->ispure = true; + this->purity = PUREfwdref; if (stc & STCnothrow) this->isnothrow = true; if (stc & STCproperty) @@ -4616,7 +4617,7 @@ Type *TypeFunction::syntaxCopy() TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage); t->mod = mod; t->isnothrow = isnothrow; - t->ispure = ispure; + t->purity = purity; t->isproperty = isproperty; t->isref = isref; t->trust = trust; @@ -4750,7 +4751,7 @@ Lcovariant: /* Can convert pure to impure, and nothrow to throw */ - if (!t1->ispure && t2->ispure) + if (!t1->purity && t2->purity) goto Lnotcovariant; if (!t1->isnothrow && t2->isnothrow) @@ -4802,9 +4803,9 @@ void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) assert(0); } buf->writeByte(mc); - if (ispure || isnothrow || isproperty || isref || trust) + if (purity || isnothrow || isproperty || isref || trust) { - if (ispure) + if (purity) buf->writestring("Na"); if (isnothrow) buf->writestring("Nb"); @@ -4876,7 +4877,7 @@ void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs buf->writeByte(' '); } - if (ispure) + if (purity) buf->writestring("pure "); if (isnothrow) buf->writestring("nothrow "); @@ -4976,7 +4977,7 @@ void TypeFunction::attributesToCBuffer(OutBuffer *buf, int mod) { modToBuffer(buf); } - if (ispure) + if (purity) buf->writestring(" pure"); if (isnothrow) buf->writestring(" nothrow"); @@ -5028,7 +5029,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) } if (sc->stc & STCpure) - tf->ispure = TRUE; + tf->purity = PUREfwdref; if (sc->stc & STCnothrow) tf->isnothrow = TRUE; if (sc->stc & STCref) @@ -5205,6 +5206,84 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) return tf; } + +/******************************************** + * Do this lazily, as the parameter types might be forward referenced. + */ +void TypeFunction::purityLevel() +{ + TypeFunction *tf = this; + if (tf->purity == PUREfwdref) + { /* Evaluate what kind of purity based on the modifiers for the parameters + */ + tf->purity = PUREstrong; // assume strong until something weakens it + if (tf->parameters) + { + size_t dim = Parameter::dim(tf->parameters); + for (size_t i = 0; i < dim; i++) + { Parameter *fparam = Parameter::getNth(tf->parameters, i); + if (fparam->storageClass & STClazy) + { + /* We could possibly allow this by doing further analysis on the + * lazy parameter to see if it's pure. + */ + error(0, "cannot have lazy parameters to a pure function"); + } + if (fparam->storageClass & STCout) + { + tf->purity = PUREweak; + break; + } + if (!fparam->type) + continue; + if (fparam->storageClass & STCref) + { + if (!(fparam->type->mod & (MODconst | MODimmutable | MODwild))) + { tf->purity = PUREweak; + break; + } + if (fparam->type->mod & MODconst) + { tf->purity = PUREconst; + continue; + } + } + Type *t = fparam->type->toBasetype(); + if (!t->hasPointers()) + continue; + if (t->mod & (MODimmutable | MODwild)) + continue; + /* The rest of this is too strict; fix later. + * For example, the only pointer members of a struct may be immutable, + * which would maintain strong purity. + */ + if (t->mod & MODconst) + { tf->purity = PUREconst; + continue; + } + Type *tn = t->nextOf(); + if (tn) + { tn = tn->toBasetype(); + if (tn->ty == Tpointer || tn->ty == Tarray) + { /* Accept immutable(T)* and immutable(T)[] as being strongly pure + */ + if (tn->mod & (MODimmutable | MODwild)) + continue; + if (tn->mod & MODconst) + { tf->purity = PUREconst; + continue; + } + } + } + /* Should catch delegates and function pointers, and fold in their purity + */ + tf->purity = PUREweak; // err on the side of too strict + break; + } + } + } +} + + /******************************** * 'args' are being matched to function 'this' * Determine match level. @@ -5425,7 +5504,7 @@ bool TypeFunction::parameterEscapes(Parameter *p) if (p->storageClass & (STCscope | STClazy)) return FALSE; - if (ispure) + if (purity) { /* With pure functions, we need only be concerned if p escapes * via any return statement. */ @@ -6039,7 +6118,7 @@ Type *TypeInstance::semantic(Loc loc, Scope *sc) printf("2: "); #endif error(loc, "%s is used as a type", toChars()); - t = tvoid; + t = terror; } return t; } @@ -7979,11 +8058,11 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc) TypeTuple *tt = (TypeTuple *)tbn; lwr = semanticLength(sc, tbn, lwr); - lwr = lwr->optimize(WANTvalue); + lwr = lwr->optimize(WANTvalue | WANTinterpret); uinteger_t i1 = lwr->toUInteger(); upr = semanticLength(sc, tbn, upr); - upr = upr->optimize(WANTvalue); + upr = upr->optimize(WANTvalue | WANTinterpret); uinteger_t i2 = upr->toUInteger(); if (!(i1 <= i2 && i2 <= tt->arguments->dim)) @@ -8023,11 +8102,11 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol sc = sc->push(sym); lwr = lwr->semantic(sc); - lwr = lwr->optimize(WANTvalue); + lwr = lwr->optimize(WANTvalue | WANTinterpret); uinteger_t i1 = lwr->toUInteger(); upr = upr->semantic(sc); - upr = upr->optimize(WANTvalue); + upr = upr->optimize(WANTvalue | WANTinterpret); uinteger_t i2 = upr->toUInteger(); sc = sc->pop(); diff --git a/dmd2/mtype.h b/dmd2/mtype.h index bb2e0e19..d1d337fd 100644 --- a/dmd2/mtype.h +++ b/dmd2/mtype.h @@ -589,6 +589,15 @@ enum TRUST TRUSTsafe = 3, // @safe }; +enum PURE +{ + PUREimpure = 0, // not pure at all + PUREweak = 1, // no mutable globals are read or written + PUREconst = 2, // parameters are values or const + PUREstrong = 3, // parameters are values or immutable + PUREfwdref = 4, // it's pure, but not known which level yet +}; + struct TypeFunction : TypeNext { // .next is the return type @@ -597,11 +606,11 @@ struct TypeFunction : TypeNext int varargs; // 1: T t, ...) style for variable number of arguments // 2: T t ...) style for variable number of arguments bool isnothrow; // true: nothrow - bool ispure; // true: pure bool isproperty; // can be called without parentheses bool isref; // true: returns a reference enum LINK linkage; // calling convention enum TRUST trust; // level of trust + enum PURE purity; // PURExxxx Expressions *fargs; // function arguments int inuse; @@ -609,6 +618,7 @@ struct TypeFunction : TypeNext TypeFunction(Parameters *parameters, Type *treturn, int varargs, enum LINK linkage, StorageClass stc = 0); Type *syntaxCopy(); Type *semantic(Loc loc, Scope *sc); + void purityLevel(); void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); diff --git a/dmd2/opover.c b/dmd2/opover.c index 338019c0..68dded02 100644 --- a/dmd2/opover.c +++ b/dmd2/opover.c @@ -251,7 +251,7 @@ Expression *UnaExp::op_overload(Scope *sc) ((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); Expression *e = copy(); ((UnaExp *)e)->e1 = e1; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } } @@ -294,7 +294,7 @@ Expression *UnaExp::op_overload(Scope *sc) ((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident); Expression *e = copy(); ((UnaExp *)e)->e1 = e1; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } } @@ -356,7 +356,7 @@ Expression *UnaExp::op_overload(Scope *sc) Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); Expression *e = copy(); ((UnaExp *)e)->e1 = e1; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } #endif @@ -391,7 +391,7 @@ Expression *ArrayExp::op_overload(Scope *sc) Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); Expression *e = copy(); ((UnaExp *)e)->e1 = e1; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } } @@ -438,7 +438,7 @@ Expression *CastExp::op_overload(Scope *sc) Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); Expression *e = copy(); ((UnaExp *)e)->e1 = e1; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } } @@ -683,7 +683,8 @@ L1: #if DMDV2 // Try alias this on first operand - if (ad1 && ad1->aliasthis) + if (ad1 && ad1->aliasthis && + !(op == TOKassign && ad2 && ad1 == ad2)) // See Bugzilla 2943 { /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) @@ -691,12 +692,16 @@ L1: Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); Expression *e = copy(); ((BinExp *)e)->e1 = e1; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } // Try alias this on second operand - if (ad2 && ad2->aliasthis) + if (ad2 && ad2->aliasthis && + /* Bugzilla 2943: make sure that when we're copying the struct, we don't + * just copy the alias this member + */ + !(op == TOKassign && ad1 && ad1 == ad2)) { /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) @@ -704,7 +709,7 @@ L1: Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); Expression *e = copy(); ((BinExp *)e)->e2 = e2; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } #endif @@ -860,7 +865,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); Expression *e = copy(); ((BinExp *)e)->e1 = e1; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } @@ -873,7 +878,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); Expression *e = copy(); ((BinExp *)e)->e2 = e2; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } @@ -954,7 +959,7 @@ Expression *BinAssignExp::op_overload(Scope *sc) ((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); Expression *e = copy(); ((UnaExp *)e)->e1 = e1; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } } @@ -998,7 +1003,7 @@ Expression *BinAssignExp::op_overload(Scope *sc) ((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident); Expression *e = copy(); ((UnaExp *)e)->e1 = e1; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } } @@ -1099,7 +1104,7 @@ L1: Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); Expression *e = copy(); ((BinExp *)e)->e1 = e1; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } @@ -1113,7 +1118,7 @@ L1: Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); Expression *e = copy(); ((BinExp *)e)->e2 = e2; - e = e->semantic(sc); + e = e->trySemantic(sc); return e; } #endif diff --git a/dmd2/optimize.c b/dmd2/optimize.c index 35abcd02..911992da 100644 --- a/dmd2/optimize.c +++ b/dmd2/optimize.c @@ -138,7 +138,15 @@ Expression *fromConstInitializer(int result, Expression *e1) int fwdref = (v && !v->originalType && v->scope); e = expandVar(result, v); if (e) - { if (e->type != e1->type && e1->type && e1->type->ty != Tident) + { + // If it is a comma expression involving a declaration, we mustn't + // perform a copy -- we'd get two declarations of the same variable. + // See bugzilla 4465. + if (e->op == TOKcomma && ((CommaExp *)e)->e1->op == TOKdeclaration) + e = e1; + else + + if (e->type != e1->type && e1->type && e1->type->ty != Tident) { // Type 'paint' operation e = e->copy(); e->type = e1->type; diff --git a/dmd2/parse.c b/dmd2/parse.c index 4f11e221..712dc95f 100644 --- a/dmd2/parse.c +++ b/dmd2/parse.c @@ -2413,12 +2413,6 @@ Type *Parser::parseBasicType2(Type *t) t = new TypeDArray(t); // [] nextToken(); } - else if (token.value == TOKnew && peekNext() == TOKrbracket) - { - t = new TypeNewArray(t); // [new] - nextToken(); - nextToken(); - } else if (isDeclaration(&token, 0, TOKrbracket, NULL)) { // It's an associative array declaration @@ -2498,14 +2492,39 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters * break; case TOKlparen: - /* Parse things with parentheses around the identifier, like: - * int (*ident[3])[] - * although the D style would be: - * int[]*[3] ident + if (peekNext() == TOKmul || // like: T (*fp)(); + peekNext() == TOKlparen // like: T ((*fp))(); + /* || peekNext() == TOKlbracket*/) // like: T ([] a) + { + /* Parse things with parentheses around the identifier, like: + * int (*ident[3])[] + * although the D style would be: + * int[]*[3] ident + */ + if (!global.params.useDeprecated) + { + error("C-style function pointer and pointer to array syntax is deprecated. Use 'function' to declare function pointers"); + } + nextToken(); + ts = parseDeclarator(t, pident); + check(TOKrparen); + break; + } + ts = t; + { + Token *peekt = &token; + /* Completely disallow C-style things like: + * T (a); + * Improve error messages for the common bug of a missing return type + * by looking to see if (a) looks like a parameter list. */ - nextToken(); - ts = parseDeclarator(t, pident); - check(TOKrparen); + if (isParameters(&peekt)) { + error("function declaration without return type. " + "(Note that constructors are always named 'this')"); + } + else + error("unexpected ( in declarator"); + } break; default: @@ -2533,12 +2552,6 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters * ta = new TypeDArray(t); // [] nextToken(); } - else if (token.value == TOKnew && peekNext() == TOKrbracket) - { - t = new TypeNewArray(t); // [new] - nextToken(); - nextToken(); - } else if (isDeclaration(&token, 0, TOKrbracket, NULL)) { // It's an associative array @@ -4457,11 +4470,6 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok) { t = peek(t); } - else if (t->value == TOKnew && peek(t)->value == TOKrbracket) - { - t = peek(t); - t = peek(t); - } else if (isDeclaration(t, 0, TOKrbracket, &t)) { // It's an associative array declaration t = peek(t); @@ -6273,37 +6281,53 @@ void initPrecedence() precedence[TOKsuper] = PREC_primary; precedence[TOKint64] = PREC_primary; precedence[TOKfloat64] = PREC_primary; + precedence[TOKcomplex80] = PREC_primary; precedence[TOKnull] = PREC_primary; precedence[TOKstring] = PREC_primary; precedence[TOKarrayliteral] = PREC_primary; + precedence[TOKassocarrayliteral] = PREC_primary; +#if DMDV2 + precedence[TOKfile] = PREC_primary; + precedence[TOKline] = PREC_primary; +#endif precedence[TOKtypeid] = PREC_primary; precedence[TOKis] = PREC_primary; precedence[TOKassert] = PREC_primary; + precedence[TOKhalt] = PREC_primary; + precedence[TOKtemplate] = PREC_primary; + precedence[TOKdsymbol] = PREC_primary; precedence[TOKfunction] = PREC_primary; precedence[TOKvar] = PREC_primary; precedence[TOKsymoff] = PREC_primary; precedence[TOKstructliteral] = PREC_primary; precedence[TOKarraylength] = PREC_primary; + precedence[TOKremove] = PREC_primary; precedence[TOKtuple] = PREC_primary; #if DMDV2 precedence[TOKtraits] = PREC_primary; precedence[TOKdefault] = PREC_primary; + precedence[TOKoverloadset] = PREC_primary; #endif // post precedence[TOKdotti] = PREC_primary; precedence[TOKdot] = PREC_primary; precedence[TOKdottd] = PREC_primary; + precedence[TOKdotexp] = PREC_primary; + precedence[TOKdottype] = PREC_primary; // precedence[TOKarrow] = PREC_primary; precedence[TOKplusplus] = PREC_primary; precedence[TOKminusminus] = PREC_primary; +#if DMDV2 precedence[TOKpreplusplus] = PREC_primary; precedence[TOKpreminusminus] = PREC_primary; +#endif precedence[TOKcall] = PREC_primary; precedence[TOKslice] = PREC_primary; precedence[TOKarray] = PREC_primary; precedence[TOKindex] = PREC_primary; + precedence[TOKdelegate] = PREC_unary; precedence[TOKaddress] = PREC_unary; precedence[TOKstar] = PREC_unary; precedence[TOKneg] = PREC_unary; @@ -6313,14 +6337,16 @@ void initPrecedence() precedence[TOKtilde] = PREC_unary; precedence[TOKdelete] = PREC_unary; precedence[TOKnew] = PREC_unary; + precedence[TOKnewanonclass] = PREC_unary; precedence[TOKcast] = PREC_unary; +#if DMDV2 precedence[TOKpow] = PREC_pow; +#endif precedence[TOKmul] = PREC_mul; precedence[TOKdiv] = PREC_mul; precedence[TOKmod] = PREC_mul; - precedence[TOKpow] = PREC_mul; precedence[TOKadd] = PREC_add; precedence[TOKmin] = PREC_add; @@ -6380,7 +6406,9 @@ void initPrecedence() precedence[TOKmulass] = PREC_assign; precedence[TOKdivass] = PREC_assign; precedence[TOKmodass] = PREC_assign; +#if DMDV2 precedence[TOKpowass] = PREC_assign; +#endif precedence[TOKshlass] = PREC_assign; precedence[TOKshrass] = PREC_assign; precedence[TOKushrass] = PREC_assign; diff --git a/dmd2/statement.c b/dmd2/statement.c index 9c0ef3e3..f7db947b 100644 --- a/dmd2/statement.c +++ b/dmd2/statement.c @@ -4286,6 +4286,9 @@ int TryCatchStatement::blockExit() for (size_t i = 0; i < catches->dim; i++) { Catch *c = (Catch *)catches->data[i]; + if (c->type == Type::terror) + continue; + catchresult |= c->blockExit(); /* If we're catching Object, then there is no throwing @@ -4361,7 +4364,12 @@ void Catch::semantic(Scope *sc) type = new TypeIdentifier(0, Id::Object); type = type->semantic(loc, sc); if (!type->toBasetype()->isClassHandle()) - error(loc, "can only catch class objects, not '%s'", type->toChars()); + { + if (type != Type::terror) + { error(loc, "can only catch class objects, not '%s'", type->toChars()); + type = Type::terror; + } + } else if (ident) { var = new VarDeclaration(loc, type, ident, NULL); diff --git a/dmd2/staticassert.c b/dmd2/staticassert.c index e80e4603..fcbe913e 100644 --- a/dmd2/staticassert.c +++ b/dmd2/staticassert.c @@ -1,8 +1,9 @@ -// Copyright (c) 1999-2007 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com +// http://www.dsource.org/projects/dmd/browser/trunk/src/staticassert.c // License for redistribution is by either the Artistic License // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. @@ -55,6 +56,8 @@ void StaticAssert::semantic2(Scope *sc) //printf("StaticAssert::semantic2() %s\n", toChars()); e = exp->semantic(sc); + if (e->op == TOKerror) + return; e = e->optimize(WANTvalue | WANTinterpret); if (e->isBool(FALSE)) { diff --git a/dmd2/struct.c b/dmd2/struct.c index 0e83d221..8d6b765b 100644 --- a/dmd2/struct.c +++ b/dmd2/struct.c @@ -226,11 +226,14 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) if (!isUnionDeclaration()) sc->offset = ofs; #endif - if (sc->structalign < memalignsize) + if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16) + /* Not sure how to handle this */ + ; + else if (sc->structalign < memalignsize) memalignsize = sc->structalign; if (alignsize < memalignsize) alignsize = memalignsize; - //printf("\talignsize = %d\n", alignsize); + //printf("\t%s: alignsize = %d\n", toChars(), alignsize); v->storage_class |= STCfield; //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize); diff --git a/dmd2/template.c b/dmd2/template.c index ebd9ad5d..2954b242 100644 --- a/dmd2/template.c +++ b/dmd2/template.c @@ -894,6 +894,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec ScopeDsymbol *paramsym = new ScopeDsymbol(); paramsym->parent = scope->parent; Scope *paramscope = scope->push(paramsym); + paramscope->stc = 0; TemplateTupleParameter *tp = isVariadic(); int tp_is_declared = 0; diff --git a/druntime.patch b/druntime.patch index 9e64e253..64a5affc 100644 --- a/druntime.patch +++ b/druntime.patch @@ -1,6 +1,6 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/ldc/cstdarg.di druntime/import/ldc/cstdarg.di --- druntime-orig/import/ldc/cstdarg.di 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/import/ldc/cstdarg.di 2010-11-05 13:57:24.315267000 +0300 ++++ druntime/import/ldc/cstdarg.di 2010-11-05 13:57:24.000000000 +0300 @@ -0,0 +1,29 @@ +/* + * vararg support for extern(C) functions @@ -417,7 +417,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/ldc/vararg.d druntime/import/ldc/vararg.d --- druntime-orig/import/ldc/vararg.d 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/import/ldc/vararg.d 2010-11-05 13:57:12.991267001 +0300 ++++ druntime/import/ldc/vararg.d 2010-11-05 13:57:12.000000000 +0300 @@ -0,0 +1,43 @@ +/* + * This module holds the implementation of special vararg templates for D style var args. @@ -463,18 +463,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + dst = src; +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/object.di druntime/import/object.di ---- druntime-orig/import/object.di 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/import/object.di 2010-11-04 17:49:07.000000000 +0300 -@@ -130,7 +130,7 @@ - Interface[] interfaces; - TypeInfo_Class base; - void* destructor; -- void(*classInvariant)(Object); -+ void function(Object) classInvariant; - uint m_flags; - // 1: // is IUnknown or is derived from IUnknown - // 2: // has no possible pointers into GC memory -@@ -140,7 +140,7 @@ +--- druntime-orig/import/object.di 2010-10-13 10:37:58.000000000 +0400 ++++ druntime/import/object.di 2010-11-07 19:11:32.000000000 +0300 +@@ -142,7 +142,7 @@ // 32: // has typeinfo member void* deallocator; OffsetTypeInfo[] m_offTi; @@ -483,7 +474,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. const(MemberInfo[]) function(string) xgetMembers; static TypeInfo_Class find(in char[] classname); -@@ -179,7 +179,7 @@ +@@ -189,7 +189,7 @@ class TypeInfo_Const : TypeInfo { @@ -492,7 +483,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } class TypeInfo_Invariant : TypeInfo_Const -@@ -288,7 +288,6 @@ +@@ -298,7 +298,6 @@ interface TraceInfo { int opApply(scope int delegate(ref char[])); @@ -501,8 +492,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. string msg; diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/core/atomic.d druntime/src/core/atomic.d ---- druntime-orig/src/core/atomic.d 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/src/core/atomic.d 2010-11-04 17:49:07.000000000 +0300 +--- druntime-orig/src/core/atomic.d 2010-10-11 00:37:54.000000000 +0400 ++++ druntime/src/core/atomic.d 2010-11-07 19:11:32.000000000 +0300 @@ -89,6 +89,117 @@ return false; } @@ -677,8 +668,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { // use the unoptimized version diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/gc/gcx.d druntime/src/gc/gcx.d ---- druntime-orig/src/gc/gcx.d 2010-08-27 01:23:26.000000000 +0400 -+++ druntime/src/gc/gcx.d 2010-11-06 18:16:41.638720001 +0300 +--- druntime-orig/src/gc/gcx.d 2010-10-03 10:52:12.000000000 +0400 ++++ druntime/src/gc/gcx.d 2010-11-07 19:11:32.000000000 +0300 @@ -1464,7 +1464,8 @@ @@ -906,9 +897,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. thread_suspendAll(); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/object_.d druntime/src/object_.d ---- druntime-orig/src/object_.d 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/src/object_.d 2010-11-06 19:28:37.000000000 +0300 -@@ -1663,7 +1663,6 @@ +--- druntime-orig/src/object_.d 2010-10-13 10:37:58.000000000 +0400 ++++ druntime/src/object_.d 2010-11-07 19:11:32.000000000 +0300 +@@ -1754,7 +1754,6 @@ { int len = 0; ModuleReference *mr; @@ -916,7 +907,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. for (mr = _Dmodule_ref; mr; mr = mr.next) len++; _moduleinfo_array = new ModuleInfo*[len]; -@@ -2025,7 +2024,6 @@ +@@ -2116,7 +2115,6 @@ _d_monitor_create(h); m = getMonitor(h); } @@ -924,7 +915,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. IMonitor i = m.impl; if (i is null) -@@ -2124,7 +2122,7 @@ +@@ -2215,7 +2213,7 @@ size_t _aaLen(void* p); void* _aaGet(void** pp, TypeInfo keyti, size_t valuesize, ...); void* _aaGetRvalue(void* p, TypeInfo keyti, size_t valuesize, ...); @@ -933,7 +924,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. void _aaDel(void* p, TypeInfo keyti, ...); void[] _aaValues(void* p, size_t keysize, size_t valuesize); void[] _aaKeys(void* p, size_t keysize, size_t valuesize); -@@ -2169,7 +2167,7 @@ +@@ -2260,7 +2258,7 @@ return *cast(Key[]*) &a; } @@ -944,7 +935,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/aaA.d druntime/src/rt/aaA.d --- druntime-orig/src/rt/aaA.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/aaA.d 2010-11-05 11:43:19.831267002 +0300 ++++ druntime/src/rt/aaA.d 2010-11-05 11:43:19.000000000 +0300 @@ -204,7 +204,7 @@ * Add entry for key if it is not already there. */ @@ -1776,8 +1767,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + _Unwind_Resume(&exception_struct.unwind_info); +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/lifetime.d druntime/src/rt/lifetime.d ---- druntime-orig/src/rt/lifetime.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/lifetime.d 2010-11-05 11:43:02.207267001 +0300 +--- druntime-orig/src/rt/lifetime.d 2010-10-12 07:07:36.000000000 +0400 ++++ druntime/src/rt/lifetime.d 2010-11-07 19:12:13.000000000 +0300 @@ -92,6 +92,18 @@ return gc_malloc(sz); } @@ -1797,52 +1788,25 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. /** * -@@ -670,7 +682,7 @@ - * ti is the type of the resulting array, or pointer to element. - * (For when the array is initialized to 0) - */ --extern (C) ulong _d_newarrayT(TypeInfo ti, size_t length) -+extern (C) void[] _d_newarrayT(TypeInfo ti, size_t length) - { - ulong result; - auto size = ti.next.tsize(); // array element size @@ -702,7 +714,7 @@ __setArrayAllocLength(info, size, isshared); - result = cast(ulong)length + (cast(ulong)cast(size_t)arrstart << 32); + result = arrstart[0..length]; } - return result; + return *cast(void[]*)&result; Loverflow: onOutOfMemoryError(); -@@ -711,7 +723,7 @@ - /** - * For when the array has a non-zero initializer. - */ --extern (C) ulong _d_newarrayiT(TypeInfo ti, size_t length) -+extern (C) void[] _d_newarrayiT(TypeInfo ti, size_t length) - { - ulong result; - auto size = ti.next.tsize(); // array element size @@ -764,7 +776,7 @@ __setArrayAllocLength(info, size, isshared); - result = cast(ulong)length + (cast(ulong)cast(uint)arrstart << 32); + result = arrstart[0..length]; } - return result; + return *cast(void[]*)&result; Loverflow: onOutOfMemoryError(); -@@ -773,7 +785,7 @@ - /** - * - */ --extern (C) ulong _d_newarraymT(TypeInfo ti, int ndims, ...) -+extern (C) void[] _d_newarraymT(TypeInfo ti, int ndims, ...) - { - ulong result; - -@@ -823,14 +835,14 @@ +@@ -823,7 +835,7 @@ } va_end(q); } @@ -1851,14 +1815,6 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } - /** - * - */ --extern (C) ulong _d_newarraymiT(TypeInfo ti, int ndims, ...) -+extern (C) void[] _d_newarraymiT(TypeInfo ti, int ndims, ...) - { - ulong result; - @@ -881,7 +893,7 @@ } va_end(q); @@ -1953,8 +1909,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/memory.d druntime/src/rt/memory.d ---- druntime-orig/src/rt/memory.d 2010-08-05 09:55:22.000000000 +0400 -+++ druntime/src/rt/memory.d 2010-11-06 19:35:02.518720000 +0300 +--- druntime-orig/src/rt/memory.d 2010-10-11 00:37:52.000000000 +0400 ++++ druntime/src/rt/memory.d 2010-11-07 19:11:32.000000000 +0300 @@ -12,6 +12,8 @@ */ module rt.memory; @@ -1964,7 +1920,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. private { -@@ -213,3 +215,616 @@ +@@ -230,3 +232,616 @@ static assert( false, "Operating system not supported." ); } } @@ -2581,7 +2537,6 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +{ + static assert( false, "Compiler not supported." ); +} -\ No newline at end of file diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/qsort.d druntime/src/rt/qsort.d --- druntime-orig/src/rt/qsort.d 2010-08-05 05:39:06.000000000 +0400 +++ druntime/src/rt/qsort.d 2010-11-04 17:49:07.000000000 +0300 diff --git a/gen/toir.cpp b/gen/toir.cpp index 78d4bbf4..3b8f5473 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2786,15 +2786,20 @@ DValue* TupleExp::toElem(IRState *p) for (size_t i = 0; i < exps->dim; i++) { Expression *el = (Expression *)exps->data[i]; - DValue* ep = el->toElem(p); - types[i] = ep->getRVal()->getType(); + types[i] = DtoTypeNotVoid(el->type); } LLValue *val = DtoRawAlloca(LLStructType::get(gIR->context(), types),0, "tuple"); for (size_t i = 0; i < exps->dim; i++) { Expression *el = (Expression *)exps->data[i]; DValue* ep = el->toElem(p); - DtoStore(ep->getRVal(), DtoGEPi(val,0,i)); + LLValue *gep = DtoGEPi(val,0,i); + if (el->type->ty == Tstruct) + DtoStore(DtoLoad(ep->getRVal()), gep); + else if (el->type->ty != Tvoid) + DtoStore(ep->getRVal(), gep); + else + DtoStore(LLConstantInt::get(LLType::getInt8Ty(gIR->context()), 0, false), gep); } return new DImValue(type, val); } diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 7a4b967c..e10f66d1 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -117,6 +117,10 @@ const LLType* DtoType(Type* t) // aggregates case Tstruct: { TypeStruct* ts = (TypeStruct*)t; +#if 1 + if (t != ts->sym->type) // TODO: interesting... why does it happen? + ts->sym->type->irtype = NULL; // set irtype to NULL, so IrTypeStruct constructor would not assert... +#endif t->irtype = new IrTypeStruct(ts->sym); return t->irtype->buildType(); } diff --git a/gen/typinf.cpp b/gen/typinf.cpp index 1ff705a6..977d3116 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -661,7 +661,7 @@ void TypeInfoStructDeclaration::llvmDefine() ClassDeclaration* tscd = Type::typeinfostruct; - assert(tscd->fields.dim == 10); + assert(tscd->fields.dim == 11); // const(MemberInfo[]) function(in char[]) xgetMembers; VarDeclaration* xgetMembers = (VarDeclaration*)tscd->fields.data[7]; @@ -674,6 +674,9 @@ void TypeInfoStructDeclaration::llvmDefine() //void function(void*) xpostblit; VarDeclaration* xpostblit = (VarDeclaration*)tscd->fields.data[9]; b.push_null(xpostblit->type); + + //uint m_align; + b.push_uint(0); #endif // finish diff --git a/ir/irstruct.cpp b/ir/irstruct.cpp index 4a627a9b..118bdca5 100644 --- a/ir/irstruct.cpp +++ b/ir/irstruct.cpp @@ -149,7 +149,8 @@ LLConstant * IrStruct::createStructDefaultInitializer() assert(type->ty == Tstruct && "cannot build struct default initializer for non struct type"); - IrTypeStruct* ts = type->irtype->isStruct(); + DtoType(type); + IrTypeStruct* ts = stripModifiers(type)->irtype->isStruct(); assert(ts); // start at offset zero diff --git a/phobos.patch b/phobos.patch index 751759e3..4a33e826 100644 --- a/phobos.patch +++ b/phobos.patch @@ -1,7 +1,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/concurrency.d phobos/std/concurrency.d ---- phobos-orig/std/concurrency.d 2010-09-17 00:27:48.000000000 +0400 -+++ phobos/std/concurrency.d 2010-11-02 21:33:03.417359999 +0300 -@@ -342,9 +342,10 @@ +--- phobos-orig/std/concurrency.d 2010-10-29 05:54:44.000000000 +0400 ++++ phobos/std/concurrency.d 2010-11-07 19:26:52.000000000 +0300 +@@ -359,9 +359,10 @@ owner = ownerTid; fn( args ); } @@ -14,18 +14,18 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. return spawnTid; } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/conv.d phobos/std/conv.d ---- phobos-orig/std/conv.d 2010-09-17 00:27:48.000000000 +0400 -+++ phobos/std/conv.d 2010-11-04 13:24:59.758325002 +0300 -@@ -1395,7 +1395,7 @@ +--- phobos-orig/std/conv.d 2010-10-29 05:54:44.000000000 +0400 ++++ phobos/std/conv.d 2010-11-08 15:54:33.109464001 +0300 +@@ -1405,7 +1405,7 @@ else // not hex { - if (toupper(p.front) == 'N') + if (toupper(p.front) == 'N' && !startsWithZero) - { + { // nan enforce((p.popFront(), !p.empty && toupper(p.front) == 'A') && (p.popFront(), !p.empty && toupper(p.front) == 'N'), -@@ -3191,6 +3191,11 @@ +@@ -3243,6 +3243,11 @@ T toImpl(T, S)(S d) if (is(Unqual!S == double) && isSomeString!(T)) { //alias Unqual!(ElementType!T) Char; @@ -38,9 +38,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. int len = sprintf(buffer.ptr, "%g", d); return to!T(buffer[0 .. len].dup); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/format.d phobos/std/format.d ---- phobos-orig/std/format.d 2010-09-17 00:27:48.000000000 +0400 -+++ phobos/std/format.d 2010-11-04 18:17:53.483219002 +0300 -@@ -2531,20 +2531,42 @@ +--- phobos-orig/std/format.d 2010-10-29 05:54:44.000000000 +0400 ++++ phobos/std/format.d 2010-11-07 19:26:52.000000000 +0300 +@@ -2582,20 +2582,42 @@ FLprecision = 0x80, } @@ -95,8 +95,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. void formatArg(char fc) diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/functional.d phobos/std/functional.d ---- phobos-orig/std/functional.d 2010-09-17 00:27:48.000000000 +0400 -+++ phobos/std/functional.d 2010-10-29 12:01:35.285035001 +0400 +--- phobos-orig/std/functional.d 2010-10-29 05:54:44.000000000 +0400 ++++ phobos/std/functional.d 2010-11-07 19:26:52.000000000 +0300 @@ -713,6 +713,13 @@ assert(dg_pure_nothrow() == 7); //assert(dg_pure_nothrow_safe() == 8); @@ -119,9 +119,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + } } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/internal/math/biguintx86.d phobos/std/internal/math/biguintx86.d ---- phobos-orig/std/internal/math/biguintx86.d 2010-09-17 00:27:48.000000000 +0400 -+++ phobos/std/internal/math/biguintx86.d 2010-10-26 14:08:51.480925001 +0400 -@@ -733,7 +733,10 @@ +--- phobos-orig/std/internal/math/biguintx86.d 2010-10-29 05:54:44.000000000 +0400 ++++ phobos/std/internal/math/biguintx86.d 2010-11-07 19:26:52.000000000 +0300 +@@ -734,7 +734,10 @@ // EDI = dest // ESI = src @@ -133,7 +133,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. version(D_PIC) { enum { zero = 0 } } else { -@@ -767,7 +770,10 @@ +@@ -768,7 +771,10 @@ jnz L_enter_odd; } // Main loop, with entry point for even length @@ -145,7 +145,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. asm { mov EAX, EBP; // get final carry pop EBP; -@@ -777,6 +783,9 @@ +@@ -778,6 +784,9 @@ ret 5*4; } L_enter_odd: @@ -156,8 +156,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/math.d phobos/std/math.d ---- phobos-orig/std/math.d 2010-09-17 00:27:48.000000000 +0400 -+++ phobos/std/math.d 2010-11-07 17:42:39.390374001 +0300 +--- phobos-orig/std/math.d 2010-10-29 05:54:44.000000000 +0400 ++++ phobos/std/math.d 2010-11-07 19:26:52.000000000 +0300 @@ -276,7 +276,7 @@ assert(abs(71.6Li) == 71.6L); assert(abs(-56) == 56); @@ -308,7 +308,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. /** Compute the value of an integer x, raised to the power of a positive diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/openrj.d phobos/std/openrj.d --- phobos-orig/std/openrj.d 2009-09-03 12:01:40.000000000 +0400 -+++ phobos/std/openrj.d 2010-10-26 13:17:37.480925001 +0400 ++++ phobos/std/openrj.d 2010-10-26 13:17:37.000000000 +0400 @@ -620,11 +620,11 @@ /** * @@ -352,8 +352,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. result = dg(field); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/outbuffer.d phobos/std/outbuffer.d ---- phobos-orig/std/outbuffer.d 2010-09-17 00:27:48.000000000 +0400 -+++ phobos/std/outbuffer.d 2010-11-05 13:59:42.227267001 +0300 +--- phobos-orig/std/outbuffer.d 2010-10-29 05:54:44.000000000 +0400 ++++ phobos/std/outbuffer.d 2010-11-05 13:59:42.000000000 +0300 @@ -308,8 +308,15 @@ void printf(string format, ...) { diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 67ca541c..a43729a5 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -109,6 +109,7 @@ elseif(D_VERSION EQUAL 2) list(REMOVE_ITEM ZLIB_C ${PHOBOS2_DIR}/etc/c/zlib/minigzip.c ${PHOBOS2_DIR}/etc/c/zlib/example.c + ${PHOBOS2_DIR}/etc/c/zlib/gzio.c ) if(WIN32) file(GLOB PHOBOS2_D_WIN ${PHOBOS2_DIR}/std/windows/*.d) From c3ea7b27c64bc3dfacc669a4ba500692ad7db81c Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 14 Dec 2010 14:35:48 +0300 Subject: [PATCH 27/31] Work on debug --- dmd/declaration.h | 4 ++++ dmd2/declaration.h | 4 ++++ gen/llvmhelpers.cpp | 7 +++++++ gen/todebug.cpp | 42 +++++++++++++++++++++++++++--------------- gen/todebug.h | 3 +++ ir/irfunction.h | 1 + 6 files changed, 46 insertions(+), 15 deletions(-) diff --git a/dmd/declaration.h b/dmd/declaration.h index 02c60be3..bda5820d 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -19,6 +19,7 @@ #include #include #include +#include #endif #include "dsymbol.h" @@ -350,6 +351,9 @@ struct VarDeclaration : Declaration /// This var is used by a naked function. bool nakedUse; + + // debug description + llvm::DIVariable debugVariable; #endif }; diff --git a/dmd2/declaration.h b/dmd2/declaration.h index e7c8f920..2f8551b4 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -19,6 +19,7 @@ #include #include #include +#include #endif #include "dsymbol.h" @@ -347,6 +348,9 @@ struct VarDeclaration : Declaration /// This var is used by a naked function. bool nakedUse; + + // debug description + llvm::DIVariable debugVariable; #endif }; diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 40eb39f3..4993eefa 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -470,6 +470,13 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs) } gIR->ir->CreateStore(r, l); } + + #ifndef DISABLE_DEBUG_INFO + DVarValue *var = lhs->isVar(); + VarDeclaration *varDecl = var ? var->var : 0; + if (global.params.symdebug && varDecl && varDecl->debugVariable) + DtoDwarfValue(rhs->getRVal(), lhs->isVar()->var); + #endif } /****************************************************************************************/ diff --git a/gen/todebug.cpp b/gen/todebug.cpp index 043bc721..cd69b861 100644 --- a/gen/todebug.cpp +++ b/gen/todebug.cpp @@ -114,7 +114,7 @@ static llvm::DIDerivedType dwarfDerivedType(Type* type, llvm::DICompileUnit comp return gIR->difactory.CreateDerivedType( DW_TAG_pointer_type, // tag compileUnit, // context - "", // name + type->toChars(), // name DtoDwarfFile(Loc(gIR->dmodule, 0), DtoDwarfCompileUnit(gIR->dmodule)), // file 0, // line number getTypeBitSize(T), // size (bits) @@ -350,11 +350,12 @@ static llvm::DIVariable dwarfVariable(VarDeclaration* vd, llvm::DIType type) return gIR->difactory.CreateVariable( tag, // tag - gIR->func()->diSubprogram, // context + gIR->func()->diLexicalBlock, // context vd->toChars(), // name DtoDwarfFile(vd->loc, DtoDwarfCompileUnit(getDefinedModule(vd))), // file vd->loc.linnum, // line num - type // type + type, // type + true // preserve ); } @@ -408,10 +409,10 @@ void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd) return; // unsupported // get variable description - llvm::DIVariable VD = dwarfVariable(vd, TD); + vd->debugVariable = dwarfVariable(vd, TD); // declare - dwarfDeclare(ll, VD); + dwarfDeclare(ll, vd->debugVariable); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -447,7 +448,6 @@ llvm::DICompileUnit DtoDwarfCompileUnit(Module* m) m->srcfile->name->toChars(), srcpath, "LDC (http://www.dsource.org/projects/ldc)", -//FIXME: What do these two mean? gIR->dmodule == m, // isMain, false // isOptimized ); @@ -464,6 +464,7 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd) llvm::DICompileUnit context = DtoDwarfCompileUnit(gIR->dmodule); llvm::DIFile file = DtoDwarfFile(fd->loc, DtoDwarfCompileUnit(getDefinedModule(fd))); + Type *retType = ((TypeFunction*)fd->type)->next; // FIXME: duplicates ? return gIR->difactory.CreateSubprogram( @@ -473,10 +474,14 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd) fd->mangle(), // linkage name file, // file fd->loc.linnum, // line no -//FIXME: what's this type for? - llvm::DIType(NULL), // type + dwarfTypeDescription(retType, context, NULL), // type fd->protection == PROTprivate, // is local to unit - gIR->dmodule == getDefinedModule(fd) // isdefinition + gIR->dmodule == getDefinedModule(fd), // isdefinition + 0, 0, // VK, Index + llvm::DIType(), + false, // isArtificial + false, // isOptimized + fd->ir.irFunc->func ); } @@ -497,8 +502,7 @@ llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char mangledname, // linkage name DtoDwarfFile(Loc(gIR->dmodule, 0), context), // compile unit 0, // line no -//FIXME: what's this type for? - llvm::DIType(NULL), // type + llvm::DIType(NULL), // return type. TODO: fill it up true, // is local to unit true // isdefinition ); @@ -523,8 +527,11 @@ void DtoDwarfFuncStart(FuncDeclaration* fd) LOG_SCOPE; assert((llvm::MDNode*)fd->ir.irFunc->diSubprogram != 0); - //TODO: - //gIR->difactory.InsertSubprogramStart(fd->ir.irFunc->diSubprogram, gIR->scopebb()); + fd->ir.irFunc->diLexicalBlock = gIR->difactory.CreateLexicalBlock( + fd->ir.irFunc->diSubprogram, // context + DtoDwarfFile(fd->loc, DtoDwarfCompileUnit(getDefinedModule(fd))), // file + fd->loc.linnum + ); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -535,8 +542,6 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd) LOG_SCOPE; assert((llvm::MDNode*)fd->ir.irFunc->diSubprogram != 0); - //TODO: - //gIR->difactory.InsertRegionEnd(fd->ir.irFunc->diSubprogram, gIR->scopebb()); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -549,4 +554,11 @@ void DtoDwarfStopPoint(unsigned ln) gIR->ir->SetCurrentDebugLocation(loc); } +////////////////////////////////////////////////////////////////////////////////////////////////// + +void DtoDwarfValue(LLValue* var, VarDeclaration* vd) +{ + gIR->difactory.InsertDbgValueIntrinsic(var, 0, vd->debugVariable, gIR->scopebb()); +} + #endif diff --git a/gen/todebug.h b/gen/todebug.h index 1d3922a1..5a4fa757 100644 --- a/gen/todebug.h +++ b/gen/todebug.h @@ -32,6 +32,8 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd); void DtoDwarfStopPoint(unsigned ln); +void DtoDwarfValue(LLValue* var, VarDeclaration* vd); + /** * Emits all things necessary for making debug info for a local variable vd. * @param ll LLVM Value of the variable. @@ -47,6 +49,7 @@ void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd); */ llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd); + #endif // DISABLE_DEBUG_INFO #endif // LDC_GEN_TODEBUG_H diff --git a/ir/irfunction.h b/ir/irfunction.h index 02b79fbd..055233b2 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -98,6 +98,7 @@ struct IrFunction : IrBase llvm::Value* _argptr; llvm::DISubprogram diSubprogram; + llvm::DILexicalBlock diLexicalBlock; }; #endif From 0b4b009a69270d1708d3ce08e01c6659320a278a Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 14 Dec 2010 14:35:52 +0300 Subject: [PATCH 28/31] Fixed some unresolved symbols --- gen/tollvm.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index e10f66d1..7bffb3cc 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -303,8 +303,9 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) // The following breaks for nested naked functions and other declarations, so check for that. bool skipNestedCheck = !mustDefineSymbol(sym); - if (FuncDeclaration* fd = sym->isFuncDeclaration()) - skipNestedCheck = (fd->naked != 0); + if (!skipNestedCheck) + if (FuncDeclaration* fd = sym->isFuncDeclaration()) + skipNestedCheck = (fd->naked != 0); // Any symbol nested in a function can't be referenced directly from // outside that function, so we can give such symbols internal linkage. @@ -353,10 +354,10 @@ llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym) llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym) { - if (isAvailableExternally(sym) && mustDefineSymbol(sym)) - return llvm::GlobalValue::AvailableExternallyLinkage; if (needsTemplateLinkage(sym)) return templateLinkage; + else if (isAvailableExternally(sym) && mustDefineSymbol(sym)) + return llvm::GlobalValue::AvailableExternallyLinkage; else return llvm::GlobalValue::ExternalLinkage; } From 3eb6b5e8c88ed231c08cd26a9a2f0f25b9177fea Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 14 Dec 2010 14:35:52 +0300 Subject: [PATCH 29/31] Fixed a crash when compiling test runnable/A16. --- gen/functions.cpp | 12 +-- gen/llvmhelpers.cpp | 1 - gen/nested.cpp | 215 +++++++++++++++++++++++++++----------------- ir/irfunction.cpp | 1 + ir/irfunction.h | 1 + 5 files changed, 134 insertions(+), 96 deletions(-) diff --git a/gen/functions.cpp b/gen/functions.cpp index a6c84a29..0c1bd292 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -529,7 +529,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) #endif // we never reference parameters of function prototypes std::string str; - if (!declareOnly) + // if (!declareOnly) { // name parameters llvm::Function::arg_iterator iarg = func->arg_begin(); @@ -772,16 +772,6 @@ void DtoDefineFunction(FuncDeclaration* fd) } #endif -#if DMDV2 - // fill nestedVars - size_t nnest = fd->closureVars.dim; - for (size_t i = 0; i < nnest; ++i) - { - VarDeclaration* vd = (VarDeclaration*)fd->closureVars.data[i]; - fd->nestedVars.insert(vd); - } -#endif - DtoCreateNestedContext(fd); #if DMDV2 diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 4993eefa..02aafeb6 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -958,7 +958,6 @@ DValue* DtoDeclarationExp(Dsymbol* declaration) #endif Logger::println("has nestedref set"); assert(vd->ir.irLocal); - DtoNestedInit(vd); } // normal stack variable, allocate storage on the stack if it has not already been done diff --git a/gen/nested.cpp b/gen/nested.cpp index 27a9d47d..cd024e85 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -68,6 +68,8 @@ static FuncDeclaration* getParentFunc(Dsymbol* sym, bool stopOnStatic) { return (parent ? parent->isFuncDeclaration() : NULL); } +static void DtoCreateNestedContextType(FuncDeclaration* fd); + DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) { Logger::println("DtoNestedVariable for %s @ %s", vd->toChars(), loc.toChars()); @@ -109,6 +111,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) ctx = irfunc->nestArg; assert(ctx); + DtoCreateNestedContextType(vdparent->isFuncDeclaration()); assert(vd->ir.irLocal); //////////////////////////////////// @@ -270,14 +273,18 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) if (nestedCtx == NCHybrid) { if (FuncDeclaration* symfd = sym->isFuncDeclaration()) { // Make sure we've had a chance to analyze nested context usage + #if DMDV2 + DtoCreateNestedContextType(symfd); + #else DtoDefineFunction(symfd); - + #endif + // if this is for a function that doesn't access variables from // enclosing scopes, it doesn't matter what we pass. // Tell LLVM about it by passing an 'undef'. if (symfd && symfd->ir.irFunc->depth == -1) return llvm::UndefValue::get(getVoidPtrType()); - + // If sym is a nested function, and it's parent context is different than the // one we got, adjust it. if (FuncDeclaration* fd = getParentFunc(symfd, true)) { @@ -289,13 +296,13 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) assert(ctxfd && "Context from outer function, but no outer function?"); } Logger::println("Context is from %s", ctxfd->toChars()); - + unsigned neededDepth = fd->ir.irFunc->depth; unsigned ctxDepth = ctxfd->ir.irFunc->depth; - + Logger::cout() << "Needed depth: " << neededDepth << '\n'; Logger::cout() << "Context depth: " << ctxDepth << '\n'; - + if (neededDepth >= ctxDepth) { // assert(neededDepth <= ctxDepth + 1 && "How are we going more than one nesting level up?"); // fd needs the same context as we do, so all is well @@ -313,10 +320,125 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) return val; } +static void DtoCreateNestedContextType(FuncDeclaration* fd) { + Logger::println("DtoCreateNestedContextType for %s", fd->toChars()); + LOG_SCOPE + + if (fd->ir.irFunc->nestedContextCreated) + return; + fd->ir.irFunc->nestedContextCreated = true; + +#if DMDV2 + DtoDeclareFunction(fd); + if (fd->nestedVars.empty()) { + // fill nestedVars + size_t nnest = fd->closureVars.dim; + for (size_t i = 0; i < nnest; ++i) + { + VarDeclaration* vd = (VarDeclaration*)fd->closureVars.data[i]; + fd->nestedVars.insert(vd); + } + } +#endif + if (nestedCtx == NCHybrid) { + // construct nested variables array + if (!fd->nestedVars.empty()) + { + Logger::println("has nested frame"); + // start with adding all enclosing parent frames until a static parent is reached + + const LLStructType* innerFrameType = NULL; + unsigned depth = -1; + if (!fd->isStatic()) { + if (FuncDeclaration* parfd = getParentFunc(fd, true)) { + innerFrameType = parfd->ir.irFunc->frameType; + if (innerFrameType) + depth = parfd->ir.irFunc->depth; + } + } + fd->ir.irFunc->depth = ++depth; + + Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n'; + + typedef std::vector TypeVec; + TypeVec types; + if (depth != 0) { + assert(innerFrameType); + // Add frame pointer types for all but last frame + if (depth > 1) { + for (unsigned i = 0; i < (depth - 1); ++i) { + types.push_back(innerFrameType->getElementType(i)); + } + } + // Add frame pointer type for last frame + types.push_back(LLPointerType::getUnqual(innerFrameType)); + } + + if (Logger::enabled()) { + Logger::println("Frame types: "); + LOG_SCOPE; + for (TypeVec::iterator i = types.begin(); i != types.end(); ++i) + Logger::cout() << **i << '\n'; + } + + // Add the direct nested variables of this function, and update their indices to match. + // TODO: optimize ordering for minimal space usage? + for (std::set::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) + { + VarDeclaration* vd = *i; + if (!vd->ir.irLocal) + vd->ir.irLocal = new IrLocal(vd); + + vd->ir.irLocal->nestedIndex = types.size(); + vd->ir.irLocal->nestedDepth = depth; + if (vd->isParameter()) { + // Parameters already have storage associated with them (to handle byref etc.), + // so handle those cases specially by storing a pointer instead of a value. + assert(vd->ir.irLocal->value); + LLValue* value = vd->ir.irLocal->value; + const LLType* type = value->getType(); + if (llvm::isa(value->getUnderlyingObject())) + // This will be copied to the nesting frame. + type = type->getContainedType(0); + types.push_back(type); + } else if (vd->isRef() || vd->isOut()) { + // Foreach variables can also be by reference, for instance. + types.push_back(DtoType(vd->type->pointerTo())); + } else { + types.push_back(DtoType(vd->type)); + } + if (Logger::enabled()) { + Logger::println("Nested var: %s", vd->toChars()); + Logger::cout() << "of type: " << *types.back() << '\n'; + } + } + + const LLStructType* frameType = LLStructType::get(gIR->context(), types); + gIR->module->addTypeName(std::string("nest.") + fd->toChars(), frameType); + + Logger::cout() << "frameType = " << *frameType << '\n'; + + // Store type in IrFunction + fd->ir.irFunc->frameType = frameType; + } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) { + // Propagate context arg properties if the context arg is passed on unmodified. + DtoCreateNestedContextType(parFunc); + fd->ir.irFunc->frameType = parFunc->ir.irFunc->frameType; + fd->ir.irFunc->depth = parFunc->ir.irFunc->depth; + } + } + else { + assert(0 && "Not implemented yet"); + } +} + + void DtoCreateNestedContext(FuncDeclaration* fd) { Logger::println("DtoCreateNestedContext for %s", fd->toChars()); LOG_SCOPE - + + DtoCreateNestedContextType(fd); + if (nestedCtx == NCArray) { // construct nested variables array if (!fd->nestedVars.empty()) @@ -408,84 +530,9 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { // construct nested variables array if (!fd->nestedVars.empty()) { - Logger::println("has nested frame"); - // start with adding all enclosing parent frames until a static parent is reached - - const LLStructType* innerFrameType = NULL; - unsigned depth = -1; - if (!fd->isStatic()) { - if (FuncDeclaration* parfd = getParentFunc(fd, true)) { - innerFrameType = parfd->ir.irFunc->frameType; - if (innerFrameType) - depth = parfd->ir.irFunc->depth; - } - } - fd->ir.irFunc->depth = ++depth; - - Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n'; - - typedef std::vector TypeVec; - TypeVec types; - if (depth != 0) { - assert(innerFrameType); - // Add frame pointer types for all but last frame - if (depth > 1) { - for (unsigned i = 0; i < (depth - 1); ++i) { - types.push_back(innerFrameType->getElementType(i)); - } - } - // Add frame pointer type for last frame - types.push_back(LLPointerType::getUnqual(innerFrameType)); - } - - if (Logger::enabled()) { - Logger::println("Frame types: "); - LOG_SCOPE; - for (TypeVec::iterator i = types.begin(); i != types.end(); ++i) - Logger::cout() << **i << '\n'; - } - - // Add the direct nested variables of this function, and update their indices to match. - // TODO: optimize ordering for minimal space usage? - for (std::set::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) - { - VarDeclaration* vd = *i; - if (!vd->ir.irLocal) - vd->ir.irLocal = new IrLocal(vd); - - vd->ir.irLocal->nestedIndex = types.size(); - vd->ir.irLocal->nestedDepth = depth; - if (vd->isParameter()) { - // Parameters already have storage associated with them (to handle byref etc.), - // so handle those cases specially by storing a pointer instead of a value. - assert(vd->ir.irLocal->value); - LLValue* value = vd->ir.irLocal->value; - const LLType* type = value->getType(); - if (llvm::isa(value->getUnderlyingObject())) - // This will be copied to the nesting frame. - type = type->getContainedType(0); - types.push_back(type); - } else if (vd->isRef() || vd->isOut()) { - // Foreach variables can also be by reference, for instance. - types.push_back(DtoType(vd->type->pointerTo())); - } else { - types.push_back(DtoType(vd->type)); - } - if (Logger::enabled()) { - Logger::println("Nested var: %s", vd->toChars()); - Logger::cout() << "of type: " << *types.back() << '\n'; - } - } - - const LLStructType* frameType = LLStructType::get(gIR->context(), types); - gIR->module->addTypeName(std::string("nest.") + fd->toChars(), frameType); - - Logger::cout() << "frameType = " << *frameType << '\n'; - - // Store type in IrFunction IrFunction* irfunction = fd->ir.irFunc; - irfunction->frameType = frameType; - + unsigned depth = irfunction->depth; + const llvm::StructType *frameType = irfunction->frameType; // Create frame for current function and append to frames list // FIXME: For D2, this should be a gc_malloc (or similar) call, not alloca // (Note that it'd also require more aggressive copying of @@ -522,7 +569,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { getABITypeAlign(getVoidPtrType())); } // Copy nestArg into framelist; the outer frame is not in the list of pointers - src = DtoBitCast(src, types[depth-1]); + src = DtoBitCast(src, frameType->getContainedType(depth-1)); LLValue* gep = DtoGEPi(frame, 0, depth-1); DtoAlignedStore(src, gep); } diff --git a/ir/irfunction.cpp b/ir/irfunction.cpp index 415dad66..518c85eb 100644 --- a/ir/irfunction.cpp +++ b/ir/irfunction.cpp @@ -144,6 +144,7 @@ IrFunction::IrFunction(FuncDeclaration* fd) nestedVar = NULL; frameType = NULL; depth = -1; + nestedContextCreated = false; _arguments = NULL; _argptr = NULL; diff --git a/ir/irfunction.h b/ir/irfunction.h index 055233b2..2bc13243 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -93,6 +93,7 @@ struct IrFunction : IrBase // number of enclosing functions with variables accessed by nested functions // (-1 if neither this function nor any enclosing ones access variables from enclosing functions) int depth; + bool nestedContextCreated; // holds whether nested context is created llvm::Value* _arguments; llvm::Value* _argptr; From f8bf67dc6e0a99b92a6ccf11ccc988cefdf5d838 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 14 Dec 2010 14:35:52 +0300 Subject: [PATCH 30/31] Fixed a crash when compiling multiple files in one object file --- gen/todebug.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gen/todebug.cpp b/gen/todebug.cpp index cd69b861..393197a6 100644 --- a/gen/todebug.cpp +++ b/gen/todebug.cpp @@ -422,6 +422,8 @@ llvm::DICompileUnit DtoDwarfCompileUnit(Module* m) Logger::println("D to dwarf compile_unit"); LOG_SCOPE; + static bool mainUnitCreated = false; + // we might be generating for an import IrModule* irmod = getIrModule(m); @@ -442,15 +444,18 @@ llvm::DICompileUnit DtoDwarfCompileUnit(Module* m) srcpath = srcpath + '/'; } + bool isMain = !mainUnitCreated && gIR->dmodule == m; // make compile unit irmod->diCompileUnit = gIR->difactory.CreateCompileUnit( global.params.symdebug == 2 ? DW_LANG_C : DW_LANG_D, m->srcfile->name->toChars(), srcpath, "LDC (http://www.dsource.org/projects/ldc)", - gIR->dmodule == m, // isMain, + isMain, // isMain, false // isOptimized ); + if (isMain) + mainUnitCreated = true; return irmod->diCompileUnit; } From e48d0f6b79bd3e07794cda131f4986c88058a195 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Tue, 14 Dec 2010 14:38:46 +0300 Subject: [PATCH 31/31] Fixed test runnable/arrayop --- dmd2/arrayop.c | 6 +++--- gen/tocall.cpp | 22 +++++++++++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/dmd2/arrayop.c b/dmd2/arrayop.c index 92985f39..15cfcc04 100644 --- a/dmd2/arrayop.c +++ b/dmd2/arrayop.c @@ -353,10 +353,10 @@ Expression *BinExp::arrayOp(Scope *sc) fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype); fd->fbody = fbody; fd->protection = PROTpublic; - fd->linkage = LINKd; + fd->linkage = LINKd; - // special attention for array ops - fd->isArrayOp = true; + // special attention for array ops + fd->isArrayOp = true; sc->module->importedFrom->members->push(fd); diff --git a/gen/tocall.cpp b/gen/tocall.cpp index 33be5ef8..f3854fc0 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -424,13 +424,29 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* LLSmallVector attrptr(n, 0); + std::vector argvals; + if (dfnval && dfnval->func->isArrayOp) { + // slightly different approach for array operators + for (int i=n-1; i>=0; --i) { + Parameter* fnarg = Parameter::getNth(tf->parameters, i); + assert(fnarg); + DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); + argvals.insert(argvals.begin(), argval); + } + } else { + for (int i=0; iparameters, i); + assert(fnarg); + DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); + argvals.push_back(argval); + } + } + // do formal params int beg = argiter-argbegin; for (int i=0; iparameters, i); - assert(fnarg); - DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); + DValue* argval = argvals.at(i); #if 0 if (Logger::enabled()) {