mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-28 02:23:13 +01:00
Implemented first class delegates. closes #101
This commit is contained in:
@@ -1517,6 +1517,9 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
Expression *flde;
|
||||
Identifier *id;
|
||||
Type *tret;
|
||||
TypeDelegate* dgty;
|
||||
TypeDelegate* dgty2;
|
||||
TypeDelegate* fldeTy;
|
||||
|
||||
tret = func->type->nextOf();
|
||||
|
||||
@@ -1600,6 +1603,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
*/
|
||||
//LDC: Build arguments.
|
||||
static FuncDeclaration *aaApply2_fd = NULL;
|
||||
static TypeDelegate* aaApply2_dg;
|
||||
if(!aaApply2_fd) {
|
||||
Arguments* args = new Arguments;
|
||||
args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL));
|
||||
@@ -1607,25 +1611,28 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
Arguments* dgargs = new Arguments;
|
||||
dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
|
||||
dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
|
||||
TypeDelegate* dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
|
||||
args->push(new Argument(STCin, dgty, NULL, NULL));
|
||||
aaApply2_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
|
||||
args->push(new Argument(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) {
|
||||
Arguments* args = new Arguments;
|
||||
args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL));
|
||||
args->push(new Argument(STCin, Type::tsize_t, NULL, NULL));
|
||||
Arguments* dgargs = new Arguments;
|
||||
dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
|
||||
TypeDelegate* dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
|
||||
args->push(new Argument(STCin, dgty, NULL, NULL));
|
||||
aaApply_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
|
||||
args->push(new Argument(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();
|
||||
@@ -1633,7 +1640,15 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
size_t keysize = taa->key->size();
|
||||
keysize = (keysize + 3) & ~3;
|
||||
exps->push(new IntegerExp(0, keysize, Type::tsize_t));
|
||||
|
||||
// LDC paint delegate argument to the type runtime expects
|
||||
if (!fldeTy->equals(flde->type))
|
||||
{
|
||||
flde = new CastExp(loc, flde, flde->type);
|
||||
flde->type = fldeTy;
|
||||
}
|
||||
exps->push(flde);
|
||||
|
||||
e = new CallExp(loc, ec, exps);
|
||||
e->type = Type::tindex; // don't run semantic() on e
|
||||
}
|
||||
@@ -1674,13 +1689,13 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
Arguments* dgargs = new Arguments;
|
||||
dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
|
||||
dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
|
||||
TypeDelegate* dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
|
||||
dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
|
||||
args->push(new Argument(STCin, dgty, NULL, NULL));
|
||||
fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname);
|
||||
} else {
|
||||
Arguments* dgargs = new Arguments;
|
||||
dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
|
||||
TypeDelegate* dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
|
||||
dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
|
||||
args->push(new Argument(STCin, dgty, NULL, NULL));
|
||||
fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname);
|
||||
}
|
||||
@@ -1690,7 +1705,15 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
if (tab->ty == Tsarray)
|
||||
aggr = aggr->castTo(sc, tn->arrayOf());
|
||||
exps->push(aggr);
|
||||
|
||||
// LDC paint delegate argument to the type runtime expects
|
||||
if (!dgty->equals(flde->type))
|
||||
{
|
||||
flde = new CastExp(loc, flde, flde->type);
|
||||
flde->type = dgty;
|
||||
}
|
||||
exps->push(flde);
|
||||
|
||||
e = new CallExp(loc, ec, exps);
|
||||
e->type = Type::tindex; // don't run semantic() on e
|
||||
}
|
||||
|
||||
@@ -123,15 +123,24 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
|
||||
|
||||
const LLType* at = DtoType(argT);
|
||||
|
||||
// handle lazy args
|
||||
if (arg->storageClass & STClazy)
|
||||
{
|
||||
Logger::println("lazy param");
|
||||
TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
|
||||
TypeDelegate *ltd = new TypeDelegate(ltf);
|
||||
at = DtoType(ltd);
|
||||
paramvec.push_back(at);
|
||||
}
|
||||
// opaque types need special handling
|
||||
if (llvm::isa<llvm::OpaqueType>(at)) {
|
||||
else if (llvm::isa<llvm::OpaqueType>(at)) {
|
||||
Logger::println("opaque param");
|
||||
assert(argT->ty == Tstruct || argT->ty == Tclass);
|
||||
paramvec.push_back(getPtrToType(at));
|
||||
}
|
||||
// structs and delegates are passed as a reference, but by value
|
||||
else if (argT->ty == Tstruct || argT->ty == Tdelegate) {
|
||||
Logger::println("struct/sarray param");
|
||||
// structs are passed as a reference, but by value
|
||||
else if (argT->ty == Tstruct) {
|
||||
Logger::println("struct param");
|
||||
if (!refOrOut)
|
||||
arg->llvmAttrs |= llvm::Attribute::ByVal;
|
||||
paramvec.push_back(getPtrToType(at));
|
||||
@@ -156,23 +165,6 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
|
||||
arg->llvmAttrs |= ea;
|
||||
paramvec.push_back(at);
|
||||
}
|
||||
|
||||
// handle lazy args
|
||||
if (arg->storageClass & STClazy)
|
||||
{
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "for lazy got: " << *paramvec.back() << '\n';
|
||||
|
||||
TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
|
||||
TypeDelegate *ltd = new TypeDelegate(ltf);
|
||||
at = getPtrToType(DtoType(ltd));
|
||||
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "lazy updated to: " << *at << '\n';
|
||||
|
||||
paramvec.back() = at;
|
||||
// lazy doesn't need byval as the delegate is not visible to the user
|
||||
}
|
||||
}
|
||||
|
||||
// construct function type
|
||||
@@ -652,13 +644,14 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
||||
IrLocal* irloc = vd->ir.irLocal;
|
||||
assert(irloc);
|
||||
|
||||
bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy);
|
||||
bool refout = vd->storage_class & (STCref | STCout);
|
||||
bool lazy = vd->storage_class & STClazy;
|
||||
|
||||
if (refoutlazy)
|
||||
if (refout)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (DtoIsPassedByRef(vd->type))
|
||||
else if (!lazy && DtoIsPassedByRef(vd->type))
|
||||
{
|
||||
LLValue* vdirval = irloc->value;
|
||||
if (global.params.symdebug && !(isaArgument(vdirval) && !isaArgument(vdirval)->hasByValAttr()))
|
||||
@@ -875,6 +868,13 @@ DValue* DtoArgument(Argument* fnarg, Expression* argexp)
|
||||
else
|
||||
arg = new DImValue(argexp->type, arg->getRVal());
|
||||
}
|
||||
// lazy arg
|
||||
else if (fnarg && (fnarg->storageClass & STClazy))
|
||||
{
|
||||
assert(argexp->type->toBasetype()->ty == Tdelegate);
|
||||
assert(!arg->isLVal());
|
||||
return arg;
|
||||
}
|
||||
// byval arg, but expr has no storage yet
|
||||
else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isNull()))
|
||||
{
|
||||
|
||||
@@ -452,15 +452,11 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
|
||||
}
|
||||
}
|
||||
else if (t->ty == Tdelegate) {
|
||||
if (rhs->isNull())
|
||||
DtoAggrZeroInit(lhs->getLVal());
|
||||
else {
|
||||
LLValue* l = lhs->getLVal();
|
||||
LLValue* r = rhs->getRVal();
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
|
||||
DtoAggrCopy(l, r);
|
||||
}
|
||||
LLValue* l = lhs->getLVal();
|
||||
LLValue* r = rhs->getRVal();
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
|
||||
DtoStore(r, l);
|
||||
}
|
||||
else if (t->ty == Tclass) {
|
||||
assert(t2->ty == Tclass);
|
||||
@@ -694,21 +690,15 @@ DValue* DtoCastFloat(Loc& loc, DValue* val, Type* to)
|
||||
|
||||
DValue* DtoCastDelegate(Loc& loc, DValue* val, Type* to)
|
||||
{
|
||||
LLValue* res = 0;
|
||||
to = to->toBasetype();
|
||||
|
||||
if (to->ty == Tdelegate)
|
||||
if (to->toBasetype()->ty == Tdelegate)
|
||||
{
|
||||
const LLType* toll = getPtrToType(DtoType(to));
|
||||
res = DtoBitCast(val->getRVal(), toll);
|
||||
return DtoPaintType(loc, val, to);
|
||||
}
|
||||
else
|
||||
{
|
||||
error(loc, "invalid cast from '%s' to '%s'", val->getType()->toChars(), to->toChars());
|
||||
fatal();
|
||||
}
|
||||
|
||||
return new DImValue(to, res);
|
||||
}
|
||||
|
||||
DValue* DtoCast(Loc& loc, DValue* val, Type* to)
|
||||
@@ -773,6 +763,31 @@ DValue* DtoPaintType(Loc& loc, DValue* val, Type* to)
|
||||
return new DImValue(to, DtoAggrPair(len, ptr, "tmp"));
|
||||
}
|
||||
}
|
||||
else if (from->ty == Tdelegate)
|
||||
{
|
||||
Type* dgty = to->toBasetype();
|
||||
assert(dgty->ty == Tdelegate);
|
||||
if (val->isLVal())
|
||||
{
|
||||
LLValue* ptr = val->getLVal();
|
||||
assert(isaPointer(ptr));
|
||||
ptr = DtoBitCast(ptr, getPtrToType(DtoType(dgty)));
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "dg ptr: " << *ptr << '\n';
|
||||
return new DVarValue(to, ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLValue* dg = val->getRVal();
|
||||
LLValue* context = gIR->ir->CreateExtractValue(dg, 0, ".context");
|
||||
LLValue* funcptr = gIR->ir->CreateExtractValue(dg, 1, ".funcptr");
|
||||
funcptr = DtoBitCast(funcptr, DtoType(dgty)->getContainedType(1));
|
||||
LLValue* aggr = DtoAggrPair(context, funcptr, "tmp");
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "dg: " << *aggr << '\n';
|
||||
return new DImValue(to, aggr);
|
||||
}
|
||||
}
|
||||
else if (from->ty == Tpointer || from->ty == Tclass || from->ty == Taarray)
|
||||
{
|
||||
Type* b = to->toBasetype();
|
||||
|
||||
@@ -119,11 +119,7 @@ static const LLType* rt_dg1()
|
||||
types.push_back(rt_ptr(LLType::Int8Ty));
|
||||
types.push_back(rt_ptr(LLType::Int8Ty));
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(LLType::Int32Ty, types, false);
|
||||
|
||||
std::vector<const LLType*> t;
|
||||
t.push_back(rt_ptr(LLType::Int8Ty));
|
||||
t.push_back(rt_ptr(fty));
|
||||
return rt_ptr(llvm::StructType::get(t));
|
||||
return llvm::StructType::get(rt_ptr(LLType::Int8Ty), rt_ptr(fty), 0);
|
||||
}
|
||||
|
||||
static const LLType* rt_dg2()
|
||||
@@ -133,11 +129,7 @@ static const LLType* rt_dg2()
|
||||
types.push_back(rt_ptr(LLType::Int8Ty));
|
||||
types.push_back(rt_ptr(LLType::Int8Ty));
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(LLType::Int32Ty, types, false);
|
||||
|
||||
std::vector<const LLType*> t;
|
||||
t.push_back(rt_ptr(LLType::Int8Ty));
|
||||
t.push_back(rt_ptr(fty));
|
||||
return rt_ptr(llvm::StructType::get(t));
|
||||
return llvm::StructType::get(rt_ptr(LLType::Int8Ty), rt_ptr(fty), 0);
|
||||
}
|
||||
|
||||
static void LLVM_D_BuildRuntimeModule()
|
||||
@@ -365,10 +357,8 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
types.push_back(TY); \
|
||||
types.push_back(rt_dg1()); \
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(intTy, types, false); \
|
||||
llvm::AttrListPtr palist; \
|
||||
palist = palist.addAttr(2, llvm::Attribute::ByVal); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)->setAttributes(palist); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M)->setAttributes(palist); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M); \
|
||||
}
|
||||
STR_APPLY1(stringTy, "_aApplycw1", "_aApplycd1")
|
||||
STR_APPLY1(wstringTy, "_aApplywc1", "_aApplywd1")
|
||||
@@ -384,10 +374,8 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
types.push_back(TY); \
|
||||
types.push_back(rt_dg2()); \
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(intTy, types, false); \
|
||||
llvm::AttrListPtr palist; \
|
||||
palist = palist.addAttr(2, llvm::Attribute::ByVal); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)->setAttributes(palist); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M)->setAttributes(palist); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M); \
|
||||
}
|
||||
STR_APPLY2(stringTy, "_aApplycw2", "_aApplycd2")
|
||||
STR_APPLY2(wstringTy, "_aApplywc2", "_aApplywd2")
|
||||
@@ -402,10 +390,8 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
types.push_back(TY); \
|
||||
types.push_back(rt_dg1()); \
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(intTy, types, false); \
|
||||
llvm::AttrListPtr palist; \
|
||||
palist = palist.addAttr(2, llvm::Attribute::ByVal); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)->setAttributes(palist); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M)->setAttributes(palist); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M); \
|
||||
}
|
||||
STR_APPLY_R1(stringTy, "_aApplyRcw1", "_aApplyRcd1")
|
||||
STR_APPLY_R1(wstringTy, "_aApplyRwc1", "_aApplyRwd1")
|
||||
@@ -420,10 +406,8 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
types.push_back(TY); \
|
||||
types.push_back(rt_dg2()); \
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(intTy, types, false); \
|
||||
llvm::AttrListPtr palist; \
|
||||
palist = palist.addAttr(2, llvm::Attribute::ByVal); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)->setAttributes(palist); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M)->setAttributes(palist); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); \
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M); \
|
||||
}
|
||||
STR_APPLY_R2(stringTy, "_aApplyRcw2", "_aApplyRcd2")
|
||||
STR_APPLY_R2(wstringTy, "_aApplyRwc2", "_aApplyRwd2")
|
||||
@@ -662,9 +646,7 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
types.push_back(sizeTy);
|
||||
types.push_back(rt_dg1());
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(intTy, types, false);
|
||||
llvm::AttrListPtr palist;
|
||||
palist = palist.addAttr(3, llvm::Attribute::ByVal);
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)->setAttributes(palist);
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
|
||||
// int _aaApply2(AA aa, size_t keysize, dg2_t dg)
|
||||
@@ -675,9 +657,7 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
types.push_back(sizeTy);
|
||||
types.push_back(rt_dg2());
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(intTy, types, false);
|
||||
llvm::AttrListPtr palist;
|
||||
palist = palist.addAttr(3, llvm::Attribute::ByVal);
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)->setAttributes(palist);
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -75,11 +75,18 @@ LLValue* DtoCallableValue(DValue* fn)
|
||||
}
|
||||
else if (type->ty == Tdelegate)
|
||||
{
|
||||
LLValue* dg = fn->getRVal();
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "delegate: " << *dg << '\n';
|
||||
LLValue* funcptr = DtoGEPi(dg, 0, 1);
|
||||
return DtoLoad(funcptr);
|
||||
if (fn->isLVal())
|
||||
{
|
||||
LLValue* dg = fn->getLVal();
|
||||
LLValue* funcptr = DtoGEPi(dg, 0, 1);
|
||||
return DtoLoad(funcptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLValue* dg = fn->getRVal();
|
||||
assert(isaStruct(dg));
|
||||
return gIR->ir->CreateExtractValue(dg, 1, ".funcptr");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -266,7 +273,15 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||
// ... or a delegate context arg
|
||||
else if (delegatecall)
|
||||
{
|
||||
LLValue* ctxarg = DtoLoad(DtoGEPi(fnval->getRVal(), 0,0));
|
||||
LLValue* ctxarg;
|
||||
if (fnval->isLVal())
|
||||
{
|
||||
ctxarg = DtoLoad(DtoGEPi(fnval->getLVal(), 0,0));
|
||||
}
|
||||
else
|
||||
{
|
||||
ctxarg = gIR->ir->CreateExtractValue(fnval->getRVal(), 0, ".ptr");
|
||||
}
|
||||
assert(ctxarg->getType() == argiter->get());
|
||||
++argiter;
|
||||
args.push_back(ctxarg);
|
||||
|
||||
31
gen/toir.cpp
31
gen/toir.cpp
@@ -110,11 +110,17 @@ DValue* VarExp::toElem(IRState* p)
|
||||
// function parameter
|
||||
else if (vd->isParameter()) {
|
||||
Logger::println("function param");
|
||||
Logger::println("type: %s", vd->type->toChars());
|
||||
FuncDeclaration* fd = vd->toParent2()->isFuncDeclaration();
|
||||
if (fd && fd != p->func()->decl) {
|
||||
Logger::println("nested parameter");
|
||||
return DtoNestedVariable(loc, type, vd);
|
||||
}
|
||||
else if (vd->storage_class & STClazy) {
|
||||
Logger::println("lazy parameter");
|
||||
assert(type->ty == Tdelegate);
|
||||
return new DVarValue(type, vd->ir.getIrValue());
|
||||
}
|
||||
else if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->ir.getIrValue())) {
|
||||
return new DVarValue(type, vd, vd->ir.getIrValue());
|
||||
}
|
||||
@@ -1833,7 +1839,8 @@ DValue* DelegateExp::toElem(IRState* p)
|
||||
|
||||
const LLPointerType* int8ptrty = getPtrToType(LLType::Int8Ty);
|
||||
|
||||
LLValue* lval = DtoAlloca(DtoType(type), "tmpdelegate");
|
||||
assert(type->toBasetype()->ty == Tdelegate);
|
||||
const LLType* dgty = DtoType(type);
|
||||
|
||||
DValue* u = e1->toElem(p);
|
||||
LLValue* uval;
|
||||
@@ -1859,11 +1866,7 @@ DValue* DelegateExp::toElem(IRState* p)
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "context = " << *uval << '\n';
|
||||
|
||||
LLValue* context = DtoGEPi(lval,0,0);
|
||||
LLValue* castcontext = DtoBitCast(uval, int8ptrty);
|
||||
DtoStore(castcontext, context);
|
||||
|
||||
LLValue* fptr = DtoGEPi(lval,0,1);
|
||||
|
||||
Logger::println("func: '%s'", func->toPrettyChars());
|
||||
|
||||
@@ -1880,10 +1883,9 @@ DValue* DelegateExp::toElem(IRState* p)
|
||||
castfptr = func->ir.irFunc->func;
|
||||
}
|
||||
|
||||
castfptr = DtoBitCast(castfptr, fptr->getType()->getContainedType(0));
|
||||
DtoStore(castfptr, fptr);
|
||||
castfptr = DtoBitCast(castfptr, dgty->getContainedType(1));
|
||||
|
||||
return new DImValue(type, lval);
|
||||
return new DImValue(type, DtoAggrPair(castcontext, castfptr, ".dg"));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -2098,12 +2100,9 @@ DValue* FuncExp::toElem(IRState* p)
|
||||
DtoForceDefineDsymbol(fd);
|
||||
assert(fd->ir.irFunc->func);
|
||||
|
||||
LLValue *lval, *fptr;
|
||||
if(fd->tok == TOKdelegate) {
|
||||
const LLType* dgty = DtoType(type);
|
||||
lval = DtoAlloca(dgty,"dgstorage");
|
||||
|
||||
LLValue* context = DtoGEPi(lval,0,0);
|
||||
LLValue* cval;
|
||||
IrFunction* irfn = p->func();
|
||||
if (irfn->nestedVar)
|
||||
@@ -2112,15 +2111,11 @@ DValue* FuncExp::toElem(IRState* p)
|
||||
cval = irfn->nestArg;
|
||||
else
|
||||
cval = getNullPtr(getVoidPtrType());
|
||||
cval = DtoBitCast(cval, context->getType()->getContainedType(0));
|
||||
DtoStore(cval, context);
|
||||
cval = DtoBitCast(cval, dgty->getContainedType(0));
|
||||
|
||||
fptr = DtoGEPi(lval,0,1,"tmp",p->scopebb());
|
||||
LLValue* castfptr = DtoBitCast(fd->ir.irFunc->func, dgty->getContainedType(1));
|
||||
|
||||
LLValue* castfptr = DtoBitCast(fd->ir.irFunc->func, fptr->getType()->getContainedType(0));
|
||||
DtoStore(castfptr, fptr);
|
||||
|
||||
return new DVarValue(type, lval);
|
||||
return new DImValue(type, DtoAggrPair(cval, castfptr, ".func"));
|
||||
|
||||
} else if(fd->tok == TOKfunction) {
|
||||
return new DImValue(type, fd->ir.irFunc->func);
|
||||
|
||||
@@ -25,14 +25,14 @@ bool DtoIsPassedByRef(Type* type)
|
||||
{
|
||||
Type* typ = type->toBasetype();
|
||||
TY t = typ->ty;
|
||||
return (t == Tstruct || t == Tdelegate || t == Tsarray);
|
||||
return (t == Tstruct || t == Tsarray);
|
||||
}
|
||||
|
||||
bool DtoIsReturnedInArg(Type* type)
|
||||
{
|
||||
Type* typ = type->toBasetype();
|
||||
TY t = typ->ty;
|
||||
return (t == Tstruct || t == Tdelegate || t == Tsarray);
|
||||
return (t == Tstruct || t == Tsarray);
|
||||
}
|
||||
|
||||
unsigned DtoShouldExtend(Type* type)
|
||||
@@ -221,6 +221,7 @@ const LLType* DtoTypeNotVoid(Type* t)
|
||||
|
||||
const LLStructType* DtoDelegateType(Type* t)
|
||||
{
|
||||
assert(t->ty == Tdelegate);
|
||||
const LLType* i8ptr = getVoidPtrType();
|
||||
const LLType* func = DtoFunctionType(t->next, NULL, i8ptr);
|
||||
const LLType* funcptr = getPtrToType(func);
|
||||
@@ -235,25 +236,22 @@ LLValue* DtoDelegateEquals(TOK op, LLValue* lhs, LLValue* rhs)
|
||||
llvm::Value *b1, *b2;
|
||||
if (rhs == NULL)
|
||||
{
|
||||
LLValue* l = DtoLoad(DtoGEPi(lhs,0,0));
|
||||
LLValue* r = llvm::Constant::getNullValue(l->getType());
|
||||
b1 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,l,r,"tmp");
|
||||
l = DtoLoad(DtoGEPi(lhs,0,1));
|
||||
r = llvm::Constant::getNullValue(l->getType());
|
||||
b2 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,l,r,"tmp");
|
||||
}
|
||||
else
|
||||
{
|
||||
LLValue* l = DtoLoad(DtoGEPi(lhs,0,0));
|
||||
LLValue* r = DtoLoad(DtoGEPi(rhs,0,0));
|
||||
b1 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,l,r,"tmp");
|
||||
l = DtoLoad(DtoGEPi(lhs,0,1));
|
||||
r = DtoLoad(DtoGEPi(rhs,0,1));
|
||||
b2 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,l,r,"tmp");
|
||||
rhs = LLConstant::getNullValue(lhs->getType());
|
||||
}
|
||||
|
||||
LLValue* l = gIR->ir->CreateExtractValue(lhs, 0);
|
||||
LLValue* r = gIR->ir->CreateExtractValue(rhs, 0);
|
||||
b1 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,l,r,"tmp");
|
||||
|
||||
l = gIR->ir->CreateExtractValue(lhs, 1);
|
||||
r = gIR->ir->CreateExtractValue(rhs, 1);
|
||||
b2 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,l,r,"tmp");
|
||||
|
||||
LLValue* b = gIR->ir->CreateAnd(b1,b2,"tmp");
|
||||
|
||||
if (op == TOKnotequal || op == TOKnotidentity)
|
||||
return gIR->ir->CreateNot(b,"tmp");
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -557,8 +555,8 @@ LLConstant* DtoConstStringPtr(const char* str, const char* section)
|
||||
|
||||
LLValue* DtoLoad(LLValue* src, const char* name)
|
||||
{
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "loading " << *src << '\n';
|
||||
// if (Logger::enabled())
|
||||
// Logger::cout() << "loading " << *src << '\n';
|
||||
LLValue* ld = gIR->ir->CreateLoad(src, name ? name : "tmp");
|
||||
//ld->setVolatile(gIR->func()->inVolatile);
|
||||
return ld;
|
||||
@@ -566,8 +564,8 @@ LLValue* DtoLoad(LLValue* src, const char* name)
|
||||
|
||||
void DtoStore(LLValue* src, LLValue* dst)
|
||||
{
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "storing " << *src << " into " << *dst << '\n';
|
||||
// if (Logger::enabled())
|
||||
// Logger::cout() << "storing " << *src << " into " << *dst << '\n';
|
||||
LLValue* st = gIR->ir->CreateStore(src,dst);
|
||||
//st->setVolatile(gIR->func()->inVolatile);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ void Module::genobjfile(int multiobj, char** envp)
|
||||
Logger::println("Generating module: %s\n", (md ? md->toChars() : toChars()));
|
||||
LOG_SCOPE;
|
||||
|
||||
//printf("codegen: %s\n", srcfile->toChars());
|
||||
printf("codegen: %s\n", srcfile->toChars());
|
||||
|
||||
// start by deleting the old object file
|
||||
deleteObjFile();
|
||||
|
||||
Reference in New Issue
Block a user