@@ -125,36 +125,75 @@ namespace {
125
125
// / result may be indirect, in which case it is returned in memory
126
126
// / whose address is passed as an implicit first argument, or it may
127
127
// / be direct.
128
- struct CallResult {
129
- private:
130
- ManagedValue DirectValues[ExplosionSchema::MaxScalarsForDirectResult];
131
- unsigned char NumDirectValues;
132
- public:
133
- ExplosionKind DirectExplosionLevel;
128
+ class CallResult {
129
+ union Value {
130
+ Explosion Direct;
131
+
132
+ // / The address into which to emit an indirect call. If this is
133
+ // / set, the call will be evaluated (as an initialization) into
134
+ // / this address; otherwise, memory will be allocated on the stack.
135
+ Address Indirect;
136
+
137
+ Value () {}
138
+ ~Value () {}
139
+ };
134
140
135
- // / The address into which to emit an indirect call. If this is
136
- // / set, the call will be evaluated (as an initialization) into
137
- // / this address; otherwise, memory will be allocated on the stack.
138
- Address IndirectAddress;
141
+ enum class State {
142
+ Invalid, Indirect, Direct
143
+ };
139
144
140
- CallResult () : NumDirectValues(0 ) {}
145
+ Value CurValue;
146
+ State CurState;
141
147
142
- void addDirectUnmanagedValue (llvm::Value *value) {
143
- addDirectValue (ManagedValue (value));
148
+ public:
149
+ CallResult () : CurState(State::Invalid) {}
150
+ ~CallResult () { reset (); }
151
+
152
+ // / Configure this result to carry a number of direct values at
153
+ // / the given explosion level.
154
+ Explosion &initForDirectValues (ExplosionKind level) {
155
+ assert (CurState == State::Invalid);
156
+ CurState = State::Direct;
157
+ Explosion *buffer = &CurValue.Direct ;
158
+ return *new (buffer) Explosion (level);
144
159
}
145
- void addDirectValue (ManagedValue value) {
146
- assert (NumDirectValues < ExplosionSchema::MaxScalarsForDirectResult);
147
- DirectValues[NumDirectValues++] = value;
160
+
161
+ // / As a potential efficiency, set that this is a direct result
162
+ // / with no values.
163
+ void setAsEmptyDirect () {
164
+ initForDirectValues (ExplosionKind::Maximal);
148
165
}
149
- ManagedValue getDirectValue (unsigned i) const {
150
- assert (i < NumDirectValues);
151
- return DirectValues[i];
166
+
167
+ // / Set this result so that it carries a single directly-returned
168
+ // / maximally-fragile value without management.
169
+ void setAsSingleDirectUnmanagedFragileValue (llvm::Value *value) {
170
+ initForDirectValues (ExplosionKind::Maximal).addUnmanaged (value);
152
171
}
153
- void clearDirectValues () {
154
- NumDirectValues = 0 ;
172
+
173
+ void setAsIndirectAddress (Address address) {
174
+ assert (CurState == State::Invalid);
175
+ CurState = State::Indirect;
176
+ CurValue.Indirect = address;
155
177
}
156
- llvm::ArrayRef<ManagedValue> getDirectValues () const {
157
- return ArrayRef<ManagedValue>(DirectValues, DirectValues+NumDirectValues);
178
+
179
+ bool isInvalid () const { return CurState == State::Invalid; }
180
+ bool isDirect () const { return CurState == State::Direct; }
181
+ bool isIndirect () const { return CurState == State::Indirect; }
182
+
183
+ Explosion &getDirectValues () {
184
+ assert (isDirect ());
185
+ return CurValue.Direct ;
186
+ }
187
+
188
+ Address getIndirectAddress () const {
189
+ assert (isIndirect ());
190
+ return CurValue.Indirect ;
191
+ }
192
+
193
+ void reset () {
194
+ if (CurState == State::Direct)
195
+ CurValue.Direct .~Explosion ();
196
+ CurState = State::Invalid;
158
197
}
159
198
};
160
199
@@ -475,6 +514,15 @@ namespace {
475
514
? ManagedValue (nullptr ) : data);
476
515
}
477
516
517
+ void setForIndirectCallFromResult (CallResult &result) {
518
+ assert (result.isDirect ());
519
+ Explosion &values = result.getDirectValues ();
520
+ assert (values.size () == 2 );
521
+ llvm::Value *fn = values.claimUnmanagedNext ();
522
+ ManagedValue data = values.claimNext ();
523
+ setForIndirectCall (fn, data);
524
+ }
525
+
478
526
llvm::Value *getOpaqueFunctionPointer (IRGenFunction &IGF) const {
479
527
return IGF.Builder .CreateBitCast (FnPtr, IGF.IGM .Int8PtrTy );
480
528
}
@@ -550,15 +598,24 @@ namespace {
550
598
};
551
599
}
552
600
553
- static void emitCastBuiltin (llvm::Instruction::CastOps Opcode ,
601
+ static void emitCastBuiltin (llvm::Instruction::CastOps opcode ,
554
602
IRGenFunction &IGF, ArgList &args,
555
603
Type DestType, CallResult &result) {
556
- llvm::Value *Input = args.Values .claimUnmanagedNext ();
557
- llvm::Type *DestTy = IGF.IGM .getFragileTypeInfo (DestType).getStorageType ();
604
+ llvm::Value *input = args.Values .claimUnmanagedNext ();
605
+ llvm::Type *destTy = IGF.IGM .getFragileTypeInfo (DestType).getStorageType ();
558
606
assert (args.Values .empty () && " wrong operands to cast operation" );
559
- return result.addDirectUnmanagedValue (IGF.Builder .CreateCast (Opcode, Input,
560
- DestTy));
607
+ llvm::Value *output = IGF.Builder .CreateCast (opcode, input, destTy);
608
+ result.setAsSingleDirectUnmanagedFragileValue (output);
609
+ }
561
610
611
+ // / Given an address representing an unsafe pointer to the given type,
612
+ // / turn it into a valid Address.
613
+ static Address getAddressForUnsafePointer (IRGenFunction &IGF,
614
+ const TypeInfo &type,
615
+ llvm::Value *addr) {
616
+ llvm::Value *castAddr =
617
+ IGF.Builder .CreateBitCast (addr, type.getStorageType ()->getPointerTo ());
618
+ return Address (castAddr, type.StorageAlignment );
562
619
}
563
620
564
621
@@ -578,50 +635,43 @@ static void emitBuiltinCall(IRGenFunction &IGF, FuncDecl *Fn,
578
635
llvm::Value *lhs = args.Values .claimUnmanagedNext ();
579
636
llvm::Value *rhs = args.Values .claimUnmanagedNext ();
580
637
assert (args.Values .empty () && " wrong operands to gep operation" );
581
- return result.addDirectUnmanagedValue (IGF.Builder .CreateGEP (lhs, rhs));
638
+
639
+ // We don't expose a non-inbounds GEP operation.
640
+ llvm::Value *gep = IGF.Builder .CreateInBoundsGEP (lhs, rhs);
641
+ return result.setAsSingleDirectUnmanagedFragileValue (gep);
582
642
}
583
643
584
644
case BuiltinValueKind::Load: {
585
- llvm::Value *addr = args.Values .claimUnmanagedNext ();
645
+ // The type of the operation is the result type of the load function.
646
+ Type valueTy = Fn->getType ()->castTo <FunctionType>()->getResult ();
647
+ const TypeInfo &valueTI = IGF.IGM .getFragileTypeInfo (valueTy);
648
+
649
+ // Treat the raw pointer as a physical l-value of that type.
650
+ llvm::Value *addrValue = args.Values .claimUnmanagedNext ();
651
+ Address addr = getAddressForUnsafePointer (IGF, valueTI, addrValue);
586
652
assert (args.Values .empty () && " wrong operands to load operation" );
587
653
588
- Type ResultTy = Fn->getType ()->castTo <FunctionType>()->getResult ();
589
-
590
- // Cast the raw pointer to an appropriately-typed pointer.
591
- const TypeInfo &ResultTypeInfo = IGF.IGM .getFragileTypeInfo (ResultTy);
592
- llvm::Type *ptr = ResultTypeInfo.StorageType ->getPointerTo ();
593
- addr = IGF.Builder .CreateBitCast (addr, ptr);
594
-
595
- // Create the load.
596
- llvm::Value *load
597
- = IGF.Builder .CreateLoad (addr, ResultTypeInfo.StorageAlignment );
598
-
599
- if (ResultTy->is <BuiltinObjectPointerType>())
600
- return result.addDirectValue (IGF.enterReleaseCleanup (load));
601
-
602
- return result.addDirectUnmanagedValue (load);
654
+ // Perform the load.
655
+ Explosion &out = result.initForDirectValues (ExplosionKind::Maximal);
656
+ return valueTI.load (IGF, addr, out);
603
657
}
604
658
605
659
case BuiltinValueKind::Store: {
606
- llvm::Value *value = args.Values .forwardNext (IGF);
607
- llvm::Value *addr = args.Values .claimUnmanagedNext ();
608
- assert (args.Values .empty () && " wrong operands to store operation" );
609
-
610
- // Extract the type of the value we're storing.
611
- Type ValueTy = Fn->getType ()->castTo <FunctionType>()->getInput ()
660
+ // The type of the operation is the type of the first argument of
661
+ // the store function.
662
+ Type valueTy = Fn->getType ()->castTo <FunctionType>()->getInput ()
612
663
->castTo <TupleType>()->getElementType (0 );
613
- const TypeInfo &ValueTypeInfo = IGF.IGM .getFragileTypeInfo (ValueTy);
614
-
615
- // Cast the raw pointer to an appropriately-typed pointer.
616
- addr = IGF.Builder .CreateBitCast (addr, value->getType ()->getPointerTo ());
617
-
618
- // Create the store.
619
- if (ValueTy->is <BuiltinObjectPointerType>())
620
- IGF.emitAssignRetained (value,
621
- Address (addr, ValueTypeInfo.StorageAlignment ));
622
- else
623
- IGF.Builder .CreateStore (value, addr, ValueTypeInfo.StorageAlignment );
624
- return ;
664
+ const TypeInfo &valueTI = IGF.IGM .getFragileTypeInfo (valueTy);
665
+
666
+ // Treat the raw pointer as a physical l-value of that type.
667
+ llvm::Value *addrValue = args.Values .takeLast ().getUnmanagedValue ();
668
+ Address addr = getAddressForUnsafePointer (IGF, valueTI, addrValue);
669
+
670
+ // Mark that we're not returning anything.
671
+ result.setAsEmptyDirect ();
672
+
673
+ // Perform the assignment operation.
674
+ return valueTI.assign (IGF, args.Values , addr);
625
675
}
626
676
627
677
// / A macro which expands to the emission of a simple binary operation
@@ -630,7 +680,8 @@ static void emitBuiltinCall(IRGenFunction &IGF, FuncDecl *Fn,
630
680
llvm::Value *lhs = args.Values .claimUnmanagedNext (); \
631
681
llvm::Value *rhs = args.Values .claimUnmanagedNext (); \
632
682
assert (args.Values .empty () && " wrong operands to binary operation" ); \
633
- return result.addDirectUnmanagedValue (IGF.Builder .Create ##Op (lhs, rhs));\
683
+ return result.setAsSingleDirectUnmanagedFragileValue ( \
684
+ IGF.Builder .Create ##Op (lhs, rhs)); \
634
685
}
635
686
636
687
// / A macro which expands to the emission of a simple binary operation
@@ -640,10 +691,10 @@ static void emitBuiltinCall(IRGenFunction &IGF, FuncDecl *Fn,
640
691
llvm::Value *rhs = args.Values .claimUnmanagedNext (); \
641
692
assert (args.Values .empty () && " wrong operands to binary operation" ); \
642
693
if (lhs->getType ()->isFloatingPointTy ()) { \
643
- return result.addDirectUnmanagedValue ( \
694
+ return result.setAsSingleDirectUnmanagedFragileValue ( \
644
695
IGF.Builder .Create ##FPOp (lhs, rhs)); \
645
696
} else { \
646
- return result.addDirectUnmanagedValue ( \
697
+ return result.setAsSingleDirectUnmanagedFragileValue ( \
647
698
IGF.Builder .Create ##IntOp (lhs, rhs)); \
648
699
} \
649
700
}
@@ -852,6 +903,14 @@ static void extractScalarResults(IRGenFunction &IGF, llvm::Value *call,
852
903
// / Emit a function call.
853
904
void CallPlan::emit (IRGenFunction &IGF, CallResult &result,
854
905
const TypeInfo &resultType) {
906
+ // Save the final result address if one was given, then reset
907
+ // to establish the invariant that the result is always invalid.
908
+ Address finalAddress;
909
+ if (result.isIndirect ()) {
910
+ finalAddress = result.getIndirectAddress ();
911
+ result.reset ();
912
+ }
913
+
855
914
// 1. Emit the function expression.
856
915
Callee callee;
857
916
@@ -869,9 +928,8 @@ void CallPlan::emit(IRGenFunction &IGF, CallResult &result,
869
928
if (CallSites.size () == 1 ) return ;
870
929
871
930
// Otherwise, pop that call site off and set up the callee conservatively.
872
- callee.setForIndirectCall (result.getDirectValue (0 ).getUnmanagedValue (),
873
- result.getDirectValue (1 ));
874
- result.clearDirectValues ();
931
+ callee.setForIndirectCallFromResult (result);
932
+ result.reset ();
875
933
876
934
// Otherwise, compute information about the function we're calling.
877
935
} else {
@@ -950,16 +1008,20 @@ void CallPlan::emit(IRGenFunction &IGF, CallResult &result,
950
1008
assert (CallSites.empty () && " aggregate result on non-final call?" );
951
1009
952
1010
// Force there to be an indirect address.
953
- if (!result.IndirectAddress .isValid ()) {
1011
+ Address resultAddress;
1012
+ if (finalAddress.isValid ()) {
1013
+ resultAddress = finalAddress;
1014
+ } else {
954
1015
indirectResultObject = indirectInit.getObjectForTemporary ();
955
1016
indirectInit.registerObject (IGF, indirectResultObject,
956
1017
NotOnHeap, resultTI);
957
- result. IndirectAddress =
1018
+ resultAddress =
958
1019
indirectInit.emitLocalAllocation (IGF, indirectResultObject,
959
1020
NotOnHeap, resultTI,
960
1021
" call.aggresult" );
961
1022
}
962
- args[0 ] = result.IndirectAddress .getAddress ();
1023
+ args[0 ] = resultAddress.getAddress ();
1024
+ result.setAsIndirectAddress (resultAddress);
963
1025
}
964
1026
965
1027
// Make the call.
@@ -975,33 +1037,29 @@ void CallPlan::emit(IRGenFunction &IGF, CallResult &result,
975
1037
indirectInit.markInitialized (IGF, indirectResultObject);
976
1038
977
1039
setAggResultAttributes (call);
978
- assert (result.getDirectValues ().empty ());
979
- assert (result.IndirectAddress .isValid ());
1040
+ assert (result.isIndirect ());
980
1041
return ;
981
1042
}
982
1043
983
1044
// Extract out the scalar results.
984
- if (! call->getType ()->isVoidTy ()) {
985
- Explosion resultExplosion (callee. ExplosionLevel );
986
- extractScalarResults (IGF, call, resultTI, resultExplosion);
987
- for ( auto value : resultExplosion. claimAll ())
988
- result. addDirectValue (value );
1045
+ if (call->getType ()->isVoidTy ()) {
1046
+ result. setAsEmptyDirect ( );
1047
+ } else {
1048
+ Explosion &out = result. initForDirectValues (callee. ExplosionLevel );
1049
+ extractScalarResults (IGF, call, resultTI, out );
989
1050
}
990
1051
991
1052
// If this is the end of the call sites, we're done.
992
1053
if (CallSites.empty ()) {
993
- assert (!result.IndirectAddress . isValid () &&
1054
+ assert (!result.isIndirect () &&
994
1055
" returning direct values when indirect result was requested!" );
995
- result.DirectExplosionLevel = callee.ExplosionLevel ;
996
1056
return ;
997
1057
}
998
1058
999
1059
// Otherwise, we must have gotten a function back. Set ourselves
1000
1060
// up to call it, then continue emitting calls.
1001
- assert (result.getDirectValues ().size () == 2 );
1002
- callee.setForIndirectCall (result.getDirectValue (0 ).getUnmanagedValue (),
1003
- result.getDirectValue (1 ));
1004
- result.clearDirectValues ();
1061
+ callee.setForIndirectCallFromResult (result);
1062
+ result.reset ();
1005
1063
}
1006
1064
}
1007
1065
@@ -1016,16 +1074,19 @@ void swift::irgen::emitApplyExpr(IRGenFunction &IGF, ApplyExpr *E,
1016
1074
plan.emit (IGF, result, resultTI);
1017
1075
1018
1076
// If this was an indirect return, explode it.
1019
- if (result.IndirectAddress . isValid ()) {
1020
- return resultTI.load (IGF, result.IndirectAddress , explosion);
1077
+ if (result.isIndirect ()) {
1078
+ return resultTI.load (IGF, result.getIndirectAddress () , explosion);
1021
1079
}
1022
1080
1023
- if (result.DirectExplosionLevel == explosion.getKind ())
1024
- return explosion.add (result.getDirectValues ());
1081
+ Explosion &directValues = result.getDirectValues ();
1082
+
1083
+ // If the explosion kind of the direct values matches that of the
1084
+ // result, we're okay.
1085
+ if (directValues.getKind () == explosion.getKind ())
1086
+ return explosion.add (directValues.claimAll ());
1025
1087
1026
- Explosion resultExplosion (result.DirectExplosionLevel );
1027
- resultExplosion.add (result.getDirectValues ());
1028
- resultTI.reexplode (IGF, resultExplosion, explosion);
1088
+ // Otherwise we need to re-explode.
1089
+ resultTI.reexplode (IGF, directValues, explosion);
1029
1090
}
1030
1091
1031
1092
// / See whether we can emit the result of the given call as an object
@@ -1043,8 +1104,8 @@ swift::irgen::tryEmitApplyAsAddress(IRGenFunction &IGF, ApplyExpr *E,
1043
1104
1044
1105
CallResult result;
1045
1106
plan.emit (IGF, result, resultTI);
1046
- assert (result.IndirectAddress . isValid ());
1047
- return result.IndirectAddress ;
1107
+ assert (result.isIndirect ());
1108
+ return result.getIndirectAddress () ;
1048
1109
}
1049
1110
1050
1111
// / Emit a nullary call to the given function, using the standard
0 commit comments