xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86AsmPrinter.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- X86AsmPrinter.h - X86 implementation of AsmPrinter ------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_X86_X86ASMPRINTER_H
100b57cec5SDimitry Andric #define LLVM_LIB_TARGET_X86_X86ASMPRINTER_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/FaultMaps.h"
140b57cec5SDimitry Andric #include "llvm/CodeGen/StackMaps.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric // Implemented in X86MCInstLower.cpp
170b57cec5SDimitry Andric namespace {
180b57cec5SDimitry Andric   class X86MCInstLower;
190b57cec5SDimitry Andric }
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric namespace llvm {
225ffd83dbSDimitry Andric class MCCodeEmitter;
230b57cec5SDimitry Andric class MCStreamer;
245ffd83dbSDimitry Andric class X86Subtarget;
255ffd83dbSDimitry Andric class TargetMachine;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
28480093f4SDimitry Andric   const X86Subtarget *Subtarget = nullptr;
290b57cec5SDimitry Andric   FaultMaps FM;
300b57cec5SDimitry Andric   std::unique_ptr<MCCodeEmitter> CodeEmitter;
310b57cec5SDimitry Andric   bool EmitFPOData = false;
320eae32dcSDimitry Andric   bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags = false;
33bdd1243dSDimitry Andric   bool IndCSPrefix = false;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   // This utility class tracks the length of a stackmap instruction's 'shadow'.
360b57cec5SDimitry Andric   // It is used by the X86AsmPrinter to ensure that the stackmap shadow
370b57cec5SDimitry Andric   // invariants (i.e. no other stackmaps, patchpoints, or control flow within
380b57cec5SDimitry Andric   // the shadow) are met, while outputting a minimal number of NOPs for padding.
390b57cec5SDimitry Andric   //
400b57cec5SDimitry Andric   // To minimise the number of NOPs used, the shadow tracker counts the number
410b57cec5SDimitry Andric   // of instruction bytes output since the last stackmap. Only if there are too
420b57cec5SDimitry Andric   // few instruction bytes to cover the shadow are NOPs used for padding.
430b57cec5SDimitry Andric   class StackMapShadowTracker {
440b57cec5SDimitry Andric   public:
450b57cec5SDimitry Andric     void startFunction(MachineFunction &MF) {
460b57cec5SDimitry Andric       this->MF = &MF;
470b57cec5SDimitry Andric     }
480b57cec5SDimitry Andric     void count(MCInst &Inst, const MCSubtargetInfo &STI,
490b57cec5SDimitry Andric                MCCodeEmitter *CodeEmitter);
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric     // Called to signal the start of a shadow of RequiredSize bytes.
520b57cec5SDimitry Andric     void reset(unsigned RequiredSize) {
530b57cec5SDimitry Andric       RequiredShadowSize = RequiredSize;
540b57cec5SDimitry Andric       CurrentShadowSize = 0;
550b57cec5SDimitry Andric       InShadow = true;
560b57cec5SDimitry Andric     }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric     // Called before every stackmap/patchpoint, and at the end of basic blocks,
590b57cec5SDimitry Andric     // to emit any necessary padding-NOPs.
600b57cec5SDimitry Andric     void emitShadowPadding(MCStreamer &OutStreamer, const MCSubtargetInfo &STI);
610b57cec5SDimitry Andric   private:
62480093f4SDimitry Andric     const MachineFunction *MF = nullptr;
630b57cec5SDimitry Andric     bool InShadow = false;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric     // RequiredShadowSize holds the length of the shadow specified in the most
660b57cec5SDimitry Andric     // recently encountered STACKMAP instruction.
670b57cec5SDimitry Andric     // CurrentShadowSize counts the number of bytes encoded since the most
680b57cec5SDimitry Andric     // recently encountered STACKMAP, stopping when that number is greater than
690b57cec5SDimitry Andric     // or equal to RequiredShadowSize.
700b57cec5SDimitry Andric     unsigned RequiredShadowSize = 0, CurrentShadowSize = 0;
710b57cec5SDimitry Andric   };
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   StackMapShadowTracker SMShadowTracker;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   // All instructions emitted by the X86AsmPrinter should use this helper
760b57cec5SDimitry Andric   // method.
770b57cec5SDimitry Andric   //
780b57cec5SDimitry Andric   // This helper function invokes the SMShadowTracker on each instruction before
790b57cec5SDimitry Andric   // outputting it to the OutStream. This allows the shadow tracker to minimise
800b57cec5SDimitry Andric   // the number of NOPs used for stackmap padding.
810b57cec5SDimitry Andric   void EmitAndCountInstruction(MCInst &Inst);
820b57cec5SDimitry Andric   void LowerSTACKMAP(const MachineInstr &MI);
830b57cec5SDimitry Andric   void LowerPATCHPOINT(const MachineInstr &MI, X86MCInstLower &MCIL);
840b57cec5SDimitry Andric   void LowerSTATEPOINT(const MachineInstr &MI, X86MCInstLower &MCIL);
850b57cec5SDimitry Andric   void LowerFAULTING_OP(const MachineInstr &MI, X86MCInstLower &MCIL);
860b57cec5SDimitry Andric   void LowerPATCHABLE_OP(const MachineInstr &MI, X86MCInstLower &MCIL);
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   void LowerTlsAddr(X86MCInstLower &MCInstLowering, const MachineInstr &MI);
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   // XRay-specific lowering for X86.
910b57cec5SDimitry Andric   void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI,
920b57cec5SDimitry Andric                                      X86MCInstLower &MCIL);
930b57cec5SDimitry Andric   void LowerPATCHABLE_RET(const MachineInstr &MI, X86MCInstLower &MCIL);
940b57cec5SDimitry Andric   void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI, X86MCInstLower &MCIL);
950b57cec5SDimitry Andric   void LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI, X86MCInstLower &MCIL);
960b57cec5SDimitry Andric   void LowerPATCHABLE_TYPED_EVENT_CALL(const MachineInstr &MI,
970b57cec5SDimitry Andric                                        X86MCInstLower &MCIL);
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   void LowerFENTRY_CALL(const MachineInstr &MI, X86MCInstLower &MCIL);
1000b57cec5SDimitry Andric 
101bdd1243dSDimitry Andric   // KCFI specific lowering for X86.
102bdd1243dSDimitry Andric   uint32_t MaskKCFIType(uint32_t Value);
103bdd1243dSDimitry Andric   void EmitKCFITypePadding(const MachineFunction &MF, bool HasType = true);
104bdd1243dSDimitry Andric   void LowerKCFI_CHECK(const MachineInstr &MI);
105bdd1243dSDimitry Andric 
106349cc55cSDimitry Andric   // Address sanitizer specific lowering for X86.
107349cc55cSDimitry Andric   void LowerASAN_CHECK_MEMACCESS(const MachineInstr &MI);
108349cc55cSDimitry Andric 
1090b57cec5SDimitry Andric   // Choose between emitting .seh_ directives and .cv_fpo_ directives.
1100b57cec5SDimitry Andric   void EmitSEHInstruction(const MachineInstr *MI);
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
1130b57cec5SDimitry Andric   void PrintOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
1140b57cec5SDimitry Andric   void PrintModifiedOperand(const MachineInstr *MI, unsigned OpNo,
1150b57cec5SDimitry Andric                             raw_ostream &O, const char *Modifier);
1160b57cec5SDimitry Andric   void PrintPCRelImm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
1170b57cec5SDimitry Andric   void PrintLeaMemReference(const MachineInstr *MI, unsigned OpNo,
1180b57cec5SDimitry Andric                             raw_ostream &O, const char *Modifier);
1190b57cec5SDimitry Andric   void PrintMemReference(const MachineInstr *MI, unsigned OpNo, raw_ostream &O,
1200b57cec5SDimitry Andric                          const char *Modifier);
1210b57cec5SDimitry Andric   void PrintIntelMemReference(const MachineInstr *MI, unsigned OpNo,
122480093f4SDimitry Andric                               raw_ostream &O, const char *Modifier);
123*5f757f3fSDimitry Andric   const MCSubtargetInfo *getIFuncMCSubtargetInfo() const override;
124*5f757f3fSDimitry Andric   void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
125*5f757f3fSDimitry Andric                               MCSymbol *LazyPointer) override;
126*5f757f3fSDimitry Andric   void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
127*5f757f3fSDimitry Andric                                     MCSymbol *LazyPointer) override;
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric public:
1300b57cec5SDimitry Andric   X86AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   StringRef getPassName() const override {
1330b57cec5SDimitry Andric     return "X86 Assembly Printer";
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   const X86Subtarget &getSubtarget() const { return *Subtarget; }
1370b57cec5SDimitry Andric 
1385ffd83dbSDimitry Andric   void emitStartOfAsmFile(Module &M) override;
1390b57cec5SDimitry Andric 
1405ffd83dbSDimitry Andric   void emitEndOfAsmFile(Module &M) override;
1410b57cec5SDimitry Andric 
1425ffd83dbSDimitry Andric   void emitInstruction(const MachineInstr *MI) override;
1430b57cec5SDimitry Andric 
14481ad6265SDimitry Andric   void emitBasicBlockEnd(const MachineBasicBlock &MBB) override;
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
147e8d8bef9SDimitry Andric                        const char *ExtraCode, raw_ostream &O) override;
1480b57cec5SDimitry Andric   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
149e8d8bef9SDimitry Andric                              const char *ExtraCode, raw_ostream &O) override;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   bool doInitialization(Module &M) override {
1520b57cec5SDimitry Andric     SMShadowTracker.reset(0);
1530b57cec5SDimitry Andric     SM.reset();
1540b57cec5SDimitry Andric     FM.reset();
1550b57cec5SDimitry Andric     return AsmPrinter::doInitialization(M);
1560b57cec5SDimitry Andric   }
1570b57cec5SDimitry Andric 
158e8d8bef9SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
1595ffd83dbSDimitry Andric   void emitFunctionBodyStart() override;
1605ffd83dbSDimitry Andric   void emitFunctionBodyEnd() override;
161bdd1243dSDimitry Andric   void emitKCFITypeId(const MachineFunction &MF) override;
1620eae32dcSDimitry Andric 
1630eae32dcSDimitry Andric   bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const override {
1640eae32dcSDimitry Andric     return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
1650eae32dcSDimitry Andric   }
1660b57cec5SDimitry Andric };
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric } // end namespace llvm
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric #endif
171