xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DWARFCFIChecker/DWARFCFIFunctionFrameStreamer.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file declares CFIFunctionFrameStreamer class.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_DWARFCFICHECKER_DWARFCFIFUNCTIONFRAMESTREAMER_H
15 #define LLVM_DWARFCFICHECKER_DWARFCFIFUNCTIONFRAMESTREAMER_H
16 
17 #include "DWARFCFIFunctionFrameReceiver.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCDwarf.h"
21 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/MC/MCStreamer.h"
23 #include "llvm/Support/Compiler.h"
24 #include <memory>
25 #include <optional>
26 
27 namespace llvm {
28 
29 /// This class is an `MCStreamer` implementation that watches for machine
30 /// instructions and CFI directives. It cuts the stream into function frames and
31 /// channels them to `CFIFunctionFrameReceiver`. A function frame is the machine
32 /// instructions and CFI directives that are between `.cfi_startproc` and
33 /// `.cfi_endproc` directives.
34 class LLVM_ABI CFIFunctionFrameStreamer : public MCStreamer {
35 public:
CFIFunctionFrameStreamer(MCContext & Context,std::unique_ptr<CFIFunctionFrameReceiver> Receiver)36   CFIFunctionFrameStreamer(MCContext &Context,
37                            std::unique_ptr<CFIFunctionFrameReceiver> Receiver)
38       : MCStreamer(Context), Receiver(std::move(Receiver)) {
39     assert(this->Receiver && "Receiver should not be null");
40   }
41 
hasRawTextSupport()42   bool hasRawTextSupport() const override { return true; }
emitRawTextImpl(StringRef String)43   void emitRawTextImpl(StringRef String) override {}
44 
emitSymbolAttribute(MCSymbol * Symbol,MCSymbolAttr Attribute)45   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
46     return true;
47   }
48 
emitCommonSymbol(MCSymbol * Symbol,uint64_t Size,Align ByteAlignment)49   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
50                         Align ByteAlignment) override {}
emitSubsectionsViaSymbols()51   void emitSubsectionsViaSymbols() override {};
beginCOFFSymbolDef(const MCSymbol * Symbol)52   void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
emitCOFFSymbolStorageClass(int StorageClass)53   void emitCOFFSymbolStorageClass(int StorageClass) override {}
emitCOFFSymbolType(int Type)54   void emitCOFFSymbolType(int Type) override {}
endCOFFSymbolDef()55   void endCOFFSymbolDef() override {}
emitXCOFFSymbolLinkageWithVisibility(MCSymbol * Symbol,MCSymbolAttr Linkage,MCSymbolAttr Visibility)56   void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
57                                             MCSymbolAttr Linkage,
58                                             MCSymbolAttr Visibility) override {}
59 
60   void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
61   void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
62   void emitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame) override;
63 
64 private:
65   /// This method sends the last instruction, along with its associated
66   /// directives, to the receiver and then updates the internal state of the
67   /// class. It moves the directive index to after the last directive and sets
68   /// the last instruction to \p NewInst . This method assumes it is called in
69   /// the middle of an unfinished DWARF debug frame; if not, an assertion will
70   /// fail.
71   void updateReceiver(const std::optional<MCInst> &NewInst);
72 
73 private:
74   /// The following fields are stacks that store the state of the stream sent to
75   /// the receiver in each frame. This class, like `MCStreamer`, assumes that
76   /// the debug frames are intertwined with each other only in stack form.
77 
78   /// The last instruction that is not sent to the receiver for each frame.
79   SmallVector<std::optional<MCInst>> LastInstructions;
80   /// The index of the last directive that is not sent to the receiver for each
81   /// frame.
82   SmallVector<unsigned> LastDirectiveIndices;
83   /// The index of each frame in `DwarfFrameInfos` field in `MCStreamer`.
84   SmallVector<unsigned> FrameIndices;
85 
86   std::unique_ptr<CFIFunctionFrameReceiver> Receiver;
87 };
88 
89 } // namespace llvm
90 
91 #endif
92