diff options
Diffstat (limited to 'clang-r353983/include/llvm/MC')
76 files changed, 14857 insertions, 0 deletions
diff --git a/clang-r353983/include/llvm/MC/ConstantPools.h b/clang-r353983/include/llvm/MC/ConstantPools.h new file mode 100644 index 00000000..2fe5ce25 --- /dev/null +++ b/clang-r353983/include/llvm/MC/ConstantPools.h @@ -0,0 +1,102 @@ +//===- ConstantPools.h - Keep track of assembler-generated ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the ConstantPool and AssemblerConstantPools classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_CONSTANTPOOLS_H +#define LLVM_MC_CONSTANTPOOLS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/SMLoc.h" +#include <cstdint> +#include <map> + +namespace llvm { + +class MCContext; +class MCExpr; +class MCSection; +class MCStreamer; +class MCSymbol; +class MCSymbolRefExpr; + +struct ConstantPoolEntry { + ConstantPoolEntry(MCSymbol *L, const MCExpr *Val, unsigned Sz, SMLoc Loc_) + : Label(L), Value(Val), Size(Sz), Loc(Loc_) {} + + MCSymbol *Label; + const MCExpr *Value; + unsigned Size; + SMLoc Loc; +}; + +// A class to keep track of assembler-generated constant pools that are use to +// implement the ldr-pseudo. +class ConstantPool { + using EntryVecTy = SmallVector<ConstantPoolEntry, 4>; + EntryVecTy Entries; + std::map<int64_t, const MCSymbolRefExpr *> CachedEntries; + +public: + // Initialize a new empty constant pool + ConstantPool() = default; + + // Add a new entry to the constant pool in the next slot. + // \param Value is the new entry to put in the constant pool. + // \param Size is the size in bytes of the entry + // + // \returns a MCExpr that references the newly inserted value + const MCExpr *addEntry(const MCExpr *Value, MCContext &Context, + unsigned Size, SMLoc Loc); + + // Emit the contents of the constant pool using the provided streamer. + void emitEntries(MCStreamer &Streamer); + + // Return true if the constant pool is empty + bool empty(); + + void clearCache(); +}; + +class AssemblerConstantPools { + // Map type used to keep track of per-Section constant pools used by the + // ldr-pseudo opcode. The map associates a section to its constant pool. The + // constant pool is a vector of (label, value) pairs. When the ldr + // pseudo is parsed we insert a new (label, value) pair into the constant pool + // for the current section and add MCSymbolRefExpr to the new label as + // an opcode to the ldr. After we have parsed all the user input we + // output the (label, value) pairs in each constant pool at the end of the + // section. + // + // We use the MapVector for the map type to ensure stable iteration of + // the sections at the end of the parse. We need to iterate over the + // sections in a stable order to ensure that we have print the + // constant pools in a deterministic order when printing an assembly + // file. + using ConstantPoolMapTy = MapVector<MCSection *, ConstantPool>; + ConstantPoolMapTy ConstantPools; + +public: + void emitAll(MCStreamer &Streamer); + void emitForCurrentSection(MCStreamer &Streamer); + void clearCacheForCurrentSection(MCStreamer &Streamer); + const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr, + unsigned Size, SMLoc Loc); + +private: + ConstantPool *getConstantPool(MCSection *Section); + ConstantPool &getOrCreateConstantPool(MCSection *Section); +}; + +} // end namespace llvm + +#endif // LLVM_MC_CONSTANTPOOLS_H diff --git a/clang-r353983/include/llvm/MC/LaneBitmask.h b/clang-r353983/include/llvm/MC/LaneBitmask.h new file mode 100644 index 00000000..d5f69287 --- /dev/null +++ b/clang-r353983/include/llvm/MC/LaneBitmask.h @@ -0,0 +1,101 @@ +//===- llvm/MC/LaneBitmask.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// A common definition of LaneBitmask for use in TableGen and CodeGen. +/// +/// A lane mask is a bitmask representing the covering of a register with +/// sub-registers. +/// +/// This is typically used to track liveness at sub-register granularity. +/// Lane masks for sub-register indices are similar to register units for +/// physical registers. The individual bits in a lane mask can't be assigned +/// any specific meaning. They can be used to check if two sub-register +/// indices overlap. +/// +/// Iff the target has a register such that: +/// +/// getSubReg(Reg, A) overlaps getSubReg(Reg, B) +/// +/// then: +/// +/// (getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B)) != 0 + +#ifndef LLVM_MC_LANEBITMASK_H +#define LLVM_MC_LANEBITMASK_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Printable.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + + struct LaneBitmask { + // When changing the underlying type, change the format string as well. + using Type = unsigned; + enum : unsigned { BitWidth = 8*sizeof(Type) }; + constexpr static const char *const FormatStr = "%08X"; + + constexpr LaneBitmask() = default; + explicit constexpr LaneBitmask(Type V) : Mask(V) {} + + constexpr bool operator== (LaneBitmask M) const { return Mask == M.Mask; } + constexpr bool operator!= (LaneBitmask M) const { return Mask != M.Mask; } + constexpr bool operator< (LaneBitmask M) const { return Mask < M.Mask; } + constexpr bool none() const { return Mask == 0; } + constexpr bool any() const { return Mask != 0; } + constexpr bool all() const { return ~Mask == 0; } + + constexpr LaneBitmask operator~() const { + return LaneBitmask(~Mask); + } + constexpr LaneBitmask operator|(LaneBitmask M) const { + return LaneBitmask(Mask | M.Mask); + } + constexpr LaneBitmask operator&(LaneBitmask M) const { + return LaneBitmask(Mask & M.Mask); + } + LaneBitmask &operator|=(LaneBitmask M) { + Mask |= M.Mask; + return *this; + } + LaneBitmask &operator&=(LaneBitmask M) { + Mask &= M.Mask; + return *this; + } + + constexpr Type getAsInteger() const { return Mask; } + + unsigned getNumLanes() const { + return countPopulation(Mask); + } + unsigned getHighestLane() const { + return Log2_32(Mask); + } + + static constexpr LaneBitmask getNone() { return LaneBitmask(0); } + static constexpr LaneBitmask getAll() { return ~LaneBitmask(0); } + static constexpr LaneBitmask getLane(unsigned Lane) { + return LaneBitmask(Type(1) << Lane); + } + + private: + Type Mask = 0; + }; + + /// Create Printable object to print LaneBitmasks on a \ref raw_ostream. + inline Printable PrintLaneMask(LaneBitmask LaneMask) { + return Printable([LaneMask](raw_ostream &OS) { + OS << format(LaneBitmask::FormatStr, LaneMask.getAsInteger()); + }); + } + +} // end namespace llvm + +#endif // LLVM_MC_LANEBITMASK_H diff --git a/clang-r353983/include/llvm/MC/MCAsmBackend.h b/clang-r353983/include/llvm/MC/MCAsmBackend.h new file mode 100644 index 00000000..1f3ad6c1 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCAsmBackend.h @@ -0,0 +1,225 @@ +//===- llvm/MC/MCAsmBackend.h - MC Asm Backend ------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMBACKEND_H +#define LLVM_MC_MCASMBACKEND_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFragment.h" +#include "llvm/Support/Endian.h" +#include <cstdint> +#include <memory> + +namespace llvm { + +class MCAsmLayout; +class MCAssembler; +class MCCFIInstruction; +class MCCodePadder; +struct MCFixupKindInfo; +class MCFragment; +class MCInst; +class MCObjectStreamer; +class MCObjectTargetWriter; +class MCObjectWriter; +struct MCCodePaddingContext; +class MCRelaxableFragment; +class MCSubtargetInfo; +class MCValue; +class raw_pwrite_stream; + +/// Generic interface to target specific assembler backends. +class MCAsmBackend { + std::unique_ptr<MCCodePadder> CodePadder; + +protected: // Can only create subclasses. + MCAsmBackend(support::endianness Endian); + +public: + MCAsmBackend(const MCAsmBackend &) = delete; + MCAsmBackend &operator=(const MCAsmBackend &) = delete; + virtual ~MCAsmBackend(); + + const support::endianness Endian; + + /// lifetime management + virtual void reset() {} + + /// Create a new MCObjectWriter instance for use by the assembler backend to + /// emit the final object file. + std::unique_ptr<MCObjectWriter> + createObjectWriter(raw_pwrite_stream &OS) const; + + /// Create an MCObjectWriter that writes two object files: a .o file which is + /// linked into the final program and a .dwo file which is used by debuggers. + /// This function is only supported with ELF targets. + std::unique_ptr<MCObjectWriter> + createDwoObjectWriter(raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS) const; + + virtual std::unique_ptr<MCObjectTargetWriter> + createObjectTargetWriter() const = 0; + + /// \name Target Fixup Interfaces + /// @{ + + /// Get the number of target specific fixup kinds. + virtual unsigned getNumFixupKinds() const = 0; + + /// Map a relocation name used in .reloc to a fixup kind. + virtual Optional<MCFixupKind> getFixupKind(StringRef Name) const; + + /// Get information on a fixup kind. + virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; + + /// Hook to check if a relocation is needed for some target specific reason. + virtual bool shouldForceRelocation(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target) { + return false; + } + + /// Hook to check if extra nop bytes must be inserted for alignment directive. + /// For some targets this may be necessary in order to support linker + /// relaxation. The number of bytes to insert are returned in Size. + virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF, + unsigned &Size) { + return false; + } + + /// Hook which indicates if the target requires a fixup to be generated when + /// handling an align directive in an executable section + virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, + const MCAsmLayout &Layout, + MCAlignFragment &AF) { + return false; + } + + /// Apply the \p Value for given \p Fixup into the provided data fragment, at + /// the offset specified by the fixup and following the fixup kind as + /// appropriate. Errors (such as an out of range fixup value) should be + /// reported via \p Ctx. + /// The \p STI is present only for fragments of type MCRelaxableFragment and + /// MCDataFragment with hasInstructions() == true. + virtual void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, MutableArrayRef<char> Data, + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const = 0; + + /// Check whether the given target requires emitting differences of two + /// symbols as a set of relocations. + virtual bool requiresDiffExpressionRelocations() const { return false; } + + /// @} + + /// \name Target Relaxation Interfaces + /// @{ + + /// Check whether the given instruction may need relaxation. + /// + /// \param Inst - The instruction to test. + /// \param STI - The MCSubtargetInfo in effect when the instruction was + /// encoded. + virtual bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const = 0; + + /// Target specific predicate for whether a given fixup requires the + /// associated instruction to be relaxed. + virtual bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved, + uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout, + const bool WasForced) const; + + /// Simple predicate for targets where !Resolved implies requiring relaxation + virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const = 0; + + /// Relax the instruction in the given fragment to the next wider instruction. + /// + /// \param Inst The instruction to relax, which may be the same as the + /// output. + /// \param STI the subtarget information for the associated instruction. + /// \param [out] Res On return, the relaxed instruction. + virtual void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + MCInst &Res) const = 0; + + /// @} + + /// Returns the minimum size of a nop in bytes on this target. The assembler + /// will use this to emit excess padding in situations where the padding + /// required for simple alignment would be less than the minimum nop size. + /// + virtual unsigned getMinimumNopSize() const { return 1; } + + /// Write an (optimal) nop sequence of Count bytes to the given output. If the + /// target cannot generate such a sequence, it should return an error. + /// + /// \return - True on success. + virtual bool writeNopData(raw_ostream &OS, uint64_t Count) const = 0; + + /// Give backend an opportunity to finish layout after relaxation + virtual void finishLayout(MCAssembler const &Asm, + MCAsmLayout &Layout) const {} + + /// Handle any target-specific assembler flags. By default, do nothing. + virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} + + /// Generate the compact unwind encoding for the CFI instructions. + virtual uint32_t + generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const { + return 0; + } + + /// Check whether a given symbol has been flagged with MICROMIPS flag. + virtual bool isMicroMips(const MCSymbol *Sym) const { + return false; + } + + /// Handles all target related code padding when starting to write a new + /// basic block to an object file. + /// + /// \param OS The streamer used for writing the padding data and function. + /// \param Context the context of the padding, Embeds the basic block's + /// parameters. + void handleCodePaddingBasicBlockStart(MCObjectStreamer *OS, + const MCCodePaddingContext &Context); + /// Handles all target related code padding after writing a block to an object + /// file. + /// + /// \param Context the context of the padding, Embeds the basic block's + /// parameters. + void handleCodePaddingBasicBlockEnd(const MCCodePaddingContext &Context); + /// Handles all target related code padding before writing a new instruction + /// to an object file. + /// + /// \param Inst the instruction. + void handleCodePaddingInstructionBegin(const MCInst &Inst); + /// Handles all target related code padding after writing an instruction to an + /// object file. + /// + /// \param Inst the instruction. + void handleCodePaddingInstructionEnd(const MCInst &Inst); + + /// Relaxes a fragment (changes the size of the padding) according to target + /// requirements. The new size computation is done w.r.t a layout. + /// + /// \param PF The fragment to relax. + /// \param Layout Code layout information. + /// + /// \returns true iff any relaxation occurred. + bool relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout); +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCASMBACKEND_H diff --git a/clang-r353983/include/llvm/MC/MCAsmInfo.h b/clang-r353983/include/llvm/MC/MCAsmInfo.h new file mode 100644 index 00000000..e861df5b --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCAsmInfo.h @@ -0,0 +1,641 @@ +//===-- llvm/MC/MCAsmInfo.h - Asm info --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains a class to be used as the basis for target specific +// asm writers. This class primarily takes care of global printing constants, +// which are used in very similar ways across all targets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMINFO_H +#define LLVM_MC_MCASMINFO_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCTargetOptions.h" +#include <vector> + +namespace llvm { + +class MCContext; +class MCExpr; +class MCSection; +class MCStreamer; +class MCSymbol; + +namespace WinEH { + +enum class EncodingType { + Invalid, /// Invalid + Alpha, /// Windows Alpha + Alpha64, /// Windows AXP64 + ARM, /// Windows NT (Windows on ARM) + CE, /// Windows CE ARM, PowerPC, SH3, SH4 + Itanium, /// Windows x64, Windows Itanium (IA-64) + X86, /// Windows x86, uses no CFI, just EH tables + MIPS = Alpha, +}; + +} // end namespace WinEH + +namespace LCOMM { + +enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment }; + +} // end namespace LCOMM + +/// This class is intended to be used as a base class for asm +/// properties and features specific to the target. +class MCAsmInfo { +protected: + //===------------------------------------------------------------------===// + // Properties to be set by the target writer, used to configure asm printer. + // + + /// Code pointer size in bytes. Default is 4. + unsigned CodePointerSize = 4; + + /// Size of the stack slot reserved for callee-saved registers, in bytes. + /// Default is same as pointer size. + unsigned CalleeSaveStackSlotSize = 4; + + /// True if target is little endian. Default is true. + bool IsLittleEndian = true; + + /// True if target stack grow up. Default is false. + bool StackGrowsUp = false; + + /// True if this target has the MachO .subsections_via_symbols directive. + /// Default is false. + bool HasSubsectionsViaSymbols = false; + + /// True if this is a MachO target that supports the macho-specific .zerofill + /// directive for emitting BSS Symbols. Default is false. + bool HasMachoZeroFillDirective = false; + + /// True if this is a MachO target that supports the macho-specific .tbss + /// directive for emitting thread local BSS Symbols. Default is false. + bool HasMachoTBSSDirective = false; + + /// True if this is a non-GNU COFF target. The COFF port of the GNU linker + /// doesn't handle associative comdats in the way that we would like to use + /// them. + bool HasCOFFAssociativeComdats = false; + + /// True if this is a non-GNU COFF target. For GNU targets, we don't generate + /// constants into comdat sections. + bool HasCOFFComdatConstants = false; + + /// This is the maximum possible length of an instruction, which is needed to + /// compute the size of an inline asm. Defaults to 4. + unsigned MaxInstLength = 4; + + /// Every possible instruction length is a multiple of this value. Factored + /// out in .debug_frame and .debug_line. Defaults to 1. + unsigned MinInstAlignment = 1; + + /// The '$' token, when not referencing an identifier or constant, refers to + /// the current PC. Defaults to false. + bool DollarIsPC = false; + + /// This string, if specified, is used to separate instructions from each + /// other when on the same line. Defaults to ';' + const char *SeparatorString; + + /// This indicates the comment character used by the assembler. Defaults to + /// "#" + StringRef CommentString; + + /// This is appended to emitted labels. Defaults to ":" + const char *LabelSuffix; + + // Print the EH begin symbol with an assignment. Defaults to false. + bool UseAssignmentForEHBegin = false; + + // Do we need to create a local symbol for .size? + bool NeedsLocalForSize = false; + + /// This prefix is used for globals like constant pool entries that are + /// completely private to the .s file and should not have names in the .o + /// file. Defaults to "L" + StringRef PrivateGlobalPrefix; + + /// This prefix is used for labels for basic blocks. Defaults to the same as + /// PrivateGlobalPrefix. + StringRef PrivateLabelPrefix; + + /// This prefix is used for symbols that should be passed through the + /// assembler but be removed by the linker. This is 'l' on Darwin, currently + /// used for some ObjC metadata. The default of "" meast that for this system + /// a plain private symbol should be used. Defaults to "". + StringRef LinkerPrivateGlobalPrefix; + + /// If these are nonempty, they contain a directive to emit before and after + /// an inline assembly statement. Defaults to "#APP\n", "#NO_APP\n" + const char *InlineAsmStart; + const char *InlineAsmEnd; + + /// These are assembly directives that tells the assembler to interpret the + /// following instructions differently. Defaults to ".code16", ".code32", + /// ".code64". + const char *Code16Directive; + const char *Code32Directive; + const char *Code64Directive; + + /// Which dialect of an assembler variant to use. Defaults to 0 + unsigned AssemblerDialect = 0; + + /// This is true if the assembler allows @ characters in symbol names. + /// Defaults to false. + bool AllowAtInName = false; + + /// If this is true, symbol names with invalid characters will be printed in + /// quotes. + bool SupportsQuotedNames = true; + + /// This is true if data region markers should be printed as + /// ".data_region/.end_data_region" directives. If false, use "$d/$a" labels + /// instead. + bool UseDataRegionDirectives = false; + + //===--- Data Emission Directives -------------------------------------===// + + /// This should be set to the directive used to get some number of zero bytes + /// emitted to the current section. Common cases are "\t.zero\t" and + /// "\t.space\t". If this is set to null, the Data*bitsDirective's will be + /// used to emit zero bytes. Defaults to "\t.zero\t" + const char *ZeroDirective; + + /// This directive allows emission of an ascii string with the standard C + /// escape characters embedded into it. If a target doesn't support this, it + /// can be set to null. Defaults to "\t.ascii\t" + const char *AsciiDirective; + + /// If not null, this allows for special handling of zero terminated strings + /// on this target. This is commonly supported as ".asciz". If a target + /// doesn't support this, it can be set to null. Defaults to "\t.asciz\t" + const char *AscizDirective; + + /// These directives are used to output some unit of integer data to the + /// current section. If a data directive is set to null, smaller data + /// directives will be used to emit the large sizes. Defaults to "\t.byte\t", + /// "\t.short\t", "\t.long\t", "\t.quad\t" + const char *Data8bitsDirective; + const char *Data16bitsDirective; + const char *Data32bitsDirective; + const char *Data64bitsDirective; + + /// If non-null, a directive that is used to emit a word which should be + /// relocated as a 64-bit GP-relative offset, e.g. .gpdword on Mips. Defaults + /// to nullptr. + const char *GPRel64Directive = nullptr; + + /// If non-null, a directive that is used to emit a word which should be + /// relocated as a 32-bit GP-relative offset, e.g. .gpword on Mips or .gprel32 + /// on Alpha. Defaults to nullptr. + const char *GPRel32Directive = nullptr; + + /// If non-null, directives that are used to emit a word/dword which should + /// be relocated as a 32/64-bit DTP/TP-relative offset, e.g. .dtprelword/ + /// .dtpreldword/.tprelword/.tpreldword on Mips. + const char *DTPRel32Directive = nullptr; + const char *DTPRel64Directive = nullptr; + const char *TPRel32Directive = nullptr; + const char *TPRel64Directive = nullptr; + + /// This is true if this target uses "Sun Style" syntax for section switching + /// ("#alloc,#write" etc) instead of the normal ELF syntax (,"a,w") in + /// .section directives. Defaults to false. + bool SunStyleELFSectionSwitchSyntax = false; + + /// This is true if this target uses ELF '.section' directive before the + /// '.bss' one. It's used for PPC/Linux which doesn't support the '.bss' + /// directive only. Defaults to false. + bool UsesELFSectionDirectiveForBSS = false; + + bool NeedsDwarfSectionOffsetDirective = false; + + //===--- Alignment Information ----------------------------------------===// + + /// If this is true (the default) then the asmprinter emits ".align N" + /// directives, where N is the number of bytes to align to. Otherwise, it + /// emits ".align log2(N)", e.g. 3 to align to an 8 byte boundary. Defaults + /// to true. + bool AlignmentIsInBytes = true; + + /// If non-zero, this is used to fill the executable space created as the + /// result of a alignment directive. Defaults to 0 + unsigned TextAlignFillValue = 0; + + //===--- Global Variable Emission Directives --------------------------===// + + /// This is the directive used to declare a global entity. Defaults to + /// ".globl". + const char *GlobalDirective; + + /// True if the expression + /// .long f - g + /// uses a relocation but it can be suppressed by writing + /// a = f - g + /// .long a + bool SetDirectiveSuppressesReloc = false; + + /// False if the assembler requires that we use + /// \code + /// Lc = a - b + /// .long Lc + /// \endcode + // + /// instead of + // + /// \code + /// .long a - b + /// \endcode + /// + /// Defaults to true. + bool HasAggressiveSymbolFolding = true; + + /// True is .comm's and .lcomms optional alignment is to be specified in bytes + /// instead of log2(n). Defaults to true. + bool COMMDirectiveAlignmentIsInBytes = true; + + /// Describes if the .lcomm directive for the target supports an alignment + /// argument and how it is interpreted. Defaults to NoAlignment. + LCOMM::LCOMMType LCOMMDirectiveAlignmentType = LCOMM::NoAlignment; + + // True if the target allows .align directives on functions. This is true for + // most targets, so defaults to true. + bool HasFunctionAlignment = true; + + /// True if the target has .type and .size directives, this is true for most + /// ELF targets. Defaults to true. + bool HasDotTypeDotSizeDirective = true; + + /// True if the target has a single parameter .file directive, this is true + /// for ELF targets. Defaults to true. + bool HasSingleParameterDotFile = true; + + /// True if the target has a .ident directive, this is true for ELF targets. + /// Defaults to false. + bool HasIdentDirective = false; + + /// True if this target supports the MachO .no_dead_strip directive. Defaults + /// to false. + bool HasNoDeadStrip = false; + + /// True if this target supports the MachO .alt_entry directive. Defaults to + /// false. + bool HasAltEntry = false; + + /// Used to declare a global as being a weak symbol. Defaults to ".weak". + const char *WeakDirective; + + /// This directive, if non-null, is used to declare a global as being a weak + /// undefined symbol. Defaults to nullptr. + const char *WeakRefDirective = nullptr; + + /// True if we have a directive to declare a global as being a weak defined + /// symbol. Defaults to false. + bool HasWeakDefDirective = false; + + /// True if we have a directive to declare a global as being a weak defined + /// symbol that can be hidden (unexported). Defaults to false. + bool HasWeakDefCanBeHiddenDirective = false; + + /// True if we have a .linkonce directive. This is used on cygwin/mingw. + /// Defaults to false. + bool HasLinkOnceDirective = false; + + /// This attribute, if not MCSA_Invalid, is used to declare a symbol as having + /// hidden visibility. Defaults to MCSA_Hidden. + MCSymbolAttr HiddenVisibilityAttr = MCSA_Hidden; + + /// This attribute, if not MCSA_Invalid, is used to declare an undefined + /// symbol as having hidden visibility. Defaults to MCSA_Hidden. + MCSymbolAttr HiddenDeclarationVisibilityAttr = MCSA_Hidden; + + /// This attribute, if not MCSA_Invalid, is used to declare a symbol as having + /// protected visibility. Defaults to MCSA_Protected + MCSymbolAttr ProtectedVisibilityAttr = MCSA_Protected; + + //===--- Dwarf Emission Directives -----------------------------------===// + + /// True if target supports emission of debugging information. Defaults to + /// false. + bool SupportsDebugInformation = false; + + /// Exception handling format for the target. Defaults to None. + ExceptionHandling ExceptionsType = ExceptionHandling::None; + + /// Windows exception handling data (.pdata) encoding. Defaults to Invalid. + WinEH::EncodingType WinEHEncodingType = WinEH::EncodingType::Invalid; + + /// True if Dwarf2 output generally uses relocations for references to other + /// .debug_* sections. + bool DwarfUsesRelocationsAcrossSections = true; + + /// True if DWARF FDE symbol reference relocations should be replaced by an + /// absolute difference. + bool DwarfFDESymbolsUseAbsDiff = false; + + /// True if dwarf register numbers are printed instead of symbolic register + /// names in .cfi_* directives. Defaults to false. + bool DwarfRegNumForCFI = false; + + /// True if target uses parens to indicate the symbol variant instead of @. + /// For example, foo(plt) instead of foo@plt. Defaults to false. + bool UseParensForSymbolVariant = false; + + /// True if the target supports flags in ".loc" directive, false if only + /// location is allowed. + bool SupportsExtendedDwarfLocDirective = true; + + //===--- Prologue State ----------------------------------------------===// + + std::vector<MCCFIInstruction> InitialFrameState; + + //===--- Integrated Assembler Information ----------------------------===// + + /// Should we use the integrated assembler? + /// The integrated assembler should be enabled by default (by the + /// constructors) when failing to parse a valid piece of assembly (inline + /// or otherwise) is considered a bug. It may then be overridden after + /// construction (see LLVMTargetMachine::initAsmInfo()). + bool UseIntegratedAssembler; + + /// Preserve Comments in assembly + bool PreserveAsmComments; + + /// Compress DWARF debug sections. Defaults to no compression. + DebugCompressionType CompressDebugSections = DebugCompressionType::None; + + /// True if the integrated assembler should interpret 'a >> b' constant + /// expressions as logical rather than arithmetic. + bool UseLogicalShr = true; + + // If true, emit GOTPCRELX/REX_GOTPCRELX instead of GOTPCREL, on + // X86_64 ELF. + bool RelaxELFRelocations = true; + + // If true, then the lexer and expression parser will support %neg(), + // %hi(), and similar unary operators. + bool HasMipsExpressions = false; + +public: + explicit MCAsmInfo(); + virtual ~MCAsmInfo(); + + /// Get the code pointer size in bytes. + unsigned getCodePointerSize() const { return CodePointerSize; } + + /// Get the callee-saved register stack slot + /// size in bytes. + unsigned getCalleeSaveStackSlotSize() const { + return CalleeSaveStackSlotSize; + } + + /// True if the target is little endian. + bool isLittleEndian() const { return IsLittleEndian; } + + /// True if target stack grow up. + bool isStackGrowthDirectionUp() const { return StackGrowsUp; } + + bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } + + // Data directive accessors. + + const char *getData8bitsDirective() const { return Data8bitsDirective; } + const char *getData16bitsDirective() const { return Data16bitsDirective; } + const char *getData32bitsDirective() const { return Data32bitsDirective; } + const char *getData64bitsDirective() const { return Data64bitsDirective; } + const char *getGPRel64Directive() const { return GPRel64Directive; } + const char *getGPRel32Directive() const { return GPRel32Directive; } + const char *getDTPRel64Directive() const { return DTPRel64Directive; } + const char *getDTPRel32Directive() const { return DTPRel32Directive; } + const char *getTPRel64Directive() const { return TPRel64Directive; } + const char *getTPRel32Directive() const { return TPRel32Directive; } + + /// Targets can implement this method to specify a section to switch to if the + /// translation unit doesn't have any trampolines that require an executable + /// stack. + virtual MCSection *getNonexecutableStackSection(MCContext &Ctx) const { + return nullptr; + } + + /// True if the section is atomized using the symbols in it. + /// This is false if the section is not atomized at all (most ELF sections) or + /// if it is atomized based on its contents (MachO' __TEXT,__cstring for + /// example). + virtual bool isSectionAtomizableBySymbols(const MCSection &Section) const; + + virtual const MCExpr *getExprForPersonalitySymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; + + virtual const MCExpr *getExprForFDESymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; + + /// Return true if the identifier \p Name does not need quotes to be + /// syntactically correct. + virtual bool isValidUnquotedName(StringRef Name) const; + + /// Return true if the .section directive should be omitted when + /// emitting \p SectionName. For example: + /// + /// shouldOmitSectionDirective(".text") + /// + /// returns false => .section .text,#alloc,#execinstr + /// returns true => .text + virtual bool shouldOmitSectionDirective(StringRef SectionName) const; + + bool usesSunStyleELFSectionSwitchSyntax() const { + return SunStyleELFSectionSwitchSyntax; + } + + bool usesELFSectionDirectiveForBSS() const { + return UsesELFSectionDirectiveForBSS; + } + + bool needsDwarfSectionOffsetDirective() const { + return NeedsDwarfSectionOffsetDirective; + } + + // Accessors. + + bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } + bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } + bool hasCOFFAssociativeComdats() const { return HasCOFFAssociativeComdats; } + bool hasCOFFComdatConstants() const { return HasCOFFComdatConstants; } + unsigned getMaxInstLength() const { return MaxInstLength; } + unsigned getMinInstAlignment() const { return MinInstAlignment; } + bool getDollarIsPC() const { return DollarIsPC; } + const char *getSeparatorString() const { return SeparatorString; } + + /// This indicates the column (zero-based) at which asm comments should be + /// printed. + unsigned getCommentColumn() const { return 40; } + + StringRef getCommentString() const { return CommentString; } + const char *getLabelSuffix() const { return LabelSuffix; } + + bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; } + bool needsLocalForSize() const { return NeedsLocalForSize; } + StringRef getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } + StringRef getPrivateLabelPrefix() const { return PrivateLabelPrefix; } + + bool hasLinkerPrivateGlobalPrefix() const { + return !LinkerPrivateGlobalPrefix.empty(); + } + + StringRef getLinkerPrivateGlobalPrefix() const { + if (hasLinkerPrivateGlobalPrefix()) + return LinkerPrivateGlobalPrefix; + return getPrivateGlobalPrefix(); + } + + const char *getInlineAsmStart() const { return InlineAsmStart; } + const char *getInlineAsmEnd() const { return InlineAsmEnd; } + const char *getCode16Directive() const { return Code16Directive; } + const char *getCode32Directive() const { return Code32Directive; } + const char *getCode64Directive() const { return Code64Directive; } + unsigned getAssemblerDialect() const { return AssemblerDialect; } + bool doesAllowAtInName() const { return AllowAtInName; } + bool supportsNameQuoting() const { return SupportsQuotedNames; } + + bool doesSupportDataRegionDirectives() const { + return UseDataRegionDirectives; + } + + const char *getZeroDirective() const { return ZeroDirective; } + const char *getAsciiDirective() const { return AsciiDirective; } + const char *getAscizDirective() const { return AscizDirective; } + bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; } + unsigned getTextAlignFillValue() const { return TextAlignFillValue; } + const char *getGlobalDirective() const { return GlobalDirective; } + + bool doesSetDirectiveSuppressReloc() const { + return SetDirectiveSuppressesReloc; + } + + bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; } + + bool getCOMMDirectiveAlignmentIsInBytes() const { + return COMMDirectiveAlignmentIsInBytes; + } + + LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const { + return LCOMMDirectiveAlignmentType; + } + + bool hasFunctionAlignment() const { return HasFunctionAlignment; } + bool hasDotTypeDotSizeDirective() const { return HasDotTypeDotSizeDirective; } + bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } + bool hasIdentDirective() const { return HasIdentDirective; } + bool hasNoDeadStrip() const { return HasNoDeadStrip; } + bool hasAltEntry() const { return HasAltEntry; } + const char *getWeakDirective() const { return WeakDirective; } + const char *getWeakRefDirective() const { return WeakRefDirective; } + bool hasWeakDefDirective() const { return HasWeakDefDirective; } + + bool hasWeakDefCanBeHiddenDirective() const { + return HasWeakDefCanBeHiddenDirective; + } + + bool hasLinkOnceDirective() const { return HasLinkOnceDirective; } + + MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr; } + + MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { + return HiddenDeclarationVisibilityAttr; + } + + MCSymbolAttr getProtectedVisibilityAttr() const { + return ProtectedVisibilityAttr; + } + + bool doesSupportDebugInformation() const { return SupportsDebugInformation; } + + bool doesSupportExceptionHandling() const { + return ExceptionsType != ExceptionHandling::None; + } + + ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } + WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } + + void setExceptionsType(ExceptionHandling EH) { + ExceptionsType = EH; + } + + /// Returns true if the exception handling method for the platform uses call + /// frame information to unwind. + bool usesCFIForEH() const { + return (ExceptionsType == ExceptionHandling::DwarfCFI || + ExceptionsType == ExceptionHandling::ARM || usesWindowsCFI()); + } + + bool usesWindowsCFI() const { + return ExceptionsType == ExceptionHandling::WinEH && + (WinEHEncodingType != WinEH::EncodingType::Invalid && + WinEHEncodingType != WinEH::EncodingType::X86); + } + + bool doesDwarfUseRelocationsAcrossSections() const { + return DwarfUsesRelocationsAcrossSections; + } + + bool doDwarfFDESymbolsUseAbsDiff() const { return DwarfFDESymbolsUseAbsDiff; } + bool useDwarfRegNumForCFI() const { return DwarfRegNumForCFI; } + bool useParensForSymbolVariant() const { return UseParensForSymbolVariant; } + bool supportsExtendedDwarfLocDirective() const { + return SupportsExtendedDwarfLocDirective; + } + + void addInitialFrameState(const MCCFIInstruction &Inst) { + InitialFrameState.push_back(Inst); + } + + const std::vector<MCCFIInstruction> &getInitialFrameState() const { + return InitialFrameState; + } + + /// Return true if assembly (inline or otherwise) should be parsed. + bool useIntegratedAssembler() const { return UseIntegratedAssembler; } + + /// Set whether assembly (inline or otherwise) should be parsed. + virtual void setUseIntegratedAssembler(bool Value) { + UseIntegratedAssembler = Value; + } + + /// Return true if assembly (inline or otherwise) should be parsed. + bool preserveAsmComments() const { return PreserveAsmComments; } + + /// Set whether assembly (inline or otherwise) should be parsed. + virtual void setPreserveAsmComments(bool Value) { + PreserveAsmComments = Value; + } + + DebugCompressionType compressDebugSections() const { + return CompressDebugSections; + } + + void setCompressDebugSections(DebugCompressionType CompressDebugSections) { + this->CompressDebugSections = CompressDebugSections; + } + + bool shouldUseLogicalShr() const { return UseLogicalShr; } + + bool canRelaxRelocations() const { return RelaxELFRelocations; } + void setRelaxELFRelocations(bool V) { RelaxELFRelocations = V; } + bool hasMipsExpressions() const { return HasMipsExpressions; } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCASMINFO_H diff --git a/clang-r353983/include/llvm/MC/MCAsmInfoCOFF.h b/clang-r353983/include/llvm/MC/MCAsmInfoCOFF.h new file mode 100644 index 00000000..1dfb4750 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCAsmInfoCOFF.h @@ -0,0 +1,39 @@ +//===- MCAsmInfoCOFF.h - COFF asm properties --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMINFOCOFF_H +#define LLVM_MC_MCASMINFOCOFF_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + +class MCAsmInfoCOFF : public MCAsmInfo { + virtual void anchor(); + +protected: + explicit MCAsmInfoCOFF(); +}; + +class MCAsmInfoMicrosoft : public MCAsmInfoCOFF { + void anchor() override; + +protected: + explicit MCAsmInfoMicrosoft(); +}; + +class MCAsmInfoGNUCOFF : public MCAsmInfoCOFF { + void anchor() override; + +protected: + explicit MCAsmInfoGNUCOFF(); +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCASMINFOCOFF_H diff --git a/clang-r353983/include/llvm/MC/MCAsmInfoDarwin.h b/clang-r353983/include/llvm/MC/MCAsmInfoDarwin.h new file mode 100644 index 00000000..c889ce99 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCAsmInfoDarwin.h @@ -0,0 +1,30 @@ +//===- MCAsmInfoDarwin.h - Darwin asm properties ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines target asm properties related what form asm statements +// should take in general on Darwin-based targets +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMINFODARWIN_H +#define LLVM_MC_MCASMINFODARWIN_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + +class MCAsmInfoDarwin : public MCAsmInfo { +public: + explicit MCAsmInfoDarwin(); + + bool isSectionAtomizableBySymbols(const MCSection &Section) const override; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCASMINFODARWIN_H diff --git a/clang-r353983/include/llvm/MC/MCAsmInfoELF.h b/clang-r353983/include/llvm/MC/MCAsmInfoELF.h new file mode 100644 index 00000000..aa2e5873 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCAsmInfoELF.h @@ -0,0 +1,30 @@ +//===- llvm/MC/MCAsmInfoELF.h - ELF Asm info --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMINFOELF_H +#define LLVM_MC_MCASMINFOELF_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + +class MCAsmInfoELF : public MCAsmInfo { + virtual void anchor(); + MCSection *getNonexecutableStackSection(MCContext &Ctx) const final; + +protected: + /// Targets which have non-executable stacks by default can set this to false + /// to disable the special section which requests a non-executable stack. + bool UsesNonexecutableStackSection = true; + + MCAsmInfoELF(); +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCASMINFOELF_H diff --git a/clang-r353983/include/llvm/MC/MCAsmInfoWasm.h b/clang-r353983/include/llvm/MC/MCAsmInfoWasm.h new file mode 100644 index 00000000..3afc610b --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCAsmInfoWasm.h @@ -0,0 +1,23 @@ +//===-- llvm/MC/MCAsmInfoWasm.h - Wasm Asm info -----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMINFOWASM_H +#define LLVM_MC_MCASMINFOWASM_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { +class MCAsmInfoWasm : public MCAsmInfo { + virtual void anchor(); + +protected: + MCAsmInfoWasm(); +}; +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCAsmLayout.h b/clang-r353983/include/llvm/MC/MCAsmLayout.h new file mode 100644 index 00000000..45ac96f0 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCAsmLayout.h @@ -0,0 +1,106 @@ +//===- MCAsmLayout.h - Assembly Layout Object -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMLAYOUT_H +#define LLVM_MC_MCASMLAYOUT_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { +class MCAssembler; +class MCFragment; +class MCSection; +class MCSymbol; + +/// Encapsulates the layout of an assembly file at a particular point in time. +/// +/// Assembly may require computing multiple layouts for a particular assembly +/// file as part of the relaxation process. This class encapsulates the layout +/// at a single point in time in such a way that it is always possible to +/// efficiently compute the exact address of any symbol in the assembly file, +/// even during the relaxation process. +class MCAsmLayout { + MCAssembler &Assembler; + + /// List of sections in layout order. + llvm::SmallVector<MCSection *, 16> SectionOrder; + + /// The last fragment which was laid out, or 0 if nothing has been laid + /// out. Fragments are always laid out in order, so all fragments with a + /// lower ordinal will be valid. + mutable DenseMap<const MCSection *, MCFragment *> LastValidFragment; + + /// Make sure that the layout for the given fragment is valid, lazily + /// computing it if necessary. + void ensureValid(const MCFragment *F) const; + + /// Is the layout for this fragment valid? + bool isFragmentValid(const MCFragment *F) const; + +public: + MCAsmLayout(MCAssembler &Assembler); + + /// Get the assembler object this is a layout for. + MCAssembler &getAssembler() const { return Assembler; } + + /// Invalidate the fragments starting with F because it has been + /// resized. The fragment's size should have already been updated, but + /// its bundle padding will be recomputed. + void invalidateFragmentsFrom(MCFragment *F); + + /// Perform layout for a single fragment, assuming that the previous + /// fragment has already been laid out correctly, and the parent section has + /// been initialized. + void layoutFragment(MCFragment *Fragment); + + /// \name Section Access (in layout order) + /// @{ + + llvm::SmallVectorImpl<MCSection *> &getSectionOrder() { return SectionOrder; } + const llvm::SmallVectorImpl<MCSection *> &getSectionOrder() const { + return SectionOrder; + } + + /// @} + /// \name Fragment Layout Data + /// @{ + + /// Get the offset of the given fragment inside its containing section. + uint64_t getFragmentOffset(const MCFragment *F) const; + + /// @} + /// \name Utility Functions + /// @{ + + /// Get the address space size of the given section, as it effects + /// layout. This may differ from the size reported by \see getSectionSize() by + /// not including section tail padding. + uint64_t getSectionAddressSize(const MCSection *Sec) const; + + /// Get the data size of the given section, as emitted to the object + /// file. This may include additional padding, or be 0 for virtual sections. + uint64_t getSectionFileSize(const MCSection *Sec) const; + + /// Get the offset of the given symbol, as computed in the current + /// layout. + /// \return True on success. + bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const; + + /// Variant that reports a fatal error if the offset is not computable. + uint64_t getSymbolOffset(const MCSymbol &S) const; + + /// If this symbol is equivalent to A + Constant, return A. + const MCSymbol *getBaseSymbol(const MCSymbol &Symbol) const; + + /// @} +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCAsmMacro.h b/clang-r353983/include/llvm/MC/MCAsmMacro.h new file mode 100644 index 00000000..364d3b5f --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCAsmMacro.h @@ -0,0 +1,157 @@ +//===- MCAsmMacro.h - Assembly Macros ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMMACRO_H +#define LLVM_MC_MCASMMACRO_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/SMLoc.h" +#include <vector> + +namespace llvm { + +/// Target independent representation for an assembler token. +class AsmToken { +public: + enum TokenKind { + // Markers + Eof, Error, + + // String values. + Identifier, + String, + + // Integer values. + Integer, + BigNum, // larger than 64 bits + + // Real values. + Real, + + // Comments + Comment, + HashDirective, + // No-value. + EndOfStatement, + Colon, + Space, + Plus, Minus, Tilde, + Slash, // '/' + BackSlash, // '\' + LParen, RParen, LBrac, RBrac, LCurly, RCurly, + Star, Dot, Comma, Dollar, Equal, EqualEqual, + + Pipe, PipePipe, Caret, + Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash, + Less, LessEqual, LessLess, LessGreater, + Greater, GreaterEqual, GreaterGreater, At, MinusGreater, + + // MIPS unary expression operators such as %neg. + PercentCall16, PercentCall_Hi, PercentCall_Lo, PercentDtprel_Hi, + PercentDtprel_Lo, PercentGot, PercentGot_Disp, PercentGot_Hi, PercentGot_Lo, + PercentGot_Ofst, PercentGot_Page, PercentGottprel, PercentGp_Rel, PercentHi, + PercentHigher, PercentHighest, PercentLo, PercentNeg, PercentPcrel_Hi, + PercentPcrel_Lo, PercentTlsgd, PercentTlsldm, PercentTprel_Hi, + PercentTprel_Lo + }; + +private: + TokenKind Kind; + + /// A reference to the entire token contents; this is always a pointer into + /// a memory buffer owned by the source manager. + StringRef Str; + + APInt IntVal; + +public: + AsmToken() = default; + AsmToken(TokenKind Kind, StringRef Str, APInt IntVal) + : Kind(Kind), Str(Str), IntVal(std::move(IntVal)) {} + AsmToken(TokenKind Kind, StringRef Str, int64_t IntVal = 0) + : Kind(Kind), Str(Str), IntVal(64, IntVal, true) {} + + TokenKind getKind() const { return Kind; } + bool is(TokenKind K) const { return Kind == K; } + bool isNot(TokenKind K) const { return Kind != K; } + + SMLoc getLoc() const; + SMLoc getEndLoc() const; + SMRange getLocRange() const; + + /// Get the contents of a string token (without quotes). + StringRef getStringContents() const { + assert(Kind == String && "This token isn't a string!"); + return Str.slice(1, Str.size() - 1); + } + + /// Get the identifier string for the current token, which should be an + /// identifier or a string. This gets the portion of the string which should + /// be used as the identifier, e.g., it does not include the quotes on + /// strings. + StringRef getIdentifier() const { + if (Kind == Identifier) + return getString(); + return getStringContents(); + } + + /// Get the string for the current token, this includes all characters (for + /// example, the quotes on strings) in the token. + /// + /// The returned StringRef points into the source manager's memory buffer, and + /// is safe to store across calls to Lex(). + StringRef getString() const { return Str; } + + // FIXME: Don't compute this in advance, it makes every token larger, and is + // also not generally what we want (it is nicer for recovery etc. to lex 123br + // as a single token, then diagnose as an invalid number). + int64_t getIntVal() const { + assert(Kind == Integer && "This token isn't an integer!"); + return IntVal.getZExtValue(); + } + + APInt getAPIntVal() const { + assert((Kind == Integer || Kind == BigNum) && + "This token isn't an integer!"); + return IntVal; + } + + void dump(raw_ostream &OS) const; + void dump() const { dump(dbgs()); } +}; + +struct MCAsmMacroParameter { + StringRef Name; + std::vector<AsmToken> Value; + bool Required = false; + bool Vararg = false; + + MCAsmMacroParameter() = default; + + void dump() const { dump(dbgs()); } + void dump(raw_ostream &OS) const; +}; + +typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters; +struct MCAsmMacro { + StringRef Name; + StringRef Body; + MCAsmMacroParameters Parameters; + +public: + MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P) + : Name(N), Body(B), Parameters(std::move(P)) {} + + void dump() const { dump(dbgs()); } + void dump(raw_ostream &OS) const; +}; +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCAssembler.h b/clang-r353983/include/llvm/MC/MCAssembler.h new file mode 100644 index 00000000..45430189 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCAssembler.h @@ -0,0 +1,468 @@ +//===- MCAssembler.h - Object File Generation -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASSEMBLER_H +#define LLVM_MC_MCASSEMBLER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFragment.h" +#include "llvm/MC/MCLinkerOptimizationHint.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/VersionTuple.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + +class MCAsmBackend; +class MCAsmLayout; +class MCContext; +class MCCodeEmitter; +class MCFragment; +class MCObjectWriter; +class MCSection; +class MCValue; + +// FIXME: This really doesn't belong here. See comments below. +struct IndirectSymbolData { + MCSymbol *Symbol; + MCSection *Section; +}; + +// FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk +// to one another. +struct DataRegionData { + // This enum should be kept in sync w/ the mach-o definition in + // llvm/Object/MachOFormat.h. + enum KindTy { Data = 1, JumpTable8, JumpTable16, JumpTable32 } Kind; + MCSymbol *Start; + MCSymbol *End; +}; + +class MCAssembler { + friend class MCAsmLayout; + +public: + using SectionListType = std::vector<MCSection *>; + using SymbolDataListType = std::vector<const MCSymbol *>; + + using const_iterator = pointee_iterator<SectionListType::const_iterator>; + using iterator = pointee_iterator<SectionListType::iterator>; + + using const_symbol_iterator = + pointee_iterator<SymbolDataListType::const_iterator>; + using symbol_iterator = pointee_iterator<SymbolDataListType::iterator>; + + using symbol_range = iterator_range<symbol_iterator>; + using const_symbol_range = iterator_range<const_symbol_iterator>; + + using const_indirect_symbol_iterator = + std::vector<IndirectSymbolData>::const_iterator; + using indirect_symbol_iterator = std::vector<IndirectSymbolData>::iterator; + + using const_data_region_iterator = + std::vector<DataRegionData>::const_iterator; + using data_region_iterator = std::vector<DataRegionData>::iterator; + + /// MachO specific deployment target version info. + // A Major version of 0 indicates that no version information was supplied + // and so the corresponding load command should not be emitted. + using VersionInfoType = struct { + bool EmitBuildVersion; + union { + MCVersionMinType Type; ///< Used when EmitBuildVersion==false. + MachO::PlatformType Platform; ///< Used when EmitBuildVersion==true. + } TypeOrPlatform; + unsigned Major; + unsigned Minor; + unsigned Update; + /// An optional version of the SDK that was used to build the source. + VersionTuple SDKVersion; + }; + +private: + MCContext &Context; + + std::unique_ptr<MCAsmBackend> Backend; + + std::unique_ptr<MCCodeEmitter> Emitter; + + std::unique_ptr<MCObjectWriter> Writer; + + SectionListType Sections; + + SymbolDataListType Symbols; + + std::vector<IndirectSymbolData> IndirectSymbols; + + std::vector<DataRegionData> DataRegions; + + /// The list of linker options to propagate into the object file. + std::vector<std::vector<std::string>> LinkerOptions; + + /// List of declared file names + std::vector<std::string> FileNames; + + MCDwarfLineTableParams LTParams; + + /// The set of function symbols for which a .thumb_func directive has + /// been seen. + // + // FIXME: We really would like this in target specific code rather than + // here. Maybe when the relocation stuff moves to target specific, + // this can go with it? The streamer would need some target specific + // refactoring too. + mutable SmallPtrSet<const MCSymbol *, 32> ThumbFuncs; + + /// The bundle alignment size currently set in the assembler. + /// + /// By default it's 0, which means bundling is disabled. + unsigned BundleAlignSize; + + bool RelaxAll : 1; + bool SubsectionsViaSymbols : 1; + bool IncrementalLinkerCompatible : 1; + + /// ELF specific e_header flags + // It would be good if there were an MCELFAssembler class to hold this. + // ELF header flags are used both by the integrated and standalone assemblers. + // Access to the flags is necessary in cases where assembler directives affect + // which flags to be set. + unsigned ELFHeaderEFlags; + + /// Used to communicate Linker Optimization Hint information between + /// the Streamer and the .o writer + MCLOHContainer LOHContainer; + + VersionInfoType VersionInfo; + + /// Evaluate a fixup to a relocatable expression and the value which should be + /// placed into the fixup. + /// + /// \param Layout The layout to use for evaluation. + /// \param Fixup The fixup to evaluate. + /// \param DF The fragment the fixup is inside. + /// \param Target [out] On return, the relocatable expression the fixup + /// evaluates to. + /// \param Value [out] On return, the value of the fixup as currently laid + /// out. + /// \param WasForced [out] On return, the value in the fixup is set to the + /// correct value if WasForced is true, even if evaluateFixup returns false. + /// \return Whether the fixup value was fully resolved. This is true if the + /// \p Value result is fixed, otherwise the value may change due to + /// relocation. + bool evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, + const MCFragment *DF, MCValue &Target, + uint64_t &Value, bool &WasForced) const; + + /// Check whether a fixup can be satisfied, or whether it needs to be relaxed + /// (increased in size, in order to hold its value correctly). + bool fixupNeedsRelaxation(const MCFixup &Fixup, const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const; + + /// Check whether the given fragment needs relaxation. + bool fragmentNeedsRelaxation(const MCRelaxableFragment *IF, + const MCAsmLayout &Layout) const; + + /// Perform one layout iteration and return true if any offsets + /// were adjusted. + bool layoutOnce(MCAsmLayout &Layout); + + /// Perform one layout iteration of the given section and return true + /// if any offsets were adjusted. + bool layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec); + + bool relaxInstruction(MCAsmLayout &Layout, MCRelaxableFragment &IF); + + bool relaxPaddingFragment(MCAsmLayout &Layout, MCPaddingFragment &PF); + + bool relaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF); + + bool relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF); + bool relaxDwarfCallFrameFragment(MCAsmLayout &Layout, + MCDwarfCallFrameFragment &DF); + bool relaxCVInlineLineTable(MCAsmLayout &Layout, + MCCVInlineLineTableFragment &DF); + bool relaxCVDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &DF); + + /// finishLayout - Finalize a layout, including fragment lowering. + void finishLayout(MCAsmLayout &Layout); + + std::tuple<MCValue, uint64_t, bool> + handleFixup(const MCAsmLayout &Layout, MCFragment &F, const MCFixup &Fixup); + +public: + std::vector<std::pair<StringRef, const MCSymbol *>> Symvers; + + /// Construct a new assembler instance. + // + // FIXME: How are we going to parameterize this? Two obvious options are stay + // concrete and require clients to pass in a target like object. The other + // option is to make this abstract, and have targets provide concrete + // implementations as we do with AsmParser. + MCAssembler(MCContext &Context, std::unique_ptr<MCAsmBackend> Backend, + std::unique_ptr<MCCodeEmitter> Emitter, + std::unique_ptr<MCObjectWriter> Writer); + MCAssembler(const MCAssembler &) = delete; + MCAssembler &operator=(const MCAssembler &) = delete; + ~MCAssembler(); + + /// Compute the effective fragment size assuming it is laid out at the given + /// \p SectionAddress and \p FragmentOffset. + uint64_t computeFragmentSize(const MCAsmLayout &Layout, + const MCFragment &F) const; + + /// Find the symbol which defines the atom containing the given symbol, or + /// null if there is no such symbol. + const MCSymbol *getAtom(const MCSymbol &S) const; + + /// Check whether a particular symbol is visible to the linker and is required + /// in the symbol table, or whether it can be discarded by the assembler. This + /// also effects whether the assembler treats the label as potentially + /// defining a separate atom. + bool isSymbolLinkerVisible(const MCSymbol &SD) const; + + /// Emit the section contents to \p OS. + void writeSectionData(raw_ostream &OS, const MCSection *Section, + const MCAsmLayout &Layout) const; + + /// Check whether a given symbol has been flagged with .thumb_func. + bool isThumbFunc(const MCSymbol *Func) const; + + /// Flag a function symbol as the target of a .thumb_func directive. + void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); } + + /// ELF e_header flags + unsigned getELFHeaderEFlags() const { return ELFHeaderEFlags; } + void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags; } + + /// MachO deployment target version information. + const VersionInfoType &getVersionInfo() const { return VersionInfo; } + void setVersionMin(MCVersionMinType Type, unsigned Major, unsigned Minor, + unsigned Update, + VersionTuple SDKVersion = VersionTuple()) { + VersionInfo.EmitBuildVersion = false; + VersionInfo.TypeOrPlatform.Type = Type; + VersionInfo.Major = Major; + VersionInfo.Minor = Minor; + VersionInfo.Update = Update; + VersionInfo.SDKVersion = SDKVersion; + } + void setBuildVersion(MachO::PlatformType Platform, unsigned Major, + unsigned Minor, unsigned Update, + VersionTuple SDKVersion = VersionTuple()) { + VersionInfo.EmitBuildVersion = true; + VersionInfo.TypeOrPlatform.Platform = Platform; + VersionInfo.Major = Major; + VersionInfo.Minor = Minor; + VersionInfo.Update = Update; + VersionInfo.SDKVersion = SDKVersion; + } + + /// Reuse an assembler instance + /// + void reset(); + + MCContext &getContext() const { return Context; } + + MCAsmBackend *getBackendPtr() const { return Backend.get(); } + + MCCodeEmitter *getEmitterPtr() const { return Emitter.get(); } + + MCObjectWriter *getWriterPtr() const { return Writer.get(); } + + MCAsmBackend &getBackend() const { return *Backend; } + + MCCodeEmitter &getEmitter() const { return *Emitter; } + + MCObjectWriter &getWriter() const { return *Writer; } + + MCDwarfLineTableParams getDWARFLinetableParams() const { return LTParams; } + void setDWARFLinetableParams(MCDwarfLineTableParams P) { LTParams = P; } + + /// Finish - Do final processing and write the object to the output stream. + /// \p Writer is used for custom object writer (as the MCJIT does), + /// if not specified it is automatically created from backend. + void Finish(); + + // Layout all section and prepare them for emission. + void layout(MCAsmLayout &Layout); + + // FIXME: This does not belong here. + bool getSubsectionsViaSymbols() const { return SubsectionsViaSymbols; } + void setSubsectionsViaSymbols(bool Value) { SubsectionsViaSymbols = Value; } + + bool isIncrementalLinkerCompatible() const { + return IncrementalLinkerCompatible; + } + void setIncrementalLinkerCompatible(bool Value) { + IncrementalLinkerCompatible = Value; + } + + bool getRelaxAll() const { return RelaxAll; } + void setRelaxAll(bool Value) { RelaxAll = Value; } + + bool isBundlingEnabled() const { return BundleAlignSize != 0; } + + unsigned getBundleAlignSize() const { return BundleAlignSize; } + + void setBundleAlignSize(unsigned Size) { + assert((Size == 0 || !(Size & (Size - 1))) && + "Expect a power-of-two bundle align size"); + BundleAlignSize = Size; + } + + /// \name Section List Access + /// @{ + + iterator begin() { return Sections.begin(); } + const_iterator begin() const { return Sections.begin(); } + + iterator end() { return Sections.end(); } + const_iterator end() const { return Sections.end(); } + + size_t size() const { return Sections.size(); } + + /// @} + /// \name Symbol List Access + /// @{ + symbol_iterator symbol_begin() { return Symbols.begin(); } + const_symbol_iterator symbol_begin() const { return Symbols.begin(); } + + symbol_iterator symbol_end() { return Symbols.end(); } + const_symbol_iterator symbol_end() const { return Symbols.end(); } + + symbol_range symbols() { return make_range(symbol_begin(), symbol_end()); } + const_symbol_range symbols() const { + return make_range(symbol_begin(), symbol_end()); + } + + size_t symbol_size() const { return Symbols.size(); } + + /// @} + /// \name Indirect Symbol List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + std::vector<IndirectSymbolData> &getIndirectSymbols() { + return IndirectSymbols; + } + + indirect_symbol_iterator indirect_symbol_begin() { + return IndirectSymbols.begin(); + } + const_indirect_symbol_iterator indirect_symbol_begin() const { + return IndirectSymbols.begin(); + } + + indirect_symbol_iterator indirect_symbol_end() { + return IndirectSymbols.end(); + } + const_indirect_symbol_iterator indirect_symbol_end() const { + return IndirectSymbols.end(); + } + + size_t indirect_symbol_size() const { return IndirectSymbols.size(); } + + /// @} + /// \name Linker Option List Access + /// @{ + + std::vector<std::vector<std::string>> &getLinkerOptions() { + return LinkerOptions; + } + + /// @} + /// \name Data Region List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + std::vector<DataRegionData> &getDataRegions() { return DataRegions; } + + data_region_iterator data_region_begin() { return DataRegions.begin(); } + const_data_region_iterator data_region_begin() const { + return DataRegions.begin(); + } + + data_region_iterator data_region_end() { return DataRegions.end(); } + const_data_region_iterator data_region_end() const { + return DataRegions.end(); + } + + size_t data_region_size() const { return DataRegions.size(); } + + /// @} + /// \name Data Region List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + MCLOHContainer &getLOHContainer() { return LOHContainer; } + const MCLOHContainer &getLOHContainer() const { + return const_cast<MCAssembler *>(this)->getLOHContainer(); + } + + struct CGProfileEntry { + const MCSymbolRefExpr *From; + const MCSymbolRefExpr *To; + uint64_t Count; + }; + std::vector<CGProfileEntry> CGProfile; + /// @} + /// \name Backend Data Access + /// @{ + + bool registerSection(MCSection &Section); + + void registerSymbol(const MCSymbol &Symbol, bool *Created = nullptr); + + ArrayRef<std::string> getFileNames() { return FileNames; } + + void addFileName(StringRef FileName) { + if (!is_contained(FileNames, FileName)) + FileNames.push_back(FileName); + } + + /// Write the necessary bundle padding to \p OS. + /// Expects a fragment \p F containing instructions and its size \p FSize. + void writeFragmentPadding(raw_ostream &OS, const MCEncodedFragment &F, + uint64_t FSize) const; + + /// @} + + void dump() const; +}; + +/// Compute the amount of padding required before the fragment \p F to +/// obey bundling restrictions, where \p FOffset is the fragment's offset in +/// its section and \p FSize is the fragment's size. +uint64_t computeBundlePadding(const MCAssembler &Assembler, + const MCEncodedFragment *F, uint64_t FOffset, + uint64_t FSize); + +} // end namespace llvm + +#endif // LLVM_MC_MCASSEMBLER_H diff --git a/clang-r353983/include/llvm/MC/MCCodeEmitter.h b/clang-r353983/include/llvm/MC/MCCodeEmitter.h new file mode 100644 index 00000000..04b4367a --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCCodeEmitter.h @@ -0,0 +1,42 @@ +//===- llvm/MC/MCCodeEmitter.h - Instruction Encoding -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCCODEEMITTER_H +#define LLVM_MC_MCCODEEMITTER_H + +namespace llvm { + +class MCFixup; +class MCInst; +class MCSubtargetInfo; +class raw_ostream; +template<typename T> class SmallVectorImpl; + +/// MCCodeEmitter - Generic instruction encoding interface. +class MCCodeEmitter { +protected: // Can only create subclasses. + MCCodeEmitter(); + +public: + MCCodeEmitter(const MCCodeEmitter &) = delete; + MCCodeEmitter &operator=(const MCCodeEmitter &) = delete; + virtual ~MCCodeEmitter(); + + /// Lifetime management + virtual void reset() {} + + /// EncodeInstruction - Encode the given \p Inst to bytes on the output + /// stream \p OS. + virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const = 0; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCCODEEMITTER_H diff --git a/clang-r353983/include/llvm/MC/MCCodePadder.h b/clang-r353983/include/llvm/MC/MCCodePadder.h new file mode 100644 index 00000000..f7b1a211 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCCodePadder.h @@ -0,0 +1,241 @@ +//===- llvm/MC/MCCodePadder.h - MC Code Padder ------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCCODEPADDER_H +#define LLVM_MC_MCCODEPADDER_H + +#include "MCFragment.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class MCAsmLayout; +class MCCodePaddingPolicy; +class MCFragment; +class MCInst; +class MCObjectStreamer; +class MCSection; + +typedef SmallVector<const MCPaddingFragment *, 8> MCPFRange; + +struct MCCodePaddingContext { + bool IsPaddingActive; + bool IsBasicBlockReachableViaFallthrough; + bool IsBasicBlockReachableViaBranch; +}; + +/// Target-independent base class incharge of all code padding decisions for a +/// target. During encoding it determines if and where MCPaddingFragments will +/// be located, as later on, when layout information is available, it determines +/// their sizes. +class MCCodePadder { + MCCodePadder(const MCCodePadder &) = delete; + void operator=(const MCCodePadder &) = delete; + + /// Determines if the MCCodePaddingPolicies are active. + bool ArePoliciesActive; + + /// All the supported MCCodePaddingPolicies. + SmallPtrSet<MCCodePaddingPolicy *, 4> CodePaddingPolicies; + + /// A pointer to the fragment of the instruction whose padding is currently + /// done for. + MCPaddingFragment *CurrHandledInstFragment; + + /// A map holding the jurisdiction for each padding fragment. Key: padding + /// fragment. Value: The fragment's jurisdiction. A jurisdiction is a vector + /// of padding fragments whose conditions are being controlled by another + /// fragment, the key fragment. + DenseMap<MCPaddingFragment *, MCPFRange> FragmentToJurisdiction; + MCPFRange &getJurisdiction(MCPaddingFragment *Fragment, MCAsmLayout &Layout); + + /// A map holding the maximal instruction window size relevant for a padding + /// fragment. + DenseMap<MCPaddingFragment *, uint64_t> FragmentToMaxWindowSize; + uint64_t getMaxWindowSize(MCPaddingFragment *Fragment, MCAsmLayout &Layout); + +protected: + /// The current streamer, used to stream code padding. + MCObjectStreamer *OS; + + bool addPolicy(MCCodePaddingPolicy *Policy); + + virtual bool + basicBlockRequiresInsertionPoint(const MCCodePaddingContext &Context) { + return false; + } + + virtual bool instructionRequiresInsertionPoint(const MCInst &Inst) { + return false; + } + + virtual bool usePoliciesForBasicBlock(const MCCodePaddingContext &Context) { + return Context.IsPaddingActive; + } + +public: + MCCodePadder() + : ArePoliciesActive(false), CurrHandledInstFragment(nullptr), + OS(nullptr) {} + virtual ~MCCodePadder(); + + /// Handles all target related code padding when starting to write a new + /// basic block to an object file. + /// + /// \param OS The streamer used for writing the padding data and function. + /// \param Context the context of the padding, Embeds the basic block's + /// parameters. + void handleBasicBlockStart(MCObjectStreamer *OS, + const MCCodePaddingContext &Context); + /// Handles all target related code padding when done writing a block to an + /// object file. + /// + /// \param Context the context of the padding, Embeds the basic block's + /// parameters. + void handleBasicBlockEnd(const MCCodePaddingContext &Context); + /// Handles all target related code padding before writing a new instruction + /// to an object file. + /// + /// \param Inst the instruction. + void handleInstructionBegin(const MCInst &Inst); + /// Handles all target related code padding after writing an instruction to an + /// object file. + /// + /// \param Inst the instruction. + void handleInstructionEnd(const MCInst &Inst); + + /// Relaxes a fragment (changes the size of the padding) according to target + /// requirements. The new size computation is done w.r.t a layout. + /// + /// \param Fragment The fragment to relax. + /// \param Layout Code layout information. + /// + /// \returns true iff any relaxation occurred. + bool relaxFragment(MCPaddingFragment *Fragment, MCAsmLayout &Layout); +}; + +/// The base class for all padding policies, i.e. a rule or set of rules to pad +/// the generated code. +class MCCodePaddingPolicy { + MCCodePaddingPolicy() = delete; + MCCodePaddingPolicy(const MCCodePaddingPolicy &) = delete; + void operator=(const MCCodePaddingPolicy &) = delete; + +protected: + /// A mask holding the kind of this policy, i.e. only the i'th bit will be set + /// where i is the kind number. + const uint64_t KindMask; + /// Instruction window size relevant to this policy. + const uint64_t WindowSize; + /// A boolean indicating which byte of the instruction determies its + /// instruction window. If true - the last byte of the instructions, o.w. - + /// the first byte of the instruction. + const bool InstByteIsLastByte; + + MCCodePaddingPolicy(uint64_t Kind, uint64_t WindowSize, + bool InstByteIsLastByte) + : KindMask(UINT64_C(1) << Kind), WindowSize(WindowSize), + InstByteIsLastByte(InstByteIsLastByte) {} + + /// Computes and returns the offset of the consecutive fragment of a given + /// fragment. + /// + /// \param Fragment The fragment whose consecutive offset will be computed. + /// \param Layout Code layout information. + /// + /// \returns the offset of the consecutive fragment of \p Fragment. + static uint64_t getNextFragmentOffset(const MCFragment *Fragment, + const MCAsmLayout &Layout); + /// Returns the instruction byte of an instruction pointed by a given + /// MCPaddingFragment. An instruction byte is the address of the byte of an + /// instruction which determines its instruction window. + /// + /// \param Fragment The fragment pointing to the instruction. + /// \param Layout Code layout information. + /// + /// \returns the instruction byte of an instruction pointed by \p Fragment. + uint64_t getFragmentInstByte(const MCPaddingFragment *Fragment, + MCAsmLayout &Layout) const; + uint64_t computeWindowEndAddress(const MCPaddingFragment *Fragment, + uint64_t Offset, MCAsmLayout &Layout) const; + + /// Computes and returns the penalty weight of a first instruction window in a + /// range. This requires a special function since the first window does not + /// contain all the padding fragments in that window. It only contains all the + /// padding fragments starting from the relevant insertion point. + /// + /// \param Window The first window. + /// \param Offset The offset of the parent section relative to the beginning + /// of the file, mod the window size. + /// \param Layout Code layout information. + /// + /// \returns the penalty weight of a first instruction window in a range, \p + /// Window. + double computeFirstWindowPenaltyWeight(const MCPFRange &Window, + uint64_t Offset, + MCAsmLayout &Layout) const; + /// Computes and returns the penalty caused by an instruction window. + /// + /// \param Window The instruction window. + /// \param Offset The offset of the parent section relative to the beginning + /// of the file, mod the window size. + /// \param Layout Code layout information. + /// + /// \returns the penalty caused by \p Window. + virtual double computeWindowPenaltyWeight(const MCPFRange &Window, + uint64_t Offset, + MCAsmLayout &Layout) const = 0; + +public: + virtual ~MCCodePaddingPolicy() {} + + /// Returns the kind mask of this policy - A mask holding the kind of this + /// policy, i.e. only the i'th bit will be set where i is the kind number. + uint64_t getKindMask() const { return KindMask; } + /// Returns the instruction window size relevant to this policy. + uint64_t getWindowSize() const { return WindowSize; } + /// Returns true if the last byte of an instruction determines its instruction + /// window, or false if the first of an instruction determines it. + bool isInstByteLastByte() const { return InstByteIsLastByte; } + + /// Returns true iff this policy needs padding for a given basic block. + /// + /// \param Context the context of the padding, Embeds the basic block's + /// parameters. + /// + /// \returns true iff this policy needs padding for the basic block. + virtual bool + basicBlockRequiresPaddingFragment(const MCCodePaddingContext &Context) const { + return false; + } + /// Returns true iff this policy needs padding for a given instruction. + /// + /// \param Inst The given instruction. + /// + /// \returns true iff this policy needs padding for \p Inst. + virtual bool instructionRequiresPaddingFragment(const MCInst &Inst) const { + return false; + } + /// Computes and returns the penalty caused by a range of instruction windows. + /// The weight is computed for each window separelty and then accumulated. + /// + /// \param Range The range. + /// \param Offset The offset of the parent section relative to the beginning + /// of the file, mod the window size. + /// \param Layout Code layout information. + /// + /// \returns the penalty caused by \p Range. + double computeRangePenaltyWeight(const MCPFRange &Range, uint64_t Offset, + MCAsmLayout &Layout) const; +}; + +} // namespace llvm + +#endif // LLVM_MC_MCCODEPADDER_H diff --git a/clang-r353983/include/llvm/MC/MCCodeView.h b/clang-r353983/include/llvm/MC/MCCodeView.h new file mode 100644 index 00000000..2126354c --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCCodeView.h @@ -0,0 +1,264 @@ +//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Holds state from .cv_file and .cv_loc directives for later emission. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCCODEVIEW_H +#define LLVM_MC_MCCODEVIEW_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCFragment.h" +#include "llvm/MC/MCObjectStreamer.h" +#include <map> +#include <vector> + +namespace llvm { +class MCContext; +class MCObjectStreamer; +class MCStreamer; +class CodeViewContext; + +/// Instances of this class represent the information from a +/// .cv_loc directive. +class MCCVLoc { + const MCSymbol *Label = nullptr; + uint32_t FunctionId; + uint32_t FileNum; + uint32_t Line; + uint16_t Column; + uint16_t PrologueEnd : 1; + uint16_t IsStmt : 1; + +private: // CodeViewContext manages these + friend class CodeViewContext; + MCCVLoc(const MCSymbol *Label, unsigned functionid, unsigned fileNum, + unsigned line, unsigned column, bool prologueend, bool isstmt) + : Label(Label), FunctionId(functionid), FileNum(fileNum), Line(line), + Column(column), PrologueEnd(prologueend), IsStmt(isstmt) {} + + // Allow the default copy constructor and assignment operator to be used + // for an MCCVLoc object. + +public: + const MCSymbol *getLabel() const { return Label; } + + unsigned getFunctionId() const { return FunctionId; } + + /// Get the FileNum of this MCCVLoc. + unsigned getFileNum() const { return FileNum; } + + /// Get the Line of this MCCVLoc. + unsigned getLine() const { return Line; } + + /// Get the Column of this MCCVLoc. + unsigned getColumn() const { return Column; } + + bool isPrologueEnd() const { return PrologueEnd; } + bool isStmt() const { return IsStmt; } + + void setLabel(const MCSymbol *L) { Label = L; } + + void setFunctionId(unsigned FID) { FunctionId = FID; } + + /// Set the FileNum of this MCCVLoc. + void setFileNum(unsigned fileNum) { FileNum = fileNum; } + + /// Set the Line of this MCCVLoc. + void setLine(unsigned line) { Line = line; } + + /// Set the Column of this MCCVLoc. + void setColumn(unsigned column) { + assert(column <= UINT16_MAX); + Column = column; + } + + void setPrologueEnd(bool PE) { PrologueEnd = PE; } + void setIsStmt(bool IS) { IsStmt = IS; } +}; + +/// Information describing a function or inlined call site introduced by +/// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc +/// directives used with this function's id or the id of an inlined call site +/// within this function or inlined call site. +struct MCCVFunctionInfo { + /// If this represents an inlined call site, then ParentFuncIdPlusOne will be + /// the parent function id plus one. If this represents a normal function, + /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel. + /// If this struct is an unallocated slot in the function info vector, then + /// ParentFuncIdPlusOne will be zero. + unsigned ParentFuncIdPlusOne = 0; + + enum : unsigned { FunctionSentinel = ~0U }; + + struct LineInfo { + unsigned File; + unsigned Line; + unsigned Col; + }; + + LineInfo InlinedAt; + + /// The section of the first .cv_loc directive used for this function, or null + /// if none has been seen yet. + MCSection *Section = nullptr; + + /// Map from inlined call site id to the inlined at location to use for that + /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h', + /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both + /// list the line info for the 'g' call site. + DenseMap<unsigned, LineInfo> InlinedAtMap; + + /// Returns true if this is function info has not yet been used in a + /// .cv_func_id or .cv_inline_site_id directive. + bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; } + + /// Returns true if this represents an inlined call site, meaning + /// ParentFuncIdPlusOne is neither zero nor ~0U. + bool isInlinedCallSite() const { + return !isUnallocatedFunctionInfo() && + ParentFuncIdPlusOne != FunctionSentinel; + } + + unsigned getParentFuncId() const { + assert(isInlinedCallSite()); + return ParentFuncIdPlusOne - 1; + } +}; + +/// Holds state from .cv_file and .cv_loc directives for later emission. +class CodeViewContext { +public: + CodeViewContext(); + ~CodeViewContext(); + + bool isValidFileNumber(unsigned FileNumber) const; + bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename, + ArrayRef<uint8_t> ChecksumBytes, uint8_t ChecksumKind); + + /// Records the function id of a normal function. Returns false if the + /// function id has already been used, and true otherwise. + bool recordFunctionId(unsigned FuncId); + + /// Records the function id of an inlined call site. Records the "inlined at" + /// location info of the call site, including what function or inlined call + /// site it was inlined into. Returns false if the function id has already + /// been used, and true otherwise. + bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc, + unsigned IAFile, unsigned IALine, + unsigned IACol); + + /// Retreive the function info if this is a valid function id, or nullptr. + MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId); + + /// Saves the information from the currently parsed .cv_loc directive + /// and sets CVLocSeen. When the next instruction is assembled an entry + /// in the line number table with this information and the address of the + /// instruction will be created. + void recordCVLoc(MCContext &Ctx, const MCSymbol *Label, unsigned FunctionId, + unsigned FileNo, unsigned Line, unsigned Column, + bool PrologueEnd, bool IsStmt); + + bool isValidCVFileNumber(unsigned FileNumber); + + /// Add a line entry. + void addLineEntry(const MCCVLoc &LineEntry); + + std::vector<MCCVLoc> getFunctionLineEntries(unsigned FuncId); + + std::pair<size_t, size_t> getLineExtent(unsigned FuncId); + + ArrayRef<MCCVLoc> getLinesForExtent(size_t L, size_t R); + + /// Emits a line table substream. + void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId, + const MCSymbol *FuncBegin, + const MCSymbol *FuncEnd); + + void emitInlineLineTableForFunction(MCObjectStreamer &OS, + unsigned PrimaryFunctionId, + unsigned SourceFileId, + unsigned SourceLineNum, + const MCSymbol *FnStartSym, + const MCSymbol *FnEndSym); + + /// Encodes the binary annotations once we have a layout. + void encodeInlineLineTable(MCAsmLayout &Layout, + MCCVInlineLineTableFragment &F); + + MCFragment * + emitDefRange(MCObjectStreamer &OS, + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + StringRef FixedSizePortion); + + void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F); + + /// Emits the string table substream. + void emitStringTable(MCObjectStreamer &OS); + + /// Emits the file checksum substream. + void emitFileChecksums(MCObjectStreamer &OS); + + /// Emits the offset into the checksum table of the given file number. + void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo); + + /// Add something to the string table. Returns the final string as well as + /// offset into the string table. + std::pair<StringRef, unsigned> addToStringTable(StringRef S); + +private: + /// Map from string to string table offset. + StringMap<unsigned> StringTable; + + /// The fragment that ultimately holds our strings. + MCDataFragment *StrTabFragment = nullptr; + bool InsertedStrTabFragment = false; + + MCDataFragment *getStringTableFragment(); + + /// Get a string table offset. + unsigned getStringTableOffset(StringRef S); + + struct FileInfo { + unsigned StringTableOffset; + + // Indicates if this FileInfo corresponds to an actual file, or hasn't been + // set yet. + bool Assigned = false; + + uint8_t ChecksumKind; + + ArrayRef<uint8_t> Checksum; + + // Checksum offset stored as a symbol because it might be requested + // before it has been calculated, so a fixup may be needed. + MCSymbol *ChecksumTableOffset; + }; + + /// Array storing added file information. + SmallVector<FileInfo, 4> Files; + + /// The offset of the first and last .cv_loc directive for a given function + /// id. + std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop; + + /// A collection of MCCVLoc for each section. + std::vector<MCCVLoc> MCCVLines; + + /// All known functions and inlined call sites, indexed by function id. + std::vector<MCCVFunctionInfo> Functions; + + /// Indicate whether we have already laid out the checksum table addresses or + /// not. + bool ChecksumOffsetsAssigned = false; +}; + +} // end namespace llvm +#endif diff --git a/clang-r353983/include/llvm/MC/MCContext.h b/clang-r353983/include/llvm/MC/MCContext.h new file mode 100644 index 00000000..b964965c --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCContext.h @@ -0,0 +1,741 @@ +//===- MCContext.h - Machine Code Context -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCCONTEXT_H +#define LLVM_MC_MCCONTEXT_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/MC/MCAsmMacro.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MD5.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + + class CodeViewContext; + class MCAsmInfo; + class MCLabel; + class MCObjectFileInfo; + class MCRegisterInfo; + class MCSection; + class MCSectionCOFF; + class MCSectionELF; + class MCSectionMachO; + class MCSectionWasm; + class MCStreamer; + class MCSymbol; + class MCSymbolELF; + class MCSymbolWasm; + class SMLoc; + class SourceMgr; + + /// Context object for machine code objects. This class owns all of the + /// sections that it creates. + /// + class MCContext { + public: + using SymbolTable = StringMap<MCSymbol *, BumpPtrAllocator &>; + + private: + /// The SourceMgr for this object, if any. + const SourceMgr *SrcMgr; + + /// The SourceMgr for inline assembly, if any. + SourceMgr *InlineSrcMgr; + + /// The MCAsmInfo for this target. + const MCAsmInfo *MAI; + + /// The MCRegisterInfo for this target. + const MCRegisterInfo *MRI; + + /// The MCObjectFileInfo for this target. + const MCObjectFileInfo *MOFI; + + std::unique_ptr<CodeViewContext> CVContext; + + /// Allocator object used for creating machine code objects. + /// + /// We use a bump pointer allocator to avoid the need to track all allocated + /// objects. + BumpPtrAllocator Allocator; + + SpecificBumpPtrAllocator<MCSectionCOFF> COFFAllocator; + SpecificBumpPtrAllocator<MCSectionELF> ELFAllocator; + SpecificBumpPtrAllocator<MCSectionMachO> MachOAllocator; + SpecificBumpPtrAllocator<MCSectionWasm> WasmAllocator; + + /// Bindings of names to symbols. + SymbolTable Symbols; + + /// A mapping from a local label number and an instance count to a symbol. + /// For example, in the assembly + /// 1: + /// 2: + /// 1: + /// We have three labels represented by the pairs (1, 0), (2, 0) and (1, 1) + DenseMap<std::pair<unsigned, unsigned>, MCSymbol *> LocalSymbols; + + /// Keeps tracks of names that were used both for used declared and + /// artificial symbols. The value is "true" if the name has been used for a + /// non-section symbol (there can be at most one of those, plus an unlimited + /// number of section symbols with the same name). + StringMap<bool, BumpPtrAllocator &> UsedNames; + + /// The next ID to dole out to an unnamed assembler temporary symbol with + /// a given prefix. + StringMap<unsigned> NextID; + + /// Instances of directional local labels. + DenseMap<unsigned, MCLabel *> Instances; + /// NextInstance() creates the next instance of the directional local label + /// for the LocalLabelVal and adds it to the map if needed. + unsigned NextInstance(unsigned LocalLabelVal); + /// GetInstance() gets the current instance of the directional local label + /// for the LocalLabelVal and adds it to the map if needed. + unsigned GetInstance(unsigned LocalLabelVal); + + /// The file name of the log file from the environment variable + /// AS_SECURE_LOG_FILE. Which must be set before the .secure_log_unique + /// directive is used or it is an error. + char *SecureLogFile; + /// The stream that gets written to for the .secure_log_unique directive. + std::unique_ptr<raw_fd_ostream> SecureLog; + /// Boolean toggled when .secure_log_unique / .secure_log_reset is seen to + /// catch errors if .secure_log_unique appears twice without + /// .secure_log_reset appearing between them. + bool SecureLogUsed = false; + + /// The compilation directory to use for DW_AT_comp_dir. + SmallString<128> CompilationDir; + + /// Prefix replacement map for source file information. + std::map<const std::string, const std::string> DebugPrefixMap; + + /// The main file name if passed in explicitly. + std::string MainFileName; + + /// The dwarf file and directory tables from the dwarf .file directive. + /// We now emit a line table for each compile unit. To reduce the prologue + /// size of each line table, the files and directories used by each compile + /// unit are separated. + std::map<unsigned, MCDwarfLineTable> MCDwarfLineTablesCUMap; + + /// The current dwarf line information from the last dwarf .loc directive. + MCDwarfLoc CurrentDwarfLoc; + bool DwarfLocSeen = false; + + /// Generate dwarf debugging info for assembly source files. + bool GenDwarfForAssembly = false; + + /// The current dwarf file number when generate dwarf debugging info for + /// assembly source files. + unsigned GenDwarfFileNumber = 0; + + /// Sections for generating the .debug_ranges and .debug_aranges sections. + SetVector<MCSection *> SectionsForRanges; + + /// The information gathered from labels that will have dwarf label + /// entries when generating dwarf assembly source files. + std::vector<MCGenDwarfLabelEntry> MCGenDwarfLabelEntries; + + /// The string to embed in the debug information for the compile unit, if + /// non-empty. + StringRef DwarfDebugFlags; + + /// The string to embed in as the dwarf AT_producer for the compile unit, if + /// non-empty. + StringRef DwarfDebugProducer; + + /// The maximum version of dwarf that we should emit. + uint16_t DwarfVersion = 4; + + /// Honor temporary labels, this is useful for debugging semantic + /// differences between temporary and non-temporary labels (primarily on + /// Darwin). + bool AllowTemporaryLabels = true; + bool UseNamesOnTempLabels = true; + + /// The Compile Unit ID that we are currently processing. + unsigned DwarfCompileUnitID = 0; + + struct ELFSectionKey { + std::string SectionName; + StringRef GroupName; + unsigned UniqueID; + + ELFSectionKey(StringRef SectionName, StringRef GroupName, + unsigned UniqueID) + : SectionName(SectionName), GroupName(GroupName), UniqueID(UniqueID) { + } + + bool operator<(const ELFSectionKey &Other) const { + if (SectionName != Other.SectionName) + return SectionName < Other.SectionName; + if (GroupName != Other.GroupName) + return GroupName < Other.GroupName; + return UniqueID < Other.UniqueID; + } + }; + + struct COFFSectionKey { + std::string SectionName; + StringRef GroupName; + int SelectionKey; + unsigned UniqueID; + + COFFSectionKey(StringRef SectionName, StringRef GroupName, + int SelectionKey, unsigned UniqueID) + : SectionName(SectionName), GroupName(GroupName), + SelectionKey(SelectionKey), UniqueID(UniqueID) {} + + bool operator<(const COFFSectionKey &Other) const { + if (SectionName != Other.SectionName) + return SectionName < Other.SectionName; + if (GroupName != Other.GroupName) + return GroupName < Other.GroupName; + if (SelectionKey != Other.SelectionKey) + return SelectionKey < Other.SelectionKey; + return UniqueID < Other.UniqueID; + } + }; + + struct WasmSectionKey { + std::string SectionName; + StringRef GroupName; + unsigned UniqueID; + + WasmSectionKey(StringRef SectionName, StringRef GroupName, + unsigned UniqueID) + : SectionName(SectionName), GroupName(GroupName), UniqueID(UniqueID) { + } + + bool operator<(const WasmSectionKey &Other) const { + if (SectionName != Other.SectionName) + return SectionName < Other.SectionName; + if (GroupName != Other.GroupName) + return GroupName < Other.GroupName; + return UniqueID < Other.UniqueID; + } + }; + + StringMap<MCSectionMachO *> MachOUniquingMap; + std::map<ELFSectionKey, MCSectionELF *> ELFUniquingMap; + std::map<COFFSectionKey, MCSectionCOFF *> COFFUniquingMap; + std::map<WasmSectionKey, MCSectionWasm *> WasmUniquingMap; + StringMap<bool> RelSecNames; + + SpecificBumpPtrAllocator<MCSubtargetInfo> MCSubtargetAllocator; + + /// Do automatic reset in destructor + bool AutoReset; + + bool HadError = false; + + MCSymbol *createSymbolImpl(const StringMapEntry<bool> *Name, + bool CanBeUnnamed); + MCSymbol *createSymbol(StringRef Name, bool AlwaysAddSuffix, + bool IsTemporary); + + MCSymbol *getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal, + unsigned Instance); + + MCSectionELF *createELFSectionImpl(StringRef Section, unsigned Type, + unsigned Flags, SectionKind K, + unsigned EntrySize, + const MCSymbolELF *Group, + unsigned UniqueID, + const MCSymbolELF *Associated); + + /// Map of currently defined macros. + StringMap<MCAsmMacro> MacroMap; + + public: + explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI, + const MCObjectFileInfo *MOFI, + const SourceMgr *Mgr = nullptr, bool DoAutoReset = true); + MCContext(const MCContext &) = delete; + MCContext &operator=(const MCContext &) = delete; + ~MCContext(); + + const SourceMgr *getSourceManager() const { return SrcMgr; } + + void setInlineSourceManager(SourceMgr *SM) { InlineSrcMgr = SM; } + + const MCAsmInfo *getAsmInfo() const { return MAI; } + + const MCRegisterInfo *getRegisterInfo() const { return MRI; } + + const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; } + + CodeViewContext &getCVContext(); + + void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; } + void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; } + + /// \name Module Lifetime Management + /// @{ + + /// reset - return object to right after construction state to prepare + /// to process a new module + void reset(); + + /// @} + + /// \name Symbol Management + /// @{ + + /// Create and return a new linker temporary symbol with a unique but + /// unspecified name. + MCSymbol *createLinkerPrivateTempSymbol(); + + /// Create and return a new assembler temporary symbol with a unique but + /// unspecified name. + MCSymbol *createTempSymbol(bool CanBeUnnamed = true); + + MCSymbol *createTempSymbol(const Twine &Name, bool AlwaysAddSuffix, + bool CanBeUnnamed = true); + + /// Create the definition of a directional local symbol for numbered label + /// (used for "1:" definitions). + MCSymbol *createDirectionalLocalSymbol(unsigned LocalLabelVal); + + /// Create and return a directional local symbol for numbered label (used + /// for "1b" or 1f" references). + MCSymbol *getDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before); + + /// Lookup the symbol inside with the specified \p Name. If it exists, + /// return it. If not, create a forward reference and return it. + /// + /// \param Name - The symbol name, which must be unique across all symbols. + MCSymbol *getOrCreateSymbol(const Twine &Name); + + /// Gets a symbol that will be defined to the final stack offset of a local + /// variable after codegen. + /// + /// \param Idx - The index of a local variable passed to \@llvm.localescape. + MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx); + + MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName); + + MCSymbol *getOrCreateLSDASymbol(StringRef FuncName); + + /// Get the symbol for \p Name, or null. + MCSymbol *lookupSymbol(const Twine &Name) const; + + /// Set value for a symbol. + void setSymbolValue(MCStreamer &Streamer, StringRef Sym, uint64_t Val); + + /// getSymbols - Get a reference for the symbol table for clients that + /// want to, for example, iterate over all symbols. 'const' because we + /// still want any modifications to the table itself to use the MCContext + /// APIs. + const SymbolTable &getSymbols() const { return Symbols; } + + /// @} + + /// \name Section Management + /// @{ + + enum : unsigned { + /// Pass this value as the UniqueID during section creation to get the + /// generic section with the given name and characteristics. The usual + /// sections such as .text use this ID. + GenericSectionID = ~0U + }; + + /// Return the MCSection for the specified mach-o section. This requires + /// the operands to be valid. + MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind K, + const char *BeginSymName = nullptr); + + MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, SectionKind K, + const char *BeginSymName = nullptr) { + return getMachOSection(Segment, Section, TypeAndAttributes, 0, K, + BeginSymName); + } + + MCSectionELF *getELFSection(const Twine &Section, unsigned Type, + unsigned Flags) { + return getELFSection(Section, Type, Flags, 0, ""); + } + + MCSectionELF *getELFSection(const Twine &Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + const Twine &Group) { + return getELFSection(Section, Type, Flags, EntrySize, Group, ~0); + } + + MCSectionELF *getELFSection(const Twine &Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + const Twine &Group, unsigned UniqueID) { + return getELFSection(Section, Type, Flags, EntrySize, Group, UniqueID, + nullptr); + } + + MCSectionELF *getELFSection(const Twine &Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + const Twine &Group, unsigned UniqueID, + const MCSymbolELF *Associated); + + MCSectionELF *getELFSection(const Twine &Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + const MCSymbolELF *Group, unsigned UniqueID, + const MCSymbolELF *Associated); + + /// Get a section with the provided group identifier. This section is + /// named by concatenating \p Prefix with '.' then \p Suffix. The \p Type + /// describes the type of the section and \p Flags are used to further + /// configure this named section. + MCSectionELF *getELFNamedSection(const Twine &Prefix, const Twine &Suffix, + unsigned Type, unsigned Flags, + unsigned EntrySize = 0); + + MCSectionELF *createELFRelSection(const Twine &Name, unsigned Type, + unsigned Flags, unsigned EntrySize, + const MCSymbolELF *Group, + const MCSectionELF *RelInfoSection); + + void renameELFSection(MCSectionELF *Section, StringRef Name); + + MCSectionELF *createELFGroupSection(const MCSymbolELF *Group); + + MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind, StringRef COMDATSymName, + int Selection, + unsigned UniqueID = GenericSectionID, + const char *BeginSymName = nullptr); + + MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind, + const char *BeginSymName = nullptr); + + MCSectionCOFF *getCOFFSection(StringRef Section); + + /// Gets or creates a section equivalent to Sec that is associated with the + /// section containing KeySym. For example, to create a debug info section + /// associated with an inline function, pass the normal debug info section + /// as Sec and the function symbol as KeySym. + MCSectionCOFF * + getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym, + unsigned UniqueID = GenericSectionID); + + MCSectionWasm *getWasmSection(const Twine &Section, SectionKind K) { + return getWasmSection(Section, K, nullptr); + } + + MCSectionWasm *getWasmSection(const Twine &Section, SectionKind K, + const char *BeginSymName) { + return getWasmSection(Section, K, "", ~0, BeginSymName); + } + + MCSectionWasm *getWasmSection(const Twine &Section, SectionKind K, + const Twine &Group, unsigned UniqueID) { + return getWasmSection(Section, K, Group, UniqueID, nullptr); + } + + MCSectionWasm *getWasmSection(const Twine &Section, SectionKind K, + const Twine &Group, unsigned UniqueID, + const char *BeginSymName); + + MCSectionWasm *getWasmSection(const Twine &Section, SectionKind K, + const MCSymbolWasm *Group, unsigned UniqueID, + const char *BeginSymName); + + // Create and save a copy of STI and return a reference to the copy. + MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI); + + /// @} + + /// \name Dwarf Management + /// @{ + + /// Get the compilation directory for DW_AT_comp_dir + /// The compilation directory should be set with \c setCompilationDir before + /// calling this function. If it is unset, an empty string will be returned. + StringRef getCompilationDir() const { return CompilationDir; } + + /// Set the compilation directory for DW_AT_comp_dir + void setCompilationDir(StringRef S) { CompilationDir = S.str(); } + + /// Get the debug prefix map. + const std::map<const std::string, const std::string> & + getDebugPrefixMap() const { + return DebugPrefixMap; + } + + /// Add an entry to the debug prefix map. + void addDebugPrefixMapEntry(const std::string &From, const std::string &To); + + // Remaps all debug directory paths in-place as per the debug prefix map. + void RemapDebugPaths(); + + /// Get the main file name for use in error messages and debug + /// info. This can be set to ensure we've got the correct file name + /// after preprocessing or for -save-temps. + const std::string &getMainFileName() const { return MainFileName; } + + /// Set the main file name and override the default. + void setMainFileName(StringRef S) { MainFileName = S; } + + /// Creates an entry in the dwarf file and directory tables. + Expected<unsigned> getDwarfFile(StringRef Directory, StringRef FileName, + unsigned FileNumber, + MD5::MD5Result *Checksum, + Optional<StringRef> Source, unsigned CUID); + + bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0); + + const std::map<unsigned, MCDwarfLineTable> &getMCDwarfLineTables() const { + return MCDwarfLineTablesCUMap; + } + + MCDwarfLineTable &getMCDwarfLineTable(unsigned CUID) { + return MCDwarfLineTablesCUMap[CUID]; + } + + const MCDwarfLineTable &getMCDwarfLineTable(unsigned CUID) const { + auto I = MCDwarfLineTablesCUMap.find(CUID); + assert(I != MCDwarfLineTablesCUMap.end()); + return I->second; + } + + const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles(unsigned CUID = 0) { + return getMCDwarfLineTable(CUID).getMCDwarfFiles(); + } + + const SmallVectorImpl<std::string> &getMCDwarfDirs(unsigned CUID = 0) { + return getMCDwarfLineTable(CUID).getMCDwarfDirs(); + } + + bool hasMCLineSections() const { + for (const auto &Table : MCDwarfLineTablesCUMap) + if (!Table.second.getMCDwarfFiles().empty() || Table.second.getLabel()) + return true; + return false; + } + + unsigned getDwarfCompileUnitID() { return DwarfCompileUnitID; } + + void setDwarfCompileUnitID(unsigned CUIndex) { + DwarfCompileUnitID = CUIndex; + } + + /// Specifies the "root" file and directory of the compilation unit. + /// These are "file 0" and "directory 0" in DWARF v5. + void setMCLineTableRootFile(unsigned CUID, StringRef CompilationDir, + StringRef Filename, MD5::MD5Result *Checksum, + Optional<StringRef> Source) { + getMCDwarfLineTable(CUID).setRootFile(CompilationDir, Filename, Checksum, + Source); + } + + /// Reports whether MD5 checksum usage is consistent (all-or-none). + bool isDwarfMD5UsageConsistent(unsigned CUID) const { + return getMCDwarfLineTable(CUID).isMD5UsageConsistent(); + } + + /// Saves the information from the currently parsed dwarf .loc directive + /// and sets DwarfLocSeen. When the next instruction is assembled an entry + /// in the line number table with this information and the address of the + /// instruction will be created. + void setCurrentDwarfLoc(unsigned FileNum, unsigned Line, unsigned Column, + unsigned Flags, unsigned Isa, + unsigned Discriminator) { + CurrentDwarfLoc.setFileNum(FileNum); + CurrentDwarfLoc.setLine(Line); + CurrentDwarfLoc.setColumn(Column); + CurrentDwarfLoc.setFlags(Flags); + CurrentDwarfLoc.setIsa(Isa); + CurrentDwarfLoc.setDiscriminator(Discriminator); + DwarfLocSeen = true; + } + + void clearDwarfLocSeen() { DwarfLocSeen = false; } + + bool getDwarfLocSeen() { return DwarfLocSeen; } + const MCDwarfLoc &getCurrentDwarfLoc() { return CurrentDwarfLoc; } + + bool getGenDwarfForAssembly() { return GenDwarfForAssembly; } + void setGenDwarfForAssembly(bool Value) { GenDwarfForAssembly = Value; } + unsigned getGenDwarfFileNumber() { return GenDwarfFileNumber; } + + void setGenDwarfFileNumber(unsigned FileNumber) { + GenDwarfFileNumber = FileNumber; + } + + const SetVector<MCSection *> &getGenDwarfSectionSyms() { + return SectionsForRanges; + } + + bool addGenDwarfSection(MCSection *Sec) { + return SectionsForRanges.insert(Sec); + } + + void finalizeDwarfSections(MCStreamer &MCOS); + + const std::vector<MCGenDwarfLabelEntry> &getMCGenDwarfLabelEntries() const { + return MCGenDwarfLabelEntries; + } + + void addMCGenDwarfLabelEntry(const MCGenDwarfLabelEntry &E) { + MCGenDwarfLabelEntries.push_back(E); + } + + void setDwarfDebugFlags(StringRef S) { DwarfDebugFlags = S; } + StringRef getDwarfDebugFlags() { return DwarfDebugFlags; } + + void setDwarfDebugProducer(StringRef S) { DwarfDebugProducer = S; } + StringRef getDwarfDebugProducer() { return DwarfDebugProducer; } + + dwarf::DwarfFormat getDwarfFormat() const { + // TODO: Support DWARF64 + return dwarf::DWARF32; + } + + void setDwarfVersion(uint16_t v) { DwarfVersion = v; } + uint16_t getDwarfVersion() const { return DwarfVersion; } + + /// @} + + char *getSecureLogFile() { return SecureLogFile; } + raw_fd_ostream *getSecureLog() { return SecureLog.get(); } + + void setSecureLog(std::unique_ptr<raw_fd_ostream> Value) { + SecureLog = std::move(Value); + } + + bool getSecureLogUsed() { return SecureLogUsed; } + void setSecureLogUsed(bool Value) { SecureLogUsed = Value; } + + void *allocate(unsigned Size, unsigned Align = 8) { + return Allocator.Allocate(Size, Align); + } + + void deallocate(void *Ptr) {} + + bool hadError() { return HadError; } + void reportError(SMLoc L, const Twine &Msg); + // Unrecoverable error has occurred. Display the best diagnostic we can + // and bail via exit(1). For now, most MC backend errors are unrecoverable. + // FIXME: We should really do something about that. + LLVM_ATTRIBUTE_NORETURN void reportFatalError(SMLoc L, + const Twine &Msg); + + const MCAsmMacro *lookupMacro(StringRef Name) { + StringMap<MCAsmMacro>::iterator I = MacroMap.find(Name); + return (I == MacroMap.end()) ? nullptr : &I->getValue(); + } + + void defineMacro(StringRef Name, MCAsmMacro Macro) { + MacroMap.insert(std::make_pair(Name, std::move(Macro))); + } + + void undefineMacro(StringRef Name) { MacroMap.erase(Name); } + }; + +} // end namespace llvm + +// operator new and delete aren't allowed inside namespaces. +// The throw specifications are mandated by the standard. +/// Placement new for using the MCContext's allocator. +/// +/// This placement form of operator new uses the MCContext's allocator for +/// obtaining memory. It is a non-throwing new, which means that it returns +/// null on error. (If that is what the allocator does. The current does, so if +/// this ever changes, this operator will have to be changed, too.) +/// Usage looks like this (assuming there's an MCContext 'Context' in scope): +/// \code +/// // Default alignment (8) +/// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments); +/// // Specific alignment +/// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments); +/// \endcode +/// Please note that you cannot use delete on the pointer; it must be +/// deallocated using an explicit destructor call followed by +/// \c Context.Deallocate(Ptr). +/// +/// \param Bytes The number of bytes to allocate. Calculated by the compiler. +/// \param C The MCContext that provides the allocator. +/// \param Alignment The alignment of the allocated memory (if the underlying +/// allocator supports it). +/// \return The allocated memory. Could be NULL. +inline void *operator new(size_t Bytes, llvm::MCContext &C, + size_t Alignment = 8) noexcept { + return C.allocate(Bytes, Alignment); +} +/// Placement delete companion to the new above. +/// +/// This operator is just a companion to the new above. There is no way of +/// invoking it directly; see the new operator for more details. This operator +/// is called implicitly by the compiler if a placement new expression using +/// the MCContext throws in the object constructor. +inline void operator delete(void *Ptr, llvm::MCContext &C, size_t) noexcept { + C.deallocate(Ptr); +} + +/// This placement form of operator new[] uses the MCContext's allocator for +/// obtaining memory. It is a non-throwing new[], which means that it returns +/// null on error. +/// Usage looks like this (assuming there's an MCContext 'Context' in scope): +/// \code +/// // Default alignment (8) +/// char *data = new (Context) char[10]; +/// // Specific alignment +/// char *data = new (Context, 4) char[10]; +/// \endcode +/// Please note that you cannot use delete on the pointer; it must be +/// deallocated using an explicit destructor call followed by +/// \c Context.Deallocate(Ptr). +/// +/// \param Bytes The number of bytes to allocate. Calculated by the compiler. +/// \param C The MCContext that provides the allocator. +/// \param Alignment The alignment of the allocated memory (if the underlying +/// allocator supports it). +/// \return The allocated memory. Could be NULL. +inline void *operator new[](size_t Bytes, llvm::MCContext &C, + size_t Alignment = 8) noexcept { + return C.allocate(Bytes, Alignment); +} + +/// Placement delete[] companion to the new[] above. +/// +/// This operator is just a companion to the new[] above. There is no way of +/// invoking it directly; see the new[] operator for more details. This operator +/// is called implicitly by the compiler if a placement new[] expression using +/// the MCContext throws in the object constructor. +inline void operator delete[](void *Ptr, llvm::MCContext &C) noexcept { + C.deallocate(Ptr); +} + +#endif // LLVM_MC_MCCONTEXT_H diff --git a/clang-r353983/include/llvm/MC/MCDirectives.h b/clang-r353983/include/llvm/MC/MCDirectives.h new file mode 100644 index 00000000..4029264c --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCDirectives.h @@ -0,0 +1,73 @@ +//===- MCDirectives.h - Enums for directives on various targets -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines various enums that represent target-specific directives. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCDIRECTIVES_H +#define LLVM_MC_MCDIRECTIVES_H + +namespace llvm { + +enum MCSymbolAttr { + MCSA_Invalid = 0, ///< Not a valid directive. + + // Various directives in alphabetical order. + MCSA_Cold, ///< .cold (MachO) + MCSA_ELF_TypeFunction, ///< .type _foo, STT_FUNC # aka @function + MCSA_ELF_TypeIndFunction, ///< .type _foo, STT_GNU_IFUNC + MCSA_ELF_TypeObject, ///< .type _foo, STT_OBJECT # aka @object + MCSA_ELF_TypeTLS, ///< .type _foo, STT_TLS # aka @tls_object + MCSA_ELF_TypeCommon, ///< .type _foo, STT_COMMON # aka @common + MCSA_ELF_TypeNoType, ///< .type _foo, STT_NOTYPE # aka @notype + MCSA_ELF_TypeGnuUniqueObject, /// .type _foo, @gnu_unique_object + MCSA_Global, ///< .globl + MCSA_Hidden, ///< .hidden (ELF) + MCSA_IndirectSymbol, ///< .indirect_symbol (MachO) + MCSA_Internal, ///< .internal (ELF) + MCSA_LazyReference, ///< .lazy_reference (MachO) + MCSA_Local, ///< .local (ELF) + MCSA_NoDeadStrip, ///< .no_dead_strip (MachO) + MCSA_SymbolResolver, ///< .symbol_resolver (MachO) + MCSA_AltEntry, ///< .alt_entry (MachO) + MCSA_PrivateExtern, ///< .private_extern (MachO) + MCSA_Protected, ///< .protected (ELF) + MCSA_Reference, ///< .reference (MachO) + MCSA_Weak, ///< .weak + MCSA_WeakDefinition, ///< .weak_definition (MachO) + MCSA_WeakReference, ///< .weak_reference (MachO) + MCSA_WeakDefAutoPrivate ///< .weak_def_can_be_hidden (MachO) +}; + +enum MCAssemblerFlag { + MCAF_SyntaxUnified, ///< .syntax (ARM/ELF) + MCAF_SubsectionsViaSymbols, ///< .subsections_via_symbols (MachO) + MCAF_Code16, ///< .code16 (X86) / .code 16 (ARM) + MCAF_Code32, ///< .code32 (X86) / .code 32 (ARM) + MCAF_Code64 ///< .code64 (X86) +}; + +enum MCDataRegionType { + MCDR_DataRegion, ///< .data_region + MCDR_DataRegionJT8, ///< .data_region jt8 + MCDR_DataRegionJT16, ///< .data_region jt16 + MCDR_DataRegionJT32, ///< .data_region jt32 + MCDR_DataRegionEnd ///< .end_data_region +}; + +enum MCVersionMinType { + MCVM_IOSVersionMin, ///< .ios_version_min + MCVM_OSXVersionMin, ///< .macosx_version_min + MCVM_TvOSVersionMin, ///< .tvos_version_min + MCVM_WatchOSVersionMin, ///< .watchos_version_min +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCDisassembler/MCDisassembler.h b/clang-r353983/include/llvm/MC/MCDisassembler/MCDisassembler.h new file mode 100644 index 00000000..268f3cca --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCDisassembler/MCDisassembler.h @@ -0,0 +1,132 @@ +//===- llvm/MC/MCDisassembler.h - Disassembler interface --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCDISASSEMBLER_MCDISASSEMBLER_H +#define LLVM_MC_MCDISASSEMBLER_MCDISASSEMBLER_H + +#include "llvm/MC/MCDisassembler/MCSymbolizer.h" +#include <cstdint> +#include <memory> + +namespace llvm { + +template <typename T> class ArrayRef; +class StringRef; +class MCContext; +class MCInst; +class MCSubtargetInfo; +class raw_ostream; + +/// Superclass for all disassemblers. Consumes a memory region and provides an +/// array of assembly instructions. +class MCDisassembler { +public: + /// Ternary decode status. Most backends will just use Fail and + /// Success, however some have a concept of an instruction with + /// understandable semantics but which is architecturally + /// incorrect. An example of this is ARM UNPREDICTABLE instructions + /// which are disassemblable but cause undefined behaviour. + /// + /// Because it makes sense to disassemble these instructions, there + /// is a "soft fail" failure mode that indicates the MCInst& is + /// valid but architecturally incorrect. + /// + /// The enum numbers are deliberately chosen such that reduction + /// from Success->SoftFail ->Fail can be done with a simple + /// bitwise-AND: + /// + /// LEFT & TOP = | Success Unpredictable Fail + /// --------------+----------------------------------- + /// Success | Success Unpredictable Fail + /// Unpredictable | Unpredictable Unpredictable Fail + /// Fail | Fail Fail Fail + /// + /// An easy way of encoding this is as 0b11, 0b01, 0b00 for + /// Success, SoftFail, Fail respectively. + enum DecodeStatus { + Fail = 0, + SoftFail = 1, + Success = 3 + }; + + MCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) + : Ctx(Ctx), STI(STI) {} + + virtual ~MCDisassembler(); + + /// Returns the disassembly of a single instruction. + /// + /// \param Instr - An MCInst to populate with the contents of the + /// instruction. + /// \param Size - A value to populate with the size of the instruction, or + /// the number of bytes consumed while attempting to decode + /// an invalid instruction. + /// \param Address - The address, in the memory space of region, of the first + /// byte of the instruction. + /// \param Bytes - A reference to the actual bytes of the instruction. + /// \param VStream - The stream to print warnings and diagnostic messages on. + /// \param CStream - The stream to print comments and annotations on. + /// \return - MCDisassembler::Success if the instruction is valid, + /// MCDisassembler::SoftFail if the instruction was + /// disassemblable but invalid, + /// MCDisassembler::Fail if the instruction was invalid. + virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const = 0; + + /// May parse any prelude that precedes instructions after the start of a + /// symbol. Needed for some targets, e.g. WebAssembly. + /// + /// \param Name - The name of the symbol. + /// \param Size - The number of bytes consumed. + /// \param Address - The address, in the memory space of region, of the first + /// byte of the symbol. + /// \param Bytes - A reference to the actual bytes at the symbol location. + /// \param VStream - The stream to print warnings and diagnostic messages on. + /// \param CStream - The stream to print comments and annotations on. + /// \return - MCDisassembler::Success if the bytes are valid, + /// MCDisassembler::Fail if the bytes were invalid. + virtual DecodeStatus onSymbolStart(StringRef Name, uint64_t &Size, + ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const; + +private: + MCContext &Ctx; + +protected: + // Subtarget information, for instruction decoding predicates if required. + const MCSubtargetInfo &STI; + std::unique_ptr<MCSymbolizer> Symbolizer; + +public: + // Helpers around MCSymbolizer + bool tryAddingSymbolicOperand(MCInst &Inst, + int64_t Value, + uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t InstSize) const; + + void tryAddingPcLoadReferenceComment(int64_t Value, uint64_t Address) const; + + /// Set \p Symzer as the current symbolizer. + /// This takes ownership of \p Symzer, and deletes the previously set one. + void setSymbolizer(std::unique_ptr<MCSymbolizer> Symzer); + + MCContext& getContext() const { return Ctx; } + + const MCSubtargetInfo& getSubtargetInfo() const { return STI; } + + // Marked mutable because we cache it inside the disassembler, rather than + // having to pass it around as an argument through all the autogenerated code. + mutable raw_ostream *CommentStream = nullptr; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCDISASSEMBLER_MCDISASSEMBLER_H diff --git a/clang-r353983/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h b/clang-r353983/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h new file mode 100644 index 00000000..ffac5ee5 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h @@ -0,0 +1,57 @@ +//===-- llvm/MC/MCExternalSymbolizer.h - ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCExternalSymbolizer class, which +// enables library users to provide callbacks (through the C API) to do the +// symbolization externally. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCDISASSEMBLER_MCEXTERNALSYMBOLIZER_H +#define LLVM_MC_MCDISASSEMBLER_MCEXTERNALSYMBOLIZER_H + +#include "llvm-c/Disassembler.h" +#include "llvm/MC/MCDisassembler/MCSymbolizer.h" +#include <memory> + +namespace llvm { + +/// Symbolize using user-provided, C API, callbacks. +/// +/// See llvm-c/Disassembler.h. +class MCExternalSymbolizer : public MCSymbolizer { +protected: + /// \name Hooks for symbolic disassembly via the public 'C' interface. + /// @{ + /// The function to get the symbolic information for operands. + LLVMOpInfoCallback GetOpInfo; + /// The function to lookup a symbol name. + LLVMSymbolLookupCallback SymbolLookUp; + /// The pointer to the block of symbolic information for above call back. + void *DisInfo; + /// @} + +public: + MCExternalSymbolizer(MCContext &Ctx, + std::unique_ptr<MCRelocationInfo> RelInfo, + LLVMOpInfoCallback getOpInfo, + LLVMSymbolLookupCallback symbolLookUp, void *disInfo) + : MCSymbolizer(Ctx, std::move(RelInfo)), GetOpInfo(getOpInfo), + SymbolLookUp(symbolLookUp), DisInfo(disInfo) {} + + bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &CommentStream, + int64_t Value, uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t InstSize) override; + void tryAddingPcLoadReferenceComment(raw_ostream &CommentStream, + int64_t Value, + uint64_t Address) override; +}; + +} + +#endif diff --git a/clang-r353983/include/llvm/MC/MCDisassembler/MCRelocationInfo.h b/clang-r353983/include/llvm/MC/MCDisassembler/MCRelocationInfo.h new file mode 100644 index 00000000..efc59da1 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCDisassembler/MCRelocationInfo.h @@ -0,0 +1,44 @@ +//===- llvm/MC/MCRelocationInfo.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCRelocationInfo class, which provides methods to +// create MCExprs from relocations, either found in an object::ObjectFile +// (object::RelocationRef), or provided through the C API. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCDISASSEMBLER_MCRELOCATIONINFO_H +#define LLVM_MC_MCDISASSEMBLER_MCRELOCATIONINFO_H + +namespace llvm { + +class MCContext; +class MCExpr; + +/// Create MCExprs from relocations found in an object file. +class MCRelocationInfo { +protected: + MCContext &Ctx; + +public: + MCRelocationInfo(MCContext &Ctx); + MCRelocationInfo(const MCRelocationInfo &) = delete; + MCRelocationInfo &operator=(const MCRelocationInfo &) = delete; + virtual ~MCRelocationInfo(); + + /// Create an MCExpr for the target-specific \p VariantKind. + /// The VariantKinds are defined in llvm-c/Disassembler.h. + /// Used by MCExternalSymbolizer. + /// \returns If possible, an MCExpr corresponding to VariantKind, else 0. + virtual const MCExpr *createExprForCAPIVariantKind(const MCExpr *SubExpr, + unsigned VariantKind); +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCDISASSEMBLER_MCRELOCATIONINFO_H diff --git a/clang-r353983/include/llvm/MC/MCDisassembler/MCSymbolizer.h b/clang-r353983/include/llvm/MC/MCDisassembler/MCSymbolizer.h new file mode 100644 index 00000000..b7ca83a5 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCDisassembler/MCSymbolizer.h @@ -0,0 +1,82 @@ +//===- llvm/MC/MCSymbolizer.h - MCSymbolizer class --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCSymbolizer class, which is used +// to symbolize instructions decoded from an object, that is, transform their +// immediate operands to MCExprs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCDISASSEMBLER_MCSYMBOLIZER_H +#define LLVM_MC_MCDISASSEMBLER_MCSYMBOLIZER_H + +#include "llvm/MC/MCDisassembler/MCRelocationInfo.h" +#include <algorithm> +#include <cstdint> +#include <memory> + +namespace llvm { + +class MCContext; +class MCInst; +class raw_ostream; + +/// Symbolize and annotate disassembled instructions. +/// +/// For now this mimics the old symbolization logic (from both ARM and x86), that +/// relied on user-provided (C API) callbacks to do the actual symbol lookup in +/// the object file. This was moved to MCExternalSymbolizer. +/// A better API would not rely on actually calling the two methods here from +/// inside each disassembler, but would use the instr info to determine what +/// operands are actually symbolizable, and in what way. I don't think this +/// information exists right now. +class MCSymbolizer { +protected: + MCContext &Ctx; + std::unique_ptr<MCRelocationInfo> RelInfo; + +public: + /// Construct an MCSymbolizer, taking ownership of \p RelInfo. + MCSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> RelInfo) + : Ctx(Ctx), RelInfo(std::move(RelInfo)) { + } + + MCSymbolizer(const MCSymbolizer &) = delete; + MCSymbolizer &operator=(const MCSymbolizer &) = delete; + virtual ~MCSymbolizer(); + + /// Try to add a symbolic operand instead of \p Value to the MCInst. + /// + /// Instead of having a difficult to read immediate, a symbolic operand would + /// represent this immediate in a more understandable way, for instance as a + /// symbol or an offset from a symbol. Relocations can also be used to enrich + /// the symbolic expression. + /// \param Inst - The MCInst where to insert the symbolic operand. + /// \param cStream - Stream to print comments and annotations on. + /// \param Value - Operand value, pc-adjusted by the caller if necessary. + /// \param Address - Load address of the instruction. + /// \param IsBranch - Is the instruction a branch? + /// \param Offset - Byte offset of the operand inside the inst. + /// \param InstSize - Size of the instruction in bytes. + /// \return Whether a symbolic operand was added. + virtual bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream, + int64_t Value, uint64_t Address, + bool IsBranch, uint64_t Offset, + uint64_t InstSize) = 0; + + /// Try to add a comment on the PC-relative load. + /// For instance, in Mach-O, this is used to add annotations to instructions + /// that use C string literals, as found in __cstring. + virtual void tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, + uint64_t Address) = 0; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCDISASSEMBLER_MCSYMBOLIZER_H diff --git a/clang-r353983/include/llvm/MC/MCDwarf.h b/clang-r353983/include/llvm/MC/MCDwarf.h new file mode 100644 index 00000000..8eaa1523 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCDwarf.h @@ -0,0 +1,617 @@ +//===- MCDwarf.h - Machine Code Dwarf support -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCDwarfFile to support the dwarf +// .file directive and the .loc directive. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCDWARF_H +#define LLVM_MC_MCDWARF_H + +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCSection.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MD5.h" +#include <cassert> +#include <cstdint> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + +template <typename T> class ArrayRef; +class MCAsmBackend; +class MCContext; +class MCDwarfLineStr; +class MCObjectStreamer; +class MCStreamer; +class MCSymbol; +class raw_ostream; +class SMLoc; +class SourceMgr; + +/// Instances of this class represent the name of the dwarf +/// .file directive and its associated dwarf file number in the MC file, +/// and MCDwarfFile's are created and uniqued by the MCContext class where +/// the file number for each is its index into the vector of DwarfFiles (note +/// index 0 is not used and not a valid dwarf file number). +struct MCDwarfFile { + // The base name of the file without its directory path. + std::string Name; + + // The index into the list of directory names for this file name. + unsigned DirIndex; + + /// The MD5 checksum, if there is one. Non-owning pointer to data allocated + /// in MCContext. + MD5::MD5Result *Checksum = nullptr; + + /// The source code of the file. Non-owning reference to data allocated in + /// MCContext. + Optional<StringRef> Source; +}; + +/// Instances of this class represent the information from a +/// dwarf .loc directive. +class MCDwarfLoc { + uint32_t FileNum; + uint32_t Line; + uint16_t Column; + // Flags (see #define's below) + uint8_t Flags; + uint8_t Isa; + uint32_t Discriminator; + +// Flag that indicates the initial value of the is_stmt_start flag. +#define DWARF2_LINE_DEFAULT_IS_STMT 1 + +#define DWARF2_FLAG_IS_STMT (1 << 0) +#define DWARF2_FLAG_BASIC_BLOCK (1 << 1) +#define DWARF2_FLAG_PROLOGUE_END (1 << 2) +#define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3) + +private: // MCContext manages these + friend class MCContext; + friend class MCDwarfLineEntry; + + MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, + unsigned isa, unsigned discriminator) + : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), + Discriminator(discriminator) {} + + // Allow the default copy constructor and assignment operator to be used + // for an MCDwarfLoc object. + +public: + /// Get the FileNum of this MCDwarfLoc. + unsigned getFileNum() const { return FileNum; } + + /// Get the Line of this MCDwarfLoc. + unsigned getLine() const { return Line; } + + /// Get the Column of this MCDwarfLoc. + unsigned getColumn() const { return Column; } + + /// Get the Flags of this MCDwarfLoc. + unsigned getFlags() const { return Flags; } + + /// Get the Isa of this MCDwarfLoc. + unsigned getIsa() const { return Isa; } + + /// Get the Discriminator of this MCDwarfLoc. + unsigned getDiscriminator() const { return Discriminator; } + + /// Set the FileNum of this MCDwarfLoc. + void setFileNum(unsigned fileNum) { FileNum = fileNum; } + + /// Set the Line of this MCDwarfLoc. + void setLine(unsigned line) { Line = line; } + + /// Set the Column of this MCDwarfLoc. + void setColumn(unsigned column) { + assert(column <= UINT16_MAX); + Column = column; + } + + /// Set the Flags of this MCDwarfLoc. + void setFlags(unsigned flags) { + assert(flags <= UINT8_MAX); + Flags = flags; + } + + /// Set the Isa of this MCDwarfLoc. + void setIsa(unsigned isa) { + assert(isa <= UINT8_MAX); + Isa = isa; + } + + /// Set the Discriminator of this MCDwarfLoc. + void setDiscriminator(unsigned discriminator) { + Discriminator = discriminator; + } +}; + +/// Instances of this class represent the line information for +/// the dwarf line table entries. Which is created after a machine +/// instruction is assembled and uses an address from a temporary label +/// created at the current address in the current section and the info from +/// the last .loc directive seen as stored in the context. +class MCDwarfLineEntry : public MCDwarfLoc { + MCSymbol *Label; + +private: + // Allow the default copy constructor and assignment operator to be used + // for an MCDwarfLineEntry object. + +public: + // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc. + MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc) + : MCDwarfLoc(loc), Label(label) {} + + MCSymbol *getLabel() const { return Label; } + + // This is called when an instruction is assembled into the specified + // section and if there is information from the last .loc directive that + // has yet to have a line entry made for it is made. + static void Make(MCObjectStreamer *MCOS, MCSection *Section); +}; + +/// Instances of this class represent the line information for a compile +/// unit where machine instructions have been assembled after seeing .loc +/// directives. This is the information used to build the dwarf line +/// table for a section. +class MCLineSection { +public: + // Add an entry to this MCLineSection's line entries. + void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) { + MCLineDivisions[Sec].push_back(LineEntry); + } + + using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>; + using iterator = MCDwarfLineEntryCollection::iterator; + using const_iterator = MCDwarfLineEntryCollection::const_iterator; + using MCLineDivisionMap = MapVector<MCSection *, MCDwarfLineEntryCollection>; + +private: + // A collection of MCDwarfLineEntry for each section. + MCLineDivisionMap MCLineDivisions; + +public: + // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID. + const MCLineDivisionMap &getMCLineEntries() const { + return MCLineDivisions; + } +}; + +struct MCDwarfLineTableParams { + /// First special line opcode - leave room for the standard opcodes. + /// Note: If you want to change this, you'll have to update the + /// "StandardOpcodeLengths" table that is emitted in + /// \c Emit(). + uint8_t DWARF2LineOpcodeBase = 13; + /// Minimum line offset in a special line info. opcode. The value + /// -5 was chosen to give a reasonable range of values. + int8_t DWARF2LineBase = -5; + /// Range of line offsets in a special line info. opcode. + uint8_t DWARF2LineRange = 14; +}; + +struct MCDwarfLineTableHeader { + MCSymbol *Label = nullptr; + SmallVector<std::string, 3> MCDwarfDirs; + SmallVector<MCDwarfFile, 3> MCDwarfFiles; + StringMap<unsigned> SourceIdMap; + std::string CompilationDir; + MCDwarfFile RootFile; + bool HasSource = false; +private: + bool HasAllMD5 = true; + bool HasAnyMD5 = false; + +public: + MCDwarfLineTableHeader() = default; + + Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName, + MD5::MD5Result *Checksum, + Optional<StringRef> &Source, + unsigned FileNumber = 0); + std::pair<MCSymbol *, MCSymbol *> + Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, + Optional<MCDwarfLineStr> &LineStr) const; + std::pair<MCSymbol *, MCSymbol *> + Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, + ArrayRef<char> SpecialOpcodeLengths, + Optional<MCDwarfLineStr> &LineStr) const; + void resetMD5Usage() { + HasAllMD5 = true; + HasAnyMD5 = false; + } + void trackMD5Usage(bool MD5Used) { + HasAllMD5 &= MD5Used; + HasAnyMD5 |= MD5Used; + } + bool isMD5UsageConsistent() const { + return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5); + } + +private: + void emitV2FileDirTables(MCStreamer *MCOS) const; + void emitV5FileDirTables(MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr, + StringRef CtxCompilationDir) const; +}; + +class MCDwarfDwoLineTable { + MCDwarfLineTableHeader Header; + +public: + void maybeSetRootFile(StringRef Directory, StringRef FileName, + MD5::MD5Result *Checksum, Optional<StringRef> Source) { + if (!Header.RootFile.Name.empty()) + return; + Header.CompilationDir = Directory; + Header.RootFile.Name = FileName; + Header.RootFile.DirIndex = 0; + Header.RootFile.Checksum = Checksum; + Header.RootFile.Source = Source; + Header.trackMD5Usage(Checksum); + Header.HasSource = Source.hasValue(); + } + + unsigned getFile(StringRef Directory, StringRef FileName, + MD5::MD5Result *Checksum, Optional<StringRef> Source) { + return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source)); + } + + void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params, + MCSection *Section) const; +}; + +class MCDwarfLineTable { + MCDwarfLineTableHeader Header; + MCLineSection MCLineSections; + +public: + // This emits the Dwarf file and the line tables for all Compile Units. + static void Emit(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params); + + // This emits the Dwarf file and the line tables for a given Compile Unit. + void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params, + Optional<MCDwarfLineStr> &LineStr) const; + + Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName, + MD5::MD5Result *Checksum, + Optional<StringRef> Source, + unsigned FileNumber = 0); + unsigned getFile(StringRef &Directory, StringRef &FileName, + MD5::MD5Result *Checksum, Optional<StringRef> &Source, + unsigned FileNumber = 0) { + return cantFail(tryGetFile(Directory, FileName, Checksum, Source, + FileNumber)); + } + + void setRootFile(StringRef Directory, StringRef FileName, + MD5::MD5Result *Checksum, Optional<StringRef> Source) { + Header.CompilationDir = Directory; + Header.RootFile.Name = FileName; + Header.RootFile.DirIndex = 0; + Header.RootFile.Checksum = Checksum; + Header.RootFile.Source = Source; + Header.trackMD5Usage(Checksum); + Header.HasSource = Source.hasValue(); + } + + void resetRootFile() { + assert(Header.MCDwarfFiles.empty()); + Header.RootFile.Name.clear(); + Header.resetMD5Usage(); + Header.HasSource = false; + } + + bool hasRootFile() const { return !Header.RootFile.Name.empty(); } + + // Report whether MD5 usage has been consistent (all-or-none). + bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); } + + MCSymbol *getLabel() const { + return Header.Label; + } + + void setLabel(MCSymbol *Label) { + Header.Label = Label; + } + + const SmallVectorImpl<std::string> &getMCDwarfDirs() const { + return Header.MCDwarfDirs; + } + + SmallVectorImpl<std::string> &getMCDwarfDirs() { + return Header.MCDwarfDirs; + } + + const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const { + return Header.MCDwarfFiles; + } + + SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() { + return Header.MCDwarfFiles; + } + + const MCLineSection &getMCLineSections() const { + return MCLineSections; + } + MCLineSection &getMCLineSections() { + return MCLineSections; + } +}; + +class MCDwarfLineAddr { +public: + /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. + 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 using + /// fixed length operands. + static bool FixedEncode(MCContext &Context, + MCDwarfLineTableParams Params, + int64_t LineDelta, uint64_t AddrDelta, + raw_ostream &OS, uint32_t *Offset, uint32_t *Size); + + /// Utility function to emit the encoding to a streamer. + static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, + int64_t LineDelta, uint64_t AddrDelta); +}; + +class MCGenDwarfInfo { +public: + // + // When generating dwarf for assembly source files this emits the Dwarf + // sections. + // + static void Emit(MCStreamer *MCOS); +}; + +// When generating dwarf for assembly source files this is the info that is +// needed to be gathered for each symbol that will have a dwarf label. +class MCGenDwarfLabelEntry { +private: + // Name of the symbol without a leading underbar, if any. + StringRef Name; + // The dwarf file number this symbol is in. + unsigned FileNumber; + // The line number this symbol is at. + unsigned LineNumber; + // The low_pc for the dwarf label is taken from this symbol. + MCSymbol *Label; + +public: + MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, + MCSymbol *label) + : Name(name), FileNumber(fileNumber), LineNumber(lineNumber), + Label(label) {} + + StringRef getName() const { return Name; } + unsigned getFileNumber() const { return FileNumber; } + unsigned getLineNumber() const { return LineNumber; } + MCSymbol *getLabel() const { return Label; } + + // This is called when label is created when we are generating dwarf for + // assembly source files. + static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, + SMLoc &Loc); +}; + +class MCCFIInstruction { +public: + enum OpType { + OpSameValue, + OpRememberState, + OpRestoreState, + OpOffset, + OpDefCfaRegister, + OpDefCfaOffset, + OpDefCfa, + OpRelOffset, + OpAdjustCfaOffset, + OpEscape, + OpRestore, + OpUndefined, + OpRegister, + OpWindowSave, + OpNegateRAState, + OpGnuArgsSize + }; + +private: + OpType Operation; + MCSymbol *Label; + unsigned Register; + union { + int Offset; + unsigned Register2; + }; + std::vector<char> Values; + + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) + : Operation(Op), Label(L), Register(R), Offset(O), + Values(V.begin(), V.end()) { + assert(Op != OpRegister); + } + + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) + : Operation(Op), Label(L), Register(R1), Register2(R2) { + assert(Op == OpRegister); + } + +public: + /// .cfi_def_cfa defines a rule for computing CFA as: take address from + /// Register and add Offset to it. + static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); + } + + /// .cfi_def_cfa_register modifies a rule for computing CFA. From now + /// on Register will be used instead of the old one. Offset remains the same. + static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); + } + + /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register + /// remains the same, but offset is new. Note that it is the absolute offset + /// that will be added to a defined register to the compute CFA address. + static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { + return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); + } + + /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but + /// Offset is a relative value that is added/subtracted from the previous + /// offset. + static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) { + return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); + } + + /// .cfi_offset Previous value of Register is saved at offset Offset + /// from CFA. + static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpOffset, L, Register, Offset, ""); + } + + /// .cfi_rel_offset Previous value of Register is saved at offset + /// Offset from the current CFA register. This is transformed to .cfi_offset + /// using the known displacement of the CFA register from the CFA. + static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); + } + + /// .cfi_register Previous value of Register1 is saved in + /// register Register2. + static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, + unsigned Register2) { + return MCCFIInstruction(OpRegister, L, Register1, Register2); + } + + /// .cfi_window_save SPARC register window is saved. + static MCCFIInstruction createWindowSave(MCSymbol *L) { + return MCCFIInstruction(OpWindowSave, L, 0, 0, ""); + } + + /// .cfi_negate_ra_state AArch64 negate RA state. + static MCCFIInstruction createNegateRAState(MCSymbol *L) { + return MCCFIInstruction(OpNegateRAState, L, 0, 0, ""); + } + + /// .cfi_restore says that the rule for Register is now the same as it + /// was at the beginning of the function, after all initial instructions added + /// by .cfi_startproc were executed. + static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpRestore, L, Register, 0, ""); + } + + /// .cfi_undefined From now on the previous value of Register can't be + /// restored anymore. + static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpUndefined, L, Register, 0, ""); + } + + /// .cfi_same_value Current value of Register is the same as in the + /// previous frame. I.e., no restoration is needed. + static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpSameValue, L, Register, 0, ""); + } + + /// .cfi_remember_state Save all current rules for all registers. + static MCCFIInstruction createRememberState(MCSymbol *L) { + return MCCFIInstruction(OpRememberState, L, 0, 0, ""); + } + + /// .cfi_restore_state Restore the previously saved state. + static MCCFIInstruction createRestoreState(MCSymbol *L) { + return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); + } + + /// .cfi_escape Allows the user to add arbitrary bytes to the unwind + /// info. + static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { + return MCCFIInstruction(OpEscape, L, 0, 0, Vals); + } + + /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE + static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) { + return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, ""); + } + + OpType getOperation() const { return Operation; } + MCSymbol *getLabel() const { return Label; } + + unsigned getRegister() const { + assert(Operation == OpDefCfa || Operation == OpOffset || + Operation == OpRestore || Operation == OpUndefined || + Operation == OpSameValue || Operation == OpDefCfaRegister || + Operation == OpRelOffset || Operation == OpRegister); + return Register; + } + + unsigned getRegister2() const { + assert(Operation == OpRegister); + return Register2; + } + + int getOffset() const { + assert(Operation == OpDefCfa || Operation == OpOffset || + Operation == OpRelOffset || Operation == OpDefCfaOffset || + Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize); + return Offset; + } + + StringRef getValues() const { + assert(Operation == OpEscape); + return StringRef(&Values[0], Values.size()); + } +}; + +struct MCDwarfFrameInfo { + MCDwarfFrameInfo() = default; + + MCSymbol *Begin = nullptr; + MCSymbol *End = nullptr; + const MCSymbol *Personality = nullptr; + const MCSymbol *Lsda = nullptr; + std::vector<MCCFIInstruction> Instructions; + unsigned CurrentCfaRegister = 0; + unsigned PersonalityEncoding = 0; + unsigned LsdaEncoding = 0; + uint32_t CompactUnwindEncoding = 0; + bool IsSignalFrame = false; + bool IsSimple = false; + unsigned RAReg = static_cast<unsigned>(INT_MAX); + bool IsBKeyFrame = false; +}; + +class MCDwarfFrameEmitter { +public: + // + // This emits the frame info section. + // + static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH); + static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta); + static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, + raw_ostream &OS); +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCDWARF_H diff --git a/clang-r353983/include/llvm/MC/MCELFObjectWriter.h b/clang-r353983/include/llvm/MC/MCELFObjectWriter.h new file mode 100644 index 00000000..9ff7011d --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCELFObjectWriter.h @@ -0,0 +1,161 @@ +//===- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELFOBJECTWRITER_H +#define LLVM_MC_MCELFOBJECTWRITER_H + +#include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +class MCAssembler; +class MCContext; +class MCFixup; +class MCObjectWriter; +class MCSymbol; +class MCSymbolELF; +class MCValue; + +struct ELFRelocationEntry { + uint64_t Offset; // Where is the relocation. + const MCSymbolELF *Symbol; // The symbol to relocate with. + unsigned Type; // The type of the relocation. + uint64_t Addend; // The addend to use. + const MCSymbolELF *OriginalSymbol; // The original value of Symbol if we changed it. + uint64_t OriginalAddend; // The original value of addend. + + ELFRelocationEntry(uint64_t Offset, const MCSymbolELF *Symbol, unsigned Type, + uint64_t Addend, const MCSymbolELF *OriginalSymbol, + uint64_t OriginalAddend) + : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend), + OriginalSymbol(OriginalSymbol), OriginalAddend(OriginalAddend) {} + + void print(raw_ostream &Out) const { + Out << "Off=" << Offset << ", Sym=" << Symbol << ", Type=" << Type + << ", Addend=" << Addend << ", OriginalSymbol=" << OriginalSymbol + << ", OriginalAddend=" << OriginalAddend; + } + + void dump() const { print(errs()); } +}; + +class MCELFObjectTargetWriter : public MCObjectTargetWriter { + const uint8_t OSABI; + const uint16_t EMachine; + const unsigned HasRelocationAddend : 1; + const unsigned Is64Bit : 1; + +protected: + MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_, uint16_t EMachine_, + bool HasRelocationAddend); + +public: + virtual ~MCELFObjectTargetWriter() = default; + + virtual Triple::ObjectFormatType getFormat() const { return Triple::ELF; } + static bool classof(const MCObjectTargetWriter *W) { + return W->getFormat() == Triple::ELF; + } + + static uint8_t getOSABI(Triple::OSType OSType) { + switch (OSType) { + case Triple::CloudABI: + return ELF::ELFOSABI_CLOUDABI; + case Triple::HermitCore: + return ELF::ELFOSABI_STANDALONE; + case Triple::PS4: + case Triple::FreeBSD: + return ELF::ELFOSABI_FREEBSD; + default: + return ELF::ELFOSABI_NONE; + } + } + + virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const = 0; + + virtual bool needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const; + + virtual void sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs); + + virtual void addTargetSectionFlags(MCContext &Ctx, MCSectionELF &Sec); + + /// \name Accessors + /// @{ + uint8_t getOSABI() const { return OSABI; } + uint16_t getEMachine() const { return EMachine; } + bool hasRelocationAddend() const { return HasRelocationAddend; } + bool is64Bit() const { return Is64Bit; } + /// @} + + // Instead of changing everyone's API we pack the N64 Type fields + // into the existing 32 bit data unsigned. +#define R_TYPE_SHIFT 0 +#define R_TYPE_MASK 0xffffff00 +#define R_TYPE2_SHIFT 8 +#define R_TYPE2_MASK 0xffff00ff +#define R_TYPE3_SHIFT 16 +#define R_TYPE3_MASK 0xff00ffff +#define R_SSYM_SHIFT 24 +#define R_SSYM_MASK 0x00ffffff + + // N64 relocation type accessors + uint8_t getRType(uint32_t Type) const { + return (unsigned)((Type >> R_TYPE_SHIFT) & 0xff); + } + uint8_t getRType2(uint32_t Type) const { + return (unsigned)((Type >> R_TYPE2_SHIFT) & 0xff); + } + uint8_t getRType3(uint32_t Type) const { + return (unsigned)((Type >> R_TYPE3_SHIFT) & 0xff); + } + uint8_t getRSsym(uint32_t Type) const { + return (unsigned)((Type >> R_SSYM_SHIFT) & 0xff); + } + + // N64 relocation type setting + unsigned setRType(unsigned Value, unsigned Type) const { + return ((Type & R_TYPE_MASK) | ((Value & 0xff) << R_TYPE_SHIFT)); + } + unsigned setRType2(unsigned Value, unsigned Type) const { + return (Type & R_TYPE2_MASK) | ((Value & 0xff) << R_TYPE2_SHIFT); + } + unsigned setRType3(unsigned Value, unsigned Type) const { + return (Type & R_TYPE3_MASK) | ((Value & 0xff) << R_TYPE3_SHIFT); + } + unsigned setRSsym(unsigned Value, unsigned Type) const { + return (Type & R_SSYM_MASK) | ((Value & 0xff) << R_SSYM_SHIFT); + } +}; + +/// Construct a new ELF writer instance. +/// +/// \param MOTW - The target specific ELF writer subclass. +/// \param OS - The stream to write to. +/// \returns The constructed object writer. +std::unique_ptr<MCObjectWriter> +createELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW, + raw_pwrite_stream &OS, bool IsLittleEndian); + +std::unique_ptr<MCObjectWriter> +createELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW, + raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS, + bool IsLittleEndian); + +} // end namespace llvm + +#endif // LLVM_MC_MCELFOBJECTWRITER_H diff --git a/clang-r353983/include/llvm/MC/MCELFStreamer.h b/clang-r353983/include/llvm/MC/MCELFStreamer.h new file mode 100644 index 00000000..8838d53d --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCELFStreamer.h @@ -0,0 +1,108 @@ +//===- MCELFStreamer.h - MCStreamer ELF Object File Interface ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELFSTREAMER_H +#define LLVM_MC_MCELFSTREAMER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCObjectStreamer.h" + +namespace llvm { + +class MCAsmBackend; +class MCCodeEmitter; +class MCExpr; +class MCInst; + +class MCELFStreamer : public MCObjectStreamer { +public: + MCELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, + std::unique_ptr<MCObjectWriter> OW, + std::unique_ptr<MCCodeEmitter> Emitter); + + ~MCELFStreamer() override = default; + + /// state management + void reset() override { + SeenIdent = false; + BundleGroups.clear(); + MCObjectStreamer::reset(); + } + + /// \name MCStreamer Interface + /// @{ + + void InitSections(bool NoExecStack) override; + void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; + void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + void EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) override; + void EmitAssemblerFlag(MCAssemblerFlag Flag) override; + void EmitThumbFunc(MCSymbol *Func) override; + void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + + void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; + void emitELFSymverDirective(StringRef AliasName, + const MCSymbol *Aliasee) override; + + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + + void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0, + SMLoc L = SMLoc()) override; + void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment = 0) override; + void EmitValueImpl(const MCExpr *Value, unsigned Size, + SMLoc Loc = SMLoc()) override; + + void EmitIdent(StringRef IdentString) override; + + void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned) override; + + void emitCGProfileEntry(const MCSymbolRefExpr *From, + const MCSymbolRefExpr *To, uint64_t Count) override; + + void FinishImpl() override; + + void EmitBundleAlignMode(unsigned AlignPow2) override; + void EmitBundleLock(bool AlignToEnd) override; + void EmitBundleUnlock() override; + +private: + bool isBundleLocked() const; + void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override; + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; + + void fixSymbolsInTLSFixups(const MCExpr *expr); + void finalizeCGProfileEntry(const MCSymbolRefExpr *&S); + void finalizeCGProfile(); + + /// Merge the content of the fragment \p EF into the fragment \p DF. + void mergeFragment(MCDataFragment *, MCDataFragment *); + + bool SeenIdent = false; + + /// BundleGroups - The stack of fragments holding the bundle-locked + /// instructions. + SmallVector<MCDataFragment *, 4> BundleGroups; +}; + +MCELFStreamer *createARMELFStreamer(MCContext &Context, + std::unique_ptr<MCAsmBackend> TAB, + std::unique_ptr<MCObjectWriter> OW, + std::unique_ptr<MCCodeEmitter> Emitter, + bool RelaxAll, bool IsThumb); + +} // end namespace llvm + +#endif // LLVM_MC_MCELFSTREAMER_H diff --git a/clang-r353983/include/llvm/MC/MCExpr.h b/clang-r353983/include/llvm/MC/MCExpr.h new file mode 100644 index 00000000..85316303 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCExpr.h @@ -0,0 +1,609 @@ +//===- MCExpr.h - Assembly Level Expressions --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCEXPR_H +#define LLVM_MC_MCEXPR_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/SMLoc.h" +#include <cstdint> + +namespace llvm { + +class MCAsmInfo; +class MCAsmLayout; +class MCAssembler; +class MCContext; +class MCFixup; +class MCFragment; +class MCSection; +class MCStreamer; +class MCSymbol; +class MCValue; +class raw_ostream; +class StringRef; + +using SectionAddrMap = DenseMap<const MCSection *, uint64_t>; + +/// Base class for the full range of assembler expressions which are +/// needed for parsing. +class MCExpr { +public: + enum ExprKind { + Binary, ///< Binary expressions. + Constant, ///< Constant expressions. + SymbolRef, ///< References to labels and assigned expressions. + Unary, ///< Unary expressions. + Target ///< Target specific expression. + }; + +private: + ExprKind Kind; + SMLoc Loc; + + bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs) const; + + bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, bool InSet) const; + +protected: + explicit MCExpr(ExprKind Kind, SMLoc Loc) : Kind(Kind), Loc(Loc) {} + + bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const MCFixup *Fixup, + const SectionAddrMap *Addrs, bool InSet) const; + +public: + MCExpr(const MCExpr &) = delete; + MCExpr &operator=(const MCExpr &) = delete; + + /// \name Accessors + /// @{ + + ExprKind getKind() const { return Kind; } + SMLoc getLoc() const { return Loc; } + + /// @} + /// \name Utility Methods + /// @{ + + void print(raw_ostream &OS, const MCAsmInfo *MAI, + bool InParens = false) const; + void dump() const; + + /// @} + /// \name Expression Evaluation + /// @{ + + /// Try to evaluate the expression to an absolute value. + /// + /// \param Res - The absolute value, if evaluation succeeds. + /// \param Layout - The assembler layout object to use for evaluating symbol + /// values. If not given, then only non-symbolic expressions will be + /// evaluated. + /// \return - True on success. + bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, + const SectionAddrMap &Addrs) const; + bool evaluateAsAbsolute(int64_t &Res) const; + bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; + bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const; + bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + + bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + + /// Try to evaluate the expression to a relocatable value, i.e. an + /// expression of the fixed form (a - b + constant). + /// + /// \param Res - The relocatable value, if evaluation succeeds. + /// \param Layout - The assembler layout object to use for evaluating values. + /// \param Fixup - The Fixup object if available. + /// \return - True on success. + bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const; + + /// Try to evaluate the expression to the form (a - b + constant) where + /// neither a nor b are variables. + /// + /// This is a more aggressive variant of evaluateAsRelocatable. The intended + /// use is for when relocations are not available, like the .size directive. + bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const; + + /// Find the "associated section" for this expression, which is + /// currently defined as the absolute section for constants, or + /// otherwise the section associated with the first defined symbol in the + /// expression. + MCFragment *findAssociatedFragment() const; + + /// @} +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { + E.print(OS, nullptr); + return OS; +} + +//// Represent a constant integer expression. +class MCConstantExpr : public MCExpr { + int64_t Value; + + explicit MCConstantExpr(int64_t Value) + : MCExpr(MCExpr::Constant, SMLoc()), Value(Value) {} + +public: + /// \name Construction + /// @{ + + static const MCConstantExpr *create(int64_t Value, MCContext &Ctx); + + /// @} + /// \name Accessors + /// @{ + + int64_t getValue() const { return Value; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Constant; + } +}; + +/// Represent a reference to a symbol from inside an expression. +/// +/// A symbol reference in an expression may be a use of a label, a use of an +/// assembler variable (defined constant), or constitute an implicit definition +/// of the symbol as external. +class MCSymbolRefExpr : public MCExpr { +public: + enum VariantKind : uint16_t { + VK_None, + VK_Invalid, + + VK_GOT, + VK_GOTOFF, + VK_GOTREL, + VK_GOTPCREL, + VK_GOTTPOFF, + VK_INDNTPOFF, + VK_NTPOFF, + VK_GOTNTPOFF, + VK_PLT, + VK_TLSGD, + VK_TLSLD, + VK_TLSLDM, + VK_TPOFF, + VK_DTPOFF, + VK_TLSCALL, // symbol(tlscall) + VK_TLSDESC, // symbol(tlsdesc) + VK_TLVP, // Mach-O thread local variable relocations + VK_TLVPPAGE, + VK_TLVPPAGEOFF, + VK_PAGE, + VK_PAGEOFF, + VK_GOTPAGE, + VK_GOTPAGEOFF, + VK_SECREL, + VK_SIZE, // symbol@SIZE + VK_WEAKREF, // The link between the symbols in .weakref foo, bar + + VK_X86_ABS8, + + VK_ARM_NONE, + VK_ARM_GOT_PREL, + VK_ARM_TARGET1, + VK_ARM_TARGET2, + VK_ARM_PREL31, + VK_ARM_SBREL, // symbol(sbrel) + VK_ARM_TLSLDO, // symbol(tlsldo) + VK_ARM_TLSDESCSEQ, + + VK_AVR_NONE, + VK_AVR_LO8, + VK_AVR_HI8, + VK_AVR_HLO8, + VK_AVR_DIFF8, + VK_AVR_DIFF16, + VK_AVR_DIFF32, + + VK_PPC_LO, // symbol@l + VK_PPC_HI, // symbol@h + VK_PPC_HA, // symbol@ha + VK_PPC_HIGH, // symbol@high + VK_PPC_HIGHA, // symbol@higha + VK_PPC_HIGHER, // symbol@higher + VK_PPC_HIGHERA, // symbol@highera + VK_PPC_HIGHEST, // symbol@highest + VK_PPC_HIGHESTA, // symbol@highesta + VK_PPC_GOT_LO, // symbol@got@l + VK_PPC_GOT_HI, // symbol@got@h + VK_PPC_GOT_HA, // symbol@got@ha + VK_PPC_TOCBASE, // symbol@tocbase + VK_PPC_TOC, // symbol@toc + VK_PPC_TOC_LO, // symbol@toc@l + VK_PPC_TOC_HI, // symbol@toc@h + VK_PPC_TOC_HA, // symbol@toc@ha + VK_PPC_DTPMOD, // symbol@dtpmod + VK_PPC_TPREL_LO, // symbol@tprel@l + VK_PPC_TPREL_HI, // symbol@tprel@h + VK_PPC_TPREL_HA, // symbol@tprel@ha + VK_PPC_TPREL_HIGH, // symbol@tprel@high + VK_PPC_TPREL_HIGHA, // symbol@tprel@higha + VK_PPC_TPREL_HIGHER, // symbol@tprel@higher + VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera + VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest + VK_PPC_TPREL_HIGHESTA, // symbol@tprel@highesta + VK_PPC_DTPREL_LO, // symbol@dtprel@l + VK_PPC_DTPREL_HI, // symbol@dtprel@h + VK_PPC_DTPREL_HA, // symbol@dtprel@ha + VK_PPC_DTPREL_HIGH, // symbol@dtprel@high + VK_PPC_DTPREL_HIGHA, // symbol@dtprel@higha + VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher + VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera + VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest + VK_PPC_DTPREL_HIGHESTA,// symbol@dtprel@highesta + VK_PPC_GOT_TPREL, // symbol@got@tprel + VK_PPC_GOT_TPREL_LO, // symbol@got@tprel@l + VK_PPC_GOT_TPREL_HI, // symbol@got@tprel@h + VK_PPC_GOT_TPREL_HA, // symbol@got@tprel@ha + VK_PPC_GOT_DTPREL, // symbol@got@dtprel + VK_PPC_GOT_DTPREL_LO, // symbol@got@dtprel@l + VK_PPC_GOT_DTPREL_HI, // symbol@got@dtprel@h + VK_PPC_GOT_DTPREL_HA, // symbol@got@dtprel@ha + VK_PPC_TLS, // symbol@tls + VK_PPC_GOT_TLSGD, // symbol@got@tlsgd + VK_PPC_GOT_TLSGD_LO, // symbol@got@tlsgd@l + VK_PPC_GOT_TLSGD_HI, // symbol@got@tlsgd@h + VK_PPC_GOT_TLSGD_HA, // symbol@got@tlsgd@ha + VK_PPC_TLSGD, // symbol@tlsgd + VK_PPC_GOT_TLSLD, // symbol@got@tlsld + VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l + VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h + VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha + VK_PPC_TLSLD, // symbol@tlsld + VK_PPC_LOCAL, // symbol@local + + VK_COFF_IMGREL32, // symbol@imgrel (image-relative) + + VK_Hexagon_PCREL, + VK_Hexagon_LO16, + VK_Hexagon_HI16, + VK_Hexagon_GPREL, + VK_Hexagon_GD_GOT, + VK_Hexagon_LD_GOT, + VK_Hexagon_GD_PLT, + VK_Hexagon_LD_PLT, + VK_Hexagon_IE, + VK_Hexagon_IE_GOT, + + VK_WebAssembly_FUNCTION, // Function table index, rather than virtual addr + VK_WebAssembly_GLOBAL, // Global object index + VK_WebAssembly_TYPEINDEX,// Type table index + VK_WebAssembly_EVENT, // Event index + + VK_AMDGPU_GOTPCREL32_LO, // symbol@gotpcrel32@lo + VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi + VK_AMDGPU_REL32_LO, // symbol@rel32@lo + VK_AMDGPU_REL32_HI, // symbol@rel32@hi + VK_AMDGPU_REL64, // symbol@rel64 + + VK_TPREL, + VK_DTPREL + }; + +private: + /// The symbol reference modifier. + const VariantKind Kind; + + /// Specifies how the variant kind should be printed. + const unsigned UseParensForSymbolVariant : 1; + + // FIXME: Remove this bit. + const unsigned HasSubsectionsViaSymbols : 1; + + /// The symbol being referenced. + const MCSymbol *Symbol; + + explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, + const MCAsmInfo *MAI, SMLoc Loc = SMLoc()); + +public: + /// \name Construction + /// @{ + + static const MCSymbolRefExpr *create(const MCSymbol *Symbol, MCContext &Ctx) { + return MCSymbolRefExpr::create(Symbol, VK_None, Ctx); + } + + static const MCSymbolRefExpr *create(const MCSymbol *Symbol, VariantKind Kind, + MCContext &Ctx, SMLoc Loc = SMLoc()); + static const MCSymbolRefExpr *create(StringRef Name, VariantKind Kind, + MCContext &Ctx); + + /// @} + /// \name Accessors + /// @{ + + const MCSymbol &getSymbol() const { return *Symbol; } + + VariantKind getKind() const { return Kind; } + + void printVariantKind(raw_ostream &OS) const; + + bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } + + /// @} + /// \name Static Utility Functions + /// @{ + + static StringRef getVariantKindName(VariantKind Kind); + + static VariantKind getVariantKindForName(StringRef Name); + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::SymbolRef; + } +}; + +/// Unary assembler expressions. +class MCUnaryExpr : public MCExpr { +public: + enum Opcode { + LNot, ///< Logical negation. + Minus, ///< Unary minus. + Not, ///< Bitwise negation. + Plus ///< Unary plus. + }; + +private: + Opcode Op; + const MCExpr *Expr; + + MCUnaryExpr(Opcode Op, const MCExpr *Expr, SMLoc Loc) + : MCExpr(MCExpr::Unary, Loc), Op(Op), Expr(Expr) {} + +public: + /// \name Construction + /// @{ + + static const MCUnaryExpr *create(Opcode Op, const MCExpr *Expr, + MCContext &Ctx, SMLoc Loc = SMLoc()); + + static const MCUnaryExpr *createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { + return create(LNot, Expr, Ctx, Loc); + } + + static const MCUnaryExpr *createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { + return create(Minus, Expr, Ctx, Loc); + } + + static const MCUnaryExpr *createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { + return create(Not, Expr, Ctx, Loc); + } + + static const MCUnaryExpr *createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { + return create(Plus, Expr, Ctx, Loc); + } + + /// @} + /// \name Accessors + /// @{ + + /// Get the kind of this unary expression. + Opcode getOpcode() const { return Op; } + + /// Get the child of this unary expression. + const MCExpr *getSubExpr() const { return Expr; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Unary; + } +}; + +/// Binary assembler expressions. +class MCBinaryExpr : public MCExpr { +public: + enum Opcode { + Add, ///< Addition. + And, ///< Bitwise and. + Div, ///< Signed division. + EQ, ///< Equality comparison. + GT, ///< Signed greater than comparison (result is either 0 or some + ///< target-specific non-zero value) + GTE, ///< Signed greater than or equal comparison (result is either 0 or + ///< some target-specific non-zero value). + LAnd, ///< Logical and. + LOr, ///< Logical or. + LT, ///< Signed less than comparison (result is either 0 or + ///< some target-specific non-zero value). + LTE, ///< Signed less than or equal comparison (result is either 0 or + ///< some target-specific non-zero value). + Mod, ///< Signed remainder. + Mul, ///< Multiplication. + NE, ///< Inequality comparison. + Or, ///< Bitwise or. + Shl, ///< Shift left. + AShr, ///< Arithmetic shift right. + LShr, ///< Logical shift right. + Sub, ///< Subtraction. + Xor ///< Bitwise exclusive or. + }; + +private: + Opcode Op; + const MCExpr *LHS, *RHS; + + MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, + SMLoc Loc = SMLoc()) + : MCExpr(MCExpr::Binary, Loc), Op(Op), LHS(LHS), RHS(RHS) {} + +public: + /// \name Construction + /// @{ + + static const MCBinaryExpr *create(Opcode Op, const MCExpr *LHS, + const MCExpr *RHS, MCContext &Ctx, + SMLoc Loc = SMLoc()); + + static const MCBinaryExpr *createAdd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Add, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createAnd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(And, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createDiv(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Div, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createEQ(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(EQ, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createGT(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(GT, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createGTE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(GTE, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createLAnd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(LAnd, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createLOr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(LOr, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createLT(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(LT, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createLTE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(LTE, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createMod(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Mod, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createMul(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Mul, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createNE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(NE, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createOr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Or, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createShl(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Shl, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createAShr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(AShr, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createLShr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(LShr, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createSub(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Sub, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createXor(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Xor, LHS, RHS, Ctx); + } + + /// @} + /// \name Accessors + /// @{ + + /// Get the kind of this binary expression. + Opcode getOpcode() const { return Op; } + + /// Get the left-hand side expression of the binary operator. + const MCExpr *getLHS() const { return LHS; } + + /// Get the right-hand side expression of the binary operator. + const MCExpr *getRHS() const { return RHS; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Binary; + } +}; + +/// This is an extension point for target-specific MCExpr subclasses to +/// implement. +/// +/// NOTE: All subclasses are required to have trivial destructors because +/// MCExprs are bump pointer allocated and not destructed. +class MCTargetExpr : public MCExpr { + virtual void anchor(); + +protected: + MCTargetExpr() : MCExpr(Target, SMLoc()) {} + virtual ~MCTargetExpr() = default; + +public: + virtual void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const = 0; + virtual bool evaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout, + const MCFixup *Fixup) const = 0; + // allow Target Expressions to be checked for equality + virtual bool isEqualTo(const MCExpr *x) const { return false; } + // This should be set when assigned expressions are not valid ".set" + // expressions, e.g. registers, and must be inlined. + virtual bool inlineAssignedExpr() const { return false; } + virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; + virtual MCFragment *findAssociatedFragment() const = 0; + + virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0; + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCEXPR_H diff --git a/clang-r353983/include/llvm/MC/MCFixedLenDisassembler.h b/clang-r353983/include/llvm/MC/MCFixedLenDisassembler.h new file mode 100644 index 00000000..218ae0d1 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCFixedLenDisassembler.h @@ -0,0 +1,33 @@ +//===-- llvm/MC/MCFixedLenDisassembler.h - Decoder driver -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Fixed length disassembler decoder state machine driver. +//===----------------------------------------------------------------------===// +#ifndef LLVM_MC_MCFIXEDLENDISASSEMBLER_H +#define LLVM_MC_MCFIXEDLENDISASSEMBLER_H + +namespace llvm { + +namespace MCD { +// Disassembler state machine opcodes. +enum DecoderOps { + OPC_ExtractField = 1, // OPC_ExtractField(uint8_t Start, uint8_t Len) + OPC_FilterValue, // OPC_FilterValue(uleb128 Val, uint16_t NumToSkip) + OPC_CheckField, // OPC_CheckField(uint8_t Start, uint8_t Len, + // uleb128 Val, uint16_t NumToSkip) + OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, uint16_t NumToSkip) + OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx) + OPC_TryDecode, // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx, + // uint16_t NumToSkip) + OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask) + OPC_Fail // OPC_Fail() +}; + +} // namespace MCDecode +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCFixup.h b/clang-r353983/include/llvm/MC/MCFixup.h new file mode 100644 index 00000000..559a19e9 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCFixup.h @@ -0,0 +1,170 @@ +//===-- llvm/MC/MCFixup.h - Instruction Relocation and Patching -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCFIXUP_H +#define LLVM_MC_MCFIXUP_H + +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SMLoc.h" +#include <cassert> + +namespace llvm { +class MCExpr; + +/// Extensible enumeration to represent the type of a fixup. +enum MCFixupKind { + FK_Data_1 = 0, ///< A one-byte fixup. + FK_Data_2, ///< A two-byte fixup. + FK_Data_4, ///< A four-byte fixup. + FK_Data_8, ///< A eight-byte fixup. + FK_PCRel_1, ///< A one-byte pc relative fixup. + FK_PCRel_2, ///< A two-byte pc relative fixup. + FK_PCRel_4, ///< A four-byte pc relative fixup. + FK_PCRel_8, ///< A eight-byte pc relative fixup. + FK_GPRel_1, ///< A one-byte gp relative fixup. + FK_GPRel_2, ///< A two-byte gp relative fixup. + FK_GPRel_4, ///< A four-byte gp relative fixup. + FK_GPRel_8, ///< A eight-byte gp relative fixup. + FK_DTPRel_4, ///< A four-byte dtp relative fixup. + FK_DTPRel_8, ///< A eight-byte dtp relative fixup. + FK_TPRel_4, ///< A four-byte tp relative fixup. + FK_TPRel_8, ///< A eight-byte tp relative fixup. + FK_SecRel_1, ///< A one-byte section relative fixup. + FK_SecRel_2, ///< A two-byte section relative fixup. + FK_SecRel_4, ///< A four-byte section relative fixup. + FK_SecRel_8, ///< A eight-byte section relative fixup. + FK_Data_Add_1, ///< A one-byte add fixup. + FK_Data_Add_2, ///< A two-byte add fixup. + FK_Data_Add_4, ///< A four-byte add fixup. + FK_Data_Add_8, ///< A eight-byte add fixup. + FK_Data_Sub_1, ///< A one-byte sub fixup. + FK_Data_Sub_2, ///< A two-byte sub fixup. + FK_Data_Sub_4, ///< A four-byte sub fixup. + FK_Data_Sub_8, ///< A eight-byte sub fixup. + + FirstTargetFixupKind = 128, + + // Limit range of target fixups, in case we want to pack more efficiently + // later. + MaxTargetFixupKind = (1 << 8) +}; + +/// Encode information on a single operation to perform on a byte +/// sequence (e.g., an encoded instruction) which requires assemble- or run- +/// time patching. +/// +/// Fixups are used any time the target instruction encoder needs to represent +/// some value in an instruction which is not yet concrete. The encoder will +/// encode the instruction assuming the value is 0, and emit a fixup which +/// communicates to the assembler backend how it should rewrite the encoded +/// value. +/// +/// During the process of relaxation, the assembler will apply fixups as +/// symbolic values become concrete. When relaxation is complete, any remaining +/// fixups become relocations in the object file (or errors, if the fixup cannot +/// be encoded on the target). +class MCFixup { + /// The value to put into the fixup location. The exact interpretation of the + /// expression is target dependent, usually it will be one of the operands to + /// an instruction or an assembler directive. + const MCExpr *Value; + + /// The byte index of start of the relocation inside the MCFragment. + uint32_t Offset; + + /// The target dependent kind of fixup item this is. The kind is used to + /// determine how the operand value should be encoded into the instruction. + unsigned Kind; + + /// The source location which gave rise to the fixup, if any. + SMLoc Loc; +public: + static MCFixup create(uint32_t Offset, const MCExpr *Value, + MCFixupKind Kind, SMLoc Loc = SMLoc()) { + assert(unsigned(Kind) < MaxTargetFixupKind && "Kind out of range!"); + MCFixup FI; + FI.Value = Value; + FI.Offset = Offset; + FI.Kind = unsigned(Kind); + FI.Loc = Loc; + return FI; + } + + /// Return a fixup corresponding to the add half of a add/sub fixup pair for + /// the given Fixup. + static MCFixup createAddFor(const MCFixup &Fixup) { + MCFixup FI; + FI.Value = Fixup.getValue(); + FI.Offset = Fixup.getOffset(); + FI.Kind = (unsigned)getAddKindForKind(Fixup.getKind()); + FI.Loc = Fixup.getLoc(); + return FI; + } + + /// Return a fixup corresponding to the sub half of a add/sub fixup pair for + /// the given Fixup. + static MCFixup createSubFor(const MCFixup &Fixup) { + MCFixup FI; + FI.Value = Fixup.getValue(); + FI.Offset = Fixup.getOffset(); + FI.Kind = (unsigned)getSubKindForKind(Fixup.getKind()); + FI.Loc = Fixup.getLoc(); + return FI; + } + + MCFixupKind getKind() const { return MCFixupKind(Kind); } + + uint32_t getOffset() const { return Offset; } + void setOffset(uint32_t Value) { Offset = Value; } + + const MCExpr *getValue() const { return Value; } + + /// Return the generic fixup kind for a value with the given size. It + /// is an error to pass an unsupported size. + static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) { + switch (Size) { + default: llvm_unreachable("Invalid generic fixup size!"); + case 1: return isPCRel ? FK_PCRel_1 : FK_Data_1; + case 2: return isPCRel ? FK_PCRel_2 : FK_Data_2; + case 4: return isPCRel ? FK_PCRel_4 : FK_Data_4; + case 8: return isPCRel ? FK_PCRel_8 : FK_Data_8; + } + } + + /// Return the generic fixup kind for an addition with a given size. It + /// is an error to pass an unsupported size. + static MCFixupKind getAddKindForKind(unsigned Kind) { + switch (Kind) { + default: llvm_unreachable("Unknown type to convert!"); + case FK_Data_1: return FK_Data_Add_1; + case FK_Data_2: return FK_Data_Add_2; + case FK_Data_4: return FK_Data_Add_4; + case FK_Data_8: return FK_Data_Add_8; + } + } + + /// Return the generic fixup kind for an subtraction with a given size. It + /// is an error to pass an unsupported size. + static MCFixupKind getSubKindForKind(unsigned Kind) { + switch (Kind) { + default: llvm_unreachable("Unknown type to convert!"); + case FK_Data_1: return FK_Data_Sub_1; + case FK_Data_2: return FK_Data_Sub_2; + case FK_Data_4: return FK_Data_Sub_4; + case FK_Data_8: return FK_Data_Sub_8; + } + } + + SMLoc getLoc() const { return Loc; } +}; + +} // End llvm namespace + +#endif diff --git a/clang-r353983/include/llvm/MC/MCFixupKindInfo.h b/clang-r353983/include/llvm/MC/MCFixupKindInfo.h new file mode 100644 index 00000000..0ea34866 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCFixupKindInfo.h @@ -0,0 +1,42 @@ +//===-- llvm/MC/MCFixupKindInfo.h - Fixup Descriptors -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCFIXUPKINDINFO_H +#define LLVM_MC_MCFIXUPKINDINFO_H + +namespace llvm { + +/// Target independent information on a fixup kind. +struct MCFixupKindInfo { + enum FixupKindFlags { + /// Is this fixup kind PCrelative? This is used by the assembler backend to + /// evaluate fixup values in a target independent manner when possible. + FKF_IsPCRel = (1 << 0), + + /// Should this fixup kind force a 4-byte aligned effective PC value? + FKF_IsAlignedDownTo32Bits = (1 << 1) + }; + + /// A target specific name for the fixup kind. The names will be unique for + /// distinct kinds on any given target. + const char *Name; + + /// The bit offset to write the relocation into. + unsigned TargetOffset; + + /// The number of bits written by this fixup. The bits are assumed to be + /// contiguous. + unsigned TargetSize; + + /// Flags describing additional information on this fixup kind. + unsigned Flags; +}; + +} // End llvm namespace + +#endif diff --git a/clang-r353983/include/llvm/MC/MCFragment.h b/clang-r353983/include/llvm/MC/MCFragment.h new file mode 100644 index 00000000..aadf2ce7 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCFragment.h @@ -0,0 +1,667 @@ +//===- MCFragment.h - Fragment type hierarchy -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCFRAGMENT_H +#define LLVM_MC_MCFRAGMENT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/SMLoc.h" +#include <cstdint> +#include <utility> + +namespace llvm { + +class MCSection; +class MCSubtargetInfo; +class MCSymbol; + +class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> { + friend class MCAsmLayout; + +public: + enum FragmentType : uint8_t { + FT_Align, + FT_Data, + FT_CompactEncodedInst, + FT_Fill, + FT_Relaxable, + FT_Org, + FT_Dwarf, + FT_DwarfFrame, + FT_LEB, + FT_Padding, + FT_SymbolId, + FT_CVInlineLines, + FT_CVDefRange, + FT_Dummy + }; + +private: + FragmentType Kind; + +protected: + bool HasInstructions; + +private: + /// LayoutOrder - The layout order of this fragment. + unsigned LayoutOrder; + + /// The data for the section this fragment is in. + MCSection *Parent; + + /// Atom - The atom this fragment is in, as represented by its defining + /// symbol. + const MCSymbol *Atom; + + /// \name Assembler Backend Data + /// @{ + // + // FIXME: This could all be kept private to the assembler implementation. + + /// Offset - The offset of this fragment in its section. This is ~0 until + /// initialized. + uint64_t Offset; + + /// @} + +protected: + MCFragment(FragmentType Kind, bool HasInstructions, + MCSection *Parent = nullptr); + + ~MCFragment(); + +public: + MCFragment() = delete; + MCFragment(const MCFragment &) = delete; + MCFragment &operator=(const MCFragment &) = delete; + + /// Destroys the current fragment. + /// + /// This must be used instead of delete as MCFragment is non-virtual. + /// This method will dispatch to the appropriate subclass. + void destroy(); + + FragmentType getKind() const { return Kind; } + + MCSection *getParent() const { return Parent; } + void setParent(MCSection *Value) { Parent = Value; } + + const MCSymbol *getAtom() const { return Atom; } + void setAtom(const MCSymbol *Value) { Atom = Value; } + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + + /// Does this fragment have instructions emitted into it? By default + /// this is false, but specific fragment types may set it to true. + bool hasInstructions() const { return HasInstructions; } + + /// Return true if given frgment has FT_Dummy type. + bool isDummy() const { return Kind == FT_Dummy; } + + void dump() const; +}; + +class MCDummyFragment : public MCFragment { +public: + explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {} + + static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data. +/// +class MCEncodedFragment : public MCFragment { + /// Should this fragment be aligned to the end of a bundle? + bool AlignToBundleEnd = false; + + uint8_t BundlePadding = 0; + +protected: + MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions, + MCSection *Sec) + : MCFragment(FType, HasInstructions, Sec) {} + + /// STI - The MCSubtargetInfo in effect when the instruction was encoded. + /// must be non-null for instructions. + const MCSubtargetInfo *STI = nullptr; + +public: + static bool classof(const MCFragment *F) { + MCFragment::FragmentType Kind = F->getKind(); + switch (Kind) { + default: + return false; + case MCFragment::FT_Relaxable: + case MCFragment::FT_CompactEncodedInst: + case MCFragment::FT_Data: + case MCFragment::FT_Dwarf: + return true; + } + } + + /// Should this fragment be placed at the end of an aligned bundle? + bool alignToBundleEnd() const { return AlignToBundleEnd; } + void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } + + /// Get the padding size that must be inserted before this fragment. + /// Used for bundling. By default, no padding is inserted. + /// Note that padding size is restricted to 8 bits. This is an optimization + /// to reduce the amount of space used for each fragment. In practice, larger + /// padding should never be required. + uint8_t getBundlePadding() const { return BundlePadding; } + + /// Set the padding size for this fragment. By default it's a no-op, + /// and only some fragments have a meaningful implementation. + void setBundlePadding(uint8_t N) { BundlePadding = N; } + + /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded. + /// Guaranteed to be non-null if hasInstructions() == true + const MCSubtargetInfo *getSubtargetInfo() const { return STI; } + + /// Record that the fragment contains instructions with the MCSubtargetInfo in + /// effect when the instruction was encoded. + void setHasInstructions(const MCSubtargetInfo &STI) { + HasInstructions = true; + this->STI = &STI; + } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data. +/// +template<unsigned ContentsSize> +class MCEncodedFragmentWithContents : public MCEncodedFragment { + SmallVector<char, ContentsSize> Contents; + +protected: + MCEncodedFragmentWithContents(MCFragment::FragmentType FType, + bool HasInstructions, + MCSection *Sec) + : MCEncodedFragment(FType, HasInstructions, Sec) {} + +public: + SmallVectorImpl<char> &getContents() { return Contents; } + const SmallVectorImpl<char> &getContents() const { return Contents; } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data and also have fixups registered. +/// +template<unsigned ContentsSize, unsigned FixupsSize> +class MCEncodedFragmentWithFixups : + public MCEncodedFragmentWithContents<ContentsSize> { + + /// Fixups - The list of fixups in this fragment. + SmallVector<MCFixup, FixupsSize> Fixups; + +protected: + MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, + bool HasInstructions, + MCSection *Sec) + : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions, + Sec) {} + +public: + + using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator; + using fixup_iterator = SmallVectorImpl<MCFixup>::iterator; + + SmallVectorImpl<MCFixup> &getFixups() { return Fixups; } + const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; } + + fixup_iterator fixup_begin() { return Fixups.begin(); } + const_fixup_iterator fixup_begin() const { return Fixups.begin(); } + + fixup_iterator fixup_end() { return Fixups.end(); } + const_fixup_iterator fixup_end() const { return Fixups.end(); } + + static bool classof(const MCFragment *F) { + MCFragment::FragmentType Kind = F->getKind(); + return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data || + Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf;; + } +}; + +/// Fragment for data and encoded instructions. +/// +class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> { +public: + MCDataFragment(MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Data; + } +}; + +/// This is a compact (memory-size-wise) fragment for holding an encoded +/// instruction (non-relaxable) that has no fixups registered. When applicable, +/// it can be used instead of MCDataFragment and lead to lower memory +/// consumption. +/// +class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> { +public: + MCCompactEncodedInstFragment(MCSection *Sec = nullptr) + : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) { + } + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_CompactEncodedInst; + } +}; + +/// A relaxable fragment holds on to its MCInst, since it may need to be +/// relaxed during the assembler layout and relaxation stage. +/// +class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> { + + /// Inst - The instruction this is a fragment for. + MCInst Inst; + +public: + MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI, + MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec), + Inst(Inst) { this->STI = &STI; } + + const MCInst &getInst() const { return Inst; } + void setInst(const MCInst &Value) { Inst = Value; } + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Relaxable; + } +}; + +class MCAlignFragment : public MCFragment { + /// Alignment - The alignment to ensure, in bytes. + unsigned Alignment; + + /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead + /// of using the provided value. The exact interpretation of this flag is + /// target dependent. + bool EmitNops : 1; + + /// Value - Value to use for filling padding bytes. + int64_t Value; + + /// ValueSize - The size of the integer (in bytes) of \p Value. + unsigned ValueSize; + + /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment + /// cannot be satisfied in this width then this fragment is ignored. + unsigned MaxBytesToEmit; + +public: + MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize, + unsigned MaxBytesToEmit, MCSection *Sec = nullptr) + : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false), + Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {} + + /// \name Accessors + /// @{ + + unsigned getAlignment() const { return Alignment; } + + int64_t getValue() const { return Value; } + + unsigned getValueSize() const { return ValueSize; } + + unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } + + bool hasEmitNops() const { return EmitNops; } + void setEmitNops(bool Value) { EmitNops = Value; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Align; + } +}; + +/// Fragment for adding required padding. +/// This fragment is always inserted before an instruction, and holds that +/// instruction as context information (as well as a mask of kinds) for +/// determining the padding size. +/// +class MCPaddingFragment : public MCFragment { + /// A mask containing all the kinds relevant to this fragment. i.e. the i'th + /// bit will be set iff kind i is relevant to this fragment. + uint64_t PaddingPoliciesMask; + /// A boolean indicating if this fragment will actually hold padding. If its + /// value is false, then this fragment serves only as a placeholder, + /// containing data to assist other insertion point in their decision making. + bool IsInsertionPoint; + + uint64_t Size; + + struct MCInstInfo { + bool IsInitialized; + MCInst Inst; + /// A boolean indicating whether the instruction pointed by this fragment is + /// a fixed size instruction or a relaxable instruction held by a + /// MCRelaxableFragment. + bool IsImmutableSizedInst; + union { + /// If the instruction is a fixed size instruction, hold its size. + size_t InstSize; + /// Otherwise, hold a pointer to the MCRelaxableFragment holding it. + MCRelaxableFragment *InstFragment; + }; + }; + MCInstInfo InstInfo; + +public: + static const uint64_t PFK_None = UINT64_C(0); + + enum MCPaddingFragmentKind { + // values 0-7 are reserved for future target independet values. + + FirstTargetPerfNopFragmentKind = 8, + + /// Limit range of target MCPerfNopFragment kinds to fit in uint64_t + MaxTargetPerfNopFragmentKind = 63 + }; + + MCPaddingFragment(MCSection *Sec = nullptr) + : MCFragment(FT_Padding, false, Sec), PaddingPoliciesMask(PFK_None), + IsInsertionPoint(false), Size(UINT64_C(0)), + InstInfo({false, MCInst(), false, {0}}) {} + + bool isInsertionPoint() const { return IsInsertionPoint; } + void setAsInsertionPoint() { IsInsertionPoint = true; } + uint64_t getPaddingPoliciesMask() const { return PaddingPoliciesMask; } + void setPaddingPoliciesMask(uint64_t Value) { PaddingPoliciesMask = Value; } + bool hasPaddingPolicy(uint64_t PolicyMask) const { + assert(isPowerOf2_64(PolicyMask) && + "Policy mask must contain exactly one policy"); + return (getPaddingPoliciesMask() & PolicyMask) != PFK_None; + } + const MCInst &getInst() const { + assert(isInstructionInitialized() && "Fragment has no instruction!"); + return InstInfo.Inst; + } + size_t getInstSize() const { + assert(isInstructionInitialized() && "Fragment has no instruction!"); + if (InstInfo.IsImmutableSizedInst) + return InstInfo.InstSize; + assert(InstInfo.InstFragment != nullptr && + "Must have a valid InstFragment to retrieve InstSize from"); + return InstInfo.InstFragment->getContents().size(); + } + void setInstAndInstSize(const MCInst &Inst, size_t InstSize) { + InstInfo.IsInitialized = true; + InstInfo.IsImmutableSizedInst = true; + InstInfo.Inst = Inst; + InstInfo.InstSize = InstSize; + } + void setInstAndInstFragment(const MCInst &Inst, + MCRelaxableFragment *InstFragment) { + InstInfo.IsInitialized = true; + InstInfo.IsImmutableSizedInst = false; + InstInfo.Inst = Inst; + InstInfo.InstFragment = InstFragment; + } + uint64_t getSize() const { return Size; } + void setSize(uint64_t Value) { Size = Value; } + bool isInstructionInitialized() const { return InstInfo.IsInitialized; } + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Padding; + } +}; + +class MCFillFragment : public MCFragment { + /// Value to use for filling bytes. + uint64_t Value; + uint8_t ValueSize; + /// The number of bytes to insert. + const MCExpr &NumValues; + + /// Source location of the directive that this fragment was created for. + SMLoc Loc; + +public: + MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues, + SMLoc Loc, MCSection *Sec = nullptr) + : MCFragment(FT_Fill, false, Sec), Value(Value), ValueSize(VSize), + NumValues(NumValues), Loc(Loc) {} + + uint64_t getValue() const { return Value; } + uint8_t getValueSize() const { return ValueSize; } + const MCExpr &getNumValues() const { return NumValues; } + + SMLoc getLoc() const { return Loc; } + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Fill; + } +}; + +class MCOrgFragment : public MCFragment { + /// The offset this fragment should start at. + const MCExpr *Offset; + + /// Value to use for filling bytes. + int8_t Value; + + /// Source location of the directive that this fragment was created for. + SMLoc Loc; + +public: + MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc, + MCSection *Sec = nullptr) + : MCFragment(FT_Org, false, Sec), Offset(&Offset), Value(Value), Loc(Loc) {} + + /// \name Accessors + /// @{ + + const MCExpr &getOffset() const { return *Offset; } + + uint8_t getValue() const { return Value; } + + SMLoc getLoc() const { return Loc; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Org; + } +}; + +class MCLEBFragment : public MCFragment { + /// Value - The value this fragment should contain. + const MCExpr *Value; + + /// IsSigned - True if this is a sleb128, false if uleb128. + bool IsSigned; + + SmallString<8> Contents; + +public: + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr) + : MCFragment(FT_LEB, false, Sec), Value(&Value_), IsSigned(IsSigned_) { + Contents.push_back(0); + } + + /// \name Accessors + /// @{ + + const MCExpr &getValue() const { return *Value; } + + bool isSigned() const { return IsSigned; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_LEB; + } +}; + +class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> { + /// LineDelta - the value of the difference between the two line numbers + /// between two .loc dwarf directives. + int64_t LineDelta; + + /// AddrDelta - The expression for the difference of the two symbols that + /// make up the address delta between two .loc dwarf directives. + const MCExpr *AddrDelta; + +public: + MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta, + MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec), + LineDelta(LineDelta), AddrDelta(&AddrDelta) {} + + /// \name Accessors + /// @{ + + int64_t getLineDelta() const { return LineDelta; } + + const MCExpr &getAddrDelta() const { return *AddrDelta; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Dwarf; + } +}; + +class MCDwarfCallFrameFragment : public MCFragment { + /// AddrDelta - The expression for the difference of the two symbols that + /// make up the address delta between two .cfi_* dwarf directives. + const MCExpr *AddrDelta; + + SmallString<8> Contents; + +public: + MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) + : MCFragment(FT_DwarfFrame, false, Sec), AddrDelta(&AddrDelta) { + Contents.push_back(0); + } + + /// \name Accessors + /// @{ + + const MCExpr &getAddrDelta() const { return *AddrDelta; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_DwarfFrame; + } +}; + +/// Represents a symbol table index fragment. +class MCSymbolIdFragment : public MCFragment { + const MCSymbol *Sym; + +public: + MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr) + : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {} + + /// \name Accessors + /// @{ + + const MCSymbol *getSymbol() { return Sym; } + const MCSymbol *getSymbol() const { return Sym; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_SymbolId; + } +}; + +/// Fragment representing the binary annotations produced by the +/// .cv_inline_linetable directive. +class MCCVInlineLineTableFragment : public MCFragment { + unsigned SiteFuncId; + unsigned StartFileId; + unsigned StartLineNum; + const MCSymbol *FnStartSym; + const MCSymbol *FnEndSym; + SmallString<8> Contents; + + /// CodeViewContext has the real knowledge about this format, so let it access + /// our members. + friend class CodeViewContext; + +public: + MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId, + unsigned StartLineNum, const MCSymbol *FnStartSym, + const MCSymbol *FnEndSym, + MCSection *Sec = nullptr) + : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId), + StartFileId(StartFileId), StartLineNum(StartLineNum), + FnStartSym(FnStartSym), FnEndSym(FnEndSym) {} + + /// \name Accessors + /// @{ + + const MCSymbol *getFnStartSym() const { return FnStartSym; } + const MCSymbol *getFnEndSym() const { return FnEndSym; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_CVInlineLines; + } +}; + +/// Fragment representing the .cv_def_range directive. +class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> { + SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges; + SmallString<32> FixedSizePortion; + + /// CodeViewContext has the real knowledge about this format, so let it access + /// our members. + friend class CodeViewContext; + +public: + MCCVDefRangeFragment( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + StringRef FixedSizePortion, MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec), + Ranges(Ranges.begin(), Ranges.end()), + FixedSizePortion(FixedSizePortion) {} + + /// \name Accessors + /// @{ + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const { + return Ranges; + } + + StringRef getFixedSizePortion() const { return FixedSizePortion; } + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_CVDefRange; + } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCFRAGMENT_H diff --git a/clang-r353983/include/llvm/MC/MCInst.h b/clang-r353983/include/llvm/MC/MCInst.h new file mode 100644 index 00000000..9675b786 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCInst.h @@ -0,0 +1,224 @@ +//===- llvm/MC/MCInst.h - MCInst class --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCInst and MCOperand classes, which +// is the basic representation used to represent low-level machine code +// instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINST_H +#define LLVM_MC_MCINST_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SMLoc.h" +#include <cassert> +#include <cstddef> +#include <cstdint> + +namespace llvm { + +class MCExpr; +class MCInst; +class MCInstPrinter; +class raw_ostream; + +/// Instances of this class represent operands of the MCInst class. +/// This is a simple discriminated union. +class MCOperand { + enum MachineOperandType : unsigned char { + kInvalid, ///< Uninitialized. + kRegister, ///< Register operand. + kImmediate, ///< Immediate operand. + kFPImmediate, ///< Floating-point immediate operand. + kExpr, ///< Relocatable immediate operand. + kInst ///< Sub-instruction operand. + }; + MachineOperandType Kind = kInvalid; + + union { + unsigned RegVal; + int64_t ImmVal; + double FPImmVal; + const MCExpr *ExprVal; + const MCInst *InstVal; + }; + +public: + MCOperand() : FPImmVal(0.0) {} + + bool isValid() const { return Kind != kInvalid; } + bool isReg() const { return Kind == kRegister; } + bool isImm() const { return Kind == kImmediate; } + bool isFPImm() const { return Kind == kFPImmediate; } + bool isExpr() const { return Kind == kExpr; } + bool isInst() const { return Kind == kInst; } + + /// Returns the register number. + unsigned getReg() const { + assert(isReg() && "This is not a register operand!"); + return RegVal; + } + + /// Set the register number. + void setReg(unsigned Reg) { + assert(isReg() && "This is not a register operand!"); + RegVal = Reg; + } + + int64_t getImm() const { + assert(isImm() && "This is not an immediate"); + return ImmVal; + } + + void setImm(int64_t Val) { + assert(isImm() && "This is not an immediate"); + ImmVal = Val; + } + + double getFPImm() const { + assert(isFPImm() && "This is not an FP immediate"); + return FPImmVal; + } + + void setFPImm(double Val) { + assert(isFPImm() && "This is not an FP immediate"); + FPImmVal = Val; + } + + const MCExpr *getExpr() const { + assert(isExpr() && "This is not an expression"); + return ExprVal; + } + + void setExpr(const MCExpr *Val) { + assert(isExpr() && "This is not an expression"); + ExprVal = Val; + } + + const MCInst *getInst() const { + assert(isInst() && "This is not a sub-instruction"); + return InstVal; + } + + void setInst(const MCInst *Val) { + assert(isInst() && "This is not a sub-instruction"); + InstVal = Val; + } + + static MCOperand createReg(unsigned Reg) { + MCOperand Op; + Op.Kind = kRegister; + Op.RegVal = Reg; + return Op; + } + + static MCOperand createImm(int64_t Val) { + MCOperand Op; + Op.Kind = kImmediate; + Op.ImmVal = Val; + return Op; + } + + static MCOperand createFPImm(double Val) { + MCOperand Op; + Op.Kind = kFPImmediate; + Op.FPImmVal = Val; + return Op; + } + + static MCOperand createExpr(const MCExpr *Val) { + MCOperand Op; + Op.Kind = kExpr; + Op.ExprVal = Val; + return Op; + } + + static MCOperand createInst(const MCInst *Val) { + MCOperand Op; + Op.Kind = kInst; + Op.InstVal = Val; + return Op; + } + + void print(raw_ostream &OS) const; + void dump() const; + bool isBareSymbolRef() const; + bool evaluateAsConstantImm(int64_t &Imm) const; +}; + +/// Instances of this class represent a single low-level machine +/// instruction. +class MCInst { + unsigned Opcode = 0; + SMLoc Loc; + SmallVector<MCOperand, 8> Operands; + // These flags could be used to pass some info from one target subcomponent + // to another, for example, from disassembler to asm printer. The values of + // the flags have any sense on target level only (e.g. prefixes on x86). + unsigned Flags = 0; + +public: + MCInst() = default; + + void setOpcode(unsigned Op) { Opcode = Op; } + unsigned getOpcode() const { return Opcode; } + + void setFlags(unsigned F) { Flags = F; } + unsigned getFlags() const { return Flags; } + + void setLoc(SMLoc loc) { Loc = loc; } + SMLoc getLoc() const { return Loc; } + + const MCOperand &getOperand(unsigned i) const { return Operands[i]; } + MCOperand &getOperand(unsigned i) { return Operands[i]; } + unsigned getNumOperands() const { return Operands.size(); } + + void addOperand(const MCOperand &Op) { Operands.push_back(Op); } + + using iterator = SmallVectorImpl<MCOperand>::iterator; + using const_iterator = SmallVectorImpl<MCOperand>::const_iterator; + + void clear() { Operands.clear(); } + void erase(iterator I) { Operands.erase(I); } + size_t size() const { return Operands.size(); } + iterator begin() { return Operands.begin(); } + const_iterator begin() const { return Operands.begin(); } + iterator end() { return Operands.end(); } + const_iterator end() const { return Operands.end(); } + + iterator insert(iterator I, const MCOperand &Op) { + return Operands.insert(I, Op); + } + + void print(raw_ostream &OS) const; + void dump() const; + + /// Dump the MCInst as prettily as possible using the additional MC + /// structures, if given. Operators are separated by the \p Separator + /// string. + void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer = nullptr, + StringRef Separator = " ") const; + void dump_pretty(raw_ostream &OS, StringRef Name, + StringRef Separator = " ") const; +}; + +inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) { + MO.print(OS); + return OS; +} + +inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) { + MI.print(OS); + return OS; +} + +} // end namespace llvm + +#endif // LLVM_MC_MCINST_H diff --git a/clang-r353983/include/llvm/MC/MCInstBuilder.h b/clang-r353983/include/llvm/MC/MCInstBuilder.h new file mode 100644 index 00000000..0c8e01fd --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCInstBuilder.h @@ -0,0 +1,73 @@ +//===-- llvm/MC/MCInstBuilder.h - Simplify creation of MCInsts --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the MCInstBuilder class for convenient creation of +// MCInsts. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTBUILDER_H +#define LLVM_MC_MCINSTBUILDER_H + +#include "llvm/MC/MCInst.h" + +namespace llvm { + +class MCInstBuilder { + MCInst Inst; + +public: + /// Create a new MCInstBuilder for an MCInst with a specific opcode. + MCInstBuilder(unsigned Opcode) { + Inst.setOpcode(Opcode); + } + + /// Add a new register operand. + MCInstBuilder &addReg(unsigned Reg) { + Inst.addOperand(MCOperand::createReg(Reg)); + return *this; + } + + /// Add a new integer immediate operand. + MCInstBuilder &addImm(int64_t Val) { + Inst.addOperand(MCOperand::createImm(Val)); + return *this; + } + + /// Add a new floating point immediate operand. + MCInstBuilder &addFPImm(double Val) { + Inst.addOperand(MCOperand::createFPImm(Val)); + return *this; + } + + /// Add a new MCExpr operand. + MCInstBuilder &addExpr(const MCExpr *Val) { + Inst.addOperand(MCOperand::createExpr(Val)); + return *this; + } + + /// Add a new MCInst operand. + MCInstBuilder &addInst(const MCInst *Val) { + Inst.addOperand(MCOperand::createInst(Val)); + return *this; + } + + /// Add an operand. + MCInstBuilder &addOperand(const MCOperand &Op) { + Inst.addOperand(Op); + return *this; + } + + operator MCInst&() { + return Inst; + } +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCInstPrinter.h b/clang-r353983/include/llvm/MC/MCInstPrinter.h new file mode 100644 index 00000000..916aa892 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCInstPrinter.h @@ -0,0 +1,107 @@ +//===- MCInstPrinter.h - MCInst to target assembly syntax -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTPRINTER_H +#define LLVM_MC_MCINSTPRINTER_H + +#include "llvm/Support/Format.h" +#include <cstdint> + +namespace llvm { + +class MCAsmInfo; +class MCInst; +class MCInstrInfo; +class MCRegisterInfo; +class MCSubtargetInfo; +class raw_ostream; +class StringRef; + +/// Convert `Bytes' to a hex string and output to `OS' +void dumpBytes(ArrayRef<uint8_t> Bytes, raw_ostream &OS); + +namespace HexStyle { + +enum Style { + C, ///< 0xff + Asm ///< 0ffh +}; + +} // end namespace HexStyle + +/// This is an instance of a target assembly language printer that +/// converts an MCInst to valid target assembly syntax. +class MCInstPrinter { +protected: + /// A stream that comments can be emitted to if desired. Each comment + /// must end with a newline. This will be null if verbose assembly emission + /// is disabled. + raw_ostream *CommentStream = nullptr; + const MCAsmInfo &MAI; + const MCInstrInfo &MII; + const MCRegisterInfo &MRI; + + /// True if we are printing marked up assembly. + bool UseMarkup = false; + + /// True if we are printing immediates as hex. + bool PrintImmHex = false; + + /// Which style to use for printing hexadecimal values. + HexStyle::Style PrintHexStyle = HexStyle::C; + + /// Utility function for printing annotations. + void printAnnotation(raw_ostream &OS, StringRef Annot); + +public: + MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, + const MCRegisterInfo &mri) : MAI(mai), MII(mii), MRI(mri) {} + + virtual ~MCInstPrinter(); + + /// Specify a stream to emit comments to. + void setCommentStream(raw_ostream &OS) { CommentStream = &OS; } + + /// Print the specified MCInst to the specified raw_ostream. + virtual void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot, + const MCSubtargetInfo &STI) = 0; + + /// Return the name of the specified opcode enum (e.g. "MOV32ri") or + /// empty if we can't resolve it. + StringRef getOpcodeName(unsigned Opcode) const; + + /// Print the assembler register name. + virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; + + bool getUseMarkup() const { return UseMarkup; } + void setUseMarkup(bool Value) { UseMarkup = Value; } + + /// Utility functions to make adding mark ups simpler. + StringRef markup(StringRef s) const; + StringRef markup(StringRef a, StringRef b) const; + + bool getPrintImmHex() const { return PrintImmHex; } + void setPrintImmHex(bool Value) { PrintImmHex = Value; } + + HexStyle::Style getPrintHexStyle() const { return PrintHexStyle; } + void setPrintHexStyle(HexStyle::Style Value) { PrintHexStyle = Value; } + + /// Utility function to print immediates in decimal or hex. + format_object<int64_t> formatImm(int64_t Value) const { + return PrintImmHex ? formatHex(Value) : formatDec(Value); + } + + /// Utility functions to print decimal/hexadecimal values. + format_object<int64_t> formatDec(int64_t Value) const; + format_object<int64_t> formatHex(int64_t Value) const; + format_object<uint64_t> formatHex(uint64_t Value) const; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCINSTPRINTER_H diff --git a/clang-r353983/include/llvm/MC/MCInstrAnalysis.h b/clang-r353983/include/llvm/MC/MCInstrAnalysis.h new file mode 100644 index 00000000..dfefd7e7 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCInstrAnalysis.h @@ -0,0 +1,165 @@ +//===- llvm/MC/MCInstrAnalysis.h - InstrDesc target hooks -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the MCInstrAnalysis class which the MCTargetDescs can +// derive from to give additional information to MC. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTRANALYSIS_H +#define LLVM_MC_MCINSTRANALYSIS_H + +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" +#include <cstdint> + +namespace llvm { + +class MCRegisterInfo; +class Triple; + +class MCInstrAnalysis { +protected: + friend class Target; + + const MCInstrInfo *Info; + +public: + MCInstrAnalysis(const MCInstrInfo *Info) : Info(Info) {} + virtual ~MCInstrAnalysis() = default; + + virtual bool isBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isBranch(); + } + + virtual bool isConditionalBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isConditionalBranch(); + } + + virtual bool isUnconditionalBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isUnconditionalBranch(); + } + + virtual bool isIndirectBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isIndirectBranch(); + } + + virtual bool isCall(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isCall(); + } + + virtual bool isReturn(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isReturn(); + } + + virtual bool isTerminator(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isTerminator(); + } + + /// Returns true if at least one of the register writes performed by + /// \param Inst implicitly clears the upper portion of all super-registers. + /// + /// Example: on X86-64, a write to EAX implicitly clears the upper half of + /// RAX. Also (still on x86) an XMM write perfomed by an AVX 128-bit + /// instruction implicitly clears the upper portion of the correspondent + /// YMM register. + /// + /// This method also updates an APInt which is used as mask of register + /// writes. There is one bit for every explicit/implicit write performed by + /// the instruction. If a write implicitly clears its super-registers, then + /// the corresponding bit is set (vic. the corresponding bit is cleared). + /// + /// The first bits in the APint are related to explicit writes. The remaining + /// bits are related to implicit writes. The sequence of writes follows the + /// machine operand sequence. For implicit writes, the sequence is defined by + /// the MCInstrDesc. + /// + /// The assumption is that the bit-width of the APInt is correctly set by + /// the caller. The default implementation conservatively assumes that none of + /// the writes clears the upper portion of a super-register. + virtual bool clearsSuperRegisters(const MCRegisterInfo &MRI, + const MCInst &Inst, + APInt &Writes) const; + + /// Returns true if MI is a dependency breaking zero-idiom for the given + /// subtarget. + /// + /// Mask is used to identify input operands that have their dependency + /// broken. Each bit of the mask is associated with a specific input operand. + /// Bits associated with explicit input operands are laid out first in the + /// mask; implicit operands come after explicit operands. + /// + /// Dependencies are broken only for operands that have their corresponding bit + /// set. Operands that have their bit cleared, or that don't have a + /// corresponding bit in the mask don't have their dependency broken. Note + /// that Mask may not be big enough to describe all operands. The assumption + /// for operands that don't have a correspondent bit in the mask is that those + /// are still data dependent. + /// + /// The only exception to the rule is for when Mask has all zeroes. + /// A zero mask means: dependencies are broken for all explicit register + /// operands. + virtual bool isZeroIdiom(const MCInst &MI, APInt &Mask, + unsigned CPUID) const { + return false; + } + + /// Returns true if MI is a dependency breaking instruction for the + /// subtarget associated with CPUID . + /// + /// The value computed by a dependency breaking instruction is not dependent + /// on the inputs. An example of dependency breaking instruction on X86 is + /// `XOR %eax, %eax`. + /// + /// If MI is a dependency breaking instruction for subtarget CPUID, then Mask + /// can be inspected to identify independent operands. + /// + /// Essentially, each bit of the mask corresponds to an input operand. + /// Explicit operands are laid out first in the mask; implicit operands follow + /// explicit operands. Bits are set for operands that are independent. + /// + /// Note that the number of bits in Mask may not be equivalent to the sum of + /// explicit and implicit operands in MI. Operands that don't have a + /// corresponding bit in Mask are assumed "not independente". + /// + /// The only exception is for when Mask is all zeroes. That means: explicit + /// input operands of MI are independent. + virtual bool isDependencyBreaking(const MCInst &MI, APInt &Mask, + unsigned CPUID) const { + return isZeroIdiom(MI, Mask, CPUID); + } + + /// Returns true if MI is a candidate for move elimination. + /// + /// Different subtargets may apply different constraints to optimizable + /// register moves. For example, on most X86 subtargets, a candidate for move + /// elimination cannot specify the same register for both source and + /// destination. + virtual bool isOptimizableRegisterMove(const MCInst &MI, + unsigned CPUID) const { + return false; + } + + /// Given a branch instruction try to get the address the branch + /// targets. Return true on success, and the address in Target. + virtual bool + evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const; + + /// Returns (PLT virtual address, GOT virtual address) pairs for PLT entries. + virtual std::vector<std::pair<uint64_t, uint64_t>> + findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents, + uint64_t GotPltSectionVA, const Triple &TargetTriple) const { + return {}; + } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCINSTRANALYSIS_H diff --git a/clang-r353983/include/llvm/MC/MCInstrDesc.h b/clang-r353983/include/llvm/MC/MCInstrDesc.h new file mode 100644 index 00000000..ad5a3e9c --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCInstrDesc.h @@ -0,0 +1,602 @@ +//===-- llvm/MC/MCInstrDesc.h - Instruction Descriptors -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the MCOperandInfo and MCInstrDesc classes, which +// are used to describe target instructions and their operands. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTRDESC_H +#define LLVM_MC_MCINSTRDESC_H + +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/DataTypes.h" +#include <string> + +namespace llvm { + class MCInst; + class MCSubtargetInfo; + class FeatureBitset; + +//===----------------------------------------------------------------------===// +// Machine Operand Flags and Description +//===----------------------------------------------------------------------===// + +namespace MCOI { +// Operand constraints +enum OperandConstraint { + TIED_TO = 0, // Must be allocated the same register as. + EARLY_CLOBBER // Operand is an early clobber register operand +}; + +/// These are flags set on operands, but should be considered +/// private, all access should go through the MCOperandInfo accessors. +/// See the accessors for a description of what these are. +enum OperandFlags { LookupPtrRegClass = 0, Predicate, OptionalDef }; + +/// Operands are tagged with one of the values of this enum. +enum OperandType { + OPERAND_UNKNOWN = 0, + OPERAND_IMMEDIATE = 1, + OPERAND_REGISTER = 2, + OPERAND_MEMORY = 3, + OPERAND_PCREL = 4, + + OPERAND_FIRST_GENERIC = 6, + OPERAND_GENERIC_0 = 6, + OPERAND_GENERIC_1 = 7, + OPERAND_GENERIC_2 = 8, + OPERAND_GENERIC_3 = 9, + OPERAND_GENERIC_4 = 10, + OPERAND_GENERIC_5 = 11, + OPERAND_LAST_GENERIC = 11, + + OPERAND_FIRST_TARGET = 12, +}; + +} + +/// This holds information about one operand of a machine instruction, +/// indicating the register class for register operands, etc. +class MCOperandInfo { +public: + /// This specifies the register class enumeration of the operand + /// if the operand is a register. If isLookupPtrRegClass is set, then this is + /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to + /// get a dynamic register class. + int16_t RegClass; + + /// These are flags from the MCOI::OperandFlags enum. + uint8_t Flags; + + /// Information about the type of the operand. + uint8_t OperandType; + /// The lower 16 bits are used to specify which constraints are set. + /// The higher 16 bits are used to specify the value of constraints (4 bits + /// each). + uint32_t Constraints; + + /// Set if this operand is a pointer value and it requires a callback + /// to look up its register class. + bool isLookupPtrRegClass() const { + return Flags & (1 << MCOI::LookupPtrRegClass); + } + + /// Set if this is one of the operands that made up of the predicate + /// operand that controls an isPredicable() instruction. + bool isPredicate() const { return Flags & (1 << MCOI::Predicate); } + + /// Set if this operand is a optional def. + bool isOptionalDef() const { return Flags & (1 << MCOI::OptionalDef); } + + bool isGenericType() const { + return OperandType >= MCOI::OPERAND_FIRST_GENERIC && + OperandType <= MCOI::OPERAND_LAST_GENERIC; + } + + unsigned getGenericTypeIndex() const { + assert(isGenericType() && "non-generic types don't have an index"); + return OperandType - MCOI::OPERAND_FIRST_GENERIC; + } +}; + +//===----------------------------------------------------------------------===// +// Machine Instruction Flags and Description +//===----------------------------------------------------------------------===// + +namespace MCID { +/// These should be considered private to the implementation of the +/// MCInstrDesc class. Clients should use the predicate methods on MCInstrDesc, +/// not use these directly. These all correspond to bitfields in the +/// MCInstrDesc::Flags field. +enum Flag { + Variadic = 0, + HasOptionalDef, + Pseudo, + Return, + EHScopeReturn, + Call, + Barrier, + Terminator, + Branch, + IndirectBranch, + Compare, + MoveImm, + MoveReg, + Bitcast, + Select, + DelaySlot, + FoldableAsLoad, + MayLoad, + MayStore, + Predicable, + NotDuplicable, + UnmodeledSideEffects, + Commutable, + ConvertibleTo3Addr, + UsesCustomInserter, + HasPostISelHook, + Rematerializable, + CheapAsAMove, + ExtraSrcRegAllocReq, + ExtraDefRegAllocReq, + RegSequence, + ExtractSubreg, + InsertSubreg, + Convergent, + Add, + Trap, + VariadicOpsAreDefs, +}; +} + +/// Describe properties that are true of each instruction in the target +/// description file. This captures information about side effects, register +/// use and many other things. There is one instance of this struct for each +/// target instruction class, and the MachineInstr class points to this struct +/// directly to describe itself. +class MCInstrDesc { +public: + unsigned short Opcode; // The opcode number + unsigned short NumOperands; // Num of args (may be more if variable_ops) + unsigned char NumDefs; // Num of args that are definitions + unsigned char Size; // Number of bytes in encoding. + unsigned short SchedClass; // enum identifying instr sched class + uint64_t Flags; // Flags identifying machine instr class + uint64_t TSFlags; // Target Specific Flag values + const MCPhysReg *ImplicitUses; // Registers implicitly read by this instr + const MCPhysReg *ImplicitDefs; // Registers implicitly defined by this instr + const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands + // Subtarget feature that this is deprecated on, if any + // -1 implies this is not deprecated by any single feature. It may still be + // deprecated due to a "complex" reason, below. + int64_t DeprecatedFeature; + + // A complex method to determine if a certain instruction is deprecated or + // not, and return the reason for deprecation. + bool (*ComplexDeprecationInfo)(MCInst &, const MCSubtargetInfo &, + std::string &); + + /// Returns the value of the specific constraint if + /// it is set. Returns -1 if it is not set. + int getOperandConstraint(unsigned OpNum, + MCOI::OperandConstraint Constraint) const { + if (OpNum < NumOperands && + (OpInfo[OpNum].Constraints & (1 << Constraint))) { + unsigned Pos = 16 + Constraint * 4; + return (int)(OpInfo[OpNum].Constraints >> Pos) & 0xf; + } + return -1; + } + + /// Returns true if a certain instruction is deprecated and if so + /// returns the reason in \p Info. + bool getDeprecatedInfo(MCInst &MI, const MCSubtargetInfo &STI, + std::string &Info) const; + + /// Return the opcode number for this descriptor. + unsigned getOpcode() const { return Opcode; } + + /// Return the number of declared MachineOperands for this + /// MachineInstruction. Note that variadic (isVariadic() returns true) + /// instructions may have additional operands at the end of the list, and note + /// that the machine instruction may include implicit register def/uses as + /// well. + unsigned getNumOperands() const { return NumOperands; } + + using const_opInfo_iterator = const MCOperandInfo *; + + const_opInfo_iterator opInfo_begin() const { return OpInfo; } + const_opInfo_iterator opInfo_end() const { return OpInfo + NumOperands; } + + iterator_range<const_opInfo_iterator> operands() const { + return make_range(opInfo_begin(), opInfo_end()); + } + + /// Return the number of MachineOperands that are register + /// definitions. Register definitions always occur at the start of the + /// machine operand list. This is the number of "outs" in the .td file, + /// and does not include implicit defs. + unsigned getNumDefs() const { return NumDefs; } + + /// Return flags of this instruction. + uint64_t getFlags() const { return Flags; } + + /// Return true if this instruction can have a variable number of + /// operands. In this case, the variable operands will be after the normal + /// operands but before the implicit definitions and uses (if any are + /// present). + bool isVariadic() const { return Flags & (1ULL << MCID::Variadic); } + + /// Set if this instruction has an optional definition, e.g. + /// ARM instructions which can set condition code if 's' bit is set. + bool hasOptionalDef() const { return Flags & (1ULL << MCID::HasOptionalDef); } + + /// Return true if this is a pseudo instruction that doesn't + /// correspond to a real machine instruction. + bool isPseudo() const { return Flags & (1ULL << MCID::Pseudo); } + + /// Return true if the instruction is a return. + bool isReturn() const { return Flags & (1ULL << MCID::Return); } + + /// Return true if the instruction is an add instruction. + bool isAdd() const { return Flags & (1ULL << MCID::Add); } + + /// Return true if this instruction is a trap. + bool isTrap() const { return Flags & (1ULL << MCID::Trap); } + + /// Return true if the instruction is a register to register move. + bool isMoveReg() const { return Flags & (1ULL << MCID::MoveReg); } + + /// Return true if the instruction is a call. + bool isCall() const { return Flags & (1ULL << MCID::Call); } + + /// Returns true if the specified instruction stops control flow + /// from executing the instruction immediately following it. Examples include + /// unconditional branches and return instructions. + bool isBarrier() const { return Flags & (1ULL << MCID::Barrier); } + + /// Returns true if this instruction part of the terminator for + /// a basic block. Typically this is things like return and branch + /// instructions. + /// + /// Various passes use this to insert code into the bottom of a basic block, + /// but before control flow occurs. + bool isTerminator() const { return Flags & (1ULL << MCID::Terminator); } + + /// Returns true if this is a conditional, unconditional, or + /// indirect branch. Predicates below can be used to discriminate between + /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to + /// get more information. + bool isBranch() const { return Flags & (1ULL << MCID::Branch); } + + /// Return true if this is an indirect branch, such as a + /// branch through a register. + bool isIndirectBranch() const { return Flags & (1ULL << MCID::IndirectBranch); } + + /// Return true if this is a branch which may fall + /// through to the next instruction or may transfer control flow to some other + /// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more + /// information about this branch. + bool isConditionalBranch() const { + return isBranch() & !isBarrier() & !isIndirectBranch(); + } + + /// Return true if this is a branch which always + /// transfers control flow to some other block. The + /// TargetInstrInfo::AnalyzeBranch method can be used to get more information + /// about this branch. + bool isUnconditionalBranch() const { + return isBranch() & isBarrier() & !isIndirectBranch(); + } + + /// Return true if this is a branch or an instruction which directly + /// writes to the program counter. Considered 'may' affect rather than + /// 'does' affect as things like predication are not taken into account. + bool mayAffectControlFlow(const MCInst &MI, const MCRegisterInfo &RI) const; + + /// Return true if this instruction has a predicate operand + /// that controls execution. It may be set to 'always', or may be set to other + /// values. There are various methods in TargetInstrInfo that can be used to + /// control and modify the predicate in this instruction. + bool isPredicable() const { return Flags & (1ULL << MCID::Predicable); } + + /// Return true if this instruction is a comparison. + bool isCompare() const { return Flags & (1ULL << MCID::Compare); } + + /// Return true if this instruction is a move immediate + /// (including conditional moves) instruction. + bool isMoveImmediate() const { return Flags & (1ULL << MCID::MoveImm); } + + /// Return true if this instruction is a bitcast instruction. + bool isBitcast() const { return Flags & (1ULL << MCID::Bitcast); } + + /// Return true if this is a select instruction. + bool isSelect() const { return Flags & (1ULL << MCID::Select); } + + /// Return true if this instruction cannot be safely + /// duplicated. For example, if the instruction has a unique labels attached + /// to it, duplicating it would cause multiple definition errors. + bool isNotDuplicable() const { return Flags & (1ULL << MCID::NotDuplicable); } + + /// Returns true if the specified instruction has a delay slot which + /// must be filled by the code generator. + bool hasDelaySlot() const { return Flags & (1ULL << MCID::DelaySlot); } + + /// Return true for instructions that can be folded as memory operands + /// in other instructions. The most common use for this is instructions that + /// are simple loads from memory that don't modify the loaded value in any + /// way, but it can also be used for instructions that can be expressed as + /// constant-pool loads, such as V_SETALLONES on x86, to allow them to be + /// folded when it is beneficial. This should only be set on instructions + /// that return a value in their only virtual register definition. + bool canFoldAsLoad() const { return Flags & (1ULL << MCID::FoldableAsLoad); } + + /// Return true if this instruction behaves + /// the same way as the generic REG_SEQUENCE instructions. + /// E.g., on ARM, + /// dX VMOVDRR rY, rZ + /// is equivalent to + /// dX = REG_SEQUENCE rY, ssub_0, rZ, ssub_1. + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getRegSequenceLikeInputs has to be + /// override accordingly. + bool isRegSequenceLike() const { return Flags & (1ULL << MCID::RegSequence); } + + /// Return true if this instruction behaves + /// the same way as the generic EXTRACT_SUBREG instructions. + /// E.g., on ARM, + /// rX, rY VMOVRRD dZ + /// is equivalent to two EXTRACT_SUBREG: + /// rX = EXTRACT_SUBREG dZ, ssub_0 + /// rY = EXTRACT_SUBREG dZ, ssub_1 + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getExtractSubregLikeInputs has to be + /// override accordingly. + bool isExtractSubregLike() const { + return Flags & (1ULL << MCID::ExtractSubreg); + } + + /// Return true if this instruction behaves + /// the same way as the generic INSERT_SUBREG instructions. + /// E.g., on ARM, + /// dX = VSETLNi32 dY, rZ, Imm + /// is equivalent to a INSERT_SUBREG: + /// dX = INSERT_SUBREG dY, rZ, translateImmToSubIdx(Imm) + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getInsertSubregLikeInputs has to be + /// override accordingly. + bool isInsertSubregLike() const { return Flags & (1ULL << MCID::InsertSubreg); } + + + /// Return true if this instruction is convergent. + /// + /// Convergent instructions may not be made control-dependent on any + /// additional values. + bool isConvergent() const { return Flags & (1ULL << MCID::Convergent); } + + /// Return true if variadic operands of this instruction are definitions. + bool variadicOpsAreDefs() const { + return Flags & (1ULL << MCID::VariadicOpsAreDefs); + } + + //===--------------------------------------------------------------------===// + // Side Effect Analysis + //===--------------------------------------------------------------------===// + + /// Return true if this instruction could possibly read memory. + /// Instructions with this flag set are not necessarily simple load + /// instructions, they may load a value and modify it, for example. + bool mayLoad() const { return Flags & (1ULL << MCID::MayLoad); } + + /// Return true if this instruction could possibly modify memory. + /// Instructions with this flag set are not necessarily simple store + /// instructions, they may store a modified value based on their operands, or + /// may not actually modify anything, for example. + bool mayStore() const { return Flags & (1ULL << MCID::MayStore); } + + /// Return true if this instruction has side + /// effects that are not modeled by other flags. This does not return true + /// for instructions whose effects are captured by: + /// + /// 1. Their operand list and implicit definition/use list. Register use/def + /// info is explicit for instructions. + /// 2. Memory accesses. Use mayLoad/mayStore. + /// 3. Calling, branching, returning: use isCall/isReturn/isBranch. + /// + /// Examples of side effects would be modifying 'invisible' machine state like + /// a control register, flushing a cache, modifying a register invisible to + /// LLVM, etc. + bool hasUnmodeledSideEffects() const { + return Flags & (1ULL << MCID::UnmodeledSideEffects); + } + + //===--------------------------------------------------------------------===// + // Flags that indicate whether an instruction can be modified by a method. + //===--------------------------------------------------------------------===// + + /// Return true if this may be a 2- or 3-address instruction (of the + /// form "X = op Y, Z, ..."), which produces the same result if Y and Z are + /// exchanged. If this flag is set, then the + /// TargetInstrInfo::commuteInstruction method may be used to hack on the + /// instruction. + /// + /// Note that this flag may be set on instructions that are only commutable + /// sometimes. In these cases, the call to commuteInstruction will fail. + /// Also note that some instructions require non-trivial modification to + /// commute them. + bool isCommutable() const { return Flags & (1ULL << MCID::Commutable); } + + /// Return true if this is a 2-address instruction which can be changed + /// into a 3-address instruction if needed. Doing this transformation can be + /// profitable in the register allocator, because it means that the + /// instruction can use a 2-address form if possible, but degrade into a less + /// efficient form if the source and dest register cannot be assigned to the + /// same register. For example, this allows the x86 backend to turn a "shl + /// reg, 3" instruction into an LEA instruction, which is the same speed as + /// the shift but has bigger code size. + /// + /// If this returns true, then the target must implement the + /// TargetInstrInfo::convertToThreeAddress method for this instruction, which + /// is allowed to fail if the transformation isn't valid for this specific + /// instruction (e.g. shl reg, 4 on x86). + /// + bool isConvertibleTo3Addr() const { + return Flags & (1ULL << MCID::ConvertibleTo3Addr); + } + + /// Return true if this instruction requires custom insertion support + /// when the DAG scheduler is inserting it into a machine basic block. If + /// this is true for the instruction, it basically means that it is a pseudo + /// instruction used at SelectionDAG time that is expanded out into magic code + /// by the target when MachineInstrs are formed. + /// + /// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method + /// is used to insert this into the MachineBasicBlock. + bool usesCustomInsertionHook() const { + return Flags & (1ULL << MCID::UsesCustomInserter); + } + + /// Return true if this instruction requires *adjustment* after + /// instruction selection by calling a target hook. For example, this can be + /// used to fill in ARM 's' optional operand depending on whether the + /// conditional flag register is used. + bool hasPostISelHook() const { return Flags & (1ULL << MCID::HasPostISelHook); } + + /// Returns true if this instruction is a candidate for remat. This + /// flag is only used in TargetInstrInfo method isTriviallyRematerializable. + /// + /// If this flag is set, the isReallyTriviallyReMaterializable() + /// or isReallyTriviallyReMaterializableGeneric methods are called to verify + /// the instruction is really rematable. + bool isRematerializable() const { + return Flags & (1ULL << MCID::Rematerializable); + } + + /// Returns true if this instruction has the same cost (or less) than a + /// move instruction. This is useful during certain types of optimizations + /// (e.g., remat during two-address conversion or machine licm) where we would + /// like to remat or hoist the instruction, but not if it costs more than + /// moving the instruction into the appropriate register. Note, we are not + /// marking copies from and to the same register class with this flag. + /// + /// This method could be called by interface TargetInstrInfo::isAsCheapAsAMove + /// for different subtargets. + bool isAsCheapAsAMove() const { return Flags & (1ULL << MCID::CheapAsAMove); } + + /// Returns true if this instruction source operands have special + /// register allocation requirements that are not captured by the operand + /// register classes. e.g. ARM::STRD's two source registers must be an even / + /// odd pair, ARM::STM registers have to be in ascending order. Post-register + /// allocation passes should not attempt to change allocations for sources of + /// instructions with this flag. + bool hasExtraSrcRegAllocReq() const { + return Flags & (1ULL << MCID::ExtraSrcRegAllocReq); + } + + /// Returns true if this instruction def operands have special register + /// allocation requirements that are not captured by the operand register + /// classes. e.g. ARM::LDRD's two def registers must be an even / odd pair, + /// ARM::LDM registers have to be in ascending order. Post-register + /// allocation passes should not attempt to change allocations for definitions + /// of instructions with this flag. + bool hasExtraDefRegAllocReq() const { + return Flags & (1ULL << MCID::ExtraDefRegAllocReq); + } + + /// Return a list of registers that are potentially read by any + /// instance of this machine instruction. For example, on X86, the "adc" + /// instruction adds two register operands and adds the carry bit in from the + /// flags register. In this case, the instruction is marked as implicitly + /// reading the flags. Likewise, the variable shift instruction on X86 is + /// marked as implicitly reading the 'CL' register, which it always does. + /// + /// This method returns null if the instruction has no implicit uses. + const MCPhysReg *getImplicitUses() const { return ImplicitUses; } + + /// Return the number of implicit uses this instruction has. + unsigned getNumImplicitUses() const { + if (!ImplicitUses) + return 0; + unsigned i = 0; + for (; ImplicitUses[i]; ++i) /*empty*/ + ; + return i; + } + + /// Return a list of registers that are potentially written by any + /// instance of this machine instruction. For example, on X86, many + /// instructions implicitly set the flags register. In this case, they are + /// marked as setting the FLAGS. Likewise, many instructions always deposit + /// their result in a physical register. For example, the X86 divide + /// instruction always deposits the quotient and remainder in the EAX/EDX + /// registers. For that instruction, this will return a list containing the + /// EAX/EDX/EFLAGS registers. + /// + /// This method returns null if the instruction has no implicit defs. + const MCPhysReg *getImplicitDefs() const { return ImplicitDefs; } + + /// Return the number of implicit defs this instruct has. + unsigned getNumImplicitDefs() const { + if (!ImplicitDefs) + return 0; + unsigned i = 0; + for (; ImplicitDefs[i]; ++i) /*empty*/ + ; + return i; + } + + /// Return true if this instruction implicitly + /// uses the specified physical register. + bool hasImplicitUseOfPhysReg(unsigned Reg) const { + if (const MCPhysReg *ImpUses = ImplicitUses) + for (; *ImpUses; ++ImpUses) + if (*ImpUses == Reg) + return true; + return false; + } + + /// Return true if this instruction implicitly + /// defines the specified physical register. + bool hasImplicitDefOfPhysReg(unsigned Reg, + const MCRegisterInfo *MRI = nullptr) const; + + /// Return the scheduling class for this instruction. The + /// scheduling class is an index into the InstrItineraryData table. This + /// returns zero if there is no known scheduling information for the + /// instruction. + unsigned getSchedClass() const { return SchedClass; } + + /// Return the number of bytes in the encoding of this instruction, + /// or zero if the encoding size cannot be known from the opcode. + unsigned getSize() const { return Size; } + + /// Find the index of the first operand in the + /// operand list that is used to represent the predicate. It returns -1 if + /// none is found. + int findFirstPredOperandIdx() const { + if (isPredicable()) { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (OpInfo[i].isPredicate()) + return i; + } + return -1; + } + + /// Return true if this instruction defines the specified physical + /// register, either explicitly or implicitly. + bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg, + const MCRegisterInfo &RI) const; +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCInstrInfo.h b/clang-r353983/include/llvm/MC/MCInstrInfo.h new file mode 100644 index 00000000..874b1e46 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCInstrInfo.h @@ -0,0 +1,58 @@ +//===-- llvm/MC/MCInstrInfo.h - Target Instruction Info ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file describes the target machine instruction set. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTRINFO_H +#define LLVM_MC_MCINSTRINFO_H + +#include "llvm/MC/MCInstrDesc.h" +#include <cassert> + +namespace llvm { + +//--------------------------------------------------------------------------- +/// Interface to description of machine instruction set. +class MCInstrInfo { + const MCInstrDesc *Desc; // Raw array to allow static init'n + const unsigned *InstrNameIndices; // Array for name indices in InstrNameData + const char *InstrNameData; // Instruction name string pool + unsigned NumOpcodes; // Number of entries in the desc array + +public: + /// Initialize MCInstrInfo, called by TableGen auto-generated routines. + /// *DO NOT USE*. + void InitMCInstrInfo(const MCInstrDesc *D, const unsigned *NI, const char *ND, + unsigned NO) { + Desc = D; + InstrNameIndices = NI; + InstrNameData = ND; + NumOpcodes = NO; + } + + unsigned getNumOpcodes() const { return NumOpcodes; } + + /// Return the machine instruction descriptor that corresponds to the + /// specified instruction opcode. + const MCInstrDesc &get(unsigned Opcode) const { + assert(Opcode < NumOpcodes && "Invalid opcode!"); + return Desc[Opcode]; + } + + /// Returns the name for the instructions with the given opcode. + StringRef getName(unsigned Opcode) const { + assert(Opcode < NumOpcodes && "Invalid opcode!"); + return StringRef(&InstrNameData[InstrNameIndices[Opcode]]); + } +}; + +} // End llvm namespace + +#endif diff --git a/clang-r353983/include/llvm/MC/MCInstrItineraries.h b/clang-r353983/include/llvm/MC/MCInstrItineraries.h new file mode 100644 index 00000000..485aa663 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCInstrItineraries.h @@ -0,0 +1,234 @@ +//===- llvm/MC/MCInstrItineraries.h - Scheduling ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file describes the structures used for instruction +// itineraries, stages, and operand reads/writes. This is used by +// schedulers to determine instruction stages and latencies. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTRITINERARIES_H +#define LLVM_MC_MCINSTRITINERARIES_H + +#include "llvm/MC/MCSchedule.h" +#include <algorithm> + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// These values represent a non-pipelined step in +/// the execution of an instruction. Cycles represents the number of +/// discrete time slots needed to complete the stage. Units represent +/// the choice of functional units that can be used to complete the +/// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many +/// cycles should elapse from the start of this stage to the start of +/// the next stage in the itinerary. A value of -1 indicates that the +/// next stage should start immediately after the current one. +/// For example: +/// +/// { 1, x, -1 } +/// indicates that the stage occupies FU x for 1 cycle and that +/// the next stage starts immediately after this one. +/// +/// { 2, x|y, 1 } +/// indicates that the stage occupies either FU x or FU y for 2 +/// consecutive cycles and that the next stage starts one cycle +/// after this stage starts. That is, the stage requirements +/// overlap in time. +/// +/// { 1, x, 0 } +/// indicates that the stage occupies FU x for 1 cycle and that +/// the next stage starts in this same cycle. This can be used to +/// indicate that the instruction requires multiple stages at the +/// same time. +/// +/// FU reservation can be of two different kinds: +/// - FUs which instruction actually requires +/// - FUs which instruction just reserves. Reserved unit is not available for +/// execution of other instruction. However, several instructions can reserve +/// the same unit several times. +/// Such two types of units reservation is used to model instruction domain +/// change stalls, FUs using the same resource (e.g. same register file), etc. + +struct InstrStage { + enum ReservationKinds { + Required = 0, + Reserved = 1 + }; + + unsigned Cycles_; ///< Length of stage in machine cycles + unsigned Units_; ///< Choice of functional units + int NextCycles_; ///< Number of machine cycles to next stage + ReservationKinds Kind_; ///< Kind of the FU reservation + + /// Returns the number of cycles the stage is occupied. + unsigned getCycles() const { + return Cycles_; + } + + /// Returns the choice of FUs. + unsigned getUnits() const { + return Units_; + } + + ReservationKinds getReservationKind() const { + return Kind_; + } + + /// Returns the number of cycles from the start of this stage to the + /// start of the next stage in the itinerary + unsigned getNextCycles() const { + return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; + } +}; + +//===----------------------------------------------------------------------===// +/// An itinerary represents the scheduling information for an instruction. +/// This includes a set of stages occupied by the instruction and the pipeline +/// cycle in which operands are read and written. +/// +struct InstrItinerary { + int16_t NumMicroOps; ///< # of micro-ops, -1 means it's variable + uint16_t FirstStage; ///< Index of first stage in itinerary + uint16_t LastStage; ///< Index of last + 1 stage in itinerary + uint16_t FirstOperandCycle; ///< Index of first operand rd/wr + uint16_t LastOperandCycle; ///< Index of last + 1 operand rd/wr +}; + +//===----------------------------------------------------------------------===// +/// Itinerary data supplied by a subtarget to be used by a target. +/// +class InstrItineraryData { +public: + MCSchedModel SchedModel = + MCSchedModel::GetDefaultSchedModel(); ///< Basic machine properties. + const InstrStage *Stages = nullptr; ///< Array of stages selected + const unsigned *OperandCycles = nullptr; ///< Array of operand cycles selected + const unsigned *Forwardings = nullptr; ///< Array of pipeline forwarding paths + const InstrItinerary *Itineraries = + nullptr; ///< Array of itineraries selected + + InstrItineraryData() = default; + InstrItineraryData(const MCSchedModel &SM, const InstrStage *S, + const unsigned *OS, const unsigned *F) + : SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F), + Itineraries(SchedModel.InstrItineraries) {} + + /// Returns true if there are no itineraries. + bool isEmpty() const { return Itineraries == nullptr; } + + /// Returns true if the index is for the end marker itinerary. + bool isEndMarker(unsigned ItinClassIndx) const { + return ((Itineraries[ItinClassIndx].FirstStage == UINT16_MAX) && + (Itineraries[ItinClassIndx].LastStage == UINT16_MAX)); + } + + /// Return the first stage of the itinerary. + const InstrStage *beginStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; + return Stages + StageIdx; + } + + /// Return the last+1 stage of the itinerary. + const InstrStage *endStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; + return Stages + StageIdx; + } + + /// Return the total stage latency of the given class. The latency is + /// the maximum completion time for any stage in the itinerary. If no stages + /// exist, it defaults to one cycle. + unsigned getStageLatency(unsigned ItinClassIndx) const { + // If the target doesn't provide itinerary information, use a simple + // non-zero default value for all instructions. + if (isEmpty()) + return 1; + + // Calculate the maximum completion time for any stage. + unsigned Latency = 0, StartCycle = 0; + for (const InstrStage *IS = beginStage(ItinClassIndx), + *E = endStage(ItinClassIndx); IS != E; ++IS) { + Latency = std::max(Latency, StartCycle + IS->getCycles()); + StartCycle += IS->getNextCycles(); + } + return Latency; + } + + /// Return the cycle for the given class and operand. Return -1 if no + /// cycle is specified for the operand. + int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { + if (isEmpty()) + return -1; + + unsigned FirstIdx = Itineraries[ItinClassIndx].FirstOperandCycle; + unsigned LastIdx = Itineraries[ItinClassIndx].LastOperandCycle; + if ((FirstIdx + OperandIdx) >= LastIdx) + return -1; + + return (int)OperandCycles[FirstIdx + OperandIdx]; + } + + /// Return true if there is a pipeline forwarding between instructions + /// of itinerary classes DefClass and UseClasses so that value produced by an + /// instruction of itinerary class DefClass, operand index DefIdx can be + /// bypassed when it's read by an instruction of itinerary class UseClass, + /// operand index UseIdx. + bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, + unsigned UseClass, unsigned UseIdx) const { + unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle; + unsigned LastDefIdx = Itineraries[DefClass].LastOperandCycle; + if ((FirstDefIdx + DefIdx) >= LastDefIdx) + return false; + if (Forwardings[FirstDefIdx + DefIdx] == 0) + return false; + + unsigned FirstUseIdx = Itineraries[UseClass].FirstOperandCycle; + unsigned LastUseIdx = Itineraries[UseClass].LastOperandCycle; + if ((FirstUseIdx + UseIdx) >= LastUseIdx) + return false; + + return Forwardings[FirstDefIdx + DefIdx] == + Forwardings[FirstUseIdx + UseIdx]; + } + + /// Compute and return the use operand latency of a given itinerary + /// class and operand index if the value is produced by an instruction of the + /// specified itinerary class and def operand index. + int getOperandLatency(unsigned DefClass, unsigned DefIdx, + unsigned UseClass, unsigned UseIdx) const { + if (isEmpty()) + return -1; + + int DefCycle = getOperandCycle(DefClass, DefIdx); + if (DefCycle == -1) + return -1; + + int UseCycle = getOperandCycle(UseClass, UseIdx); + if (UseCycle == -1) + return -1; + + UseCycle = DefCycle - UseCycle + 1; + if (UseCycle > 0 && + hasPipelineForwarding(DefClass, DefIdx, UseClass, UseIdx)) + // FIXME: This assumes one cycle benefit for every pipeline forwarding. + --UseCycle; + return UseCycle; + } + + /// Return the number of micro-ops that the given class decodes to. + /// Return -1 for classes that require dynamic lookup via TargetInstrInfo. + int getNumMicroOps(unsigned ItinClassIndx) const { + if (isEmpty()) + return 1; + return Itineraries[ItinClassIndx].NumMicroOps; + } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCINSTRITINERARIES_H diff --git a/clang-r353983/include/llvm/MC/MCLabel.h b/clang-r353983/include/llvm/MC/MCLabel.h new file mode 100644 index 00000000..0b8afac8 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCLabel.h @@ -0,0 +1,56 @@ +//===- MCLabel.h - Machine Code Directional Local Labels --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCLabel class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCLABEL_H +#define LLVM_MC_MCLABEL_H + +namespace llvm { + +class raw_ostream; + +/// Instances of this class represent a label name in the MC file, +/// and MCLabel are created and uniqued by the MCContext class. MCLabel +/// should only be constructed for valid instances in the object file. +class MCLabel { + // The instance number of this Directional Local Label. + unsigned Instance; + +private: // MCContext creates and uniques these. + friend class MCContext; + + MCLabel(unsigned instance) : Instance(instance) {} + +public: + MCLabel(const MCLabel &) = delete; + MCLabel &operator=(const MCLabel &) = delete; + + /// Get the current instance of this Directional Local Label. + unsigned getInstance() const { return Instance; } + + /// Increment the current instance of this Directional Local Label. + unsigned incInstance() { return ++Instance; } + + /// Print the value to the stream \p OS. + void print(raw_ostream &OS) const; + + /// Print the value to stderr. + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCLabel &Label) { + Label.print(OS); + return OS; +} + +} // end namespace llvm + +#endif // LLVM_MC_MCLABEL_H diff --git a/clang-r353983/include/llvm/MC/MCLinkerOptimizationHint.h b/clang-r353983/include/llvm/MC/MCLinkerOptimizationHint.h new file mode 100644 index 00000000..f2a1364a --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCLinkerOptimizationHint.h @@ -0,0 +1,186 @@ +//===- MCLinkerOptimizationHint.h - LOH interface ---------------*- C++ -*-===// +// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares some helpers classes to handle Linker Optimization Hint +// (LOH). +// +// FIXME: LOH interface supports only MachO format at the moment. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCLINKEROPTIMIZATIONHINT_H +#define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> + +namespace llvm { + +class MachObjectWriter; +class MCAsmLayout; +class MCSymbol; + +/// Linker Optimization Hint Type. +enum MCLOHType { + MCLOH_AdrpAdrp = 0x1u, ///< Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE. + MCLOH_AdrpLdr = 0x2u, ///< Adrp _v@PAGE -> Ldr _v@PAGEOFF. + MCLOH_AdrpAddLdr = 0x3u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr. + MCLOH_AdrpLdrGotLdr = 0x4u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr. + MCLOH_AdrpAddStr = 0x5u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Str. + MCLOH_AdrpLdrGotStr = 0x6u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str. + MCLOH_AdrpAdd = 0x7u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF. + MCLOH_AdrpLdrGot = 0x8u ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF. +}; + +static inline StringRef MCLOHDirectiveName() { + return StringRef(".loh"); +} + +static inline bool isValidMCLOHType(unsigned Kind) { + return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot; +} + +static inline int MCLOHNameToId(StringRef Name) { +#define MCLOHCaseNameToId(Name) .Case(#Name, MCLOH_ ## Name) + return StringSwitch<int>(Name) + MCLOHCaseNameToId(AdrpAdrp) + MCLOHCaseNameToId(AdrpLdr) + MCLOHCaseNameToId(AdrpAddLdr) + MCLOHCaseNameToId(AdrpLdrGotLdr) + MCLOHCaseNameToId(AdrpAddStr) + MCLOHCaseNameToId(AdrpLdrGotStr) + MCLOHCaseNameToId(AdrpAdd) + MCLOHCaseNameToId(AdrpLdrGot) + .Default(-1); +} + +static inline StringRef MCLOHIdToName(MCLOHType Kind) { +#define MCLOHCaseIdToName(Name) case MCLOH_ ## Name: return StringRef(#Name); + switch (Kind) { + MCLOHCaseIdToName(AdrpAdrp); + MCLOHCaseIdToName(AdrpLdr); + MCLOHCaseIdToName(AdrpAddLdr); + MCLOHCaseIdToName(AdrpLdrGotLdr); + MCLOHCaseIdToName(AdrpAddStr); + MCLOHCaseIdToName(AdrpLdrGotStr); + MCLOHCaseIdToName(AdrpAdd); + MCLOHCaseIdToName(AdrpLdrGot); + } + return StringRef(); +} + +static inline int MCLOHIdToNbArgs(MCLOHType Kind) { + switch (Kind) { + // LOH with two arguments + case MCLOH_AdrpAdrp: + case MCLOH_AdrpLdr: + case MCLOH_AdrpAdd: + case MCLOH_AdrpLdrGot: + return 2; + // LOH with three arguments + case MCLOH_AdrpAddLdr: + case MCLOH_AdrpLdrGotLdr: + case MCLOH_AdrpAddStr: + case MCLOH_AdrpLdrGotStr: + return 3; + } + return -1; +} + +/// Store Linker Optimization Hint information (LOH). +class MCLOHDirective { + MCLOHType Kind; + + /// Arguments of this directive. Order matters. + SmallVector<MCSymbol *, 3> Args; + + /// Emit this directive in \p OutStream using the information available + /// in the given \p ObjWriter and \p Layout to get the address of the + /// arguments within the object file. + void emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter, + const MCAsmLayout &Layout) const; + +public: + using LOHArgs = SmallVectorImpl<MCSymbol *>; + + MCLOHDirective(MCLOHType Kind, const LOHArgs &Args) + : Kind(Kind), Args(Args.begin(), Args.end()) { + assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!"); + } + + MCLOHType getKind() const { return Kind; } + + const LOHArgs &getArgs() const { return Args; } + + /// Emit this directive as: + /// <kind, numArgs, addr1, ..., addrN> + void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const; + + /// Get the size in bytes of this directive if emitted in \p ObjWriter with + /// the given \p Layout. + uint64_t getEmitSize(const MachObjectWriter &ObjWriter, + const MCAsmLayout &Layout) const; +}; + +class MCLOHContainer { + /// Keep track of the emit size of all the LOHs. + mutable uint64_t EmitSize = 0; + + /// Keep track of all LOH directives. + SmallVector<MCLOHDirective, 32> Directives; + +public: + using LOHDirectives = SmallVectorImpl<MCLOHDirective>; + + MCLOHContainer() = default; + + /// Const accessor to the directives. + const LOHDirectives &getDirectives() const { + return Directives; + } + + /// Add the directive of the given kind \p Kind with the given arguments + /// \p Args to the container. + void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) { + Directives.push_back(MCLOHDirective(Kind, Args)); + } + + /// Get the size of the directives if emitted. + uint64_t getEmitSize(const MachObjectWriter &ObjWriter, + const MCAsmLayout &Layout) const { + if (!EmitSize) { + for (const MCLOHDirective &D : Directives) + EmitSize += D.getEmitSize(ObjWriter, Layout); + } + return EmitSize; + } + + /// Emit all Linker Optimization Hint in one big table. + /// Each line of the table is emitted by LOHDirective::emit. + void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { + for (const MCLOHDirective &D : Directives) + D.emit(ObjWriter, Layout); + } + + void reset() { + Directives.clear(); + EmitSize = 0; + } +}; + +// Add types for specialized template using MCSymbol. +using MCLOHArgs = MCLOHDirective::LOHArgs; +using MCLOHDirectives = MCLOHContainer::LOHDirectives; + +} // end namespace llvm + +#endif // LLVM_MC_MCLINKEROPTIMIZATIONHINT_H diff --git a/clang-r353983/include/llvm/MC/MCMachObjectWriter.h b/clang-r353983/include/llvm/MC/MCMachObjectWriter.h new file mode 100644 index 00000000..278aebee --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCMachObjectWriter.h @@ -0,0 +1,287 @@ +//===- llvm/MC/MCMachObjectWriter.h - Mach Object Writer --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCMACHOBJECTWRITER_H +#define LLVM_MC_MCMACHOBJECTWRITER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/StringTableBuilder.h" +#include <cstdint> +#include <memory> +#include <string> +#include <vector> + +namespace llvm { + +class MachObjectWriter; + +class MCMachObjectTargetWriter : public MCObjectTargetWriter { + const unsigned Is64Bit : 1; + const uint32_t CPUType; + const uint32_t CPUSubtype; + unsigned LocalDifference_RIT; + +protected: + MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_, + uint32_t CPUSubtype_); + + void setLocalDifferenceRelocationType(unsigned Type) { + LocalDifference_RIT = Type; + } + +public: + virtual ~MCMachObjectTargetWriter(); + + virtual Triple::ObjectFormatType getFormat() const { return Triple::MachO; } + static bool classof(const MCObjectTargetWriter *W) { + return W->getFormat() == Triple::MachO; + } + + /// \name Lifetime Management + /// @{ + + virtual void reset() {} + + /// @} + + /// \name Accessors + /// @{ + + bool is64Bit() const { return Is64Bit; } + uint32_t getCPUType() const { return CPUType; } + uint32_t getCPUSubtype() const { return CPUSubtype; } + unsigned getLocalDifferenceRelocationType() const { + return LocalDifference_RIT; + } + + /// @} + + /// \name API + /// @{ + + virtual void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) = 0; + + /// @} +}; + +class MachObjectWriter : public MCObjectWriter { + /// Helper struct for containing some precomputed information on symbols. + struct MachSymbolData { + const MCSymbol *Symbol; + uint64_t StringIndex; + uint8_t SectionIndex; + + // Support lexicographic sorting. + bool operator<(const MachSymbolData &RHS) const; + }; + + /// The target specific Mach-O writer instance. + std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter; + + /// \name Relocation Data + /// @{ + + struct RelAndSymbol { + const MCSymbol *Sym; + MachO::any_relocation_info MRE; + RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE) + : Sym(Sym), MRE(MRE) {} + }; + + DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations; + DenseMap<const MCSection *, unsigned> IndirectSymBase; + + SectionAddrMap SectionAddress; + + /// @} + /// \name Symbol Table Data + /// @{ + + StringTableBuilder StringTable{StringTableBuilder::MachO}; + std::vector<MachSymbolData> LocalSymbolData; + std::vector<MachSymbolData> ExternalSymbolData; + std::vector<MachSymbolData> UndefinedSymbolData; + + /// @} + + MachSymbolData *findSymbolData(const MCSymbol &Sym); + + void writeWithPadding(StringRef Str, uint64_t Size); + +public: + MachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW, + raw_pwrite_stream &OS, bool IsLittleEndian) + : TargetObjectWriter(std::move(MOTW)), + W(OS, IsLittleEndian ? support::little : support::big) {} + + support::endian::Writer W; + + const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const; + + /// \name Lifetime management Methods + /// @{ + + void reset() override; + + /// @} + + /// \name Utility Methods + /// @{ + + bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); + + SectionAddrMap &getSectionAddressMap() { return SectionAddress; } + + uint64_t getSectionAddress(const MCSection *Sec) const { + return SectionAddress.lookup(Sec); + } + uint64_t getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const; + + uint64_t getFragmentAddress(const MCFragment *Fragment, + const MCAsmLayout &Layout) const; + + uint64_t getPaddingSize(const MCSection *SD, const MCAsmLayout &Layout) const; + + bool doesSymbolRequireExternRelocation(const MCSymbol &S); + + /// @} + + /// \name Target Writer Proxy Accessors + /// @{ + + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + bool isX86_64() const { + uint32_t CPUType = TargetObjectWriter->getCPUType(); + return CPUType == MachO::CPU_TYPE_X86_64; + } + + /// @} + + void writeHeader(MachO::HeaderFileType Type, unsigned NumLoadCommands, + unsigned LoadCommandsSize, bool SubsectionsViaSymbols); + + /// Write a segment load command. + /// + /// \param NumSections The number of sections in this segment. + /// \param SectionDataSize The total size of the sections. + void writeSegmentLoadCommand(StringRef Name, unsigned NumSections, + uint64_t VMAddr, uint64_t VMSize, + uint64_t SectionDataStartOffset, + uint64_t SectionDataSize, uint32_t MaxProt, + uint32_t InitProt); + + void writeSection(const MCAsmLayout &Layout, const MCSection &Sec, + uint64_t VMAddr, uint64_t FileOffset, unsigned Flags, + uint64_t RelocationsStart, unsigned NumRelocations); + + void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, + uint32_t StringTableOffset, + uint32_t StringTableSize); + + void writeDysymtabLoadCommand( + uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols, + uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols, + uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols, + uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols); + + void writeNlist(MachSymbolData &MSD, const MCAsmLayout &Layout); + + void writeLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset, + uint32_t DataSize); + + void writeLinkerOptionsLoadCommand(const std::vector<std::string> &Options); + + // FIXME: We really need to improve the relocation validation. Basically, we + // want to implement a separate computation which evaluates the relocation + // entry as the linker would, and verifies that the resultant fixup value is + // exactly what the encoder wanted. This will catch several classes of + // problems: + // + // - Relocation entry bugs, the two algorithms are unlikely to have the same + // exact bug. + // + // - Relaxation issues, where we forget to relax something. + // + // - Input errors, where something cannot be correctly encoded. 'as' allows + // these through in many cases. + + // Add a relocation to be output in the object file. At the time this is + // called, the symbol indexes are not know, so if the relocation refers + // to a symbol it should be passed as \p RelSymbol so that it can be updated + // afterwards. If the relocation doesn't refer to a symbol, nullptr should be + // used. + void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec, + MachO::any_relocation_info &MRE) { + RelAndSymbol P(RelSymbol, MRE); + Relocations[Sec].push_back(P); + } + + void recordScatteredRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, uint64_t &FixedValue); + + void recordTLVPRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue); + + void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) override; + + void bindIndirectSymbols(MCAssembler &Asm); + + /// Compute the symbol table data. + void computeSymbolTable(MCAssembler &Asm, + std::vector<MachSymbolData> &LocalSymbolData, + std::vector<MachSymbolData> &ExternalSymbolData, + std::vector<MachSymbolData> &UndefinedSymbolData); + + void computeSectionAddresses(const MCAssembler &Asm, + const MCAsmLayout &Layout); + + void executePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) override; + + bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbol &A, + const MCSymbol &B, + bool InSet) const override; + + bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbol &SymA, + const MCFragment &FB, bool InSet, + bool IsPCRel) const override; + + uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; +}; + +/// Construct a new Mach-O writer instance. +/// +/// This routine takes ownership of the target writer subclass. +/// +/// \param MOTW - The target specific Mach-O writer subclass. +/// \param OS - The stream to write to. +/// \returns The constructed object writer. +std::unique_ptr<MCObjectWriter> +createMachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW, + raw_pwrite_stream &OS, bool IsLittleEndian); + +} // end namespace llvm + +#endif // LLVM_MC_MCMACHOBJECTWRITER_H diff --git a/clang-r353983/include/llvm/MC/MCObjectFileInfo.h b/clang-r353983/include/llvm/MC/MCObjectFileInfo.h new file mode 100644 index 00000000..0c1ade48 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCObjectFileInfo.h @@ -0,0 +1,413 @@ +//===-- llvm/MC/MCObjectFileInfo.h - Object File Info -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file describes common object file formats. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTFILEINFO_H +#define LLVM_MC_MCOBJECTFILEINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Triple.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/VersionTuple.h" + +namespace llvm { +class MCContext; +class MCSection; + +class MCObjectFileInfo { +protected: + /// True if .comm supports alignment. This is a hack for as long as we + /// support 10.4 Tiger, whose assembler doesn't support alignment on comm. + bool CommDirectiveSupportsAlignment; + + /// True if target object file supports a weak_definition of constant 0 for an + /// omitted EH frame. + bool SupportsWeakOmittedEHFrame; + + /// True if the target object file supports emitting a compact unwind section + /// without an associated EH frame section. + bool SupportsCompactUnwindWithoutEHFrame; + + /// OmitDwarfIfHaveCompactUnwind - True if the target object file + /// supports having some functions with compact unwind and other with + /// dwarf unwind. + bool OmitDwarfIfHaveCompactUnwind; + + /// FDE CFI encoding. Controls the encoding of the begin label in the + /// .eh_frame section. Unlike the LSDA encoding, personality encoding, and + /// type encodings, this is something that the assembler just "knows" about + /// its target + unsigned FDECFIEncoding = 0; + + /// Compact unwind encoding indicating that we should emit only an EH frame. + unsigned CompactUnwindDwarfEHFrameOnly; + + /// Section directive for standard text. + MCSection *TextSection; + + /// Section directive for standard data. + MCSection *DataSection; + + /// Section that is default initialized to zero. + MCSection *BSSSection; + + /// Section that is readonly and can contain arbitrary initialized data. + /// Targets are not required to have a readonly section. If they don't, + /// various bits of code will fall back to using the data section for + /// constants. + MCSection *ReadOnlySection; + + /// If exception handling is supported by the target, this is the section the + /// Language Specific Data Area information is emitted to. + MCSection *LSDASection; + + /// If exception handling is supported by the target and the target can + /// support a compact representation of the CIE and FDE, this is the section + /// to emit them into. + MCSection *CompactUnwindSection; + + // Dwarf sections for debug info. If a target supports debug info, these must + // be set. + MCSection *DwarfAbbrevSection; + MCSection *DwarfInfoSection; + MCSection *DwarfLineSection; + MCSection *DwarfLineStrSection; + MCSection *DwarfFrameSection; + MCSection *DwarfPubTypesSection; + const MCSection *DwarfDebugInlineSection; + MCSection *DwarfStrSection; + MCSection *DwarfLocSection; + MCSection *DwarfARangesSection; + MCSection *DwarfRangesSection; + MCSection *DwarfMacinfoSection; + // The pubnames section is no longer generated by default. The generation + // can be enabled by a compiler flag. + MCSection *DwarfPubNamesSection; + + /// Accelerator table sections. DwarfDebugNamesSection is the DWARF v5 + /// accelerator table, while DwarfAccelNamesSection, DwarfAccelObjCSection, + /// DwarfAccelNamespaceSection, DwarfAccelTypesSection are pre-DWARF v5 + /// extensions. + MCSection *DwarfDebugNamesSection; + MCSection *DwarfAccelNamesSection; + MCSection *DwarfAccelObjCSection; + MCSection *DwarfAccelNamespaceSection; + MCSection *DwarfAccelTypesSection; + + // These are used for the Fission separate debug information files. + MCSection *DwarfInfoDWOSection; + MCSection *DwarfTypesDWOSection; + MCSection *DwarfAbbrevDWOSection; + MCSection *DwarfStrDWOSection; + MCSection *DwarfLineDWOSection; + MCSection *DwarfLocDWOSection; + MCSection *DwarfStrOffDWOSection; + + /// The DWARF v5 string offset and address table sections. + MCSection *DwarfStrOffSection; + MCSection *DwarfAddrSection; + /// The DWARF v5 range list section. + MCSection *DwarfRnglistsSection; + /// The DWARF v5 locations list section. + MCSection *DwarfLoclistsSection; + + /// The DWARF v5 range list section for fission. + MCSection *DwarfRnglistsDWOSection; + + // These are for Fission DWP files. + MCSection *DwarfCUIndexSection; + MCSection *DwarfTUIndexSection; + + /// Section for newer gnu pubnames. + MCSection *DwarfGnuPubNamesSection; + /// Section for newer gnu pubtypes. + MCSection *DwarfGnuPubTypesSection; + + // Section for Swift AST + MCSection *DwarfSwiftASTSection; + + MCSection *COFFDebugSymbolsSection; + MCSection *COFFDebugTypesSection; + MCSection *COFFGlobalTypeHashesSection; + + /// Extra TLS Variable Data section. + /// + /// If the target needs to put additional information for a TLS variable, + /// it'll go here. + MCSection *TLSExtraDataSection; + + /// Section directive for Thread Local data. ELF, MachO, COFF, and Wasm. + MCSection *TLSDataSection; // Defaults to ".tdata". + + /// Section directive for Thread Local uninitialized data. + /// + /// Null if this target doesn't support a BSS section. ELF and MachO only. + MCSection *TLSBSSSection; // Defaults to ".tbss". + + /// StackMap section. + MCSection *StackMapSection; + + /// FaultMap section. + MCSection *FaultMapSection; + + /// EH frame section. + /// + /// It is initialized on demand so it can be overwritten (with uniquing). + MCSection *EHFrameSection; + + /// Section containing metadata on function stack sizes. + MCSection *StackSizesSection; + mutable DenseMap<const MCSymbol *, unsigned> StackSizesUniquing; + + // ELF specific sections. + MCSection *DataRelROSection; + MCSection *MergeableConst4Section; + MCSection *MergeableConst8Section; + MCSection *MergeableConst16Section; + MCSection *MergeableConst32Section; + + // MachO specific sections. + + /// Section for thread local structure information. + /// + /// Contains the source code name of the variable, visibility and a pointer to + /// the initial value (.tdata or .tbss). + MCSection *TLSTLVSection; // Defaults to ".tlv". + + /// Section for thread local data initialization functions. + const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func". + + MCSection *CStringSection; + MCSection *UStringSection; + MCSection *TextCoalSection; + MCSection *ConstTextCoalSection; + MCSection *ConstDataSection; + MCSection *DataCoalSection; + MCSection *ConstDataCoalSection; + MCSection *DataCommonSection; + MCSection *DataBSSSection; + MCSection *FourByteConstantSection; + MCSection *EightByteConstantSection; + MCSection *SixteenByteConstantSection; + MCSection *LazySymbolPointerSection; + MCSection *NonLazySymbolPointerSection; + MCSection *ThreadLocalPointerSection; + + /// COFF specific sections. + MCSection *DrectveSection; + MCSection *PDataSection; + MCSection *XDataSection; + MCSection *SXDataSection; + MCSection *GFIDsSection; + +public: + void InitMCObjectFileInfo(const Triple &TT, bool PIC, MCContext &ctx, + bool LargeCodeModel = false); + + bool getSupportsWeakOmittedEHFrame() const { + return SupportsWeakOmittedEHFrame; + } + bool getSupportsCompactUnwindWithoutEHFrame() const { + return SupportsCompactUnwindWithoutEHFrame; + } + bool getOmitDwarfIfHaveCompactUnwind() const { + return OmitDwarfIfHaveCompactUnwind; + } + + bool getCommDirectiveSupportsAlignment() const { + return CommDirectiveSupportsAlignment; + } + + unsigned getFDEEncoding() const { return FDECFIEncoding; } + + unsigned getCompactUnwindDwarfEHFrameOnly() const { + return CompactUnwindDwarfEHFrameOnly; + } + + MCSection *getTextSection() const { return TextSection; } + MCSection *getDataSection() const { return DataSection; } + MCSection *getBSSSection() const { return BSSSection; } + MCSection *getReadOnlySection() const { return ReadOnlySection; } + MCSection *getLSDASection() const { return LSDASection; } + MCSection *getCompactUnwindSection() const { return CompactUnwindSection; } + MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } + MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } + MCSection *getDwarfInfoSection(uint64_t Hash) const { + return getDwarfComdatSection(".debug_info", Hash); + } + MCSection *getDwarfLineSection() const { return DwarfLineSection; } + MCSection *getDwarfLineStrSection() const { return DwarfLineStrSection; } + MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } + MCSection *getDwarfPubNamesSection() const { return DwarfPubNamesSection; } + MCSection *getDwarfPubTypesSection() const { return DwarfPubTypesSection; } + MCSection *getDwarfGnuPubNamesSection() const { + return DwarfGnuPubNamesSection; + } + MCSection *getDwarfGnuPubTypesSection() const { + return DwarfGnuPubTypesSection; + } + const MCSection *getDwarfDebugInlineSection() const { + return DwarfDebugInlineSection; + } + MCSection *getDwarfStrSection() const { return DwarfStrSection; } + MCSection *getDwarfLocSection() const { return DwarfLocSection; } + MCSection *getDwarfARangesSection() const { return DwarfARangesSection; } + MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } + MCSection *getDwarfRnglistsSection() const { return DwarfRnglistsSection; } + MCSection *getDwarfLoclistsSection() const { return DwarfLoclistsSection; } + MCSection *getDwarfMacinfoSection() const { return DwarfMacinfoSection; } + + MCSection *getDwarfDebugNamesSection() const { + return DwarfDebugNamesSection; + } + MCSection *getDwarfAccelNamesSection() const { + return DwarfAccelNamesSection; + } + MCSection *getDwarfAccelObjCSection() const { return DwarfAccelObjCSection; } + MCSection *getDwarfAccelNamespaceSection() const { + return DwarfAccelNamespaceSection; + } + MCSection *getDwarfAccelTypesSection() const { + return DwarfAccelTypesSection; + } + MCSection *getDwarfInfoDWOSection() const { return DwarfInfoDWOSection; } + MCSection *getDwarfTypesSection(uint64_t Hash) const { + return getDwarfComdatSection(".debug_types", Hash); + } + MCSection *getDwarfTypesDWOSection() const { return DwarfTypesDWOSection; } + MCSection *getDwarfAbbrevDWOSection() const { return DwarfAbbrevDWOSection; } + MCSection *getDwarfStrDWOSection() const { return DwarfStrDWOSection; } + MCSection *getDwarfLineDWOSection() const { return DwarfLineDWOSection; } + MCSection *getDwarfLocDWOSection() const { return DwarfLocDWOSection; } + MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; } + MCSection *getDwarfStrOffSection() const { return DwarfStrOffSection; } + MCSection *getDwarfAddrSection() const { return DwarfAddrSection; } + MCSection *getDwarfRnglistsDWOSection() const { + return DwarfRnglistsDWOSection; + } + MCSection *getDwarfCUIndexSection() const { return DwarfCUIndexSection; } + MCSection *getDwarfTUIndexSection() const { return DwarfTUIndexSection; } + MCSection *getDwarfSwiftASTSection() const { return DwarfSwiftASTSection; } + + MCSection *getCOFFDebugSymbolsSection() const { + return COFFDebugSymbolsSection; + } + MCSection *getCOFFDebugTypesSection() const { + return COFFDebugTypesSection; + } + MCSection *getCOFFGlobalTypeHashesSection() const { + return COFFGlobalTypeHashesSection; + } + + MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; } + const MCSection *getTLSDataSection() const { return TLSDataSection; } + MCSection *getTLSBSSSection() const { return TLSBSSSection; } + + MCSection *getStackMapSection() const { return StackMapSection; } + MCSection *getFaultMapSection() const { return FaultMapSection; } + + MCSection *getStackSizesSection(const MCSection &TextSec) const; + + // ELF specific sections. + MCSection *getDataRelROSection() const { return DataRelROSection; } + const MCSection *getMergeableConst4Section() const { + return MergeableConst4Section; + } + const MCSection *getMergeableConst8Section() const { + return MergeableConst8Section; + } + const MCSection *getMergeableConst16Section() const { + return MergeableConst16Section; + } + const MCSection *getMergeableConst32Section() const { + return MergeableConst32Section; + } + + // MachO specific sections. + const MCSection *getTLSTLVSection() const { return TLSTLVSection; } + const MCSection *getTLSThreadInitSection() const { + return TLSThreadInitSection; + } + const MCSection *getCStringSection() const { return CStringSection; } + const MCSection *getUStringSection() const { return UStringSection; } + MCSection *getTextCoalSection() const { return TextCoalSection; } + const MCSection *getConstTextCoalSection() const { + return ConstTextCoalSection; + } + const MCSection *getConstDataSection() const { return ConstDataSection; } + const MCSection *getDataCoalSection() const { return DataCoalSection; } + const MCSection *getConstDataCoalSection() const { + return ConstDataCoalSection; + } + const MCSection *getDataCommonSection() const { return DataCommonSection; } + MCSection *getDataBSSSection() const { return DataBSSSection; } + const MCSection *getFourByteConstantSection() const { + return FourByteConstantSection; + } + const MCSection *getEightByteConstantSection() const { + return EightByteConstantSection; + } + const MCSection *getSixteenByteConstantSection() const { + return SixteenByteConstantSection; + } + MCSection *getLazySymbolPointerSection() const { + return LazySymbolPointerSection; + } + MCSection *getNonLazySymbolPointerSection() const { + return NonLazySymbolPointerSection; + } + MCSection *getThreadLocalPointerSection() const { + return ThreadLocalPointerSection; + } + + // COFF specific sections. + MCSection *getDrectveSection() const { return DrectveSection; } + MCSection *getPDataSection() const { return PDataSection; } + MCSection *getXDataSection() const { return XDataSection; } + MCSection *getSXDataSection() const { return SXDataSection; } + MCSection *getGFIDsSection() const { return GFIDsSection; } + + MCSection *getEHFrameSection() { + return EHFrameSection; + } + + enum Environment { IsMachO, IsELF, IsCOFF, IsWasm }; + Environment getObjectFileType() const { return Env; } + + bool isPositionIndependent() const { return PositionIndependent; } + +private: + Environment Env; + bool PositionIndependent; + MCContext *Ctx; + Triple TT; + VersionTuple SDKVersion; + + void initMachOMCObjectFileInfo(const Triple &T); + void initELFMCObjectFileInfo(const Triple &T, bool Large); + void initCOFFMCObjectFileInfo(const Triple &T); + void initWasmMCObjectFileInfo(const Triple &T); + MCSection *getDwarfComdatSection(const char *Name, uint64_t Hash) const; + +public: + const Triple &getTargetTriple() const { return TT; } + + void setSDKVersion(const VersionTuple &TheSDKVersion) { + SDKVersion = TheSDKVersion; + } + + const VersionTuple &getSDKVersion() const { return SDKVersion; } +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCObjectStreamer.h b/clang-r353983/include/llvm/MC/MCObjectStreamer.h new file mode 100644 index 00000000..8affca49 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCObjectStreamer.h @@ -0,0 +1,205 @@ +//===- MCObjectStreamer.h - MCStreamer Object File Interface ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTSTREAMER_H +#define LLVM_MC_MCOBJECTSTREAMER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" + +namespace llvm { +class MCAssembler; +class MCCodeEmitter; +class MCSubtargetInfo; +class MCExpr; +class MCFragment; +class MCDataFragment; +class MCAsmBackend; +class raw_ostream; +class raw_pwrite_stream; + +/// Streaming object file generation interface. +/// +/// This class provides an implementation of the MCStreamer interface which is +/// suitable for use with the assembler backend. Specific object file formats +/// are expected to subclass this interface to implement directives specific +/// to that file format or custom semantics expected by the object writer +/// implementation. +class MCObjectStreamer : public MCStreamer { + std::unique_ptr<MCAssembler> Assembler; + MCSection::iterator CurInsertionPoint; + bool EmitEHFrame; + bool EmitDebugFrame; + SmallVector<MCSymbol *, 2> PendingLabels; + struct PendingMCFixup { + const MCSymbol *Sym; + MCFixup Fixup; + MCDataFragment *DF; + PendingMCFixup(const MCSymbol *McSym, MCDataFragment *F, MCFixup McFixup) + : Sym(McSym), Fixup(McFixup), DF(F) {} + }; + SmallVector<PendingMCFixup, 2> PendingFixups; + + virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0; + void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; + void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; + MCSymbol *EmitCFILabel() override; + void EmitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI); + void resolvePendingFixups(); + +protected: + MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, + std::unique_ptr<MCObjectWriter> OW, + std::unique_ptr<MCCodeEmitter> Emitter); + ~MCObjectStreamer(); + +public: + /// state management + void reset() override; + + /// Object streamers require the integrated assembler. + bool isIntegratedAssemblerRequired() const override { return true; } + + void EmitFrames(MCAsmBackend *MAB); + void EmitCFISections(bool EH, bool Debug) override; + + MCFragment *getCurrentFragment() const; + + void insert(MCFragment *F) { + flushPendingLabels(F); + MCSection *CurSection = getCurrentSectionOnly(); + CurSection->getFragmentList().insert(CurInsertionPoint, F); + F->setParent(CurSection); + } + + /// Get a data fragment to write into, creating a new one if the current + /// fragment is not a data fragment. + /// Optionally a \p STI can be passed in so that a new fragment is created + /// if the Subtarget differs from the current fragment. + MCDataFragment *getOrCreateDataFragment(const MCSubtargetInfo* STI = nullptr); + MCPaddingFragment *getOrCreatePaddingFragment(); + +protected: + bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection); + + /// If any labels have been emitted but not assigned fragments, ensure that + /// they get assigned, either to F if possible or to a new data fragment. + /// Optionally, it is also possible to provide an offset \p FOffset, which + /// will be used as a symbol offset within the fragment. + void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0); + +public: + void visitUsedSymbol(const MCSymbol &Sym) override; + + /// Create a dummy fragment to assign any pending labels. + void flushPendingLabels() { flushPendingLabels(nullptr); } + + MCAssembler &getAssembler() { return *Assembler; } + MCAssembler *getAssemblerPtr() override; + /// \name MCStreamer Interface + /// @{ + + void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F); + void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; + void EmitValueImpl(const MCExpr *Value, unsigned Size, + SMLoc Loc = SMLoc()) override; + void EmitULEB128Value(const MCExpr *Value) override; + void EmitSLEB128Value(const MCExpr *Value) override; + void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; + void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + + /// Emit an instruction to a special fragment, because this instruction + /// can change its size during relaxation. + virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &); + + void EmitBundleAlignMode(unsigned AlignPow2) override; + void EmitBundleLock(bool AlignToEnd) override; + void EmitBundleUnlock() override; + void EmitBytes(StringRef Data) override; + void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) override; + void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0) override; + void emitValueToOffset(const MCExpr *Offset, unsigned char Value, + SMLoc Loc) override; + void + EmitCodePaddingBasicBlockStart(const MCCodePaddingContext &Context) override; + void + EmitCodePaddingBasicBlockEnd(const MCCodePaddingContext &Context) override; + void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName) override; + void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, + const MCSymbol *Label, + unsigned PointerSize); + void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label); + void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, + unsigned Column, bool PrologueEnd, bool IsStmt, + StringRef FileName, SMLoc Loc) override; + void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *Begin, + const MCSymbol *End) override; + void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, + unsigned SourceFileId, + unsigned SourceLineNum, + const MCSymbol *FnStartSym, + const MCSymbol *FnEndSym) override; + void EmitCVDefRangeDirective( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + StringRef FixedSizePortion) override; + void EmitCVStringTableDirective() override; + void EmitCVFileChecksumsDirective() override; + void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override; + void EmitDTPRel32Value(const MCExpr *Value) override; + void EmitDTPRel64Value(const MCExpr *Value) override; + void EmitTPRel32Value(const MCExpr *Value) override; + void EmitTPRel64Value(const MCExpr *Value) override; + void EmitGPRel32Value(const MCExpr *Value) override; + void EmitGPRel64Value(const MCExpr *Value) override; + bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, + const MCExpr *Expr, SMLoc Loc, + const MCSubtargetInfo &STI) override; + using MCStreamer::emitFill; + void emitFill(const MCExpr &NumBytes, uint64_t FillValue, + SMLoc Loc = SMLoc()) override; + void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, + SMLoc Loc = SMLoc()) override; + void EmitFileDirective(StringRef Filename) override; + + void EmitAddrsig() override; + void EmitAddrsigSym(const MCSymbol *Sym) override; + + void FinishImpl() override; + + /// Emit the absolute difference between two symbols if possible. + /// + /// Emit the absolute difference between \c Hi and \c Lo, as long as we can + /// compute it. Currently, that requires that both symbols are in the same + /// data fragment and that the target has not specified that diff expressions + /// require relocations to be emitted. Otherwise, do nothing and return + /// \c false. + /// + /// \pre Offset of \c Hi is greater than the offset \c Lo. + void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size) override; + + void emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, + const MCSymbol *Lo) override; + + bool mayHaveInstructions(MCSection &Sec) const override; +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCObjectWriter.h b/clang-r353983/include/llvm/MC/MCObjectWriter.h new file mode 100644 index 00000000..2547b2b7 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCObjectWriter.h @@ -0,0 +1,123 @@ +//===- llvm/MC/MCObjectWriter.h - Object File Writer Interface --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTWRITER_H +#define LLVM_MC_MCOBJECTWRITER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> + +namespace llvm { + +class MCAsmLayout; +class MCAssembler; +class MCFixup; +class MCFragment; +class MCSymbol; +class MCSymbolRefExpr; +class MCValue; + +/// Defines the object file and target independent interfaces used by the +/// assembler backend to write native file format object files. +/// +/// The object writer contains a few callbacks used by the assembler to allow +/// the object writer to modify the assembler data structures at appropriate +/// points. Once assembly is complete, the object writer is given the +/// MCAssembler instance, which contains all the symbol and section data which +/// should be emitted as part of writeObject(). +class MCObjectWriter { +protected: + MCObjectWriter() = default; + +public: + MCObjectWriter(const MCObjectWriter &) = delete; + MCObjectWriter &operator=(const MCObjectWriter &) = delete; + virtual ~MCObjectWriter(); + + /// lifetime management + virtual void reset() {} + + /// \name High-Level API + /// @{ + + /// Perform any late binding of symbols (for example, to assign symbol + /// indices for use when generating relocations). + /// + /// This routine is called by the assembler after layout and relaxation is + /// complete. + virtual void executePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) = 0; + + /// Record a relocation entry. + /// + /// This routine is called by the assembler after layout and relaxation, and + /// post layout binding. The implementation is responsible for storing + /// information about the relocation so that it can be emitted during + /// writeObject(). + virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) = 0; + + /// Check whether the difference (A - B) between two symbol references is + /// fully resolved. + /// + /// Clients are not required to answer precisely and may conservatively return + /// false, even when a difference is fully resolved. + bool isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, + const MCSymbolRefExpr *A, + const MCSymbolRefExpr *B, + bool InSet) const; + + virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbol &A, + const MCSymbol &B, + bool InSet) const; + + virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbol &SymA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + + /// Tell the object writer to emit an address-significance table during + /// writeObject(). If this function is not called, all symbols are treated as + /// address-significant. + virtual void emitAddrsigSection() {} + + /// Record the given symbol in the address-significance table to be written + /// diring writeObject(). + virtual void addAddrsigSymbol(const MCSymbol *Sym) {} + + /// Write the object file and returns the number of bytes written. + /// + /// This routine is called by the assembler after layout and relaxation is + /// complete, fixups have been evaluated and applied, and relocations + /// generated. + virtual uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0; + + /// @} +}; + +/// Base class for classes that define behaviour that is specific to both the +/// target and the object format. +class MCObjectTargetWriter { +public: + virtual ~MCObjectTargetWriter() = default; + virtual Triple::ObjectFormatType getFormat() const = 0; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCOBJECTWRITER_H diff --git a/clang-r353983/include/llvm/MC/MCParser/AsmCond.h b/clang-r353983/include/llvm/MC/MCParser/AsmCond.h new file mode 100644 index 00000000..ea215501 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCParser/AsmCond.h @@ -0,0 +1,39 @@ +//===- AsmCond.h - Assembly file conditional assembly ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCPARSER_ASMCOND_H +#define LLVM_MC_MCPARSER_ASMCOND_H + +namespace llvm { + +/// AsmCond - Class to support conditional assembly +/// +/// The conditional assembly feature (.if, .else, .elseif and .endif) is +/// implemented with AsmCond that tells us what we are in the middle of +/// processing. Ignore can be either true or false. When true we are ignoring +/// the block of code in the middle of a conditional. + +class AsmCond { +public: + enum ConditionalAssemblyType { + NoCond, // no conditional is being processed + IfCond, // inside if conditional + ElseIfCond, // inside elseif conditional + ElseCond // inside else conditional + }; + + ConditionalAssemblyType TheCond = NoCond; + bool CondMet = false; + bool Ignore = false; + + AsmCond() = default; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCPARSER_ASMCOND_H diff --git a/clang-r353983/include/llvm/MC/MCParser/AsmLexer.h b/clang-r353983/include/llvm/MC/MCParser/AsmLexer.h new file mode 100644 index 00000000..b7294493 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCParser/AsmLexer.h @@ -0,0 +1,73 @@ +//===- AsmLexer.h - Lexer for Assembly Files --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This class declares the lexer for assembly files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCPARSER_ASMLEXER_H +#define LLVM_MC_MCPARSER_ASMLEXER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include <string> + +namespace llvm { + +class MCAsmInfo; + +/// AsmLexer - Lexer class for assembly files. +class AsmLexer : public MCAsmLexer { + const MCAsmInfo &MAI; + + const char *CurPtr = nullptr; + StringRef CurBuf; + bool IsAtStartOfLine = true; + bool IsAtStartOfStatement = true; + bool IsPeeking = false; + +protected: + /// LexToken - Read the next token and return its code. + AsmToken LexToken() override; + +public: + AsmLexer(const MCAsmInfo &MAI); + AsmLexer(const AsmLexer &) = delete; + AsmLexer &operator=(const AsmLexer &) = delete; + ~AsmLexer() override; + + void setBuffer(StringRef Buf, const char *ptr = nullptr); + + StringRef LexUntilEndOfStatement() override; + + size_t peekTokens(MutableArrayRef<AsmToken> Buf, + bool ShouldSkipSpace = true) override; + + const MCAsmInfo &getMAI() const { return MAI; } + +private: + bool isAtStartOfComment(const char *Ptr); + bool isAtStatementSeparator(const char *Ptr); + int getNextChar(); + AsmToken ReturnError(const char *Loc, const std::string &Msg); + + AsmToken LexIdentifier(); + AsmToken LexSlash(); + AsmToken LexLineComment(); + AsmToken LexDigit(); + AsmToken LexSingleQuote(); + AsmToken LexQuote(); + AsmToken LexFloatLiteral(); + AsmToken LexHexFloatLiteral(bool NoIntDigits); + + StringRef LexUntilEndOfLine(); +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCPARSER_ASMLEXER_H diff --git a/clang-r353983/include/llvm/MC/MCParser/MCAsmLexer.h b/clang-r353983/include/llvm/MC/MCParser/MCAsmLexer.h new file mode 100644 index 00000000..e89abeaa --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCParser/MCAsmLexer.h @@ -0,0 +1,157 @@ +//===- llvm/MC/MCAsmLexer.h - Abstract Asm Lexer Interface ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCPARSER_MCASMLEXER_H +#define LLVM_MC_MCPARSER_MCASMLEXER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCAsmMacro.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <string> + +namespace llvm { + +/// A callback class which is notified of each comment in an assembly file as +/// it is lexed. +class AsmCommentConsumer { +public: + virtual ~AsmCommentConsumer() = default; + + /// Callback function for when a comment is lexed. Loc is the start of the + /// comment text (excluding the comment-start marker). CommentText is the text + /// of the comment, excluding the comment start and end markers, and the + /// newline for single-line comments. + virtual void HandleComment(SMLoc Loc, StringRef CommentText) = 0; +}; + + +/// Generic assembler lexer interface, for use by target specific assembly +/// lexers. +class MCAsmLexer { + /// The current token, stored in the base class for faster access. + SmallVector<AsmToken, 1> CurTok; + + /// The location and description of the current error + SMLoc ErrLoc; + std::string Err; + +protected: // Can only create subclasses. + const char *TokStart = nullptr; + bool SkipSpace = true; + bool AllowAtInIdentifier; + bool IsAtStartOfStatement = true; + bool LexMasmIntegers = false; + AsmCommentConsumer *CommentConsumer = nullptr; + + MCAsmLexer(); + + virtual AsmToken LexToken() = 0; + + void SetError(SMLoc errLoc, const std::string &err) { + ErrLoc = errLoc; + Err = err; + } + +public: + MCAsmLexer(const MCAsmLexer &) = delete; + MCAsmLexer &operator=(const MCAsmLexer &) = delete; + virtual ~MCAsmLexer(); + + /// Consume the next token from the input stream and return it. + /// + /// The lexer will continuously return the end-of-file token once the end of + /// the main input file has been reached. + const AsmToken &Lex() { + assert(!CurTok.empty()); + // Mark if we parsing out a EndOfStatement. + IsAtStartOfStatement = CurTok.front().getKind() == AsmToken::EndOfStatement; + CurTok.erase(CurTok.begin()); + // LexToken may generate multiple tokens via UnLex but will always return + // the first one. Place returned value at head of CurTok vector. + if (CurTok.empty()) { + AsmToken T = LexToken(); + CurTok.insert(CurTok.begin(), T); + } + return CurTok.front(); + } + + void UnLex(AsmToken const &Token) { + IsAtStartOfStatement = false; + CurTok.insert(CurTok.begin(), Token); + } + + bool isAtStartOfStatement() { return IsAtStartOfStatement; } + + virtual StringRef LexUntilEndOfStatement() = 0; + + /// Get the current source location. + SMLoc getLoc() const; + + /// Get the current (last) lexed token. + const AsmToken &getTok() const { + return CurTok[0]; + } + + /// Look ahead at the next token to be lexed. + const AsmToken peekTok(bool ShouldSkipSpace = true) { + AsmToken Tok; + + MutableArrayRef<AsmToken> Buf(Tok); + size_t ReadCount = peekTokens(Buf, ShouldSkipSpace); + + assert(ReadCount == 1); + (void)ReadCount; + + return Tok; + } + + /// Look ahead an arbitrary number of tokens. + virtual size_t peekTokens(MutableArrayRef<AsmToken> Buf, + bool ShouldSkipSpace = true) = 0; + + /// Get the current error location + SMLoc getErrLoc() { + return ErrLoc; + } + + /// Get the current error string + const std::string &getErr() { + return Err; + } + + /// Get the kind of current token. + AsmToken::TokenKind getKind() const { return getTok().getKind(); } + + /// Check if the current token has kind \p K. + bool is(AsmToken::TokenKind K) const { return getTok().is(K); } + + /// Check if the current token has kind \p K. + bool isNot(AsmToken::TokenKind K) const { return getTok().isNot(K); } + + /// Set whether spaces should be ignored by the lexer + void setSkipSpace(bool val) { SkipSpace = val; } + + bool getAllowAtInIdentifier() { return AllowAtInIdentifier; } + void setAllowAtInIdentifier(bool v) { AllowAtInIdentifier = v; } + + void setCommentConsumer(AsmCommentConsumer *CommentConsumer) { + this->CommentConsumer = CommentConsumer; + } + + /// Set whether to lex masm-style binary and hex literals. They look like + /// 0b1101 and 0ABCh respectively. + void setLexMasmIntegers(bool V) { LexMasmIntegers = V; } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCPARSER_MCASMLEXER_H diff --git a/clang-r353983/include/llvm/MC/MCParser/MCAsmParser.h b/clang-r353983/include/llvm/MC/MCParser/MCAsmParser.h new file mode 100644 index 00000000..da5653ee --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCParser/MCAsmParser.h @@ -0,0 +1,309 @@ +//===- llvm/MC/MCAsmParser.h - Abstract Asm Parser Interface ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCPARSER_MCASMPARSER_H +#define LLVM_MC_MCPARSER_MCASMPARSER_H + +#include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/Support/SMLoc.h" +#include <cstdint> +#include <string> +#include <utility> + +namespace llvm { + +class MCAsmInfo; +class MCAsmParserExtension; +class MCContext; +class MCExpr; +class MCInstPrinter; +class MCInstrInfo; +class MCStreamer; +class MCTargetAsmParser; +class SourceMgr; + +struct InlineAsmIdentifierInfo { + enum IdKind { + IK_Invalid, // Initial state. Unexpected after a successful parsing. + IK_Label, // Function/Label reference. + IK_EnumVal, // Value of enumeration type. + IK_Var // Variable. + }; + // Represents an Enum value + struct EnumIdentifier { + int64_t EnumVal; + }; + // Represents a label/function reference + struct LabelIdentifier { + void *Decl; + }; + // Represents a variable + struct VariableIdentifier { + void *Decl; + bool IsGlobalLV; + unsigned Length; + unsigned Size; + unsigned Type; + }; + // An InlineAsm identifier can only be one of those + union { + EnumIdentifier Enum; + LabelIdentifier Label; + VariableIdentifier Var; + }; + bool isKind(IdKind kind) const { return Kind == kind; } + // Initializers + void setEnum(int64_t enumVal) { + assert(isKind(IK_Invalid) && "should be initialized only once"); + Kind = IK_EnumVal; + Enum.EnumVal = enumVal; + } + void setLabel(void *decl) { + assert(isKind(IK_Invalid) && "should be initialized only once"); + Kind = IK_Label; + Label.Decl = decl; + } + void setVar(void *decl, bool isGlobalLV, unsigned size, unsigned type) { + assert(isKind(IK_Invalid) && "should be initialized only once"); + Kind = IK_Var; + Var.Decl = decl; + Var.IsGlobalLV = isGlobalLV; + Var.Size = size; + Var.Type = type; + Var.Length = size / type; + } + InlineAsmIdentifierInfo() : Kind(IK_Invalid) {} + +private: + // Discriminate using the current kind. + IdKind Kind; +}; + +/// Generic Sema callback for assembly parser. +class MCAsmParserSemaCallback { +public: + virtual ~MCAsmParserSemaCallback(); + + virtual void LookupInlineAsmIdentifier(StringRef &LineBuf, + InlineAsmIdentifierInfo &Info, + bool IsUnevaluatedContext) = 0; + virtual StringRef LookupInlineAsmLabel(StringRef Identifier, SourceMgr &SM, + SMLoc Location, bool Create) = 0; + virtual bool LookupInlineAsmField(StringRef Base, StringRef Member, + unsigned &Offset) = 0; +}; + +/// Generic assembler parser interface, for use by target specific +/// assembly parsers. +class MCAsmParser { +public: + using DirectiveHandler = bool (*)(MCAsmParserExtension*, StringRef, SMLoc); + using ExtensionDirectiveHandler = + std::pair<MCAsmParserExtension*, DirectiveHandler>; + + struct MCPendingError { + SMLoc Loc; + SmallString<64> Msg; + SMRange Range; + }; + +private: + MCTargetAsmParser *TargetParser = nullptr; + +protected: // Can only create subclasses. + MCAsmParser(); + + SmallVector<MCPendingError, 0> PendingErrors; + + /// Flag tracking whether any errors have been encountered. + bool HadError = false; + + bool ShowParsedOperands = false; + +public: + MCAsmParser(const MCAsmParser &) = delete; + MCAsmParser &operator=(const MCAsmParser &) = delete; + virtual ~MCAsmParser(); + + virtual void addDirectiveHandler(StringRef Directive, + ExtensionDirectiveHandler Handler) = 0; + + virtual void addAliasForDirective(StringRef Directive, StringRef Alias) = 0; + + virtual SourceMgr &getSourceManager() = 0; + + virtual MCAsmLexer &getLexer() = 0; + const MCAsmLexer &getLexer() const { + return const_cast<MCAsmParser*>(this)->getLexer(); + } + + virtual MCContext &getContext() = 0; + + /// Return the output streamer for the assembler. + virtual MCStreamer &getStreamer() = 0; + + MCTargetAsmParser &getTargetParser() const { return *TargetParser; } + void setTargetParser(MCTargetAsmParser &P); + + virtual unsigned getAssemblerDialect() { return 0;} + virtual void setAssemblerDialect(unsigned i) { } + + bool getShowParsedOperands() const { return ShowParsedOperands; } + void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; } + + /// Run the parser on the input source buffer. + virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; + + virtual void setParsingInlineAsm(bool V) = 0; + virtual bool isParsingInlineAsm() = 0; + + /// Parse MS-style inline assembly. + virtual bool parseMSInlineAsm( + void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, + unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls, + SmallVectorImpl<std::string> &Constraints, + SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, + const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0; + + /// Emit a note at the location \p L, with the message \p Msg. + virtual void Note(SMLoc L, const Twine &Msg, SMRange Range = None) = 0; + + /// Emit a warning at the location \p L, with the message \p Msg. + /// + /// \return The return value is true, if warnings are fatal. + virtual bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) = 0; + + /// Return an error at the location \p L, with the message \p Msg. This + /// may be modified before being emitted. + /// + /// \return The return value is always true, as an idiomatic convenience to + /// clients. + bool Error(SMLoc L, const Twine &Msg, SMRange Range = None); + + /// Emit an error at the location \p L, with the message \p Msg. + /// + /// \return The return value is always true, as an idiomatic convenience to + /// clients. + virtual bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) = 0; + + bool hasPendingError() { return !PendingErrors.empty(); } + + bool printPendingErrors() { + bool rv = !PendingErrors.empty(); + for (auto Err : PendingErrors) { + printError(Err.Loc, Twine(Err.Msg), Err.Range); + } + PendingErrors.clear(); + return rv; + } + + void clearPendingErrors() { PendingErrors.clear(); } + + bool addErrorSuffix(const Twine &Suffix); + + /// Get the next AsmToken in the stream, possibly handling file + /// inclusion first. + virtual const AsmToken &Lex() = 0; + + /// Get the current AsmToken from the stream. + const AsmToken &getTok() const; + + /// Report an error at the current lexer location. + bool TokError(const Twine &Msg, SMRange Range = None); + + bool parseTokenLoc(SMLoc &Loc); + bool parseToken(AsmToken::TokenKind T, const Twine &Msg = "unexpected token"); + /// Attempt to parse and consume token, returning true on + /// success. + bool parseOptionalToken(AsmToken::TokenKind T); + + bool parseEOL(const Twine &ErrMsg); + + bool parseMany(function_ref<bool()> parseOne, bool hasComma = true); + + bool parseIntToken(int64_t &V, const Twine &ErrMsg); + + bool check(bool P, const Twine &Msg); + bool check(bool P, SMLoc Loc, const Twine &Msg); + + /// Parse an identifier or string (as a quoted identifier) and set \p + /// Res to the identifier contents. + virtual bool parseIdentifier(StringRef &Res) = 0; + + /// Parse up to the end of statement and return the contents from the + /// current token until the end of the statement; the current token on exit + /// will be either the EndOfStatement or EOF. + virtual StringRef parseStringToEndOfStatement() = 0; + + /// Parse the current token as a string which may include escaped + /// characters and return the string contents. + virtual bool parseEscapedString(std::string &Data) = 0; + + /// Skip to the end of the current statement, for error recovery. + virtual void eatToEndOfStatement() = 0; + + /// Parse an arbitrary expression. + /// + /// \param Res - The value of the expression. The result is undefined + /// on error. + /// \return - False on success. + virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; + bool parseExpression(const MCExpr *&Res); + + /// Parse a primary expression. + /// + /// \param Res - The value of the expression. The result is undefined + /// on error. + /// \return - False on success. + virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0; + + /// Parse an arbitrary expression, assuming that an initial '(' has + /// already been consumed. + /// + /// \param Res - The value of the expression. The result is undefined + /// on error. + /// \return - False on success. + virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; + + /// Parse an expression which must evaluate to an absolute value. + /// + /// \param Res - The value of the absolute expression. The result is undefined + /// on error. + /// \return - False on success. + virtual bool parseAbsoluteExpression(int64_t &Res) = 0; + + /// Ensure that we have a valid section set in the streamer. Otherwise, + /// report an error and switch to .text. + /// \return - False on success. + virtual bool checkForValidSection() = 0; + + /// Parse an arbitrary expression of a specified parenthesis depth, + /// assuming that the initial '(' characters have already been consumed. + /// + /// \param ParenDepth - Specifies how many trailing expressions outside the + /// current parentheses we have to parse. + /// \param Res - The value of the expression. The result is undefined + /// on error. + /// \return - False on success. + virtual bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, + SMLoc &EndLoc) = 0; +}; + +/// Create an MCAsmParser instance. +MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &, + const MCAsmInfo &, unsigned CB = 0); + +} // end namespace llvm + +#endif // LLVM_MC_MCPARSER_MCASMPARSER_H diff --git a/clang-r353983/include/llvm/MC/MCParser/MCAsmParserExtension.h b/clang-r353983/include/llvm/MC/MCParser/MCAsmParserExtension.h new file mode 100644 index 00000000..5d2afe81 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -0,0 +1,120 @@ +//===- llvm/MC/MCAsmParserExtension.h - Asm Parser Hooks --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H +#define LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/Support/SMLoc.h" + +namespace llvm { + +class Twine; + +/// Generic interface for extending the MCAsmParser, +/// which is implemented by target and object file assembly parser +/// implementations. +class MCAsmParserExtension { + MCAsmParser *Parser; + +protected: + MCAsmParserExtension(); + + // Helper template for implementing static dispatch functions. + template<typename T, bool (T::*Handler)(StringRef, SMLoc)> + static bool HandleDirective(MCAsmParserExtension *Target, + StringRef Directive, + SMLoc DirectiveLoc) { + T *Obj = static_cast<T*>(Target); + return (Obj->*Handler)(Directive, DirectiveLoc); + } + + bool BracketExpressionsSupported = false; + +public: + MCAsmParserExtension(const MCAsmParserExtension &) = delete; + MCAsmParserExtension &operator=(const MCAsmParserExtension &) = delete; + virtual ~MCAsmParserExtension(); + + /// Initialize the extension for parsing using the given \p Parser. + /// The extension should use the AsmParser interfaces to register its + /// parsing routines. + virtual void Initialize(MCAsmParser &Parser); + + /// \name MCAsmParser Proxy Interfaces + /// @{ + + MCContext &getContext() { return getParser().getContext(); } + + MCAsmLexer &getLexer() { return getParser().getLexer(); } + const MCAsmLexer &getLexer() const { + return const_cast<MCAsmParserExtension *>(this)->getLexer(); + } + + MCAsmParser &getParser() { return *Parser; } + const MCAsmParser &getParser() const { + return const_cast<MCAsmParserExtension*>(this)->getParser(); + } + + SourceMgr &getSourceManager() { return getParser().getSourceManager(); } + MCStreamer &getStreamer() { return getParser().getStreamer(); } + + bool Warning(SMLoc L, const Twine &Msg) { + return getParser().Warning(L, Msg); + } + + bool Error(SMLoc L, const Twine &Msg, SMRange Range = SMRange()) { + return getParser().Error(L, Msg, Range); + } + + void Note(SMLoc L, const Twine &Msg) { + getParser().Note(L, Msg); + } + + bool TokError(const Twine &Msg) { + return getParser().TokError(Msg); + } + + const AsmToken &Lex() { return getParser().Lex(); } + const AsmToken &getTok() { return getParser().getTok(); } + bool parseToken(AsmToken::TokenKind T, + const Twine &Msg = "unexpected token") { + return getParser().parseToken(T, Msg); + } + + bool parseMany(function_ref<bool()> parseOne, bool hasComma = true) { + return getParser().parseMany(parseOne, hasComma); + } + + bool parseOptionalToken(AsmToken::TokenKind T) { + return getParser().parseOptionalToken(T); + } + + bool check(bool P, const Twine &Msg) { + return getParser().check(P, Msg); + } + + bool check(bool P, SMLoc Loc, const Twine &Msg) { + return getParser().check(P, Loc, Msg); + } + + bool addErrorSuffix(const Twine &Suffix) { + return getParser().addErrorSuffix(Suffix); + } + + bool HasBracketExpressions() const { return BracketExpressionsSupported; } + + /// @} +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H diff --git a/clang-r353983/include/llvm/MC/MCParser/MCAsmParserUtils.h b/clang-r353983/include/llvm/MC/MCParser/MCAsmParserUtils.h new file mode 100644 index 00000000..d692da74 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCParser/MCAsmParserUtils.h @@ -0,0 +1,33 @@ +//===- llvm/MC/MCAsmParserUtils.h - Asm Parser Utilities --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCPARSER_MCASMPARSERUTILS_H +#define LLVM_MC_MCPARSER_MCASMPARSERUTILS_H + +namespace llvm { + +class MCAsmParser; +class MCExpr; +class MCSymbol; +class StringRef; + +namespace MCParserUtils { + +/// Parse a value expression and return whether it can be assigned to a symbol +/// with the given name. +/// +/// On success, returns false and sets the Symbol and Value output parameters. +bool parseAssignmentExpression(StringRef Name, bool allow_redef, + MCAsmParser &Parser, MCSymbol *&Symbol, + const MCExpr *&Value); + +} // namespace MCParserUtils + +} // namespace llvm + +#endif // LLVM_MC_MCPARSER_MCASMPARSERUTILS_H diff --git a/clang-r353983/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/clang-r353983/include/llvm/MC/MCParser/MCParsedAsmOperand.h new file mode 100644 index 00000000..2b6e2aa4 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -0,0 +1,99 @@ +//===- llvm/MC/MCParsedAsmOperand.h - Asm Parser Operand --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H +#define LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SMLoc.h" +#include <string> + +namespace llvm { + +class raw_ostream; + +/// MCParsedAsmOperand - This abstract class represents a source-level assembly +/// instruction operand. It should be subclassed by target-specific code. This +/// base class is used by target-independent clients and is the interface +/// between parsing an asm instruction and recognizing it. +class MCParsedAsmOperand { + /// MCOperandNum - The corresponding MCInst operand number. Only valid when + /// parsing MS-style inline assembly. + unsigned MCOperandNum; + + /// Constraint - The constraint on this operand. Only valid when parsing + /// MS-style inline assembly. + std::string Constraint; + +protected: + // This only seems to need to be movable (by ARMOperand) but ARMOperand has + // lots of members and MSVC doesn't support defaulted move ops, so to avoid + // that verbosity, just rely on defaulted copy ops. It's only the Constraint + // string member that would benefit from movement anyway. + MCParsedAsmOperand() = default; + MCParsedAsmOperand(const MCParsedAsmOperand &RHS) = default; + MCParsedAsmOperand &operator=(const MCParsedAsmOperand &) = default; + +public: + virtual ~MCParsedAsmOperand() = default; + + void setConstraint(StringRef C) { Constraint = C.str(); } + StringRef getConstraint() { return Constraint; } + + void setMCOperandNum (unsigned OpNum) { MCOperandNum = OpNum; } + unsigned getMCOperandNum() { return MCOperandNum; } + + virtual StringRef getSymName() { return StringRef(); } + virtual void *getOpDecl() { return nullptr; } + + /// isToken - Is this a token operand? + virtual bool isToken() const = 0; + /// isImm - Is this an immediate operand? + virtual bool isImm() const = 0; + /// isReg - Is this a register operand? + virtual bool isReg() const = 0; + virtual unsigned getReg() const = 0; + + /// isMem - Is this a memory operand? + virtual bool isMem() const = 0; + + /// getStartLoc - Get the location of the first token of this operand. + virtual SMLoc getStartLoc() const = 0; + /// getEndLoc - Get the location of the last token of this operand. + virtual SMLoc getEndLoc() const = 0; + + /// needAddressOf - Do we need to emit code to get the address of the + /// variable/label? Only valid when parsing MS-style inline assembly. + virtual bool needAddressOf() const { return false; } + + /// isOffsetOf - Do we need to emit code to get the offset of the variable, + /// rather then the value of the variable? Only valid when parsing MS-style + /// inline assembly. + virtual bool isOffsetOf() const { return false; } + + /// getOffsetOfLoc - Get the location of the offset operator. + virtual SMLoc getOffsetOfLoc() const { return SMLoc(); } + + /// print - Print a debug representation of the operand to the given stream. + virtual void print(raw_ostream &OS) const = 0; + + /// dump - Print to the debug stream. + virtual void dump() const; +}; + +//===----------------------------------------------------------------------===// +// Debugging Support + +inline raw_ostream& operator<<(raw_ostream &OS, const MCParsedAsmOperand &MO) { + MO.print(OS); + return OS; +} + +} // end namespace llvm + +#endif // LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H diff --git a/clang-r353983/include/llvm/MC/MCParser/MCTargetAsmParser.h b/clang-r353983/include/llvm/MC/MCParser/MCTargetAsmParser.h new file mode 100644 index 00000000..c5683b74 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCParser/MCTargetAsmParser.h @@ -0,0 +1,499 @@ +//===- llvm/MC/MCTargetAsmParser.h - Target Assembly Parser -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCPARSER_MCTARGETASMPARSER_H +#define LLVM_MC_MCPARSER_MCTARGETASMPARSER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/SMLoc.h" +#include <cstdint> +#include <memory> + +namespace llvm { + +class MCInst; +class MCParsedAsmOperand; +class MCStreamer; +class MCSubtargetInfo; +template <typename T> class SmallVectorImpl; + +using OperandVector = SmallVectorImpl<std::unique_ptr<MCParsedAsmOperand>>; + +enum AsmRewriteKind { + AOK_Align, // Rewrite align as .align. + AOK_EVEN, // Rewrite even as .even. + AOK_Emit, // Rewrite _emit as .byte. + AOK_Input, // Rewrite in terms of $N. + AOK_Output, // Rewrite in terms of $N. + AOK_SizeDirective, // Add a sizing directive (e.g., dword ptr). + AOK_Label, // Rewrite local labels. + AOK_EndOfStatement, // Add EndOfStatement (e.g., "\n\t"). + AOK_Skip, // Skip emission (e.g., offset/type operators). + AOK_IntelExpr // SizeDirective SymDisp [BaseReg + IndexReg * Scale + ImmDisp] +}; + +const char AsmRewritePrecedence [] = { + 2, // AOK_Align + 2, // AOK_EVEN + 2, // AOK_Emit + 3, // AOK_Input + 3, // AOK_Output + 5, // AOK_SizeDirective + 1, // AOK_Label + 5, // AOK_EndOfStatement + 2, // AOK_Skip + 2 // AOK_IntelExpr +}; + +// Represnt the various parts which makes up an intel expression, +// used for emitting compound intel expressions +struct IntelExpr { + bool NeedBracs; + int64_t Imm; + StringRef BaseReg; + StringRef IndexReg; + unsigned Scale; + + IntelExpr(bool needBracs = false) : NeedBracs(needBracs), Imm(0), + BaseReg(StringRef()), IndexReg(StringRef()), + Scale(1) {} + // Compund immediate expression + IntelExpr(int64_t imm, bool needBracs) : IntelExpr(needBracs) { + Imm = imm; + } + // [Reg + ImmediateExpression] + // We don't bother to emit an immediate expression evaluated to zero + IntelExpr(StringRef reg, int64_t imm = 0, unsigned scale = 0, + bool needBracs = true) : + IntelExpr(imm, needBracs) { + IndexReg = reg; + if (scale) + Scale = scale; + } + // [BaseReg + IndexReg * ScaleExpression + ImmediateExpression] + IntelExpr(StringRef baseReg, StringRef indexReg, unsigned scale = 0, + int64_t imm = 0, bool needBracs = true) : + IntelExpr(indexReg, imm, scale, needBracs) { + BaseReg = baseReg; + } + bool hasBaseReg() const { + return BaseReg.size(); + } + bool hasIndexReg() const { + return IndexReg.size(); + } + bool hasRegs() const { + return hasBaseReg() || hasIndexReg(); + } + bool isValid() const { + return (Scale == 1) || + (hasIndexReg() && (Scale == 2 || Scale == 4 || Scale == 8)); + } +}; + +struct AsmRewrite { + AsmRewriteKind Kind; + SMLoc Loc; + unsigned Len; + int64_t Val; + StringRef Label; + IntelExpr IntelExp; + +public: + AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len = 0, int64_t val = 0) + : Kind(kind), Loc(loc), Len(len), Val(val) {} + AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len, StringRef label) + : AsmRewrite(kind, loc, len) { Label = label; } + AsmRewrite(SMLoc loc, unsigned len, IntelExpr exp) + : AsmRewrite(AOK_IntelExpr, loc, len) { IntelExp = exp; } +}; + +struct ParseInstructionInfo { + SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr; + + ParseInstructionInfo() = default; + ParseInstructionInfo(SmallVectorImpl<AsmRewrite> *rewrites) + : AsmRewrites(rewrites) {} +}; + +enum OperandMatchResultTy { + MatchOperand_Success, // operand matched successfully + MatchOperand_NoMatch, // operand did not match + MatchOperand_ParseFail // operand matched but had errors +}; + +enum class DiagnosticPredicateTy { + Match, + NearMatch, + NoMatch, +}; + +// When an operand is parsed, the assembler will try to iterate through a set of +// possible operand classes that the operand might match and call the +// corresponding PredicateMethod to determine that. +// +// If there are two AsmOperands that would give a specific diagnostic if there +// is no match, there is currently no mechanism to distinguish which operand is +// a closer match. The DiagnosticPredicate distinguishes between 'completely +// no match' and 'near match', so the assembler can decide whether to give a +// specific diagnostic, or use 'InvalidOperand' and continue to find a +// 'better matching' diagnostic. +// +// For example: +// opcode opnd0, onpd1, opnd2 +// +// where: +// opnd2 could be an 'immediate of range [-8, 7]' +// opnd2 could be a 'register + shift/extend'. +// +// If opnd2 is a valid register, but with a wrong shift/extend suffix, it makes +// little sense to give a diagnostic that the operand should be an immediate +// in range [-8, 7]. +// +// This is a light-weight alternative to the 'NearMissInfo' approach +// below which collects *all* possible diagnostics. This alternative +// is optional and fully backward compatible with existing +// PredicateMethods that return a 'bool' (match or no match). +struct DiagnosticPredicate { + DiagnosticPredicateTy Type; + + explicit DiagnosticPredicate(bool Match) + : Type(Match ? DiagnosticPredicateTy::Match + : DiagnosticPredicateTy::NearMatch) {} + DiagnosticPredicate(DiagnosticPredicateTy T) : Type(T) {} + DiagnosticPredicate(const DiagnosticPredicate &) = default; + + operator bool() const { return Type == DiagnosticPredicateTy::Match; } + bool isMatch() const { return Type == DiagnosticPredicateTy::Match; } + bool isNearMatch() const { return Type == DiagnosticPredicateTy::NearMatch; } + bool isNoMatch() const { return Type == DiagnosticPredicateTy::NoMatch; } +}; + +// When matching of an assembly instruction fails, there may be multiple +// encodings that are close to being a match. It's often ambiguous which one +// the programmer intended to use, so we want to report an error which mentions +// each of these "near-miss" encodings. This struct contains information about +// one such encoding, and why it did not match the parsed instruction. +class NearMissInfo { +public: + enum NearMissKind { + NoNearMiss, + NearMissOperand, + NearMissFeature, + NearMissPredicate, + NearMissTooFewOperands, + }; + + // The encoding is valid for the parsed assembly string. This is only used + // internally to the table-generated assembly matcher. + static NearMissInfo getSuccess() { return NearMissInfo(); } + + // The instruction encoding is not valid because it requires some target + // features that are not currently enabled. MissingFeatures has a bit set for + // each feature that the encoding needs but which is not enabled. + static NearMissInfo getMissedFeature(uint64_t MissingFeatures) { + NearMissInfo Result; + Result.Kind = NearMissFeature; + Result.Features = MissingFeatures; + return Result; + } + + // The instruction encoding is not valid because the target-specific + // predicate function returned an error code. FailureCode is the + // target-specific error code returned by the predicate. + static NearMissInfo getMissedPredicate(unsigned FailureCode) { + NearMissInfo Result; + Result.Kind = NearMissPredicate; + Result.PredicateError = FailureCode; + return Result; + } + + // The instruction encoding is not valid because one (and only one) parsed + // operand is not of the correct type. OperandError is the error code + // relating to the operand class expected by the encoding. OperandClass is + // the type of the expected operand. Opcode is the opcode of the encoding. + // OperandIndex is the index into the parsed operand list. + static NearMissInfo getMissedOperand(unsigned OperandError, + unsigned OperandClass, unsigned Opcode, + unsigned OperandIndex) { + NearMissInfo Result; + Result.Kind = NearMissOperand; + Result.MissedOperand.Error = OperandError; + Result.MissedOperand.Class = OperandClass; + Result.MissedOperand.Opcode = Opcode; + Result.MissedOperand.Index = OperandIndex; + return Result; + } + + // The instruction encoding is not valid because it expects more operands + // than were parsed. OperandClass is the class of the expected operand that + // was not provided. Opcode is the instruction encoding. + static NearMissInfo getTooFewOperands(unsigned OperandClass, + unsigned Opcode) { + NearMissInfo Result; + Result.Kind = NearMissTooFewOperands; + Result.TooFewOperands.Class = OperandClass; + Result.TooFewOperands.Opcode = Opcode; + return Result; + } + + operator bool() const { return Kind != NoNearMiss; } + + NearMissKind getKind() const { return Kind; } + + // Feature flags required by the instruction, that the current target does + // not have. + uint64_t getFeatures() const { + assert(Kind == NearMissFeature); + return Features; + } + // Error code returned by the target predicate when validating this + // instruction encoding. + unsigned getPredicateError() const { + assert(Kind == NearMissPredicate); + return PredicateError; + } + // MatchClassKind of the operand that we expected to see. + unsigned getOperandClass() const { + assert(Kind == NearMissOperand || Kind == NearMissTooFewOperands); + return MissedOperand.Class; + } + // Opcode of the encoding we were trying to match. + unsigned getOpcode() const { + assert(Kind == NearMissOperand || Kind == NearMissTooFewOperands); + return MissedOperand.Opcode; + } + // Error code returned when validating the operand. + unsigned getOperandError() const { + assert(Kind == NearMissOperand); + return MissedOperand.Error; + } + // Index of the actual operand we were trying to match in the list of parsed + // operands. + unsigned getOperandIndex() const { + assert(Kind == NearMissOperand); + return MissedOperand.Index; + } + +private: + NearMissKind Kind; + + // These two structs share a common prefix, so we can safely rely on the fact + // that they overlap in the union. + struct MissedOpInfo { + unsigned Class; + unsigned Opcode; + unsigned Error; + unsigned Index; + }; + + struct TooFewOperandsInfo { + unsigned Class; + unsigned Opcode; + }; + + union { + uint64_t Features; + unsigned PredicateError; + MissedOpInfo MissedOperand; + TooFewOperandsInfo TooFewOperands; + }; + + NearMissInfo() : Kind(NoNearMiss) {} +}; + +/// MCTargetAsmParser - Generic interface to target specific assembly parsers. +class MCTargetAsmParser : public MCAsmParserExtension { +public: + enum MatchResultTy { + Match_InvalidOperand, + Match_InvalidTiedOperand, + Match_MissingFeature, + Match_MnemonicFail, + Match_Success, + Match_NearMisses, + FIRST_TARGET_MATCH_RESULT_TY + }; + +protected: // Can only create subclasses. + MCTargetAsmParser(MCTargetOptions const &, const MCSubtargetInfo &STI, + const MCInstrInfo &MII); + + /// Create a copy of STI and return a non-const reference to it. + MCSubtargetInfo ©STI(); + + /// AvailableFeatures - The current set of available features. + uint64_t AvailableFeatures = 0; + + /// ParsingInlineAsm - Are we parsing ms-style inline assembly? + bool ParsingInlineAsm = false; + + /// SemaCallback - The Sema callback implementation. Must be set when parsing + /// ms-style inline assembly. + MCAsmParserSemaCallback *SemaCallback; + + /// Set of options which affects instrumentation of inline assembly. + MCTargetOptions MCOptions; + + /// Current STI. + const MCSubtargetInfo *STI; + + const MCInstrInfo &MII; + +public: + MCTargetAsmParser(const MCTargetAsmParser &) = delete; + MCTargetAsmParser &operator=(const MCTargetAsmParser &) = delete; + + ~MCTargetAsmParser() override; + + const MCSubtargetInfo &getSTI() const; + + uint64_t getAvailableFeatures() const { return AvailableFeatures; } + void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } + + bool isParsingInlineAsm () { return ParsingInlineAsm; } + void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; } + + MCTargetOptions getTargetOptions() const { return MCOptions; } + + void setSemaCallback(MCAsmParserSemaCallback *Callback) { + SemaCallback = Callback; + } + + // Target-specific parsing of expression. + virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { + return getParser().parsePrimaryExpr(Res, EndLoc); + } + + virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) = 0; + + /// Sets frame register corresponding to the current MachineFunction. + virtual void SetFrameRegister(unsigned RegNo) {} + + /// ParseInstruction - Parse one assembly instruction. + /// + /// The parser is positioned following the instruction name. The target + /// specific instruction parser should parse the entire instruction and + /// construct the appropriate MCInst, or emit an error. On success, the entire + /// line should be parsed up to and including the end-of-statement token. On + /// failure, the parser is not required to read to the end of the line. + // + /// \param Name - The instruction name. + /// \param NameLoc - The source location of the name. + /// \param Operands [out] - The list of parsed operands, this returns + /// ownership of them to the caller. + /// \return True on failure. + virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, OperandVector &Operands) = 0; + virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, + AsmToken Token, OperandVector &Operands) { + return ParseInstruction(Info, Name, Token.getLoc(), Operands); + } + + /// ParseDirective - Parse a target specific assembler directive + /// + /// The parser is positioned following the directive name. The target + /// specific directive parser should parse the entire directive doing or + /// recording any target specific work, or return true and do nothing if the + /// directive is not target specific. If the directive is specific for + /// the target, the entire line is parsed up to and including the + /// end-of-statement token and false is returned. + /// + /// \param DirectiveID - the identifier token of the directive. + virtual bool ParseDirective(AsmToken DirectiveID) = 0; + + /// MatchAndEmitInstruction - Recognize a series of operands of a parsed + /// instruction as an actual MCInst and emit it to the specified MCStreamer. + /// This returns false on success and returns true on failure to match. + /// + /// On failure, the target parser is responsible for emitting a diagnostic + /// explaining the match failure. + virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + OperandVector &Operands, MCStreamer &Out, + uint64_t &ErrorInfo, + bool MatchingInlineAsm) = 0; + + /// Allows targets to let registers opt out of clobber lists. + virtual bool OmitRegisterFromClobberLists(unsigned RegNo) { return false; } + + /// Allow a target to add special case operand matching for things that + /// tblgen doesn't/can't handle effectively. For example, literal + /// immediates on ARM. TableGen expects a token operand, but the parser + /// will recognize them as immediates. + virtual unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, + unsigned Kind) { + return Match_InvalidOperand; + } + + /// Validate the instruction match against any complex target predicates + /// before rendering any operands to it. + virtual unsigned + checkEarlyTargetMatchPredicate(MCInst &Inst, const OperandVector &Operands) { + return Match_Success; + } + + /// checkTargetMatchPredicate - Validate the instruction match against + /// any complex target predicates not expressible via match classes. + virtual unsigned checkTargetMatchPredicate(MCInst &Inst) { + return Match_Success; + } + + virtual void convertToMapAndConstraints(unsigned Kind, + const OperandVector &Operands) = 0; + + /// Returns whether two registers are equal and is used by the tied-operands + /// checks in the AsmMatcher. This method can be overridden allow e.g. a + /// sub- or super-register as the tied operand. + virtual bool regsEqual(const MCParsedAsmOperand &Op1, + const MCParsedAsmOperand &Op2) const { + assert(Op1.isReg() && Op2.isReg() && "Operands not all regs"); + return Op1.getReg() == Op2.getReg(); + } + + // Return whether this parser uses assignment statements with equals tokens + virtual bool equalIsAsmAssignment() { return true; }; + // Return whether this start of statement identifier is a label + virtual bool isLabel(AsmToken &Token) { return true; }; + // Return whether this parser accept star as start of statement + virtual bool starIsStartOfStatement() { return false; }; + + virtual const MCExpr *applyModifierToExpr(const MCExpr *E, + MCSymbolRefExpr::VariantKind, + MCContext &Ctx) { + return nullptr; + } + + // For actions that have to be performed before a label is emitted + virtual void doBeforeLabelEmit(MCSymbol *Symbol) {} + + virtual void onLabelParsed(MCSymbol *Symbol) {} + + /// Ensure that all previously parsed instructions have been emitted to the + /// output streamer, if the target does not emit them immediately. + virtual void flushPendingInstructions(MCStreamer &Out) {} + + virtual const MCExpr *createTargetUnaryExpr(const MCExpr *E, + AsmToken::TokenKind OperatorToken, + MCContext &Ctx) { + return nullptr; + } + + // For any checks or cleanups at the end of parsing. + virtual void onEndOfFile() {} +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCPARSER_MCTARGETASMPARSER_H diff --git a/clang-r353983/include/llvm/MC/MCRegisterInfo.h b/clang-r353983/include/llvm/MC/MCRegisterInfo.h new file mode 100644 index 00000000..92d39c3f --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCRegisterInfo.h @@ -0,0 +1,727 @@ +//===- MC/MCRegisterInfo.h - Target Register Description --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file describes an abstract interface used to get information about a +// target machines register file. This information is used for a variety of +// purposed, especially register allocation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCREGISTERINFO_H +#define LLVM_MC_MCREGISTERINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/MC/LaneBitmask.h" +#include <cassert> +#include <cstdint> +#include <utility> + +namespace llvm { + +/// An unsigned integer type large enough to represent all physical registers, +/// but not necessarily virtual registers. +using MCPhysReg = uint16_t; + +/// MCRegisterClass - Base class of TargetRegisterClass. +class MCRegisterClass { +public: + using iterator = const MCPhysReg*; + using const_iterator = const MCPhysReg*; + + const iterator RegsBegin; + const uint8_t *const RegSet; + const uint32_t NameIdx; + const uint16_t RegsSize; + const uint16_t RegSetSize; + const uint16_t ID; + const int8_t CopyCost; + const bool Allocatable; + + /// getID() - Return the register class ID number. + /// + unsigned getID() const { return ID; } + + /// begin/end - Return all of the registers in this class. + /// + iterator begin() const { return RegsBegin; } + iterator end() const { return RegsBegin + RegsSize; } + + /// getNumRegs - Return the number of registers in this class. + /// + unsigned getNumRegs() const { return RegsSize; } + + /// getRegister - Return the specified register in the class. + /// + unsigned getRegister(unsigned i) const { + assert(i < getNumRegs() && "Register number out of range!"); + return RegsBegin[i]; + } + + /// contains - Return true if the specified register is included in this + /// register class. This does not include virtual registers. + bool contains(unsigned Reg) const { + unsigned InByte = Reg % 8; + unsigned Byte = Reg / 8; + if (Byte >= RegSetSize) + return false; + return (RegSet[Byte] & (1 << InByte)) != 0; + } + + /// contains - Return true if both registers are in this class. + bool contains(unsigned Reg1, unsigned Reg2) const { + return contains(Reg1) && contains(Reg2); + } + + /// getCopyCost - Return the cost of copying a value between two registers in + /// this class. A negative number means the register class is very expensive + /// to copy e.g. status flag register classes. + int getCopyCost() const { return CopyCost; } + + /// isAllocatable - Return true if this register class may be used to create + /// virtual registers. + bool isAllocatable() const { return Allocatable; } +}; + +/// MCRegisterDesc - This record contains information about a particular +/// register. The SubRegs field is a zero terminated array of registers that +/// are sub-registers of the specific register, e.g. AL, AH are sub-registers +/// of AX. The SuperRegs field is a zero terminated array of registers that are +/// super-registers of the specific register, e.g. RAX, EAX, are +/// super-registers of AX. +/// +struct MCRegisterDesc { + uint32_t Name; // Printable name for the reg (for debugging) + uint32_t SubRegs; // Sub-register set, described above + uint32_t SuperRegs; // Super-register set, described above + + // Offset into MCRI::SubRegIndices of a list of sub-register indices for each + // sub-register in SubRegs. + uint32_t SubRegIndices; + + // RegUnits - Points to the list of register units. The low 4 bits holds the + // Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator. + uint32_t RegUnits; + + /// Index into list with lane mask sequences. The sequence contains a lanemask + /// for every register unit. + uint16_t RegUnitLaneMasks; +}; + +/// MCRegisterInfo base class - We assume that the target defines a static +/// array of MCRegisterDesc objects that represent all of the machine +/// registers that the target has. As such, we simply have to track a pointer +/// to this array so that we can turn register number into a register +/// descriptor. +/// +/// Note this class is designed to be a base class of TargetRegisterInfo, which +/// is the interface used by codegen. However, specific targets *should never* +/// specialize this class. MCRegisterInfo should only contain getters to access +/// TableGen generated physical register data. It must not be extended with +/// virtual methods. +/// +class MCRegisterInfo { +public: + using regclass_iterator = const MCRegisterClass *; + + /// DwarfLLVMRegPair - Emitted by tablegen so Dwarf<->LLVM reg mappings can be + /// performed with a binary search. + struct DwarfLLVMRegPair { + unsigned FromReg; + unsigned ToReg; + + bool operator<(DwarfLLVMRegPair RHS) const { return FromReg < RHS.FromReg; } + }; + + /// SubRegCoveredBits - Emitted by tablegen: bit range covered by a subreg + /// index, -1 in any being invalid. + struct SubRegCoveredBits { + uint16_t Offset; + uint16_t Size; + }; + +private: + const MCRegisterDesc *Desc; // Pointer to the descriptor array + unsigned NumRegs; // Number of entries in the array + unsigned RAReg; // Return address register + unsigned PCReg; // Program counter register + const MCRegisterClass *Classes; // Pointer to the regclass array + unsigned NumClasses; // Number of entries in the array + unsigned NumRegUnits; // Number of regunits. + const MCPhysReg (*RegUnitRoots)[2]; // Pointer to regunit root table. + const MCPhysReg *DiffLists; // Pointer to the difflists array + const LaneBitmask *RegUnitMaskSequences; // Pointer to lane mask sequences + // for register units. + const char *RegStrings; // Pointer to the string table. + const char *RegClassStrings; // Pointer to the class strings. + const uint16_t *SubRegIndices; // Pointer to the subreg lookup + // array. + const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered + // bit ranges array. + unsigned NumSubRegIndices; // Number of subreg indices. + const uint16_t *RegEncodingTable; // Pointer to array of register + // encodings. + + unsigned L2DwarfRegsSize; + unsigned EHL2DwarfRegsSize; + unsigned Dwarf2LRegsSize; + unsigned EHDwarf2LRegsSize; + const DwarfLLVMRegPair *L2DwarfRegs; // LLVM to Dwarf regs mapping + const DwarfLLVMRegPair *EHL2DwarfRegs; // LLVM to Dwarf regs mapping EH + const DwarfLLVMRegPair *Dwarf2LRegs; // Dwarf to LLVM regs mapping + const DwarfLLVMRegPair *EHDwarf2LRegs; // Dwarf to LLVM regs mapping EH + DenseMap<unsigned, int> L2SEHRegs; // LLVM to SEH regs mapping + DenseMap<unsigned, int> L2CVRegs; // LLVM to CV regs mapping + +public: + /// DiffListIterator - Base iterator class that can traverse the + /// differentially encoded register and regunit lists in DiffLists. + /// Don't use this class directly, use one of the specialized sub-classes + /// defined below. + class DiffListIterator { + uint16_t Val = 0; + const MCPhysReg *List = nullptr; + + protected: + /// Create an invalid iterator. Call init() to point to something useful. + DiffListIterator() = default; + + /// init - Point the iterator to InitVal, decoding subsequent values from + /// DiffList. The iterator will initially point to InitVal, sub-classes are + /// responsible for skipping the seed value if it is not part of the list. + void init(MCPhysReg InitVal, const MCPhysReg *DiffList) { + Val = InitVal; + List = DiffList; + } + + /// advance - Move to the next list position, return the applied + /// differential. This function does not detect the end of the list, that + /// is the caller's responsibility (by checking for a 0 return value). + unsigned advance() { + assert(isValid() && "Cannot move off the end of the list."); + MCPhysReg D = *List++; + Val += D; + return D; + } + + public: + /// isValid - returns true if this iterator is not yet at the end. + bool isValid() const { return List; } + + /// Dereference the iterator to get the value at the current position. + unsigned operator*() const { return Val; } + + /// Pre-increment to move to the next position. + void operator++() { + // The end of the list is encoded as a 0 differential. + if (!advance()) + List = nullptr; + } + }; + + // These iterators are allowed to sub-class DiffListIterator and access + // internal list pointers. + friend class MCSubRegIterator; + friend class MCSubRegIndexIterator; + friend class MCSuperRegIterator; + friend class MCRegUnitIterator; + friend class MCRegUnitMaskIterator; + friend class MCRegUnitRootIterator; + + /// Initialize MCRegisterInfo, called by TableGen + /// auto-generated routines. *DO NOT USE*. + void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA, + unsigned PC, + const MCRegisterClass *C, unsigned NC, + const MCPhysReg (*RURoots)[2], + unsigned NRU, + const MCPhysReg *DL, + const LaneBitmask *RUMS, + const char *Strings, + const char *ClassStrings, + const uint16_t *SubIndices, + unsigned NumIndices, + const SubRegCoveredBits *SubIdxRanges, + const uint16_t *RET) { + Desc = D; + NumRegs = NR; + RAReg = RA; + PCReg = PC; + Classes = C; + DiffLists = DL; + RegUnitMaskSequences = RUMS; + RegStrings = Strings; + RegClassStrings = ClassStrings; + NumClasses = NC; + RegUnitRoots = RURoots; + NumRegUnits = NRU; + SubRegIndices = SubIndices; + NumSubRegIndices = NumIndices; + SubRegIdxRanges = SubIdxRanges; + RegEncodingTable = RET; + + // Initialize DWARF register mapping variables + EHL2DwarfRegs = nullptr; + EHL2DwarfRegsSize = 0; + L2DwarfRegs = nullptr; + L2DwarfRegsSize = 0; + EHDwarf2LRegs = nullptr; + EHDwarf2LRegsSize = 0; + Dwarf2LRegs = nullptr; + Dwarf2LRegsSize = 0; + } + + /// Used to initialize LLVM register to Dwarf + /// register number mapping. Called by TableGen auto-generated routines. + /// *DO NOT USE*. + void mapLLVMRegsToDwarfRegs(const DwarfLLVMRegPair *Map, unsigned Size, + bool isEH) { + if (isEH) { + EHL2DwarfRegs = Map; + EHL2DwarfRegsSize = Size; + } else { + L2DwarfRegs = Map; + L2DwarfRegsSize = Size; + } + } + + /// Used to initialize Dwarf register to LLVM + /// register number mapping. Called by TableGen auto-generated routines. + /// *DO NOT USE*. + void mapDwarfRegsToLLVMRegs(const DwarfLLVMRegPair *Map, unsigned Size, + bool isEH) { + if (isEH) { + EHDwarf2LRegs = Map; + EHDwarf2LRegsSize = Size; + } else { + Dwarf2LRegs = Map; + Dwarf2LRegsSize = Size; + } + } + + /// mapLLVMRegToSEHReg - Used to initialize LLVM register to SEH register + /// number mapping. By default the SEH register number is just the same + /// as the LLVM register number. + /// FIXME: TableGen these numbers. Currently this requires target specific + /// initialization code. + void mapLLVMRegToSEHReg(unsigned LLVMReg, int SEHReg) { + L2SEHRegs[LLVMReg] = SEHReg; + } + + void mapLLVMRegToCVReg(unsigned LLVMReg, int CVReg) { + L2CVRegs[LLVMReg] = CVReg; + } + + /// This method should return the register where the return + /// address can be found. + unsigned getRARegister() const { + return RAReg; + } + + /// Return the register which is the program counter. + unsigned getProgramCounter() const { + return PCReg; + } + + const MCRegisterDesc &operator[](unsigned RegNo) const { + assert(RegNo < NumRegs && + "Attempting to access record for invalid register number!"); + return Desc[RegNo]; + } + + /// Provide a get method, equivalent to [], but more useful with a + /// pointer to this object. + const MCRegisterDesc &get(unsigned RegNo) const { + return operator[](RegNo); + } + + /// Returns the physical register number of sub-register "Index" + /// for physical register RegNo. Return zero if the sub-register does not + /// exist. + unsigned getSubReg(unsigned Reg, unsigned Idx) const; + + /// Return a super-register of the specified register + /// Reg so its sub-register of index SubIdx is Reg. + unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, + const MCRegisterClass *RC) const; + + /// For a given register pair, return the sub-register index + /// if the second register is a sub-register of the first. Return zero + /// otherwise. + unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const; + + /// Get the size of the bit range covered by a sub-register index. + /// If the index isn't continuous, return the sum of the sizes of its parts. + /// If the index is used to access subregisters of different sizes, return -1. + unsigned getSubRegIdxSize(unsigned Idx) const; + + /// Get the offset of the bit range covered by a sub-register index. + /// If an Offset doesn't make sense (the index isn't continuous, or is used to + /// access sub-registers at different offsets), return -1. + unsigned getSubRegIdxOffset(unsigned Idx) const; + + /// Return the human-readable symbolic target-specific name for the + /// specified physical register. + const char *getName(unsigned RegNo) const { + return RegStrings + get(RegNo).Name; + } + + /// Return the number of registers this target has (useful for + /// sizing arrays holding per register information) + unsigned getNumRegs() const { + return NumRegs; + } + + /// Return the number of sub-register indices + /// understood by the target. Index 0 is reserved for the no-op sub-register, + /// while 1 to getNumSubRegIndices() - 1 represent real sub-registers. + unsigned getNumSubRegIndices() const { + return NumSubRegIndices; + } + + /// Return the number of (native) register units in the + /// target. Register units are numbered from 0 to getNumRegUnits() - 1. They + /// can be accessed through MCRegUnitIterator defined below. + unsigned getNumRegUnits() const { + return NumRegUnits; + } + + /// Map a target register to an equivalent dwarf register + /// number. Returns -1 if there is no equivalent value. The second + /// parameter allows targets to use different numberings for EH info and + /// debugging info. + int getDwarfRegNum(unsigned RegNum, bool isEH) const; + + /// Map a dwarf register back to a target register. + int getLLVMRegNum(unsigned RegNum, bool isEH) const; + + /// Map a DWARF EH register back to a target register (same as + /// getLLVMRegNum(RegNum, true)) but return -1 if there is no mapping, + /// rather than asserting that there must be one. + int getLLVMRegNumFromEH(unsigned RegNum) const; + + /// Map a target EH register number to an equivalent DWARF register + /// number. + int getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const; + + /// Map a target register to an equivalent SEH register + /// number. Returns LLVM register number if there is no equivalent value. + int getSEHRegNum(unsigned RegNum) const; + + /// Map a target register to an equivalent CodeView register + /// number. + int getCodeViewRegNum(unsigned RegNum) const; + + regclass_iterator regclass_begin() const { return Classes; } + regclass_iterator regclass_end() const { return Classes+NumClasses; } + iterator_range<regclass_iterator> regclasses() const { + return make_range(regclass_begin(), regclass_end()); + } + + unsigned getNumRegClasses() const { + return (unsigned)(regclass_end()-regclass_begin()); + } + + /// Returns the register class associated with the enumeration + /// value. See class MCOperandInfo. + const MCRegisterClass& getRegClass(unsigned i) const { + assert(i < getNumRegClasses() && "Register Class ID out of range"); + return Classes[i]; + } + + const char *getRegClassName(const MCRegisterClass *Class) const { + return RegClassStrings + Class->NameIdx; + } + + /// Returns the encoding for RegNo + uint16_t getEncodingValue(unsigned RegNo) const { + assert(RegNo < NumRegs && + "Attempting to get encoding for invalid register number!"); + return RegEncodingTable[RegNo]; + } + + /// Returns true if RegB is a sub-register of RegA. + bool isSubRegister(unsigned RegA, unsigned RegB) const { + return isSuperRegister(RegB, RegA); + } + + /// Returns true if RegB is a super-register of RegA. + bool isSuperRegister(unsigned RegA, unsigned RegB) const; + + /// Returns true if RegB is a sub-register of RegA or if RegB == RegA. + bool isSubRegisterEq(unsigned RegA, unsigned RegB) const { + return isSuperRegisterEq(RegB, RegA); + } + + /// Returns true if RegB is a super-register of RegA or if + /// RegB == RegA. + bool isSuperRegisterEq(unsigned RegA, unsigned RegB) const { + return RegA == RegB || isSuperRegister(RegA, RegB); + } + + /// Returns true if RegB is a super-register or sub-register of RegA + /// or if RegB == RegA. + bool isSuperOrSubRegisterEq(unsigned RegA, unsigned RegB) const { + return isSubRegisterEq(RegA, RegB) || isSuperRegister(RegA, RegB); + } +}; + +//===----------------------------------------------------------------------===// +// Register List Iterators +//===----------------------------------------------------------------------===// + +// MCRegisterInfo provides lists of super-registers, sub-registers, and +// aliasing registers. Use these iterator classes to traverse the lists. + +/// MCSubRegIterator enumerates all sub-registers of Reg. +/// If IncludeSelf is set, Reg itself is included in the list. +class MCSubRegIterator : public MCRegisterInfo::DiffListIterator { +public: + MCSubRegIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf = false) { + init(Reg, MCRI->DiffLists + MCRI->get(Reg).SubRegs); + // Initially, the iterator points to Reg itself. + if (!IncludeSelf) + ++*this; + } +}; + +/// Iterator that enumerates the sub-registers of a Reg and the associated +/// sub-register indices. +class MCSubRegIndexIterator { + MCSubRegIterator SRIter; + const uint16_t *SRIndex; + +public: + /// Constructs an iterator that traverses subregisters and their + /// associated subregister indices. + MCSubRegIndexIterator(unsigned Reg, const MCRegisterInfo *MCRI) + : SRIter(Reg, MCRI) { + SRIndex = MCRI->SubRegIndices + MCRI->get(Reg).SubRegIndices; + } + + /// Returns current sub-register. + unsigned getSubReg() const { + return *SRIter; + } + + /// Returns sub-register index of the current sub-register. + unsigned getSubRegIndex() const { + return *SRIndex; + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return SRIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++SRIter; + ++SRIndex; + } +}; + +/// MCSuperRegIterator enumerates all super-registers of Reg. +/// If IncludeSelf is set, Reg itself is included in the list. +class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { +public: + MCSuperRegIterator() = default; + + MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf = false) { + init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs); + // Initially, the iterator points to Reg itself. + if (!IncludeSelf) + ++*this; + } +}; + +// Definition for isSuperRegister. Put it down here since it needs the +// iterator defined above in addition to the MCRegisterInfo class itself. +inline bool MCRegisterInfo::isSuperRegister(unsigned RegA, unsigned RegB) const{ + for (MCSuperRegIterator I(RegA, this); I.isValid(); ++I) + if (*I == RegB) + return true; + return false; +} + +//===----------------------------------------------------------------------===// +// Register Units +//===----------------------------------------------------------------------===// + +// Register units are used to compute register aliasing. Every register has at +// least one register unit, but it can have more. Two registers overlap if and +// only if they have a common register unit. +// +// A target with a complicated sub-register structure will typically have many +// fewer register units than actual registers. MCRI::getNumRegUnits() returns +// the number of register units in the target. + +// MCRegUnitIterator enumerates a list of register units for Reg. The list is +// in ascending numerical order. +class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator { +public: + /// MCRegUnitIterator - Create an iterator that traverses the register units + /// in Reg. + MCRegUnitIterator() = default; + + MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + assert(Reg && "Null register has no regunits"); + // Decode the RegUnits MCRegisterDesc field. + unsigned RU = MCRI->get(Reg).RegUnits; + unsigned Scale = RU & 15; + unsigned Offset = RU >> 4; + + // Initialize the iterator to Reg * Scale, and the List pointer to + // DiffLists + Offset. + init(Reg * Scale, MCRI->DiffLists + Offset); + + // That may not be a valid unit, we need to advance by one to get the real + // unit number. The first differential can be 0 which would normally + // terminate the list, but since we know every register has at least one + // unit, we can allow a 0 differential here. + advance(); + } +}; + +/// MCRegUnitMaskIterator enumerates a list of register units and their +/// associated lane masks for Reg. The register units are in ascending +/// numerical order. +class MCRegUnitMaskIterator { + MCRegUnitIterator RUIter; + const LaneBitmask *MaskListIter; + +public: + MCRegUnitMaskIterator() = default; + + /// Constructs an iterator that traverses the register units and their + /// associated LaneMasks in Reg. + MCRegUnitMaskIterator(unsigned Reg, const MCRegisterInfo *MCRI) + : RUIter(Reg, MCRI) { + uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks; + MaskListIter = &MCRI->RegUnitMaskSequences[Idx]; + } + + /// Returns a (RegUnit, LaneMask) pair. + std::pair<unsigned,LaneBitmask> operator*() const { + return std::make_pair(*RUIter, *MaskListIter); + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return RUIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++MaskListIter; + ++RUIter; + } +}; + +// Each register unit has one or two root registers. The complete set of +// registers containing a register unit is the union of the roots and their +// super-registers. All registers aliasing Unit can be visited like this: +// +// for (MCRegUnitRootIterator RI(Unit, MCRI); RI.isValid(); ++RI) { +// for (MCSuperRegIterator SI(*RI, MCRI, true); SI.isValid(); ++SI) +// visit(*SI); +// } + +/// MCRegUnitRootIterator enumerates the root registers of a register unit. +class MCRegUnitRootIterator { + uint16_t Reg0 = 0; + uint16_t Reg1 = 0; + +public: + MCRegUnitRootIterator() = default; + + MCRegUnitRootIterator(unsigned RegUnit, const MCRegisterInfo *MCRI) { + assert(RegUnit < MCRI->getNumRegUnits() && "Invalid register unit"); + Reg0 = MCRI->RegUnitRoots[RegUnit][0]; + Reg1 = MCRI->RegUnitRoots[RegUnit][1]; + } + + /// Dereference to get the current root register. + unsigned operator*() const { + return Reg0; + } + + /// Check if the iterator is at the end of the list. + bool isValid() const { + return Reg0; + } + + /// Preincrement to move to the next root register. + void operator++() { + assert(isValid() && "Cannot move off the end of the list."); + Reg0 = Reg1; + Reg1 = 0; + } +}; + +/// MCRegAliasIterator enumerates all registers aliasing Reg. If IncludeSelf is +/// set, Reg itself is included in the list. This iterator does not guarantee +/// any ordering or that entries are unique. +class MCRegAliasIterator { +private: + unsigned Reg; + const MCRegisterInfo *MCRI; + bool IncludeSelf; + + MCRegUnitIterator RI; + MCRegUnitRootIterator RRI; + MCSuperRegIterator SI; + +public: + MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf) + : Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) { + // Initialize the iterators. + for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) { + for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) { + for (SI = MCSuperRegIterator(*RRI, MCRI, true); SI.isValid(); ++SI) { + if (!(!IncludeSelf && Reg == *SI)) + return; + } + } + } + } + + bool isValid() const { return RI.isValid(); } + + unsigned operator*() const { + assert(SI.isValid() && "Cannot dereference an invalid iterator."); + return *SI; + } + + void advance() { + // Assuming SI is valid. + ++SI; + if (SI.isValid()) return; + + ++RRI; + if (RRI.isValid()) { + SI = MCSuperRegIterator(*RRI, MCRI, true); + return; + } + + ++RI; + if (RI.isValid()) { + RRI = MCRegUnitRootIterator(*RI, MCRI); + SI = MCSuperRegIterator(*RRI, MCRI, true); + } + } + + void operator++() { + assert(isValid() && "Cannot move off the end of the list."); + do advance(); + while (!IncludeSelf && isValid() && *SI == Reg); + } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCREGISTERINFO_H diff --git a/clang-r353983/include/llvm/MC/MCSchedule.h b/clang-r353983/include/llvm/MC/MCSchedule.h new file mode 100644 index 00000000..df3248ee --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSchedule.h @@ -0,0 +1,385 @@ +//===-- llvm/MC/MCSchedule.h - Scheduling -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the classes used to describe a subtarget's machine model +// for scheduling and other instruction cost heuristics. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSCHEDULE_H +#define LLVM_MC_MCSCHEDULE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/DataTypes.h" +#include <cassert> + +namespace llvm { + +struct InstrItinerary; +class MCSubtargetInfo; +class MCInstrInfo; +class MCInst; +class InstrItineraryData; + +/// Define a kind of processor resource that will be modeled by the scheduler. +struct MCProcResourceDesc { + const char *Name; + unsigned NumUnits; // Number of resource of this kind + unsigned SuperIdx; // Index of the resources kind that contains this kind. + + // Number of resources that may be buffered. + // + // Buffered resources (BufferSize != 0) may be consumed at some indeterminate + // cycle after dispatch. This should be used for out-of-order cpus when + // instructions that use this resource can be buffered in a reservaton + // station. + // + // Unbuffered resources (BufferSize == 0) always consume their resource some + // fixed number of cycles after dispatch. If a resource is unbuffered, then + // the scheduler will avoid scheduling instructions with conflicting resources + // in the same cycle. This is for in-order cpus, or the in-order portion of + // an out-of-order cpus. + int BufferSize; + + // If the resource has sub-units, a pointer to the first element of an array + // of `NumUnits` elements containing the ProcResourceIdx of the sub units. + // nullptr if the resource does not have sub-units. + const unsigned *SubUnitsIdxBegin; + + bool operator==(const MCProcResourceDesc &Other) const { + return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx + && BufferSize == Other.BufferSize; + } +}; + +/// Identify one of the processor resource kinds consumed by a particular +/// scheduling class for the specified number of cycles. +struct MCWriteProcResEntry { + uint16_t ProcResourceIdx; + uint16_t Cycles; + + bool operator==(const MCWriteProcResEntry &Other) const { + return ProcResourceIdx == Other.ProcResourceIdx && Cycles == Other.Cycles; + } +}; + +/// Specify the latency in cpu cycles for a particular scheduling class and def +/// index. -1 indicates an invalid latency. Heuristics would typically consider +/// an instruction with invalid latency to have infinite latency. Also identify +/// the WriteResources of this def. When the operand expands to a sequence of +/// writes, this ID is the last write in the sequence. +struct MCWriteLatencyEntry { + int16_t Cycles; + uint16_t WriteResourceID; + + bool operator==(const MCWriteLatencyEntry &Other) const { + return Cycles == Other.Cycles && WriteResourceID == Other.WriteResourceID; + } +}; + +/// Specify the number of cycles allowed after instruction issue before a +/// particular use operand reads its registers. This effectively reduces the +/// write's latency. Here we allow negative cycles for corner cases where +/// latency increases. This rule only applies when the entry's WriteResource +/// matches the write's WriteResource. +/// +/// MCReadAdvanceEntries are sorted first by operand index (UseIdx), then by +/// WriteResourceIdx. +struct MCReadAdvanceEntry { + unsigned UseIdx; + unsigned WriteResourceID; + int Cycles; + + bool operator==(const MCReadAdvanceEntry &Other) const { + return UseIdx == Other.UseIdx && WriteResourceID == Other.WriteResourceID + && Cycles == Other.Cycles; + } +}; + +/// Summarize the scheduling resources required for an instruction of a +/// particular scheduling class. +/// +/// Defined as an aggregate struct for creating tables with initializer lists. +struct MCSchedClassDesc { + static const unsigned short InvalidNumMicroOps = (1U << 14) - 1; + static const unsigned short VariantNumMicroOps = InvalidNumMicroOps - 1; + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + const char* Name; +#endif + uint16_t NumMicroOps : 14; + bool BeginGroup : 1; + bool EndGroup : 1; + uint16_t WriteProcResIdx; // First index into WriteProcResTable. + uint16_t NumWriteProcResEntries; + uint16_t WriteLatencyIdx; // First index into WriteLatencyTable. + uint16_t NumWriteLatencyEntries; + uint16_t ReadAdvanceIdx; // First index into ReadAdvanceTable. + uint16_t NumReadAdvanceEntries; + + bool isValid() const { + return NumMicroOps != InvalidNumMicroOps; + } + bool isVariant() const { + return NumMicroOps == VariantNumMicroOps; + } +}; + +/// Specify the cost of a register definition in terms of number of physical +/// register allocated at register renaming stage. For example, AMD Jaguar. +/// natively supports 128-bit data types, and operations on 256-bit registers +/// (i.e. YMM registers) are internally split into two COPs (complex operations) +/// and each COP updates a physical register. Basically, on Jaguar, a YMM +/// register write effectively consumes two physical registers. That means, +/// the cost of a YMM write in the BtVer2 model is 2. +struct MCRegisterCostEntry { + unsigned RegisterClassID; + unsigned Cost; + bool AllowMoveElimination; +}; + +/// A register file descriptor. +/// +/// This struct allows to describe processor register files. In particular, it +/// helps describing the size of the register file, as well as the cost of +/// allocating a register file at register renaming stage. +/// FIXME: this struct can be extended to provide information about the number +/// of read/write ports to the register file. A value of zero for field +/// 'NumPhysRegs' means: this register file has an unbounded number of physical +/// registers. +struct MCRegisterFileDesc { + const char *Name; + uint16_t NumPhysRegs; + uint16_t NumRegisterCostEntries; + // Index of the first cost entry in MCExtraProcessorInfo::RegisterCostTable. + uint16_t RegisterCostEntryIdx; + // A value of zero means: there is no limit in the number of moves that can be + // eliminated every cycle. + uint16_t MaxMovesEliminatedPerCycle; + // Ture if this register file only knows how to optimize register moves from + // known zero registers. + bool AllowZeroMoveEliminationOnly; +}; + +/// Provide extra details about the machine processor. +/// +/// This is a collection of "optional" processor information that is not +/// normally used by the LLVM machine schedulers, but that can be consumed by +/// external tools like llvm-mca to improve the quality of the peformance +/// analysis. +struct MCExtraProcessorInfo { + // Actual size of the reorder buffer in hardware. + unsigned ReorderBufferSize; + // Number of instructions retired per cycle. + unsigned MaxRetirePerCycle; + const MCRegisterFileDesc *RegisterFiles; + unsigned NumRegisterFiles; + const MCRegisterCostEntry *RegisterCostTable; + unsigned NumRegisterCostEntries; + unsigned LoadQueueID; + unsigned StoreQueueID; +}; + +/// Machine model for scheduling, bundling, and heuristics. +/// +/// The machine model directly provides basic information about the +/// microarchitecture to the scheduler in the form of properties. It also +/// optionally refers to scheduler resource tables and itinerary +/// tables. Scheduler resource tables model the latency and cost for each +/// instruction type. Itinerary tables are an independent mechanism that +/// provides a detailed reservation table describing each cycle of instruction +/// execution. Subtargets may define any or all of the above categories of data +/// depending on the type of CPU and selected scheduler. +/// +/// The machine independent properties defined here are used by the scheduler as +/// an abstract machine model. A real micro-architecture has a number of +/// buffers, queues, and stages. Declaring that a given machine-independent +/// abstract property corresponds to a specific physical property across all +/// subtargets can't be done. Nonetheless, the abstract model is +/// useful. Futhermore, subtargets typically extend this model with processor +/// specific resources to model any hardware features that can be exploited by +/// sceduling heuristics and aren't sufficiently represented in the abstract. +/// +/// The abstract pipeline is built around the notion of an "issue point". This +/// is merely a reference point for counting machine cycles. The physical +/// machine will have pipeline stages that delay execution. The scheduler does +/// not model those delays because they are irrelevant as long as they are +/// consistent. Inaccuracies arise when instructions have different execution +/// delays relative to each other, in addition to their intrinsic latency. Those +/// special cases can be handled by TableGen constructs such as, ReadAdvance, +/// which reduces latency when reading data, and ResourceCycles, which consumes +/// a processor resource when writing data for a number of abstract +/// cycles. +/// +/// TODO: One tool currently missing is the ability to add a delay to +/// ResourceCycles. That would be easy to add and would likely cover all cases +/// currently handled by the legacy itinerary tables. +/// +/// A note on out-of-order execution and, more generally, instruction +/// buffers. Part of the CPU pipeline is always in-order. The issue point, which +/// is the point of reference for counting cycles, only makes sense as an +/// in-order part of the pipeline. Other parts of the pipeline are sometimes +/// falling behind and sometimes catching up. It's only interesting to model +/// those other, decoupled parts of the pipeline if they may be predictably +/// resource constrained in a way that the scheduler can exploit. +/// +/// The LLVM machine model distinguishes between in-order constraints and +/// out-of-order constraints so that the target's scheduling strategy can apply +/// appropriate heuristics. For a well-balanced CPU pipeline, out-of-order +/// resources would not typically be treated as a hard scheduling +/// constraint. For example, in the GenericScheduler, a delay caused by limited +/// out-of-order resources is not directly reflected in the number of cycles +/// that the scheduler sees between issuing an instruction and its dependent +/// instructions. In other words, out-of-order resources don't directly increase +/// the latency between pairs of instructions. However, they can still be used +/// to detect potential bottlenecks across a sequence of instructions and bias +/// the scheduling heuristics appropriately. +struct MCSchedModel { + // IssueWidth is the maximum number of instructions that may be scheduled in + // the same per-cycle group. This is meant to be a hard in-order constraint + // (a.k.a. "hazard"). In the GenericScheduler strategy, no more than + // IssueWidth micro-ops can ever be scheduled in a particular cycle. + // + // In practice, IssueWidth is useful to model any bottleneck between the + // decoder (after micro-op expansion) and the out-of-order reservation + // stations or the decoder bandwidth itself. If the total number of + // reservation stations is also a bottleneck, or if any other pipeline stage + // has a bandwidth limitation, then that can be naturally modeled by adding an + // out-of-order processor resource. + unsigned IssueWidth; + static const unsigned DefaultIssueWidth = 1; + + // MicroOpBufferSize is the number of micro-ops that the processor may buffer + // for out-of-order execution. + // + // "0" means operations that are not ready in this cycle are not considered + // for scheduling (they go in the pending queue). Latency is paramount. This + // may be more efficient if many instructions are pending in a schedule. + // + // "1" means all instructions are considered for scheduling regardless of + // whether they are ready in this cycle. Latency still causes issue stalls, + // but we balance those stalls against other heuristics. + // + // "> 1" means the processor is out-of-order. This is a machine independent + // estimate of highly machine specific characteristics such as the register + // renaming pool and reorder buffer. + unsigned MicroOpBufferSize; + static const unsigned DefaultMicroOpBufferSize = 0; + + // LoopMicroOpBufferSize is the number of micro-ops that the processor may + // buffer for optimized loop execution. More generally, this represents the + // optimal number of micro-ops in a loop body. A loop may be partially + // unrolled to bring the count of micro-ops in the loop body closer to this + // number. + unsigned LoopMicroOpBufferSize; + static const unsigned DefaultLoopMicroOpBufferSize = 0; + + // LoadLatency is the expected latency of load instructions. + unsigned LoadLatency; + static const unsigned DefaultLoadLatency = 4; + + // HighLatency is the expected latency of "very high latency" operations. + // See TargetInstrInfo::isHighLatencyDef(). + // By default, this is set to an arbitrarily high number of cycles + // likely to have some impact on scheduling heuristics. + unsigned HighLatency; + static const unsigned DefaultHighLatency = 10; + + // MispredictPenalty is the typical number of extra cycles the processor + // takes to recover from a branch misprediction. + unsigned MispredictPenalty; + static const unsigned DefaultMispredictPenalty = 10; + + bool PostRAScheduler; // default value is false + + bool CompleteModel; + + unsigned ProcID; + const MCProcResourceDesc *ProcResourceTable; + const MCSchedClassDesc *SchedClassTable; + unsigned NumProcResourceKinds; + unsigned NumSchedClasses; + // Instruction itinerary tables used by InstrItineraryData. + friend class InstrItineraryData; + const InstrItinerary *InstrItineraries; + + const MCExtraProcessorInfo *ExtraProcessorInfo; + + bool hasExtraProcessorInfo() const { return ExtraProcessorInfo; } + + unsigned getProcessorID() const { return ProcID; } + + /// Does this machine model include instruction-level scheduling. + bool hasInstrSchedModel() const { return SchedClassTable; } + + const MCExtraProcessorInfo &getExtraProcessorInfo() const { + assert(hasExtraProcessorInfo() && + "No extra information available for this model"); + return *ExtraProcessorInfo; + } + + /// Return true if this machine model data for all instructions with a + /// scheduling class (itinerary class or SchedRW list). + bool isComplete() const { return CompleteModel; } + + /// Return true if machine supports out of order execution. + bool isOutOfOrder() const { return MicroOpBufferSize > 1; } + + unsigned getNumProcResourceKinds() const { + return NumProcResourceKinds; + } + + const MCProcResourceDesc *getProcResource(unsigned ProcResourceIdx) const { + assert(hasInstrSchedModel() && "No scheduling machine model"); + + assert(ProcResourceIdx < NumProcResourceKinds && "bad proc resource idx"); + return &ProcResourceTable[ProcResourceIdx]; + } + + const MCSchedClassDesc *getSchedClassDesc(unsigned SchedClassIdx) const { + assert(hasInstrSchedModel() && "No scheduling machine model"); + + assert(SchedClassIdx < NumSchedClasses && "bad scheduling class idx"); + return &SchedClassTable[SchedClassIdx]; + } + + /// Returns the latency value for the scheduling class. + static int computeInstrLatency(const MCSubtargetInfo &STI, + const MCSchedClassDesc &SCDesc); + + int computeInstrLatency(const MCSubtargetInfo &STI, unsigned SClass) const; + int computeInstrLatency(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, + const MCInst &Inst) const; + + // Returns the reciprocal throughput information from a MCSchedClassDesc. + static double + getReciprocalThroughput(const MCSubtargetInfo &STI, + const MCSchedClassDesc &SCDesc); + + static double + getReciprocalThroughput(unsigned SchedClass, const InstrItineraryData &IID); + + double + getReciprocalThroughput(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, + const MCInst &Inst) const; + + /// Returns the maximum forwarding delay for register reads dependent on + /// writes of scheduling class WriteResourceIdx. + static unsigned getForwardingDelayCycles(ArrayRef<MCReadAdvanceEntry> Entries, + unsigned WriteResourceIdx = 0); + + /// Returns the default initialized model. + static const MCSchedModel &GetDefaultSchedModel() { return Default; } + static const MCSchedModel Default; +}; + +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCSection.h b/clang-r353983/include/llvm/MC/MCSection.h new file mode 100644 index 00000000..27490dc8 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSection.h @@ -0,0 +1,193 @@ +//===- MCSection.h - Machine Code Sections ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSection class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTION_H +#define LLVM_MC_MCSECTION_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/ilist.h" +#include "llvm/MC/MCFragment.h" +#include "llvm/MC/SectionKind.h" +#include <cassert> +#include <utility> + +namespace llvm { + +class MCAsmInfo; +class MCContext; +class MCExpr; +class MCSymbol; +class raw_ostream; +class Triple; + +template <> struct ilist_alloc_traits<MCFragment> { + static void deleteNode(MCFragment *V); +}; + +/// Instances of this class represent a uniqued identifier for a section in the +/// current translation unit. The MCContext class uniques and creates these. +class MCSection { +public: + enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm }; + + /// Express the state of bundle locked groups while emitting code. + enum BundleLockStateType { + NotBundleLocked, + BundleLocked, + BundleLockedAlignToEnd + }; + + using FragmentListType = iplist<MCFragment>; + + using const_iterator = FragmentListType::const_iterator; + using iterator = FragmentListType::iterator; + + using const_reverse_iterator = FragmentListType::const_reverse_iterator; + using reverse_iterator = FragmentListType::reverse_iterator; + +private: + MCSymbol *Begin; + MCSymbol *End = nullptr; + /// The alignment requirement of this section. + unsigned Alignment = 1; + /// The section index in the assemblers section list. + unsigned Ordinal = 0; + /// The index of this section in the layout order. + unsigned LayoutOrder; + + /// Keeping track of bundle-locked state. + BundleLockStateType BundleLockState = NotBundleLocked; + + /// Current nesting depth of bundle_lock directives. + unsigned BundleLockNestingDepth = 0; + + /// We've seen a bundle_lock directive but not its first instruction + /// yet. + bool BundleGroupBeforeFirstInst : 1; + + /// Whether this section has had instructions emitted into it. + bool HasInstructions : 1; + + /// Whether this section has had data emitted into it. + /// Right now this is only used by the ARM backend. + bool HasData : 1; + + bool IsRegistered : 1; + + MCDummyFragment DummyFragment; + + FragmentListType Fragments; + + /// Mapping from subsection number to insertion point for subsection numbers + /// below that number. + SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap; + +protected: + SectionVariant Variant; + SectionKind Kind; + + MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin); + ~MCSection(); + +public: + MCSection(const MCSection &) = delete; + MCSection &operator=(const MCSection &) = delete; + + SectionKind getKind() const { return Kind; } + + SectionVariant getVariant() const { return Variant; } + + MCSymbol *getBeginSymbol() { return Begin; } + const MCSymbol *getBeginSymbol() const { + return const_cast<MCSection *>(this)->getBeginSymbol(); + } + void setBeginSymbol(MCSymbol *Sym) { + assert(!Begin); + Begin = Sym; + } + MCSymbol *getEndSymbol(MCContext &Ctx); + bool hasEnded() const; + + unsigned getAlignment() const { return Alignment; } + void setAlignment(unsigned Value) { Alignment = Value; } + + unsigned getOrdinal() const { return Ordinal; } + void setOrdinal(unsigned Value) { Ordinal = Value; } + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + + BundleLockStateType getBundleLockState() const { return BundleLockState; } + void setBundleLockState(BundleLockStateType NewState); + bool isBundleLocked() const { return BundleLockState != NotBundleLocked; } + + bool isBundleGroupBeforeFirstInst() const { + return BundleGroupBeforeFirstInst; + } + void setBundleGroupBeforeFirstInst(bool IsFirst) { + BundleGroupBeforeFirstInst = IsFirst; + } + + bool hasInstructions() const { return HasInstructions; } + void setHasInstructions(bool Value) { HasInstructions = Value; } + + bool hasData() const { return HasData; } + void setHasData(bool Value) { HasData = Value; } + + bool isRegistered() const { return IsRegistered; } + void setIsRegistered(bool Value) { IsRegistered = Value; } + + MCSection::FragmentListType &getFragmentList() { return Fragments; } + const MCSection::FragmentListType &getFragmentList() const { + return const_cast<MCSection *>(this)->getFragmentList(); + } + + /// Support for MCFragment::getNextNode(). + static FragmentListType MCSection::*getSublistAccess(MCFragment *) { + return &MCSection::Fragments; + } + + const MCDummyFragment &getDummyFragment() const { return DummyFragment; } + MCDummyFragment &getDummyFragment() { return DummyFragment; } + + iterator begin() { return Fragments.begin(); } + const_iterator begin() const { return Fragments.begin(); } + + iterator end() { return Fragments.end(); } + const_iterator end() const { return Fragments.end(); } + + reverse_iterator rbegin() { return Fragments.rbegin(); } + const_reverse_iterator rbegin() const { return Fragments.rbegin(); } + + reverse_iterator rend() { return Fragments.rend(); } + const_reverse_iterator rend() const { return Fragments.rend(); } + + MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection); + + void dump() const; + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, + raw_ostream &OS, + const MCExpr *Subsection) const = 0; + + /// Return true if a .align directive should use "optimized nops" to fill + /// instead of 0s. + virtual bool UseCodeAlign() const = 0; + + /// Check whether this section is "virtual", that is has no actual object + /// file contents. + virtual bool isVirtualSection() const = 0; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCSECTION_H diff --git a/clang-r353983/include/llvm/MC/MCSectionCOFF.h b/clang-r353983/include/llvm/MC/MCSectionCOFF.h new file mode 100644 index 00000000..8be95e0f --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSectionCOFF.h @@ -0,0 +1,97 @@ +//===- MCSectionCOFF.h - COFF Machine Code Sections -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSectionCOFF class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONCOFF_H +#define LLVM_MC_MCSECTIONCOFF_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/SectionKind.h" +#include <cassert> + +namespace llvm { + +class MCSymbol; + +/// This represents a section on Windows +class MCSectionCOFF final : public MCSection { + // The memory for this string is stored in the same MCContext as *this. + StringRef SectionName; + + // FIXME: The following fields should not be mutable, but are for now so the + // asm parser can honor the .linkonce directive. + + /// This is the Characteristics field of a section, drawn from the enums + /// below. + mutable unsigned Characteristics; + + /// The unique IDs used with the .pdata and .xdata sections created internally + /// by the assembler. This ID is used to ensure that for every .text section, + /// there is exactly one .pdata and one .xdata section, which is required by + /// the Microsoft incremental linker. This data is mutable because this ID is + /// not notionally part of the section. + mutable unsigned WinCFISectionID = ~0U; + + /// The COMDAT symbol of this section. Only valid if this is a COMDAT section. + /// Two COMDAT sections are merged if they have the same COMDAT symbol. + MCSymbol *COMDATSymbol; + + /// This is the Selection field for the section symbol, if it is a COMDAT + /// section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 + mutable int Selection; + +private: + friend class MCContext; + MCSectionCOFF(StringRef Section, unsigned Characteristics, + MCSymbol *COMDATSymbol, int Selection, SectionKind K, + MCSymbol *Begin) + : MCSection(SV_COFF, K, Begin), SectionName(Section), + Characteristics(Characteristics), COMDATSymbol(COMDATSymbol), + Selection(Selection) { + assert((Characteristics & 0x00F00000) == 0 && + "alignment must not be set upon section creation"); + } + +public: + /// Decides whether a '.section' directive should be printed before the + /// section name + bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; + + StringRef getSectionName() const { return SectionName; } + unsigned getCharacteristics() const { return Characteristics; } + MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; } + int getSelection() const { return Selection; } + + void setSelection(int Selection) const; + + void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, + raw_ostream &OS, + const MCExpr *Subsection) const override; + bool UseCodeAlign() const override; + bool isVirtualSection() const override; + + unsigned getOrAssignWinCFISectionID(unsigned *NextID) const { + if (WinCFISectionID == ~0U) + WinCFISectionID = (*NextID)++; + return WinCFISectionID; + } + + static bool isImplicitlyDiscardable(StringRef Name) { + return Name.startswith(".debug"); + } + + static bool classof(const MCSection *S) { return S->getVariant() == SV_COFF; } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCSECTIONCOFF_H diff --git a/clang-r353983/include/llvm/MC/MCSectionELF.h b/clang-r353983/include/llvm/MC/MCSectionELF.h new file mode 100644 index 00000000..fe6b2d7a --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSectionELF.h @@ -0,0 +1,96 @@ +//===- MCSectionELF.h - ELF Machine Code Sections ---------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSectionELF class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONELF_H +#define LLVM_MC_MCSECTIONELF_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/SectionKind.h" + +namespace llvm { + +class MCSymbol; + +/// This represents a section on linux, lots of unix variants and some bare +/// metal systems. +class MCSectionELF final : public MCSection { + /// This is the name of the section. The referenced memory is owned by + /// TargetLoweringObjectFileELF's ELFUniqueMap. + StringRef SectionName; + + /// This is the sh_type field of a section, drawn from the enums below. + unsigned Type; + + /// This is the sh_flags field of a section, drawn from the enums below. + unsigned Flags; + + unsigned UniqueID; + + /// The size of each entry in this section. This size only makes sense for + /// sections that contain fixed-sized entries. If a section does not contain + /// fixed-sized entries 'EntrySize' will be 0. + unsigned EntrySize; + + const MCSymbolELF *Group; + + /// sh_info for SHF_LINK_ORDER (can be null). + const MCSymbol *AssociatedSymbol; + +private: + friend class MCContext; + + MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K, + unsigned entrySize, const MCSymbolELF *group, unsigned UniqueID, + MCSymbol *Begin, const MCSymbolELF *AssociatedSymbol) + : MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type), + Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group), + AssociatedSymbol(AssociatedSymbol) { + if (Group) + Group->setIsSignature(); + } + + void setSectionName(StringRef Name) { SectionName = Name; } + +public: + /// Decides whether a '.section' directive should be printed before the + /// section name + bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; + + StringRef getSectionName() const { return SectionName; } + unsigned getType() const { return Type; } + unsigned getFlags() const { return Flags; } + unsigned getEntrySize() const { return EntrySize; } + void setFlags(unsigned F) { Flags = F; } + const MCSymbolELF *getGroup() const { return Group; } + + void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, + raw_ostream &OS, + const MCExpr *Subsection) const override; + bool UseCodeAlign() const override; + bool isVirtualSection() const override; + + bool isUnique() const { return UniqueID != ~0U; } + unsigned getUniqueID() const { return UniqueID; } + + const MCSection *getAssociatedSection() const { return &AssociatedSymbol->getSection(); } + const MCSymbol *getAssociatedSymbol() const { return AssociatedSymbol; } + + static bool classof(const MCSection *S) { + return S->getVariant() == SV_ELF; + } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCSECTIONELF_H diff --git a/clang-r353983/include/llvm/MC/MCSectionMachO.h b/clang-r353983/include/llvm/MC/MCSectionMachO.h new file mode 100644 index 00000000..2c73661f --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSectionMachO.h @@ -0,0 +1,91 @@ +//===- MCSectionMachO.h - MachO Machine Code Sections -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSectionMachO class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONMACHO_H +#define LLVM_MC_MCSECTIONMACHO_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/MC/MCSection.h" + +namespace llvm { + +/// This represents a section on a Mach-O system (used by Mac OS X). On a Mac +/// system, these are also described in /usr/include/mach-o/loader.h. +class MCSectionMachO final : public MCSection { + char SegmentName[16]; // Not necessarily null terminated! + char SectionName[16]; // Not necessarily null terminated! + + /// This is the SECTION_TYPE and SECTION_ATTRIBUTES field of a section, drawn + /// from the enums below. + unsigned TypeAndAttributes; + + /// The 'reserved2' field of a section, used to represent the size of stubs, + /// for example. + unsigned Reserved2; + + MCSectionMachO(StringRef Segment, StringRef Section, unsigned TAA, + unsigned reserved2, SectionKind K, MCSymbol *Begin); + friend class MCContext; +public: + + StringRef getSegmentName() const { + // SegmentName is not necessarily null terminated! + if (SegmentName[15]) + return StringRef(SegmentName, 16); + return StringRef(SegmentName); + } + StringRef getSectionName() const { + // SectionName is not necessarily null terminated! + if (SectionName[15]) + return StringRef(SectionName, 16); + return StringRef(SectionName); + } + + unsigned getTypeAndAttributes() const { return TypeAndAttributes; } + unsigned getStubSize() const { return Reserved2; } + + MachO::SectionType getType() const { + return static_cast<MachO::SectionType>(TypeAndAttributes & + MachO::SECTION_TYPE); + } + bool hasAttribute(unsigned Value) const { + return (TypeAndAttributes & Value) != 0; + } + + /// Parse the section specifier indicated by "Spec". This is a string that can + /// appear after a .section directive in a mach-o flavored .s file. If + /// successful, this fills in the specified Out parameters and returns an + /// empty string. When an invalid section specifier is present, this returns + /// a string indicating the problem. If no TAA was parsed, TAA is not altered, + /// and TAAWasSet becomes false. + static std::string ParseSectionSpecifier(StringRef Spec, // In. + StringRef &Segment, // Out. + StringRef &Section, // Out. + unsigned &TAA, // Out. + bool &TAAParsed, // Out. + unsigned &StubSize); // Out. + + void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, + raw_ostream &OS, + const MCExpr *Subsection) const override; + bool UseCodeAlign() const override; + bool isVirtualSection() const override; + + static bool classof(const MCSection *S) { + return S->getVariant() == SV_MachO; + } +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCSectionWasm.h b/clang-r353983/include/llvm/MC/MCSectionWasm.h new file mode 100644 index 00000000..0e576b7b --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSectionWasm.h @@ -0,0 +1,83 @@ +//===- MCSectionWasm.h - Wasm Machine Code Sections -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSectionWasm class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONWASM_H +#define LLVM_MC_MCSECTIONWASM_H + +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbolWasm.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class MCSymbol; + +/// This represents a section on wasm. +class MCSectionWasm final : public MCSection { + /// This is the name of the section. The referenced memory is owned by + /// TargetLoweringObjectFileWasm's WasmUniqueMap. + StringRef SectionName; + + unsigned UniqueID; + + const MCSymbolWasm *Group; + + // The offset of the MC function/data section in the wasm code/data section. + // For data relocations the offset is relative to start of the data payload + // itself and does not include the size of the section header. + uint64_t SectionOffset = 0; + + // For data sections, this is the index of of the corresponding wasm data + // segment + uint32_t SegmentIndex = 0; + + friend class MCContext; + MCSectionWasm(StringRef Section, SectionKind K, const MCSymbolWasm *group, + unsigned UniqueID, MCSymbol *Begin) + : MCSection(SV_Wasm, K, Begin), SectionName(Section), UniqueID(UniqueID), + Group(group) {} + +public: + /// Decides whether a '.section' directive should be printed before the + /// section name + bool shouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; + + StringRef getSectionName() const { return SectionName; } + const MCSymbolWasm *getGroup() const { return Group; } + + void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, + raw_ostream &OS, + const MCExpr *Subsection) const override; + bool UseCodeAlign() const override; + bool isVirtualSection() const override; + + bool isWasmData() const { + return Kind.isGlobalWriteableData() || Kind.isReadOnly(); + } + + bool isUnique() const { return UniqueID != ~0U; } + unsigned getUniqueID() const { return UniqueID; } + + uint64_t getSectionOffset() const { return SectionOffset; } + void setSectionOffset(uint64_t Offset) { SectionOffset = Offset; } + + uint32_t getSegmentIndex() const { return SegmentIndex; } + void setSegmentIndex(uint32_t Index) { SegmentIndex = Index; } + + static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; } +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCStreamer.h b/clang-r353983/include/llvm/MC/MCStreamer.h new file mode 100644 index 00000000..dc2386fc --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCStreamer.h @@ -0,0 +1,1012 @@ +//===- MCStreamer.h - High-level Streaming Machine Code Output --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCStreamer class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSTREAMER_H +#define LLVM_MC_MCSTREAMER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCLinkerOptimizationHint.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCWinEH.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MD5.h" +#include "llvm/Support/SMLoc.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/VersionTuple.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + +class AssemblerConstantPools; +class formatted_raw_ostream; +class MCAsmBackend; +class MCCodeEmitter; +struct MCCodePaddingContext; +class MCContext; +class MCExpr; +class MCInst; +class MCInstPrinter; +class MCSection; +class MCStreamer; +class MCSymbolRefExpr; +class MCSubtargetInfo; +class raw_ostream; +class Twine; + +using MCSectionSubPair = std::pair<MCSection *, const MCExpr *>; + +/// Target specific streamer interface. This is used so that targets can +/// implement support for target specific assembly directives. +/// +/// If target foo wants to use this, it should implement 3 classes: +/// * FooTargetStreamer : public MCTargetStreamer +/// * FooTargetAsmStreamer : public FooTargetStreamer +/// * FooTargetELFStreamer : public FooTargetStreamer +/// +/// FooTargetStreamer should have a pure virtual method for each directive. For +/// example, for a ".bar symbol_name" directive, it should have +/// virtual emitBar(const MCSymbol &Symbol) = 0; +/// +/// The FooTargetAsmStreamer and FooTargetELFStreamer classes implement the +/// method. The assembly streamer just prints ".bar symbol_name". The object +/// streamer does whatever is needed to implement .bar in the object file. +/// +/// In the assembly printer and parser the target streamer can be used by +/// calling getTargetStreamer and casting it to FooTargetStreamer: +/// +/// MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); +/// FooTargetStreamer &ATS = static_cast<FooTargetStreamer &>(TS); +/// +/// The base classes FooTargetAsmStreamer and FooTargetELFStreamer should +/// *never* be treated differently. Callers should always talk to a +/// FooTargetStreamer. +class MCTargetStreamer { +protected: + MCStreamer &Streamer; + +public: + MCTargetStreamer(MCStreamer &S); + virtual ~MCTargetStreamer(); + + MCStreamer &getStreamer() { return Streamer; } + + // Allow a target to add behavior to the EmitLabel of MCStreamer. + virtual void emitLabel(MCSymbol *Symbol); + // Allow a target to add behavior to the emitAssignment of MCStreamer. + virtual void emitAssignment(MCSymbol *Symbol, const MCExpr *Value); + + virtual void prettyPrintAsm(MCInstPrinter &InstPrinter, raw_ostream &OS, + const MCInst &Inst, const MCSubtargetInfo &STI); + + virtual void emitDwarfFileDirective(StringRef Directive); + + /// Update streamer for a new active section. + /// + /// This is called by PopSection and SwitchSection, if the current + /// section changes. + virtual void changeSection(const MCSection *CurSection, MCSection *Section, + const MCExpr *SubSection, raw_ostream &OS); + + virtual void emitValue(const MCExpr *Value); + + /// Emit the bytes in \p Data into the output. + /// + /// This is used to emit bytes in \p Data as sequence of .byte directives. + virtual void emitRawBytes(StringRef Data); + + virtual void finish(); +}; + +// FIXME: declared here because it is used from +// lib/CodeGen/AsmPrinter/ARMException.cpp. +class ARMTargetStreamer : public MCTargetStreamer { +public: + ARMTargetStreamer(MCStreamer &S); + ~ARMTargetStreamer() override; + + virtual void emitFnStart(); + virtual void emitFnEnd(); + virtual void emitCantUnwind(); + virtual void emitPersonality(const MCSymbol *Personality); + virtual void emitPersonalityIndex(unsigned Index); + virtual void emitHandlerData(); + virtual void emitSetFP(unsigned FpReg, unsigned SpReg, + int64_t Offset = 0); + virtual void emitMovSP(unsigned Reg, int64_t Offset = 0); + virtual void emitPad(int64_t Offset); + virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList, + bool isVector); + virtual void emitUnwindRaw(int64_t StackOffset, + const SmallVectorImpl<uint8_t> &Opcodes); + + virtual void switchVendor(StringRef Vendor); + virtual void emitAttribute(unsigned Attribute, unsigned Value); + virtual void emitTextAttribute(unsigned Attribute, StringRef String); + virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, + StringRef StringValue = ""); + virtual void emitFPU(unsigned FPU); + virtual void emitArch(ARM::ArchKind Arch); + virtual void emitArchExtension(unsigned ArchExt); + virtual void emitObjectArch(ARM::ArchKind Arch); + void emitTargetAttributes(const MCSubtargetInfo &STI); + virtual void finishAttributeSection(); + virtual void emitInst(uint32_t Inst, char Suffix = '\0'); + + virtual void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE); + + virtual void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value); + + void finish() override; + + /// Reset any state between object emissions, i.e. the equivalent of + /// MCStreamer's reset method. + virtual void reset(); + + /// Callback used to implement the ldr= pseudo. + /// Add a new entry to the constant pool for the current section and return an + /// MCExpr that can be used to refer to the constant pool location. + const MCExpr *addConstantPoolEntry(const MCExpr *, SMLoc Loc); + + /// Callback used to implemnt the .ltorg directive. + /// Emit contents of constant pool for the current section. + void emitCurrentConstantPool(); + +private: + std::unique_ptr<AssemblerConstantPools> ConstantPools; +}; + +/// Streaming machine code generation interface. +/// +/// This interface is intended to provide a programatic interface that is very +/// similar to the level that an assembler .s file provides. It has callbacks +/// to emit bytes, handle directives, etc. The implementation of this interface +/// retains state to know what the current section is etc. +/// +/// There are multiple implementations of this interface: one for writing out +/// a .s file, and implementations that write out .o files of various formats. +/// +class MCStreamer { + MCContext &Context; + std::unique_ptr<MCTargetStreamer> TargetStreamer; + + std::vector<MCDwarfFrameInfo> DwarfFrameInfos; + MCDwarfFrameInfo *getCurrentDwarfFrameInfo(); + + /// Similar to DwarfFrameInfos, but for SEH unwind info. Chained frames may + /// refer to each other, so use std::unique_ptr to provide pointer stability. + std::vector<std::unique_ptr<WinEH::FrameInfo>> WinFrameInfos; + + WinEH::FrameInfo *CurrentWinFrameInfo; + + /// Tracks an index to represent the order a symbol was emitted in. + /// Zero means we did not emit that symbol. + DenseMap<const MCSymbol *, unsigned> SymbolOrdering; + + /// This is stack of current and previous section values saved by + /// PushSection. + SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; + + /// The next unique ID to use when creating a WinCFI-related section (.pdata + /// or .xdata). This ID ensures that we have a one-to-one mapping from + /// code section to unwind info section, which MSVC's incremental linker + /// requires. + unsigned NextWinCFIID = 0; + + bool UseAssemblerInfoForParsing; + +protected: + MCStreamer(MCContext &Ctx); + + virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); + virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); + + WinEH::FrameInfo *getCurrentWinFrameInfo() { + return CurrentWinFrameInfo; + } + + virtual void EmitWindowsUnwindTables(); + + virtual void EmitRawTextImpl(StringRef String); + + /// Returns true if the the .cv_loc directive is in the right section. + bool checkCVLocSection(unsigned FuncId, unsigned FileNo, SMLoc Loc); + +public: + MCStreamer(const MCStreamer &) = delete; + MCStreamer &operator=(const MCStreamer &) = delete; + virtual ~MCStreamer(); + + void visitUsedExpr(const MCExpr &Expr); + virtual void visitUsedSymbol(const MCSymbol &Sym); + + void setTargetStreamer(MCTargetStreamer *TS) { + TargetStreamer.reset(TS); + } + + /// State management + /// + virtual void reset(); + + MCContext &getContext() const { return Context; } + + virtual MCAssembler *getAssemblerPtr() { return nullptr; } + + void setUseAssemblerInfoForParsing(bool v) { UseAssemblerInfoForParsing = v; } + bool getUseAssemblerInfoForParsing() { return UseAssemblerInfoForParsing; } + + MCTargetStreamer *getTargetStreamer() { + return TargetStreamer.get(); + } + + /// When emitting an object file, create and emit a real label. When emitting + /// textual assembly, this should do nothing to avoid polluting our output. + virtual MCSymbol *EmitCFILabel(); + + /// Retreive the current frame info if one is available and it is not yet + /// closed. Otherwise, issue an error and return null. + WinEH::FrameInfo *EnsureValidWinFrameInfo(SMLoc Loc); + + unsigned getNumFrameInfos() { return DwarfFrameInfos.size(); } + ArrayRef<MCDwarfFrameInfo> getDwarfFrameInfos() const { + return DwarfFrameInfos; + } + + bool hasUnfinishedDwarfFrameInfo(); + + unsigned getNumWinFrameInfos() { return WinFrameInfos.size(); } + ArrayRef<std::unique_ptr<WinEH::FrameInfo>> getWinFrameInfos() const { + return WinFrameInfos; + } + + void generateCompactUnwindEncodings(MCAsmBackend *MAB); + + /// \name Assembly File Formatting. + /// @{ + + /// Return true if this streamer supports verbose assembly and if it is + /// enabled. + virtual bool isVerboseAsm() const { return false; } + + /// Return true if this asm streamer supports emitting unformatted text + /// to the .s file with EmitRawText. + virtual bool hasRawTextSupport() const { return false; } + + /// Is the integrated assembler required for this streamer to function + /// correctly? + virtual bool isIntegratedAssemblerRequired() const { return false; } + + /// Add a textual comment. + /// + /// Typically for comments that can be emitted to the generated .s + /// file if applicable as a QoI issue to make the output of the compiler + /// more readable. This only affects the MCAsmStreamer, and only when + /// verbose assembly output is enabled. + /// + /// If the comment includes embedded \n's, they will each get the comment + /// prefix as appropriate. The added comment should not end with a \n. + /// By default, each comment is terminated with an end of line, i.e. the + /// EOL param is set to true by default. If one prefers not to end the + /// comment with a new line then the EOL param should be passed + /// with a false value. + virtual void AddComment(const Twine &T, bool EOL = true) {} + + /// Return a raw_ostream that comments can be written to. Unlike + /// AddComment, you are required to terminate comments with \n if you use this + /// method. + virtual raw_ostream &GetCommentOS(); + + /// Print T and prefix it with the comment string (normally #) and + /// optionally a tab. This prints the comment immediately, not at the end of + /// the current line. It is basically a safe version of EmitRawText: since it + /// only prints comments, the object streamer ignores it instead of asserting. + virtual void emitRawComment(const Twine &T, bool TabPrefix = true); + + /// Add explicit comment T. T is required to be a valid + /// comment in the output and does not need to be escaped. + virtual void addExplicitComment(const Twine &T); + + /// Emit added explicit comments. + virtual void emitExplicitComments(); + + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. + virtual void AddBlankLine() {} + + /// @} + + /// \name Symbol & Section Management + /// @{ + + /// Return the current section that the streamer is emitting code to. + MCSectionSubPair getCurrentSection() const { + if (!SectionStack.empty()) + return SectionStack.back().first; + return MCSectionSubPair(); + } + MCSection *getCurrentSectionOnly() const { return getCurrentSection().first; } + + /// Return the previous section that the streamer is emitting code to. + MCSectionSubPair getPreviousSection() const { + if (!SectionStack.empty()) + return SectionStack.back().second; + return MCSectionSubPair(); + } + + /// Returns an index to represent the order a symbol was emitted in. + /// (zero if we did not emit that symbol) + unsigned GetSymbolOrder(const MCSymbol *Sym) const { + return SymbolOrdering.lookup(Sym); + } + + /// Update streamer for a new active section. + /// + /// This is called by PopSection and SwitchSection, if the current + /// section changes. + virtual void ChangeSection(MCSection *, const MCExpr *); + + /// Save the current and previous section on the section stack. + void PushSection() { + SectionStack.push_back( + std::make_pair(getCurrentSection(), getPreviousSection())); + } + + /// Restore the current and previous section from the section stack. + /// Calls ChangeSection as needed. + /// + /// Returns false if the stack was empty. + bool PopSection() { + if (SectionStack.size() <= 1) + return false; + auto I = SectionStack.end(); + --I; + MCSectionSubPair OldSection = I->first; + --I; + MCSectionSubPair NewSection = I->first; + + if (OldSection != NewSection) + ChangeSection(NewSection.first, NewSection.second); + SectionStack.pop_back(); + return true; + } + + bool SubSection(const MCExpr *Subsection) { + if (SectionStack.empty()) + return false; + + SwitchSection(SectionStack.back().first.first, Subsection); + return true; + } + + /// Set the current section where code is being emitted to \p Section. This + /// is required to update CurSection. + /// + /// This corresponds to assembler directives like .section, .text, etc. + virtual void SwitchSection(MCSection *Section, + const MCExpr *Subsection = nullptr); + + /// Set the current section where code is being emitted to \p Section. + /// This is required to update CurSection. This version does not call + /// ChangeSection. + void SwitchSectionNoChange(MCSection *Section, + const MCExpr *Subsection = nullptr) { + assert(Section && "Cannot switch to a null section!"); + MCSectionSubPair curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (MCSectionSubPair(Section, Subsection) != curSection) + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + } + + /// Create the default sections and set the initial one. + virtual void InitSections(bool NoExecStack); + + MCSymbol *endSection(MCSection *Section); + + /// Sets the symbol's section. + /// + /// Each emitted symbol will be tracked in the ordering table, + /// so we can sort on them later. + void AssignFragment(MCSymbol *Symbol, MCFragment *Fragment); + + /// Emit a label for \p Symbol into the current section. + /// + /// This corresponds to an assembler statement such as: + /// foo: + /// + /// \param Symbol - The symbol to emit. A given symbol should only be + /// emitted as a label once, and symbols emitted as a label should never be + /// used in an assignment. + // FIXME: These emission are non-const because we mutate the symbol to + // add the section we're emitting it to later. + virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()); + + virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); + + /// Note in the output the specified \p Flag. + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + + /// Emit the given list \p Options of strings as linker + /// options into the output. + virtual void EmitLinkerOptions(ArrayRef<std::string> Kind) {} + + /// Note in the output the specified region \p Kind. + virtual void EmitDataRegion(MCDataRegionType Kind) {} + + /// Specify the Mach-O minimum deployment target version. + virtual void EmitVersionMin(MCVersionMinType Type, unsigned Major, + unsigned Minor, unsigned Update, + VersionTuple SDKVersion) {} + + /// Emit/Specify Mach-O build version command. + /// \p Platform should be one of MachO::PlatformType. + virtual void EmitBuildVersion(unsigned Platform, unsigned Major, + unsigned Minor, unsigned Update, + VersionTuple SDKVersion) {} + + void EmitVersionForTarget(const Triple &Target, + const VersionTuple &SDKVersion); + + /// Note in the output that the specified \p Func is a Thumb mode + /// function (ARM target only). + virtual void EmitThumbFunc(MCSymbol *Func); + + /// Emit an assignment of \p Value to \p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// symbol = value + /// + /// The assignment generates no code, but has the side effect of binding the + /// value in the current context. For the assembly streamer, this prints the + /// binding into the .s file. + /// + /// \param Symbol - The symbol being assigned to. + /// \param Value - The value for the symbol. + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + + /// Emit an weak reference from \p Alias to \p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// .weakref alias, symbol + /// + /// \param Alias - The alias that is being created. + /// \param Symbol - The symbol being aliased. + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + + /// Add the given \p Attribute to \p Symbol. + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) = 0; + + /// Set the \p DescValue for the \p Symbol. + /// + /// \param Symbol - The symbol to have its n_desc field set. + /// \param DescValue - The value to set into the n_desc field. + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); + + /// Start emitting COFF symbol definition + /// + /// \param Symbol - The symbol to have its External & Type fields set. + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); + + /// Emit the storage class of the symbol. + /// + /// \param StorageClass - The storage class the symbol should have. + virtual void EmitCOFFSymbolStorageClass(int StorageClass); + + /// Emit the type of the symbol. + /// + /// \param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) + virtual void EmitCOFFSymbolType(int Type); + + /// Marks the end of the symbol definition. + virtual void EndCOFFSymbolDef(); + + virtual void EmitCOFFSafeSEH(MCSymbol const *Symbol); + + /// Emits the symbol table index of a Symbol into the current section. + virtual void EmitCOFFSymbolIndex(MCSymbol const *Symbol); + + /// Emits a COFF section index. + /// + /// \param Symbol - Symbol the section number relocation should point to. + virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol); + + /// Emits a COFF section relative relocation. + /// + /// \param Symbol - Symbol the section relative relocation should point to. + virtual void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset); + + /// Emits a COFF image relative relocation. + /// + /// \param Symbol - Symbol the image relative relocation should point to. + virtual void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset); + + /// Emit an ELF .size directive. + /// + /// This corresponds to an assembler statement such as: + /// .size symbol, expression + virtual void emitELFSize(MCSymbol *Symbol, const MCExpr *Value); + + /// Emit an ELF .symver directive. + /// + /// This corresponds to an assembler statement such as: + /// .symver _start, foo@@SOME_VERSION + /// \param AliasName - The versioned alias (i.e. "foo@@SOME_VERSION") + /// \param Aliasee - The aliased symbol (i.e. "_start") + virtual void emitELFSymverDirective(StringRef AliasName, + const MCSymbol *Aliasee); + + /// Emit a Linker Optimization Hint (LOH) directive. + /// \param Args - Arguments of the LOH. + virtual void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {} + + /// Emit a common symbol. + /// + /// \param Symbol - The common symbol to emit. + /// \param Size - The size of the common symbol. + /// \param ByteAlignment - The alignment of the symbol if + /// non-zero. This must be a power of 2. + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) = 0; + + /// Emit a local common (.lcomm) symbol. + /// + /// \param Symbol - The common symbol to emit. + /// \param Size - The size of the common symbol. + /// \param ByteAlignment - The alignment of the common symbol in bytes. + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + + /// Emit the zerofill section and an optional symbol. + /// + /// \param Section - The zerofill section to create and or to put the symbol + /// \param Symbol - The zerofill symbol to emit, if non-NULL. + /// \param Size - The size of the zerofill symbol. + /// \param ByteAlignment - The alignment of the zerofill symbol if + /// non-zero. This must be a power of 2 on some targets. + virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0, + SMLoc Loc = SMLoc()) = 0; + + /// Emit a thread local bss (.tbss) symbol. + /// + /// \param Section - The thread local common section. + /// \param Symbol - The thread local common symbol to emit. + /// \param Size - The size of the symbol. + /// \param ByteAlignment - The alignment of the thread local common symbol + /// if non-zero. This must be a power of 2 on some targets. + virtual void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0); + + /// @} + /// \name Generating Data + /// @{ + + /// Emit the bytes in \p Data into the output. + /// + /// This is used to implement assembler directives such as .byte, .ascii, + /// etc. + virtual void EmitBytes(StringRef Data); + + /// Functionally identical to EmitBytes. When emitting textual assembly, this + /// method uses .byte directives instead of .ascii or .asciz for readability. + virtual void EmitBinaryData(StringRef Data); + + /// Emit the expression \p Value into the output as a native + /// integer of the given \p Size bytes. + /// + /// This is used to implement assembler directives such as .word, .quad, + /// etc. + /// + /// \param Value - The value to emit. + /// \param Size - The size of the integer (in bytes) to emit. This must + /// match a native machine width. + /// \param Loc - The location of the expression for error reporting. + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + SMLoc Loc = SMLoc()); + + void EmitValue(const MCExpr *Value, unsigned Size, SMLoc Loc = SMLoc()); + + /// Special case of EmitValue that avoids the client having + /// to pass in a MCExpr for constant integers. + virtual void EmitIntValue(uint64_t Value, unsigned Size); + + virtual void EmitULEB128Value(const MCExpr *Value); + + virtual void EmitSLEB128Value(const MCExpr *Value); + + /// Special case of EmitULEB128Value that avoids the client having to + /// pass in a MCExpr for constant integers. + void EmitULEB128IntValue(uint64_t Value); + + /// Special case of EmitSLEB128Value that avoids the client having to + /// pass in a MCExpr for constant integers. + void EmitSLEB128IntValue(int64_t Value); + + /// Special case of EmitValue that avoids the client having to pass in + /// a MCExpr for MCSymbols. + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + bool IsSectionRelative = false); + + /// Emit the expression \p Value into the output as a dtprel + /// (64-bit DTP relative) value. + /// + /// This is used to implement assembler directives such as .dtpreldword on + /// targets that support them. + virtual void EmitDTPRel64Value(const MCExpr *Value); + + /// Emit the expression \p Value into the output as a dtprel + /// (32-bit DTP relative) value. + /// + /// This is used to implement assembler directives such as .dtprelword on + /// targets that support them. + virtual void EmitDTPRel32Value(const MCExpr *Value); + + /// Emit the expression \p Value into the output as a tprel + /// (64-bit TP relative) value. + /// + /// This is used to implement assembler directives such as .tpreldword on + /// targets that support them. + virtual void EmitTPRel64Value(const MCExpr *Value); + + /// Emit the expression \p Value into the output as a tprel + /// (32-bit TP relative) value. + /// + /// This is used to implement assembler directives such as .tprelword on + /// targets that support them. + virtual void EmitTPRel32Value(const MCExpr *Value); + + /// Emit the expression \p Value into the output as a gprel64 (64-bit + /// GP relative) value. + /// + /// This is used to implement assembler directives such as .gpdword on + /// targets that support them. + virtual void EmitGPRel64Value(const MCExpr *Value); + + /// Emit the expression \p Value into the output as a gprel32 (32-bit + /// GP relative) value. + /// + /// This is used to implement assembler directives such as .gprel32 on + /// targets that support them. + virtual void EmitGPRel32Value(const MCExpr *Value); + + /// Emit NumBytes bytes worth of the value specified by FillValue. + /// This implements directives such as '.space'. + void emitFill(uint64_t NumBytes, uint8_t FillValue); + + /// Emit \p Size bytes worth of the value specified by \p FillValue. + /// + /// This is used to implement assembler directives such as .space or .skip. + /// + /// \param NumBytes - The number of bytes to emit. + /// \param FillValue - The value to use when filling bytes. + /// \param Loc - The location of the expression for error reporting. + virtual void emitFill(const MCExpr &NumBytes, uint64_t FillValue, + SMLoc Loc = SMLoc()); + + /// Emit \p NumValues copies of \p Size bytes. Each \p Size bytes is + /// taken from the lowest order 4 bytes of \p Expr expression. + /// + /// This is used to implement assembler directives such as .fill. + /// + /// \param NumValues - The number of copies of \p Size bytes to emit. + /// \param Size - The size (in bytes) of each repeated value. + /// \param Expr - The expression from which \p Size bytes are used. + virtual void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, + SMLoc Loc = SMLoc()); + + /// Emit NumBytes worth of zeros. + /// This function properly handles data in virtual sections. + void EmitZeros(uint64_t NumBytes); + + /// Emit some number of copies of \p Value until the byte alignment \p + /// ByteAlignment is reached. + /// + /// If the number of bytes need to emit for the alignment is not a multiple + /// of \p ValueSize, then the contents of the emitted fill bytes is + /// undefined. + /// + /// This used to implement the .align assembler directive. + /// + /// \param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// \param Value - The value to use when filling bytes. + /// \param ValueSize - The size of the integer (in bytes) to emit for + /// \p Value. This must match a native machine width. + /// \param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0); + + /// Emit nops until the byte alignment \p ByteAlignment is reached. + /// + /// This used to align code where the alignment bytes may be executed. This + /// can emit different bytes for different sizes to optimize execution. + /// + /// \param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// \param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); + + /// Emit some number of copies of \p Value until the byte offset \p + /// Offset is reached. + /// + /// This is used to implement assembler directives such as .org. + /// + /// \param Offset - The offset to reach. This may be an expression, but the + /// expression must be associated with the current section. + /// \param Value - The value to use when filling bytes. + virtual void emitValueToOffset(const MCExpr *Offset, unsigned char Value, + SMLoc Loc); + + virtual void + EmitCodePaddingBasicBlockStart(const MCCodePaddingContext &Context) {} + + virtual void + EmitCodePaddingBasicBlockEnd(const MCCodePaddingContext &Context) {} + + /// @} + + /// Switch to a new logical file. This is used to implement the '.file + /// "foo.c"' assembler directive. + virtual void EmitFileDirective(StringRef Filename); + + /// Emit the "identifiers" directive. This implements the + /// '.ident "version foo"' assembler directive. + virtual void EmitIdent(StringRef IdentString) {} + + /// Associate a filename with a specified logical file number. This + /// implements the DWARF2 '.file 4 "foo.c"' assembler directive. + unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, + StringRef Filename, + MD5::MD5Result *Checksum = nullptr, + Optional<StringRef> Source = None, + unsigned CUID = 0) { + return cantFail( + tryEmitDwarfFileDirective(FileNo, Directory, Filename, Checksum, + Source, CUID)); + } + + /// Associate a filename with a specified logical file number. + /// Also associate a directory, optional checksum, and optional source + /// text with the logical file. This implements the DWARF2 + /// '.file 4 "dir/foo.c"' assembler directive, and the DWARF5 + /// '.file 4 "dir/foo.c" md5 "..." source "..."' assembler directive. + virtual Expected<unsigned> tryEmitDwarfFileDirective( + unsigned FileNo, StringRef Directory, StringRef Filename, + MD5::MD5Result *Checksum = nullptr, Optional<StringRef> Source = None, + unsigned CUID = 0); + + /// Specify the "root" file of the compilation, using the ".file 0" extension. + virtual void emitDwarfFile0Directive(StringRef Directory, StringRef Filename, + MD5::MD5Result *Checksum, + Optional<StringRef> Source, + unsigned CUID = 0); + + virtual void EmitCFIBKeyFrame(); + + /// This implements the DWARF2 '.loc fileno lineno ...' assembler + /// directive. + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName); + + /// Associate a filename with a specified logical file number, and also + /// specify that file's checksum information. This implements the '.cv_file 4 + /// "foo.c"' assembler directive. Returns true on success. + virtual bool EmitCVFileDirective(unsigned FileNo, StringRef Filename, + ArrayRef<uint8_t> Checksum, + unsigned ChecksumKind); + + /// Introduces a function id for use with .cv_loc. + virtual bool EmitCVFuncIdDirective(unsigned FunctionId); + + /// Introduces an inline call site id for use with .cv_loc. Includes + /// extra information for inline line table generation. + virtual bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, + unsigned IAFile, unsigned IALine, + unsigned IACol, SMLoc Loc); + + /// This implements the CodeView '.cv_loc' assembler directive. + virtual void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, + unsigned Line, unsigned Column, + bool PrologueEnd, bool IsStmt, + StringRef FileName, SMLoc Loc); + + /// This implements the CodeView '.cv_linetable' assembler directive. + virtual void EmitCVLinetableDirective(unsigned FunctionId, + const MCSymbol *FnStart, + const MCSymbol *FnEnd); + + /// This implements the CodeView '.cv_inline_linetable' assembler + /// directive. + virtual void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, + unsigned SourceFileId, + unsigned SourceLineNum, + const MCSymbol *FnStartSym, + const MCSymbol *FnEndSym); + + /// This implements the CodeView '.cv_def_range' assembler + /// directive. + virtual void EmitCVDefRangeDirective( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + StringRef FixedSizePortion); + + /// This implements the CodeView '.cv_stringtable' assembler directive. + virtual void EmitCVStringTableDirective() {} + + /// This implements the CodeView '.cv_filechecksums' assembler directive. + virtual void EmitCVFileChecksumsDirective() {} + + /// This implements the CodeView '.cv_filechecksumoffset' assembler + /// directive. + virtual void EmitCVFileChecksumOffsetDirective(unsigned FileNo) {} + + /// This implements the CodeView '.cv_fpo_data' assembler directive. + virtual void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc = {}) {} + + /// Emit the absolute difference between two symbols. + /// + /// \pre Offset of \c Hi is greater than the offset \c Lo. + virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size); + + /// Emit the absolute difference between two symbols encoded with ULEB128. + virtual void emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, + const MCSymbol *Lo); + + virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID); + virtual void EmitCFISections(bool EH, bool Debug); + void EmitCFIStartProc(bool IsSimple, SMLoc Loc = SMLoc()); + void EmitCFIEndProc(); + virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual void EmitCFIDefCfaOffset(int64_t Offset); + virtual void EmitCFIDefCfaRegister(int64_t Register); + virtual void EmitCFIOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFIRememberState(); + virtual void EmitCFIRestoreState(); + virtual void EmitCFISameValue(int64_t Register); + virtual void EmitCFIRestore(int64_t Register); + virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); + virtual void EmitCFIEscape(StringRef Values); + virtual void EmitCFIReturnColumn(int64_t Register); + virtual void EmitCFIGnuArgsSize(int64_t Size); + virtual void EmitCFISignalFrame(); + virtual void EmitCFIUndefined(int64_t Register); + virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); + virtual void EmitCFIWindowSave(); + virtual void EmitCFINegateRAState(); + + virtual void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc = SMLoc()); + virtual void EmitWinCFIEndProc(SMLoc Loc = SMLoc()); + /// This is used on platforms, such as Windows on ARM64, that require function + /// or funclet sizes to be emitted in .xdata before the End marker is emitted + /// for the frame. We cannot use the End marker, as it is not set at the + /// point of emitting .xdata, in order to indicate that the frame is active. + virtual void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc = SMLoc()); + virtual void EmitWinCFIStartChained(SMLoc Loc = SMLoc()); + virtual void EmitWinCFIEndChained(SMLoc Loc = SMLoc()); + virtual void EmitWinCFIPushReg(unsigned Register, SMLoc Loc = SMLoc()); + virtual void EmitWinCFISetFrame(unsigned Register, unsigned Offset, + SMLoc Loc = SMLoc()); + virtual void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc = SMLoc()); + virtual void EmitWinCFISaveReg(unsigned Register, unsigned Offset, + SMLoc Loc = SMLoc()); + virtual void EmitWinCFISaveXMM(unsigned Register, unsigned Offset, + SMLoc Loc = SMLoc()); + virtual void EmitWinCFIPushFrame(bool Code, SMLoc Loc = SMLoc()); + virtual void EmitWinCFIEndProlog(SMLoc Loc = SMLoc()); + virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except, + SMLoc Loc = SMLoc()); + virtual void EmitWinEHHandlerData(SMLoc Loc = SMLoc()); + + virtual void emitCGProfileEntry(const MCSymbolRefExpr *From, + const MCSymbolRefExpr *To, uint64_t Count); + + /// Get the .pdata section used for the given section. Typically the given + /// section is either the main .text section or some other COMDAT .text + /// section, but it may be any section containing code. + MCSection *getAssociatedPDataSection(const MCSection *TextSec); + + /// Get the .xdata section used for the given section. + MCSection *getAssociatedXDataSection(const MCSection *TextSec); + + virtual void EmitSyntaxDirective(); + + /// Emit a .reloc directive. + /// Returns true if the relocation could not be emitted because Name is not + /// known. + virtual bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, + const MCExpr *Expr, SMLoc Loc, + const MCSubtargetInfo &STI) { + return true; + } + + virtual void EmitAddrsig() {} + virtual void EmitAddrsigSym(const MCSymbol *Sym) {} + + /// Emit the given \p Instruction into the current section. + virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI); + + /// Set the bundle alignment mode from now on in the section. + /// The argument is the power of 2 to which the alignment is set. The + /// value 0 means turn the bundle alignment off. + virtual void EmitBundleAlignMode(unsigned AlignPow2); + + /// The following instructions are a bundle-locked group. + /// + /// \param AlignToEnd - If true, the bundle-locked group will be aligned to + /// the end of a bundle. + virtual void EmitBundleLock(bool AlignToEnd); + + /// Ends a bundle-locked group. + virtual void EmitBundleUnlock(); + + /// If this file is backed by a assembly streamer, this dumps the + /// specified string in the output .s file. This capability is indicated by + /// the hasRawTextSupport() predicate. By default this aborts. + void EmitRawText(const Twine &String); + + /// Streamer specific finalization. + virtual void FinishImpl(); + /// Finish emission of machine code. + void Finish(); + + virtual bool mayHaveInstructions(MCSection &Sec) const { return true; } +}; + +/// Create a dummy machine code streamer, which does nothing. This is useful for +/// timing the assembler front end. +MCStreamer *createNullStreamer(MCContext &Ctx); + +/// Create a machine code streamer which will print out assembly for the native +/// target, suitable for compiling with a native assembler. +/// +/// \param InstPrint - If given, the instruction printer to use. If not given +/// the MCInst representation will be printed. This method takes ownership of +/// InstPrint. +/// +/// \param CE - If given, a code emitter to use to show the instruction +/// encoding inline with the assembly. This method takes ownership of \p CE. +/// +/// \param TAB - If given, a target asm backend to use to show the fixup +/// information in conjunction with encoding information. This method takes +/// ownership of \p TAB. +/// +/// \param ShowInst - Whether to show the MCInst representation inline with +/// the assembly. +MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, + bool isVerboseAsm, bool useDwarfDirectory, + MCInstPrinter *InstPrint, MCCodeEmitter *CE, + MCAsmBackend *TAB, bool ShowInst); + +} // end namespace llvm + +#endif // LLVM_MC_MCSTREAMER_H diff --git a/clang-r353983/include/llvm/MC/MCSubtargetInfo.h b/clang-r353983/include/llvm/MC/MCSubtargetInfo.h new file mode 100644 index 00000000..c7472a28 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSubtargetInfo.h @@ -0,0 +1,187 @@ +//===- llvm/MC/MCSubtargetInfo.h - Subtarget Information --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file describes the subtarget options of a Target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSUBTARGETINFO_H +#define LLVM_MC_MCSUBTARGETINFO_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/MC/MCInstrItineraries.h" +#include "llvm/MC/MCSchedule.h" +#include "llvm/MC/SubtargetFeature.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <string> + +namespace llvm { + +class MCInst; + +//===----------------------------------------------------------------------===// +/// +/// Generic base class for all target subtargets. +/// +class MCSubtargetInfo { + Triple TargetTriple; + std::string CPU; // CPU being targeted. + ArrayRef<SubtargetFeatureKV> ProcFeatures; // Processor feature list + ArrayRef<SubtargetFeatureKV> ProcDesc; // Processor descriptions + + // Scheduler machine model + const SubtargetInfoKV *ProcSchedModels; + const MCWriteProcResEntry *WriteProcResTable; + const MCWriteLatencyEntry *WriteLatencyTable; + const MCReadAdvanceEntry *ReadAdvanceTable; + const MCSchedModel *CPUSchedModel; + + const InstrStage *Stages; // Instruction itinerary stages + const unsigned *OperandCycles; // Itinerary operand cycles + const unsigned *ForwardingPaths; + FeatureBitset FeatureBits; // Feature bits for current CPU + FS + +public: + MCSubtargetInfo(const MCSubtargetInfo &) = default; + MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, + ArrayRef<SubtargetFeatureKV> PF, + ArrayRef<SubtargetFeatureKV> PD, + const SubtargetInfoKV *ProcSched, + const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, + const MCReadAdvanceEntry *RA, const InstrStage *IS, + const unsigned *OC, const unsigned *FP); + MCSubtargetInfo() = delete; + MCSubtargetInfo &operator=(const MCSubtargetInfo &) = delete; + MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete; + virtual ~MCSubtargetInfo() = default; + + const Triple &getTargetTriple() const { return TargetTriple; } + StringRef getCPU() const { return CPU; } + + const FeatureBitset& getFeatureBits() const { return FeatureBits; } + void setFeatureBits(const FeatureBitset &FeatureBits_) { + FeatureBits = FeatureBits_; + } + + bool hasFeature(unsigned Feature) const { + return FeatureBits[Feature]; + } + +protected: + /// Initialize the scheduling model and feature bits. + /// + /// FIXME: Find a way to stick this in the constructor, since it should only + /// be called during initialization. + void InitMCProcessorInfo(StringRef CPU, StringRef FS); + +public: + /// Set the features to the default for the given CPU with an appended feature + /// string. + void setDefaultFeatures(StringRef CPU, StringRef FS); + + /// Toggle a feature and return the re-computed feature bits. + /// This version does not change the implied bits. + FeatureBitset ToggleFeature(uint64_t FB); + + /// Toggle a feature and return the re-computed feature bits. + /// This version does not change the implied bits. + FeatureBitset ToggleFeature(const FeatureBitset& FB); + + /// Toggle a set of features and return the re-computed feature bits. + /// This version will also change all implied bits. + FeatureBitset ToggleFeature(StringRef FS); + + /// Apply a feature flag and return the re-computed feature bits, including + /// all feature bits implied by the flag. + FeatureBitset ApplyFeatureFlag(StringRef FS); + + /// Check whether the subtarget features are enabled/disabled as per + /// the provided string, ignoring all other features. + bool checkFeatures(StringRef FS) const; + + /// Get the machine model of a CPU. + const MCSchedModel &getSchedModelForCPU(StringRef CPU) const; + + /// Get the machine model for this subtarget's CPU. + const MCSchedModel &getSchedModel() const { return *CPUSchedModel; } + + /// Return an iterator at the first process resource consumed by the given + /// scheduling class. + const MCWriteProcResEntry *getWriteProcResBegin( + const MCSchedClassDesc *SC) const { + return &WriteProcResTable[SC->WriteProcResIdx]; + } + const MCWriteProcResEntry *getWriteProcResEnd( + const MCSchedClassDesc *SC) const { + return getWriteProcResBegin(SC) + SC->NumWriteProcResEntries; + } + + const MCWriteLatencyEntry *getWriteLatencyEntry(const MCSchedClassDesc *SC, + unsigned DefIdx) const { + assert(DefIdx < SC->NumWriteLatencyEntries && + "MachineModel does not specify a WriteResource for DefIdx"); + + return &WriteLatencyTable[SC->WriteLatencyIdx + DefIdx]; + } + + int getReadAdvanceCycles(const MCSchedClassDesc *SC, unsigned UseIdx, + unsigned WriteResID) const { + // TODO: The number of read advance entries in a class can be significant + // (~50). Consider compressing the WriteID into a dense ID of those that are + // used by ReadAdvance and representing them as a bitset. + for (const MCReadAdvanceEntry *I = &ReadAdvanceTable[SC->ReadAdvanceIdx], + *E = I + SC->NumReadAdvanceEntries; I != E; ++I) { + if (I->UseIdx < UseIdx) + continue; + if (I->UseIdx > UseIdx) + break; + // Find the first WriteResIdx match, which has the highest cycle count. + if (!I->WriteResourceID || I->WriteResourceID == WriteResID) { + return I->Cycles; + } + } + return 0; + } + + /// Return the set of ReadAdvance entries declared by the scheduling class + /// descriptor in input. + ArrayRef<MCReadAdvanceEntry> + getReadAdvanceEntries(const MCSchedClassDesc &SC) const { + if (!SC.NumReadAdvanceEntries) + return ArrayRef<MCReadAdvanceEntry>(); + return ArrayRef<MCReadAdvanceEntry>(&ReadAdvanceTable[SC.ReadAdvanceIdx], + SC.NumReadAdvanceEntries); + } + + /// Get scheduling itinerary of a CPU. + InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const; + + /// Initialize an InstrItineraryData instance. + void initInstrItins(InstrItineraryData &InstrItins) const; + + /// Resolve a variant scheduling class for the given MCInst and CPU. + virtual unsigned + resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI, + unsigned CPUID) const { + return 0; + } + + /// Check whether the CPU string is valid. + bool isCPUStringValid(StringRef CPU) const { + auto Found = std::lower_bound(ProcDesc.begin(), ProcDesc.end(), CPU); + return Found != ProcDesc.end() && StringRef(Found->Key) == CPU; + } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCSUBTARGETINFO_H diff --git a/clang-r353983/include/llvm/MC/MCSymbol.h b/clang-r353983/include/llvm/MC/MCSymbol.h new file mode 100644 index 00000000..273e5a33 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSymbol.h @@ -0,0 +1,428 @@ +//===- MCSymbol.h - Machine Code Symbols ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCSymbol class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSYMBOL_H +#define LLVM_MC_MCSYMBOL_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCFragment.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <cstddef> +#include <cstdint> + +namespace llvm { + +class MCAsmInfo; +class MCContext; +class MCExpr; +class MCSection; +class raw_ostream; + +/// MCSymbol - Instances of this class represent a symbol name in the MC file, +/// and MCSymbols are created and uniqued by the MCContext class. MCSymbols +/// should only be constructed with valid names for the object file. +/// +/// If the symbol is defined/emitted into the current translation unit, the +/// Section member is set to indicate what section it lives in. Otherwise, if +/// it is a reference to an external entity, it has a null section. +class MCSymbol { +protected: + /// The kind of the symbol. If it is any value other than unset then this + /// class is actually one of the appropriate subclasses of MCSymbol. + enum SymbolKind { + SymbolKindUnset, + SymbolKindCOFF, + SymbolKindELF, + SymbolKindMachO, + SymbolKindWasm, + }; + + /// A symbol can contain an Offset, or Value, or be Common, but never more + /// than one of these. + enum Contents : uint8_t { + SymContentsUnset, + SymContentsOffset, + SymContentsVariable, + SymContentsCommon, + }; + + // Special sentinal value for the absolute pseudo fragment. + static MCFragment *AbsolutePseudoFragment; + + /// If a symbol has a Fragment, the section is implied, so we only need + /// one pointer. + /// The special AbsolutePseudoFragment value is for absolute symbols. + /// If this is a variable symbol, this caches the variable value's fragment. + /// FIXME: We might be able to simplify this by having the asm streamer create + /// dummy fragments. + /// If this is a section, then it gives the symbol is defined in. This is null + /// for undefined symbols. + /// + /// If this is a fragment, then it gives the fragment this symbol's value is + /// relative to, if any. + /// + /// For the 'HasName' integer, this is true if this symbol is named. + /// A named symbol will have a pointer to the name allocated in the bytes + /// immediately prior to the MCSymbol. + mutable PointerIntPair<MCFragment *, 1> FragmentAndHasName; + + /// IsTemporary - True if this is an assembler temporary label, which + /// typically does not survive in the .o file's symbol table. Usually + /// "Lfoo" or ".foo". + unsigned IsTemporary : 1; + + /// True if this symbol can be redefined. + unsigned IsRedefinable : 1; + + /// IsUsed - True if this symbol has been used. + mutable unsigned IsUsed : 1; + + mutable unsigned IsRegistered : 1; + + /// This symbol is visible outside this translation unit. + mutable unsigned IsExternal : 1; + + /// This symbol is private extern. + mutable unsigned IsPrivateExtern : 1; + + /// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is + /// unsigned to avoid sign extension and achieve better bitpacking with MSVC. + unsigned Kind : 3; + + /// True if we have created a relocation that uses this symbol. + mutable unsigned IsUsedInReloc : 1; + + /// This is actually a Contents enumerator, but is unsigned to avoid sign + /// extension and achieve better bitpacking with MSVC. + unsigned SymbolContents : 2; + + /// The alignment of the symbol, if it is 'common', or -1. + /// + /// The alignment is stored as log2(align) + 1. This allows all values from + /// 0 to 2^31 to be stored which is every power of 2 representable by an + /// unsigned. + enum : unsigned { NumCommonAlignmentBits = 5 }; + unsigned CommonAlignLog2 : NumCommonAlignmentBits; + + /// The Flags field is used by object file implementations to store + /// additional per symbol information which is not easily classified. + enum : unsigned { NumFlagsBits = 16 }; + mutable uint32_t Flags : NumFlagsBits; + + /// Index field, for use by the object file implementation. + mutable uint32_t Index = 0; + + union { + /// The offset to apply to the fragment address to form this symbol's value. + uint64_t Offset; + + /// The size of the symbol, if it is 'common'. + uint64_t CommonSize; + + /// If non-null, the value for a variable symbol. + const MCExpr *Value; + }; + + // MCContext creates and uniques these. + friend class MCExpr; + friend class MCContext; + + /// The name for a symbol. + /// MCSymbol contains a uint64_t so is probably aligned to 8. On a 32-bit + /// system, the name is a pointer so isn't going to satisfy the 8 byte + /// alignment of uint64_t. Account for that here. + using NameEntryStorageTy = union { + const StringMapEntry<bool> *NameEntry; + uint64_t AlignmentPadding; + }; + + MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary) + : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false), + IsRegistered(false), IsExternal(false), IsPrivateExtern(false), + Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset), + CommonAlignLog2(0), Flags(0) { + Offset = 0; + FragmentAndHasName.setInt(!!Name); + if (Name) + getNameEntryPtr() = Name; + } + + // Provide custom new/delete as we will only allocate space for a name + // if we need one. + void *operator new(size_t s, const StringMapEntry<bool> *Name, + MCContext &Ctx); + +private: + void operator delete(void *); + /// Placement delete - required by std, but never called. + void operator delete(void*, unsigned) { + llvm_unreachable("Constructor throws?"); + } + /// Placement delete - required by std, but never called. + void operator delete(void*, unsigned, bool) { + llvm_unreachable("Constructor throws?"); + } + + MCSection *getSectionPtr() const { + if (MCFragment *F = getFragment()) { + assert(F != AbsolutePseudoFragment); + return F->getParent(); + } + return nullptr; + } + + /// Get a reference to the name field. Requires that we have a name + const StringMapEntry<bool> *&getNameEntryPtr() { + assert(FragmentAndHasName.getInt() && "Name is required"); + NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this); + return (*(Name - 1)).NameEntry; + } + const StringMapEntry<bool> *&getNameEntryPtr() const { + return const_cast<MCSymbol*>(this)->getNameEntryPtr(); + } + +public: + MCSymbol(const MCSymbol &) = delete; + MCSymbol &operator=(const MCSymbol &) = delete; + + /// getName - Get the symbol name. + StringRef getName() const { + if (!FragmentAndHasName.getInt()) + return StringRef(); + + return getNameEntryPtr()->first(); + } + + bool isRegistered() const { return IsRegistered; } + void setIsRegistered(bool Value) const { IsRegistered = Value; } + + void setUsedInReloc() const { IsUsedInReloc = true; } + bool isUsedInReloc() const { return IsUsedInReloc; } + + /// \name Accessors + /// @{ + + /// isTemporary - Check if this is an assembler temporary symbol. + bool isTemporary() const { return IsTemporary; } + + /// isUsed - Check if this is used. + bool isUsed() const { return IsUsed; } + + /// Check if this symbol is redefinable. + bool isRedefinable() const { return IsRedefinable; } + /// Mark this symbol as redefinable. + void setRedefinable(bool Value) { IsRedefinable = Value; } + /// Prepare this symbol to be redefined. + void redefineIfPossible() { + if (IsRedefinable) { + if (SymbolContents == SymContentsVariable) { + Value = nullptr; + SymbolContents = SymContentsUnset; + } + setUndefined(); + IsRedefinable = false; + } + } + + /// @} + /// \name Associated Sections + /// @{ + + /// isDefined - Check if this symbol is defined (i.e., it has an address). + /// + /// Defined symbols are either absolute or in some section. + bool isDefined() const { return !isUndefined(); } + + /// isInSection - Check if this symbol is defined in some section (i.e., it + /// is defined but not absolute). + bool isInSection() const { + return isDefined() && !isAbsolute(); + } + + /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). + bool isUndefined(bool SetUsed = true) const { + return getFragment(SetUsed) == nullptr; + } + + /// isAbsolute - Check if this is an absolute symbol. + bool isAbsolute() const { + return getFragment() == AbsolutePseudoFragment; + } + + /// Get the section associated with a defined, non-absolute symbol. + MCSection &getSection() const { + assert(isInSection() && "Invalid accessor!"); + return *getSectionPtr(); + } + + /// Mark the symbol as defined in the fragment \p F. + void setFragment(MCFragment *F) const { + assert(!isVariable() && "Cannot set fragment of variable"); + FragmentAndHasName.setPointer(F); + } + + /// Mark the symbol as undefined. + void setUndefined() { FragmentAndHasName.setPointer(nullptr); } + + bool isELF() const { return Kind == SymbolKindELF; } + + bool isCOFF() const { return Kind == SymbolKindCOFF; } + + bool isMachO() const { return Kind == SymbolKindMachO; } + + bool isWasm() const { return Kind == SymbolKindWasm; } + + /// @} + /// \name Variable Symbols + /// @{ + + /// isVariable - Check if this is a variable symbol. + bool isVariable() const { + return SymbolContents == SymContentsVariable; + } + + /// getVariableValue - Get the value for variable symbols. + const MCExpr *getVariableValue(bool SetUsed = true) const { + assert(isVariable() && "Invalid accessor!"); + IsUsed |= SetUsed; + return Value; + } + + void setVariableValue(const MCExpr *Value); + + /// @} + + /// Get the (implementation defined) index. + uint32_t getIndex() const { + return Index; + } + + /// Set the (implementation defined) index. + void setIndex(uint32_t Value) const { + Index = Value; + } + + bool isUnset() const { return SymbolContents == SymContentsUnset; } + + uint64_t getOffset() const { + assert((SymbolContents == SymContentsUnset || + SymbolContents == SymContentsOffset) && + "Cannot get offset for a common/variable symbol"); + return Offset; + } + void setOffset(uint64_t Value) { + assert((SymbolContents == SymContentsUnset || + SymbolContents == SymContentsOffset) && + "Cannot set offset for a common/variable symbol"); + Offset = Value; + SymbolContents = SymContentsOffset; + } + + /// Return the size of a 'common' symbol. + uint64_t getCommonSize() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonSize; + } + + /// Mark this symbol as being 'common'. + /// + /// \param Size - The size of the symbol. + /// \param Align - The alignment of the symbol. + void setCommon(uint64_t Size, unsigned Align) { + assert(getOffset() == 0); + CommonSize = Size; + SymbolContents = SymContentsCommon; + + assert((!Align || isPowerOf2_32(Align)) && + "Alignment must be a power of 2"); + unsigned Log2Align = Log2_32(Align) + 1; + assert(Log2Align < (1U << NumCommonAlignmentBits) && + "Out of range alignment"); + CommonAlignLog2 = Log2Align; + } + + /// Return the alignment of a 'common' symbol. + unsigned getCommonAlignment() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonAlignLog2 ? (1U << (CommonAlignLog2 - 1)) : 0; + } + + /// Declare this symbol as being 'common'. + /// + /// \param Size - The size of the symbol. + /// \param Align - The alignment of the symbol. + /// \return True if symbol was already declared as a different type + bool declareCommon(uint64_t Size, unsigned Align) { + assert(isCommon() || getOffset() == 0); + if(isCommon()) { + if(CommonSize != Size || getCommonAlignment() != Align) + return true; + } else + setCommon(Size, Align); + return false; + } + + /// Is this a 'common' symbol. + bool isCommon() const { + return SymbolContents == SymContentsCommon; + } + + MCFragment *getFragment(bool SetUsed = true) const { + MCFragment *Fragment = FragmentAndHasName.getPointer(); + if (Fragment || !isVariable()) + return Fragment; + Fragment = getVariableValue(SetUsed)->findAssociatedFragment(); + FragmentAndHasName.setPointer(Fragment); + return Fragment; + } + + bool isExternal() const { return IsExternal; } + void setExternal(bool Value) const { IsExternal = Value; } + + bool isPrivateExtern() const { return IsPrivateExtern; } + void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } + + /// print - Print the value to the stream \p OS. + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + + /// dump - Print the value to stderr. + void dump() const; + +protected: + /// Get the (implementation defined) symbol flags. + uint32_t getFlags() const { return Flags; } + + /// Set the (implementation defined) symbol flags. + void setFlags(uint32_t Value) const { + assert(Value < (1U << NumFlagsBits) && "Out of range flags"); + Flags = Value; + } + + /// Modify the flags via a mask + void modifyFlags(uint32_t Value, uint32_t Mask) const { + assert(Value < (1U << NumFlagsBits) && "Out of range flags"); + Flags = (Flags & ~Mask) | Value; + } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { + Sym.print(OS, nullptr); + return OS; +} + +} // end namespace llvm + +#endif // LLVM_MC_MCSYMBOL_H diff --git a/clang-r353983/include/llvm/MC/MCSymbolCOFF.h b/clang-r353983/include/llvm/MC/MCSymbolCOFF.h new file mode 100644 index 00000000..94087ce8 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSymbolCOFF.h @@ -0,0 +1,66 @@ +//===- MCSymbolCOFF.h - ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSYMBOLCOFF_H +#define LLVM_MC_MCSYMBOLCOFF_H + +#include "llvm/MC/MCSymbol.h" +#include <cstdint> + +namespace llvm { + +class MCSymbolCOFF : public MCSymbol { + /// This corresponds to the e_type field of the COFF symbol. + mutable uint16_t Type = 0; + + enum SymbolFlags : uint16_t { + SF_ClassMask = 0x00FF, + SF_ClassShift = 0, + + SF_WeakExternal = 0x0100, + SF_SafeSEH = 0x0200, + }; + +public: + MCSymbolCOFF(const StringMapEntry<bool> *Name, bool isTemporary) + : MCSymbol(SymbolKindCOFF, Name, isTemporary) {} + + uint16_t getType() const { + return Type; + } + void setType(uint16_t Ty) const { + Type = Ty; + } + + uint16_t getClass() const { + return (getFlags() & SF_ClassMask) >> SF_ClassShift; + } + void setClass(uint16_t StorageClass) const { + modifyFlags(StorageClass << SF_ClassShift, SF_ClassMask); + } + + bool isWeakExternal() const { + return getFlags() & SF_WeakExternal; + } + void setIsWeakExternal() const { + modifyFlags(SF_WeakExternal, SF_WeakExternal); + } + + bool isSafeSEH() const { + return getFlags() & SF_SafeSEH; + } + void setIsSafeSEH() const { + modifyFlags(SF_SafeSEH, SF_SafeSEH); + } + + static bool classof(const MCSymbol *S) { return S->isCOFF(); } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCSYMBOLCOFF_H diff --git a/clang-r353983/include/llvm/MC/MCSymbolELF.h b/clang-r353983/include/llvm/MC/MCSymbolELF.h new file mode 100644 index 00000000..34e5c434 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSymbolELF.h @@ -0,0 +1,53 @@ +//===- MCSymbolELF.h - -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_MC_MCSYMBOLELF_H +#define LLVM_MC_MCSYMBOLELF_H + +#include "llvm/MC/MCSymbol.h" + +namespace llvm { +class MCSymbolELF : public MCSymbol { + /// An expression describing how to calculate the size of a symbol. If a + /// symbol has no size this field will be NULL. + const MCExpr *SymbolSize = nullptr; + +public: + MCSymbolELF(const StringMapEntry<bool> *Name, bool isTemporary) + : MCSymbol(SymbolKindELF, Name, isTemporary) {} + void setSize(const MCExpr *SS) { SymbolSize = SS; } + + const MCExpr *getSize() const { return SymbolSize; } + + void setVisibility(unsigned Visibility); + unsigned getVisibility() const; + + void setOther(unsigned Other); + unsigned getOther() const; + + void setType(unsigned Type) const; + unsigned getType() const; + + void setBinding(unsigned Binding) const; + unsigned getBinding() const; + + bool isBindingSet() const; + + void setIsWeakrefUsedInReloc() const; + bool isWeakrefUsedInReloc() const; + + void setIsSignature() const; + bool isSignature() const; + + static bool classof(const MCSymbol *S) { return S->isELF(); } + +private: + void setIsBindingSet() const; +}; +} + +#endif diff --git a/clang-r353983/include/llvm/MC/MCSymbolMachO.h b/clang-r353983/include/llvm/MC/MCSymbolMachO.h new file mode 100644 index 00000000..8f9ff564 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSymbolMachO.h @@ -0,0 +1,140 @@ +//===- MCSymbolMachO.h - ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_MC_MCSYMBOLMACHO_H +#define LLVM_MC_MCSYMBOLMACHO_H + +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCSymbol.h" + +namespace llvm { +class MCSymbolMachO : public MCSymbol { + /// We store the value for the 'desc' symbol field in the + /// lowest 16 bits of the implementation defined flags. + enum MachOSymbolFlags : uint16_t { // See <mach-o/nlist.h>. + SF_DescFlagsMask = 0xFFFF, + + // Reference type flags. + SF_ReferenceTypeMask = 0x0007, + SF_ReferenceTypeUndefinedNonLazy = 0x0000, + SF_ReferenceTypeUndefinedLazy = 0x0001, + SF_ReferenceTypeDefined = 0x0002, + SF_ReferenceTypePrivateDefined = 0x0003, + SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004, + SF_ReferenceTypePrivateUndefinedLazy = 0x0005, + + // Other 'desc' flags. + SF_ThumbFunc = 0x0008, + SF_NoDeadStrip = 0x0020, + SF_WeakReference = 0x0040, + SF_WeakDefinition = 0x0080, + SF_SymbolResolver = 0x0100, + SF_AltEntry = 0x0200, + SF_Cold = 0x0400, + + // Common alignment + SF_CommonAlignmentMask = 0xF0FF, + SF_CommonAlignmentShift = 8 + }; + +public: + MCSymbolMachO(const StringMapEntry<bool> *Name, bool isTemporary) + : MCSymbol(SymbolKindMachO, Name, isTemporary) {} + + // Reference type methods. + + void clearReferenceType() const { + modifyFlags(0, SF_ReferenceTypeMask); + } + + void setReferenceTypeUndefinedLazy(bool Value) const { + modifyFlags(Value ? SF_ReferenceTypeUndefinedLazy : 0, + SF_ReferenceTypeUndefinedLazy); + } + + // Other 'desc' methods. + + void setThumbFunc() const { + modifyFlags(SF_ThumbFunc, SF_ThumbFunc); + } + + bool isNoDeadStrip() const { + return getFlags() & SF_NoDeadStrip; + } + void setNoDeadStrip() const { + modifyFlags(SF_NoDeadStrip, SF_NoDeadStrip); + } + + bool isWeakReference() const { + return getFlags() & SF_WeakReference; + } + void setWeakReference() const { + modifyFlags(SF_WeakReference, SF_WeakReference); + } + + bool isWeakDefinition() const { + return getFlags() & SF_WeakDefinition; + } + void setWeakDefinition() const { + modifyFlags(SF_WeakDefinition, SF_WeakDefinition); + } + + bool isSymbolResolver() const { + return getFlags() & SF_SymbolResolver; + } + void setSymbolResolver() const { + modifyFlags(SF_SymbolResolver, SF_SymbolResolver); + } + + void setAltEntry() const { + modifyFlags(SF_AltEntry, SF_AltEntry); + } + + bool isAltEntry() const { + return getFlags() & SF_AltEntry; + } + + void setCold() const { modifyFlags(SF_Cold, SF_Cold); } + + bool isCold() const { return getFlags() & SF_Cold; } + + void setDesc(unsigned Value) const { + assert(Value == (Value & SF_DescFlagsMask) && + "Invalid .desc value!"); + setFlags(Value & SF_DescFlagsMask); + } + + /// Get the encoded value of the flags as they will be emitted in to + /// the MachO binary + uint16_t getEncodedFlags(bool EncodeAsAltEntry) const { + uint16_t Flags = getFlags(); + + // Common alignment is packed into the 'desc' bits. + if (isCommon()) { + if (unsigned Align = getCommonAlignment()) { + unsigned Log2Size = Log2_32(Align); + assert((1U << Log2Size) == Align && "Invalid 'common' alignment!"); + if (Log2Size > 15) + report_fatal_error("invalid 'common' alignment '" + + Twine(Align) + "' for '" + getName() + "'", + false); + Flags = (Flags & SF_CommonAlignmentMask) | + (Log2Size << SF_CommonAlignmentShift); + } + } + + if (EncodeAsAltEntry) + Flags |= SF_AltEntry; + + return Flags; + } + + static bool classof(const MCSymbol *S) { return S->isMachO(); } +}; +} + +#endif diff --git a/clang-r353983/include/llvm/MC/MCSymbolWasm.h b/clang-r353983/include/llvm/MC/MCSymbolWasm.h new file mode 100644 index 00000000..88759fe4 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCSymbolWasm.h @@ -0,0 +1,99 @@ +//===- MCSymbolWasm.h - ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_MC_MCSYMBOLWASM_H +#define LLVM_MC_MCSYMBOLWASM_H + +#include "llvm/BinaryFormat/Wasm.h" +#include "llvm/MC/MCSymbol.h" + +namespace llvm { + +class MCSymbolWasm : public MCSymbol { + wasm::WasmSymbolType Type = wasm::WASM_SYMBOL_TYPE_DATA; + bool IsWeak = false; + bool IsHidden = false; + bool IsComdat = false; + Optional<std::string> ImportModule; + Optional<std::string> ImportName; + wasm::WasmSignature *Signature = nullptr; + Optional<wasm::WasmGlobalType> GlobalType; + Optional<wasm::WasmEventType> EventType; + + /// An expression describing how to calculate the size of a symbol. If a + /// symbol has no size this field will be NULL. + const MCExpr *SymbolSize = nullptr; + +public: + // Use a module name of "env" for now, for compatibility with existing tools. + // This is temporary, and may change, as the ABI is not yet stable. + MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary) + : MCSymbol(SymbolKindWasm, Name, isTemporary) {} + static bool classof(const MCSymbol *S) { return S->isWasm(); } + + const MCExpr *getSize() const { return SymbolSize; } + void setSize(const MCExpr *SS) { SymbolSize = SS; } + + bool isFunction() const { return Type == wasm::WASM_SYMBOL_TYPE_FUNCTION; } + bool isData() const { return Type == wasm::WASM_SYMBOL_TYPE_DATA; } + bool isGlobal() const { return Type == wasm::WASM_SYMBOL_TYPE_GLOBAL; } + bool isSection() const { return Type == wasm::WASM_SYMBOL_TYPE_SECTION; } + bool isEvent() const { return Type == wasm::WASM_SYMBOL_TYPE_EVENT; } + wasm::WasmSymbolType getType() const { return Type; } + void setType(wasm::WasmSymbolType type) { Type = type; } + + bool isExported() const { + return getFlags() & wasm::WASM_SYMBOL_EXPORTED; + } + void setExported() const { + modifyFlags(wasm::WASM_SYMBOL_EXPORTED, wasm::WASM_SYMBOL_EXPORTED); + } + + bool isWeak() const { return IsWeak; } + void setWeak(bool isWeak) { IsWeak = isWeak; } + + bool isHidden() const { return IsHidden; } + void setHidden(bool isHidden) { IsHidden = isHidden; } + + bool isComdat() const { return IsComdat; } + void setComdat(bool isComdat) { IsComdat = isComdat; } + + const StringRef getImportModule() const { + if (ImportModule.hasValue()) { + return ImportModule.getValue(); + } + return "env"; + } + void setImportModule(StringRef Name) { ImportModule = Name; } + + const StringRef getImportName() const { + if (ImportName.hasValue()) { + return ImportName.getValue(); + } + return getName(); + } + void setImportName(StringRef Name) { ImportName = Name; } + + const wasm::WasmSignature *getSignature() const { return Signature; } + void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; } + + const wasm::WasmGlobalType &getGlobalType() const { + assert(GlobalType.hasValue()); + return GlobalType.getValue(); + } + void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; } + + const wasm::WasmEventType &getEventType() const { + assert(EventType.hasValue()); + return EventType.getValue(); + } + void setEventType(wasm::WasmEventType ET) { EventType = ET; } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCSYMBOLWASM_H diff --git a/clang-r353983/include/llvm/MC/MCTargetOptions.h b/clang-r353983/include/llvm/MC/MCTargetOptions.h new file mode 100644 index 00000000..087d1553 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCTargetOptions.h @@ -0,0 +1,79 @@ +//===- MCTargetOptions.h - MC Target Options --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCTARGETOPTIONS_H +#define LLVM_MC_MCTARGETOPTIONS_H + +#include <string> +#include <vector> + +namespace llvm { + +enum class ExceptionHandling { + None, /// No exception support + DwarfCFI, /// DWARF-like instruction based exceptions + SjLj, /// setjmp/longjmp based exceptions + ARM, /// ARM EHABI + WinEH, /// Windows Exception Handling + Wasm, /// WebAssembly Exception Handling +}; + +enum class DebugCompressionType { + None, /// No compression + GNU, /// zlib-gnu style compression + Z, /// zlib style complession +}; + +class StringRef; + +class MCTargetOptions { +public: + enum AsmInstrumentation { + AsmInstrumentationNone, + AsmInstrumentationAddress + }; + + /// Enables AddressSanitizer instrumentation at machine level. + bool SanitizeAddress : 1; + + bool MCRelaxAll : 1; + bool MCNoExecStack : 1; + bool MCFatalWarnings : 1; + bool MCNoWarn : 1; + bool MCNoDeprecatedWarn : 1; + bool MCSaveTempLabels : 1; + bool MCUseDwarfDirectory : 1; + bool MCIncrementalLinkerCompatible : 1; + bool MCPIECopyRelocations : 1; + bool ShowMCEncoding : 1; + bool ShowMCInst : 1; + bool AsmVerbose : 1; + + /// Preserve Comments in Assembly. + bool PreserveAsmComments : 1; + + int DwarfVersion = 0; + + std::string ABIName; + std::string SplitDwarfFile; + + /// Additional paths to search for `.include` directives when using the + /// integrated assembler. + std::vector<std::string> IASSearchPaths; + + MCTargetOptions(); + + /// getABIName - If this returns a non-empty string this represents the + /// textual name of the ABI that we want the backend to use, e.g. o32, or + /// aapcs-linux. + StringRef getABIName() const; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCTARGETOPTIONS_H diff --git a/clang-r353983/include/llvm/MC/MCTargetOptionsCommandFlags.inc b/clang-r353983/include/llvm/MC/MCTargetOptionsCommandFlags.inc new file mode 100644 index 00000000..f8129463 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCTargetOptionsCommandFlags.inc @@ -0,0 +1,79 @@ +//===-- MCTargetOptionsCommandFlags.h --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains machine code-specific flags that are shared between +// different command line tools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H +#define LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H + +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +static cl::opt<MCTargetOptions::AsmInstrumentation> AsmInstrumentation( + "asm-instrumentation", cl::desc("Instrumentation of inline assembly and " + "assembly source files"), + cl::init(MCTargetOptions::AsmInstrumentationNone), + cl::values(clEnumValN(MCTargetOptions::AsmInstrumentationNone, "none", + "no instrumentation at all"), + clEnumValN(MCTargetOptions::AsmInstrumentationAddress, "address", + "instrument instructions with memory arguments"))); + +static cl::opt<bool> RelaxAll("mc-relax-all", + cl::desc("When used with filetype=obj, " + "relax all fixups in the emitted object file")); + +static 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")); + +static cl::opt<bool> PIECopyRelocations("pie-copy-relocations", cl::desc("PIE Copy Relocations")); + +static cl::opt<int> DwarfVersion("dwarf-version", cl::desc("Dwarf version"), + cl::init(0)); + +static cl::opt<bool> ShowMCInst("asm-show-inst", + cl::desc("Emit internal instruction representation to " + "assembly file")); + +static cl::opt<bool> FatalWarnings("fatal-warnings", + cl::desc("Treat warnings as errors")); + +static cl::opt<bool> NoWarn("no-warn", cl::desc("Suppress all warnings")); +static cl::alias NoWarnW("W", cl::desc("Alias for --no-warn"), cl::aliasopt(NoWarn)); + +static cl::opt<bool> NoDeprecatedWarn("no-deprecated-warn", + cl::desc("Suppress all deprecated warnings")); + +static cl::opt<std::string> +ABIName("target-abi", cl::Hidden, + cl::desc("The name of the ABI to be targeted from the backend."), + cl::init("")); + +static MCTargetOptions InitMCTargetOptionsFromFlags() { + MCTargetOptions Options; + Options.SanitizeAddress = + (AsmInstrumentation == MCTargetOptions::AsmInstrumentationAddress); + Options.MCRelaxAll = RelaxAll; + Options.MCIncrementalLinkerCompatible = IncrementalLinkerCompatible; + Options.MCPIECopyRelocations = PIECopyRelocations; + Options.DwarfVersion = DwarfVersion; + Options.ShowMCInst = ShowMCInst; + Options.ABIName = ABIName; + Options.MCFatalWarnings = FatalWarnings; + Options.MCNoWarn = NoWarn; + Options.MCNoDeprecatedWarn = NoDeprecatedWarn; + return Options; +} + +#endif diff --git a/clang-r353983/include/llvm/MC/MCValue.h b/clang-r353983/include/llvm/MC/MCValue.h new file mode 100644 index 00000000..0be7ce70 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCValue.h @@ -0,0 +1,86 @@ +//===-- llvm/MC/MCValue.h - MCValue class -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCValue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCVALUE_H +#define LLVM_MC_MCVALUE_H + +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/DataTypes.h" +#include <cassert> + +namespace llvm { +class MCAsmInfo; +class raw_ostream; + +/// This represents an "assembler immediate". +/// +/// In its most general form, this can hold ":Kind:(SymbolA - SymbolB + +/// imm64)". Not all targets supports relocations of this general form, but we +/// need to represent this anyway. +/// +/// In general both SymbolA and SymbolB will also have a modifier +/// analogous to the top-level Kind. Current targets are not expected +/// to make use of both though. The choice comes down to whether +/// relocation modifiers apply to the closest symbol or the whole +/// expression. +/// +/// Note that this class must remain a simple POD value class, because we need +/// it to live in unions etc. +class MCValue { + const MCSymbolRefExpr *SymA = nullptr, *SymB = nullptr; + int64_t Cst = 0; + uint32_t RefKind = 0; + +public: + MCValue() = default; + int64_t getConstant() const { return Cst; } + const MCSymbolRefExpr *getSymA() const { return SymA; } + const MCSymbolRefExpr *getSymB() const { return SymB; } + uint32_t getRefKind() const { return RefKind; } + + /// Is this an absolute (as opposed to relocatable) value. + bool isAbsolute() const { return !SymA && !SymB; } + + /// Print the value to the stream \p OS. + void print(raw_ostream &OS) const; + + /// Print the value to stderr. + void dump() const; + + MCSymbolRefExpr::VariantKind getAccessVariant() const; + + static MCValue get(const MCSymbolRefExpr *SymA, + const MCSymbolRefExpr *SymB = nullptr, + int64_t Val = 0, uint32_t RefKind = 0) { + MCValue R; + R.Cst = Val; + R.SymA = SymA; + R.SymB = SymB; + R.RefKind = RefKind; + return R; + } + + static MCValue get(int64_t Val) { + MCValue R; + R.Cst = Val; + R.SymA = nullptr; + R.SymB = nullptr; + R.RefKind = 0; + return R; + } + +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCWasmObjectWriter.h b/clang-r353983/include/llvm/MC/MCWasmObjectWriter.h new file mode 100644 index 00000000..4adbca28 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCWasmObjectWriter.h @@ -0,0 +1,55 @@ +//===-- llvm/MC/MCWasmObjectWriter.h - Wasm Object Writer -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCWASMOBJECTWRITER_H +#define LLVM_MC_MCWASMOBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" +#include <memory> + +namespace llvm { + +class MCFixup; +class MCValue; +class raw_pwrite_stream; + +class MCWasmObjectTargetWriter : public MCObjectTargetWriter { + const unsigned Is64Bit : 1; + +protected: + explicit MCWasmObjectTargetWriter(bool Is64Bit_); + +public: + virtual ~MCWasmObjectTargetWriter(); + + virtual Triple::ObjectFormatType getFormat() const { return Triple::Wasm; } + static bool classof(const MCObjectTargetWriter *W) { + return W->getFormat() == Triple::Wasm; + } + + virtual unsigned getRelocType(const MCValue &Target, + const MCFixup &Fixup) const = 0; + + /// \name Accessors + /// @{ + bool is64Bit() const { return Is64Bit; } + /// @} +}; + +/// Construct a new Wasm writer instance. +/// +/// \param MOTW - The target specific Wasm writer subclass. +/// \param OS - The stream to write to. +/// \returns The constructed object writer. +std::unique_ptr<MCObjectWriter> +createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, + raw_pwrite_stream &OS); + +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCWasmStreamer.h b/clang-r353983/include/llvm/MC/MCWasmStreamer.h new file mode 100644 index 00000000..2d7f2b99 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCWasmStreamer.h @@ -0,0 +1,87 @@ +//===- MCWasmStreamer.h - MCStreamer Wasm Object File Interface -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCWASMSTREAMER_H +#define LLVM_MC_MCWASMSTREAMER_H + +#include "MCAsmBackend.h" +#include "MCCodeEmitter.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class MCAssembler; +class MCExpr; +class MCInst; +class raw_ostream; + +class MCWasmStreamer : public MCObjectStreamer { +public: + MCWasmStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, + std::unique_ptr<MCObjectWriter> OW, + std::unique_ptr<MCCodeEmitter> Emitter) + : MCObjectStreamer(Context, std::move(TAB), std::move(OW), + std::move(Emitter)), + SeenIdent(false) {} + + ~MCWasmStreamer() override; + + /// state management + void reset() override { + SeenIdent = false; + MCObjectStreamer::reset(); + } + + /// \name MCStreamer Interface + /// @{ + + void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; + void EmitAssemblerFlag(MCAssemblerFlag Flag) override; + void EmitThumbFunc(MCSymbol *Func) override; + void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + + void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; + + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + + void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0, + SMLoc Loc = SMLoc()) override; + void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment = 0) override; + void EmitValueImpl(const MCExpr *Value, unsigned Size, + SMLoc Loc = SMLoc()) override; + + void EmitIdent(StringRef IdentString) override; + + void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned) override; + + void FinishImpl() override; + +private: + void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override; + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; + + /// Merge the content of the fragment \p EF into the fragment \p DF. + void mergeFragment(MCDataFragment *, MCDataFragment *); + + bool SeenIdent; +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCWin64EH.h b/clang-r353983/include/llvm/MC/MCWin64EH.h new file mode 100644 index 00000000..60ec06e6 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCWin64EH.h @@ -0,0 +1,69 @@ +//===- MCWin64EH.h - Machine Code Win64 EH support --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains declarations to support the Win64 Exception Handling +// scheme in MC. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCWIN64EH_H +#define LLVM_MC_MCWIN64EH_H + +#include "llvm/MC/MCWinEH.h" +#include "llvm/Support/Win64EH.h" + +namespace llvm { +class MCStreamer; +class MCSymbol; + +namespace Win64EH { +struct Instruction { + static WinEH::Instruction PushNonVol(MCSymbol *L, unsigned Reg) { + return WinEH::Instruction(Win64EH::UOP_PushNonVol, L, Reg, -1); + } + static WinEH::Instruction Alloc(MCSymbol *L, unsigned Size) { + return WinEH::Instruction(Size > 128 ? UOP_AllocLarge : UOP_AllocSmall, L, + -1, Size); + } + static WinEH::Instruction PushMachFrame(MCSymbol *L, bool Code) { + return WinEH::Instruction(UOP_PushMachFrame, L, -1, Code ? 1 : 0); + } + static WinEH::Instruction SaveNonVol(MCSymbol *L, unsigned Reg, + unsigned Offset) { + return WinEH::Instruction(Offset > 512 * 1024 - 8 ? UOP_SaveNonVolBig + : UOP_SaveNonVol, + L, Reg, Offset); + } + static WinEH::Instruction SaveXMM(MCSymbol *L, unsigned Reg, + unsigned Offset) { + return WinEH::Instruction(Offset > 512 * 1024 - 8 ? UOP_SaveXMM128Big + : UOP_SaveXMM128, + L, Reg, Offset); + } + static WinEH::Instruction SetFPReg(MCSymbol *L, unsigned Reg, unsigned Off) { + return WinEH::Instruction(UOP_SetFPReg, L, Reg, Off); + } +}; + +class UnwindEmitter : public WinEH::UnwindEmitter { +public: + void Emit(MCStreamer &Streamer) const override; + void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI) const override; +}; + +class ARM64UnwindEmitter : public WinEH::UnwindEmitter { +public: + void Emit(MCStreamer &Streamer) const override; + void EmitUnwindInfo(MCStreamer &Streamer, + WinEH::FrameInfo *FI) const override; +}; + +} +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/MCWinCOFFObjectWriter.h b/clang-r353983/include/llvm/MC/MCWinCOFFObjectWriter.h new file mode 100644 index 00000000..3fe124fd --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -0,0 +1,56 @@ +//===- llvm/MC/MCWinCOFFObjectWriter.h - Win COFF Object Writer -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCWINCOFFOBJECTWRITER_H +#define LLVM_MC_MCWINCOFFOBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" +#include <memory> + +namespace llvm { + +class MCAsmBackend; +class MCContext; +class MCFixup; +class MCValue; +class raw_pwrite_stream; + + class MCWinCOFFObjectTargetWriter : public MCObjectTargetWriter { + virtual void anchor(); + + const unsigned Machine; + + protected: + MCWinCOFFObjectTargetWriter(unsigned Machine_); + + public: + virtual ~MCWinCOFFObjectTargetWriter() = default; + + virtual Triple::ObjectFormatType getFormat() const { return Triple::COFF; } + static bool classof(const MCObjectTargetWriter *W) { + return W->getFormat() == Triple::COFF; + } + + unsigned getMachine() const { return Machine; } + virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsCrossSection, + const MCAsmBackend &MAB) const = 0; + virtual bool recordRelocation(const MCFixup &) const { return true; } + }; + + /// Construct a new Win COFF writer instance. + /// + /// \param MOTW - The target specific WinCOFF writer subclass. + /// \param OS - The stream to write to. + /// \returns The constructed object writer. + std::unique_ptr<MCObjectWriter> + createWinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, + raw_pwrite_stream &OS); +} // end namespace llvm + +#endif // LLVM_MC_MCWINCOFFOBJECTWRITER_H diff --git a/clang-r353983/include/llvm/MC/MCWinCOFFStreamer.h b/clang-r353983/include/llvm/MC/MCWinCOFFStreamer.h new file mode 100644 index 00000000..c1c1ec56 --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCWinCOFFStreamer.h @@ -0,0 +1,82 @@ +//===- MCWinCOFFStreamer.h - COFF Object File Interface ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCWINCOFFSTREAMER_H +#define LLVM_MC_MCWINCOFFSTREAMER_H + +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCObjectStreamer.h" + +namespace llvm { + +class MCAsmBackend; +class MCContext; +class MCCodeEmitter; +class MCInst; +class MCSection; +class MCSubtargetInfo; +class MCSymbol; +class StringRef; +class raw_pwrite_stream; + +class MCWinCOFFStreamer : public MCObjectStreamer { +public: + MCWinCOFFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, + std::unique_ptr<MCCodeEmitter> CE, + std::unique_ptr<MCObjectWriter> OW); + + /// state management + void reset() override { + CurSymbol = nullptr; + MCObjectStreamer::reset(); + } + + /// \name MCStreamer interface + /// \{ + + void InitSections(bool NoExecStack) override; + void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + void EmitAssemblerFlag(MCAssemblerFlag Flag) override; + void EmitThumbFunc(MCSymbol *Func) override; + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; + void BeginCOFFSymbolDef(MCSymbol const *Symbol) override; + void EmitCOFFSymbolStorageClass(int StorageClass) override; + void EmitCOFFSymbolType(int Type) override; + void EndCOFFSymbolDef() override; + void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; + void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override; + void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; + void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; + void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment, SMLoc Loc = SMLoc()) override; + void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitIdent(StringRef IdentString) override; + void EmitWinEHHandlerData(SMLoc Loc) override; + void FinishImpl() override; + + /// \} + +protected: + const MCSymbol *CurSymbol; + + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override; + +private: + void Error(const Twine &Msg) const; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCWINCOFFSTREAMER_H diff --git a/clang-r353983/include/llvm/MC/MCWinEH.h b/clang-r353983/include/llvm/MC/MCWinEH.h new file mode 100644 index 00000000..b1c28c0e --- /dev/null +++ b/clang-r353983/include/llvm/MC/MCWinEH.h @@ -0,0 +1,69 @@ +//===- MCWinEH.h - Windows Unwinding Support --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCWINEH_H +#define LLVM_MC_MCWINEH_H + +#include "llvm/ADT/MapVector.h" +#include <vector> + +namespace llvm { +class MCSection; +class MCStreamer; +class MCSymbol; + +namespace WinEH { +struct Instruction { + const MCSymbol *Label; + unsigned Offset; + unsigned Register; + unsigned Operation; + + Instruction(unsigned Op, MCSymbol *L, unsigned Reg, unsigned Off) + : Label(L), Offset(Off), Register(Reg), Operation(Op) {} +}; + +struct FrameInfo { + const MCSymbol *Begin = nullptr; + const MCSymbol *End = nullptr; + const MCSymbol *FuncletOrFuncEnd = nullptr; + const MCSymbol *ExceptionHandler = nullptr; + const MCSymbol *Function = nullptr; + const MCSymbol *PrologEnd = nullptr; + const MCSymbol *Symbol = nullptr; + const MCSection *TextSection = nullptr; + + bool HandlesUnwind = false; + bool HandlesExceptions = false; + + int LastFrameInst = -1; + const FrameInfo *ChainedParent = nullptr; + std::vector<Instruction> Instructions; + MapVector<MCSymbol*, std::vector<Instruction>> EpilogMap; + + FrameInfo() = default; + FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel) + : Begin(BeginFuncEHLabel), Function(Function) {} + FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel, + const FrameInfo *ChainedParent) + : Begin(BeginFuncEHLabel), Function(Function), + ChainedParent(ChainedParent) {} +}; + +class UnwindEmitter { +public: + virtual ~UnwindEmitter(); + + /// This emits the unwind info sections (.pdata and .xdata in PE/COFF). + virtual void Emit(MCStreamer &Streamer) const = 0; + virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI) const = 0; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/MC/MachineLocation.h b/clang-r353983/include/llvm/MC/MachineLocation.h new file mode 100644 index 00000000..5872540e --- /dev/null +++ b/clang-r353983/include/llvm/MC/MachineLocation.h @@ -0,0 +1,58 @@ +//===- llvm/MC/MachineLocation.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// The MachineLocation class is used to represent a simple location in a machine +// frame. Locations will be one of two forms; a register or an address formed +// from a base address plus an offset. Register indirection can be specified by +// explicitly passing an offset to the constructor. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MACHINELOCATION_H +#define LLVM_MC_MACHINELOCATION_H + +#include <cstdint> +#include <cassert> + +namespace llvm { + +class MachineLocation { +private: + bool IsRegister = false; ///< True if location is a register. + unsigned Register = 0; ///< gcc/gdb register number. + +public: + enum : uint32_t { + // The target register number for an abstract frame pointer. The value is + // an arbitrary value that doesn't collide with any real target register. + VirtualFP = ~0U + }; + + MachineLocation() = default; + /// Create a direct register location. + explicit MachineLocation(unsigned R, bool Indirect = false) + : IsRegister(!Indirect), Register(R) {} + + bool operator==(const MachineLocation &Other) const { + return IsRegister == Other.IsRegister && Register == Other.Register; + } + + // Accessors. + /// \return true iff this is a register-indirect location. + bool isIndirect() const { return !IsRegister; } + bool isReg() const { return IsRegister; } + unsigned getReg() const { return Register; } + void setIsRegister(bool Is) { IsRegister = Is; } + void setRegister(unsigned R) { Register = R; } +}; + +inline bool operator!=(const MachineLocation &LHS, const MachineLocation &RHS) { + return !(LHS == RHS); +} + +} // end namespace llvm + +#endif // LLVM_MC_MACHINELOCATION_H diff --git a/clang-r353983/include/llvm/MC/SectionKind.h b/clang-r353983/include/llvm/MC/SectionKind.h new file mode 100644 index 00000000..0342c4cf --- /dev/null +++ b/clang-r353983/include/llvm/MC/SectionKind.h @@ -0,0 +1,207 @@ +//===-- llvm/MC/SectionKind.h - Classification of sections ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_SECTIONKIND_H +#define LLVM_MC_SECTIONKIND_H + +namespace llvm { + +/// SectionKind - This is a simple POD value that classifies the properties of +/// a section. A section is classified into the deepest possible +/// classification, and then the target maps them onto their sections based on +/// what capabilities they have. +/// +/// The comments below describe these as if they were an inheritance hierarchy +/// in order to explain the predicates below. +/// +class SectionKind { + enum Kind { + /// Metadata - Debug info sections or other metadata. + Metadata, + + /// Text - Text section, used for functions and other executable code. + Text, + + /// ExecuteOnly, Text section that is not readable. + ExecuteOnly, + + /// ReadOnly - Data that is never written to at program runtime by the + /// program or the dynamic linker. Things in the top-level readonly + /// SectionKind are not mergeable. + ReadOnly, + + /// MergableCString - Any null-terminated string which allows merging. + /// These values are known to end in a nul value of the specified size, + /// not otherwise contain a nul value, and be mergable. This allows the + /// linker to unique the strings if it so desires. + + /// Mergeable1ByteCString - 1 byte mergable, null terminated, string. + Mergeable1ByteCString, + + /// Mergeable2ByteCString - 2 byte mergable, null terminated, string. + Mergeable2ByteCString, + + /// Mergeable4ByteCString - 4 byte mergable, null terminated, string. + Mergeable4ByteCString, + + /// MergeableConst - These are sections for merging fixed-length + /// constants together. For example, this can be used to unique + /// constant pool entries etc. + + /// MergeableConst4 - This is a section used by 4-byte constants, + /// for example, floats. + MergeableConst4, + + /// MergeableConst8 - This is a section used by 8-byte constants, + /// for example, doubles. + MergeableConst8, + + /// MergeableConst16 - This is a section used by 16-byte constants, + /// for example, vectors. + MergeableConst16, + + /// MergeableConst32 - This is a section used by 32-byte constants, + /// for example, vectors. + MergeableConst32, + + /// Writeable - This is the base of all segments that need to be written + /// to during program runtime. + + /// ThreadLocal - This is the base of all TLS segments. All TLS + /// objects must be writeable, otherwise there is no reason for them to + /// be thread local! + + /// ThreadBSS - Zero-initialized TLS data objects. + ThreadBSS, + + /// ThreadData - Initialized TLS data objects. + ThreadData, + + /// GlobalWriteableData - Writeable data that is global (not thread + /// local). + + /// BSS - Zero initialized writeable data. + BSS, + + /// BSSLocal - This is BSS (zero initialized and writable) data + /// which has local linkage. + BSSLocal, + + /// BSSExtern - This is BSS data with normal external linkage. + BSSExtern, + + /// Common - Data with common linkage. These represent tentative + /// definitions, which always have a zero initializer and are never + /// marked 'constant'. + Common, + + /// This is writeable data that has a non-zero initializer. + Data, + + /// ReadOnlyWithRel - These are global variables that are never + /// written to by the program, but that have relocations, so they + /// must be stuck in a writeable section so that the dynamic linker + /// can write to them. If it chooses to, the dynamic linker can + /// mark the pages these globals end up on as read-only after it is + /// done with its relocation phase. + ReadOnlyWithRel + } K : 8; +public: + + bool isMetadata() const { return K == Metadata; } + + bool isText() const { return K == Text || K == ExecuteOnly; } + + bool isExecuteOnly() const { return K == ExecuteOnly; } + + bool isReadOnly() const { + return K == ReadOnly || isMergeableCString() || + isMergeableConst(); + } + + bool isMergeableCString() const { + return K == Mergeable1ByteCString || K == Mergeable2ByteCString || + K == Mergeable4ByteCString; + } + bool isMergeable1ByteCString() const { return K == Mergeable1ByteCString; } + bool isMergeable2ByteCString() const { return K == Mergeable2ByteCString; } + bool isMergeable4ByteCString() const { return K == Mergeable4ByteCString; } + + bool isMergeableConst() const { + return K == MergeableConst4 || K == MergeableConst8 || + K == MergeableConst16 || K == MergeableConst32; + } + bool isMergeableConst4() const { return K == MergeableConst4; } + bool isMergeableConst8() const { return K == MergeableConst8; } + bool isMergeableConst16() const { return K == MergeableConst16; } + bool isMergeableConst32() const { return K == MergeableConst32; } + + bool isWriteable() const { + return isThreadLocal() || isGlobalWriteableData(); + } + + bool isThreadLocal() const { + return K == ThreadData || K == ThreadBSS; + } + + bool isThreadBSS() const { return K == ThreadBSS; } + bool isThreadData() const { return K == ThreadData; } + + bool isGlobalWriteableData() const { + return isBSS() || isCommon() || isData() || isReadOnlyWithRel(); + } + + bool isBSS() const { return K == BSS || K == BSSLocal || K == BSSExtern; } + bool isBSSLocal() const { return K == BSSLocal; } + bool isBSSExtern() const { return K == BSSExtern; } + + bool isCommon() const { return K == Common; } + + bool isData() const { return K == Data; } + + bool isReadOnlyWithRel() const { + return K == ReadOnlyWithRel; + } +private: + static SectionKind get(Kind K) { + SectionKind Res; + Res.K = K; + return Res; + } +public: + + static SectionKind getMetadata() { return get(Metadata); } + static SectionKind getText() { return get(Text); } + static SectionKind getExecuteOnly() { return get(ExecuteOnly); } + static SectionKind getReadOnly() { return get(ReadOnly); } + static SectionKind getMergeable1ByteCString() { + return get(Mergeable1ByteCString); + } + static SectionKind getMergeable2ByteCString() { + return get(Mergeable2ByteCString); + } + static SectionKind getMergeable4ByteCString() { + return get(Mergeable4ByteCString); + } + static SectionKind getMergeableConst4() { return get(MergeableConst4); } + static SectionKind getMergeableConst8() { return get(MergeableConst8); } + static SectionKind getMergeableConst16() { return get(MergeableConst16); } + static SectionKind getMergeableConst32() { return get(MergeableConst32); } + static SectionKind getThreadBSS() { return get(ThreadBSS); } + static SectionKind getThreadData() { return get(ThreadData); } + static SectionKind getBSS() { return get(BSS); } + static SectionKind getBSSLocal() { return get(BSSLocal); } + static SectionKind getBSSExtern() { return get(BSSExtern); } + static SectionKind getCommon() { return get(Common); } + static SectionKind getData() { return get(Data); } + static SectionKind getReadOnlyWithRel() { return get(ReadOnlyWithRel); } +}; + +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/MC/StringTableBuilder.h b/clang-r353983/include/llvm/MC/StringTableBuilder.h new file mode 100644 index 00000000..c83eca4e --- /dev/null +++ b/clang-r353983/include/llvm/MC/StringTableBuilder.h @@ -0,0 +1,74 @@ +//===- StringTableBuilder.h - String table building utility -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_STRINGTABLEBUILDER_H +#define LLVM_MC_STRINGTABLEBUILDER_H + +#include "llvm/ADT/CachedHashString.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include <cstddef> +#include <cstdint> + +namespace llvm { + +class raw_ostream; + +/// Utility for building string tables with deduplicated suffixes. +class StringTableBuilder { +public: + enum Kind { ELF, WinCOFF, MachO, RAW, DWARF }; + +private: + DenseMap<CachedHashStringRef, size_t> StringIndexMap; + size_t Size = 0; + Kind K; + unsigned Alignment; + bool Finalized = false; + + void finalizeStringTable(bool Optimize); + void initSize(); + +public: + StringTableBuilder(Kind K, unsigned Alignment = 1); + ~StringTableBuilder(); + + /// Add a string to the builder. Returns the position of S in the + /// table. The position will be changed if finalize is used. + /// Can only be used before the table is finalized. + size_t add(CachedHashStringRef S); + size_t add(StringRef S) { return add(CachedHashStringRef(S)); } + + /// Analyze the strings and build the final table. No more strings can + /// be added after this point. + void finalize(); + + /// Finalize the string table without reording it. In this mode, offsets + /// returned by add will still be valid. + void finalizeInOrder(); + + /// Get the offest of a string in the string table. Can only be used + /// after the table is finalized. + size_t getOffset(CachedHashStringRef S) const; + size_t getOffset(StringRef S) const { + return getOffset(CachedHashStringRef(S)); + } + + size_t getSize() const { return Size; } + void clear(); + + void write(raw_ostream &OS) const; + void write(uint8_t *Buf) const; + +private: + bool isFinalized() const { return Finalized; } +}; + +} // end namespace llvm + +#endif // LLVM_MC_STRINGTABLEBUILDER_H diff --git a/clang-r353983/include/llvm/MC/SubtargetFeature.h b/clang-r353983/include/llvm/MC/SubtargetFeature.h new file mode 100644 index 00000000..5f49d389 --- /dev/null +++ b/clang-r353983/include/llvm/MC/SubtargetFeature.h @@ -0,0 +1,132 @@ +//===- llvm/MC/SubtargetFeature.h - CPU characteristics ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file Defines and manages user or tool specified CPU characteristics. +/// The intent is to be able to package specific features that should or should +/// not be used on a specific target processor. A tool, such as llc, could, as +/// as example, gather chip info from the command line, a long with features +/// that should be used on that chip. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_SUBTARGETFEATURE_H +#define LLVM_MC_SUBTARGETFEATURE_H + +#include "llvm/ADT/StringRef.h" +#include <bitset> +#include <initializer_list> +#include <string> +#include <vector> + +namespace llvm { + +template <typename T> class ArrayRef; +class raw_ostream; +class Triple; + +const unsigned MAX_SUBTARGET_FEATURES = 192; +/// Container class for subtarget features. +/// This is convenient because std::bitset does not have a constructor +/// with an initializer list of set bits. +class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> { +public: + // Cannot inherit constructors because it's not supported by VC++.. + FeatureBitset() = default; + + FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {} + + FeatureBitset(std::initializer_list<unsigned> Init) { + for (auto I : Init) + set(I); + } +}; + +//===----------------------------------------------------------------------===// + +/// Used to provide key value pairs for feature and CPU bit flags. +struct SubtargetFeatureKV { + const char *Key; ///< K-V key string + const char *Desc; ///< Help descriptor + FeatureBitset Value; ///< K-V integer value + FeatureBitset Implies; ///< K-V bit mask + + /// Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; + } + + /// Compare routine for std::is_sorted. + bool operator<(const SubtargetFeatureKV &Other) const { + return StringRef(Key) < StringRef(Other.Key); + } +}; + +//===----------------------------------------------------------------------===// + +/// Used to provide key value pairs for CPU and arbitrary pointers. +struct SubtargetInfoKV { + const char *Key; ///< K-V key string + const void *Value; ///< K-V pointer value + + /// Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; + } +}; + +//===----------------------------------------------------------------------===// + +/// Manages the enabling and disabling of subtarget specific features. +/// +/// Features are encoded as a string of the form +/// "+attr1,+attr2,-attr3,...,+attrN" +/// A comma separates each feature from the next (all lowercase.) +/// Each of the remaining features is prefixed with + or - indicating whether +/// that feature should be enabled or disabled contrary to the cpu +/// specification. +class SubtargetFeatures { + std::vector<std::string> Features; ///< Subtarget features as a vector + +public: + explicit SubtargetFeatures(StringRef Initial = ""); + + /// Returns features as a string. + std::string getString() const; + + /// Adds Features. + void AddFeature(StringRef String, bool Enable = true); + + /// Toggles a feature and update the feature bits. + static void ToggleFeature(FeatureBitset &Bits, StringRef String, + ArrayRef<SubtargetFeatureKV> FeatureTable); + + /// Applies the feature flag and update the feature bits. + static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, + ArrayRef<SubtargetFeatureKV> FeatureTable); + + /// Returns feature bits of a CPU. + FeatureBitset getFeatureBits(StringRef CPU, + ArrayRef<SubtargetFeatureKV> CPUTable, + ArrayRef<SubtargetFeatureKV> FeatureTable); + + /// Returns the vector of individual subtarget features. + const std::vector<std::string> &getFeatures() const { return Features; } + + /// Prints feature string. + void print(raw_ostream &OS) const; + + // Dumps feature info. + void dump() const; + + /// Adds the default features for the specified target triple. + void getDefaultSubtargetFeatures(const Triple& Triple); +}; + +} // end namespace llvm + +#endif // LLVM_MC_SUBTARGETFEATURE_H |
