diff --git a/dmd2/declaration.c b/dmd2/declaration.c index 5f0dd6f1..4cb6c42e 100644 --- a/dmd2/declaration.c +++ b/dmd2/declaration.c @@ -525,7 +525,7 @@ void AliasDeclaration::semantic(Scope *sc) { FuncAliasDeclaration *fa = new FuncAliasDeclaration(f); #if IN_LLVM - fa->importprot = importprot; + fa->importprot = importprot; #endif if (!fa->overloadInsert(overnext)) ScopeDsymbol::multiplyDefined(0, f, overnext); diff --git a/dmd2/expression.c b/dmd2/expression.c index 3a866751..a9074925 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -6454,8 +6454,12 @@ Expression *DelegateExp::semantic(Scope *sc) { m = sc->module; e1 = e1->semantic(sc); - // LDC we need a copy as we store the LLVM tpye in TypeFunction, and delegate/members have different types for 'this' - type = new TypeDelegate(func->type->syntaxCopy()); +#if IN_LLVM + // LDC we need a copy as we store the LLVM type in TypeFunction, and delegate/members have different types for 'this' + type = new TypeDelegate(func->type->syntaxCopy()); +#else + type = new TypeDelegate(func->type); +#endif type = type->semantic(loc, sc); AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration(); if (func->needThis()) @@ -7416,7 +7420,7 @@ Expression *AddrExp::semantic(Scope *sc) if (f) { -#if !IN_LLVM +#if IN_LLVM if (f->isIntrinsic()) { error("cannot take the address of intrinsic function %s", e1->toChars()); diff --git a/dmd2/expression.h b/dmd2/expression.h index 7c9e369e..27cbb8c5 100644 --- a/dmd2/expression.h +++ b/dmd2/expression.h @@ -1124,6 +1124,7 @@ struct CallExp : UnaExp #if IN_LLVM DValue* toElem(IRState* irs); + void cacheLvalue(IRState* irs); #endif }; diff --git a/dmd2/func.c b/dmd2/func.c index 35c1ff27..f6020c1f 100644 --- a/dmd2/func.c +++ b/dmd2/func.c @@ -880,8 +880,8 @@ void FuncDeclaration::semantic3(Scope *sc) #if !IN_LLVM sc2->tf = NULL; #else - sc2->enclosingFinally = NULL; - sc2->enclosingScopeExit = NULL; + sc2->enclosingFinally = NULL; + sc2->enclosingScopeExit = NULL; #endif sc2->noctor = 0; @@ -1012,7 +1012,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (f->parameters) { for (size_t i = 0; i < Parameter::dim(f->parameters); i++) - { Parameter *arg = (Parameter *)Parameter::getNth(f->parameters, i); + { Parameter *arg = (Parameter *)Parameter::getNth(f->parameters, i); Type* nw = arg->type->semantic(0, sc); if (arg->type != nw) { arg->type = nw; diff --git a/dmd2/interpret.c b/dmd2/interpret.c index 4bdc7995..ec2a5c73 100644 --- a/dmd2/interpret.c +++ b/dmd2/interpret.c @@ -1252,12 +1252,10 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) if (v) { #if DMDV2 -#if !IN_LLVM // TODO: /* Magic variable __ctfe always returns true when interpreting */ if (v->ident == Id::ctfe) return new IntegerExp(loc, 1, Type::tbool); -#endif if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value) #else if (v->isConst() && v->init) diff --git a/dmd2/mangle.c b/dmd2/mangle.c index 144f0185..e6429a9a 100644 --- a/dmd2/mangle.c +++ b/dmd2/mangle.c @@ -114,7 +114,7 @@ char *Declaration::mangle() break; #if IN_LLVM - case LINKintrinsic: + case LINKintrinsic: #endif case LINKc: case LINKwindows: diff --git a/dmd2/mtype.c b/dmd2/mtype.c index 8f4b1521..6c67f127 100644 --- a/dmd2/mtype.c +++ b/dmd2/mtype.c @@ -1538,7 +1538,7 @@ Type *Type::merge() //if (next) //next = next->merge(); - toDecoBuffer(&buf, false); + toDecoBuffer(&buf, 0, false); sv = stringtable.update((char *)buf.data, buf.offset); if (sv->ptrvalue) { t = (Type *) sv->ptrvalue; @@ -1557,7 +1557,7 @@ Type *Type::merge() // or Type::equals fails, which breaks a bunch of stuff, // like covariant member function overloads. OutBuffer mangle; - toDecoBuffer(&mangle, true); + toDecoBuffer(&mangle, 0, true); StringValue* sv2 = deco_stringtable.update((char *)mangle.data, mangle.offset); if (sv2->ptrvalue) { Type* t2 = (Type *) sv2->ptrvalue; @@ -1986,7 +1986,7 @@ Identifier *Type::getTypeInfoIdent(int internal) buf.writeByte(mangleChar[((TypeArray *)this)->next->ty]); } else - toDecoBuffer(&buf, true); + toDecoBuffer(&buf, 0, true); len = buf.offset; name = (char *)alloca(19 + sizeof(len) * 3 + len + 1); buf.writeByte(0); diff --git a/dmd2/optimize.c b/dmd2/optimize.c index 449f8848..35abcd02 100644 --- a/dmd2/optimize.c +++ b/dmd2/optimize.c @@ -557,9 +557,6 @@ Expression *CastExp::optimize(int result) e1->type->nextOf()->size() == type->nextOf()->size() ) { - // LDC make a copy before adjusting type to avoid - // messing up the type of an existing initializer - e1 = e1->syntaxCopy(); Expression *e = e1->castTo(NULL, type); if (X) printf(" returning1 %s\n", e->toChars()); return e; diff --git a/dmd2/statement.c b/dmd2/statement.c index 541e5fb9..9c0ef3e3 100644 --- a/dmd2/statement.c +++ b/dmd2/statement.c @@ -1849,39 +1849,39 @@ Lagain: /* Call: * _aaApply(aggr, keysize, flde) */ - //LDC: Build arguments. - static FuncDeclaration *aaApply2_fd = NULL; - static TypeDelegate* aaApply2_dg; - if(!aaApply2_fd) { - Parameters* args = new Parameters; - args->push(new Parameter(STCin, Type::tvoid->pointerTo(), NULL, NULL)); - args->push(new Parameter(STCin, Type::tsize_t, NULL, NULL)); - Parameters* dgargs = new Parameters; - dgargs->push(new Parameter(STCin, Type::tvoidptr, NULL, NULL)); - dgargs->push(new Parameter(STCin, Type::tvoidptr, NULL, NULL)); - aaApply2_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd)); - args->push(new Parameter(STCin, aaApply2_dg, NULL, NULL)); - aaApply2_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply2"); - } - static FuncDeclaration *aaApply_fd = NULL; - static TypeDelegate* aaApply_dg; - if(!aaApply_fd) { - Parameters* args = new Parameters; - args->push(new Parameter(STCin, Type::tvoid->pointerTo(), NULL, NULL)); - args->push(new Parameter(STCin, Type::tsize_t, NULL, NULL)); - Parameters* dgargs = new Parameters; - dgargs->push(new Parameter(STCin, Type::tvoidptr, NULL, NULL)); - aaApply_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd)); - args->push(new Parameter(STCin, aaApply_dg, NULL, NULL)); - aaApply_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply"); - } - if (dim == 2) { - fdapply = aaApply2_fd; - fldeTy = aaApply2_dg; - } else { - fdapply = aaApply_fd; - fldeTy = aaApply_dg; - } + //LDC: Build arguments. + static FuncDeclaration *aaApply2_fd = NULL; + static TypeDelegate* aaApply2_dg; + if(!aaApply2_fd) { + Parameters* args = new Parameters; + args->push(new Parameter(STCin, Type::tvoid->pointerTo(), NULL, NULL)); + args->push(new Parameter(STCin, Type::tsize_t, NULL, NULL)); + Parameters* dgargs = new Parameters; + dgargs->push(new Parameter(STCin, Type::tvoidptr, NULL, NULL)); + dgargs->push(new Parameter(STCin, Type::tvoidptr, NULL, NULL)); + aaApply2_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd)); + args->push(new Parameter(STCin, aaApply2_dg, NULL, NULL)); + aaApply2_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply2"); + } + static FuncDeclaration *aaApply_fd = NULL; + static TypeDelegate* aaApply_dg; + if(!aaApply_fd) { + Parameters* args = new Parameters; + args->push(new Parameter(STCin, Type::tvoid->pointerTo(), NULL, NULL)); + args->push(new Parameter(STCin, Type::tsize_t, NULL, NULL)); + Parameters* dgargs = new Parameters; + dgargs->push(new Parameter(STCin, Type::tvoidptr, NULL, NULL)); + aaApply_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd)); + args->push(new Parameter(STCin, aaApply_dg, NULL, NULL)); + aaApply_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply"); + } + if (dim == 2) { + fdapply = aaApply2_fd; + fldeTy = aaApply2_dg; + } else { + fdapply = aaApply_fd; + fldeTy = aaApply_dg; + } ec = new VarExp(0, fdapply); Expressions *exps = new Expressions(); exps->push(aggr); @@ -1890,12 +1890,12 @@ Lagain: exps->push(new IntegerExp(0, keysize, Type::tsize_t)); #if IN_LLVM - // LDC paint delegate argument to the type runtime expects - if (!fldeTy->equals(flde->type)) - { - flde = new CastExp(loc, flde, flde->type); - flde->type = fldeTy; - } + // LDC paint delegate argument to the type runtime expects + if (!fldeTy->equals(flde->type)) + { + flde = new CastExp(loc, flde, flde->type); + flde->type = fldeTy; + } #endif exps->push(flde); e = new CallExp(loc, ec, exps); diff --git a/gen/abi.cpp b/gen/abi.cpp index 8d024a39..ab0af4c9 100644 --- a/gen/abi.cpp +++ b/gen/abi.cpp @@ -151,6 +151,10 @@ struct X86TargetABI : TargetABI bool returnInArg(TypeFunction* tf) { +#if DMDV2 + if (tf->isref) + return false; +#endif Type* rt = tf->next->toBasetype(); // D only returns structs on the stack if (tf->linkage == LINKd) @@ -287,6 +291,10 @@ struct UnknownTargetABI : TargetABI { bool returnInArg(TypeFunction* tf) { +#if DMDV2 + if (tf->isref) + return false; +#endif return (tf->next->toBasetype()->ty == Tstruct); } diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 9e33b077..4289f894 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -804,6 +804,29 @@ DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2) } } +////////////////////////////////////////////////////////////////////////////////////////// + +DSliceValue* DtoAppendDChar(DValue* arr, Expression* exp) +{ + Logger::println("DtoCatAssignArray"); + LOG_SCOPE; + Type *arrayType = arr->getType(); + DValue* valueToAppend = exp->toElem(gIR); + + // Prepare arguments + LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_arrayappendcd"); + LLSmallVector args; + // ref char[] x + args.push_back(DtoBitCast(arr->getLVal(), fn->getFunctionType()->getParamType(0))); + // dchar c + args.push_back(DtoBitCast(valueToAppend->getRVal(), fn->getFunctionType()->getParamType(1))); + + // Call _d_arrayappendcd + LLValue* newArray = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".appendedArray").getInstruction(); + + return getSlice(arrayType, newArray); +} + ////////////////////////////////////////////////////////////////////////////////////////// // helper for eq and cmp static LLValue* DtoArrayEqCmp_impl(Loc& loc, const char* func, DValue* l, DValue* r, bool useti) @@ -1127,14 +1150,11 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to) LLConstant* nul = getNullPtr(ptr->getType()); rval = gIR->ir->CreateICmpNE(ptr, nul, "tmp"); } - else if (fromtype->nextOf()->ty == Tvoid) { - // TODO: + else { rval = DtoArrayPtr(u); rval = DtoBitCast(rval, getPtrToType(tolltype)); - rval = DtoLoad(rval); - } - else { - assert(0); + if (totype->ty != Tstruct) + rval = DtoLoad(rval); } if (isslice) { diff --git a/gen/arrays.h b/gen/arrays.h index cfc66ab0..b7e2a0ed 100644 --- a/gen/arrays.h +++ b/gen/arrays.h @@ -28,6 +28,7 @@ void DtoCatAssignElement(Loc& loc, Type* type, DValue* arr, Expression* exp); DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp); DSliceValue* DtoCatArrays(Type* type, Expression* e1, Expression* e2); DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2); +DSliceValue* DtoAppendDChar(DValue* arr, Expression* exp); void DtoStaticArrayCopy(LLValue* dst, LLValue* src); diff --git a/gen/functions.cpp b/gen/functions.cpp index e48b7e45..d1671f8c 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -64,11 +64,21 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest lidx++; } // sext/zext return - else if (unsigned se = DtoShouldExtend(rt)) + else { - a = se; + Type *t = rt; +#if DMDV2 + if (f->isref) + t = t->pointerTo(); +#endif + if (unsigned se = DtoShouldExtend(t)) + a = se; } +#if DMDV2 + fty.ret = new IrFuncTyArg(rt, f->isref, a); +#else fty.ret = new IrFuncTyArg(rt, false, a); +#endif } lidx++; @@ -146,6 +156,9 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd); TypeDelegate *ltd = new TypeDelegate(ltf); argtype = ltd; +#if DMDV2 + byref = byref && arg->type->toBasetype()->ty != Tsarray; +#endif } // byval else if (abi->passByVal(byref ? argtype->pointerTo() : argtype)) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 12eef5e2..1c57f036 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -767,7 +767,7 @@ DValue* DtoPaintType(Loc& loc, DValue* val, Type* to) } else { - assert(!val->isLVal()); + // assert(!val->isLVal()); TODO: what is it needed for? assert(DtoType(to) == DtoType(to)); return new DImValue(to, val->getRVal()); } @@ -912,7 +912,17 @@ DValue* DtoDeclarationExp(Dsymbol* declaration) assert(ex->exp); AssignExp* as = ex->exp->isAssignExp(); assert(as && "ref vars must be initialized by an assign exp"); - vd->ir.irLocal->value = as->e2->toElem(gIR)->getLVal(); + DValue *val = as->e2->toElem(gIR); + if (val->isLVal()) + { + vd->ir.irLocal->value = val->getLVal(); + } + else + { + LLValue *newVal = DtoAlloca(val->type); + DtoStore(val->getRVal(), newVal); + vd->ir.irLocal->value = newVal; + } } // referenced by nested delegate? @@ -1033,6 +1043,12 @@ DValue* DtoDeclarationExp(Dsymbol* declaration) DtoDeclarationExp(exp->s); } } + // template + else if (TemplateDeclaration* t = declaration->isTemplateDeclaration()) + { + Logger::println("TemplateDeclaration"); + // do nothing + } // unsupported declaration else { @@ -1223,8 +1239,13 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp) LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp) { +#if DMDV2 + Type* expbase = exp->type->toBasetype()->mutableOf()->merge(); + Type* base = type->toBasetype()->mutableOf()->merge(); +#else Type* expbase = exp->type->toBasetype(); Type* base = type->toBasetype(); +#endif // if not the same basetypes, we won't get the same llvm types either if (!expbase->equals(base)) @@ -1240,7 +1261,7 @@ LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp) } else { - error("cannot yet convert default initializer %s to type %s to %s", exp->toChars(), exp->type->toChars(), type->toChars()); + error("cannot yet convert default initializer %s of type %s to %s", exp->toChars(), exp->type->toChars(), type->toChars()); fatal(); } assert(0); @@ -1504,6 +1525,8 @@ size_t realignOffset(size_t offset, Type* type) Type * stripModifiers( Type * type ) { #if DMDV2 + if (type->ty == Tfunction) + return type; Type *t = type; while (t->mod) { diff --git a/gen/nested.cpp b/gen/nested.cpp index e81d097e..a2ba52c6 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -534,6 +534,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { } } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) { // Propagate context arg properties if the context arg is passed on unmodified. + DtoDeclareFunction(parFunc); fd->ir.irFunc->frameType = parFunc->ir.irFunc->frameType; fd->ir.irFunc->depth = parFunc->ir.irFunc->depth; } diff --git a/gen/runtime.cpp b/gen/runtime.cpp index a734de16..009388cc 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -381,7 +381,15 @@ static void LLVM_D_BuildRuntimeModule() const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); } - + // void[] _d_arrayappendcd(ref char[] x, dchar c) + { + llvm::StringRef fname("_d_arrayappendcd"); + std::vector types; + types.push_back(getPtrToType(stringTy)); + types.push_back(intTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false); + llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } // byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y) { llvm::StringRef fname("_d_arraycatT"); diff --git a/gen/statements.cpp b/gen/statements.cpp index b0426338..80e32ce1 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -97,17 +97,29 @@ void ReturnStatement::toIR(IRState* p) v = LLConstant::getNullValue(p->mainFunc->getReturnType()); else // do abi specific transformations on the return value +#if DMDV2 + v = p->func()->type->fty.putRet(exp->type, exp->toElem(p), p->func()->type->isref); +#else v = p->func()->type->fty.putRet(exp->type, exp->toElem(p)); +#endif if (Logger::enabled()) Logger::cout() << "return value is '" <<*v << "'\n"; IrFunction* f = p->func(); - // Hack around LDC assuming structs are in memory: - // If the function returns a struct, and the return value is a - // pointer to a struct, load from it before returning. - if (f->type->next->ty == Tstruct && isaPointer(v->getType())) { - Logger::println("Loading struct type for return"); + // Hack around LDC assuming structs and static arrays are in memory: + // If the function returns a struct or a static array, and the return + // value is a pointer to a struct or a static array, load from it + // before returning. + int ty = f->type->next->ty; + if (v->getType() != p->topfunc()->getReturnType() && + (ty == Tstruct +#if DMDV2 + || ty == Tsarray +#endif + ) && isaPointer(v->getType())) + { + Logger::println("Loading value for return"); v = DtoLoad(v); } diff --git a/gen/tocall.cpp b/gen/tocall.cpp index b3ebf638..44a37187 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -551,10 +551,17 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* retllval = tf->fty.getRet(tf->next, &dretval); } - // Hack around LDC assuming structs are in memory: - // If the function returns a struct, and the return value is not a - // pointer to a struct, store it to a stack slot before continuing. - if (tf->next->ty == Tstruct && !isaPointer(retllval)) { + // Hack around LDC assuming structs and static arrays are in memory: + // If the function returns a struct or a static array, and the return + // value is not a pointer to a struct or a static array, store it to + // a stack slot before continuing. + int ty = tf->next->ty; + if ((ty == Tstruct && !isaPointer(retllval)) +#if DMDV2 + || (ty == Tsarray && isaArray(retllval)) +#endif + ) + { Logger::println("Storing return value to stack slot"); LLValue* mem = DtoRawAlloca(retllval->getType(), 0); DtoStore(retllval, mem); @@ -608,8 +615,13 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* call.setAttributes(attrlist); // if we are returning through a pointer arg + // or if we are returning a reference // make sure we provide a lvalue back! - if (retinptr) + if (retinptr +#if DMDV2 + || tf->isref +#endif + ) return new DVarValue(resulttype, retllval); return new DImValue(resulttype, retllval); diff --git a/gen/toir.cpp b/gen/toir.cpp index 5775b34b..9c3b34f3 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -92,6 +92,14 @@ DValue* VarExp::toElem(IRState* p) { Logger::println("VarDeclaration ' %s ' of type ' %s '", vd->toChars(), vd->type->toChars()); +#if DMDV2 + /* The magic variable __ctfe is always false at runtime + */ + if (vd->ident == Id::ctfe) { + return new DConstValue(type, DtoConstBool(false)); + } +#endif + // this is an error! must be accessed with DotVarExp if (var->needThis()) { @@ -763,6 +771,15 @@ DValue* ModExp::toElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// +void CallExp::cacheLvalue(IRState* p) +{ + Logger::println("Caching l-value of %s", toChars()); + LOG_SCOPE; + cachedLvalue = toElem(p)->getLVal(); +} + +////////////////////////////////////////////////////////////////////////////////////////// + DValue* CallExp::toElem(IRState* p) { Logger::print("CallExp::toElem: %s @ %s\n", toChars(), type->toChars()); @@ -823,7 +840,6 @@ DValue* CallExp::toElem(IRState* p) return new DImValue(type, p->ir->CreateAlloca(LLType::getInt8Ty(gIR->context()), expv->getRVal(), ".alloca")); } } - return DtoCallFunction(loc, type, fnval, arguments); } @@ -1439,6 +1455,10 @@ DValue* CmpExp::toElem(IRState* p) Logger::println("static or dynamic array"); eval = DtoArrayCompare(loc,op,l,r); } + else if (t->ty == Taarray) + { + eval = LLConstantInt::getFalse(gIR->context()); + } else { assert(0 && "Unsupported CmpExp type"); @@ -1804,8 +1824,10 @@ DValue* AssertExp::toElem(IRState* p) p->scope() = IRScope(endbb,oldend); } - // no meaningful return value - return NULL; + // DMD allows syntax like this: + // f() == 0 || assert(false) + // TODO: or should we return true? + return new DImValue(type, DtoConstBool(false)); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2239,8 +2261,15 @@ DValue* CatAssignExp::toElem(IRState* p) DSliceValue* slice = DtoCatAssignArray(l,e2); DtoAssign(loc, l, slice); } - else + else if (elemtype->ty == Tchar) { + if (e2type->ty == Tdchar) + DtoAppendDChar(l, e2); + else + assert(0 && "cannot append the element to a string"); + } + else { assert(0 && "only one element at a time right now"); + } return l; } @@ -2632,10 +2661,31 @@ DValue* TypeExp::toElem(IRState *p) ////////////////////////////////////////////////////////////////////////////////////////// +DValue* TupleExp::toElem(IRState *p) +{ + Logger::print("TupleExp::toElem() %s\n", toChars()); + std::vector types(exps->dim, NULL); + 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(); + } + 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)); + } + return new DImValue(type, val); +} + +////////////////////////////////////////////////////////////////////////////////////////// + #define STUB(x) DValue *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; } STUB(Expression); STUB(ScopeExp); -STUB(TupleExp); #if DMDV2 STUB(SymbolExp); diff --git a/ir/irfunction.cpp b/ir/irfunction.cpp index c0b29c83..415dad66 100644 --- a/ir/irfunction.cpp +++ b/ir/irfunction.cpp @@ -30,7 +30,7 @@ bool IrFuncTyArg::isByVal() const { return (attrs & llvm::Attribute::ByVal) != 0 ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -llvm::Value* IrFuncTy::putRet(Type* dty, DValue* val) +llvm::Value* IrFuncTy::putRet(Type* dty, DValue* val, bool isref) { assert(!arg_sret); if (ret->rewrite) { @@ -38,7 +38,7 @@ llvm::Value* IrFuncTy::putRet(Type* dty, DValue* val) LOG_SCOPE return ret->rewrite->put(dty, val); } - return val->getRVal(); + return isref ? val->getLVal() : val->getRVal(); } llvm::Value* IrFuncTy::getRet(Type* dty, DValue* val) diff --git a/ir/irfuncty.h b/ir/irfuncty.h index 9681b951..9b1fcbf9 100644 --- a/ir/irfuncty.h +++ b/ir/irfuncty.h @@ -101,7 +101,7 @@ struct IrFuncTy : IrBase reverseParams = false; } - llvm::Value* putRet(Type* dty, DValue* dval); + llvm::Value* putRet(Type* dty, DValue* dval, bool isref = false); llvm::Value* getRet(Type* dty, DValue* dval); llvm::Value* putParam(Type* dty, int idx, DValue* dval); diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index e9f86276..f8b15d8d 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -75,6 +75,29 @@ elseif(D_VERSION EQUAL 2) ${RUNTIME_DIR}/src/core/stdc/stdarg.d ) file(GLOB CORE_C ${RUNTIME_DIR}/src/core/stdc/*.c) + + if(PHOBOS2_DIR) + file(GLOB PHOBOS2_D ${PHOBOS2_DIR}/std/*.d) + file(GLOB PHOBOS2_D_MATH ${PHOBOS2_DIR}/std/internal/math/*.d) + file(GLOB PHOBOS2_D_C ${PHOBOS2_DIR}/std/c/*.d) + if(UNIX) + file(GLOB PHOBOS2_D_C_SYS ${PHOBOS2_DIR}/std/c/linux/*.d) + elseif(WIN32) + file(GLOB PHOBOS2_D_C_SYS ${PHOBOS2_DIR}/std/c/windows/*.d) + elseif(APPLE) + file(GLOB PHOBOS2_D_C_SYS ${PHOBOS2_DIR}/std/c/osx/*.d) + endif(UNIX) + file(GLOB ZLIB_C ${PHOBOS2_DIR}/etc/c/zlib/*.c) + list(REMOVE_ITEM ZLIB_C + ${PHOBOS2_DIR}/etc/c/zlib/minigzip.c + ${PHOBOS2_DIR}/etc/c/zlib/example.c + ) + 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}) + endif(PHOBOS2_DIR) endif(D_VERSION EQUAL 1) # should only be necessary if run independently from ldc cmake project @@ -212,3 +235,12 @@ set_target_properties( # BCLIBS is empty if BUILD_BC_LIBS is not selected add_custom_target(runtime DEPENDS ${LIBS} ${BCLIBS}) + +if(PHOBOS2_DIR) + foreach(f ${PHOBOS2_D}) + dc(${f} PHOBOS2_O PHOBOS2_BC ${RUNTIME_DIR}/src/ "-I${PHOBOS2_DIR}" ${PHOBOS2_DIR}) + endforeach(f) + + add_library(phobos2 ${ZLIB_C} ${PHOBOS2_O}) + add_dependencies(phobos2 runtime) +endif(PHOBOS2_DIR)