36 bool emitFPOEndPrologue(
SMLoc L)
override;
37 bool emitFPOEndProc(
SMLoc L)
override;
39 bool emitFPOPushReg(
unsigned Reg,
SMLoc L)
override;
40 bool emitFPOStackAlloc(
unsigned StackAlloc,
SMLoc L)
override;
41 bool emitFPOStackAlign(
unsigned Align,
SMLoc L)
override;
42 bool emitFPOSetFrame(
unsigned Reg,
SMLoc L)
override;
46 struct FPOInstruction {
62 unsigned ParamsSize = 0;
73 std::unique_ptr<FPOData> CurFPOData;
75 bool haveOpenFPOData() {
return !!CurFPOData; }
79 bool checkInFPOPrologue(
SMLoc L);
83 MCContext &getContext() {
return getStreamer().getContext(); }
90 bool emitFPOEndPrologue(
SMLoc L)
override;
91 bool emitFPOEndProc(
SMLoc L)
override;
93 bool emitFPOPushReg(
unsigned Reg,
SMLoc L)
override;
94 bool emitFPOStackAlloc(
unsigned StackAlloc,
SMLoc L)
override;
95 bool emitFPOStackAlign(
unsigned Align,
SMLoc L)
override;
96 bool emitFPOSetFrame(
unsigned Reg,
SMLoc L)
override;
101 unsigned ParamsSize,
SMLoc L) {
102 OS <<
"\t.cv_fpo_proc\t";
103 ProcSym->
print(OS, getStreamer().getContext().getAsmInfo());
104 OS <<
' ' << ParamsSize <<
'\n';
108 bool X86WinCOFFAsmTargetStreamer::emitFPOEndPrologue(
SMLoc L) {
109 OS <<
"\t.cv_fpo_endprologue\n";
113 bool X86WinCOFFAsmTargetStreamer::emitFPOEndProc(
SMLoc L) {
114 OS <<
"\t.cv_fpo_endproc\n";
118 bool X86WinCOFFAsmTargetStreamer::emitFPOData(
const MCSymbol *ProcSym,
120 OS <<
"\t.cv_fpo_data\t";
121 ProcSym->
print(OS, getStreamer().getContext().getAsmInfo());
126 bool X86WinCOFFAsmTargetStreamer::emitFPOPushReg(
unsigned Reg,
SMLoc L) {
127 OS <<
"\t.cv_fpo_pushreg\t";
128 InstPrinter.printRegName(OS, Reg);
133 bool X86WinCOFFAsmTargetStreamer::emitFPOStackAlloc(
unsigned StackAlloc,
135 OS <<
"\t.cv_fpo_stackalloc\t" << StackAlloc <<
'\n';
139 bool X86WinCOFFAsmTargetStreamer::emitFPOStackAlign(
unsigned Align,
SMLoc L) {
140 OS <<
"\t.cv_fpo_stackalign\t" << Align <<
'\n';
144 bool X86WinCOFFAsmTargetStreamer::emitFPOSetFrame(
unsigned Reg,
SMLoc L) {
145 OS <<
"\t.cv_fpo_setframe\t";
146 InstPrinter.printRegName(OS, Reg);
151 bool X86WinCOFFTargetStreamer::checkInFPOPrologue(
SMLoc L) {
152 if (!haveOpenFPOData() || CurFPOData->PrologueEnd) {
153 getContext().reportError(
155 "directive must appear between .cv_fpo_proc and .cv_fpo_endprologue");
161 MCSymbol *X86WinCOFFTargetStreamer::emitFPOLabel() {
162 MCSymbol *
Label = getContext().createTempSymbol(
"cfi",
true);
163 getStreamer().EmitLabel(Label);
167 bool X86WinCOFFTargetStreamer::emitFPOProc(
const MCSymbol *ProcSym,
168 unsigned ParamsSize,
SMLoc L) {
169 if (haveOpenFPOData()) {
170 getContext().reportError(
171 L,
"opening new .cv_fpo_proc before closing previous frame");
174 CurFPOData = llvm::make_unique<FPOData>();
175 CurFPOData->Function = ProcSym;
176 CurFPOData->Begin = emitFPOLabel();
177 CurFPOData->ParamsSize = ParamsSize;
181 bool X86WinCOFFTargetStreamer::emitFPOEndProc(
SMLoc L) {
182 if (!haveOpenFPOData()) {
183 getContext().reportError(L,
".cv_fpo_endproc must appear after .cv_proc");
186 if (!CurFPOData->PrologueEnd) {
188 if (!CurFPOData->Instructions.empty()) {
189 getContext().reportError(L,
"missing .cv_fpo_endprologue");
190 CurFPOData->Instructions.clear();
195 CurFPOData->PrologueEnd = CurFPOData->Begin;
198 CurFPOData->End = emitFPOLabel();
199 const MCSymbol *Fn = CurFPOData->Function;
200 AllFPOData.insert({Fn, std::move(CurFPOData)});
204 bool X86WinCOFFTargetStreamer::emitFPOSetFrame(
unsigned Reg,
SMLoc L) {
205 if (checkInFPOPrologue(L))
208 Inst.Label = emitFPOLabel();
209 Inst.Op = FPOInstruction::SetFrame;
210 Inst.RegOrOffset =
Reg;
211 CurFPOData->Instructions.push_back(Inst);
215 bool X86WinCOFFTargetStreamer::emitFPOPushReg(
unsigned Reg,
SMLoc L) {
216 if (checkInFPOPrologue(L))
219 Inst.Label = emitFPOLabel();
220 Inst.Op = FPOInstruction::PushReg;
221 Inst.RegOrOffset =
Reg;
222 CurFPOData->Instructions.push_back(Inst);
226 bool X86WinCOFFTargetStreamer::emitFPOStackAlloc(
unsigned StackAlloc,
SMLoc L) {
227 if (checkInFPOPrologue(L))
230 Inst.Label = emitFPOLabel();
231 Inst.Op = FPOInstruction::StackAlloc;
232 Inst.RegOrOffset = StackAlloc;
233 CurFPOData->Instructions.push_back(Inst);
237 bool X86WinCOFFTargetStreamer::emitFPOStackAlign(
unsigned Align,
SMLoc L) {
238 if (checkInFPOPrologue(L))
240 if (!
llvm::any_of(CurFPOData->Instructions, [](
const FPOInstruction &Inst) {
241 return Inst.Op == FPOInstruction::SetFrame;
243 getContext().reportError(
244 L,
"a frame register must be established before aligning the stack");
248 Inst.Label = emitFPOLabel();
249 Inst.Op = FPOInstruction::StackAlign;
250 Inst.RegOrOffset =
Align;
251 CurFPOData->Instructions.push_back(Inst);
255 bool X86WinCOFFTargetStreamer::emitFPOEndPrologue(
SMLoc L) {
256 if (checkInFPOPrologue(L))
258 CurFPOData->PrologueEnd = emitFPOLabel();
263 struct RegSaveOffset {
264 RegSaveOffset(
unsigned Reg,
unsigned Offset) : Reg(Reg), Offset(Offset) {}
270 struct FPOStateMachine {
271 explicit FPOStateMachine(
const FPOData *FPO) : FPO(FPO) {}
273 const FPOData *
FPO =
nullptr;
274 unsigned FrameReg = 0;
275 unsigned FrameRegOff = 0;
276 unsigned CurOffset = 0;
277 unsigned LocalSize = 0;
278 unsigned SavedRegSize = 0;
279 unsigned StackOffsetBeforeAlign = 0;
280 unsigned StackAlign = 0;
303 case X86::EBP: OS <<
"$ebp";
break;
304 case X86::EIP: OS <<
"$eip";
break;
314 unsigned CurFlags = Flags;
315 if (Label == FPO->Begin)
322 assert((StackAlign == 0 || FrameReg != 0) &&
323 "cannot align stack without frame reg");
324 StringRef CFAVar = StackAlign == 0 ?
"$T0" :
"$T1";
328 FuncOS << CFAVar <<
' ' <<
printFPOReg(MRI, FrameReg) <<
' ' << FrameRegOff
336 FuncOS <<
"$T0 " << CFAVar <<
' ' << StackOffsetBeforeAlign <<
" - " 337 << StackAlign <<
" @ = ";
344 FuncOS << CFAVar <<
" .raSearch = ";
348 FuncOS <<
"$eip " << CFAVar <<
" ^ = ";
349 FuncOS <<
"$esp " << CFAVar <<
" 4 + = ";
352 for (RegSaveOffset RO : RegSaveOffsets)
353 FuncOS <<
printFPOReg(MRI, RO.Reg) <<
' ' << CFAVar <<
' ' << RO.Offset
361 unsigned MaxStackSize = 0;
386 bool X86WinCOFFTargetStreamer::emitFPOData(
const MCSymbol *ProcSym,
SMLoc L) {
390 auto I = AllFPOData.find(ProcSym);
391 if (
I == AllFPOData.end()) {
396 const FPOData *FPO =
I->second.get();
397 assert(FPO->Begin && FPO->End && FPO->PrologueEnd &&
"missing FPO label");
412 FPOStateMachine FSM(FPO);
414 FSM.emitFrameDataRecord(OS, FPO->Begin);
415 for (
const FPOInstruction &Inst : FPO->Instructions) {
417 case FPOInstruction::PushReg:
419 FSM.SavedRegSize += 4;
420 FSM.RegSaveOffsets.push_back({Inst.RegOrOffset, FSM.CurOffset});
422 case FPOInstruction::SetFrame:
423 FSM.FrameReg = Inst.RegOrOffset;
424 FSM.FrameRegOff = FSM.CurOffset;
426 case FPOInstruction::StackAlign:
427 FSM.StackOffsetBeforeAlign = FSM.CurOffset;
428 FSM.StackAlign = Inst.RegOrOffset;
430 case FPOInstruction::StackAlloc:
431 FSM.CurOffset += Inst.RegOrOffset;
432 FSM.LocalSize += Inst.RegOrOffset;
438 FSM.emitFrameDataRecord(OS, Inst.Label);
452 return new X86WinCOFFAsmTargetStreamer(S, OS, *InstPrinter);
461 return new X86WinCOFFTargetStreamer(S);
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
This class represents lattice values for constants.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MCTargetStreamer * createX86ObjectTargetStreamer(MCStreamer &OS, const MCSubtargetInfo &STI)
Implements X86-only directives for object files.
Target specific streamer interface.
std::pair< StringRef, unsigned > addToStringTable(StringRef S)
Add something to the string table.
A raw_ostream that writes to an SmallVector or SmallString.
const Triple & getTargetTriple() const
MCContext & getContext() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Context object for machine code objects.
virtual void EmitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers...
void EmitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Streaming machine code generation interface.
MCSymbol * createTempSymbol(bool CanBeUnnamed=true)
Create and return a new assembler temporary symbol with a unique but unspecified name.
unsigned const MachineRegisterInfo * MRI
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
PowerPC Reduce CR logical Operation
static Printable printFPOReg(const MCRegisterInfo *MRI, unsigned LLVMReg)
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly...
void reportError(SMLoc L, const Twine &Msg)
MCTargetStreamer * createX86AsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint, bool isVerboseAsm)
Implements X86-only directives for assembly emission.
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size)
Emit the absolute difference between two symbols.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
StringRef str()
Return a StringRef for the vector contents.
X86 target streamer implementing x86-only assembly directives.
int getCodeViewRegNum(unsigned RegNum) const
Map a target register to an equivalent CodeView register number.
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Generic base class for all target subtargets.
StringRef getName() const
getName - Get the symbol name.
CodeViewContext & getCVContext()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MCRegisterInfo * getRegisterInfo() const
virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
Simple wrapper around std::function<void(raw_ostream&)>.
Represents a location in source code.
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Holds state from .cv_file and .cv_loc directives for later emission.