89 lines · cpp
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-exception6//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 18using namespace llvm;19 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 else50 // 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 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 frame63 // to the receiver.64 updateReceiver(Inst);65}66 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 75void CFIFunctionFrameStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame) {76 // Send the last instruction with the final directives of the current frame to77 // 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