Teach dwarf writer to handle complex address expression for .debug_loc entries.
This fixes clang generated blocks' variables' debug info.
Radar 9279956.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130373 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index d830e97..86e8bb6 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -749,33 +749,49 @@
   return MachineLocation();
 }
 
+/// getDwarfRegOpSize - get size required to emit given machine location using
+/// dwarf encoding.
+unsigned AsmPrinter::getDwarfRegOpSize(const MachineLocation &MLoc) const {
+  const TargetRegisterInfo *RI = TM.getRegisterInfo();
+  unsigned DWReg = RI->getDwarfRegNum(MLoc.getReg(), false);
+  if (int Offset = MLoc.getOffset()) {
+    // If the value is at a certain offset from frame register then
+    // use DW_OP_breg.
+    if (DWReg < 32)
+      return 1 + MCAsmInfo::getSLEB128Size(Offset);
+    else
+      return 1 + MCAsmInfo::getULEB128Size(MLoc.getReg()) 
+        + MCAsmInfo::getSLEB128Size(Offset);
+  }
+  if (DWReg < 32)
+    return 1;
+
+  return 1 + MCAsmInfo::getULEB128Size(DWReg);
+}
+
 /// EmitDwarfRegOp - Emit dwarf register operation.
 void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
-  const TargetRegisterInfo *RI = TM.getRegisterInfo();
-  unsigned Reg = RI->getDwarfRegNum(MLoc.getReg(), false);
+  const TargetRegisterInfo *TRI = TM.getRegisterInfo();
+  unsigned Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
   if (int Offset =  MLoc.getOffset()) {
-    // If the value is at a certain offset from frame register then
-    // use DW_OP_fbreg.
-    unsigned OffsetSize = Offset ? MCAsmInfo::getSLEB128Size(Offset) : 1;
-    OutStreamer.AddComment("Loc expr size");
-    EmitInt16(1 + OffsetSize);
-    OutStreamer.AddComment(
-      dwarf::OperationEncodingString(dwarf::DW_OP_fbreg));
-    EmitInt8(dwarf::DW_OP_fbreg);
-    OutStreamer.AddComment("Offset");
+    if (Reg < 32) {
+      OutStreamer.AddComment(
+        dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg));
+      EmitInt8(dwarf::DW_OP_breg0 + Reg);
+    } else {
+      OutStreamer.AddComment("DW_OP_bregx");
+      EmitInt8(dwarf::DW_OP_bregx);
+      OutStreamer.AddComment(Twine(Reg));
+      EmitULEB128(Reg);
+    }
     EmitSLEB128(Offset);
   } else {
     if (Reg < 32) {
-      OutStreamer.AddComment("Loc expr size");
-      EmitInt16(1);
       OutStreamer.AddComment(
         dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg));
       EmitInt8(dwarf::DW_OP_reg0 + Reg);
     } else {
-      OutStreamer.AddComment("Loc expr size");
-      EmitInt16(1 + MCAsmInfo::getULEB128Size(Reg));
-      OutStreamer.AddComment(
-        dwarf::OperationEncodingString(dwarf::DW_OP_regx));
+      OutStreamer.AddComment("DW_OP_regx");
       EmitInt8(dwarf::DW_OP_regx);
       OutStreamer.AddComment(Twine(Reg));
       EmitULEB128(Reg);