Skip to content

Commit 4d60ec3

Browse files
committed
AST/SILGen support for constant string literals
rdar://30545013
1 parent ea48ab5 commit 4d60ec3

File tree

10 files changed

+121
-10
lines changed

10 files changed

+121
-10
lines changed

include/swift/AST/Expr.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class alignas(8) Expr {
157157
friend class StringLiteralExpr;
158158
unsigned : NumLiteralExprBits;
159159

160-
unsigned Encoding : 2;
160+
unsigned Encoding : 3;
161161
unsigned IsSingleUnicodeScalar : 1;
162162
unsigned IsSingleExtendedGraphemeCluster : 1;
163163
};
@@ -940,6 +940,12 @@ class StringLiteralExpr : public LiteralExpr {
940940
/// A UTF-16 string.
941941
UTF16,
942942

943+
/// A UTF-8 constant string.
944+
UTF8ConstString,
945+
946+
/// A UTF-16 constant string.
947+
UTF16ConstString,
948+
943949
/// A single UnicodeScalar, passed as an integer.
944950
OneUnicodeScalar
945951
};

include/swift/AST/KnownIdentifiers.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ IDENTIFIER(unicodeScalarLiteral)
123123
IDENTIFIER(stringLiteral)
124124
IDENTIFIER_(builtinUTF16StringLiteral)
125125
IDENTIFIER_(builtinStringLiteral)
126+
IDENTIFIER_(builtinConstUTF16StringLiteral)
127+
IDENTIFIER_(builtinConstStringLiteral)
126128
IDENTIFIER(StringLiteralType)
127129
IDENTIFIER(stringInterpolation)
128130
IDENTIFIER(stringInterpolationSegment)

include/swift/AST/KnownProtocols.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ BUILTIN_EXPRESSIBLE_BY_LITERAL_PROTOCOL_(ExpressibleByBuiltinIntegerLiteral)
8787
BUILTIN_EXPRESSIBLE_BY_LITERAL_PROTOCOL_(ExpressibleByBuiltinStringLiteral)
8888
BUILTIN_EXPRESSIBLE_BY_LITERAL_PROTOCOL_(ExpressibleByBuiltinUTF16StringLiteral)
8989
BUILTIN_EXPRESSIBLE_BY_LITERAL_PROTOCOL_(ExpressibleByBuiltinUnicodeScalarLiteral)
90+
BUILTIN_EXPRESSIBLE_BY_LITERAL_PROTOCOL_(ExpressibleByBuiltinConstStringLiteral)
91+
BUILTIN_EXPRESSIBLE_BY_LITERAL_PROTOCOL_(ExpressibleByBuiltinConstUTF16StringLiteral)
9092

9193
#undef EXPRESSIBLE_BY_LITERAL_PROTOCOL
9294
#undef EXPRESSIBLE_BY_LITERAL_PROTOCOL_

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 332; // Last change: constant_string_literal
57+
const uint16_t VERSION_MINOR = 333; // Last change: AST constant_string_literal
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;

lib/AST/ASTDumper.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,10 @@ getStringLiteralExprEncodingString(StringLiteralExpr::Encoding value) {
359359
switch (value) {
360360
case StringLiteralExpr::UTF8: return "utf8";
361361
case StringLiteralExpr::UTF16: return "utf16";
362+
case StringLiteralExpr::UTF8ConstString:
363+
return "utf8_const_string";
364+
case StringLiteralExpr::UTF16ConstString:
365+
return "utf16_const_string";
362366
case StringLiteralExpr::OneUnicodeScalar: return "unicodeScalar";
363367
}
364368

lib/IRGen/GenMeta.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5526,6 +5526,8 @@ SpecialProtocol irgen::getSpecialProtocolID(ProtocolDecl *P) {
55265526
case KnownProtocolKind::BridgedNSError:
55275527
case KnownProtocolKind::BridgedStoredNSError:
55285528
case KnownProtocolKind::ErrorCodeProtocol:
5529+
case KnownProtocolKind::ExpressibleByBuiltinConstStringLiteral:
5530+
case KnownProtocolKind::ExpressibleByBuiltinConstUTF16StringLiteral:
55295531
return SpecialProtocol::None;
55305532
}
55315533

lib/SILGen/SILGenApply.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,8 +1519,9 @@ static RValue emitStringLiteral(SILGenFunction &SGF, Expr *E, StringRef Str,
15191519
break;
15201520
}
15211521
}
1522-
1522+
bool useConstantStringBuiltin = false;
15231523
StringLiteralInst::Encoding instEncoding;
1524+
ConstStringLiteralInst::Encoding constInstEncoding;
15241525
switch (encoding) {
15251526
case StringLiteralExpr::UTF8:
15261527
instEncoding = StringLiteralInst::Encoding::UTF8;
@@ -1532,6 +1533,16 @@ static RValue emitStringLiteral(SILGenFunction &SGF, Expr *E, StringRef Str,
15321533
Length = unicode::getUTF16Length(Str);
15331534
break;
15341535
}
1536+
case StringLiteralExpr::UTF8ConstString:
1537+
constInstEncoding = ConstStringLiteralInst::Encoding::UTF8;
1538+
useConstantStringBuiltin = true;
1539+
break;
1540+
1541+
case StringLiteralExpr::UTF16ConstString: {
1542+
constInstEncoding = ConstStringLiteralInst::Encoding::UTF16;
1543+
useConstantStringBuiltin = true;
1544+
break;
1545+
}
15351546
case StringLiteralExpr::OneUnicodeScalar: {
15361547
SILType Int32Ty = SILType::getBuiltinIntegerType(32, SGF.getASTContext());
15371548
SILValue UnicodeScalarValue =
@@ -1542,8 +1553,18 @@ static RValue emitStringLiteral(SILGenFunction &SGF, Expr *E, StringRef Str,
15421553
}
15431554
}
15441555

1556+
// Should we build a constant string literal?
1557+
if (useConstantStringBuiltin) {
1558+
auto *string = SGF.B.createConstStringLiteral(E, Str, constInstEncoding);
1559+
ManagedValue Elts[] = {ManagedValue::forUnmanaged(string)};
1560+
TupleTypeElt TypeElts[] = {Elts[0].getType().getSwiftRValueType()};
1561+
CanType ty =
1562+
TupleType::get(TypeElts, SGF.getASTContext())->getCanonicalType();
1563+
return RValue::withPreExplodedElements(Elts, ty);
1564+
}
1565+
15451566
// The string literal provides the data.
1546-
StringLiteralInst *string = SGF.B.createStringLiteral(E, Str, instEncoding);
1567+
auto *string = SGF.B.createStringLiteral(E, Str, instEncoding);
15471568

15481569
// The length is lowered as an integer_literal.
15491570
auto WordTy = SILType::getBuiltinWordType(SGF.getASTContext());

lib/Sema/CSApply.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,18 +1958,49 @@ namespace {
19581958
builtinProtocol = tc.getProtocol(
19591959
expr->getLoc(),
19601960
KnownProtocolKind::ExpressibleByBuiltinUTF16StringLiteral);
1961+
auto *builtinConstUTF16StringProtocol = tc.getProtocol(
1962+
expr->getLoc(),
1963+
KnownProtocolKind::ExpressibleByBuiltinConstUTF16StringLiteral);
1964+
auto *builtinConstStringProtocol = tc.getProtocol(
1965+
expr->getLoc(),
1966+
KnownProtocolKind::ExpressibleByBuiltinConstStringLiteral);
1967+
1968+
// First try the constant string protocols.
19611969
if (!forceASCII &&
1962-
tc.conformsToProtocol(type, builtinProtocol, cs.DC,
1963-
ConformanceCheckFlags::InExpression)) {
1964-
builtinLiteralFuncName
1965-
= DeclName(tc.Context, tc.Context.Id_init,
1966-
{ tc.Context.Id_builtinUTF16StringLiteral,
1967-
tc.Context.getIdentifier("utf16CodeUnitCount") });
1970+
(tc.conformsToProtocol(type, builtinConstUTF16StringProtocol, cs.DC,
1971+
ConformanceCheckFlags::InExpression))) {
1972+
builtinProtocol = builtinConstUTF16StringProtocol;
1973+
builtinLiteralFuncName =
1974+
DeclName(tc.Context, tc.Context.Id_init,
1975+
{tc.Context.Id_builtinConstUTF16StringLiteral});
1976+
1977+
if (stringLiteral)
1978+
stringLiteral->setEncoding(StringLiteralExpr::UTF16ConstString);
1979+
else
1980+
magicLiteral->setStringEncoding(StringLiteralExpr::UTF16);
1981+
} else if (!forceASCII && (tc.conformsToProtocol(
1982+
type, builtinProtocol, cs.DC,
1983+
ConformanceCheckFlags::InExpression))) {
1984+
builtinLiteralFuncName =
1985+
DeclName(tc.Context, tc.Context.Id_init,
1986+
{tc.Context.Id_builtinUTF16StringLiteral,
1987+
tc.Context.getIdentifier("utf16CodeUnitCount")});
19681988

19691989
if (stringLiteral)
19701990
stringLiteral->setEncoding(StringLiteralExpr::UTF16);
19711991
else
19721992
magicLiteral->setStringEncoding(StringLiteralExpr::UTF16);
1993+
} else if (tc.conformsToProtocol(type, builtinConstStringProtocol,
1994+
cs.DC,
1995+
ConformanceCheckFlags::InExpression)) {
1996+
builtinProtocol = builtinConstStringProtocol;
1997+
builtinLiteralFuncName =
1998+
DeclName(tc.Context, tc.Context.Id_init,
1999+
{tc.Context.Id_builtinConstStringLiteral});
2000+
if (stringLiteral)
2001+
stringLiteral->setEncoding(StringLiteralExpr::UTF8ConstString);
2002+
else
2003+
magicLiteral->setStringEncoding(StringLiteralExpr::UTF8);
19732004
} else {
19742005
// Otherwise, fall back to UTF-8.
19752006
builtinProtocol = tc.getProtocol(

stdlib/public/core/CompilerProtocols.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,18 @@ public protocol _ExpressibleByBuiltinUTF16StringLiteral
412412
utf16CodeUnitCount: Builtin.Word)
413413
}
414414

415+
public protocol _ExpressibleByBuiltinConstStringLiteral
416+
: _ExpressibleByBuiltinExtendedGraphemeClusterLiteral {
417+
418+
init(_builtinConstStringLiteral constantString: Builtin.RawPointer)
419+
}
420+
421+
public protocol _ExpressibleByBuiltinConstUTF16StringLiteral
422+
: _ExpressibleByBuiltinConstStringLiteral {
423+
424+
init(_builtinConstUTF16StringLiteral constantUTF16String: Builtin.RawPointer)
425+
}
426+
415427
/// A type that can be initialized with a string literal.
416428
///
417429
/// The `String` and `StaticString` types conform to the

test/SILGen/expressions.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,48 @@ struct SillyUTF16String : _ExpressibleByBuiltinUTF16StringLiteral, ExpressibleBy
5858
init(stringLiteral value: SillyUTF16String) { }
5959
}
6060

61+
struct SillyConstUTF16String : _ExpressibleByBuiltinConstUTF16StringLiteral, ExpressibleByStringLiteral {
62+
init(_builtinUnicodeScalarLiteral value: Builtin.Int32) { }
63+
64+
init(unicodeScalarLiteral value: SillyString) { }
65+
66+
init(
67+
_builtinExtendedGraphemeClusterLiteral start: Builtin.RawPointer,
68+
utf8CodeUnitCount: Builtin.Word,
69+
isASCII: Builtin.Int1
70+
) {
71+
}
72+
73+
init(extendedGraphemeClusterLiteral value: SillyString) { }
74+
75+
init( _builtinConstStringLiteral start: Builtin.RawPointer) { }
76+
77+
init( _builtinConstUTF16StringLiteral start: Builtin.RawPointer) { }
78+
79+
init(stringLiteral value: SillyUTF16String) { }
80+
}
81+
6182
func literals() {
6283
var a = 1
6384
var b = 1.25
6485
var d = "foö"
6586
var e:SillyString = "foo"
87+
88+
var f:SillyConstUTF16String = "foobar"
89+
var non_ascii:SillyConstUTF16String = "foobarö"
6690
}
6791
// CHECK-LABEL: sil hidden @_T011expressions8literalsyyF
6892
// CHECK: integer_literal $Builtin.Int2048, 1
6993
// CHECK: float_literal $Builtin.FPIEEE{{64|80}}, {{0x3FF4000000000000|0x3FFFA000000000000000}}
7094
// CHECK: string_literal utf16 "foö"
7195
// CHECK: string_literal utf8 "foo"
96+
// CHECK: [[CONST_STRING_LIT:%.*]] = const_string_literal utf8 "foobar"
97+
// CHECK: [[METATYPE:%.*]] = metatype $@thin SillyConstUTF16String.Type
98+
// CHECK: [[FUN:%.*]] = function_ref @_T011expressions21SillyConstUTF16StringVACBp08_builtincE7Literal_tcfC : $@convention(method) (Builtin.RawPointer, @thin SillyConstUTF16String.Type) -> SillyConstUTF16String
99+
// CHECK: apply [[FUN]]([[CONST_STRING_LIT]], [[METATYPE]]) : $@convention(method) (Builtin.RawPointer, @thin SillyConstUTF16String.Type) -> SillyConstUTF16String
100+
// CHECK: [[CONST_UTF16STRING_LIT:%.*]] = const_string_literal utf16 "foobarö"
101+
// CHECK: [[FUN:%.*]] = function_ref @_T011expressions21SillyConstUTF16StringVACBp08_builtincdE7Literal_tcfC : $@convention(method) (Builtin.RawPointer, @thin SillyConstUTF16String.Type) -> SillyConstUTF16String
102+
// CHECK: apply [[FUN]]([[CONST_UTF16STRING_LIT]], {{.*}}) : $@convention(method) (Builtin.RawPointer, @thin SillyConstUTF16String.Type) -> SillyConstUTF16String
72103

73104
func bar(_ x: Int) {}
74105
func bar(_ x: Int, _ y: Int) {}

0 commit comments

Comments
 (0)