@@ -838,17 +838,21 @@ CodeViewDebug::createDefRangeMem(uint16_t CVRegister, int Offset) {
838
838
DR.InMemory = -1 ;
839
839
DR.DataOffset = Offset;
840
840
assert (DR.DataOffset == Offset && " truncation" );
841
+ DR.IsSubfield = 0 ;
841
842
DR.StructOffset = 0 ;
842
843
DR.CVRegister = CVRegister;
843
844
return DR;
844
845
}
845
846
846
847
CodeViewDebug::LocalVarDefRange
847
- CodeViewDebug::createDefRangeReg (uint16_t CVRegister) {
848
+ CodeViewDebug::createDefRangeGeneral (uint16_t CVRegister, bool InMemory,
849
+ int Offset, bool IsSubfield,
850
+ uint16_t StructOffset) {
848
851
LocalVarDefRange DR;
849
- DR.InMemory = 0 ;
850
- DR.DataOffset = 0 ;
851
- DR.StructOffset = 0 ;
852
+ DR.InMemory = InMemory;
853
+ DR.DataOffset = Offset;
854
+ DR.IsSubfield = IsSubfield;
855
+ DR.StructOffset = StructOffset;
852
856
DR.CVRegister = CVRegister;
853
857
return DR;
854
858
}
@@ -929,10 +933,16 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
929
933
const MachineInstr *DVInst = Range.first ;
930
934
assert (DVInst->isDebugValue () && " Invalid History entry" );
931
935
const DIExpression *DIExpr = DVInst->getDebugExpression ();
932
-
933
- // Bail if there is a complex DWARF expression for now.
934
- if (DIExpr && DIExpr->getNumElements () > 0 )
935
- continue ;
936
+ bool IsSubfield = false ;
937
+ unsigned StructOffset = 0 ;
938
+
939
+ // Handle bitpieces.
940
+ if (DIExpr && DIExpr->isBitPiece ()) {
941
+ IsSubfield = true ;
942
+ StructOffset = DIExpr->getBitPieceOffset () / 8 ;
943
+ } else if (DIExpr && DIExpr->getNumElements () > 0 ) {
944
+ continue ; // Ignore unrecognized exprs.
945
+ }
936
946
937
947
// Bail if operand 0 is not a valid register. This means the variable is a
938
948
// simple constant, or is described by a complex expression.
@@ -944,28 +954,34 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
944
954
continue ;
945
955
946
956
// Handle the two cases we can handle: indirect in memory and in register.
947
- bool IsIndirect = DVInst->getOperand (1 ).isImm ();
948
- unsigned CVReg = TRI->getCodeViewRegNum (DVInst->getOperand (0 ).getReg ());
957
+ unsigned CVReg = TRI->getCodeViewRegNum (Reg);
958
+ bool InMemory = DVInst->getOperand (1 ).isImm ();
959
+ int Offset = InMemory ? DVInst->getOperand (1 ).getImm () : 0 ;
949
960
{
950
- LocalVarDefRange DefRange ;
951
- if (IsIndirect) {
952
- int64_t Offset = DVInst-> getOperand ( 1 ). getImm () ;
953
- DefRange = createDefRangeMem (CVReg, Offset) ;
954
- } else {
955
- DefRange = createDefRangeReg (CVReg) ;
956
- }
961
+ LocalVarDefRange DR ;
962
+ DR. CVRegister = CVReg;
963
+ DR. InMemory = InMemory ;
964
+ DR. DataOffset = Offset;
965
+ DR. IsSubfield = IsSubfield;
966
+ DR. StructOffset = StructOffset ;
967
+
957
968
if (Var.DefRanges .empty () ||
958
- Var.DefRanges .back ().isDifferentLocation (DefRange )) {
959
- Var.DefRanges .emplace_back (std::move (DefRange ));
969
+ Var.DefRanges .back ().isDifferentLocation (DR )) {
970
+ Var.DefRanges .emplace_back (std::move (DR ));
960
971
}
961
972
}
962
973
963
974
// Compute the label range.
964
975
const MCSymbol *Begin = getLabelBeforeInsn (Range.first );
965
976
const MCSymbol *End = getLabelAfterInsn (Range.second );
966
977
if (!End) {
967
- if (std::next (I) != E)
968
- End = getLabelBeforeInsn (std::next (I)->first );
978
+ // This range is valid until the next overlapping bitpiece. In the
979
+ // common case, ranges will not be bitpieces, so they will overlap.
980
+ auto J = std::next (I);
981
+ while (J != E && !piecesOverlap (DIExpr, J->first ->getDebugExpression ()))
982
+ ++J;
983
+ if (J != E)
984
+ End = getLabelBeforeInsn (J->first );
969
985
else
970
986
End = Asm->getFunctionEnd ();
971
987
}
@@ -2024,13 +2040,15 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
2024
2040
SmallString<20 > BytePrefix;
2025
2041
for (const LocalVarDefRange &DefRange : Var.DefRanges ) {
2026
2042
BytePrefix.clear ();
2027
- // FIXME: Handle bitpieces.
2028
- if (DefRange.StructOffset != 0 )
2029
- continue ;
2030
-
2031
2043
if (DefRange.InMemory ) {
2032
- DefRangeRegisterRelSym Sym (DefRange.CVRegister , 0 , DefRange.DataOffset , 0 ,
2033
- 0 , 0 , ArrayRef<LocalVariableAddrGap>());
2044
+ uint16_t RegRelFlags = 0 ;
2045
+ if (DefRange.IsSubfield ) {
2046
+ RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag |
2047
+ (DefRange.StructOffset
2048
+ << DefRangeRegisterRelSym::OffsetInParentShift);
2049
+ }
2050
+ DefRangeRegisterRelSym Sym (DefRange.CVRegister , RegRelFlags,
2051
+ DefRange.DataOffset , None);
2034
2052
ulittle16_t SymKind = ulittle16_t (S_DEFRANGE_REGISTER_REL);
2035
2053
BytePrefix +=
2036
2054
StringRef (reinterpret_cast <const char *>(&SymKind), sizeof (SymKind));
@@ -2039,15 +2057,26 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
2039
2057
sizeof (Sym.Header ) - sizeof (LocalVariableAddrRange));
2040
2058
} else {
2041
2059
assert (DefRange.DataOffset == 0 && " unexpected offset into register" );
2042
- // Unclear what matters here.
2043
- DefRangeRegisterSym Sym (DefRange.CVRegister , 0 , 0 , 0 , 0 ,
2044
- ArrayRef<LocalVariableAddrGap>());
2045
- ulittle16_t SymKind = ulittle16_t (S_DEFRANGE_REGISTER);
2046
- BytePrefix +=
2047
- StringRef (reinterpret_cast <const char *>(&SymKind), sizeof (SymKind));
2048
- BytePrefix +=
2049
- StringRef (reinterpret_cast <const char *>(&Sym.Header ),
2050
- sizeof (Sym.Header ) - sizeof (LocalVariableAddrRange));
2060
+ if (DefRange.IsSubfield ) {
2061
+ // Unclear what matters here.
2062
+ DefRangeSubfieldRegisterSym Sym (DefRange.CVRegister , 0 ,
2063
+ DefRange.StructOffset , None);
2064
+ ulittle16_t SymKind = ulittle16_t (S_DEFRANGE_SUBFIELD_REGISTER);
2065
+ BytePrefix += StringRef (reinterpret_cast <const char *>(&SymKind),
2066
+ sizeof (SymKind));
2067
+ BytePrefix +=
2068
+ StringRef (reinterpret_cast <const char *>(&Sym.Header ),
2069
+ sizeof (Sym.Header ) - sizeof (LocalVariableAddrRange));
2070
+ } else {
2071
+ // Unclear what matters here.
2072
+ DefRangeRegisterSym Sym (DefRange.CVRegister , 0 , None);
2073
+ ulittle16_t SymKind = ulittle16_t (S_DEFRANGE_REGISTER);
2074
+ BytePrefix += StringRef (reinterpret_cast <const char *>(&SymKind),
2075
+ sizeof (SymKind));
2076
+ BytePrefix +=
2077
+ StringRef (reinterpret_cast <const char *>(&Sym.Header ),
2078
+ sizeof (Sym.Header ) - sizeof (LocalVariableAddrRange));
2079
+ }
2051
2080
}
2052
2081
OS.EmitCVDefRangeDirective (DefRange.Ranges , BytePrefix);
2053
2082
}
0 commit comments