Start keeping track of where the various unwind instructions are in the prolog.
authorCharles Davis <cdavis@mines.edu>
Fri, 27 May 2011 03:25:01 +0000 (03:25 +0000)
committerCharles Davis <cdavis@mines.edu>
Fri, 27 May 2011 03:25:01 +0000 (03:25 +0000)
Use them to calculate the offset inside the prolog. Emit this value when
emitting the unwind codes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132177 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCWin64EH.h
lib/MC/MCStreamer.cpp
lib/MC/MCWin64EH.cpp

index 39f304654662002e28391f2f338ef618a969222a..5c0cfad7c36e4b3cb51c23013d0050c8ff7f6767 100644 (file)
@@ -28,30 +28,31 @@ namespace llvm {
     typedef Win64EH::UnwindOpcodes OpType;
   private:
     OpType Operation;
+    MCSymbol *Label;
     unsigned Offset;
     unsigned Register;
   public:
-    MCWin64EHInstruction(OpType Op, unsigned Reg)
-      : Operation(Op), Offset(0), Register(Reg) {
-      assert(Op == Win64EH::UOP_PushNonVol);
+    MCWin64EHInstruction(OpType Op, MCSymbol *L, unsigned Reg)
+      : Operation(Op), Label(L), Offset(0), Register(Reg) {
+     assert(Op == Win64EH::UOP_PushNonVol);
     }
-    MCWin64EHInstruction(unsigned Size)
+    MCWin64EHInstruction(MCSymbol *L, unsigned Size)
       : Operation(Size>128 ? Win64EH::UOP_AllocLarge : Win64EH::UOP_AllocSmall),
-        Offset(Size) { }
-    MCWin64EHInstruction(OpType Op, unsigned Reg,
-                         unsigned Off)
-      : Operation(Op), Offset(Off), Register(Reg) {
+        Label(L), Offset(Size) { }
+    MCWin64EHInstruction(OpType Op, MCSymbol *L, unsigned Reg, unsigned Off)
+      : Operation(Op), Label(L), Offset(Off), Register(Reg) {
       assert(Op == Win64EH::UOP_SetFPReg ||
              Op == Win64EH::UOP_SaveNonVol ||
              Op == Win64EH::UOP_SaveNonVolBig ||
              Op == Win64EH::UOP_SaveXMM128 ||
              Op == Win64EH::UOP_SaveXMM128Big);
     }
-    MCWin64EHInstruction(OpType Op, bool Code)
-      : Operation(Op), Offset(Code ? 1 : 0) {
+    MCWin64EHInstruction(OpType Op, MCSymbol *L, bool Code)
+      : Operation(Op), Label(L), Offset(Code ? 1 : 0) {
       assert(Op == Win64EH::UOP_PushMachFrame);
     }
     OpType getOperation() const { return Operation; }
+    MCSymbol *getLabel() const { return Label; }
     unsigned getOffset() const { return Offset; }
     unsigned getSize() const { return Offset; }
     unsigned getRegister() const { return Register; }
index 881bc8eabaeea7d9bbab3290e9e18e80364def42..974e885aacd0c642b3a137ab2aad752d32a7c4e2 100644 (file)
@@ -385,7 +385,9 @@ void MCStreamer::EmitWin64EHHandlerData() {
 void MCStreamer::EmitWin64EHPushReg(unsigned Register) {
   EnsureValidW64UnwindInfo();
   MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo;
-  MCWin64EHInstruction Inst(Win64EH::UOP_PushNonVol, Register);
+  MCSymbol *Label = getContext().CreateTempSymbol();
+  MCWin64EHInstruction Inst(Win64EH::UOP_PushNonVol, Label, Register);
+  EmitLabel(Label);
   CurFrame->Instructions.push_back(Inst);
 }
 
@@ -396,7 +398,7 @@ void MCStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) {
     report_fatal_error("Frame register and offset already specified!");
   if (Offset & 0x0F)
     report_fatal_error("Misaligned frame pointer offset!");
-  MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, Register, Offset);
+  MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, NULL, Register, Offset);
   CurFrame->LastFrameInst = CurFrame->Instructions.size();
   CurFrame->Instructions.push_back(Inst);
 }
@@ -406,7 +408,9 @@ void MCStreamer::EmitWin64EHAllocStack(unsigned Size) {
   if (Size & 7)
     report_fatal_error("Misaligned stack allocation!");
   MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo;
-  MCWin64EHInstruction Inst(Size);
+  MCSymbol *Label = getContext().CreateTempSymbol();
+  MCWin64EHInstruction Inst(Label, Size);
+  EmitLabel(Label);
   CurFrame->Instructions.push_back(Inst);
 }
 
@@ -415,9 +419,11 @@ void MCStreamer::EmitWin64EHSaveReg(unsigned Register, unsigned Offset) {
   if (Offset & 7)
     report_fatal_error("Misaligned saved register offset!");
   MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo;
+  MCSymbol *Label = getContext().CreateTempSymbol();
   MCWin64EHInstruction Inst(
      Offset > 512*1024-8 ? Win64EH::UOP_SaveNonVolBig : Win64EH::UOP_SaveNonVol,
-                            Register, Offset);
+                            Label, Register, Offset);
+  EmitLabel(Label);
   CurFrame->Instructions.push_back(Inst);
 }
 
@@ -426,9 +432,11 @@ void MCStreamer::EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) {
   if (Offset & 0x0F)
     report_fatal_error("Misaligned saved vector register offset!");
   MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo;
+  MCSymbol *Label = getContext().CreateTempSymbol();
   MCWin64EHInstruction Inst(
     Offset > 512*1024-16 ? Win64EH::UOP_SaveXMM128Big : Win64EH::UOP_SaveXMM128,
-                            Register, Offset);
+                            Label, Register, Offset);
+  EmitLabel(Label);
   CurFrame->Instructions.push_back(Inst);
 }
 
@@ -437,7 +445,9 @@ void MCStreamer::EmitWin64EHPushFrame(bool Code) {
   MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo;
   if (CurFrame->Instructions.size() > 0)
     report_fatal_error("If present, PushMachFrame must be the first UOP");
-  MCWin64EHInstruction Inst(Win64EH::UOP_PushMachFrame, Code);
+  MCSymbol *Label = getContext().CreateTempSymbol();
+  MCWin64EHInstruction Inst(Win64EH::UOP_PushMachFrame, Label, Code);
+  EmitLabel(Label);
   CurFrame->Instructions.push_back(Inst);
 }
 
index 2511e91b850730a5ab0a4149cc1e791c87e5f360..c7141f7ad3ce5c5e92a93b08f184db50876729bc 100644 (file)
@@ -47,18 +47,31 @@ static uint8_t CountOfUnwindCodes(std::vector<MCWin64EHInstruction> &instArray){
   return count;
 }
 
-static void EmitUnwindCode(MCStreamer &streamer, MCWin64EHInstruction &inst) {
+static void EmitAbsDifference(MCStreamer &streamer, MCSymbol *lhs,
+                              MCSymbol *rhs) {
+  MCContext &context = streamer.getContext();
+  const MCExpr *diff = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(
+                                                                  lhs, context),
+                                               MCSymbolRefExpr::Create(
+                                                                  rhs, context),
+                                               context);
+  streamer.EmitAbsValue(diff, 1);
+
+}
+
+static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
+                           MCWin64EHInstruction &inst) {
   uint8_t b1, b2;
   uint16_t w;
   b2 = (inst.getOperation() & 0x0F) << 4;
   switch (inst.getOperation()) {
   case Win64EH::UOP_PushNonVol:
-    streamer.EmitIntValue(0, 1);
+    EmitAbsDifference(streamer, inst.getLabel(), begin);
     b2 |= inst.getRegister() & 0x0F;
     streamer.EmitIntValue(b2, 1);
     break;
   case Win64EH::UOP_AllocLarge:
-    streamer.EmitIntValue(0, 1);
+    EmitAbsDifference(streamer, inst.getLabel(), begin);
     if (inst.getSize() > 512*1024-8) {
       b2 |= 1;
       streamer.EmitIntValue(b2, 1);
@@ -72,8 +85,8 @@ static void EmitUnwindCode(MCStreamer &streamer, MCWin64EHInstruction &inst) {
     streamer.EmitIntValue(w, 2);
     break;
   case Win64EH::UOP_AllocSmall:
-    b2 |= (inst.getSize() >> 3) & 0x0F;
-    streamer.EmitIntValue(0, 1);
+    b2 |= ((inst.getSize()-8) >> 3) & 0x0F;
+    EmitAbsDifference(streamer, inst.getLabel(), begin);
     streamer.EmitIntValue(b2, 1);
     break;
   case Win64EH::UOP_SetFPReg:
@@ -84,7 +97,7 @@ static void EmitUnwindCode(MCStreamer &streamer, MCWin64EHInstruction &inst) {
   case Win64EH::UOP_SaveNonVol:
   case Win64EH::UOP_SaveXMM128:
     b2 |= inst.getRegister() & 0x0F;
-    streamer.EmitIntValue(0, 1);
+    EmitAbsDifference(streamer, inst.getLabel(), begin);
     streamer.EmitIntValue(b2, 1);
     w = inst.getOffset() >> 3;
     if (inst.getOperation() == Win64EH::UOP_SaveXMM128)
@@ -94,7 +107,7 @@ static void EmitUnwindCode(MCStreamer &streamer, MCWin64EHInstruction &inst) {
   case Win64EH::UOP_SaveNonVolBig:
   case Win64EH::UOP_SaveXMM128Big:
     b2 |= inst.getRegister() & 0x0F;
-    streamer.EmitIntValue(0, 1);
+    EmitAbsDifference(streamer, inst.getLabel(), begin);
     streamer.EmitIntValue(b2, 1);
     if (inst.getOperation() == Win64EH::UOP_SaveXMM128Big)
       w = inst.getOffset() & 0xFFF0;
@@ -107,7 +120,7 @@ static void EmitUnwindCode(MCStreamer &streamer, MCWin64EHInstruction &inst) {
   case Win64EH::UOP_PushMachFrame:
     if (inst.isPushCodeFrame())
       b2 |= 1;
-    streamer.EmitIntValue(0, 1);
+    EmitAbsDifference(streamer, inst.getLabel(), begin);
     streamer.EmitIntValue(b2, 1);
     break;
   }
@@ -144,13 +157,7 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) {
   }
   streamer.EmitIntValue(flags, 1);
 
-  // Build up the prolog size expression.
-  const MCExpr *prologSize = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(
-                                                      info->PrologEnd, context),
-                                                     MCSymbolRefExpr::Create(
-                                                          info->Begin, context),
-                                                     context);
-  streamer.EmitAbsValue(prologSize, 1);
+  EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
 
   uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
   streamer.EmitIntValue(numCodes, 1);
@@ -169,7 +176,7 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) {
   for (uint8_t c = 0; c < numInst; ++c) {
     MCWin64EHInstruction inst = info->Instructions.back();
     info->Instructions.pop_back();
-    EmitUnwindCode(streamer, inst);
+    EmitUnwindCode(streamer, info->Begin, inst);
   }
 
   if (flags & Win64EH::UNW_ChainInfo)