@@ -794,7 +794,7 @@ class IRGenSILFunction :
794
794
#ifndef NDEBUG
795
795
// / Check if \p Val can be stored into \p Alloca, and emit some diagnostic
796
796
// / info if it can't.
797
- bool canAllocaStoreValue (Address Alloca, llvm::Value *Val,
797
+ bool canAllocaStoreValue (llvm::Value * Alloca, llvm::Value *Val,
798
798
SILDebugVariable VarInfo,
799
799
const SILDebugScope *Scope) {
800
800
bool canStore =
@@ -804,7 +804,7 @@ class IRGenSILFunction :
804
804
return true ;
805
805
llvm::errs () << " Invalid shadow copy:\n "
806
806
<< " Value : " << *Val << " \n "
807
- << " Alloca: " << *Alloca. getAddress () << " \n "
807
+ << " Alloca: " << *Alloca << " \n "
808
808
<< " ---\n "
809
809
<< " Previous shadow copy into " << VarInfo.Name
810
810
<< " in the same scope!\n "
@@ -889,13 +889,21 @@ class IRGenSILFunction :
889
889
return Addr;
890
890
}
891
891
892
+ // This returns shadow alloca when \p init is false or the shadowed value
893
+ // derived from that alloca with \p init is true.
892
894
llvm::Value *emitTaskAllocShadowCopy (llvm::Value *Storage,
893
- const SILDebugScope *Scope) {
895
+ const SILDebugScope *Scope,
896
+ bool Init) {
894
897
auto getRec = [&](llvm::Instruction *Orig) {
898
+ llvm::Value *Inner =
899
+ emitTaskAllocShadowCopy (Orig->getOperand (0 ), Scope, Init);
900
+ if (!Init)
901
+ return Inner;
902
+
895
903
llvm::Instruction *Cloned = Orig->clone ();
896
- Cloned->setOperand (0 , emitTaskAllocShadowCopy (Orig-> getOperand ( 0 ), Scope) );
904
+ Cloned->setOperand (0 , Inner );
897
905
Cloned->insertBefore (Orig);
898
- return Cloned;
906
+ return static_cast <llvm::Value *>( Cloned) ;
899
907
};
900
908
if (auto *LdInst = dyn_cast<llvm::LoadInst>(Storage))
901
909
return getRec (LdInst);
@@ -909,11 +917,13 @@ class IRGenSILFunction :
909
917
auto &Alloca = TaskAllocStackSlots[CallInst];
910
918
if (!Alloca.isValid ())
911
919
Alloca = createAlloca (Storage->getType (), Align, " taskalloc.debug" );
912
- zeroInit (cast<llvm::AllocaInst>(Alloca.getAddress ()));
913
- ArtificialLocation AutoRestore (Scope, IGM.DebugInfo .get (), Builder);
914
- auto *Store =
920
+ if (Init) {
921
+ zeroInit (cast<llvm::AllocaInst>(Alloca.getAddress ()));
922
+ ArtificialLocation AutoRestore (Scope, IGM.DebugInfo .get (), Builder);
923
+ auto *Store =
915
924
Builder.CreateStore (Storage, Alloca.getAddress (), Align);
916
- Store->moveAfter (CallInst);
925
+ Store->moveAfter (CallInst);
926
+ }
917
927
return Alloca.getAddress ();
918
928
}
919
929
return Storage;
@@ -922,23 +932,39 @@ class IRGenSILFunction :
922
932
// / Unconditionally emit a stack shadow copy of an \c llvm::Value.
923
933
llvm::Value *emitShadowCopy (llvm::Value *Storage, const SILDebugScope *Scope,
924
934
SILDebugVariable VarInfo,
925
- llvm::Optional<Alignment> _Align) {
935
+ llvm::Optional<Alignment> _Align, bool Init ) {
926
936
if (CurSILFn->isAsync ())
927
937
if (isTaskAlloc (Storage))
928
- return emitTaskAllocShadowCopy (Storage, Scope);
938
+ return emitTaskAllocShadowCopy (Storage, Scope, Init);
939
+
929
940
auto Align = _Align.getValueOr (IGM.getPointerAlignment ());
930
941
unsigned ArgNo = VarInfo.ArgNo ;
931
942
auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, VarInfo.Name }}];
932
943
if (!Alloca.isValid ())
933
944
Alloca = createAlloca (Storage->getType (), Align, VarInfo.Name + " .debug" );
934
- zeroInit (cast<llvm::AllocaInst>(Alloca.getAddress ()));
935
- assert (canAllocaStoreValue (Alloca, Storage, VarInfo, Scope) &&
945
+ assert (canAllocaStoreValue (Alloca.getAddress (), Storage, VarInfo, Scope) &&
936
946
" bad scope?" );
937
- ArtificialLocation AutoRestore (Scope, IGM.DebugInfo .get (), Builder);
938
- Builder.CreateStore (Storage, Alloca.getAddress (), Align);
947
+ if (Init) {
948
+ zeroInit (cast<llvm::AllocaInst>(Alloca.getAddress ()));
949
+ ArtificialLocation AutoRestore (Scope, IGM.DebugInfo .get (), Builder);
950
+ Builder.CreateStore (Storage, Alloca.getAddress (), Align);
951
+ }
939
952
return Alloca.getAddress ();
940
953
}
941
954
955
+ bool shouldShadowVariable (SILDebugVariable varInfo, bool isAnonymous) {
956
+ return !IGM.IRGen .Opts .DisableDebuggerShadowCopies
957
+ && !IGM.IRGen .Opts .shouldOptimize ()
958
+ && !isAnonymous
959
+ && !CurSILFn->isAsync ();
960
+ }
961
+
962
+ bool shouldShadowStorage (llvm::Value *Storage) {
963
+ return !isa<llvm::AllocaInst>(Storage)
964
+ && !isa<llvm::UndefValue>(Storage)
965
+ && needsShadowCopy (Storage);
966
+ }
967
+
942
968
// / At -Onone, emit a shadow copy of an Address in an alloca, so the
943
969
// / register allocator doesn't elide the dbg.value intrinsic when
944
970
// / register pressure is high. There is a trade-off to this: With
@@ -961,14 +987,14 @@ class IRGenSILFunction :
961
987
if (emitLifetimeExtendingUse (Value))
962
988
if (ValueVariables.insert (Value).second )
963
989
ValueDomPoints.push_back ({Value, getActiveDominancePoint ()});
964
- if (IGM. IRGen . Opts . DisableDebuggerShadowCopies ||
965
- IGM. IRGen . Opts . shouldOptimize () || IsAnonymous || CurSILFn-> isAsync () ||
966
- isa<llvm::AllocaInst>(Storage) || isa<llvm::UndefValue>(Storage) ||
967
- ! needsShadowCopy (Storage))
990
+ // This condition must be consistent with emitPoisonDebugValueInst to avoid
991
+ // generating extra shadow copies for debug_value [poison].
992
+ if (! shouldShadowVariable (VarInfo, IsAnonymous)
993
+ || ! shouldShadowStorage (Storage)) {
968
994
return Storage;
969
-
995
+ }
970
996
// Emit a shadow copy.
971
- return emitShadowCopy (Storage, Scope, VarInfo, Align);
997
+ return emitShadowCopy (Storage, Scope, VarInfo, Align, true );
972
998
}
973
999
974
1000
// / Like \c emitShadowCopyIfNeeded() but takes an \c Address instead of an
@@ -988,9 +1014,7 @@ class IRGenSILFunction :
988
1014
Explosion e = getLoweredExplosion (SILVal);
989
1015
990
1016
// Only do this at -O0.
991
- if (IGM.IRGen .Opts .DisableDebuggerShadowCopies ||
992
- IGM.IRGen .Opts .shouldOptimize () || IsAnonymous ||
993
- (CurSILFn->isAsync ())) {
1017
+ if (!shouldShadowVariable (VarInfo, IsAnonymous)) {
994
1018
auto vals = e.claimAll ();
995
1019
copy.append (vals.begin (), vals.end ());
996
1020
@@ -1006,21 +1030,29 @@ class IRGenSILFunction :
1006
1030
}
1007
1031
1008
1032
// Single or empty values.
1009
- if (e.size () <= 1 ) {
1010
- auto vals = e.claimAll ();
1011
- for (auto val : vals)
1012
- copy.push_back (
1013
- emitShadowCopyIfNeeded (val, Scope, VarInfo, IsAnonymous));
1033
+ if (e.empty ())
1034
+ return ;
1035
+
1036
+ if (e.size () == 1 ) {
1037
+ copy.push_back (
1038
+ emitShadowCopyIfNeeded (e.claimNext (), Scope, VarInfo, IsAnonymous));
1014
1039
return ;
1015
1040
}
1016
1041
1017
- SILType Type = SILVal->getType ();
1018
- auto <I = cast<LoadableTypeInfo>(IGM.getTypeInfo (Type));
1019
- auto Alloca = LTI.allocateStack (*this , Type, VarInfo.Name + " .debug" );
1020
- zeroInit (cast<llvm::AllocaInst>(Alloca.getAddress ().getAddress ()));
1021
- ArtificialLocation AutoRestore (Scope, IGM.DebugInfo .get (), Builder);
1022
- LTI.initialize (*this , e, Alloca.getAddress (), false /* isOutlined */ );
1023
- copy.push_back (Alloca.getAddressPointer ());
1042
+ unsigned ArgNo = VarInfo.ArgNo ;
1043
+ auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, VarInfo.Name }}];
1044
+ if (Alloca.isValid ()) {
1045
+ (void )e.claimAll ();
1046
+ } else {
1047
+ SILType Type = SILVal->getType ();
1048
+ auto <I = cast<LoadableTypeInfo>(IGM.getTypeInfo (Type));
1049
+ Alloca =
1050
+ LTI.allocateStack (*this , Type, VarInfo.Name + " .debug" ).getAddress ();
1051
+ zeroInit (cast<llvm::AllocaInst>(Alloca.getAddress ()));
1052
+ ArtificialLocation AutoRestore (Scope, IGM.DebugInfo .get (), Builder);
1053
+ LTI.initialize (*this , e, Alloca, false /* isOutlined */ );
1054
+ }
1055
+ copy.push_back (Alloca.getAddress ());
1024
1056
}
1025
1057
1026
1058
// / Force all archetypes referenced by the type to be bound by this point.
@@ -1081,6 +1113,7 @@ class IRGenSILFunction :
1081
1113
void emitErrorResultVar (CanSILFunctionType FnTy,
1082
1114
SILResultInfo ErrorInfo,
1083
1115
DebugValueInst *DbgValue);
1116
+ void emitPoisonDebugValueInst (DebugValueInst *i);
1084
1117
void emitDebugInfoForAllocStack (AllocStackInst *i, const TypeInfo &type,
1085
1118
llvm::Value *addr);
1086
1119
void visitAllocStackInst (AllocStackInst *i);
@@ -4524,7 +4557,112 @@ void IRGenSILFunction::emitErrorResultVar(CanSILFunctionType FnTy,
4524
4557
IndirectValue, ArtificialValue);
4525
4558
}
4526
4559
4560
+ void IRGenSILFunction::emitPoisonDebugValueInst (DebugValueInst *i) {
4561
+ auto varInfo = i->getVarInfo ();
4562
+ assert (varInfo && " debug_value without debug info" );
4563
+
4564
+ bool isAnonymous = false ;
4565
+ varInfo->Name = getVarName (i, isAnonymous);
4566
+
4567
+ SILValue silVal = i->getOperand ();
4568
+ SILType silTy = silVal->getType ();
4569
+ SILType unwrappedTy = silTy.unwrapOptionalType ();
4570
+ CanType refTy = unwrappedTy.getASTType ();
4571
+ // TODO: Handling nontrivial aggregates requires implementing poisonRefs
4572
+ // within TypeInfo. However, this could inflate code size for large types.
4573
+ assert (refTy->isAnyClassReferenceType () && " type can't handle poison" );
4574
+
4575
+ Explosion e = getLoweredExplosion (silVal);
4576
+ llvm::Value *storage = e.claimNext ();
4577
+ auto storageTy = storage->getType ();
4578
+ // Safeguard: don't try to poison an non-word sized value. Not sure how this
4579
+ // could ever happen.
4580
+ if (!storageTy->isPointerTy () && storageTy != IGM.SizeTy )
4581
+ return ;
4582
+
4583
+ // Only the first word of the value is poisoned.
4584
+ //
4585
+ // TODO: This assumes that only class references are poisoned (as guaranteed
4586
+ // by MandatoryCopyPropagation). And it assumes the reference is the first
4587
+ // value (class existential witnesses are laid out after the class reference).
4588
+ bool singleValueExplosion = e.empty ();
4589
+ (void )e.claimAll ();
4590
+
4591
+ // Only poison shadow references if this storage is purely used as a shadow
4592
+ // copy--poison should never affect program behavior. Also filter everything
4593
+ // not handled by emitShadowCopyIfNeeded to avoid extra shadow copies.
4594
+ if (!shouldShadowVariable (*varInfo, isAnonymous)
4595
+ || !shouldShadowStorage (storage)) {
4596
+ return ;
4597
+ }
4598
+
4599
+ // The original decl scope.
4600
+ const SILDebugScope *scope = i->getDebugScope ();
4601
+
4602
+ // Shadow allocas are pointer aligned.
4603
+ auto ptrAlign = IGM.getPointerAlignment ();
4604
+
4605
+ // Emit or recover the unique shadow copy.
4606
+ //
4607
+ // FIXME: To limit perturbing original source, this follows the strange
4608
+ // emitShadowCopyIfNeeded logic that has separate paths for single-value
4609
+ // vs. multi-value explosions.
4610
+ llvm::Value *shadowAddress;
4611
+ if (singleValueExplosion) {
4612
+ shadowAddress = emitShadowCopy (storage, scope, *varInfo, ptrAlign, false );
4613
+ } else {
4614
+ assert (refTy->isClassExistentialType () && " unknown multi-value explosion" );
4615
+ // FIXME: Handling Optional existentials requires TypeInfo
4616
+ // support. Otherwise we would need to assume the layout of the reference
4617
+ // and bitcast everything below to scalar integers.
4618
+ if (silTy != unwrappedTy)
4619
+ return ;
4620
+
4621
+ unsigned argNo = varInfo->ArgNo ;
4622
+ auto &alloca = ShadowStackSlots[{argNo, {scope, varInfo->Name }}];
4623
+ if (!alloca .isValid ()) {
4624
+ auto <i = cast<LoadableTypeInfo>(IGM.getTypeInfo (silTy));
4625
+ alloca =
4626
+ lti.allocateStack (*this , silTy, varInfo->Name + " .debug" ).getAddress ();
4627
+ }
4628
+ shadowAddress =
4629
+ emitClassExistentialValueAddress (*this , alloca , silTy).getAddress ();
4630
+ }
4631
+ Size ::int_type poisonInt = IGM.TargetInfo .ReferencePoisonDebugValue ;
4632
+ assert ((poisonInt & IGM.TargetInfo .PointerSpareBits .asAPInt ()) == 0 );
4633
+ llvm::Value *poisonedVal = llvm::ConstantInt::get (IGM.SizeTy , poisonInt);
4634
+
4635
+ // If the current value is nil (Optional's extra inhabitant), then don't
4636
+ // overwrite it with poison. This way, lldb will correctly display
4637
+ // Optional.None rather than telling the user that an object was
4638
+ // deinitialized, when there was no object to begin with. This could also be
4639
+ // done with a spare-bits mask to handle arbitrary enums but extra inhabitants
4640
+ // are tricky.
4641
+ if (!storageTy->isPointerTy ()) {
4642
+ assert (storageTy == IGM.SizeTy && " can't handle non-word values" );
4643
+ llvm::Value *currentBits =
4644
+ Builder.CreateBitOrPointerCast (storage, IGM.SizeTy );
4645
+ llvm::Value *zeroWord = llvm::ConstantInt::get (IGM.SizeTy , 0 );
4646
+ llvm::Value *isNil = Builder.CreateICmpEQ (currentBits, zeroWord);
4647
+ poisonedVal = Builder.CreateSelect (isNil, currentBits, poisonedVal);
4648
+ }
4649
+ llvm::Value *newShadowVal =
4650
+ Builder.CreateBitOrPointerCast (poisonedVal, storageTy);
4651
+
4652
+ assert (canAllocaStoreValue (shadowAddress, newShadowVal, *varInfo, scope) &&
4653
+ " shadow copy can't handle poison" );
4654
+
4655
+ // The poison stores have an artificial location within the original variable
4656
+ // declaration's scope.
4657
+ ArtificialLocation autoRestore (scope, IGM.DebugInfo .get (), Builder);
4658
+ Builder.CreateStore (newShadowVal, shadowAddress, ptrAlign);
4659
+ }
4660
+
4527
4661
void IRGenSILFunction::visitDebugValueInst (DebugValueInst *i) {
4662
+ if (i->poisonRefs ()) {
4663
+ emitPoisonDebugValueInst (i);
4664
+ return ;
4665
+ }
4528
4666
if (i->getDebugScope ()->getInlinedFunction ()->isTransparent ())
4529
4667
return ;
4530
4668
@@ -4943,7 +5081,8 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
4943
5081
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(addr))
4944
5082
if (!Alloca->isStaticAlloca ()) {
4945
5083
// Store the address of the dynamic alloca on the stack.
4946
- addr = emitShadowCopy (addr, DS, *VarInfo, IGM.getPointerAlignment ());
5084
+ addr = emitShadowCopy (addr, DS, *VarInfo, IGM.getPointerAlignment (),
5085
+ /* init*/ true );
4947
5086
Indirection = IndirectValue;
4948
5087
}
4949
5088
0 commit comments