50struct FPOInstruction {
66 unsigned ParamsSize = 0;
77 std::unique_ptr<FPOData> CurFPOData;
79 bool haveOpenFPOData() {
return !!CurFPOData; }
83 bool checkInFPOPrologue(
SMLoc L);
102void X86WinCOFFAsmTargetStreamer::emitCode16() {
OS <<
"\t.code16\n"; }
104void X86WinCOFFAsmTargetStreamer::emitCode32() {
OS <<
"\t.code32\n"; }
106void X86WinCOFFAsmTargetStreamer::emitCode64() {
OS <<
"\t.code64\n"; }
109 unsigned ParamsSize,
SMLoc L) {
110 OS <<
"\t.cv_fpo_proc\t";
111 ProcSym->print(
OS, getContext().getAsmInfo());
112 OS <<
' ' << ParamsSize <<
'\n';
116bool X86WinCOFFAsmTargetStreamer::emitFPOEndPrologue(
SMLoc L) {
117 OS <<
"\t.cv_fpo_endprologue\n";
121bool X86WinCOFFAsmTargetStreamer::emitFPOEndProc(
SMLoc L) {
122 OS <<
"\t.cv_fpo_endproc\n";
128 OS <<
"\t.cv_fpo_data\t";
129 ProcSym->print(
OS, getStreamer().getContext().getAsmInfo());
134bool X86WinCOFFAsmTargetStreamer::emitFPOPushReg(
MCRegister Reg,
SMLoc L) {
135 OS <<
"\t.cv_fpo_pushreg\t";
136 InstPrinter.printRegName(
OS, Reg);
141bool X86WinCOFFAsmTargetStreamer::emitFPOStackAlloc(
unsigned StackAlloc,
143 OS <<
"\t.cv_fpo_stackalloc\t" << StackAlloc <<
'\n';
147bool X86WinCOFFAsmTargetStreamer::emitFPOStackAlign(
unsigned Align,
SMLoc L) {
148 OS <<
"\t.cv_fpo_stackalign\t" <<
Align <<
'\n';
152bool X86WinCOFFAsmTargetStreamer::emitFPOSetFrame(
MCRegister Reg,
SMLoc L) {
153 OS <<
"\t.cv_fpo_setframe\t";
154 InstPrinter.printRegName(
OS, Reg);
159bool X86WinCOFFTargetStreamer::checkInFPOPrologue(
SMLoc L) {
160 if (!haveOpenFPOData() || CurFPOData->PrologueEnd) {
161 getContext().reportError(
163 "directive must appear between .cv_fpo_proc and .cv_fpo_endprologue");
169MCSymbol *X86WinCOFFTargetStreamer::emitFPOLabel() {
170 MCSymbol *
Label = getContext().createTempSymbol(
"cfi",
true);
171 getStreamer().emitLabel(Label);
176 unsigned ParamsSize,
SMLoc L) {
177 if (haveOpenFPOData()) {
178 getContext().reportError(
179 L,
"opening new .cv_fpo_proc before closing previous frame");
182 CurFPOData = std::make_unique<FPOData>();
183 CurFPOData->Function =
ProcSym;
184 CurFPOData->Begin = emitFPOLabel();
185 CurFPOData->ParamsSize = ParamsSize;
189bool X86WinCOFFTargetStreamer::emitFPOEndProc(
SMLoc L) {
190 if (!haveOpenFPOData()) {
191 getContext().reportError(L,
".cv_fpo_endproc must appear after .cv_proc");
194 if (!CurFPOData->PrologueEnd) {
196 if (!CurFPOData->Instructions.empty()) {
197 getContext().reportError(L,
"missing .cv_fpo_endprologue");
198 CurFPOData->Instructions.clear();
203 CurFPOData->PrologueEnd = CurFPOData->Begin;
206 CurFPOData->End = emitFPOLabel();
207 const MCSymbol *Fn = CurFPOData->Function;
208 AllFPOData.insert({Fn, std::move(CurFPOData)});
212bool X86WinCOFFTargetStreamer::emitFPOSetFrame(
MCRegister Reg,
SMLoc L) {
213 if (checkInFPOPrologue(L))
216 Inst.Label = emitFPOLabel();
217 Inst.Op = FPOInstruction::SetFrame;
218 Inst.RegOrOffset =
Reg;
219 CurFPOData->Instructions.push_back(Inst);
223bool X86WinCOFFTargetStreamer::emitFPOPushReg(
MCRegister Reg,
SMLoc L) {
224 if (checkInFPOPrologue(L))
227 Inst.Label = emitFPOLabel();
228 Inst.Op = FPOInstruction::PushReg;
229 Inst.RegOrOffset =
Reg;
230 CurFPOData->Instructions.push_back(Inst);
234bool X86WinCOFFTargetStreamer::emitFPOStackAlloc(
unsigned StackAlloc,
SMLoc L) {
235 if (checkInFPOPrologue(L))
238 Inst.Label = emitFPOLabel();
239 Inst.Op = FPOInstruction::StackAlloc;
240 Inst.RegOrOffset = StackAlloc;
241 CurFPOData->Instructions.push_back(Inst);
245bool X86WinCOFFTargetStreamer::emitFPOStackAlign(
unsigned Align,
SMLoc L) {
246 if (checkInFPOPrologue(L))
248 if (
llvm::none_of(CurFPOData->Instructions, [](
const FPOInstruction &Inst) {
249 return Inst.Op == FPOInstruction::SetFrame;
251 getContext().reportError(
252 L,
"a frame register must be established before aligning the stack");
256 Inst.Label = emitFPOLabel();
257 Inst.Op = FPOInstruction::StackAlign;
258 Inst.RegOrOffset =
Align;
259 CurFPOData->Instructions.push_back(Inst);
263bool X86WinCOFFTargetStreamer::emitFPOEndPrologue(
SMLoc L) {
264 if (checkInFPOPrologue(L))
266 CurFPOData->PrologueEnd = emitFPOLabel();
271struct RegSaveOffset {
278struct FPOStateMachine {
279 explicit FPOStateMachine(
const FPOData *FPO) :
FPO(
FPO) {}
281 const FPOData *
FPO =
nullptr;
282 unsigned FrameReg = 0;
283 unsigned FrameRegOff = 0;
284 unsigned CurOffset = 0;
285 unsigned LocalSize = 0;
286 unsigned SavedRegSize = 0;
287 unsigned StackOffsetBeforeAlign = 0;
288 unsigned StackAlign = 0;
304 case X86::EAX:
OS <<
"$eax";
break;
305 case X86::EBX:
OS <<
"$ebx";
break;
306 case X86::ECX:
OS <<
"$ecx";
break;
307 case X86::EDX:
OS <<
"$edx";
break;
308 case X86::EDI:
OS <<
"$edi";
break;
309 case X86::ESI:
OS <<
"$esi";
break;
310 case X86::ESP:
OS <<
"$esp";
break;
311 case X86::EBP:
OS <<
"$ebp";
break;
312 case X86::EIP:
OS <<
"$eip";
break;
315 OS <<
'$' <<
MRI->getCodeViewRegNum(LLVMReg);
322 unsigned CurFlags =
Flags;
323 if (Label ==
FPO->Begin)
330 assert((StackAlign == 0 || FrameReg != 0) &&
331 "cannot align stack without frame reg");
332 StringRef CFAVar = StackAlign == 0 ?
"$T0" :
"$T1";
336 FuncOS << CFAVar <<
' ' <<
printFPOReg(
MRI, FrameReg) <<
' ' << FrameRegOff
344 FuncOS <<
"$T0 " << CFAVar <<
' ' << StackOffsetBeforeAlign <<
" - "
345 << StackAlign <<
" @ = ";
352 FuncOS << CFAVar <<
" .raSearch = ";
356 FuncOS <<
"$eip " << CFAVar <<
" ^ = ";
357 FuncOS <<
"$esp " << CFAVar <<
" 4 + = ";
360 for (RegSaveOffset RO : RegSaveOffsets)
361 FuncOS <<
printFPOReg(
MRI, RO.Reg) <<
' ' << CFAVar <<
' ' << RO.Offset
369 unsigned MaxStackSize = 0;
382 OS.emitAbsoluteSymbolDiff(Label,
FPO->Begin, 4);
383 OS.emitAbsoluteSymbolDiff(
FPO->End, Label, 4);
384 OS.emitInt32(LocalSize);
385 OS.emitInt32(
FPO->ParamsSize);
386 OS.emitInt32(MaxStackSize);
387 OS.emitInt32(FrameFuncStrTabOff);
388 OS.emitAbsoluteSymbolDiff(
FPO->PrologueEnd, Label, 2);
389 OS.emitInt16(SavedRegSize);
390 OS.emitInt32(CurFlags);
399 if (
I == AllFPOData.end()) {
404 const FPOData *
FPO =
I->second.get();
405 assert(
FPO->Begin &&
FPO->End &&
FPO->PrologueEnd &&
"missing FPO label");
410 OS.emitInt32(
unsigned(DebugSubsectionKind::FrameData));
411 OS.emitAbsoluteSymbolDiff(FrameEnd, FrameBegin, 4);
412 OS.emitLabel(FrameBegin);
420 FPOStateMachine FSM(FPO);
422 FSM.emitFrameDataRecord(
OS,
FPO->Begin);
423 for (
const FPOInstruction &Inst :
FPO->Instructions) {
425 case FPOInstruction::PushReg:
427 FSM.SavedRegSize += 4;
428 FSM.RegSaveOffsets.push_back({Inst.RegOrOffset, FSM.CurOffset});
430 case FPOInstruction::SetFrame:
431 FSM.FrameReg = Inst.RegOrOffset;
432 FSM.FrameRegOff = FSM.CurOffset;
434 case FPOInstruction::StackAlign:
435 FSM.StackOffsetBeforeAlign = FSM.CurOffset;
436 FSM.StackAlign = Inst.RegOrOffset;
438 case FPOInstruction::StackAlloc:
439 FSM.CurOffset += Inst.RegOrOffset;
440 FSM.LocalSize += Inst.RegOrOffset;
446 FSM.emitFrameDataRecord(
OS, Inst.Label);
449 OS.emitValueToAlignment(
Align(4), 0);
450 OS.emitLabel(FrameEnd);
459 return new X86WinCOFFAsmTargetStreamer(S,
OS, *InstPrinter);
468 return new X86WinCOFFTargetStreamer(S);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
PowerPC Reduce CR logical Operation
static Printable printFPOReg(const MCRegisterInfo *MRI, unsigned LLVMReg)
Holds state from .cv_file and .cv_loc directives for later emission.
std::pair< StringRef, unsigned > addToStringTable(StringRef S)
Add something to the string table.
This class represents an Operation in the Expression.
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
Streaming machine code generation interface.
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Target specific streamer interface.
Simple wrapper around std::function<void(raw_ostream&)>.
Represents a location in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
X86 target streamer implementing x86-only assembly directives.
virtual bool emitFPOPushReg(MCRegister Reg, SMLoc L={})
virtual bool emitFPOProc(const MCSymbol *ProcSym, unsigned ParamsSize, SMLoc L={})
virtual bool emitFPOEndPrologue(SMLoc L={})
virtual bool emitFPOData(const MCSymbol *ProcSym, SMLoc L={})
virtual void emitCode16()
virtual bool emitFPOEndProc(SMLoc L={})
virtual bool emitFPOStackAlign(unsigned Align, SMLoc L={})
virtual void emitCode32()
virtual bool emitFPOSetFrame(MCRegister Reg, SMLoc L={})
virtual bool emitFPOStackAlloc(unsigned StackAlloc, SMLoc L={})
virtual void emitCode64()
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an SmallVector or SmallString.
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
MCTargetStreamer * createX86ObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI)
Implements X86-only directives for object files.
MCTargetStreamer * createX86AsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrinter)
Implements X86-only directives for assembly emission.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
This struct is a compact representation of a valid (non-zero power of two) alignment.