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 #include "llvm/DWARFCFIChecker/DWARFCFIFunctionFrameStreamer.h" 10 #include "llvm/ADT/ArrayRef.h" 11 #include "llvm/MC/MCContext.h" 12 #include "llvm/MC/MCDwarf.h" 13 #include "llvm/MC/MCInst.h" 14 #include "llvm/MC/MCInstrInfo.h" 15 #include "llvm/MC/MCStreamer.h" 16 #include <optional> 17 18 using namespace llvm; 19 updateReceiver(const std::optional<MCInst> & NewInst)20void CFIFunctionFrameStreamer::updateReceiver( 21 const std::optional<MCInst> &NewInst) { 22 assert(hasUnfinishedDwarfFrameInfo() && 23 "should have an unfinished DWARF frame here"); 24 assert(!FrameIndices.empty() && 25 "there should be an index available for the current frame"); 26 assert(FrameIndices.size() == LastInstructions.size()); 27 assert(LastInstructions.size() == LastDirectiveIndices.size()); 28 29 auto Frames = getDwarfFrameInfos(); 30 assert(FrameIndices.back() < Frames.size()); 31 unsigned LastDirectiveIndex = LastDirectiveIndices.back(); 32 unsigned CurrentDirectiveIndex = 33 Frames[FrameIndices.back()].Instructions.size(); 34 assert(CurrentDirectiveIndex >= LastDirectiveIndex); 35 36 const MCDwarfFrameInfo *LastFrame = &Frames[FrameIndices.back()]; 37 ArrayRef<MCCFIInstruction> Directives; 38 if (LastDirectiveIndex < CurrentDirectiveIndex) { 39 Directives = ArrayRef<MCCFIInstruction>(LastFrame->Instructions); 40 Directives = 41 Directives.drop_front(LastDirectiveIndex) 42 .drop_back(LastFrame->Instructions.size() - CurrentDirectiveIndex); 43 } 44 45 auto MaybeLastInstruction = LastInstructions.back(); 46 if (MaybeLastInstruction) 47 // The directives are associated with an instruction. 48 Receiver->emitInstructionAndDirectives(*MaybeLastInstruction, Directives); 49 else 50 // The directives are the prologue directives. 51 Receiver->startFunctionFrame(false /* TODO: should put isEH here */, 52 Directives); 53 54 // Update the internal state for the top frame. 55 LastInstructions.back() = NewInst; 56 LastDirectiveIndices.back() = CurrentDirectiveIndex; 57 } 58 emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)59void CFIFunctionFrameStreamer::emitInstruction(const MCInst &Inst, 60 const MCSubtargetInfo &STI) { 61 if (hasUnfinishedDwarfFrameInfo()) 62 // Send the last instruction with the unsent directives already in the frame 63 // to the receiver. 64 updateReceiver(Inst); 65 } 66 emitCFIStartProcImpl(MCDwarfFrameInfo & Frame)67void CFIFunctionFrameStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { 68 LastInstructions.push_back(std::nullopt); 69 LastDirectiveIndices.push_back(0); 70 FrameIndices.push_back(getNumFrameInfos()); 71 72 MCStreamer::emitCFIStartProcImpl(Frame); 73 } 74 emitCFIEndProcImpl(MCDwarfFrameInfo & CurFrame)75void CFIFunctionFrameStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame) { 76 // Send the last instruction with the final directives of the current frame to 77 // the receiver. 78 updateReceiver(std::nullopt); 79 80 assert(!FrameIndices.empty() && "There should be at least one frame to pop"); 81 LastDirectiveIndices.pop_back(); 82 LastInstructions.pop_back(); 83 FrameIndices.pop_back(); 84 85 Receiver->finishFunctionFrame(); 86 87 MCStreamer::emitCFIEndProcImpl(CurFrame); 88 } 89