Skip to content

Commit 9880a3f

Browse files
committed
[next step: ensure no more DImValues for function ptrs and delegates]
1 parent 6b7c533 commit 9880a3f

File tree

4 files changed

+62
-28
lines changed

4 files changed

+62
-28
lines changed

gen/dvalue.cpp

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,16 @@ DRValue::DRValue(Type *t, LLValue *v) : DValue(t, v) {
6464
////////////////////////////////////////////////////////////////////////////////
6565

6666
DImValue::DImValue(Type *t, llvm::Value *v) : DRValue(t, v) {
67-
// TODO: get rid of Tfunction exception
67+
#ifndef NDEBUG
68+
const auto tb = t->toBasetype();
69+
#endif
70+
assert(tb->ty != TY::Tarray && "use DSliceValue for dynamic arrays");
71+
assert(!tb->isFunction_Delegate_PtrToFunction() &&
72+
"use DFuncValue for function pointers and delegates");
73+
6874
// v may be an addrspace qualified pointer so strip it before doing a pointer
6975
// equality check.
70-
assert(t->toBasetype()->ty == TY::Tfunction ||
71-
stripAddrSpaces(v->getType()) == DtoType(t));
72-
assert(t->toBasetype()->ty != TY::Tarray &&
73-
"use DSliceValue for dynamic arrays");
76+
assert(stripAddrSpaces(v->getType()) == DtoType(t));
7477
}
7578

7679
////////////////////////////////////////////////////////////////////////////////
@@ -119,12 +122,7 @@ DFuncValue::DFuncValue(Type *t, FuncDeclaration *fd, LLValue *funcPtr,
119122
LLValue *vt, LLValue *vtable)
120123
: DRValue(t, createFuncRValue(t, funcPtr, vt)), func(fd), funcPtr(funcPtr),
121124
vthis(vt), vtable(vtable) {
122-
#ifndef NDEBUG
123-
const auto tb = t->toBasetype();
124-
#endif
125-
assert(tb->ty == TY::Tfunction || tb->ty == TY::Tdelegate ||
126-
(tb->ty == TY::Tpointer &&
127-
tb->nextOf()->toBasetype()->ty == TY::Tfunction));
125+
assert(t->toBasetype()->isFunction_Delegate_PtrToFunction());
128126
}
129127

130128
DFuncValue::DFuncValue(FuncDeclaration *fd, LLValue *funcPtr, LLValue *vt,
@@ -150,8 +148,8 @@ DRValue *DLValue::getRVal() {
150148

151149
LLValue *rval = DtoLoad(DtoMemType(type), val);
152150

153-
const auto ty = type->toBasetype()->ty;
154-
if (ty == TY::Tbool) {
151+
const auto tb = type->toBasetype();
152+
if (tb->ty == TY::Tbool) {
155153
assert(rval->getType() == llvm::Type::getInt8Ty(gIR->context()));
156154

157155
if (isOptimizationEnabled()) {
@@ -164,8 +162,14 @@ DRValue *DLValue::getRVal() {
164162

165163
// truncate to i1
166164
rval = gIR->ir->CreateTrunc(rval, llvm::Type::getInt1Ty(gIR->context()));
167-
} else if (ty == TY::Tarray) {
165+
} else if (tb->ty == TY::Tarray) {
168166
return new DSliceValue(type, rval);
167+
} else if (tb->isPtrToFunction()) {
168+
return new DFuncValue(type, nullptr, rval);
169+
} else if (tb->ty == TY::Tdelegate) {
170+
const auto contextPtr = DtoExtractValue(rval, 0, ".ptr");
171+
const auto funcPtr = DtoExtractValue(rval, 1, ".funcptr");
172+
return new DFuncValue(type, nullptr, funcPtr, contextPtr);
169173
}
170174

171175
return new DImValue(type, rval);

gen/llvmhelpers.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,10 @@ DValue *DtoCastInt(const Loc &loc, DValue *val, Type *_to) {
527527
} else {
528528
rval = new llvm::SIToFPInst(rval, tolltype, "", gIR->scopebb());
529529
}
530+
} else if (to->isPtrToFunction()) {
531+
IF_LOG Logger::cout() << "cast function pointer: " << *tolltype << '\n';
532+
rval = gIR->ir->CreateIntToPtr(rval, tolltype);
533+
return new DFuncValue(_to, nullptr, rval);
530534
} else if (to->ty == TY::Tpointer) {
531535
IF_LOG Logger::cout() << "cast pointer: " << *tolltype << '\n';
532536
rval = gIR->ir->CreateIntToPtr(rval, tolltype);
@@ -569,7 +573,9 @@ DValue *DtoCastPtr(const Loc &loc, DValue *val, Type *to) {
569573
fatal();
570574
}
571575

572-
return new DImValue(to, rval);
576+
return totype->isPtrToFunction()
577+
? static_cast<DValue *>(new DFuncValue(to, nullptr, rval))
578+
: static_cast<DValue *>(new DImValue(to, rval));
573579
}
574580

575581
DValue *DtoCastFloat(const Loc &loc, DValue *val, Type *to) {
@@ -766,9 +772,8 @@ DValue *DtoPaintType(const Loc &loc, DValue *val, Type *to) {
766772
return new DSliceValue(to, slice->getLength(), slice->getPtr());
767773
}
768774
} else if (auto func = val->isFunc()) {
769-
if (tb->ty == TY::Tdelegate) {
770-
return new DFuncValue(to, func->func, func->funcPtr, func->vthis);
771-
}
775+
return new DFuncValue(to, func->func, func->funcPtr,
776+
tb->ty == TY::Tdelegate ? func->vthis : nullptr);
772777
} else { // generic rvalue
773778
LLValue *rval = DtoRVal(val);
774779
LLType *tll = DtoType(tb);

gen/tocall.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -712,8 +712,9 @@ class ImplicitArgumentsBuilder {
712712

713713
size_t index = args.size();
714714

715-
if (dfnval && (dfnval->func->ident == Id::ensure ||
716-
dfnval->func->ident == Id::require)) {
715+
if (dfnval && dfnval->func &&
716+
(dfnval->func->ident == Id::ensure ||
717+
dfnval->func->ident == Id::require)) {
717718
// can be the this "context" argument for a contract invocation
718719
// (pass a pointer to the aggregate `this` pointer, which can naturally be
719720
// used as the contract's parent context in case the contract features
@@ -747,7 +748,7 @@ class ImplicitArgumentsBuilder {
747748
args.push_back(ctxarg);
748749
} else if (nestedcall) {
749750
// ... or a nested function context arg
750-
if (dfnval) {
751+
if (dfnval && dfnval->func) {
751752
LLValue *contextptr = DtoNestedContext(loc, dfnval->func);
752753
args.push_back(contextptr);
753754
} else {
@@ -767,6 +768,7 @@ class ImplicitArgumentsBuilder {
767768

768769
if (irFty.arg_objcSelector) {
769770
assert(dfnval);
771+
assert(dfnval->func);
770772
const auto selector = dfnval->func->objc.selector;
771773
assert(selector);
772774
LLGlobalVariable *selptr = gIR->objc.getMethVarRef(*selector);
@@ -836,7 +838,7 @@ DValue *DtoCallFunction(const Loc &loc, Type *resulttype, DValue *fnval,
836838
// get callee llvm value
837839
LLValue *callable = DtoCallableValue(fnval);
838840
LLFunctionType *callableTy = irFty.funcType;
839-
if (dfnval && dfnval->func->isCsymbol()) {
841+
if (dfnval && dfnval->func && dfnval->func->isCsymbol()) {
840842
// See note in DtoDeclareFunction about K&R foward declared (void) functions
841843
// later defined as (...) functions. We want to use the non-variadic one.
842844
if (irFty.funcType->getNumParams() == 0 && irFty.funcType->isVarArg())
@@ -1017,7 +1019,7 @@ DValue *DtoCallFunction(const Loc &loc, Type *resulttype, DValue *fnval,
10171019
attrlist =
10181020
llvm::Intrinsic::getAttributes(gIR->context(), cf->getIntrinsicID());
10191021
}
1020-
} else if (dfnval) {
1022+
} else if (dfnval && dfnval->func) {
10211023
call->setCallingConv(getCallingConvention(dfnval->func));
10221024
} else {
10231025
call->setCallingConv(gABI->callingConv(tf, iab.hasContext));
@@ -1044,6 +1046,12 @@ DValue *DtoCallFunction(const Loc &loc, Type *resulttype, DValue *fnval,
10441046

10451047
if (rbase->ty == TY::Tarray) {
10461048
return new DSliceValue(resulttype, retllval);
1049+
} else if (rbase->isPtrToFunction()) {
1050+
return new DFuncValue(resulttype, nullptr, retllval);
1051+
} else if (rbase->ty == TY::Tdelegate) {
1052+
const auto contextPtr = DtoExtractValue(retllval, 0, ".ptr");
1053+
const auto funcPtr = DtoExtractValue(retllval, 1, ".funcptr");
1054+
return new DFuncValue(resulttype, nullptr, funcPtr, contextPtr);
10471055
}
10481056

10491057
return new DImValue(resulttype, retllval);

gen/toir.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -880,8 +880,20 @@ class ToElemVisitor : public Visitor {
880880

881881
llvm::Value *offsetValue = nullptr;
882882

883+
const auto tb = e->type->toBasetype();
884+
assert(tb->ty != TY::Tdelegate);
885+
assert(tb->ty != TY::Tfunction);
886+
883887
if (e->offset == 0) {
884888
offsetValue = baseValue;
889+
890+
if (tb->isPtrToFunction())
891+
if (auto dfn = base->isFunc()) {
892+
result = e->type == dfn->type
893+
? dfn
894+
: new DFuncValue(e->type, dfn->func, dfn->funcPtr);
895+
return;
896+
}
885897
} else {
886898
LLType *elemType = DtoType(base->type);
887899
if (elemType->isSized()) {
@@ -912,9 +924,14 @@ class ToElemVisitor : public Visitor {
912924
}
913925
}
914926

927+
if (tb->isPtrToFunction()) {
928+
result = new DFuncValue(e->type, nullptr, offsetValue);
929+
return;
930+
}
931+
915932
// Casts are also "optimized into" SymOffExp by the frontend.
916-
LLValue *llVal = (e->type->toBasetype()->isintegral()
917-
? p->ir->CreatePtrToInt(offsetValue, DtoType(e->type))
933+
LLValue *llVal =
934+
(tb->isintegral() ? p->ir->CreatePtrToInt(offsetValue, DtoType(e->type))
918935
: DtoBitCast(offsetValue, DtoType(e->type)));
919936
result = new DImValue(e->type, llVal);
920937
}
@@ -993,7 +1010,7 @@ class ToElemVisitor : public Visitor {
9931010
: new DFuncValue(e->type, dfv->func, dfv->funcPtr, dfv->vthis);
9941011
} else {
9951012
// FIXME: should not reach this
996-
result = new DImValue(e->type, DtoRVal(dv));
1013+
result = new DFuncValue(e->type, nullptr, DtoRVal(dv));
9971014
}
9981015
return;
9991016
}
@@ -2928,8 +2945,8 @@ bool toInPlaceConstruction(DLValue *lhs, Expression *rhs) {
29282945
Logger::println("is a constructor call, checking lhs of DotVarExp");
29292946
if (toInPlaceConstruction(lhs, dve->e1)) {
29302947
Logger::println("success, calling ctor on in-place constructed lhs");
2931-
auto fnval = new DFuncValue(fd, DtoCallee(fd), DtoLVal(lhs));
2932-
DtoCallFunction(ce->loc, ce->type, fnval, ce->arguments);
2948+
auto fnval = DFuncValue(fd, DtoCallee(fd), DtoLVal(lhs));
2949+
DtoCallFunction(ce->loc, ce->type, &fnval, ce->arguments);
29332950
return true;
29342951
}
29352952
}

0 commit comments

Comments
 (0)