Skip to content

Commit 50b2442

Browse files
committed
SILGen: Stop using "scalar" PreparedArguments except for ArgumentShuffleExpr
For anything else, we can decompose the argument list on the spot. Note that builtins that are implemented as EarlyEmitters now take a the argument list as a PreparedArguments instead of a single Expr. Since the PreparedArguments can still be a scalar with an ArgumentShuffleExpr, we have to jump through some hoops to turn it into a list of argument Exprs. This will all go away soon.
1 parent d7ba72f commit 50b2442

File tree

6 files changed

+82
-53
lines changed

6 files changed

+82
-53
lines changed

lib/SILGen/ArgumentSource.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,22 @@ void ArgumentSource::dump(raw_ostream &out, unsigned indent) const {
261261
llvm_unreachable("bad kind");
262262
}
263263

264+
PreparedArguments::PreparedArguments(
265+
ArrayRef<AnyFunctionType::Param> params,
266+
Expr *arg) : PreparedArguments(params, /*scalar*/ isa<ArgumentShuffleExpr>(arg)) {
267+
if (isa<ArgumentShuffleExpr>(arg))
268+
addArbitrary(arg);
269+
else if (auto *PE = dyn_cast<ParenExpr>(arg))
270+
addArbitrary(PE->getSubExpr());
271+
else if (auto *TE = dyn_cast<TupleExpr>(arg)) {
272+
for (auto *elt : TE->getElements())
273+
addArbitrary(elt);
274+
} else {
275+
// FIXME: All ApplyExprs should have a ParenExpr or TupleExpr as their argument
276+
addArbitrary(arg);
277+
}
278+
}
279+
264280
void PreparedArguments::emplaceEmptyArgumentList(SILGenFunction &SGF) {
265281
emplace({}, /*scalar*/ false);
266282
assert(isValid());

lib/SILGen/ArgumentSource.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ class PreparedArguments {
273273
emplace(params, isScalar);
274274
}
275275

276+
// Decompse an argument list expression.
277+
PreparedArguments(ArrayRef<AnyFunctionType::Param> params, Expr *arg);
278+
276279
// Move-only.
277280
PreparedArguments(const PreparedArguments &) = delete;
278281
PreparedArguments &operator=(const PreparedArguments &) = delete;

lib/SILGen/SILGenApply.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2774,6 +2774,7 @@ class ArgEmitter {
27742774
assert(argSources.size() == 1);
27752775
emitTopLevel(std::move(argSources[0]), origFormalType);
27762776
} else {
2777+
maybeEmitForeignErrorArgument();
27772778
for (auto i : indices(argSources)) {
27782779
emitSingleArg(std::move(argSources[i]),
27792780
origFormalType.getFunctionParamType(i));
@@ -4643,12 +4644,9 @@ CallEmission::applySpecializedEmitter(SpecializedEmitter &specializedEmitter,
46434644
// We should be able to enforce that these arguments are
46444645
// always still expressions.
46454646
PreparedArguments args = std::move(uncurriedSites[0]).forward();
4646-
assert(args.isScalar());
4647-
Expr *argument = std::move(std::move(args).getSources()[0]).asKnownExpr();
4648-
46494647
ManagedValue resultMV =
46504648
emitter(SGF, uncurriedLoc, callee.getSubstitutions(),
4651-
argument, uncurriedContext);
4649+
std::move(args), uncurriedContext);
46524650
firstLevelResult.value =
46534651
RValue(SGF, uncurriedLoc, formalResultType, resultMV);
46544652
return firstLevelResult;
@@ -4875,10 +4873,7 @@ CallEmission CallEmission::forApplyExpr(SILGenFunction &SGF, ApplyExpr *e) {
48754873
SmallVector<AnyFunctionType::Param, 8> params;
48764874
AnyFunctionType::decomposeInput(arg->getType(), params);
48774875

4878-
// FIXME: Split up the argument expression here instead of passing
4879-
// scalar=true.
4880-
PreparedArguments preparedArgs(params, /*scalar*/true);
4881-
preparedArgs.addArbitrary(arg);
4876+
PreparedArguments preparedArgs(params, arg);
48824877

48834878
emission.addCallSite(apply, std::move(preparedArgs),
48844879
apply->getType()->getCanonicalType(),
@@ -6069,8 +6064,7 @@ SILGenFunction::prepareSubscriptIndices(SubscriptDecl *subscript,
60696064

60706065
// Prepare the unevaluated index expression.
60716066
auto substParams = substFnType->getParams();
6072-
PreparedArguments args(substParams, /*isScalar=*/true);
6073-
args.addArbitrary(indexExpr);
6067+
PreparedArguments args(substParams, indexExpr);
60746068

60756069
// Now, force it to be evaluated.
60766070
SmallVector<ManagedValue, 4> argValues;

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "SpecializedEmitter.h"
1414

15+
#include "ArgumentSource.h"
1516
#include "Cleanup.h"
1617
#include "Initialization.h"
1718
#include "LValue.h"
@@ -45,42 +46,40 @@ static bool isTrivialShuffle(ArgumentShuffleExpr *shuffle) {
4546
///
4647
/// Because these are builtin operations, we can make some structural
4748
/// assumptions about the expression used to call them.
48-
static ArrayRef<Expr*> decomposeArguments(SILGenFunction &SGF,
49-
Expr *arg,
50-
unsigned expectedCount) {
51-
assert(expectedCount >= 2);
52-
assert(arg->getType()->is<TupleType>());
53-
assert(arg->getType()->castTo<TupleType>()->getNumElements()
54-
== expectedCount);
55-
56-
// The use of owned parameters can trip up CSApply enough to introduce
57-
// a trivial tuple shuffle here.
58-
arg = arg->getSemanticsProvidingExpr();
59-
if (auto shuffle = dyn_cast<ArgumentShuffleExpr>(arg)) {
60-
if (isTrivialShuffle(shuffle))
61-
arg = shuffle->getSubExpr();
62-
}
49+
static Optional<SmallVector<Expr*, 2>>
50+
decomposeArguments(SILGenFunction &SGF,
51+
SILLocation loc,
52+
PreparedArguments &&args,
53+
unsigned expectedCount) {
54+
SmallVector<Expr*, 2> result;
55+
auto sources = std::move(args).getSources();
56+
57+
if (sources.size() == expectedCount) {
58+
for (auto &&source : sources)
59+
result.push_back(std::move(source).asKnownExpr());
60+
return result;
61+
} else if (sources.size() == 1) {
62+
auto *arg = std::move(sources[0]).asKnownExpr();
63+
64+
// The use of owned parameters can trip up CSApply enough to introduce
65+
// a trivial tuple shuffle here.
66+
if (auto shuffle = dyn_cast<ArgumentShuffleExpr>(arg)) {
67+
if (isTrivialShuffle(shuffle))
68+
arg = shuffle->getSubExpr();
69+
}
6370

64-
auto tuple = dyn_cast<TupleExpr>(arg);
65-
if (tuple && tuple->getElements().size() == expectedCount) {
66-
return tuple->getElements();
71+
auto tuple = dyn_cast<TupleExpr>(arg);
72+
if (tuple && tuple->getElements().size() == expectedCount) {
73+
for (auto elt : tuple->getElements())
74+
result.push_back(elt);
75+
return result;
76+
}
6777
}
6878

69-
SGF.SGM.diagnose(arg, diag::invalid_sil_builtin,
79+
SGF.SGM.diagnose(loc, diag::invalid_sil_builtin,
7080
"argument to builtin should be a literal tuple");
7181

72-
auto tupleTy = arg->getType()->castTo<TupleType>();
73-
74-
// This is well-typed but may cause code to be emitted redundantly.
75-
auto &ctxt = SGF.getASTContext();
76-
SmallVector<Expr*, 4> args;
77-
for (auto index : indices(tupleTy->getElementTypes())) {
78-
Expr *projection = new (ctxt) TupleElementExpr(arg, SourceLoc(),
79-
index, SourceLoc(),
80-
tupleTy->getElementType(index));
81-
args.push_back(projection);
82-
}
83-
return ctxt.AllocateCopy(args);
82+
return None;
8483
}
8584

8685
static ManagedValue emitBuiltinRetain(SILGenFunction &SGF,
@@ -252,9 +251,13 @@ static ManagedValue emitBuiltinAssign(SILGenFunction &SGF,
252251
static ManagedValue emitBuiltinInit(SILGenFunction &SGF,
253252
SILLocation loc,
254253
SubstitutionMap substitutions,
255-
Expr *tuple,
254+
PreparedArguments &&preparedArgs,
256255
SGFContext C) {
257-
auto args = decomposeArguments(SGF, tuple, 2);
256+
auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 2);
257+
if (!argsOrError)
258+
return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
259+
260+
auto args = *argsOrError;
258261

259262
CanType formalType =
260263
substitutions.getReplacementTypes()[0]->getCanonicalType();
@@ -421,23 +424,29 @@ static ManagedValue emitBuiltinBridgeFromRawPointer(SILGenFunction &SGF,
421424
static ManagedValue emitBuiltinAddressOf(SILGenFunction &SGF,
422425
SILLocation loc,
423426
SubstitutionMap substitutions,
424-
Expr *argument,
427+
PreparedArguments &&preparedArgs,
425428
SGFContext C) {
426-
auto rawPointerTy = SILType::getRawPointerType(SGF.getASTContext());
429+
SILType rawPointerType = SILType::getRawPointerType(SGF.getASTContext());
430+
431+
auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 1);
432+
if (!argsOrError)
433+
return SGF.emitUndef(rawPointerType);
434+
435+
auto argument = (*argsOrError)[0];
436+
427437
// If the argument is inout, try forming its lvalue. This builtin only works
428438
// if it's trivially physically projectable.
429439
auto inout = cast<InOutExpr>(argument->getSemanticsProvidingExpr());
430440
auto lv = SGF.emitLValue(inout->getSubExpr(), SGFAccessKind::ReadWrite);
431441
if (!lv.isPhysical() || !lv.isLoadingPure()) {
432442
SGF.SGM.diagnose(argument->getLoc(), diag::non_physical_addressof);
433-
return SGF.emitUndef(rawPointerTy);
443+
return SGF.emitUndef(rawPointerType);
434444
}
435445

436446
auto addr = SGF.emitAddressOfLValue(argument, std::move(lv))
437447
.getLValueAddress();
438448

439449
// Take the address argument and cast it to RawPointer.
440-
SILType rawPointerType = SILType::getRawPointerType(SGF.F.getASTContext());
441450
SILValue result = SGF.B.createAddressToPointer(loc, addr,
442451
rawPointerType);
443452
return ManagedValue::forUnmanaged(result);
@@ -447,23 +456,29 @@ static ManagedValue emitBuiltinAddressOf(SILGenFunction &SGF,
447456
static ManagedValue emitBuiltinAddressOfBorrow(SILGenFunction &SGF,
448457
SILLocation loc,
449458
SubstitutionMap substitutions,
450-
Expr *argument,
459+
PreparedArguments &&preparedArgs,
451460
SGFContext C) {
452-
auto rawPointerTy = SILType::getRawPointerType(SGF.getASTContext());
461+
SILType rawPointerType = SILType::getRawPointerType(SGF.getASTContext());
462+
463+
auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 1);
464+
if (!argsOrError)
465+
return SGF.emitUndef(rawPointerType);
466+
467+
auto argument = (*argsOrError)[0];
468+
453469
SILValue addr;
454470
// Try to borrow the argument at +0. We only support if it's
455471
// naturally emitted borrowed in memory.
456472
auto borrow = SGF.emitRValue(argument, SGFContext::AllowGuaranteedPlusZero)
457473
.getAsSingleValue(SGF, argument);
458474
if (!borrow.isPlusZero() || !borrow.getType().isAddress()) {
459475
SGF.SGM.diagnose(argument->getLoc(), diag::non_borrowed_indirect_addressof);
460-
return SGF.emitUndef(rawPointerTy);
476+
return SGF.emitUndef(rawPointerType);
461477
}
462478

463479
addr = borrow.getValue();
464480

465481
// Take the address argument and cast it to RawPointer.
466-
SILType rawPointerType = SILType::getRawPointerType(SGF.F.getASTContext());
467482
SILValue result = SGF.B.createAddressToPointer(loc, addr,
468483
rawPointerType);
469484
return ManagedValue::forUnmanaged(result);

lib/SILGen/SILGenExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2415,7 +2415,7 @@ loadIndexValuesForKeyPathComponent(SILGenFunction &SGF, SILLocation loc,
24152415
indexParams.emplace_back(SGF.F.mapTypeIntoContext(elt.first));
24162416
}
24172417

2418-
PreparedArguments indexValues(indexParams, /*scalar*/ indexes.size() == 1);
2418+
PreparedArguments indexValues(indexParams, /*scalar*/ false);
24192419
if (indexes.empty()) {
24202420
assert(indexValues.isValid());
24212421
return indexValues;

lib/SILGen/SpecializedEmitter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class ManagedValue;
3232
class SGFContext;
3333
class SILGenFunction;
3434
class SILGenModule;
35+
class PreparedArguments;
3536

3637
/// Some kind of specialized emitter for a builtin function.
3738
class SpecializedEmitter {
@@ -41,7 +42,7 @@ class SpecializedEmitter {
4142
using EarlyEmitter = ManagedValue (SILGenFunction &,
4243
SILLocation,
4344
SubstitutionMap,
44-
Expr *argument,
45+
PreparedArguments &&args,
4546
SGFContext);
4647

4748
/// A special function for emitting a call after the arguments

0 commit comments

Comments
 (0)