diff options
author | Jian Cai <caij2003@gmail.com> | 2020-07-30 18:33:33 -0700 |
---|---|---|
committer | Jian Cai <caij2003@gmail.com> | 2020-08-03 11:50:56 -0700 |
commit | c6334db577e7049fe4868b1647c9f937f68ff1f5 (patch) | |
tree | 27ddbe50dde4cb63e052b32f419daba1096027f6 /llvm/lib/MC/MCAssembler.cpp | |
parent | 1e392fc44584a4909b4dced02b8386b48963002b (diff) | |
download | llvm-c6334db577e7049fe4868b1647c9f937f68ff1f5.zip llvm-c6334db577e7049fe4868b1647c9f937f68ff1f5.tar.gz llvm-c6334db577e7049fe4868b1647c9f937f68ff1f5.tar.bz2 |
[X86] support .nops directive
Add support of .nops on X86. This addresses llvm.org/PR45788.
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D82826
Diffstat (limited to 'llvm/lib/MC/MCAssembler.cpp')
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 3ca8714..9515b7e 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -62,8 +62,8 @@ STATISTIC(EmittedAlignFragments, "Number of emitted assembler fragments - align"); STATISTIC(EmittedFillFragments, "Number of emitted assembler fragments - fill"); -STATISTIC(EmittedOrgFragments, - "Number of emitted assembler fragments - org"); +STATISTIC(EmittedNopsFragments, "Number of emitted assembler fragments - nops"); +STATISTIC(EmittedOrgFragments, "Number of emitted assembler fragments - org"); STATISTIC(evaluateFixup, "Number of evaluated fixups"); STATISTIC(FragmentLayouts, "Number of fragment layouts"); STATISTIC(ObjectBytes, "Number of emitted object file bytes"); @@ -312,6 +312,9 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, return Size; } + case MCFragment::FT_Nops: + return cast<MCNopsFragment>(F).getNumBytes(); + case MCFragment::FT_LEB: return cast<MCLEBFragment>(F).getContents().size(); @@ -613,6 +616,45 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, break; } + case MCFragment::FT_Nops: { + ++stats::EmittedNopsFragments; + const MCNopsFragment &NF = cast<MCNopsFragment>(F); + int64_t NumBytes = NF.getNumBytes(); + int64_t ControlledNopLength = NF.getControlledNopLength(); + int64_t MaximumNopLength = Asm.getBackend().getMaximumNopSize(); + + assert(NumBytes > 0 && "Expected positive NOPs fragment size"); + assert(ControlledNopLength >= 0 && "Expected non-negative NOP size"); + + if (ControlledNopLength > MaximumNopLength) { + Asm.getContext().reportError(NF.getLoc(), + "illegal NOP size " + + std::to_string(ControlledNopLength) + + ". (expected within [0, " + + std::to_string(MaximumNopLength) + "])"); + // Clamp the NOP length as reportError does not stop the execution + // immediately. + ControlledNopLength = MaximumNopLength; + } + + // Use maximum value if the size of each NOP is not specified + if (!ControlledNopLength) + ControlledNopLength = MaximumNopLength; + + while (NumBytes) { + uint64_t NumBytesToEmit = + (uint64_t)std::min(NumBytes, ControlledNopLength); + assert(NumBytesToEmit && "try to emit empty NOP instruction"); + if (!Asm.getBackend().writeNopData(OS, NumBytesToEmit)) { + report_fatal_error("unable to write nop sequence of the remaining " + + Twine(NumBytesToEmit) + " bytes"); + break; + } + NumBytes -= NumBytesToEmit; + } + break; + } + case MCFragment::FT_LEB: { const MCLEBFragment &LF = cast<MCLEBFragment>(F); OS << LF.getContents(); |