aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/MC
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/MC')
-rw-r--r--include/llvm/MC/MCAsmInfo.h18
-rw-r--r--include/llvm/MC/MCAsmInfoXCOFF.h5
-rw-r--r--include/llvm/MC/MCAsmMacro.h11
-rw-r--r--include/llvm/MC/MCContext.h23
-rw-r--r--include/llvm/MC/MCDirectives.h1
-rw-r--r--include/llvm/MC/MCDwarf.h3
-rw-r--r--include/llvm/MC/MCExpr.h8
-rw-r--r--include/llvm/MC/MCFixup.h119
-rw-r--r--include/llvm/MC/MCFragment.h16
-rw-r--r--include/llvm/MC/MCInstPrinter.h2
-rw-r--r--include/llvm/MC/MCInstrAnalysis.h6
-rw-r--r--include/llvm/MC/MCInstrDesc.h23
-rw-r--r--include/llvm/MC/MCLinkerOptimizationHint.h2
-rw-r--r--include/llvm/MC/MCRegister.h110
-rw-r--r--include/llvm/MC/MCRegisterInfo.h98
-rw-r--r--include/llvm/MC/MCSection.h7
-rw-r--r--include/llvm/MC/MCSectionXCOFF.h22
-rw-r--r--include/llvm/MC/MCStreamer.h41
-rw-r--r--include/llvm/MC/MCSubtargetInfo.h46
-rw-r--r--include/llvm/MC/MCSymbolWasm.h7
-rw-r--r--include/llvm/MC/MCSymbolXCOFF.h32
-rw-r--r--include/llvm/MC/MCWasmObjectWriter.h4
-rw-r--r--include/llvm/MC/MCXCOFFStreamer.h2
-rw-r--r--include/llvm/MC/StringTableBuilder.h2
-rw-r--r--include/llvm/MC/SubtargetFeature.h139
25 files changed, 590 insertions, 157 deletions
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index 971e9354da8c..3261c483e0d8 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/include/llvm/MC/MCAsmInfo.h
@@ -165,6 +165,10 @@ protected:
/// instead.
bool UseDataRegionDirectives = false;
+ /// True if .align is to be used for alignment. Only power-of-two
+ /// alignment is supported.
+ bool UseDotAlignForAlignment = false;
+
//===--- Data Emission Directives -------------------------------------===//
/// This should be set to the directive used to get some number of zero bytes
@@ -313,6 +317,10 @@ protected:
/// Defaults to false.
bool HasLinkOnceDirective = false;
+ /// True if we have a .lglobl directive, which is used to emit the information
+ /// of a static symbol into the symbol table. Defaults to false.
+ bool HasDotLGloblDirective = 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;
@@ -388,6 +396,9 @@ protected:
// %hi(), and similar unary operators.
bool HasMipsExpressions = false;
+ // If true, emit function descriptor symbol on AIX.
+ bool NeedsFunctionDescriptors = false;
+
public:
explicit MCAsmInfo();
virtual ~MCAsmInfo();
@@ -520,6 +531,10 @@ public:
return UseDataRegionDirectives;
}
+ bool useDotAlignForAlignment() const {
+ return UseDotAlignForAlignment;
+ }
+
const char *getZeroDirective() const { return ZeroDirective; }
const char *getAsciiDirective() const { return AsciiDirective; }
const char *getAscizDirective() const { return AscizDirective; }
@@ -557,6 +572,8 @@ public:
bool hasLinkOnceDirective() const { return HasLinkOnceDirective; }
+ bool hasDotLGloblDirective() const { return HasDotLGloblDirective; }
+
MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr; }
MCSymbolAttr getHiddenDeclarationVisibilityAttr() const {
@@ -639,6 +656,7 @@ public:
bool canRelaxRelocations() const { return RelaxELFRelocations; }
void setRelaxELFRelocations(bool V) { RelaxELFRelocations = V; }
bool hasMipsExpressions() const { return HasMipsExpressions; }
+ bool needsFunctionDescriptors() const { return NeedsFunctionDescriptors; }
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCAsmInfoXCOFF.h b/include/llvm/MC/MCAsmInfoXCOFF.h
index 2a72ba7398a7..4a3bacc954e0 100644
--- a/include/llvm/MC/MCAsmInfoXCOFF.h
+++ b/include/llvm/MC/MCAsmInfoXCOFF.h
@@ -18,6 +18,11 @@ class MCAsmInfoXCOFF : public MCAsmInfo {
protected:
MCAsmInfoXCOFF();
+
+public:
+ // Return true only when the identifier Name does not need quotes to be
+ // syntactically correct for XCOFF.
+ bool isValidUnquotedName(StringRef Name) const override;
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCAsmMacro.h b/include/llvm/MC/MCAsmMacro.h
index 364d3b5f3666..7eecce0faf64 100644
--- a/include/llvm/MC/MCAsmMacro.h
+++ b/include/llvm/MC/MCAsmMacro.h
@@ -124,7 +124,6 @@ public:
}
void dump(raw_ostream &OS) const;
- void dump() const { dump(dbgs()); }
};
struct MCAsmMacroParameter {
@@ -133,10 +132,10 @@ struct MCAsmMacroParameter {
bool Required = false;
bool Vararg = false;
- MCAsmMacroParameter() = default;
-
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void dump() const { dump(dbgs()); }
- void dump(raw_ostream &OS) const;
+ LLVM_DUMP_METHOD void dump(raw_ostream &OS) const;
+#endif
};
typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters;
@@ -149,8 +148,10 @@ public:
MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P)
: Name(N), Body(B), Parameters(std::move(P)) {}
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void dump() const { dump(dbgs()); }
- void dump(raw_ostream &OS) const;
+ LLVM_DUMP_METHOD void dump(raw_ostream &OS) const;
+#endif
};
} // namespace llvm
diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h
index 5c2124cc0d15..b925f3218883 100644
--- a/include/llvm/MC/MCContext.h
+++ b/include/llvm/MC/MCContext.h
@@ -22,6 +22,7 @@
#include "llvm/MC/MCAsmMacro.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
@@ -112,6 +113,9 @@ namespace llvm {
/// number of section symbols with the same name).
StringMap<bool, BumpPtrAllocator &> UsedNames;
+ /// Keeps track of labels that are used in inline assembly.
+ SymbolTable InlineAsmUsedLabelNames;
+
/// The next ID to dole out to an unnamed assembler temporary symbol with
/// a given prefix.
StringMap<unsigned> NextID;
@@ -275,6 +279,8 @@ namespace llvm {
/// Do automatic reset in destructor
bool AutoReset;
+ MCTargetOptions const *TargetOptions;
+
bool HadError = false;
MCSymbol *createSymbolImpl(const StringMapEntry<bool> *Name,
@@ -298,7 +304,9 @@ namespace llvm {
public:
explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI,
const MCObjectFileInfo *MOFI,
- const SourceMgr *Mgr = nullptr, bool DoAutoReset = true);
+ const SourceMgr *Mgr = nullptr,
+ MCTargetOptions const *TargetOpts = nullptr,
+ bool DoAutoReset = true);
MCContext(const MCContext &) = delete;
MCContext &operator=(const MCContext &) = delete;
~MCContext();
@@ -377,6 +385,16 @@ namespace llvm {
/// APIs.
const SymbolTable &getSymbols() const { return Symbols; }
+ /// isInlineAsmLabel - Return true if the name is a label referenced in
+ /// inline assembly.
+ MCSymbol *getInlineAsmLabel(StringRef Name) const {
+ return InlineAsmUsedLabelNames.lookup(Name);
+ }
+
+ /// registerInlineAsmLabel - Records that the name is a label referenced in
+ /// inline assembly.
+ void registerInlineAsmLabel(MCSymbol *Sym);
+
/// @}
/// \name Section Management
@@ -490,6 +508,8 @@ namespace llvm {
MCSectionXCOFF *getXCOFFSection(StringRef Section,
XCOFF::StorageMappingClass MappingClass,
+ XCOFF::SymbolType CSectType,
+ XCOFF::StorageClass StorageClass,
SectionKind K,
const char *BeginSymName = nullptr);
@@ -659,6 +679,7 @@ namespace llvm {
bool hadError() { return HadError; }
void reportError(SMLoc L, const Twine &Msg);
+ void reportWarning(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.
diff --git a/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h
index 4029264c2026..ea79e68674e5 100644
--- a/include/llvm/MC/MCDirectives.h
+++ b/include/llvm/MC/MCDirectives.h
@@ -28,6 +28,7 @@ enum MCSymbolAttr {
MCSA_ELF_TypeNoType, ///< .type _foo, STT_NOTYPE # aka @notype
MCSA_ELF_TypeGnuUniqueObject, /// .type _foo, @gnu_unique_object
MCSA_Global, ///< .globl
+ MCSA_LGlobal, ///< .lglobl (XCOFF)
MCSA_Hidden, ///< .hidden (ELF)
MCSA_IndirectSymbol, ///< .indirect_symbol (MachO)
MCSA_Internal, ///< .internal (ELF)
diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h
index 1a37aafd0654..a33b4b31bb06 100644
--- a/include/llvm/MC/MCDwarf.h
+++ b/include/llvm/MC/MCDwarf.h
@@ -629,7 +629,8 @@ public:
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);
+ raw_ostream &OS, uint32_t *Offset = nullptr,
+ uint32_t *Size = nullptr);
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h
index fb23c0114c76..eb2786501f84 100644
--- a/include/llvm/MC/MCExpr.h
+++ b/include/llvm/MC/MCExpr.h
@@ -48,10 +48,6 @@ private:
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:
@@ -136,7 +132,7 @@ class MCConstantExpr : public MCExpr {
int64_t Value;
bool PrintInHex = false;
- MCConstantExpr(int64_t Value)
+ explicit MCConstantExpr(int64_t Value)
: MCExpr(MCExpr::Constant, SMLoc()), Value(Value) {}
MCConstantExpr(int64_t Value, bool PrintInHex)
@@ -239,6 +235,8 @@ public:
VK_PPC_TOC_LO, // symbol@toc@l
VK_PPC_TOC_HI, // symbol@toc@h
VK_PPC_TOC_HA, // symbol@toc@ha
+ VK_PPC_U, // symbol@u
+ VK_PPC_L, // symbol@l
VK_PPC_DTPMOD, // symbol@dtpmod
VK_PPC_TPREL_LO, // symbol@tprel@l
VK_PPC_TPREL_HI, // symbol@tprel@h
diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h
index accffb7f2247..29e321e2354c 100644
--- a/include/llvm/MC/MCFixup.h
+++ b/include/llvm/MC/MCFixup.h
@@ -20,35 +20,38 @@ class MCExpr;
/// Extensible enumeration to represent the type of a fixup.
enum MCFixupKind {
- FK_NONE = 0, ///< A no-op fixup.
- FK_Data_1, ///< 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.
+ FK_NONE = 0, ///< A no-op fixup.
+ FK_Data_1, ///< 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_Data_6b, ///< A six-bits 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_Add_6b, ///< A six-bits 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.
+ FK_Data_Sub_6b, ///< A six-bits sub fixup.
FirstTargetFixupKind = 128,
@@ -75,25 +78,25 @@ 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;
+ const MCExpr *Value = nullptr;
/// The byte index of start of the relocation inside the MCFragment.
- uint32_t Offset;
+ uint32_t Offset = 0;
/// 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;
+ MCFixupKind Kind = FK_NONE;
/// 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!");
+ assert(Kind < MaxTargetFixupKind && "Kind out of range!");
MCFixup FI;
FI.Value = Value;
FI.Offset = Offset;
- FI.Kind = unsigned(Kind);
+ FI.Kind = Kind;
FI.Loc = Loc;
return FI;
}
@@ -104,7 +107,7 @@ public:
MCFixup FI;
FI.Value = Fixup.getValue();
FI.Offset = Fixup.getOffset();
- FI.Kind = (unsigned)getAddKindForKind(Fixup.getKind());
+ FI.Kind = getAddKindForKind(Fixup.getKind());
FI.Loc = Fixup.getLoc();
return FI;
}
@@ -115,12 +118,14 @@ public:
MCFixup FI;
FI.Value = Fixup.getValue();
FI.Offset = Fixup.getOffset();
- FI.Kind = (unsigned)getSubKindForKind(Fixup.getKind());
+ FI.Kind = getSubKindForKind(Fixup.getKind());
FI.Loc = Fixup.getLoc();
return FI;
}
- MCFixupKind getKind() const { return MCFixupKind(Kind); }
+ MCFixupKind getKind() const { return Kind; }
+
+ unsigned getTargetKind() const { return Kind; }
uint32_t getOffset() const { return Offset; }
void setOffset(uint32_t Value) { Offset = Value; }
@@ -129,37 +134,63 @@ public:
/// 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) {
+ 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;
+ 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 a value with the given size in bits.
+ /// It is an error to pass an unsupported size.
+ static MCFixupKind getKindForSizeInBits(unsigned Size, bool IsPCRel) {
+ switch (Size) {
+ default:
+ llvm_unreachable("Invalid generic fixup size!");
+ case 6:
+ assert(!IsPCRel && "Invalid pc-relative fixup size!");
+ return FK_Data_6b;
+ case 8:
+ return IsPCRel ? FK_PCRel_1 : FK_Data_1;
+ case 16:
+ return IsPCRel ? FK_PCRel_2 : FK_Data_2;
+ case 32:
+ return IsPCRel ? FK_PCRel_4 : FK_Data_4;
+ case 64:
+ 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) {
+ static MCFixupKind getAddKindForKind(MCFixupKind 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;
+ case FK_Data_6b: return FK_Data_Add_6b;
}
}
/// 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) {
+ static MCFixupKind getSubKindForKind(MCFixupKind 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;
+ case FK_Data_6b: return FK_Data_Sub_6b;
}
}
diff --git a/include/llvm/MC/MCFragment.h b/include/llvm/MC/MCFragment.h
index aadf2ce725ea..b0def566c46a 100644
--- a/include/llvm/MC/MCFragment.h
+++ b/include/llvm/MC/MCFragment.h
@@ -149,6 +149,7 @@ public:
case MCFragment::FT_CompactEncodedInst:
case MCFragment::FT_Data:
case MCFragment::FT_Dwarf:
+ case MCFragment::FT_DwarfFrame:
return true;
}
}
@@ -232,7 +233,8 @@ public:
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;;
+ Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
+ Kind == MCFragment::FT_DwarfFrame;
}
};
@@ -543,27 +545,21 @@ public:
}
};
-class MCDwarfCallFrameFragment : public MCFragment {
+class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
/// 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);
- }
+ : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec),
+ AddrDelta(&AddrDelta) {}
/// \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) {
diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h
index 6bbc4bc2903b..4501ce3084c8 100644
--- a/include/llvm/MC/MCInstPrinter.h
+++ b/include/llvm/MC/MCInstPrinter.h
@@ -87,12 +87,10 @@ public:
/// 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.
diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h
index dfefd7e72777..898ca47b13b8 100644
--- a/include/llvm/MC/MCInstrAnalysis.h
+++ b/include/llvm/MC/MCInstrAnalysis.h
@@ -152,6 +152,12 @@ public:
evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const;
+ /// Given an instruction tries to get the address of a memory operand. Returns
+ /// the address on success.
+ virtual Optional<uint64_t> evaluateMemoryOperandAddress(const MCInst &Inst,
+ uint64_t Addr,
+ uint64_t Size) 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,
diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h
index 0aa586dfc901..e75a27614a22 100644
--- a/include/llvm/MC/MCInstrDesc.h
+++ b/include/llvm/MC/MCInstrDesc.h
@@ -56,7 +56,11 @@ enum OperandType {
OPERAND_GENERIC_5 = 11,
OPERAND_LAST_GENERIC = 11,
- OPERAND_FIRST_TARGET = 12,
+ OPERAND_FIRST_GENERIC_IMM = 12,
+ OPERAND_GENERIC_IMM_0 = 12,
+ OPERAND_LAST_GENERIC_IMM = 12,
+
+ OPERAND_FIRST_TARGET = 13,
};
}
@@ -103,6 +107,16 @@ public:
assert(isGenericType() && "non-generic types don't have an index");
return OperandType - MCOI::OPERAND_FIRST_GENERIC;
}
+
+ bool isGenericImm() const {
+ return OperandType >= MCOI::OPERAND_FIRST_GENERIC_IMM &&
+ OperandType <= MCOI::OPERAND_LAST_GENERIC_IMM;
+ }
+
+ unsigned getGenericImmIndex() const {
+ assert(isGenericImm() && "non-generic immediates don't have an index");
+ return OperandType - MCOI::OPERAND_FIRST_GENERIC_IMM;
+ }
};
//===----------------------------------------------------------------------===//
@@ -115,7 +129,8 @@ namespace MCID {
/// not use these directly. These all correspond to bitfields in the
/// MCInstrDesc::Flags field.
enum Flag {
- Variadic = 0,
+ PreISelOpcode = 0,
+ Variadic,
HasOptionalDef,
Pseudo,
Return,
@@ -228,6 +243,10 @@ public:
/// Return flags of this instruction.
uint64_t getFlags() const { return Flags; }
+ /// \returns true if this instruction is emitted before instruction selection
+ /// and should be legalized/regbankselected/selected.
+ bool isPreISelOpcode() const { return Flags & (1ULL << MCID::PreISelOpcode); }
+
/// 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
diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h
index f2a1364ad884..003491f32f75 100644
--- a/include/llvm/MC/MCLinkerOptimizationHint.h
+++ b/include/llvm/MC/MCLinkerOptimizationHint.h
@@ -61,6 +61,7 @@ static inline int MCLOHNameToId(StringRef Name) {
MCLOHCaseNameToId(AdrpAdd)
MCLOHCaseNameToId(AdrpLdrGot)
.Default(-1);
+#undef MCLOHCaseNameToId
}
static inline StringRef MCLOHIdToName(MCLOHType Kind) {
@@ -76,6 +77,7 @@ static inline StringRef MCLOHIdToName(MCLOHType Kind) {
MCLOHCaseIdToName(AdrpLdrGot);
}
return StringRef();
+#undef MCLOHCaseIdToName
}
static inline int MCLOHIdToNbArgs(MCLOHType Kind) {
diff --git a/include/llvm/MC/MCRegister.h b/include/llvm/MC/MCRegister.h
new file mode 100644
index 000000000000..8372947a4ba1
--- /dev/null
+++ b/include/llvm/MC/MCRegister.h
@@ -0,0 +1,110 @@
+//===-- llvm/MC/Register.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_REGISTER_H
+#define LLVM_MC_REGISTER_H
+
+#include "llvm/ADT/DenseMapInfo.h"
+#include <cassert>
+
+namespace llvm {
+
+/// An unsigned integer type large enough to represent all physical registers,
+/// but not necessarily virtual registers.
+using MCPhysReg = uint16_t;
+
+/// Wrapper class representing physical registers. Should be passed by value.
+class MCRegister {
+ unsigned Reg;
+
+public:
+ MCRegister(unsigned Val = 0): Reg(Val) {}
+
+ // Register numbers can represent physical registers, virtual registers, and
+ // sometimes stack slots. The unsigned values are divided into these ranges:
+ //
+ // 0 Not a register, can be used as a sentinel.
+ // [1;2^30) Physical registers assigned by TableGen.
+ // [2^30;2^31) Stack slots. (Rarely used.)
+ // [2^31;2^32) Virtual registers assigned by MachineRegisterInfo.
+ //
+ // Further sentinels can be allocated from the small negative integers.
+ // DenseMapInfo<unsigned> uses -1u and -2u.
+
+ /// This is the portion of the positive number space that is not a physical
+ /// register. StackSlot values do not exist in the MC layer, see
+ /// Register::isStackSlot() for the more information on them.
+ ///
+ /// Note that isVirtualRegister() and isPhysicalRegister() cannot handle stack
+ /// slots, so if a variable may contains a stack slot, always check
+ /// isStackSlot() first.
+ static bool isStackSlot(unsigned Reg) {
+ return int(Reg) >= (1 << 30);
+ }
+
+ /// Return true if the specified register number is in
+ /// the physical register namespace.
+ static bool isPhysicalRegister(unsigned Reg) {
+ assert(!isStackSlot(Reg) && "Not a register! Check isStackSlot() first.");
+ return int(Reg) > 0;
+ }
+
+ /// Return true if the specified register number is in the physical register
+ /// namespace.
+ bool isPhysical() const {
+ return isPhysicalRegister(Reg);
+ }
+
+ operator unsigned() const {
+ return Reg;
+ }
+
+ unsigned id() const {
+ return Reg;
+ }
+
+ bool isValid() const {
+ return Reg != 0;
+ }
+
+ /// Comparisons between register objects
+ bool operator==(const MCRegister &Other) const { return Reg == Other.Reg; }
+ bool operator!=(const MCRegister &Other) const { return Reg != Other.Reg; }
+
+ /// Comparisons against register constants. E.g.
+ /// * R == AArch64::WZR
+ /// * R == 0
+ /// * R == VirtRegMap::NO_PHYS_REG
+ bool operator==(unsigned Other) const { return Reg == Other; }
+ bool operator!=(unsigned Other) const { return Reg != Other; }
+ bool operator==(int Other) const { return Reg == unsigned(Other); }
+ bool operator!=(int Other) const { return Reg != unsigned(Other); }
+ // MSVC requires that we explicitly declare these two as well.
+ bool operator==(MCPhysReg Other) const { return Reg == unsigned(Other); }
+ bool operator!=(MCPhysReg Other) const { return Reg != unsigned(Other); }
+};
+
+// Provide DenseMapInfo for MCRegister
+template<> struct DenseMapInfo<MCRegister> {
+ static inline unsigned getEmptyKey() {
+ return DenseMapInfo<unsigned>::getEmptyKey();
+ }
+ static inline unsigned getTombstoneKey() {
+ return DenseMapInfo<unsigned>::getTombstoneKey();
+ }
+ static unsigned getHashValue(const MCRegister &Val) {
+ return DenseMapInfo<unsigned>::getHashValue(Val.id());
+ }
+ static bool isEqual(const MCRegister &LHS, const MCRegister &RHS) {
+ return DenseMapInfo<unsigned>::isEqual(LHS.id(), RHS.id());
+ }
+};
+
+}
+
+#endif // ifndef LLVM_MC_REGISTER_H
diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h
index 92d39c3fcfb7..c7dc56ea588e 100644
--- a/include/llvm/MC/MCRegisterInfo.h
+++ b/include/llvm/MC/MCRegisterInfo.h
@@ -18,16 +18,13 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/MC/LaneBitmask.h"
+#include "llvm/MC/MCRegister.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:
@@ -65,16 +62,17 @@ public:
/// 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;
+ bool contains(MCRegister Reg) const {
+ unsigned RegNo = unsigned(Reg);
+ unsigned InByte = RegNo % 8;
+ unsigned Byte = RegNo / 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 {
+ bool contains(MCRegister Reg1, MCRegister Reg2) const {
return contains(Reg1) && contains(Reg2);
}
@@ -148,8 +146,8 @@ public:
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
+ MCRegister RAReg; // Return address register
+ MCRegister 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.
@@ -175,8 +173,8 @@ private:
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
+ DenseMap<MCRegister, int> L2SEHRegs; // LLVM to SEH regs mapping
+ DenseMap<MCRegister, int> L2CVRegs; // LLVM to CV regs mapping
public:
/// DiffListIterator - Base iterator class that can traverse the
@@ -202,7 +200,7 @@ public:
/// 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() {
+ MCRegister advance() {
assert(isValid() && "Cannot move off the end of the list.");
MCPhysReg D = *List++;
Val += D;
@@ -214,7 +212,7 @@ public:
bool isValid() const { return List; }
/// Dereference the iterator to get the value at the current position.
- unsigned operator*() const { return Val; }
+ MCRegister operator*() const { return Val; }
/// Pre-increment to move to the next position.
void operator++() {
@@ -309,26 +307,26 @@ public:
/// as the LLVM register number.
/// FIXME: TableGen these numbers. Currently this requires target specific
/// initialization code.
- void mapLLVMRegToSEHReg(unsigned LLVMReg, int SEHReg) {
+ void mapLLVMRegToSEHReg(MCRegister LLVMReg, int SEHReg) {
L2SEHRegs[LLVMReg] = SEHReg;
}
- void mapLLVMRegToCVReg(unsigned LLVMReg, int CVReg) {
+ void mapLLVMRegToCVReg(MCRegister LLVMReg, int CVReg) {
L2CVRegs[LLVMReg] = CVReg;
}
/// This method should return the register where the return
/// address can be found.
- unsigned getRARegister() const {
+ MCRegister getRARegister() const {
return RAReg;
}
/// Return the register which is the program counter.
- unsigned getProgramCounter() const {
+ MCRegister getProgramCounter() const {
return PCReg;
}
- const MCRegisterDesc &operator[](unsigned RegNo) const {
+ const MCRegisterDesc &operator[](MCRegister RegNo) const {
assert(RegNo < NumRegs &&
"Attempting to access record for invalid register number!");
return Desc[RegNo];
@@ -336,24 +334,24 @@ public:
/// Provide a get method, equivalent to [], but more useful with a
/// pointer to this object.
- const MCRegisterDesc &get(unsigned RegNo) const {
+ const MCRegisterDesc &get(MCRegister 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;
+ MCRegister getSubReg(MCRegister 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;
+ MCRegister getMatchingSuperReg(MCRegister 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;
+ unsigned getSubRegIndex(MCRegister RegNo, MCRegister 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.
@@ -367,7 +365,7 @@ public:
/// Return the human-readable symbolic target-specific name for the
/// specified physical register.
- const char *getName(unsigned RegNo) const {
+ const char *getName(MCRegister RegNo) const {
return RegStrings + get(RegNo).Name;
}
@@ -395,15 +393,11 @@ public:
/// 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;
+ int getDwarfRegNum(MCRegister 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 dwarf register back to a target register. Returns None is there is
+ /// no mapping.
+ Optional<unsigned> getLLVMRegNum(unsigned RegNum, bool isEH) const;
/// Map a target EH register number to an equivalent DWARF register
/// number.
@@ -411,11 +405,11 @@ public:
/// 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;
+ int getSEHRegNum(MCRegister RegNum) const;
/// Map a target register to an equivalent CodeView register
/// number.
- int getCodeViewRegNum(unsigned RegNum) const;
+ int getCodeViewRegNum(MCRegister RegNum) const;
regclass_iterator regclass_begin() const { return Classes; }
regclass_iterator regclass_end() const { return Classes+NumClasses; }
@@ -439,34 +433,34 @@ public:
}
/// Returns the encoding for RegNo
- uint16_t getEncodingValue(unsigned RegNo) const {
+ uint16_t getEncodingValue(MCRegister 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 {
+ bool isSubRegister(MCRegister RegA, MCRegister RegB) const {
return isSuperRegister(RegB, RegA);
}
/// Returns true if RegB is a super-register of RegA.
- bool isSuperRegister(unsigned RegA, unsigned RegB) const;
+ bool isSuperRegister(MCRegister RegA, MCRegister RegB) const;
/// Returns true if RegB is a sub-register of RegA or if RegB == RegA.
- bool isSubRegisterEq(unsigned RegA, unsigned RegB) const {
+ bool isSubRegisterEq(MCRegister RegA, MCRegister 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 {
+ bool isSuperRegisterEq(MCRegister RegA, MCRegister 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 {
+ bool isSuperOrSubRegisterEq(MCRegister RegA, MCRegister RegB) const {
return isSubRegisterEq(RegA, RegB) || isSuperRegister(RegA, RegB);
}
};
@@ -482,8 +476,8 @@ public:
/// 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) {
+ MCSubRegIterator(MCRegister Reg, const MCRegisterInfo *MCRI,
+ bool IncludeSelf = false) {
init(Reg, MCRI->DiffLists + MCRI->get(Reg).SubRegs);
// Initially, the iterator points to Reg itself.
if (!IncludeSelf)
@@ -500,13 +494,13 @@ class MCSubRegIndexIterator {
public:
/// Constructs an iterator that traverses subregisters and their
/// associated subregister indices.
- MCSubRegIndexIterator(unsigned Reg, const MCRegisterInfo *MCRI)
+ MCSubRegIndexIterator(MCRegister Reg, const MCRegisterInfo *MCRI)
: SRIter(Reg, MCRI) {
SRIndex = MCRI->SubRegIndices + MCRI->get(Reg).SubRegIndices;
}
/// Returns current sub-register.
- unsigned getSubReg() const {
+ MCRegister getSubReg() const {
return *SRIter;
}
@@ -531,7 +525,7 @@ class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator {
public:
MCSuperRegIterator() = default;
- MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI,
+ MCSuperRegIterator(MCRegister Reg, const MCRegisterInfo *MCRI,
bool IncludeSelf = false) {
init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs);
// Initially, the iterator points to Reg itself.
@@ -542,7 +536,7 @@ public:
// 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{
+inline bool MCRegisterInfo::isSuperRegister(MCRegister RegA, MCRegister RegB) const{
for (MCSuperRegIterator I(RegA, this); I.isValid(); ++I)
if (*I == RegB)
return true;
@@ -569,7 +563,7 @@ public:
/// in Reg.
MCRegUnitIterator() = default;
- MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) {
+ MCRegUnitIterator(MCRegister Reg, const MCRegisterInfo *MCRI) {
assert(Reg && "Null register has no regunits");
// Decode the RegUnits MCRegisterDesc field.
unsigned RU = MCRI->get(Reg).RegUnits;
@@ -600,7 +594,7 @@ public:
/// Constructs an iterator that traverses the register units and their
/// associated LaneMasks in Reg.
- MCRegUnitMaskIterator(unsigned Reg, const MCRegisterInfo *MCRI)
+ MCRegUnitMaskIterator(MCRegister Reg, const MCRegisterInfo *MCRI)
: RUIter(Reg, MCRI) {
uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks;
MaskListIter = &MCRI->RegUnitMaskSequences[Idx];
@@ -667,7 +661,7 @@ public:
/// any ordering or that entries are unique.
class MCRegAliasIterator {
private:
- unsigned Reg;
+ MCRegister Reg;
const MCRegisterInfo *MCRI;
bool IncludeSelf;
@@ -676,7 +670,7 @@ private:
MCSuperRegIterator SI;
public:
- MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI,
+ MCRegAliasIterator(MCRegister Reg, const MCRegisterInfo *MCRI,
bool IncludeSelf)
: Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) {
// Initialize the iterators.
@@ -692,7 +686,7 @@ public:
bool isValid() const { return RI.isValid(); }
- unsigned operator*() const {
+ MCRegister operator*() const {
assert(SI.isValid() && "Cannot dereference an invalid iterator.");
return *SI;
}
diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h
index 6fad1ec2069c..d057feda87d8 100644
--- a/include/llvm/MC/MCSection.h
+++ b/include/llvm/MC/MCSection.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/ilist.h"
#include "llvm/MC/MCFragment.h"
#include "llvm/MC/SectionKind.h"
+#include "llvm/Support/Alignment.h"
#include <cassert>
#include <utility>
@@ -58,7 +59,7 @@ private:
MCSymbol *Begin;
MCSymbol *End = nullptr;
/// The alignment requirement of this section.
- unsigned Alignment = 1;
+ Align Alignment;
/// The section index in the assemblers section list.
unsigned Ordinal = 0;
/// The index of this section in the layout order.
@@ -117,8 +118,8 @@ public:
MCSymbol *getEndSymbol(MCContext &Ctx);
bool hasEnded() const;
- unsigned getAlignment() const { return Alignment; }
- void setAlignment(unsigned Value) { Alignment = Value; }
+ unsigned getAlignment() const { return Alignment.value(); }
+ void setAlignment(Align Value) { Alignment = Value; }
unsigned getOrdinal() const { return Ordinal; }
void setOrdinal(unsigned Value) { Ordinal = Value; }
diff --git a/include/llvm/MC/MCSectionXCOFF.h b/include/llvm/MC/MCSectionXCOFF.h
index 2a3f391fd3e2..ee302ed5ecec 100644
--- a/include/llvm/MC/MCSectionXCOFF.h
+++ b/include/llvm/MC/MCSectionXCOFF.h
@@ -23,16 +23,30 @@ class MCSymbol;
// This class represents an XCOFF `Control Section`, more commonly referred to
// as a csect. A csect represents the smallest possible unit of data/code which
-// will be relocated as a single block.
+// will be relocated as a single block. A csect can either be:
+// 1) Initialized: The Type will be XTY_SD, and the symbols inside the csect
+// will have a label definition representing their offset within the csect.
+// 2) Uninitialized: The Type will be XTY_CM, it will contain a single symbol,
+// and may not contain label definitions.
+// 3) An external reference providing a symbol table entry for a symbol
+// contained in another XCOFF object file. External reference csects are not
+// implemented yet.
class MCSectionXCOFF final : public MCSection {
friend class MCContext;
StringRef Name;
XCOFF::StorageMappingClass MappingClass;
+ XCOFF::SymbolType Type;
+ XCOFF::StorageClass StorageClass;
MCSectionXCOFF(StringRef Section, XCOFF::StorageMappingClass SMC,
- SectionKind K, MCSymbol *Begin)
- : MCSection(SV_XCOFF, K, Begin), Name(Section), MappingClass(SMC) {}
+ XCOFF::SymbolType ST, XCOFF::StorageClass SC, SectionKind K,
+ MCSymbol *Begin)
+ : MCSection(SV_XCOFF, K, Begin), Name(Section), MappingClass(SMC),
+ Type(ST), StorageClass(SC) {
+ assert((ST == XCOFF::XTY_SD || ST == XCOFF::XTY_CM) &&
+ "Invalid or unhandled type for csect.");
+ }
public:
~MCSectionXCOFF();
@@ -43,6 +57,8 @@ public:
StringRef getSectionName() const { return Name; }
XCOFF::StorageMappingClass getMappingClass() const { return MappingClass; }
+ XCOFF::StorageClass getStorageClass() const { return StorageClass; }
+ XCOFF::SymbolType getCSectType() const { return Type; }
void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
raw_ostream &OS,
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 731e7515448c..6b48580ae57c 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -46,6 +46,7 @@ struct MCDwarfFrameInfo;
class MCExpr;
class MCInst;
class MCInstPrinter;
+class MCRegister;
class MCSection;
class MCStreamer;
class MCSymbolRefExpr;
@@ -53,6 +54,13 @@ class MCSubtargetInfo;
class raw_ostream;
class Twine;
+namespace codeview {
+struct DefRangeRegisterRelHeader;
+struct DefRangeSubfieldRegisterHeader;
+struct DefRangeRegisterHeader;
+struct DefRangeFramePointerRelHeader;
+}
+
using MCSectionSubPair = std::pair<MCSection *, const MCExpr *>;
/// Target specific streamer interface. This is used so that targets can
@@ -536,6 +544,15 @@ public:
/// \param Symbol - Symbol the image relative relocation should point to.
virtual void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset);
+ /// Emits an lcomm directive with XCOFF csect information.
+ ///
+ /// \param Symbol - The symbol we are emiting.
+ /// \param Size - The size of the block of storage.
+ /// \param ByteAlignment - The alignment of the symbol in bytes. Must be a power
+ /// of 2.
+ virtual void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment);
+
/// Emit an ELF .size directive.
///
/// This corresponds to an assembler statement such as:
@@ -860,6 +877,22 @@ public:
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
StringRef FixedSizePortion);
+ virtual void EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeRegisterRelHeader DRHdr);
+
+ virtual void EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeSubfieldRegisterHeader DRHdr);
+
+ virtual void EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeRegisterHeader DRHdr);
+
+ virtual void EmitCVDefRangeDirective(
+ ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+ codeview::DefRangeFramePointerRelHeader DRHdr);
+
/// This implements the CodeView '.cv_stringtable' assembler directive.
virtual void EmitCVStringTableDirective() {}
@@ -917,13 +950,13 @@ public:
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,
+ virtual void EmitWinCFIPushReg(MCRegister Register, SMLoc Loc = SMLoc());
+ virtual void EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
SMLoc Loc = SMLoc());
virtual void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc = SMLoc());
- virtual void EmitWinCFISaveReg(unsigned Register, unsigned Offset,
+ virtual void EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
SMLoc Loc = SMLoc());
- virtual void EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
+ virtual void EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
SMLoc Loc = SMLoc());
virtual void EmitWinCFIPushFrame(bool Code, SMLoc Loc = SMLoc());
virtual void EmitWinCFIEndProlog(SMLoc Loc = SMLoc());
diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h
index 9490a6ecedad..09130c4641ef 100644
--- a/include/llvm/MC/MCSubtargetInfo.h
+++ b/include/llvm/MC/MCSubtargetInfo.h
@@ -221,6 +221,52 @@ public:
auto Found = std::lower_bound(ProcDesc.begin(), ProcDesc.end(), CPU);
return Found != ProcDesc.end() && StringRef(Found->Key) == CPU;
}
+
+ virtual unsigned getHwMode() const { return 0; }
+
+ /// Return the cache size in bytes for the given level of cache.
+ /// Level is zero-based, so a value of zero means the first level of
+ /// cache.
+ ///
+ virtual Optional<unsigned> getCacheSize(unsigned Level) const;
+
+ /// Return the cache associatvity for the given level of cache.
+ /// Level is zero-based, so a value of zero means the first level of
+ /// cache.
+ ///
+ virtual Optional<unsigned> getCacheAssociativity(unsigned Level) const;
+
+ /// Return the target cache line size in bytes at a given level.
+ ///
+ virtual Optional<unsigned> getCacheLineSize(unsigned Level) const;
+
+ /// Return the target cache line size in bytes. By default, return
+ /// the line size for the bottom-most level of cache. This provides
+ /// a more convenient interface for the common case where all cache
+ /// levels have the same line size. Return zero if there is no
+ /// cache model.
+ ///
+ virtual unsigned getCacheLineSize() const {
+ Optional<unsigned> Size = getCacheLineSize(0);
+ if (Size)
+ return *Size;
+
+ return 0;
+ }
+
+ /// Return the preferred prefetch distance in terms of instructions.
+ ///
+ virtual unsigned getPrefetchDistance() const;
+
+ /// Return the maximum prefetch distance in terms of loop
+ /// iterations.
+ ///
+ virtual unsigned getMaxPrefetchIterationsAhead() const;
+
+ /// Return the minimum stride necessary to trigger software
+ /// prefetching.
+ ///
+ virtual unsigned getMinPrefetchStride() const;
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCSymbolWasm.h b/include/llvm/MC/MCSymbolWasm.h
index c50cd0ee4709..95beebe3f75a 100644
--- a/include/llvm/MC/MCSymbolWasm.h
+++ b/include/llvm/MC/MCSymbolWasm.h
@@ -54,6 +54,13 @@ public:
modifyFlags(wasm::WASM_SYMBOL_EXPORTED, wasm::WASM_SYMBOL_EXPORTED);
}
+ bool isNoStrip() const {
+ return getFlags() & wasm::WASM_SYMBOL_NO_STRIP;
+ }
+ void setNoStrip() const {
+ modifyFlags(wasm::WASM_SYMBOL_NO_STRIP, wasm::WASM_SYMBOL_NO_STRIP);
+ }
+
bool isWeak() const { return IsWeak; }
void setWeak(bool isWeak) { IsWeak = isWeak; }
diff --git a/include/llvm/MC/MCSymbolXCOFF.h b/include/llvm/MC/MCSymbolXCOFF.h
index 0a1fe1475138..98ecd2466926 100644
--- a/include/llvm/MC/MCSymbolXCOFF.h
+++ b/include/llvm/MC/MCSymbolXCOFF.h
@@ -8,17 +8,49 @@
#ifndef LLVM_MC_MCSYMBOLXCOFF_H
#define LLVM_MC_MCSYMBOLXCOFF_H
+#include "llvm/ADT/Optional.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/MC/MCSymbol.h"
namespace llvm {
+class MCSectionXCOFF;
+
class MCSymbolXCOFF : public MCSymbol {
public:
MCSymbolXCOFF(const StringMapEntry<bool> *Name, bool isTemporary)
: MCSymbol(SymbolKindXCOFF, Name, isTemporary) {}
static bool classof(const MCSymbol *S) { return S->isXCOFF(); }
+
+ void setStorageClass(XCOFF::StorageClass SC) {
+ assert((!StorageClass.hasValue() || StorageClass.getValue() == SC) &&
+ "Redefining StorageClass of XCOFF MCSymbol.");
+ StorageClass = SC;
+ };
+
+ XCOFF::StorageClass getStorageClass() const {
+ assert(StorageClass.hasValue() &&
+ "StorageClass not set on XCOFF MCSymbol.");
+ return StorageClass.getValue();
+ }
+
+ void setContainingCsect(MCSectionXCOFF *C) {
+ assert((!ContainingCsect || ContainingCsect == C) &&
+ "Trying to set a containing csect that doesn't match the one that"
+ "this symbol is already mapped to.");
+ ContainingCsect = C;
+ }
+
+ MCSectionXCOFF *getContainingCsect() const {
+ assert(ContainingCsect &&
+ "Trying to get containing csect but none was set.");
+ return ContainingCsect;
+ }
+
+private:
+ Optional<XCOFF::StorageClass> StorageClass;
+ MCSectionXCOFF *ContainingCsect = nullptr;
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCWasmObjectWriter.h b/include/llvm/MC/MCWasmObjectWriter.h
index 4adbca28f116..fbb68549b503 100644
--- a/include/llvm/MC/MCWasmObjectWriter.h
+++ b/include/llvm/MC/MCWasmObjectWriter.h
@@ -20,9 +20,10 @@ class raw_pwrite_stream;
class MCWasmObjectTargetWriter : public MCObjectTargetWriter {
const unsigned Is64Bit : 1;
+ const unsigned IsEmscripten : 1;
protected:
- explicit MCWasmObjectTargetWriter(bool Is64Bit_);
+ explicit MCWasmObjectTargetWriter(bool Is64Bit_, bool IsEmscripten);
public:
virtual ~MCWasmObjectTargetWriter();
@@ -38,6 +39,7 @@ public:
/// \name Accessors
/// @{
bool is64Bit() const { return Is64Bit; }
+ bool isEmscripten() const { return IsEmscripten; }
/// @}
};
diff --git a/include/llvm/MC/MCXCOFFStreamer.h b/include/llvm/MC/MCXCOFFStreamer.h
index 159ae4818749..b13b0031d18e 100644
--- a/include/llvm/MC/MCXCOFFStreamer.h
+++ b/include/llvm/MC/MCXCOFFStreamer.h
@@ -26,6 +26,8 @@ public:
uint64_t Size = 0, unsigned ByteAlignment = 0,
SMLoc Loc = SMLoc()) override;
void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
+ void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlign) override;
};
} // end namespace llvm
diff --git a/include/llvm/MC/StringTableBuilder.h b/include/llvm/MC/StringTableBuilder.h
index c83eca4e512d..c8d4c3bbc262 100644
--- a/include/llvm/MC/StringTableBuilder.h
+++ b/include/llvm/MC/StringTableBuilder.h
@@ -22,7 +22,7 @@ class raw_ostream;
/// Utility for building string tables with deduplicated suffixes.
class StringTableBuilder {
public:
- enum Kind { ELF, WinCOFF, MachO, RAW, DWARF };
+ enum Kind { ELF, WinCOFF, MachO, RAW, DWARF, XCOFF };
private:
DenseMap<CachedHashStringRef, size_t> StringIndexMap;
diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h
index fc9565ceafad..defbc3c64720 100644
--- a/include/llvm/MC/SubtargetFeature.h
+++ b/include/llvm/MC/SubtargetFeature.h
@@ -18,6 +18,7 @@
#define LLVM_MC_SUBTARGETFEATURE_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
#include <array>
#include <bitset>
#include <initializer_list>
@@ -33,20 +34,123 @@ const unsigned MAX_SUBTARGET_WORDS = 3;
const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64;
/// 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) {}
+/// This is a constexpr reimplementation of a subset of std::bitset. It would be
+/// nice to use std::bitset directly, but it doesn't support constant
+/// initialization.
+class FeatureBitset {
+ static_assert((MAX_SUBTARGET_FEATURES % 64) == 0,
+ "Should be a multiple of 64!");
+ // This cannot be a std::array, operator[] is not constexpr until C++17.
+ uint64_t Bits[MAX_SUBTARGET_WORDS] = {};
+
+protected:
+ constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) {
+ for (unsigned I = 0; I != B.size(); ++I)
+ Bits[I] = B[I];
+ }
- FeatureBitset(std::initializer_list<unsigned> Init) {
+public:
+ constexpr FeatureBitset() = default;
+ constexpr FeatureBitset(std::initializer_list<unsigned> Init) {
for (auto I : Init)
set(I);
}
+ FeatureBitset &set() {
+ std::fill(std::begin(Bits), std::end(Bits), -1ULL);
+ return *this;
+ }
+
+ constexpr FeatureBitset &set(unsigned I) {
+ // GCC <6.2 crashes if this is written in a single statement.
+ uint64_t NewBits = Bits[I / 64] | (uint64_t(1) << (I % 64));
+ Bits[I / 64] = NewBits;
+ return *this;
+ }
+
+ constexpr FeatureBitset &reset(unsigned I) {
+ // GCC <6.2 crashes if this is written in a single statement.
+ uint64_t NewBits = Bits[I / 64] & ~(uint64_t(1) << (I % 64));
+ Bits[I / 64] = NewBits;
+ return *this;
+ }
+
+ constexpr FeatureBitset &flip(unsigned I) {
+ // GCC <6.2 crashes if this is written in a single statement.
+ uint64_t NewBits = Bits[I / 64] ^ (uint64_t(1) << (I % 64));
+ Bits[I / 64] = NewBits;
+ return *this;
+ }
+
+ constexpr bool operator[](unsigned I) const {
+ uint64_t Mask = uint64_t(1) << (I % 64);
+ return (Bits[I / 64] & Mask) != 0;
+ }
+
+ constexpr bool test(unsigned I) const { return (*this)[I]; }
+
+ constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; }
+
+ bool any() const {
+ return llvm::any_of(Bits, [](uint64_t I) { return I != 0; });
+ }
+ bool none() const { return !any(); }
+ size_t count() const {
+ size_t Count = 0;
+ for (auto B : Bits)
+ Count += countPopulation(B);
+ return Count;
+ }
+
+ constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) {
+ for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
+ Bits[I] ^= RHS.Bits[I];
+ }
+ return *this;
+ }
+ constexpr FeatureBitset operator^(const FeatureBitset &RHS) const {
+ FeatureBitset Result = *this;
+ Result ^= RHS;
+ return Result;
+ }
+
+ constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) {
+ for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
+ Bits[I] &= RHS.Bits[I];
+ }
+ return *this;
+ }
+ constexpr FeatureBitset operator&(const FeatureBitset &RHS) const {
+ FeatureBitset Result = *this;
+ Result &= RHS;
+ return Result;
+ }
+
+ constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) {
+ for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
+ Bits[I] |= RHS.Bits[I];
+ }
+ return *this;
+ }
+ constexpr FeatureBitset operator|(const FeatureBitset &RHS) const {
+ FeatureBitset Result = *this;
+ Result |= RHS;
+ return Result;
+ }
+
+ constexpr FeatureBitset operator~() const {
+ FeatureBitset Result = *this;
+ for (auto &B : Result.Bits)
+ B = ~B;
+ return Result;
+ }
+
+ bool operator==(const FeatureBitset &RHS) const {
+ return std::equal(std::begin(Bits), std::end(Bits), std::begin(RHS.Bits));
+ }
+
+ bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); }
+
bool operator < (const FeatureBitset &Other) const {
for (unsigned I = 0, E = size(); I != E; ++I) {
bool LHS = test(I), RHS = Other.test(I);
@@ -58,23 +162,12 @@ public:
};
/// Class used to store the subtarget bits in the tables created by tablegen.
-/// The std::initializer_list constructor of FeatureBitset can't be done at
-/// compile time and requires a static constructor to run at startup.
-class FeatureBitArray {
- std::array<uint64_t, MAX_SUBTARGET_WORDS> Bits;
-
+class FeatureBitArray : public FeatureBitset {
public:
constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
- : Bits(B) {}
-
- FeatureBitset getAsBitset() const {
- FeatureBitset Result;
-
- for (unsigned i = 0, e = Bits.size(); i != e; ++i)
- Result |= FeatureBitset(Bits[i]) << (64 * i);
+ : FeatureBitset(B) {}
- return Result;
- }
+ const FeatureBitset &getAsBitset() const { return *this; }
};
//===----------------------------------------------------------------------===//