aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
authorJian Cai <caij2003@gmail.com>2020-07-30 18:33:33 -0700
committerJian Cai <caij2003@gmail.com>2020-08-03 11:50:56 -0700
commitc6334db577e7049fe4868b1647c9f937f68ff1f5 (patch)
tree27ddbe50dde4cb63e052b32f419daba1096027f6 /llvm/lib/MC/MCAssembler.cpp
parent1e392fc44584a4909b4dced02b8386b48963002b (diff)
downloadllvm-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.cpp46
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();