Skip to content

Commit 84e858d

Browse files
author
Eli Friedman
committed
Fix static member functions so a member of type T has type "metatype<T> -> () -> ()" instead of "() -> ()".
This is much more convenient for IRGen, and gives us a reasonable representation for a static polymorphic function on a polymorphic type. I had to hack up irgen::emitArrayInjectionCall a bit to make the rest of this patch work; John, please revert those bits once emitCallee is fixed. Swift SVN r2488
1 parent bd6ff42 commit 84e858d

18 files changed

+129
-105
lines changed

include/swift/AST/Expr.h

+13
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,19 @@ class SpecializeExpr : public ImplicitConversionExpr {
12661266
}
12671267
};
12681268

1269+
/// GetMetatypeExpr -
1270+
class GetMetatypeExpr : public ImplicitConversionExpr {
1271+
public:
1272+
GetMetatypeExpr(Expr *subExpr, Type type)
1273+
: ImplicitConversionExpr(ExprKind::GetMetatype, subExpr, type) {}
1274+
1275+
// Implement isa/cast/dyncast/etc.
1276+
static bool classof(const LoadExpr *) { return true; }
1277+
static bool classof(const Expr *E) {
1278+
return E->getKind() == ExprKind::GetMetatype;
1279+
}
1280+
};
1281+
12691282
/// AddressOfExpr - Using the builtin unary '&' operator, convert the
12701283
/// given l-value into an explicit l-value.
12711284
class AddressOfExpr : public Expr {

include/swift/AST/ExprNodes.def

+2-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ ABSTRACT_EXPR(ImplicitConversion, Expr)
106106
EXPR(FunctionConversion, ImplicitConversionExpr)
107107
EXPR(Erasure, ImplicitConversionExpr)
108108
EXPR(Specialize, ImplicitConversionExpr)
109-
EXPR_RANGE(ImplicitConversion, Load, Specialize)
109+
EXPR(GetMetatype, ImplicitConversionExpr)
110+
EXPR_RANGE(ImplicitConversion, Load, GetMetatype)
110111
EXPR(Coerce, Expr)
111112

112113
#undef EXPR_RANGE

lib/AST/Decl.cpp

+4-15
Original file line numberDiff line numberDiff line change
@@ -453,19 +453,6 @@ Type FuncDecl::getExtensionType() const {
453453
Type FuncDecl::computeThisType(GenericParamList **OuterGenericParams) const {
454454
if (OuterGenericParams)
455455
*OuterGenericParams = nullptr;
456-
457-
// 'static' functions have no 'this' argument.
458-
if (isStatic()) {
459-
if (OuterGenericParams) {
460-
if (Type containerType = getExtensionType()) {
461-
if (auto UGT = containerType->getAs<UnboundGenericType>()) {
462-
*OuterGenericParams = UGT->getDecl()->getGenericParams();
463-
}
464-
}
465-
}
466-
467-
return Type();
468-
}
469456

470457
Type ContainerType = getExtensionType();
471458
if (ContainerType.isNull()) return ContainerType;
@@ -503,6 +490,10 @@ Type FuncDecl::computeThisType(GenericParamList **OuterGenericParams) const {
503490
*OuterGenericParams = D->getGenericParams();
504491
}
505492

493+
// 'static' functions have 'this' of type metatype<T>.
494+
if (isStatic())
495+
return MetaTypeType::get(ContainerType, getASTContext());
496+
506497
if (ContainerType->hasReferenceSemantics())
507498
return ContainerType;
508499

@@ -515,8 +506,6 @@ Type FuncDecl::computeThisType(GenericParamList **OuterGenericParams) const {
515506
/// extension context, it will have a 'this' argument. This method returns it
516507
/// if present, or returns null if not.
517508
VarDecl *FuncDecl::getImplicitThisDecl() {
518-
if (isStatic()) return 0;
519-
520509
if (Body->getParamPatterns().empty()) return 0;
521510

522511
// "this" is represented as (typed_pattern (named_pattern (var_decl 'this')).

lib/AST/Expr.cpp

+5-6
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,9 @@ ArchetypeType *ArchetypeMemberRefExpr::getArchetype() const {
150150
}
151151

152152
bool ArchetypeMemberRefExpr::isBaseIgnored() const {
153-
if (getBase()->getType()->getRValueType()->is<MetaTypeType>())
154-
return true;
155-
156153
if (isa<TypeDecl>(Value))
157154
return true;
158155

159-
if (auto Func = dyn_cast<FuncDecl>(Value))
160-
return Func->isStatic();
161-
162156
return false;
163157
}
164158

@@ -595,6 +589,11 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
595589
printRec(E->getSubExpr());
596590
OS << ')';
597591
}
592+
void visitGetMetatypeExpr(GetMetatypeExpr *E) {
593+
printCommon(E, "get_metatype_expr") << '\n';
594+
printRec(E->getSubExpr());
595+
OS << ')';
596+
}
598597

599598
void visitAddressOfExpr(AddressOfExpr *E) {
600599
printCommon(E, "address_of_expr") << '\n';

lib/AST/Verifier.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,8 @@ namespace {
283283
if (isa<ThisApplyExpr>(E)) {
284284
LValueType::Qual InputExprQuals;
285285
Type InputExprObjectTy;
286-
if (InputExprTy->hasReferenceSemantics())
286+
if (InputExprTy->hasReferenceSemantics() ||
287+
InputExprTy->is<MetaTypeType>())
287288
InputExprObjectTy = InputExprTy;
288289
else
289290
InputExprObjectTy = checkLValue(InputExprTy, InputExprQuals,

lib/IRGen/GenArray.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,22 @@ void swift::irgen::emitArrayInjectionCall(IRGenFunction &IGF, ManagedValue alloc
132132

133133
// Emit the callee.
134134
llvm::SmallVector<Arg, 4> args;
135+
// FIXME: emitCallee is currently broken; use an ugly workaround in the
136+
// meantime.
137+
#if 0
135138
Callee callee =
136139
emitCallee(IGF, injectionFn, out.getKind(), /*uncurry*/ 0, args);
140+
#else
141+
Explosion CalleeExplosion(ExplosionKind::Minimal);
142+
IGF.emitRValue(injectionFn, CalleeExplosion);
143+
llvm::Value *fn = CalleeExplosion.claimUnmanagedNext();
144+
llvm::Type *fnTy = IGF.IGM.getFunctionType(injectionFn->getType(),
145+
ExplosionKind::Minimal, 0, true);
146+
fn = IGF.Builder.CreateBitCast(fn, fnTy->getPointerTo());
147+
ManagedValue data = CalleeExplosion.claimNext();
148+
Callee callee = Callee::forIndirectCall(injectionFn->getType(), sliceTy,
149+
ArrayRef<Substitution>(), fn, data);
150+
#endif
137151

138152
// The injection function takes this tuple:
139153
// (Builtin.RawPointer, Builtin.ObjectPointer, typeof(length))

lib/IRGen/GenExpr.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ namespace {
300300
IGF.unimplemented(E->getLoc(), "specialize expressions");
301301
IGF.emitFakeExplosion(IGF.getFragileTypeInfo(E->getType()), Out);
302302
}
303+
void visitGetMetatypeExpr(GetMetatypeExpr *E) {
304+
IGF.emitIgnored(E->getSubExpr());
305+
}
303306
void visitTupleElementExpr(TupleElementExpr *E) {
304307
emitTupleElement(IGF, E, Out);
305308
}
@@ -462,6 +465,7 @@ namespace {
462465
NOT_LVALUE_EXPR(TupleShuffle)
463466
NOT_LVALUE_EXPR(Erasure)
464467
NOT_LVALUE_EXPR(Specialize) // FIXME: Generic subscripts?
468+
NOT_LVALUE_EXPR(GetMetatype)
465469
NOT_LVALUE_EXPR(Func)
466470
NOT_LVALUE_EXPR(Closure)
467471
NOT_LVALUE_EXPR(Load)
@@ -646,6 +650,7 @@ namespace {
646650
NON_LOCATEABLE(TupleShuffleExpr)
647651
NON_LOCATEABLE(ErasureExpr)
648652
NON_LOCATEABLE(SpecializeExpr) // FIXME: Generic subscripts?
653+
NON_LOCATEABLE(GetMetatypeExpr)
649654
NON_LOCATEABLE(CapturingExpr)
650655
NON_LOCATEABLE(ModuleExpr)
651656
NON_LOCATEABLE(DotSyntaxBaseIgnoredExpr)

lib/IRGen/GenFunc.cpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -1646,10 +1646,13 @@ static bool emitKnownCall(IRGenFunction &IGF, FuncDecl *Fn,
16461646
name != "Float" && name != "Double")
16471647
return false;
16481648

1649-
Expr *arg = callSites[0].getArg();
1649+
if (callSites.size() != 2)
1650+
return false;
1651+
1652+
Expr *arg = callSites[1].getArg();
16501653
Explosion &out = result.initForDirectValues(ExplosionKind::Maximal);
16511654
ExplosionSchema schema =
1652-
IGF.IGM.getSchema(callSites[0].getSubstResultType(), out.getKind());
1655+
IGF.IGM.getSchema(callSites[1].getSubstResultType(), out.getKind());
16531656
assert(schema.size() == 1);
16541657
llvm::Type *outTy = schema.begin()->getScalarType();
16551658
if (isa<llvm::IntegerType>(outTy)) {
@@ -1675,7 +1678,10 @@ static bool emitKnownCall(IRGenFunction &IGF, FuncDecl *Fn,
16751678
if (name != "Float" && name != "Double")
16761679
return false;
16771680

1678-
Expr *arg = callSites[0].getArg();
1681+
if (callSites.size() != 2)
1682+
return false;
1683+
1684+
Expr *arg = callSites[1].getArg();
16791685
Explosion &out = result.initForDirectValues(ExplosionKind::Maximal);
16801686
IGF.emitRValue(arg, out);
16811687
return true;

lib/IRGen/GenProto.cpp

+1-7
Original file line numberDiff line numberDiff line change
@@ -2279,7 +2279,7 @@ namespace {
22792279

22802280
void addStaticMethod(FuncDecl *iface) {
22812281
FuncDecl *impl = cast<FuncDecl>(Conformance.Mapping.find(iface)->second);
2282-
Table.push_back(getStaticMethodWitness(impl, iface->getType()));
2282+
Table.push_back(getInstanceMethodWitness(impl, iface->getType()));
22832283
}
22842284

22852285
void addInstanceMethod(FuncDecl *iface) {
@@ -2295,12 +2295,6 @@ namespace {
22952295
return getWitness(implPtr, impl->getType(), ifaceType, 1);
22962296
}
22972297

2298-
llvm::Constant *getStaticMethodWitness(FuncDecl *impl, Type ifaceType) {
2299-
llvm::Constant *implPtr =
2300-
IGM.getAddrOfFunction(impl, ExplosionKind::Minimal, 0, /*data*/ false);
2301-
return getWitness(implPtr, impl->getType(), ifaceType, 0);
2302-
}
2303-
23042298
llvm::Constant *getWitness(llvm::Constant *fn, Type fnTy, Type ifaceTy,
23052299
unsigned uncurryLevel) {
23062300
return WitnessBuilder(IGM, fn, fnTy, ifaceTy, uncurryLevel).get();

lib/IRGen/Mangle.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,6 @@ void Mangler::mangleType(Type type, ExplosionKind explosion,
297297
case TypeKind::UnboundGeneric:
298298
llvm_unreachable("mangling unresolved type");
299299

300-
case TypeKind::MetaType:
301-
llvm_unreachable("Cannot mangle metatype yet");
302300
case TypeKind::Module:
303301
llvm_unreachable("Cannot mangle module type yet");
304302

@@ -334,6 +332,11 @@ void Mangler::mangleType(Type type, ExplosionKind explosion,
334332
#define TYPE(id, parent)
335333
#include "swift/AST/TypeNodes.def"
336334

335+
case TypeKind::MetaType:
336+
Buffer << 'M';
337+
return mangleType(cast<MetaTypeType>(base)->getInstanceType(),
338+
ExplosionKind::Minimal, 0);
339+
337340
case TypeKind::LValue:
338341
Buffer << 'R';
339342
return mangleType(cast<LValueType>(base)->getObjectType(),

lib/IRGen/OptimizeARC.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,9 @@ static bool performARCExpansion(Function &F) {
11011101
CI.setTailCall(true);
11021102
Inst.eraseFromParent();
11031103

1104+
if (!isa<Instruction>(ArgVal))
1105+
continue;
1106+
11041107
TinyPtrVector<Instruction*> &GlobalEntry = DefsOfValue[ArgVal];
11051108

11061109
// If this is the first definition of a value for the argument that

lib/Parse/ParseDecl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ FuncDecl *Parser::parseDeclFunc(bool hasContainerType) {
11351135
// [byref] FooTy)->((int)->int)". Note that we can't actually compute the
11361136
// type here until Sema.
11371137
bool hasImplicitThis = false;
1138-
if (hasContainerType && !StaticLoc.isValid() && !Name.isOperator()) {
1138+
if (hasContainerType) {
11391139
Params.push_back(buildImplicitThisParameter());
11401140
hasImplicitThis = true;
11411141
}

lib/Sema/TypeCheckCoercion.cpp

+19-14
Original file line numberDiff line numberDiff line change
@@ -449,9 +449,16 @@ class SemaCoerce : public ExprVisitor<SemaCoerce, CoercedResult> {
449449
// If it does, then everything is good, resolve the reference.
450450
if (!(Flags & CF_Apply))
451451
return DED->getType();
452-
453-
return coerced(new (TC.Context) DeclRefExpr(DED, UME->getColonLoc(),
454-
DED->getType()));
452+
453+
if (!DED->hasArgumentType()) {
454+
return coerced(new (TC.Context) DeclRefExpr(DED, UME->getColonLoc(),
455+
DED->getType()));
456+
}
457+
458+
Expr *E = new (TC.Context) TypeOfExpr(UME->getColonLoc(),
459+
MetaTypeType::get(DT, TC.Context));
460+
E = TC.buildMemberRefExpr(E, SourceLoc(), DED, UME->getColonLoc());
461+
return coerced(TC.recheckTypes(E));
455462
}
456463

457464
CoercedResult visitParenExpr(ParenExpr *E) {
@@ -679,9 +686,8 @@ SemaCoerce::isLiteralCompatibleType(Type Ty, SourceLoc Loc, LiteralType LitTy) {
679686

680687
// Check that the type of the 'convertFrom*Literal' method makes
681688
// sense. We want a type of "S -> DestTy" where S is the expected type.
682-
AnyFunctionType *FT = cast<AnyFunctionType>(Method->getType());
683-
684-
// FIXME: PolymorphicFunctionType?
689+
AnyFunctionType *FT = Method->getType()->castTo<AnyFunctionType>();
690+
FT = FT->getResult()->castTo<AnyFunctionType>();
685691

686692
// The result of the convert function must be the destination type.
687693
if (!FT->getResult()->isEqual(Ty)) {
@@ -891,13 +897,12 @@ CoercedResult SemaCoerce::visitLiteralExpr(LiteralExpr *E) {
891897

892898
if (!(Flags & CF_Apply))
893899
return DestTy;
894-
895-
DeclRefExpr *DRE
896-
= new (TC.Context) DeclRefExpr(Method,
897-
// FIXME: This location is a hack!
898-
Intermediate->getStartLoc(),
899-
Method->getType());
900-
900+
901+
Expr *DRE = new (TC.Context) TypeOfExpr(Intermediate->getStartLoc(),
902+
Method->computeThisType());
903+
DRE = TC.recheckTypes(TC.buildMemberRefExpr(DRE, SourceLoc(), Method,
904+
Intermediate->getStartLoc()));
905+
901906
// Return a new call of the conversion function, passing in the integer
902907
// literal.
903908
return coerced(new (TC.Context) CallExpr(DRE, Intermediate, DestTy));
@@ -1708,7 +1713,7 @@ SemaCoerce::coerceObjectArgument(Expr *E, Type ContainerTy, CoercionContext &CC,
17081713
return nullptr;
17091714
}
17101715

1711-
if (SrcObjectTy->hasReferenceSemantics()) {
1716+
if (SrcObjectTy->hasReferenceSemantics() || SrcObjectTy->is<MetaTypeType>()) {
17121717
// The destination type is just the source object type.
17131718
if (!(Flags & CF_Apply))
17141719
return SrcObjectTy;

lib/Sema/TypeCheckDecl.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -577,9 +577,13 @@ void DeclChecker::validateAttributes(ValueDecl *VD) {
577577

578578
// Get the number of lexical arguments, for semantic checks below.
579579
int NumArguments = -1;
580-
if (AnyFunctionType *FT = dyn_cast<AnyFunctionType>(Ty))
580+
if (AnyFunctionType *FT = dyn_cast<AnyFunctionType>(Ty)) {
581+
if (isa<FuncDecl>(VD) && VD->getDeclContext()->isTypeContext() &&
582+
cast<FuncDecl>(VD)->isStatic())
583+
FT = FT->getResult()->castTo<AnyFunctionType>();
581584
if (TupleType *TT = dyn_cast<TupleType>(FT->getInput()))
582585
NumArguments = TT->getFields().size();
586+
}
583587

584588
bool isOperator = VD->isOperator();
585589

0 commit comments

Comments
 (0)