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)
82 : Context(Context), Backend(
std::
move(Backend)),
85 this->Backend->setAssembler(
this);
87 this->Writer->setAssembler(
this);
92 HasFinalLayout =
false;
108 if (Section.isRegistered())
110 Sections.push_back(&Section);
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())
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");
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;
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);
378 relocDirectives.push_back(RD);
385 uint64_t FragmentSize = Asm.computeFragmentSize(
F);
394 ++stats::EmittedFragments;
396 switch (
F.getKind()) {
405 ++stats::EmittedDataFragments;
407 ++stats::EmittedRelaxableFragments;
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()))
431 switch (
F.getAlignFillLen()) {
435 OS <<
char(
F.getAlignFill());
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;
528 if (!Asm.getBackend().writeNopData(OS, FragmentSize, BF.
getSubtargetInfo()))
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!");
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;
762 for (
const MCFixup &
Fixup :
F.getVarFixups())
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) {
865 uint64_t AlignedSize = 0;
873 uint64_t NewSize =
needPadding(AlignedOffset, AlignedSize, 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");
890 SmallVector<char, 8>
Data;
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");
911 SmallVector<char, 8>
Data;
913 F.setVarContents(
Data);
919 switch (
F.getKind()) {
930 relaxDwarfLineAddr(
F);
933 relaxDwarfCallFrameFragment(
F);
936 relaxBoundaryAlign(
static_cast<MCBoundaryAlignFragment &
>(
F));
940 *
this,
static_cast<MCCVInlineLineTableFragment &
>(
F));
944 *
this,
static_cast<MCCVDefRangeFragment &
>(
F));
948 return F.getNext()->Offset -
F.Offset !=
Size;
953void MCAssembler::layoutSection(
MCSection &Sec) {
955 for (MCFragment &
F : 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;
998 for (MCFragment &
F : Sec)
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())
1042 FragToSyms.
try_emplace(
F).first->second.push_back(&Sym);
1047 Sec.
dump(&FragToSyms);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
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
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
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.
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.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
bool isRelocRelocation(MCFixupKind FixupKind)
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
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)
FunctionAddr VTableAddr Count
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
@ 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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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.