summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86MCInstLower.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2017-10-11 21:24:33 +0000
committerReid Kleckner <rnk@google.com>2017-10-11 21:24:33 +0000
commit9cdd4df81a5ec0652931bf1c2e3706b9d54188c7 (patch)
treef8c7c13ff19d6b7933c708c22024822fc72c6521 /llvm/lib/Target/X86/X86MCInstLower.cpp
parent1961c6cb2caf16033006257e3d37c81e74f195da (diff)
downloadbcm5719-llvm-9cdd4df81a5ec0652931bf1c2e3706b9d54188c7.tar.gz
bcm5719-llvm-9cdd4df81a5ec0652931bf1c2e3706b9d54188c7.zip
[codeview] Implement FPO data assembler directives
Summary: This adds a set of new directives that describe 32-bit x86 prologues. The directives are limited and do not expose the full complexity of codeview FPO data. They are merely a convenience for the compiler to generate more readable assembly so we don't need to generate tons of labels in CodeGen. If our prologue emission changes in the future, we can change the set of available directives to suit our needs. These are modelled after the .seh_ directives, which use a different format that interacts with exception handling. The directives are: .cv_fpo_proc _foo .cv_fpo_pushreg ebp/ebx/etc .cv_fpo_setframe ebp/esi/etc .cv_fpo_stackalloc 200 .cv_fpo_endprologue .cv_fpo_endproc .cv_fpo_data _foo I tried to follow the implementation of ARM EHABI CFI directives by sinking most directives out of MCStreamer and into X86TargetStreamer. This helps avoid polluting non-X86 code with WinCOFF specific logic. I used cdb to confirm that this can show locals in parent CSRs in a few cases, most importantly the one where we use ESI as a frame pointer, i.e. the one in http://crbug.com/756153#c28 Once we have cdb integration in debuginfo-tests, we can add integration tests there. Reviewers: majnemer, hans Subscribers: aemerson, mgorny, kristof.beyls, llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D38776 llvm-svn: 315513
Diffstat (limited to 'llvm/lib/Target/X86/X86MCInstLower.cpp')
-rw-r--r--llvm/lib/Target/X86/X86MCInstLower.cpp107
1 files changed, 78 insertions, 29 deletions
diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp
index 36d81128acf..78e6e5f1b2e 100644
--- a/llvm/lib/Target/X86/X86MCInstLower.cpp
+++ b/llvm/lib/Target/X86/X86MCInstLower.cpp
@@ -15,6 +15,7 @@
#include "InstPrinter/X86ATTInstPrinter.h"
#include "InstPrinter/X86InstComments.h"
#include "MCTargetDesc/X86BaseInfo.h"
+#include "MCTargetDesc/X86TargetStreamer.h"
#include "Utils/X86ShuffleDecode.h"
#include "X86AsmPrinter.h"
#include "X86RegisterInfo.h"
@@ -1363,6 +1364,82 @@ static void printConstant(const Constant *COp, raw_ostream &CS) {
}
}
+void X86AsmPrinter::EmitSEHInstruction(const MachineInstr *MI) {
+ assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
+ assert(getSubtarget().isOSWindows() && "SEH_ instruction Windows only");
+ const X86RegisterInfo *RI =
+ MF->getSubtarget<X86Subtarget>().getRegisterInfo();
+
+ // Use the .cv_fpo directives if we're emitting CodeView on 32-bit x86.
+ if (EmitFPOData) {
+ X86TargetStreamer *XTS =
+ static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer());
+ switch (MI->getOpcode()) {
+ case X86::SEH_PushReg:
+ XTS->emitFPOPushReg(MI->getOperand(0).getImm());
+ break;
+ case X86::SEH_StackAlloc:
+ XTS->emitFPOStackAlloc(MI->getOperand(0).getImm());
+ break;
+ case X86::SEH_SetFrame:
+ assert(MI->getOperand(1).getImm() == 0 &&
+ ".cv_fpo_setframe takes no offset");
+ XTS->emitFPOSetFrame(MI->getOperand(0).getImm());
+ break;
+ case X86::SEH_EndPrologue:
+ XTS->emitFPOEndPrologue();
+ break;
+ case X86::SEH_SaveReg:
+ case X86::SEH_SaveXMM:
+ case X86::SEH_PushFrame:
+ llvm_unreachable("SEH_ directive incompatible with FPO");
+ break;
+ default:
+ llvm_unreachable("expected SEH_ instruction");
+ }
+ return;
+ }
+
+ // Otherwise, use the .seh_ directives for all other Windows platforms.
+ switch (MI->getOpcode()) {
+ case X86::SEH_PushReg:
+ OutStreamer->EmitWinCFIPushReg(
+ RI->getSEHRegNum(MI->getOperand(0).getImm()));
+ break;
+
+ case X86::SEH_SaveReg:
+ OutStreamer->EmitWinCFISaveReg(RI->getSEHRegNum(MI->getOperand(0).getImm()),
+ MI->getOperand(1).getImm());
+ break;
+
+ case X86::SEH_SaveXMM:
+ OutStreamer->EmitWinCFISaveXMM(RI->getSEHRegNum(MI->getOperand(0).getImm()),
+ MI->getOperand(1).getImm());
+ break;
+
+ case X86::SEH_StackAlloc:
+ OutStreamer->EmitWinCFIAllocStack(MI->getOperand(0).getImm());
+ break;
+
+ case X86::SEH_SetFrame:
+ OutStreamer->EmitWinCFISetFrame(
+ RI->getSEHRegNum(MI->getOperand(0).getImm()),
+ MI->getOperand(1).getImm());
+ break;
+
+ case X86::SEH_PushFrame:
+ OutStreamer->EmitWinCFIPushFrame(MI->getOperand(0).getImm());
+ break;
+
+ case X86::SEH_EndPrologue:
+ OutStreamer->EmitWinCFIEndProlog();
+ break;
+
+ default:
+ llvm_unreachable("expected SEH_ instruction");
+ }
+}
+
void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
X86MCInstLower MCInstLowering(*MF, *this);
const X86RegisterInfo *RI = MF->getSubtarget<X86Subtarget>().getRegisterInfo();
@@ -1540,41 +1617,13 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
return;
case X86::SEH_PushReg:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFIPushReg(RI->getSEHRegNum(MI->getOperand(0).getImm()));
- return;
-
case X86::SEH_SaveReg:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFISaveReg(RI->getSEHRegNum(MI->getOperand(0).getImm()),
- MI->getOperand(1).getImm());
- return;
-
case X86::SEH_SaveXMM:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFISaveXMM(RI->getSEHRegNum(MI->getOperand(0).getImm()),
- MI->getOperand(1).getImm());
- return;
-
case X86::SEH_StackAlloc:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFIAllocStack(MI->getOperand(0).getImm());
- return;
-
case X86::SEH_SetFrame:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFISetFrame(RI->getSEHRegNum(MI->getOperand(0).getImm()),
- MI->getOperand(1).getImm());
- return;
-
case X86::SEH_PushFrame:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFIPushFrame(MI->getOperand(0).getImm());
- return;
-
case X86::SEH_EndPrologue:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFIEndProlog();
+ EmitSEHInstruction(MI);
return;
case X86::SEH_Epilogue: {
OpenPOWER on IntegriCloud