26 formatted_raw_ostream &OS;
27 MCInstPrinter &InstPrinter;
30 X86WinCOFFAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
31 MCInstPrinter &InstPrinter)
32 : X86TargetStreamer(S), OS(OS), InstPrinter(InstPrinter) {}
34 void emitCode16()
override;
35 void emitCode32()
override;
36 void emitCode64()
override;
38 bool emitFPOProc(
const MCSymbol *ProcSym,
unsigned ParamsSize,
40 bool emitFPOEndPrologue(SMLoc L)
override;
41 bool emitFPOEndProc(SMLoc L)
override;
42 bool emitFPOData(
const MCSymbol *ProcSym, SMLoc L)
override;
43 bool emitFPOPushReg(MCRegister
Reg, SMLoc L)
override;
44 bool emitFPOStackAlloc(
unsigned StackAlloc, SMLoc L)
override;
45 bool emitFPOStackAlign(
unsigned Align, SMLoc L)
override;
46 bool emitFPOSetFrame(MCRegister
Reg, SMLoc L)
override;
50struct FPOInstruction {
67 unsigned ParamsSize = 0;
75 DenseMap<const MCSymbol *, std::unique_ptr<FPOData>> AllFPOData;
78 std::unique_ptr<FPOData> CurFPOData;
80 bool haveOpenFPOData() {
return !!CurFPOData; }
84 bool checkInFPOPrologue(SMLoc L);
89 X86WinCOFFTargetStreamer(MCStreamer &S) : X86TargetStreamer(S) {}
91 bool emitFPOProc(
const MCSymbol *ProcSym,
unsigned ParamsSize,
93 bool emitFPOEndPrologue(SMLoc L)
override;
94 bool emitFPOEndProc(SMLoc L)
override;
95 bool emitFPOData(
const MCSymbol *ProcSym, SMLoc L)
override;
96 bool emitFPOPushReg(MCRegister
Reg, SMLoc L)
override;
97 bool emitFPOStackAlloc(
unsigned StackAlloc, SMLoc L)
override;
98 bool emitFPOStackAlign(
unsigned Align, SMLoc L)
override;
99 bool emitFPOSetFrame(MCRegister
Reg, SMLoc L)
override;
103void X86WinCOFFAsmTargetStreamer::emitCode16() { OS <<
"\t.code16\n"; }
105void X86WinCOFFAsmTargetStreamer::emitCode32() { OS <<
"\t.code32\n"; }
107void X86WinCOFFAsmTargetStreamer::emitCode64() { OS <<
"\t.code64\n"; }
109bool X86WinCOFFAsmTargetStreamer::emitFPOProc(
const MCSymbol *ProcSym,
110 unsigned ParamsSize, SMLoc L) {
111 OS <<
"\t.cv_fpo_proc\t";
113 OS <<
' ' << ParamsSize <<
'\n';
117bool X86WinCOFFAsmTargetStreamer::emitFPOEndPrologue(SMLoc L) {
118 OS <<
"\t.cv_fpo_endprologue\n";
122bool X86WinCOFFAsmTargetStreamer::emitFPOEndProc(SMLoc L) {
123 OS <<
"\t.cv_fpo_endproc\n";
127bool X86WinCOFFAsmTargetStreamer::emitFPOData(
const MCSymbol *ProcSym,
129 OS <<
"\t.cv_fpo_data\t";
135bool X86WinCOFFAsmTargetStreamer::emitFPOPushReg(MCRegister
Reg, SMLoc L) {
136 OS <<
"\t.cv_fpo_pushreg\t";
142bool X86WinCOFFAsmTargetStreamer::emitFPOStackAlloc(
unsigned StackAlloc,
144 OS <<
"\t.cv_fpo_stackalloc\t" << StackAlloc <<
'\n';
148bool X86WinCOFFAsmTargetStreamer::emitFPOStackAlign(
unsigned Align, SMLoc L) {
149 OS <<
"\t.cv_fpo_stackalign\t" <<
Align <<
'\n';
153bool X86WinCOFFAsmTargetStreamer::emitFPOSetFrame(MCRegister
Reg, SMLoc L) {
154 OS <<
"\t.cv_fpo_setframe\t";
160bool X86WinCOFFTargetStreamer::checkInFPOPrologue(SMLoc L) {
161 if (!haveOpenFPOData() || CurFPOData->PrologueEnd) {
164 "directive must appear between .cv_fpo_proc and .cv_fpo_endprologue");
170MCSymbol *X86WinCOFFTargetStreamer::emitFPOLabel() {
172 getStreamer().emitLabel(Label);
176bool X86WinCOFFTargetStreamer::emitFPOProc(
const MCSymbol *ProcSym,
177 unsigned ParamsSize, SMLoc L) {
178 if (haveOpenFPOData()) {
180 L,
"opening new .cv_fpo_proc before closing previous frame");
183 CurFPOData = std::make_unique<FPOData>();
184 CurFPOData->Function = ProcSym;
185 CurFPOData->Begin = emitFPOLabel();
186 CurFPOData->ParamsSize = ParamsSize;
190bool X86WinCOFFTargetStreamer::emitFPOEndProc(SMLoc L) {
191 if (!haveOpenFPOData()) {
192 getContext().reportError(L,
".cv_fpo_endproc must appear after .cv_proc");
195 if (!CurFPOData->PrologueEnd) {
197 if (!CurFPOData->Instructions.empty()) {
198 getContext().reportError(L,
"missing .cv_fpo_endprologue");
199 CurFPOData->Instructions.clear();
204 CurFPOData->PrologueEnd = CurFPOData->Begin;
207 CurFPOData->End = emitFPOLabel();
208 const MCSymbol *Fn = CurFPOData->Function;
209 AllFPOData.insert({Fn, std::move(CurFPOData)});
213bool X86WinCOFFTargetStreamer::emitFPOSetFrame(MCRegister
Reg, SMLoc L) {
214 if (checkInFPOPrologue(L))
217 Inst.Label = emitFPOLabel();
218 Inst.Op = FPOInstruction::SetFrame;
219 Inst.RegOrOffset =
Reg.
id();
220 CurFPOData->Instructions.push_back(Inst);
224bool X86WinCOFFTargetStreamer::emitFPOPushReg(MCRegister
Reg, SMLoc L) {
225 if (checkInFPOPrologue(L))
228 Inst.Label = emitFPOLabel();
229 Inst.Op = FPOInstruction::PushReg;
230 Inst.RegOrOffset =
Reg.
id();
231 CurFPOData->Instructions.push_back(Inst);
235bool X86WinCOFFTargetStreamer::emitFPOStackAlloc(
unsigned StackAlloc, SMLoc L) {
236 if (checkInFPOPrologue(L))
239 Inst.Label = emitFPOLabel();
240 Inst.Op = FPOInstruction::StackAlloc;
241 Inst.RegOrOffset = StackAlloc;
242 CurFPOData->Instructions.push_back(Inst);
246bool X86WinCOFFTargetStreamer::emitFPOStackAlign(
unsigned Align, SMLoc L) {
247 if (checkInFPOPrologue(L))
249 if (
llvm::none_of(CurFPOData->Instructions, [](
const FPOInstruction &Inst) {
250 return Inst.Op == FPOInstruction::SetFrame;
253 L,
"a frame register must be established before aligning the stack");
257 Inst.Label = emitFPOLabel();
258 Inst.Op = FPOInstruction::StackAlign;
259 Inst.RegOrOffset =
Align;
260 CurFPOData->Instructions.push_back(Inst);
264bool X86WinCOFFTargetStreamer::emitFPOEndPrologue(SMLoc L) {
265 if (checkInFPOPrologue(L))
267 CurFPOData->PrologueEnd = emitFPOLabel();
272struct RegSaveOffset {
279struct FPOStateMachine {
280 explicit FPOStateMachine(
const FPOData *FPO) :
FPO(
FPO) {}
282 const FPOData *FPO =
nullptr;
283 unsigned FrameReg = 0;
284 unsigned FrameRegOff = 0;
285 unsigned CurOffset = 0;
286 unsigned LocalSize = 0;
287 unsigned SavedRegSize = 0;
288 unsigned StackOffsetBeforeAlign = 0;
289 unsigned StackAlign = 0;
292 SmallString<128> FrameFunc;
296 void emitFrameDataRecord(MCStreamer &OS, MCSymbol *Label);
305 case X86::EAX: OS <<
"$eax";
break;
306 case X86::EBX: OS <<
"$ebx";
break;
307 case X86::ECX: OS <<
"$ecx";
break;
308 case X86::EDX: OS <<
"$edx";
break;
309 case X86::EDI: OS <<
"$edi";
break;
310 case X86::ESI: OS <<
"$esi";
break;
311 case X86::ESP: OS <<
"$esp";
break;
312 case X86::EBP: OS <<
"$ebp";
break;
313 case X86::EIP: OS <<
"$eip";
break;
316 OS <<
'$' <<
MRI->getCodeViewRegNum(LLVMReg);
322void FPOStateMachine::emitFrameDataRecord(MCStreamer &OS, MCSymbol *Label) {
323 unsigned CurFlags = Flags;
324 if (Label == FPO->Begin)
329 raw_svector_ostream FuncOS(FrameFunc);
331 assert((StackAlign == 0 || FrameReg != 0) &&
332 "cannot align stack without frame reg");
333 StringRef CFAVar = StackAlign == 0 ?
"$T0" :
"$T1";
337 FuncOS << CFAVar <<
' ' <<
printFPOReg(
MRI, FrameReg) <<
' ' << FrameRegOff
345 FuncOS <<
"$T0 " << CFAVar <<
' ' << StackOffsetBeforeAlign <<
" - "
346 << StackAlign <<
" @ = ";
353 FuncOS << CFAVar <<
" .raSearch = ";
357 FuncOS <<
"$eip " << CFAVar <<
" ^ = ";
358 FuncOS <<
"$esp " << CFAVar <<
" 4 + = ";
361 for (RegSaveOffset RO : RegSaveOffsets)
362 FuncOS <<
printFPOReg(
MRI, RO.Reg) <<
' ' << CFAVar <<
' ' << RO.Offset
370 unsigned MaxStackSize = 0;
395bool X86WinCOFFTargetStreamer::emitFPOData(
const MCSymbol *ProcSym, SMLoc L) {
396 MCStreamer &OS = getStreamer();
399 auto I = AllFPOData.find(ProcSym);
400 if (
I == AllFPOData.end()) {
401 Ctx.
reportError(L, Twine(
"no FPO data found for symbol ") +
405 const FPOData *
FPO =
I->second.get();
406 assert(
FPO->Begin &&
FPO->End &&
FPO->PrologueEnd &&
"missing FPO label");
411 OS.
emitInt32(
unsigned(DebugSubsectionKind::FrameData));
421 FPOStateMachine FSM(FPO);
423 FSM.emitFrameDataRecord(OS,
FPO->Begin);
424 for (
const FPOInstruction &Inst :
FPO->Instructions) {
426 case FPOInstruction::PushReg:
428 FSM.SavedRegSize += 4;
429 FSM.RegSaveOffsets.push_back({Inst.RegOrOffset, FSM.CurOffset});
431 case FPOInstruction::SetFrame:
432 FSM.FrameReg = Inst.RegOrOffset;
433 FSM.FrameRegOff = FSM.CurOffset;
435 case FPOInstruction::StackAlign:
436 FSM.StackOffsetBeforeAlign = FSM.CurOffset;
437 FSM.StackAlign = Inst.RegOrOffset;
439 case FPOInstruction::StackAlloc:
440 FSM.CurOffset += Inst.RegOrOffset;
441 FSM.LocalSize += Inst.RegOrOffset;
447 FSM.emitFrameDataRecord(OS, Inst.Label);
460 return new X86WinCOFFAsmTargetStreamer(S, OS, *InstPrinter);
469 return new X86WinCOFFTargetStreamer(S);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Printable printFPOReg(const MCRegisterInfo *MRI, unsigned LLVMReg)
std::pair< StringRef, unsigned > addToStringTable(StringRef S)
Add something to the string table.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI CodeViewContext & getCVContext()
const MCRegisterInfo * getRegisterInfo() const
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...
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
Print the assembler register name.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Streaming machine code generation interface.
MCContext & getContext() const
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size)
Emit the absolute difference between two symbols.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
void emitInt16(uint64_t Value)
void emitInt32(uint64_t Value)
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getName() const
getName - Get the symbol name.
Target specific streamer interface.
Simple wrapper around std::function<void(raw_ostream&)>.
constexpr unsigned id() const
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
X86 target streamer implementing x86-only assembly directives.
This class implements an extremely fast bulk output stream that can only output to a stream.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
Context & getContext() const
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...