36 #define DEBUG_TYPE "assembler"
40 STATISTIC(EmittedFragments,
"Number of emitted assembler fragments - total");
42 "Number of emitted assembler fragments - relaxable");
44 "Number of emitted assembler fragments - data");
45 STATISTIC(EmittedCompactEncodedInstFragments,
46 "Number of emitted assembler fragments - compact encoded inst");
48 "Number of emitted assembler fragments - align");
50 "Number of emitted assembler fragments - fill");
52 "Number of emitted assembler fragments - org");
53 STATISTIC(evaluateFixup,
"Number of evaluated fixups");
54 STATISTIC(FragmentLayouts,
"Number of fragment layouts");
55 STATISTIC(ObjectBytes,
"Number of emitted object file bytes");
56 STATISTIC(RelaxationSteps,
"Number of assembler layout and relaxation steps");
57 STATISTIC(RelaxedInstructions,
"Number of relaxed instructions");
70 : Context(Context), Backend(Backend), Emitter(Emitter), Writer(Writer),
73 VersionMinInfo.
Major = 0;
82 IndirectSymbols.clear();
84 LinkerOptions.clear();
89 SubsectionsViaSymbols =
false;
90 IncrementalLinkerCompatible =
false;
93 VersionMinInfo.
Major = 0;
105 Sections.push_back(&Section);
111 if (ThumbFuncs.count(Symbol))
131 ThumbFuncs.insert(Symbol);
169 bool MCAssembler::evaluateFixup(
const MCAsmLayout &Layout,
172 ++stats::evaluateFixup;
193 }
else if (!Target.
getSymA()) {
202 *
this, SA, *DF,
false,
true);
225 assert((ShouldAlignPC ? IsPCRel :
true) &&
226 "FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!");
233 if (ShouldAlignPC) Offset &= ~0x3;
249 return cast<MCDataFragment>(
F).getContents().size();
251 return cast<MCRelaxableFragment>(
F).getContents().size();
253 return cast<MCCompactEncodedInstFragment>(
F).getContents().size();
255 return cast<MCFillFragment>(
F).getSize();
258 return cast<MCLEBFragment>(
F).getContents().size();
283 "expected assembly-time absolute expression");
288 int64_t TargetLocation = Value.getConstant();
295 TargetLocation += Val;
297 int64_t Size = TargetLocation - FragmentOffset;
298 if (Size < 0 || Size >= 0x40000000) {
300 OF.
getLoc(),
"invalid .org offset '" +
Twine(TargetLocation) +
301 "' (at offset '" +
Twine(FragmentOffset) +
"')");
308 return cast<MCDwarfLineAddrFragment>(
F).getContents().size();
310 return cast<MCDwarfCallFrameFragment>(
F).getContents().size();
312 return cast<MCCVInlineLineTableFragment>(
F).getContents().size();
314 return cast<MCCVDefRangeFragment>(
F).getContents().size();
326 assert(!isFragmentValid(F) &&
"Attempt to recompute a valid fragment!");
329 assert((!Prev || isFragmentValid(Prev)) &&
330 "Attempt to compute fragment before its predecessor!");
332 ++stats::FragmentLayouts;
369 assert(isa<MCEncodedFragment>(F) &&
370 "Only MCEncodedFragment implementations have instructions");
378 if (RequiredBundlePadding > UINT8_MAX)
381 F->Offset += RequiredBundlePadding;
391 Symbols.push_back(&Symbol);
399 if (BundlePadding > 0) {
401 "Writing bundle padding with disabled bundling");
403 "Writing bundle padding for a fragment without instructions");
405 unsigned TotalLength = BundlePadding +
static_cast<unsigned>(FSize);
416 if (!
getBackend().writeNopData(DistanceToBoundary, OW))
418 Twine(DistanceToBoundary) +
" bytes");
419 BundlePadding -= DistanceToBoundary;
421 if (!
getBackend().writeNopData(BundlePadding, OW))
423 Twine(BundlePadding) +
" bytes");
442 ++stats::EmittedFragments;
446 ++stats::EmittedAlignFragments;
458 "' is not a divisor of padding size '" +
459 Twine(FragmentSize) +
"'");
468 Twine(Count) +
" bytes");
473 for (uint64_t
i = 0;
i != Count; ++
i) {
486 ++stats::EmittedDataFragments;
487 OW->
writeBytes(cast<MCDataFragment>(F).getContents());
491 ++stats::EmittedRelaxableFragments;
492 OW->
writeBytes(cast<MCRelaxableFragment>(F).getContents());
496 ++stats::EmittedCompactEncodedInstFragments;
497 OW->
writeBytes(cast<MCCompactEncodedInstFragment>(F).getContents());
501 ++stats::EmittedFillFragments;
504 const unsigned MaxChunkSize = 16;
505 char Data[MaxChunkSize];
507 for (
unsigned I = 1;
I < MaxChunkSize; ++
I)
511 for (
unsigned ChunkSize = MaxChunkSize; ChunkSize; ChunkSize /= 2) {
513 for (uint64_t
I = 0,
E = Size / ChunkSize;
I !=
E; ++
I)
515 Size = Size % ChunkSize;
533 ++stats::EmittedOrgFragments;
536 for (uint64_t
i = 0, e = FragmentSize;
i != e; ++
i)
553 const auto &OF = cast<MCCVInlineLineTableFragment>(
F);
558 const auto &DRF = cast<MCCVDefRangeFragment>(
F);
567 "The stream should advance by fragment size");
578 switch (
F.getKind()) {
589 if (
auto *ELFSec = dyn_cast<const MCSectionELF>(Sec))
591 ELFSec->getSectionName() +
"'");
600 assert((cast<MCAlignFragment>(
F).getValueSize() == 0 ||
601 cast<MCAlignFragment>(
F).getValue() == 0) &&
602 "Invalid align in virtual section!");
605 assert((cast<MCFillFragment>(
F).getValue() == 0) &&
606 "Invalid fill in virtual section!");
624 std::pair<uint64_t, bool> MCAssembler::handleFixup(
const MCAsmLayout &Layout,
632 if (!evaluateFixup(Layout, Fixup, &F, Target, FixedValue)) {
639 return std::make_pair(FixedValue, IsPCRel);
644 llvm::errs() <<
"assembler backend - pre-layout\n--\n";
648 unsigned SectionIndex = 0;
663 unsigned FragmentIndex = 0;
665 Frag.setLayoutOrder(FragmentIndex++);
669 while (layoutOnce(Layout))
674 llvm::errs() <<
"assembler backend - post-relaxation\n--\n";
678 finishLayout(Layout);
681 llvm::errs() <<
"assembler backend - final-layout\n--\n";
695 if (isa<MCEncodedFragment>(&Frag) &&
696 isa<MCCompactEncodedInstFragment>(&Frag))
698 if (!isa<MCEncodedFragment>(&Frag) && !isa<MCCVDefRangeFragment>(&Frag))
702 if (
auto *FragWithFixups = dyn_cast<MCDataFragment>(&Frag)) {
703 Fixups = FragWithFixups->getFixups();
704 Contents = FragWithFixups->getContents();
705 }
else if (
auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(&Frag)) {
706 Fixups = FragWithFixups->getFixups();
707 Contents = FragWithFixups->getContents();
708 }
else if (
auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) {
709 Fixups = FragWithFixups->getFixups();
710 Contents = FragWithFixups->getContents();
713 for (
const MCFixup &Fixup : Fixups) {
716 std::tie(FixedValue, IsPCRel) = handleFixup(Layout, Frag, Fixup);
718 Contents.
size(), FixedValue, IsPCRel);
730 uint64_t StartOffset = OS.
tell();
735 stats::ObjectBytes += OS.
tell() - StartOffset;
738 bool MCAssembler::fixupNeedsRelaxation(
const MCFixup &Fixup,
743 bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value);
757 if (fixupNeedsRelaxation(Fixup, F, Layout))
763 bool MCAssembler::relaxInstruction(
MCAsmLayout &Layout,
765 if (!fragmentNeedsRelaxation(&F, Layout))
768 ++stats::RelaxedInstructions;
811 bool MCAssembler::relaxDwarfLineAddr(
MCAsmLayout &Layout,
817 assert(Abs &&
"We created a line delta with an invalid expression");
826 return OldSize != Data.
size();
829 bool MCAssembler::relaxDwarfCallFrameFragment(
MCAsmLayout &Layout,
835 assert(Abs &&
"We created call frame with an invalid expression");
841 return OldSize != Data.
size();
844 bool MCAssembler::relaxCVInlineLineTable(
MCAsmLayout &Layout,
851 bool MCAssembler::relaxCVDefRange(
MCAsmLayout &Layout,
868 bool RelaxedFrag =
false;
869 switch(
I->getKind()) {
874 "Did not expect a MCRelaxableFragment in RelaxAll mode");
875 RelaxedFrag = relaxInstruction(Layout, *cast<MCRelaxableFragment>(
I));
878 RelaxedFrag = relaxDwarfLineAddr(Layout,
879 *cast<MCDwarfLineAddrFragment>(
I));
883 relaxDwarfCallFrameFragment(Layout,
884 *cast<MCDwarfCallFrameFragment>(
I));
887 RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(
I));
891 relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(
I));
894 RelaxedFrag = relaxCVDefRange(Layout, *cast<MCCVDefRangeFragment>(
I));
897 if (RelaxedFrag && !FirstRelaxedFragment)
898 FirstRelaxedFragment = &*
I;
900 if (FirstRelaxedFragment) {
907 bool MCAssembler::layoutOnce(
MCAsmLayout &Layout) {
908 ++stats::RelaxationSteps;
910 bool WasRelaxed =
false;
913 while (layoutSectionOnce(Layout, Sec))
920 void MCAssembler::finishLayout(
MCAsmLayout &Layout) {
bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const
uint8_t getBundlePadding() const
Get the padding size that must be inserted before this fragment.
Instances of this class represent a uniqued identifier for a section in the current translation unit...
virtual void finishLayout(MCAssembler const &Asm, MCAsmLayout &Layout) const
Give backend an opportunity to finish layout after relaxation.
const MCAsmInfo * getAsmInfo() const
void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F)
unsigned getValueSize() const
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
const MCSymbol & getSymbol() const
STATISTIC(NumFunctions,"Total number of functions")
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
raw_pwrite_stream & getStream()
void write64(uint64_t Value)
This represents an "assembler immediate".
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
virtual void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, MCInst &Res) const =0
Relax the instruction in the given fragment to the next wider instruction.
unsigned getAlignment() const
SmallString< 8 > & getContents()
const MCExpr & getAddrDelta() const
bool isRegistered() const
void setLayoutOrder(unsigned Value)
unsigned getBundleAlignSize() const
virtual bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const
Target specific predicate for whether a given fixup requires the associated instruction to be relaxed...
bool alignToBundleEnd() const
Should this fragment be placed at the end of an aligned bundle?
void writeFragmentPadding(const MCFragment &F, uint64_t FSize, MCObjectWriter *OW) const
Write the necessary bundle padding to the given object writer.
virtual void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout)=0
Perform any late binding of symbols (for example, to assign symbol indices for use when generating re...
bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const
Get the offset of the given symbol, as computed in the current layout.
MCCodeEmitter & getEmitter() const
virtual void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout)=0
Write the object file.
A raw_ostream that writes to an SmallVector or SmallString.
void registerSymbol(const MCSymbol &Symbol, bool *Created=nullptr)
virtual bool isSectionAtomizableBySymbols(const MCSection &Section) const
True if the section is atomized using the symbols in it.
const MCSubtargetInfo & getSubtargetInfo()
MCContext & getContext() const
Defines the object file and target independent interfaces used by the assembler backend to write nati...
void write8(uint8_t Value)
static void Encode(MCContext &Context, MCDwarfLineTableParams Params, int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS)
Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
const MCExpr & getOffset() const
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
const MCInst & getInst() const
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
virtual unsigned getMinimumNopSize() const
Returns the minimum size of a nop in bytes on this target.
fixup_iterator fixup_end()
struct fuzzer::@269 Flags
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Encapsulates the layout of an assembly file at a particular point in time.
virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
EncodeInstruction - Encode the given Inst to bytes on the output stream OS.
Base class for the full range of assembler expressions which are needed for parsing.
bool registerSection(MCSection &Section)
unsigned getMaxBytesToEmit() const
Represent a reference to a symbol from inside an expression.
int64_t getLineDelta() const
uint64_t tell() const
tell - Return the current offset with the file.
Context object for machine code objects.
MCObjectWriter & getWriter() const
bool isAbsolute() const
Is this an absolute (as opposed to relocatable) value.
Function Alias Analysis false
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value, bool IsPCRel) const =0
Apply the Value for given Fixup into the provided data fragment, at the offset specified by the fixup...
reverse_iterator rbegin()
const MCSymbol * getSymbol()
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
bool isThumbFunc(const MCSymbol *Func) const
Check whether a given symbol has been flagged with .thumb_func.
const MCSymbol * getAtom(const MCSymbol &S) const
Find the symbol which defines the atom containing the given symbol, or null if there is no such symbo...
void layoutFragment(MCFragment *Fragment)
Perform layout for a single fragment, assuming that the previous fragment has already been laid out c...
SmallVectorImpl< char > & getContents()
uint32_t getOffset() const
const MCExpr & getAddrDelta() const
size_t size() const
size - Get the array size.
Instances of this class represent a single low-level machine instruction.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
virtual bool writeNopData(uint64_t Count, MCObjectWriter *OW) const =0
Write an (optimal) nop sequence of Count bytes to the given output.
void encodeInlineLineTable(MCAsmLayout &Layout, MCCVInlineLineTableFragment &F)
Encodes the binary annotations once we have a layout.
A relaxable fragment holds on to its MCInst, since it may need to be relaxed during the assembler lay...
void write32(uint32_t Value)
bool hasInstructions() const
Does this fragment have instructions emitted into it? By default this is false, but specific fragment...
const MCExpr * getValue() const
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
virtual void reset()
Lifetime management.
MCDwarfLineTableParams getDWARFLinetableParams() const
void writeSectionData(const MCSection *Section, const MCAsmLayout &Layout) const
Emit the section contents using the given object writer.
virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B, bool InSet) const
uint64_t computeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const
Compute the effective fragment size assuming it is laid out at the given SectionAddress and FragmentO...
uint32_t getIndex() const
Get the (implementation defined) index.
FragmentType getKind() const
void invalidateFragmentsFrom(MCFragment *F)
Invalidate the fragments starting with F because it has been resized.
MCCodeEmitter - Generic instruction encoding interface.
virtual void reset()
lifetime management
bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const
Try to evaluate the expression to the form (a - b + constant) where neither a nor b are variables...
virtual void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, const MCValue &Target, uint64_t &Value, bool &IsResolved)
Target hook to adjust the literal value of a fixup if necessary.
SmallVectorImpl< MCFixup > & getFixups()
uint64_t getSectionAddressSize(const MCSection *Sec) const
Get the address space size of the given section, as it effects layout.
void reportError(SMLoc L, const Twine &Msg)
Should this fixup kind force a 4-byte aligned effective PC value?
llvm::SmallVectorImpl< MCSection * > & getSectionOrder()
void setIsRegistered(bool Value)
bool isRegistered() const
bool isInSection(bool SetUsed=true) const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute)...
MCFixupKind getKind() const
const MCSymbolRefExpr * getSymB() const
Fragment representing the .cv_def_range directive.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void layout(MCAsmLayout &Layout)
void write16(uint16_t Value)
bool isSymbolLinkerVisible(const MCSymbol &SD) const
Check whether a particular symbol is visible to the linker and is required in the symbol table...
void setOrdinal(unsigned Value)
uint64_t computeBundlePadding(const MCAssembler &Assembler, const MCFragment *F, uint64_t FOffset, uint64_t FSize)
Compute the amount of padding required before the fragment F to obey bundling restrictions, where FOffset is the fragment's offset in its section and FSize is the fragment's size.
cl::opt< bool > IncrementalLinkerCompatible("incremental-linker-compatible", cl::desc("When used with filetype=obj, ""emit an object file which can be used with an incremental linker"))
Iterator for intrusive lists based on ilist_node.
const MCSymbolRefExpr * getSymA() const
bool isUsedInReloc() const
virtual bool isVirtualSection() const =0
Check whether this section is "virtual", that is has no actual object file contents.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool isBundlingEnabled() const
static const char * Target
static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment &F)
Write the fragment F to the output file.
static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, raw_ostream &OS)
MCLOHContainer & getLOHContainer()
MCSection * getParent() const
bool isDefined(bool SetUsed=true) const
isDefined - Check if this symbol is defined (i.e., it has an address).
void encodeSLEB128(int64_t Value, raw_ostream &OS)
Utility function to encode a SLEB128 value to an output stream.
bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Target - Wrapper for Target specific information.
void setIsRegistered(bool Value) const
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
SmallString< 8 > & getContents()
virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue)=0
Record a relocation entry.
Fragment representing the binary annotations produced by the .cv_inline_linetable directive...
void setBundlePadding(uint8_t N)
Set the padding size for this fragment.
const MCSymbol * getAtom() const
MCAsmBackend & getBackend() const
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
fixup_iterator fixup_begin()
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
SmallString< 8 > & getContents()
void writeBytes(const SmallVectorImpl< char > &ByteVec, unsigned ZeroFillSize=0)
bool isVariable() const
isVariable - Check if this is a variable symbol.
MCFragment * getFragment(bool SetUsed=true) const
CodeViewContext & getCVContext()
void reset()
Reuse an assembler instance.
Fragment for data and encoded instructions.
VariantKind getKind() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
int64_t getConstant() const
cl::opt< bool > RelaxAll("mc-relax-all", cl::desc("When used with filetype=obj, ""relax all fixups in the emitted object file"))
LLVM Value Representation.
Generic interface to target specific assembler backends.
MCAssembler & getAssembler() const
Get the assembler object this is a layout for.
uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
This class implements an extremely fast bulk output stream that can only output to a stream...
const MCExpr & getValue() const
void encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned Padding=0)
Utility function to encode a ULEB128 value to an output stream.
uint64_t getSectionFileSize(const MCSection *Sec) const
Get the data size of the given section, as emitted to the object file.
StringRef - Represent a constant reference to a string, i.e.
SmallString< 8 > & getContents()
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
pointee_iterator< SectionListType::iterator > iterator
virtual void reset()
lifetime management
void Finish()
Finish - Do final processing and write the object to the output stream.
MCSection::FragmentListType & getFragmentList()
void setInst(const MCInst &Value)
bool isUndefined(bool SetUsed=true) const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).