aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
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();