mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-03-01 18:13:18 +01:00
Started work on phobos
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -1124,6 +1124,7 @@ struct CallExp : UnaExp
|
||||
|
||||
#if IN_LLVM
|
||||
DValue* toElem(IRState* irs);
|
||||
void cacheLvalue(IRState* irs);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -114,7 +114,7 @@ char *Declaration::mangle()
|
||||
break;
|
||||
|
||||
#if IN_LLVM
|
||||
case LINKintrinsic:
|
||||
case LINKintrinsic:
|
||||
#endif
|
||||
case LINKc:
|
||||
case LINKwindows:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<LLValue*,2> 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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<const LLType*> 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");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
60
gen/toir.cpp
60
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<const LLType*> 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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user