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
8685static ManagedValue emitBuiltinRetain (SILGenFunction &SGF,
@@ -252,9 +251,13 @@ static ManagedValue emitBuiltinAssign(SILGenFunction &SGF,
252251static 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,
421424static 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,
447456static 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);
0 commit comments