Skip to content

Commit 5160da6

Browse files
committed
FloatLiteralExpr now is lowered directly into SIL.
For context, String, Nil, Bool, and Int already behave this way. Note: Swift can compile against 80 or 64 bit floats as the builtin literal type. Thus, it was necessary to capture this bit somehow in the FloatLiteralExpr. This was done as another Type field capturing this info.
1 parent 22bcbe5 commit 5160da6

File tree

12 files changed

+75
-256
lines changed

12 files changed

+75
-256
lines changed

include/swift/AST/Expr.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -823,11 +823,11 @@ class NumberLiteralExpr : public LiteralExpr {
823823
}
824824
};
825825

826-
827826
/// Integer literal with a '+' or '-' sign, like '+4' or '- 2'.
828827
///
829-
/// After semantic analysis assigns types, this is guaranteed to only have
830-
/// a BuiltinIntegerType.
828+
/// After semantic analysis assigns types, this is guaranteed to have
829+
/// a BuiltinIntegerType or be a normal type and implicitly be
830+
/// AnyBuiltinIntegerType.
831831
class IntegerLiteralExpr : public NumberLiteralExpr {
832832
public:
833833
IntegerLiteralExpr(StringRef Val, SourceLoc DigitsLoc, bool Implicit = false)
@@ -855,9 +855,12 @@ class IntegerLiteralExpr : public NumberLiteralExpr {
855855
};
856856

857857
/// FloatLiteralExpr - Floating point literal, like '4.0'. After semantic
858-
/// analysis assigns types, this is guaranteed to only have a
858+
/// analysis assigns types, BuiltinTy is guaranteed to only have a
859859
/// BuiltinFloatingPointType.
860860
class FloatLiteralExpr : public NumberLiteralExpr {
861+
/// This is the type of the builtin literal.
862+
Type BuiltinTy;
863+
861864
public:
862865
FloatLiteralExpr(StringRef Val, SourceLoc Loc, bool Implicit = false)
863866
: NumberLiteralExpr(ExprKind::FloatLiteral, Val, Loc, Implicit)
@@ -870,6 +873,9 @@ class FloatLiteralExpr : public NumberLiteralExpr {
870873
static bool classof(const Expr *E) {
871874
return E->getKind() == ExprKind::FloatLiteral;
872875
}
876+
877+
Type getBuiltinType() const { return BuiltinTy; }
878+
void setBuiltinType(Type ty) { BuiltinTy = ty; }
873879
};
874880

875881
/// A Boolean literal ('true' or 'false')

lib/AST/ASTDumper.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,6 +1831,16 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
18311831
printCommon(E, "float_literal_expr");
18321832
PrintWithColorRAII(OS, LiteralValueColor)
18331833
<< " value=" << E->getDigitsText();
1834+
PrintWithColorRAII(OS, LiteralValueColor) << " builtin_initializer=";
1835+
E->getBuiltinInitializer().dump(
1836+
PrintWithColorRAII(OS, LiteralValueColor).getOS());
1837+
PrintWithColorRAII(OS, LiteralValueColor) << " initializer=";
1838+
E->getInitializer().dump(PrintWithColorRAII(OS, LiteralValueColor).getOS());
1839+
if (!E->getBuiltinType().isNull()) {
1840+
PrintWithColorRAII(OS, TypeColor) << " builtin_type='";
1841+
E->getBuiltinType().print(PrintWithColorRAII(OS, TypeColor).getOS());
1842+
PrintWithColorRAII(OS, TypeColor) << "'";
1843+
}
18341844
PrintWithColorRAII(OS, ParenthesisColor) << ')';
18351845
}
18361846

lib/AST/Expr.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -974,8 +974,16 @@ llvm::APFloat FloatLiteralExpr::getValue() const {
974974
assert(!getType().isNull() && "Semantic analysis has not completed");
975975
assert(!getType()->hasError() && "Should have a valid type");
976976

977-
return getFloatLiteralValue(isNegative(), getDigitsText(),
978-
getType()->castTo<BuiltinFloatType>()->getAPFloatSemantics());
977+
Type ty = getType();
978+
if (!ty->is<BuiltinFloatType>()) {
979+
assert(!getBuiltinType().isNull() && "Semantic analysis has not completed");
980+
assert(!getBuiltinType()->hasError() && "Should have a valid type");
981+
ty = getBuiltinType();
982+
}
983+
984+
return getFloatLiteralValue(
985+
isNegative(), getDigitsText(),
986+
ty->castTo<BuiltinFloatType>()->getAPFloatSemantics());
979987
}
980988

981989
StringLiteralExpr::StringLiteralExpr(StringRef Val, SourceRange Range,

lib/SILGen/SILGenApply.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5543,10 +5543,21 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) {
55435543
integerLiteral,
55445544
SILType::getBuiltinIntegerLiteralType(getASTContext()),
55455545
integerLiteral->getRawValue()));
5546-
CanType ty = integerManaged.getType().getASTType()->getCanonicalType();
5546+
CanType ty = integerManaged.getType().getASTType();
55475547
builtinLiteralArgs = RValue(*this, {integerManaged}, ty);
55485548
builtinInit = integerLiteral->getBuiltinInitializer();
55495549
init = integerLiteral->getInitializer();
5550+
} else if (auto floatLiteral = dyn_cast<FloatLiteralExpr>(literal)) {
5551+
auto *litTy = floatLiteral->getBuiltinType()->castTo<BuiltinFloatType>();
5552+
ManagedValue floatManaged = ManagedValue::forUnmanaged(B.createFloatLiteral(
5553+
floatLiteral,
5554+
SILType::getBuiltinFloatType(litTy->getFPKind(), getASTContext()),
5555+
floatLiteral->getValue()));
5556+
5557+
CanType ty = floatManaged.getType().getASTType();
5558+
builtinLiteralArgs = RValue(*this, {floatManaged}, ty);
5559+
builtinInit = floatLiteral->getBuiltinInitializer();
5560+
init = floatLiteral->getInitializer();
55505561
} else {
55515562
ASTContext &ctx = getASTContext();
55525563
SourceLoc loc = literal->getStartLoc();

lib/SILGen/SILGenExpr.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -959,8 +959,11 @@ RValue RValueEmitter::visitIntegerLiteralExpr(IntegerLiteralExpr *E,
959959
}
960960
RValue RValueEmitter::visitFloatLiteralExpr(FloatLiteralExpr *E,
961961
SGFContext C) {
962-
return RValue(SGF, E,
963-
ManagedValue::forUnmanaged(SGF.B.createFloatLiteral(E)));
962+
if (E->getType()->is<BuiltinFloatType>())
963+
return RValue(SGF, E,
964+
ManagedValue::forUnmanaged(SGF.B.createFloatLiteral(E)));
965+
966+
return SGF.emitLiteral(E, C);
964967
}
965968

966969
RValue RValueEmitter::visitBooleanLiteralExpr(BooleanLiteralExpr *E,

lib/SILOptimizer/Utils/ConstantFolding.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,9 @@ static SILValue foldFPTrunc(BuiltinInst *BI, const BuiltinInfo &Builtin,
11221122
tryExtractLiteralText(flitInst, fplitStr);
11231123

11241124
auto userType = CE ? CE->getType() : destType;
1125+
if (auto *FLE = Loc.getAsASTNode<FloatLiteralExpr>()) {
1126+
userType = FLE->getType();
1127+
}
11251128
auto diagId = overflow
11261129
? diag::warning_float_trunc_overflow
11271130
: (hexnInexact ? diag::warning_float_trunc_hex_inexact

lib/Sema/CSApply.cpp

Lines changed: 5 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,65 +1060,6 @@ namespace {
10601060
/// Describes either a type or the name of a type to be resolved.
10611061
using TypeOrName = llvm::PointerUnion<Identifier, Type>;
10621062

1063-
/// Convert the given literal expression via a protocol pair.
1064-
///
1065-
/// This routine handles the two-step literal conversion process used
1066-
/// by integer, float, character, extended grapheme cluster, and string
1067-
/// literals. The first step uses \c builtinProtocol while the second
1068-
/// step uses \c protocol.
1069-
///
1070-
/// \param literal The literal expression.
1071-
///
1072-
/// \param type The literal type. This type conforms to \c protocol,
1073-
/// and may also conform to \c builtinProtocol.
1074-
///
1075-
/// \param openedType The literal type as it was opened in the type system.
1076-
///
1077-
/// \param protocol The protocol that describes the literal requirement.
1078-
///
1079-
/// \param literalType Either the name of the associated type in
1080-
/// \c protocol that describes the argument type of the conversion function
1081-
/// (\c literalFuncName) or the argument type itself.
1082-
///
1083-
/// \param literalFuncName The name of the conversion function requirement
1084-
/// in \c protocol.
1085-
///
1086-
/// \param builtinProtocol The "builtin" form of the protocol, which
1087-
/// always takes builtin types and can only be properly implemented
1088-
/// by standard library types. If \c type does not conform to this
1089-
/// protocol, it's literal type will.
1090-
///
1091-
/// \param builtinLiteralType Either the name of the associated type in
1092-
/// \c builtinProtocol that describes the argument type of the builtin
1093-
/// conversion function (\c builtinLiteralFuncName) or the argument type
1094-
/// itself.
1095-
///
1096-
/// \param builtinLiteralFuncName The name of the conversion function
1097-
/// requirement in \c builtinProtocol.
1098-
///
1099-
/// \param isBuiltinArgType Function that determines whether the given
1100-
/// type is acceptable as the argument type for the builtin conversion.
1101-
///
1102-
/// \param brokenProtocolDiag The diagnostic to emit if the protocol
1103-
/// is broken.
1104-
///
1105-
/// \param brokenBuiltinProtocolDiag The diagnostic to emit if the builtin
1106-
/// protocol is broken.
1107-
///
1108-
/// \returns the converted literal expression.
1109-
Expr *convertLiteral(Expr *literal,
1110-
Type type,
1111-
Type openedType,
1112-
ProtocolDecl *protocol,
1113-
TypeOrName literalType,
1114-
DeclName literalFuncName,
1115-
ProtocolDecl *builtinProtocol,
1116-
TypeOrName builtinLiteralType,
1117-
DeclName builtinLiteralFuncName,
1118-
bool (*isBuiltinArgType)(Type),
1119-
Diag<> brokenProtocolDiag,
1120-
Diag<> brokenBuiltinProtocolDiag);
1121-
11221063
/// Convert the given literal expression via a protocol pair.
11231064
///
11241065
/// This routine handles the two-step literal conversion process used
@@ -1903,19 +1844,11 @@ namespace {
19031844
DeclName builtinInitName(tc.Context, DeclBaseName::createConstructor(),
19041845
{ tc.Context.Id_builtinFloatLiteral });
19051846

1906-
return convertLiteral(
1907-
expr,
1908-
type,
1909-
cs.getType(expr),
1910-
protocol,
1911-
tc.Context.Id_FloatLiteralType,
1912-
initName,
1913-
builtinProtocol,
1914-
maxType,
1915-
builtinInitName,
1916-
nullptr,
1917-
diag::float_literal_broken_proto,
1918-
diag::builtin_float_literal_broken_proto);
1847+
expr->setBuiltinType(maxType);
1848+
return convertLiteralInPlace(
1849+
expr, type, protocol, tc.Context.Id_FloatLiteralType, initName,
1850+
builtinProtocol, builtinInitName, diag::float_literal_broken_proto,
1851+
diag::builtin_float_literal_broken_proto);
19191852
}
19201853

19211854
Expr *visitBooleanLiteralExpr(BooleanLiteralExpr *expr) {
@@ -6865,157 +6798,6 @@ ExprRewriter::coerceObjectArgumentToType(Expr *expr,
68656798
/*isImplicit*/ true));
68666799
}
68676800

6868-
Expr *ExprRewriter::convertLiteral(Expr *literal,
6869-
Type type,
6870-
Type openedType,
6871-
ProtocolDecl *protocol,
6872-
TypeOrName literalType,
6873-
DeclName literalFuncName,
6874-
ProtocolDecl *builtinProtocol,
6875-
TypeOrName builtinLiteralType,
6876-
DeclName builtinLiteralFuncName,
6877-
bool (*isBuiltinArgType)(Type),
6878-
Diag<> brokenProtocolDiag,
6879-
Diag<> brokenBuiltinProtocolDiag) {
6880-
auto &tc = cs.getTypeChecker();
6881-
6882-
auto getType = [&](const Expr *E) -> Type {
6883-
return cs.getType(E);
6884-
};
6885-
6886-
auto setType = [&](Expr *E, Type Ty) {
6887-
cs.setType(E, Ty);
6888-
};
6889-
6890-
// If coercing a literal to an unresolved type, we don't try to look up the
6891-
// witness members, just do it.
6892-
if (type->is<UnresolvedType>()) {
6893-
// Instead of updating the literal expr in place, allocate a new node. This
6894-
// avoids issues where Builtin types end up on expr nodes and pollute
6895-
// diagnostics.
6896-
literal = cast<LiteralExpr>(literal)->shallowClone(tc.Context, setType,
6897-
getType);
6898-
6899-
// The literal expression has this type.
6900-
cs.setType(literal, type);
6901-
return literal;
6902-
}
6903-
6904-
// Check whether this literal type conforms to the builtin protocol.
6905-
Optional<ProtocolConformanceRef> builtinConformance;
6906-
if (builtinProtocol &&
6907-
(builtinConformance =
6908-
tc.conformsToProtocol(
6909-
type, builtinProtocol, cs.DC,
6910-
(ConformanceCheckFlags::InExpression)))) {
6911-
6912-
// Find the builtin argument type we'll use.
6913-
Type argType;
6914-
if (builtinLiteralType.is<Type>())
6915-
argType = builtinLiteralType.get<Type>();
6916-
else
6917-
argType = tc.getWitnessType(type, builtinProtocol,
6918-
*builtinConformance,
6919-
builtinLiteralType.get<Identifier>(),
6920-
brokenBuiltinProtocolDiag);
6921-
6922-
if (!argType)
6923-
return nullptr;
6924-
6925-
// Make sure it's of an appropriate builtin type.
6926-
if (isBuiltinArgType && !isBuiltinArgType(argType)) {
6927-
tc.diagnose(builtinProtocol->getLoc(), brokenBuiltinProtocolDiag);
6928-
return nullptr;
6929-
}
6930-
6931-
// Instead of updating the literal expr in place, allocate a new node. This
6932-
// avoids issues where Builtin types end up on expr nodes and pollute
6933-
// diagnostics.
6934-
literal = cast<LiteralExpr>(literal)->shallowClone(tc.Context, setType,
6935-
getType);
6936-
6937-
// The literal expression has this type.
6938-
cs.setType(literal, argType);
6939-
6940-
// Call the builtin conversion operation.
6941-
// FIXME: Bogus location info.
6942-
Expr *base =
6943-
TypeExpr::createImplicitHack(literal->getLoc(), type, tc.Context);
6944-
6945-
cs.cacheExprTypes(base);
6946-
cs.setExprTypes(base);
6947-
cs.setExprTypes(literal);
6948-
SmallVector<Expr *, 1> arguments = { literal };
6949-
6950-
Expr *result = tc.callWitness(base, dc,
6951-
builtinProtocol, *builtinConformance,
6952-
builtinLiteralFuncName,
6953-
arguments,
6954-
brokenBuiltinProtocolDiag);
6955-
if (result)
6956-
cs.cacheExprTypes(result);
6957-
6958-
return result;
6959-
}
6960-
6961-
// This literal type must conform to the (non-builtin) protocol.
6962-
assert(protocol && "requirements should have stopped recursion");
6963-
auto conformance = tc.conformsToProtocol(type, protocol, cs.DC,
6964-
ConformanceCheckFlags::InExpression);
6965-
assert(conformance && "must conform to literal protocol");
6966-
6967-
// Figure out the (non-builtin) argument type if there is one.
6968-
Type argType;
6969-
if (literalType.is<Identifier>() &&
6970-
literalType.get<Identifier>().empty()) {
6971-
// If there is no argument to the constructor function, then just pass in
6972-
// the empty tuple.
6973-
literal =
6974-
cs.cacheType(
6975-
TupleExpr::createEmpty(tc.Context, literal->getLoc(),
6976-
literal->getLoc(),
6977-
/*implicit*/!literal->getLoc().isValid()));
6978-
} else {
6979-
// Otherwise, figure out the type of the constructor function and coerce to
6980-
// it.
6981-
if (literalType.is<Type>())
6982-
argType = literalType.get<Type>();
6983-
else
6984-
argType = tc.getWitnessType(type, protocol, *conformance,
6985-
literalType.get<Identifier>(),
6986-
brokenProtocolDiag);
6987-
if (!argType)
6988-
return nullptr;
6989-
6990-
// Convert the literal to the non-builtin argument type via the
6991-
// builtin protocol, first.
6992-
// FIXME: Do we need an opened type here?
6993-
literal = convertLiteral(literal, argType, argType, nullptr, Identifier(),
6994-
Identifier(), builtinProtocol,
6995-
builtinLiteralType, builtinLiteralFuncName,
6996-
isBuiltinArgType, brokenProtocolDiag,
6997-
brokenBuiltinProtocolDiag);
6998-
if (!literal)
6999-
return nullptr;
7000-
}
7001-
7002-
// Convert the resulting expression to the final literal type.
7003-
// FIXME: Bogus location info.
7004-
Expr *base = TypeExpr::createImplicitHack(literal->getLoc(), type,
7005-
tc.Context);
7006-
cs.cacheExprTypes(base);
7007-
cs.setExprTypes(base);
7008-
cs.setExprTypes(literal);
7009-
7010-
literal = tc.callWitness(base, dc,
7011-
protocol, *conformance, literalFuncName,
7012-
literal, brokenProtocolDiag);
7013-
if (literal)
7014-
cs.cacheExprTypes(literal);
7015-
7016-
return literal;
7017-
}
7018-
70196801
Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
70206802
Type type,
70216803
ProtocolDecl *protocol,

test/SILGen/default_arguments.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ func defarg1(i: Int = 17, d: Double, s: String = "Hello") { }
2626

2727
// CHECK-LABEL: sil hidden [ossa] @$s17default_arguments15testDefaultArg1yyF
2828
func testDefaultArg1() {
29-
// CHECK: [[FLOAT64:%[0-9]+]] = metatype $@thin Double.Type
3029
// CHECK: [[FLOATLIT:%[0-9]+]] = float_literal $Builtin.FPIEEE{{64|80}}, {{0x4009000000000000|0x4000C800000000000000}}
30+
// CHECK: [[FLOAT64:%[0-9]+]] = metatype $@thin Double.Type
3131
// CHECK: [[LITFN:%[0-9]+]] = function_ref @$sSd20_builtinFloatLiteralSdBf{{[_0-9]*}}__tcfC
3232
// CHECK: [[FLOATVAL:%[0-9]+]] = apply [[LITFN]]([[FLOATLIT]], [[FLOAT64]])
3333
// CHECK: [[DEF0FN:%[0-9]+]] = function_ref @$s17default_arguments7defarg1{{.*}}A_

test/SILGen/default_constructor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ struct D {
1919
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Int.Type
2020
// CHECK: [[FN:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
2121
// CHECK-NEXT: [[LEFT:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
22-
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Double.Type
2322
// CHECK-NEXT: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE{{64|80}}, {{0x400C000000000000|0x4000E000000000000000}}
23+
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Double.Type
2424
// CHECK: [[FN:%.*]] = function_ref @$sSd20_builtinFloatLiteralSdBf{{64|80}}__tcfC : $@convention(method) (Builtin.FPIEEE{{64|80}}, @thin Double.Type) -> Double
2525
// CHECK-NEXT: [[RIGHT:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE{{64|80}}, @thin Double.Type) -> Double
2626
// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[LEFT]] : $Int, [[RIGHT]] : $Double)

0 commit comments

Comments
 (0)