46#define DEBUG_TYPE "assembler"
51STATISTIC(EmittedFragments,
"Number of emitted assembler fragments - total");
53 "Number of emitted assembler fragments - relaxable");
55 "Number of emitted assembler fragments - data");
57 "Number of emitted assembler fragments - align");
59 "Number of emitted assembler fragments - fill");
60STATISTIC(EmittedNopsFragments,
"Number of emitted assembler fragments - nops");
61STATISTIC(EmittedOrgFragments,
"Number of emitted assembler fragments - org");
63STATISTIC(FixupEvalForRelax,
"Number of fixup evaluations for relaxation");
64STATISTIC(ObjectBytes,
"Number of emitted object file bytes");
65STATISTIC(RelaxationSteps,
"Number of assembler layout and relaxation steps");
66STATISTIC(RelaxedInstructions,
"Number of relaxed instructions");
79 std::unique_ptr<MCAsmBackend> Backend,
80 std::unique_ptr<MCCodeEmitter>
Emitter,
81 std::unique_ptr<MCObjectWriter> Writer)
85 this->Backend->setAssembler(
this);
87 this->Writer->setAssembler(
this);
92 HasFinalLayout =
false;
108 if (Section.isRegistered())
111 Section.setIsRegistered(
true);
116 if (ThumbFuncs.count(Symbol))
119 if (!Symbol->isVariable())
122 const MCExpr *Expr = Symbol->getVariableValue();
128 if (V.getSubSym() || V.getSpecifier())
131 auto *
Sym = V.getAddSym();
132 if (!
Sym || V.getSpecifier())
138 ThumbFuncs.insert(Symbol);
161 bool IsResolved =
false;
168 if (
Add &&
Add->isDefined())
170 if (
Sub &&
Sub->isDefined())
173 if (
Fixup.isPCRel()) {
175 if (
Add && !
Sub && !
Add->isUndefined() && !
Add->isAbsolute()) {
177 *
Add,
F,
false,
true);
180 IsResolved =
Target.isAbsolute();
195 switch (
F.getKind()) {
207 int64_t NumValues = 0;
208 if (!FF.getNumValues().evaluateKnownAbsolute(NumValues, *
this)) {
209 recordError(FF.getLoc(),
"expected assembly-time absolute expression");
212 int64_t
Size = NumValues * FF.getValueSize();
214 recordError(FF.getLoc(),
"invalid number of bytes");
221 return cast<MCNopsFragment>(
F).getNumBytes();
224 return cast<MCBoundaryAlignFragment>(
F).getSize();
232 if (!OF.getOffset().evaluateAsValue(
Value, *
this)) {
233 recordError(OF.getLoc(),
"expected assembly-time absolute expression");
238 int64_t TargetLocation =
Value.getConstant();
239 if (
const auto *SA =
Value.getAddSym()) {
242 recordError(OF.getLoc(),
"expected absolute expression");
245 TargetLocation += Val;
247 int64_t
Size = TargetLocation - FragmentOffset;
248 if (Size < 0 || Size >= 0x40000000) {
250 "' (at offset '" +
Twine(FragmentOffset) +
323 if (!Symbol.isVariable())
326 const MCExpr *Expr = Symbol.getVariableValue();
337 "' could not be evaluated in a subtraction expression");
348 "' cannot be used in assignment expr");
369 bool Changed = !Symbol.isRegistered();
371 Symbol.setIsRegistered(
true);
372 Symbols.push_back(&Symbol);
385 uint64_t FragmentSize = Asm.computeFragmentSize(
F);
394 ++stats::EmittedFragments;
396 switch (
F.getKind()) {
405 ++stats::EmittedDataFragments;
407 ++stats::EmittedRelaxableFragments;
408 const auto &EF = cast<MCFragment>(
F);
409 OS <<
StringRef(EF.getContents().data(), EF.getContents().size());
410 OS <<
StringRef(EF.getVarContents().data(), EF.getVarContents().size());
414 ++stats::EmittedAlignFragments;
415 OS <<
StringRef(
F.getContents().data(),
F.getContents().size());
417 "Invalid virtual align in concrete fragment!");
419 uint64_t Count = (FragmentSize -
F.getFixedSize()) /
F.getAlignFillLen();
420 assert((FragmentSize -
F.getFixedSize()) %
F.getAlignFillLen() == 0 &&
421 "computeFragmentSize computed size is incorrect");
424 if (
F.hasAlignEmitNops()) {
425 if (!Asm.getBackend().writeNopData(
OS, Count,
F.getSubtargetInfo()))
427 Twine(Count) +
" bytes");
430 for (
uint64_t i = 0; i != Count; ++i) {
431 switch (
F.getAlignFillLen()) {
438 support::endian::write<uint16_t>(
OS,
F.getAlignFill(),
Endian);
441 support::endian::write<uint32_t>(
OS,
F.getAlignFill(),
Endian);
444 support::endian::write<uint64_t>(
OS,
F.getAlignFill(),
Endian);
452 ++stats::EmittedFillFragments;
456 const unsigned MaxChunkSize = 16;
457 char Data[MaxChunkSize];
458 assert(0 < VSize && VSize <= MaxChunkSize &&
"Illegal fragment fill size");
461 for (
unsigned I = 0;
I != VSize; ++
I) {
465 for (
unsigned I = VSize;
I < MaxChunkSize; ++
I)
469 const unsigned NumPerChunk = MaxChunkSize / VSize;
471 const unsigned ChunkSize = VSize * NumPerChunk;
475 for (
uint64_t I = 0, E = FragmentSize / ChunkSize;
I != E; ++
I)
479 unsigned TrailingCount = FragmentSize % ChunkSize;
486 ++stats::EmittedNopsFragments;
491 int64_t MaximumNopLength =
494 assert(NumBytes > 0 &&
"Expected positive NOPs fragment size");
495 assert(ControlledNopLength >= 0 &&
"Expected non-negative NOP size");
497 if (ControlledNopLength > MaximumNopLength) {
498 Asm.reportError(NF.
getLoc(),
"illegal NOP size " +
499 std::to_string(ControlledNopLength) +
500 ". (expected within [0, " +
501 std::to_string(MaximumNopLength) +
"])");
504 ControlledNopLength = MaximumNopLength;
508 if (!ControlledNopLength)
509 ControlledNopLength = MaximumNopLength;
513 (
uint64_t)std::min(NumBytes, ControlledNopLength);
514 assert(NumBytesToEmit &&
"try to emit empty NOP instruction");
515 if (!Asm.getBackend().writeNopData(
OS, NumBytesToEmit,
518 Twine(NumBytesToEmit) +
" bytes");
521 NumBytes -= NumBytesToEmit;
530 Twine(FragmentSize) +
" bytes");
541 ++stats::EmittedOrgFragments;
544 for (
uint64_t i = 0, e = FragmentSize; i != e; ++i)
545 OS <<
char(OF.getValue());
553 "The stream should advance by fragment size");
566 auto Fn = [](
char c) {
return c != 0; };
568 bool HasNonZero =
false;
569 switch (
F.getKind()) {
572 "' contains invalid fragment");
582 assert(
F.getAlignFill() == 0 &&
"Invalid align in virtual section!");
585 HasNonZero = cast<MCFillFragment>(
F).getValue() != 0;
588 HasNonZero = cast<MCOrgFragment>(
F).getValue() != 0;
593 "' cannot have non-zero bytes");
596 if (
F.getFixups().size() ||
F.getVarFixups().size()) {
598 "BSS section '" + Sec->getName() +
"' cannot have fixups");
620 errs() <<
"assembler backend - pre-layout\n--\n";
625 unsigned SectionIndex = 0;
630 if (Sec.Subsections.size() > 1) {
633 for (
auto &[
_,
List] : Sec.Subsections) {
638 Sec.Subsections.clear();
639 Sec.Subsections.push_back({0u, {Dummy.
getNext(),
Tail}});
640 Sec.CurFragList = &Sec.Subsections[0].second;
642 unsigned FragmentIndex = 0;
644 Frag.setLayoutOrder(FragmentIndex++);
649 this->HasLayout =
true;
652 unsigned FirstStable = Sections.
size();
653 while ((FirstStable = relaxOnce(FirstStable)) > 0)
666 errs() <<
"assembler backend - final-layout\n--\n";
675 this->HasFinalLayout =
true;
678 for (
auto &PF : relocDirectives) {
681 if (!O.evaluateAsValue(Res, *
this)) {
686 auto *
F =
Sym ?
Sym->getFragment() :
nullptr;
687 auto *Sec =
F ?
F->getParent() :
nullptr;
690 ".reloc offset is not relative to a section");
702 auto Contents =
F.getContents();
707 Fixup.getOffset() <=
F.getFixedSize());
709 reinterpret_cast<uint8_t *
>(Contents.data() +
Fixup.getOffset());
719 (
Fixup.getOffset() >=
F.getFixedSize() &&
720 Fixup.getOffset() <=
F.getSize()));
722 F.getVarContents().data() + (
Fixup.getOffset() -
F.getFixedSize()));
737 assert(PendingErrors.empty());
740bool MCAssembler::fixupNeedsRelaxation(
const MCFragment &
F,
742 ++stats::FixupEvalForRelax;
753 "Expected CodeEmitter defined for relaxInstruction");
757 if (!
getBackend().mayNeedRelaxation(
F.getOpcode(),
F.getOperands(),
758 *
F.getSubtargetInfo()))
761 bool DoRelax =
false;
763 if ((DoRelax = fixupNeedsRelaxation(
F,
Fixup)))
768 ++stats::RelaxedInstructions;
780 F.setVarContents(
Data);
781 F.setVarFixups(Fixups);
785 unsigned PadTo =
F.getVarSize();
792 ?
F.getLEBValue().evaluateKnownAbsolute(
Value, *
this)
793 :
F.getLEBValue().evaluateAsAbsolute(
Value, *
this);
799 Twine(
F.isLEBSigned() ?
".s" :
".u") +
800 "leb128 expression is not absolute");
818 F.setVarContents({
reinterpret_cast<char *
>(
Data),
Size});
828 Align BoundaryAlignment) {
830 return (StartAddr >>
Log2(BoundaryAlignment)) !=
831 ((EndAddr - 1) >>
Log2(BoundaryAlignment));
841 Align BoundaryAlignment) {
843 return (EndAddr & (BoundaryAlignment.
value() - 1)) == 0;
853 Align BoundaryAlignment) {
881void MCAssembler::relaxDwarfLineAddr(
MCFragment &
F) {
887 bool Abs =
F.getDwarfAddrDelta().evaluateKnownAbsolute(AddrDelta, *
this);
888 assert(Abs &&
"We created a line delta with an invalid expression");
892 F.getDwarfLineDelta(), AddrDelta,
Data);
893 F.setVarContents(
Data);
897void MCAssembler::relaxDwarfCallFrameFragment(
MCFragment &
F) {
903 bool Abs =
F.getDwarfAddrDelta().evaluateAsAbsolute(
Value, *
this);
906 "invalid CFI advance_loc expression");
913 F.setVarContents(
Data);
919 switch (
F.getKind()) {
930 relaxDwarfLineAddr(
F);
933 relaxDwarfCallFrameFragment(
F);
948 return F.getNext()->Offset -
F.Offset !=
Size;
953void MCAssembler::layoutSection(
MCSection &Sec) {
962 bool AlignFixup =
false;
963 if (
F.hasAlignEmitNops()) {
969 Size +=
F.getAlignment().value();
971 if (!AlignFixup &&
Size >
F.getAlignMaxBytesToEmit())
975 F.VarContentStart =
F.getFixedSize();
976 F.VarContentEnd =
F.VarContentStart +
Size;
977 if (
F.VarContentEnd >
F.getParent()->ContentStorage.size())
978 F.getParent()->ContentStorage.resize(
F.VarContentEnd);
986unsigned MCAssembler::relaxOnce(
unsigned FirstStable) {
987 ++stats::RelaxationSteps;
988 PendingErrors.clear();
991 for (
unsigned I = 0;
I != FirstStable; ++
I) {
994 auto &Sec = *Sections[
I];
995 auto MaxIter = Sec.curFragList()->Tail->getLayoutOrder() + 1;
997 bool Changed =
false;
1006 FirstStable = Sections.
size();
1023 PendingErrors.emplace_back(Loc, Msg.
str());
1027 for (
auto &Err : PendingErrors)
1029 PendingErrors.clear();
1032#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1040 if (!
Sym.isVariable())
1041 if (
auto *
F =
Sym.getFragment())
1047 Sec.
dump(&FragToSyms);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
dxil DXContainer Global Emitter
static bool getSymbolOffsetImpl(const MCAssembler &Asm, const MCSymbol &S, bool ReportError, uint64_t &Val)
static bool needPadding(uint64_t StartAddr, uint64_t Size, Align BoundaryAlignment)
Check if the branch needs padding.
static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, const MCFragment &F)
Write the fragment F to the output file.
static bool mayCrossBoundary(uint64_t StartAddr, uint64_t Size, Align BoundaryAlignment)
Check if the branch crosses the boundary.
static bool isAgainstBoundary(uint64_t StartAddr, uint64_t Size, Align BoundaryAlignment)
Check if the branch is against the boundary.
static bool getLabelOffset(const MCAssembler &Asm, const MCSymbol &S, bool ReportError, uint64_t &Val)
PowerPC TLS Dynamic Call Fixup
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
void encodeInlineLineTable(const MCAssembler &Asm, MCCVInlineLineTableFragment &F)
Encodes the binary annotations once we have a layout.
void encodeDefRange(const MCAssembler &Asm, MCCVDefRangeFragment &F)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
virtual void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const
Relax the instruction in the given fragment to the next wider instruction.
virtual bool relaxAlign(MCFragment &F, unsigned &Size)
virtual std::pair< bool, bool > relaxLEB128(MCFragment &, int64_t &Value) const
virtual bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, const MCValue &, uint64_t, bool Resolved) const
Target specific predicate for whether a given fixup requires the associated instruction to be relaxed...
virtual void reset()
lifetime management
virtual void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target, uint8_t *Data, uint64_t Value, bool IsResolved)=0
MCContext & getContext() const
LLVM_ABI bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const
LLVM_ABI uint64_t getSectionAddressSize(const MCSection &Sec) const
LLVM_ABI void Finish()
Finish - Do final processing and write the object to the output stream.
LLVM_ABI void reportError(SMLoc L, const Twine &Msg) const
LLVM_ABI void writeSectionData(raw_ostream &OS, const MCSection *Section) const
Emit the section contents to OS.
LLVM_ABI void dump() const
MCObjectWriter & getWriter() const
MCCodeEmitter * getEmitterPtr() const
LLVM_ABI void addRelocDirective(RelocDirective RD)
MCCodeEmitter & getEmitter() const
LLVM_ABI void recordError(SMLoc L, const Twine &Msg) const
LLVM_ABI MCAssembler(MCContext &Context, std::unique_ptr< MCAsmBackend > Backend, std::unique_ptr< MCCodeEmitter > Emitter, std::unique_ptr< MCObjectWriter > Writer)
Construct a new assembler instance.
LLVM_ABI bool isThumbFunc(const MCSymbol *Func) const
Check whether a given symbol has been flagged with .thumb_func.
MCAsmBackend & getBackend() const
LLVM_ABI bool registerSection(MCSection &Section)
LLVM_ABI void flushPendingErrors() const
LLVM_ABI uint64_t computeFragmentSize(const MCFragment &F) const
Compute the effective fragment size.
LLVM_ABI const MCSymbol * getBaseSymbol(const MCSymbol &Symbol) const
MCAsmBackend * getBackendPtr() const
iterator_range< pointee_iterator< typename SmallVector< const MCSymbol *, 0 >::const_iterator > > symbols() const
LLVM_ABI uint64_t getSectionFileSize(const MCSection &Sec) const
LLVM_ABI void reset()
Reuse an assembler instance.
LLVM_ABI bool registerSymbol(const MCSymbol &Symbol)
uint64_t getFragmentOffset(const MCFragment &F) const
MCDwarfLineTableParams getDWARFLinetableParams() const
Represents required padding such that a particular other set of fragments does not cross a particular...
void setSize(uint64_t Value)
const MCFragment * getLastFragment() const
const MCSubtargetInfo * getSubtargetInfo() const
Align getAlignment() const
Fragment representing the .cv_def_range directive.
Fragment representing the binary annotations produced by the .cv_inline_linetable directive.
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
virtual void reset()
Lifetime management.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
LLVM_ABI CodeViewContext & getCVContext()
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
static LLVM_ABI void encodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, SmallVectorImpl< char > &OS)
static LLVM_ABI void encode(MCContext &Context, MCDwarfLineTableParams Params, int64_t LineDelta, uint64_t AddrDelta, SmallVectorImpl< char > &OS)
Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
Base class for the full range of assembler expressions which are needed for parsing.
LLVM_ABI bool evaluateAsValue(MCValue &Res, const MCAssembler &Asm) const
Try to evaluate the expression to the form (a - b + constant) where neither a nor b are variables.
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
uint8_t getValueSize() const
uint64_t getValue() const
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
const MCExpr * getValue() const
LLVM_ABI SMLoc getLoc() const
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
MCFragment * getNext() const
Instances of this class represent a single low-level machine instruction.
int64_t getControlledNopLength() const
int64_t getNumBytes() const
const MCSubtargetInfo * getSubtargetInfo() const
virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCSymbol &SymA, const MCFragment &FB, bool InSet, bool IsPCRel) const
bool getSubsectionsViaSymbols() const
virtual void executePostLayoutBinding()
Perform any late binding of symbols (for example, to assign symbol indices for use when generating re...
virtual uint64_t writeObject()=0
Write the object file and returns the number of bytes written.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
bool isBssSection() const
Check whether this section is "virtual", that is has no actual object file contents.
void dump(DenseMap< const MCFragment *, SmallVector< const MCSymbol *, 0 > > *FragToSyms=nullptr) const
void setOrdinal(unsigned Value)
FragList * curFragList() const
Generic base class for all target subtargets.
Represents a symbol table index fragment.
const MCSymbol * getSymbol()
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isCommon() const
Is this a 'common' symbol.
StringRef getName() const
getName - Get the symbol name.
bool isVariable() const
isVariable - Check if this is a variable symbol.
uint32_t getIndex() const
Get the (implementation defined) index.
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
MCFragment * getFragment() const
uint64_t getOffset() const
const MCSymbol * getAddSym() const
int64_t getConstant() const
const MCSymbol * getSubSym() const
Represents a location in source code.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
uint64_t tell() const
tell - Return the current offset with the file.
raw_ostream & write(unsigned char C)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
bool isRelocRelocation(MCFixupKind FixupKind)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
@ Sub
Subtraction of integers.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.