12
12
13
13
#include " SpecializedEmitter.h"
14
14
15
+ #include " ArgumentSource.h"
15
16
#include " Cleanup.h"
16
17
#include " Initialization.h"
17
18
#include " LValue.h"
@@ -45,42 +46,40 @@ static bool isTrivialShuffle(ArgumentShuffleExpr *shuffle) {
45
46
// /
46
47
// / Because these are builtin operations, we can make some structural
47
48
// / 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
+ }
63
70
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
+ }
67
77
}
68
78
69
- SGF.SGM .diagnose (arg , diag::invalid_sil_builtin,
79
+ SGF.SGM .diagnose (loc , diag::invalid_sil_builtin,
70
80
" argument to builtin should be a literal tuple" );
71
81
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;
84
83
}
85
84
86
85
static ManagedValue emitBuiltinRetain (SILGenFunction &SGF,
@@ -252,9 +251,13 @@ static ManagedValue emitBuiltinAssign(SILGenFunction &SGF,
252
251
static ManagedValue emitBuiltinInit (SILGenFunction &SGF,
253
252
SILLocation loc,
254
253
SubstitutionMap substitutions,
255
- Expr *tuple ,
254
+ PreparedArguments &&preparedArgs ,
256
255
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;
258
261
259
262
CanType formalType =
260
263
substitutions.getReplacementTypes ()[0 ]->getCanonicalType ();
@@ -421,23 +424,29 @@ static ManagedValue emitBuiltinBridgeFromRawPointer(SILGenFunction &SGF,
421
424
static ManagedValue emitBuiltinAddressOf (SILGenFunction &SGF,
422
425
SILLocation loc,
423
426
SubstitutionMap substitutions,
424
- Expr *argument ,
427
+ PreparedArguments &&preparedArgs ,
425
428
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
+
427
437
// If the argument is inout, try forming its lvalue. This builtin only works
428
438
// if it's trivially physically projectable.
429
439
auto inout = cast<InOutExpr>(argument->getSemanticsProvidingExpr ());
430
440
auto lv = SGF.emitLValue (inout->getSubExpr (), SGFAccessKind::ReadWrite);
431
441
if (!lv.isPhysical () || !lv.isLoadingPure ()) {
432
442
SGF.SGM .diagnose (argument->getLoc (), diag::non_physical_addressof);
433
- return SGF.emitUndef (rawPointerTy );
443
+ return SGF.emitUndef (rawPointerType );
434
444
}
435
445
436
446
auto addr = SGF.emitAddressOfLValue (argument, std::move (lv))
437
447
.getLValueAddress ();
438
448
439
449
// Take the address argument and cast it to RawPointer.
440
- SILType rawPointerType = SILType::getRawPointerType (SGF.F .getASTContext ());
441
450
SILValue result = SGF.B .createAddressToPointer (loc, addr,
442
451
rawPointerType);
443
452
return ManagedValue::forUnmanaged (result);
@@ -447,23 +456,29 @@ static ManagedValue emitBuiltinAddressOf(SILGenFunction &SGF,
447
456
static ManagedValue emitBuiltinAddressOfBorrow (SILGenFunction &SGF,
448
457
SILLocation loc,
449
458
SubstitutionMap substitutions,
450
- Expr *argument ,
459
+ PreparedArguments &&preparedArgs ,
451
460
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
+
453
469
SILValue addr;
454
470
// Try to borrow the argument at +0. We only support if it's
455
471
// naturally emitted borrowed in memory.
456
472
auto borrow = SGF.emitRValue (argument, SGFContext::AllowGuaranteedPlusZero)
457
473
.getAsSingleValue (SGF, argument);
458
474
if (!borrow.isPlusZero () || !borrow.getType ().isAddress ()) {
459
475
SGF.SGM .diagnose (argument->getLoc (), diag::non_borrowed_indirect_addressof);
460
- return SGF.emitUndef (rawPointerTy );
476
+ return SGF.emitUndef (rawPointerType );
461
477
}
462
478
463
479
addr = borrow.getValue ();
464
480
465
481
// Take the address argument and cast it to RawPointer.
466
- SILType rawPointerType = SILType::getRawPointerType (SGF.F .getASTContext ());
467
482
SILValue result = SGF.B .createAddressToPointer (loc, addr,
468
483
rawPointerType);
469
484
return ManagedValue::forUnmanaged (result);
0 commit comments