diff options
author | Derek Schuff <dschuff@chromium.org> | 2013-01-31 10:07:41 -0800 |
---|---|---|
committer | Derek Schuff <dschuff@chromium.org> | 2013-01-31 10:07:41 -0800 |
commit | 3d5de9e56f3e5af59772bdf2cbedb0903d938bb8 (patch) | |
tree | 300b7a72c61b009f0122ec1d8a155672c74459fd | |
parent | 659ebb8c18832df528effd5c970bfde7662ea368 (diff) | |
parent | 9ccb76998f741a7d3f0f217392a783dfb99c6e87 (diff) |
Cherry-pick r174067
54 files changed, 3063 insertions, 1783 deletions
diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT index c02e71c6d5..de944363a0 100644 --- a/CODE_OWNERS.TXT +++ b/CODE_OWNERS.TXT @@ -109,6 +109,10 @@ N: Duncan Sands E: baldrick@free.fr D: DragonEgg +N: Michael Spencer +E: bigcheesegs@gmail.com +D: Windows parts of Support, Object, ar, nm, objdump, ranlib, size + N: Tom Stellard E: thomas.stellard@amd.com E: mesa-dev@lists.freedesktop.org diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 2a0fca571b..c46cb0d44a 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -1274,8 +1274,23 @@ then then CXX_FLAG_CHECK(NO_UNINITIALIZED, [-Wno-uninitialized]) else - dnl AC_SUBST doesn't work with empty strings. - NO_UNINITIALIZED= + dnl Some versions of gcc accept unsupported -W flags if there is + dnl no warning but stop with an error when a warning is + dnl encountered. If this gcc is earlier than 4.7, just use + dnl -Wno-uninitialized. + gxx_version=`$CXX -dumpversion` + gxx_version_major=`echo $gxx_version | cut -d'.' -f1` + gxx_version_minor=`echo $gxx_version | cut -d'.' -f2` + gxx_version_patch=`echo $gxx_version | cut -d'.' -f3` + + if test "$gxx_version_major" -ge "4" \ + && test "$gxx_version_minor" -ge "7"; then + dnl AC_SUBST doesn't work with empty strings. + NO_UNINITIALIZED= + else + NO_MAYBE_UNINITIALIZED= + CXX_FLAG_CHECK(NO_UNINITIALIZED, [-Wno-uninitialized]) + fi fi else NO_UNINITIALIZED= @@ -12262,7 +12262,19 @@ then NO_UNINITIALIZED=`$CXX -Werror -Wno-uninitialized -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wno-uninitialized` else - NO_UNINITIALIZED= + gxx_version=`$CXX -dumpversion` + gxx_version_major=`echo $gxx_version | cut -d'.' -f1` + gxx_version_minor=`echo $gxx_version | cut -d'.' -f2` + gxx_version_patch=`echo $gxx_version | cut -d'.' -f3` + + if test "$gxx_version_major" -ge "4" \ + && test "$gxx_version_minor" -ge "7"; then + NO_UNINITIALIZED= + else + NO_MAYBE_UNINITIALIZED= + NO_UNINITIALIZED=`$CXX -Werror -Wno-uninitialized -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wno-uninitialized` + + fi fi else NO_UNINITIALIZED= diff --git a/docs/LangRef.rst b/docs/LangRef.rst index 3c49ed0a87..7d9fe41744 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -2462,14 +2462,16 @@ Each triplet has the following form: (or more) metadata with the same ID. The supported behaviors are described below. - The second element is a metadata string that is a unique ID for the - metadata. How each ID is interpreted is documented below. + metadata. Each module may only have one flag entry for each unique ID (not + including entries with the **Require** behavior). - The third element is the value of the flag. When two (or more) modules are merged together, the resulting -``llvm.module.flags`` metadata is the union of the modules' -``llvm.module.flags`` metadata. The only exception being a flag with the -*Override* behavior, which may override another flag's value (see -below). +``llvm.module.flags`` metadata is the union of the modules' flags. That is, for +each unique metadata ID string, there will be exactly one entry in the merged +modules ``llvm.module.flags`` metadata table, and the value for that entry will +be determined by the merge behavior flag, as described below. The only exception +is that entries with the *Require* behavior are always preserved. The following behaviors are supported: @@ -2482,25 +2484,33 @@ The following behaviors are supported: * - 1 - **Error** - Emits an error if two values disagree. It is an error to have an - ID with both an Error and a Warning behavior. + Emits an error if two values disagree, otherwise the resulting value + is that of the operands. * - 2 - **Warning** - Emits a warning if two values disagree. + Emits a warning if two values disagree. The result value will be the + operand for the flag from the first module being linked. * - 3 - **Require** - Emits an error when the specified value is not present or doesn't - have the specified value. It is an error for two (or more) - ``llvm.module.flags`` with the same ID to have the Require behavior - but different values. There may be multiple Require flags per ID. + Adds a requirement that another module flag be present and have a + specified value after linking is performed. The value must be a + metadata pair, where the first element of the pair is the ID of the + module flag to be restricted, and the second element of the pair is + the value the module flag should be restricted to. This behavior can + be used to restrict the allowable results (via triggering of an + error) of linking IDs with the **Override** behavior. * - 4 - **Override** - Uses the specified value if the two values disagree. It is an - error for two (or more) ``llvm.module.flags`` with the same ID - to have the Override behavior but different values. + Uses the specified value, regardless of the behavior or value of the + other module. If both modules specify **Override**, but the values + differ, an error will be emitted. + +It is an error for a particular unique flag ID to have multiple behaviors, +except in the case of **Require** (which adds restrictions on another metadata +value) or **Override**. An example of module flags: @@ -2522,7 +2532,7 @@ An example of module flags: - Metadata ``!1`` has the ID ``!"bar"`` and the value '37'. The behavior if two or more ``!"bar"`` flags are seen is to use the value - '37' if their values are not equal. + '37'. - Metadata ``!2`` has the ID ``!"qux"`` and the value '42'. The behavior if two or more ``!"qux"`` flags are seen is to emit a @@ -2534,10 +2544,9 @@ An example of module flags: metadata !{ metadata !"foo", i32 1 } - The behavior is to emit an error if the ``llvm.module.flags`` does - not contain a flag with the ID ``!"foo"`` that has the value '1'. If - two or more ``!"qux"`` flags exist, then they must have the same - value or an error will be issued. + The behavior is to emit an error if the ``llvm.module.flags`` does not + contain a flag with the ID ``!"foo"`` that has the value '1' after linking is + performed. Objective-C Garbage Collection Module Flags Metadata ---------------------------------------------------- diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index 0d68d11a12..7e40a075ed 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -237,6 +237,10 @@ public: explicit StringMap(AllocatorTy A) : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {} + StringMap(unsigned InitialSize, AllocatorTy A) + : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))), + Allocator(A) {} + StringMap(const StringMap &RHS) : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) { assert(RHS.empty() && diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 1708cccf33..00779fc329 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -40,8 +40,10 @@ namespace llvm { // New instructions receive a name to identifies them with the current pass. const char* IVName; - std::map<std::pair<const SCEV *, Instruction *>, AssertingVH<Value> > + // InsertedExpressions caches Values for reuse, so must track RAUW. + std::map<std::pair<const SCEV *, Instruction *>, TrackingVH<Value> > InsertedExpressions; + // InsertedValues only flags inserted instructions so needs no RAUW. std::set<AssertingVH<Value> > InsertedValues; std::set<AssertingVH<Value> > InsertedPostIncValues; diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 84ae516552..324a646bc1 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -953,7 +953,7 @@ public: "Both operands to ICmp instruction are not of the same type!"); // Check that the operands are the right type assert((getOperand(0)->getType()->isIntOrIntVectorTy() || - getOperand(0)->getType()->isPointerTy()) && + getOperand(0)->getType()->getScalarType()->isPointerTy()) && "Invalid operand types for ICmp instruction"); } diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 57aa08a2d0..8269f08c44 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -47,6 +47,7 @@ public: enum FragmentType { FT_Align, FT_Data, + FT_CompactEncodedInst, FT_Fill, FT_Relaxable, FT_Org, @@ -105,6 +106,7 @@ public: /// \brief Should this fragment be placed at the end of an aligned bundle? virtual bool alignToBundleEnd() const { return false; } + virtual void setAlignToBundleEnd(bool V) { } /// \brief Get the padding size that must be inserted before this fragment. /// Used for bundling. By default, no padding is inserted. @@ -120,9 +122,16 @@ public: virtual void setBundlePadding(uint8_t N) { } + virtual bool hasFixups() const { + return false; + } + void dump(); }; +/// Interface implemented by fragments that contain encoded instructions and/or +/// data. +/// class MCEncodedFragment : public MCFragment { virtual void anchor(); @@ -134,20 +143,9 @@ public: } virtual ~MCEncodedFragment(); - typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; - typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; - virtual SmallVectorImpl<char> &getContents() = 0; virtual const SmallVectorImpl<char> &getContents() const = 0; - virtual SmallVectorImpl<MCFixup> &getFixups() = 0; - virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0; - - virtual fixup_iterator fixup_begin() = 0; - virtual const_fixup_iterator fixup_begin() const = 0; - virtual fixup_iterator fixup_end() = 0; - virtual const_fixup_iterator fixup_end() const = 0; - virtual uint8_t getBundlePadding() const { return BundlePadding; } @@ -158,13 +156,55 @@ public: static bool classof(const MCFragment *F) { MCFragment::FragmentType Kind = F->getKind(); - return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data; + switch (Kind) { + default: + return false; + case MCFragment::FT_Relaxable: + case MCFragment::FT_CompactEncodedInst: + case MCFragment::FT_Data: + return true; + } + } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data and also have fixups registered. +/// +class MCEncodedFragmentWithFixups : public MCEncodedFragment { + virtual void anchor(); + +public: + MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, + MCSectionData *SD = 0) + : MCEncodedFragment(FType, SD) + { + } + + virtual ~MCEncodedFragmentWithFixups(); + + virtual bool hasFixups() const { + return true; + } + + typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; + typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; + + virtual SmallVectorImpl<MCFixup> &getFixups() = 0; + virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0; + + virtual fixup_iterator fixup_begin() = 0; + virtual const_fixup_iterator fixup_begin() const = 0; + virtual fixup_iterator fixup_end() = 0; + virtual const_fixup_iterator fixup_end() const = 0; + + static bool classof(const MCFragment *F) { + return isa<MCEncodedFragment>(F) && F->hasFixups(); } }; /// Fragment for data and encoded instructions. /// -class MCDataFragment : public MCEncodedFragment { +class MCDataFragment : public MCEncodedFragmentWithFixups { virtual void anchor(); /// \brief Does this fragment contain encoded instructions anywhere in it? @@ -179,7 +219,7 @@ class MCDataFragment : public MCEncodedFragment { SmallVector<MCFixup, 4> Fixups; public: MCDataFragment(MCSectionData *SD = 0) - : MCEncodedFragment(FT_Data, SD), + : MCEncodedFragmentWithFixups(FT_Data, SD), HasInstructions(false), AlignToBundleEnd(false) { } @@ -212,10 +252,43 @@ public: } }; +/// 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 MCEncodedFragment { + virtual void anchor(); + + /// \brief Should this fragment be aligned to the end of a bundle? + bool AlignToBundleEnd; + + SmallVector<char, 4> Contents; +public: + MCCompactEncodedInstFragment(MCSectionData *SD = 0) + : MCEncodedFragment(FT_CompactEncodedInst, SD), AlignToBundleEnd(false) + { + } + + virtual bool hasInstructions() const { + return true; + } + + virtual SmallVectorImpl<char> &getContents() { return Contents; } + virtual const SmallVectorImpl<char> &getContents() const { return Contents; } + + virtual bool alignToBundleEnd() const { return AlignToBundleEnd; } + virtual void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } + + 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 MCEncodedFragment { +class MCRelaxableFragment : public MCEncodedFragmentWithFixups { virtual void anchor(); /// Inst - The instruction this is a fragment for. @@ -229,7 +302,7 @@ class MCRelaxableFragment : public MCEncodedFragment { public: MCRelaxableFragment(const MCInst &_Inst, MCSectionData *SD = 0) - : MCEncodedFragment(FT_Relaxable, SD), Inst(_Inst) { + : MCEncodedFragmentWithFixups(FT_Relaxable, SD), Inst(_Inst) { } virtual SmallVectorImpl<char> &getContents() { return Contents; } diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index eeeacbc2fc..a256f85a7c 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -11,6 +11,7 @@ #define LLVM_MC_MCPARSER_MCASMPARSER_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" #include "llvm/MC/MCParser/AsmLexer.h" #include "llvm/Support/DataTypes.h" #include <vector> @@ -43,8 +44,24 @@ public: }; +/// \brief Helper types for tracking macro definitions. typedef std::vector<AsmToken> MCAsmMacroArgument; +typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments; +typedef std::pair<StringRef, MCAsmMacroArgument> MCAsmMacroParameter; +typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters; +struct MCAsmMacro { + StringRef Name; + StringRef Body; + MCAsmMacroParameters Parameters; + +public: + MCAsmMacro(StringRef N, StringRef B, const MCAsmMacroParameters &P) : + Name(N), Body(B), Parameters(P) {} + + MCAsmMacro(const MCAsmMacro& Other) + : Name(Other.Name), Body(Other.Body), Parameters(Other.Parameters) {} +}; /// MCAsmParser - Generic assembler parser interface, for use by target specific /// assembly parsers. @@ -141,10 +158,35 @@ public: /// recovery. virtual void EatToEndOfStatement() = 0; - /// Control a flag in the parser that enables or disables macros. + /// \brief Are macros enabled in the parser? virtual bool MacrosEnabled() = 0; + + /// \brief Control a flag in the parser that enables or disables macros. virtual void SetMacrosEnabled(bool flag) = 0; + /// \brief Lookup a previously defined macro. + /// \param Name Macro name. + /// \returns Pointer to macro. NULL if no such macro was defined. + virtual const MCAsmMacro* LookupMacro(StringRef Name) = 0; + + /// \brief Define a new macro with the given name and information. + virtual void DefineMacro(StringRef Name, const MCAsmMacro& Macro) = 0; + + /// \brief Undefine a macro. If no such macro was defined, it's a no-op. + virtual void UndefineMacro(StringRef Name) = 0; + + /// \brief Are we inside a macro instantiation? + virtual bool InsideMacroInstantiation() = 0; + + /// \brief Handle entry to macro instantiation. + /// + /// \param M The macro. + /// \param NameLoc Instantiation location. + virtual bool HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) = 0; + + /// \brief Handle exit from macro instantiation. + virtual void HandleMacroExit() = 0; + /// ParseMacroArgument - Extract AsmTokens for a macro argument. If the /// argument delimiter is initially unknown, set it to AsmToken::Eof. It will /// be set to the correct delimiter by the method. diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 735accdf7e..c47b9cdf32 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -35,6 +35,15 @@ namespace object { using support::endianness; +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +struct ELFType { + enum { + TargetEndianness = target_endianness, + MaxAlignment = max_alignment, + Is64Bits = is64Bits + }; +}; + template<typename T, int max_align> struct MaximumAlignment { enum {value = AlignOf<T>::Alignment > max_align ? max_align @@ -70,59 +79,59 @@ struct ELFDataTypeTypedefHelperCommon { MaximumAlignment<int64_t, max_alignment>::value> Elf_Sxword; }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct ELFDataTypeTypedefHelper; /// ELF 32bit types. -template<endianness target_endianness, std::size_t max_alignment> -struct ELFDataTypeTypedefHelper<target_endianness, max_alignment, false> - : ELFDataTypeTypedefHelperCommon<target_endianness, max_alignment> { +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, false> > + : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { typedef uint32_t value_type; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, - MaximumAlignment<value_type, max_alignment>::value> Elf_Addr; + <value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, - MaximumAlignment<value_type, max_alignment>::value> Elf_Off; + <value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Off; }; /// ELF 64bit types. -template<endianness target_endianness, std::size_t max_alignment> -struct ELFDataTypeTypedefHelper<target_endianness, max_alignment, true> - : ELFDataTypeTypedefHelperCommon<target_endianness, max_alignment>{ +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, true> > + : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { typedef uint64_t value_type; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, - MaximumAlignment<value_type, max_alignment>::value> Elf_Addr; + <value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, - MaximumAlignment<value_type, max_alignment>::value> Elf_Off; + <value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Off; }; // I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Addr Elf_Addr; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Off Elf_Off; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Half Elf_Half; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Word Elf_Word; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Sword Elf_Sword; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Xword Elf_Xword; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Sxword Elf_Sxword; +#define LLVM_ELF_IMPORT_TYPES(ELFT) \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Addr Elf_Addr; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Off Elf_Off; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Half Elf_Half; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Word Elf_Word; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Sword Elf_Sword; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Xword Elf_Xword; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Sxword Elf_Sxword; + +// This is required to get template types into a macro :( +#define LLVM_ELF_COMMA , // Section header. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Shdr_Base; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Shdr_Base<target_endianness, max_alignment, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Shdr_Base<ELFT<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_flags; // Section flags (SHF_*) @@ -135,9 +144,11 @@ struct Elf_Shdr_Base<target_endianness, max_alignment, false> { Elf_Word sh_entsize; // Size of records contained within the section }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Shdr_Base<target_endianness, max_alignment, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Shdr_Base<ELFT<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Xword sh_flags; // Section flags (SHF_*) @@ -150,11 +161,10 @@ struct Elf_Shdr_Base<target_endianness, max_alignment, true> { Elf_Xword sh_entsize; // Size of records contained within the section }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -struct Elf_Shdr_Impl - : Elf_Shdr_Base<target_endianness, max_alignment, is64Bits> { - using Elf_Shdr_Base<target_endianness, max_alignment, is64Bits>::sh_entsize; - using Elf_Shdr_Base<target_endianness, max_alignment, is64Bits>::sh_size; +template<class ELFT> +struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { + using Elf_Shdr_Base<ELFT>::sh_entsize; + using Elf_Shdr_Base<ELFT>::sh_size; /// @brief Get the number of entities this section contains if it has any. unsigned getEntityCount() const { @@ -164,14 +174,14 @@ struct Elf_Shdr_Impl } }; -template< endianness target_endianness - , std::size_t max_alignment - , bool is64Bits> +template<class ELFT> struct Elf_Sym_Base; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Sym_Base<target_endianness, max_alignment, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Sym_Base<ELFT<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Word st_name; // Symbol name (index into string table) Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol @@ -180,9 +190,11 @@ struct Elf_Sym_Base<target_endianness, max_alignment, false> { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Sym_Base<target_endianness, max_alignment, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Sym_Base<ELFT<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved @@ -191,10 +203,9 @@ struct Elf_Sym_Base<target_endianness, max_alignment, true> { Elf_Xword st_size; // Size of the symbol }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -struct Elf_Sym_Impl - : Elf_Sym_Base<target_endianness, max_alignment, is64Bits> { - using Elf_Sym_Base<target_endianness, max_alignment, is64Bits>::st_info; +template<class ELFT> +struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { + using Elf_Sym_Base<ELFT>::st_info; // These accessors and mutators correspond to the ELF32_ST_BIND, // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: @@ -209,22 +220,21 @@ struct Elf_Sym_Impl /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section /// (.gnu.version). This structure is identical for ELF32 and ELF64. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT) Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Verdaux_Impl; /// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section /// (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Verdef_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) - typedef - Elf_Verdaux_Impl<target_endianness, max_alignment, is64Bits> Elf_Verdaux; + LLVM_ELF_IMPORT_TYPES(ELFT) + typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) Elf_Half vd_ndx; // Version index, used in .gnu.version entries @@ -241,18 +251,18 @@ struct Elf_Verdef_Impl { /// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef /// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Verdaux_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT) Elf_Word vda_name; // Version name (offset in string table) Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) }; /// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Verneed_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT) Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) Elf_Half vn_cnt; // Number of associated Vernaux entries Elf_Word vn_file; // Library name (string table offset) @@ -262,9 +272,9 @@ struct Elf_Verneed_Impl { /// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Vernaux_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT) Elf_Word vna_hash; // Hash of dependency name Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) Elf_Half vna_other; // Version index, used in .gnu.version entries @@ -274,12 +284,14 @@ struct Elf_Vernaux_Impl { /// Elf_Dyn_Base: This structure matches the form of entries in the dynamic /// table section (.dynamic) look like. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Dyn_Base; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Dyn_Base<target_endianness, max_alignment, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Dyn_Base<ELFT<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Sword d_tag; union { Elf_Word d_val; @@ -287,9 +299,11 @@ struct Elf_Dyn_Base<target_endianness, max_alignment, false> { } d_un; }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Dyn_Base<target_endianness, max_alignment, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Dyn_Base<ELFT<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -298,24 +312,24 @@ struct Elf_Dyn_Base<target_endianness, max_alignment, true> { }; /// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -struct Elf_Dyn_Impl : Elf_Dyn_Base<target_endianness, max_alignment, is64Bits> { - using Elf_Dyn_Base<target_endianness, max_alignment, is64Bits>::d_tag; - using Elf_Dyn_Base<target_endianness, max_alignment, is64Bits>::d_un; +template<class ELFT> +struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { + using Elf_Dyn_Base<ELFT>::d_tag; + using Elf_Dyn_Base<ELFT>::d_un; int64_t getTag() const { return d_tag; } uint64_t getVal() const { return d_un.d_val; } uint64_t getPtr() const { return d_un.ptr; } }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> class ELFObjectFile; // DynRefImpl: Reference to an entry in the dynamic table // This is an ELF-specific interface. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> class DynRefImpl { - typedef Elf_Dyn_Impl<target_endianness, max_alignment, is64Bits> Elf_Dyn; - typedef ELFObjectFile<target_endianness, max_alignment, is64Bits> OwningType; + typedef Elf_Dyn_Impl<ELFT> Elf_Dyn; + typedef ELFObjectFile<ELFT> OwningType; DataRefImpl DynPimpl; const OwningType *OwningObject; @@ -337,53 +351,57 @@ public: }; // Elf_Rel: Elf Relocation -template< endianness target_endianness - , std::size_t max_alignment - , bool is64Bits - , bool isRela> +template<class ELFT, bool isRela> struct Elf_Rel_Base; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Rel_Base<target_endianness, max_alignment, false, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, false> { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Rel_Base<target_endianness, max_alignment, true, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, false> { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Rel_Base<target_endianness, max_alignment, false, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, true> { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply Elf_Sword r_addend; // Compute value for relocatable field by adding this }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Rel_Base<target_endianness, max_alignment, true, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, true> { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply Elf_Sxword r_addend; // Compute value for relocatable field by adding this. }; -template< endianness target_endianness - , std::size_t max_alignment - , bool is64Bits - , bool isRela> +template<class ELFT, bool isRela> struct Elf_Rel_Impl; -template<endianness target_endianness, std::size_t max_alignment, bool isRela> -struct Elf_Rel_Impl<target_endianness, max_alignment, true, isRela> - : Elf_Rel_Base<target_endianness, max_alignment, true, isRela> { - using Elf_Rel_Base<target_endianness, max_alignment, true, isRela>::r_info; - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign, bool isRela> +struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, true>, isRela> + : Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela> { + using Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela>::r_info; + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: @@ -398,11 +416,13 @@ struct Elf_Rel_Impl<target_endianness, max_alignment, true, isRela> } }; -template<endianness target_endianness, std::size_t max_alignment, bool isRela> -struct Elf_Rel_Impl<target_endianness, max_alignment, false, isRela> - : Elf_Rel_Base<target_endianness, max_alignment, false, isRela> { - using Elf_Rel_Base<target_endianness, max_alignment, false, isRela>::r_info; - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign, bool isRela> +struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, false>, isRela> + : Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela> { + using Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela>::r_info; + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // and ELF32_R_INFO macros defined in the ELF specification: @@ -415,9 +435,9 @@ struct Elf_Rel_Impl<target_endianness, max_alignment, false, isRela> } }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Ehdr_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT) unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes Elf_Half e_type; // Type of file (see ET_*) Elf_Half e_machine; // Required architecture for this file (see EM_*) @@ -440,12 +460,14 @@ struct Elf_Ehdr_Impl { unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Phdr_Impl; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Phdr_Impl<target_endianness, max_alignment, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Word p_type; // Type of segment Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Addr p_vaddr; // Virtual Address of beginning of segment @@ -456,9 +478,11 @@ struct Elf_Phdr_Impl<target_endianness, max_alignment, false> { Elf_Word p_align; // Segment alignment constraint }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Phdr_Impl<target_endianness, max_alignment, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Word p_type; // Type of segment Elf_Word p_flags; // Segment flags Elf_Off p_offset; // FileOffset where segment is located, in bytes @@ -469,30 +493,23 @@ struct Elf_Phdr_Impl<target_endianness, max_alignment, true> { Elf_Xword p_align; // Segment alignment constraint }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> class ELFObjectFile : public ObjectFile { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) - - typedef Elf_Ehdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Ehdr; - typedef Elf_Shdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Shdr; - typedef Elf_Sym_Impl<target_endianness, max_alignment, is64Bits> Elf_Sym; - typedef Elf_Dyn_Impl<target_endianness, max_alignment, is64Bits> Elf_Dyn; - typedef Elf_Phdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Phdr; - typedef - Elf_Rel_Impl<target_endianness, max_alignment, is64Bits, false> Elf_Rel; - typedef - Elf_Rel_Impl<target_endianness, max_alignment, is64Bits, true> Elf_Rela; - typedef - Elf_Verdef_Impl<target_endianness, max_alignment, is64Bits> Elf_Verdef; - typedef - Elf_Verdaux_Impl<target_endianness, max_alignment, is64Bits> Elf_Verdaux; - typedef - Elf_Verneed_Impl<target_endianness, max_alignment, is64Bits> Elf_Verneed; - typedef - Elf_Vernaux_Impl<target_endianness, max_alignment, is64Bits> Elf_Vernaux; - typedef - Elf_Versym_Impl<target_endianness, max_alignment, is64Bits> Elf_Versym; - typedef DynRefImpl<target_endianness, max_alignment, is64Bits> DynRef; + LLVM_ELF_IMPORT_TYPES(ELFT) + + typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr; + typedef Elf_Shdr_Impl<ELFT> Elf_Shdr; + typedef Elf_Sym_Impl<ELFT> Elf_Sym; + typedef Elf_Dyn_Impl<ELFT> Elf_Dyn; + typedef Elf_Phdr_Impl<ELFT> Elf_Phdr; + typedef Elf_Rel_Impl<ELFT, false> Elf_Rel; + typedef Elf_Rel_Impl<ELFT, true> Elf_Rela; + typedef Elf_Verdef_Impl<ELFT> Elf_Verdef; + typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; + typedef Elf_Verneed_Impl<ELFT> Elf_Verneed; + typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux; + typedef Elf_Versym_Impl<ELFT> Elf_Versym; + typedef DynRefImpl<ELFT> DynRef; typedef content_iterator<DynRef> dyn_iterator; protected: @@ -659,7 +676,7 @@ protected: section_iterator &Res) const; virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - friend class DynRefImpl<target_endianness, max_alignment, is64Bits>; + friend class DynRefImpl<ELFT>; virtual error_code getDynNext(DataRefImpl DynData, DynRef &Result) const; virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; @@ -775,16 +792,15 @@ public: // Methods for type inquiry through isa, cast, and dyn_cast bool isDyldType() const { return isDyldELFObject; } static inline bool classof(const Binary *v) { - return v->getType() == getELFType(target_endianness == support::little, - is64Bits); + return v->getType() == getELFType(ELFT::TargetEndianness == support::little, + ELFT::Is64Bits); } }; // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void ELFObjectFile<target_endianness, max_alignment, is64Bits>:: - LoadVersionDefs(const Elf_Shdr *sec) const { +template<class ELFT> +void ELFObjectFile<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { unsigned vd_size = sec->sh_size; // Size of section in bytes unsigned vd_count = sec->sh_info; // Number of Verdef entries const char *sec_start = (const char*)base() + sec->sh_offset; @@ -808,9 +824,8 @@ void ELFObjectFile<target_endianness, max_alignment, is64Bits>:: // Iterate through the versions needed section, and place each Elf_Vernaux // in the VersionMap according to its index. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void ELFObjectFile<target_endianness, max_alignment, is64Bits>:: - LoadVersionNeeds(const Elf_Shdr *sec) const { +template<class ELFT> +void ELFObjectFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { unsigned vn_size = sec->sh_size; // Size of section in bytes unsigned vn_count = sec->sh_info; // Number of Verneed entries const char *sec_start = (const char*)base() + sec->sh_offset; @@ -841,9 +856,8 @@ void ELFObjectFile<target_endianness, max_alignment, is64Bits>:: } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::LoadVersionMap() const { +template<class ELFT> +void ELFObjectFile<ELFT>::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. if (SymbolTableSections[0] == NULL || dot_gnu_version_sec == NULL) return; @@ -864,9 +878,8 @@ void ELFObjectFile<target_endianness, max_alignment, is64Bits> LoadVersionNeeds(dot_gnu_version_r_sec); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::validateSymbol(DataRefImpl Symb) const { +template<class ELFT> +void ELFObjectFile<ELFT>::validateSymbol(DataRefImpl Symb) const { const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; // FIXME: We really need to do proper error handling in the case of an invalid @@ -883,10 +896,9 @@ void ELFObjectFile<target_endianness, max_alignment, is64Bits> report_fatal_error("Symb must point to a valid symbol!"); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolNext(DataRefImpl Symb, - SymbolRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { validateSymbol(Symb); const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; @@ -911,20 +923,18 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); return getSymbolName(SymbolTableSections[Symb.d.b], symb, Result); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolVersion(SymbolRef SymRef, - StringRef &Version, - bool &IsDefault) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, + StringRef &Version, + bool &IsDefault) const { DataRefImpl Symb = SymRef.getRawDataRefImpl(); validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); @@ -932,19 +942,17 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> Version, IsDefault); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -ELF::Elf64_Word ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolTableIndex(const Elf_Sym *symb) const { +template<class ELFT> +ELF::Elf64_Word ELFObjectFile<ELFT> + ::getSymbolTableIndex(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return ExtendedSymbolTable.lookup(symb); return symb->st_shndx; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Shdr * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSection(const Elf_Sym *symb) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Shdr * +ELFObjectFile<ELFT>::getSection(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return getSection(ExtendedSymbolTable.lookup(symb)); if (symb->st_shndx >= ELF::SHN_LORESERVE) @@ -952,38 +960,31 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> return getSection(symb->st_shndx); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Shdr * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getElfSection(section_iterator &It) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Shdr * +ELFObjectFile<ELFT>::getElfSection(section_iterator &It) const { llvm::object::DataRefImpl ShdrRef = It->getRawDataRefImpl(); return reinterpret_cast<const Elf_Shdr *>(ShdrRef.p); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Sym * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getElfSymbol(symbol_iterator &It) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Sym * +ELFObjectFile<ELFT>::getElfSymbol(symbol_iterator &It) const { return getSymbol(It->getRawDataRefImpl()); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Sym * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getElfSymbol(uint32_t index) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Sym * +ELFObjectFile<ELFT>::getElfSymbol(uint32_t index) const { DataRefImpl SymbolData; SymbolData.d.a = index; SymbolData.d.b = 1; return getSymbol(SymbolData); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; @@ -1015,10 +1016,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; @@ -1059,10 +1059,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if (symb->st_size == 0) @@ -1071,10 +1070,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolNMTypeChar(DataRefImpl Symb, - char &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolNMTypeChar(DataRefImpl Symb, + char &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section = getSection(symb); @@ -1136,10 +1134,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); @@ -1168,10 +1165,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolFlags(DataRefImpl Symb, - uint32_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, + uint32_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); @@ -1203,10 +1199,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *sec = getSection(symb); @@ -1220,19 +1215,18 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); Val = symb->st_value; return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionNext(DataRefImpl Sec, + SectionRef &Result) const { const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); sec += Header->e_shentsize; Sec.p = reinterpret_cast<intptr_t>(sec); @@ -1240,65 +1234,58 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionName(DataRefImpl Sec, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); Result = sec->sh_addr; return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); Result = sec->sh_size; return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); const char *start = (const char*)base() + sec->sh_offset; Result = StringRef(start, sec->sh_size); return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionContents(const Elf_Shdr *Sec, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionContents(const Elf_Shdr *Sec, + StringRef &Result) const { const char *start = (const char*)base() + Sec->sh_offset; Result = StringRef(start, Sec->sh_size); return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); Result = sec->sh_addralign; return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionText(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & ELF::SHF_EXECINSTR) Result = true; @@ -1307,10 +1294,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionData(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && sec->sh_type == ELF::SHT_PROGBITS) @@ -1320,10 +1306,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionBSS(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && sec->sh_type == ELF::SHT_NOBITS) @@ -1333,10 +1318,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionRequiredForExecution(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionRequiredForExecution( + DataRefImpl Sec, bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & ELF::SHF_ALLOC) Result = true; @@ -1345,10 +1329,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_type == ELF::SHT_NOBITS) Result = true; @@ -1357,10 +1340,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); // For ELF, all zero-init sections are virtual (that is, they occupy no space // in the object image) and vice versa. @@ -1368,10 +1350,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & ELF::SHF_WRITE || sec->sh_flags & ELF::SHF_EXECINSTR) Result = false; @@ -1380,19 +1361,18 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -relocation_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionRelBegin(DataRefImpl Sec) const { +template<class ELFT> +relocation_iterator +ELFObjectFile<ELFT>::getSectionRelBegin(DataRefImpl Sec) const { DataRefImpl RelData; const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); @@ -1404,9 +1384,9 @@ relocation_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> return relocation_iterator(RelocationRef(RelData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -relocation_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionRelEnd(DataRefImpl Sec) const { +template<class ELFT> +relocation_iterator +ELFObjectFile<ELFT>::getSectionRelEnd(DataRefImpl Sec) const { DataRefImpl RelData; const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); @@ -1422,10 +1402,9 @@ relocation_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> } // Relocations -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationNext(DataRefImpl Rel, - RelocationRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationNext(DataRefImpl Rel, + RelocationRef &Result) const { ++Rel.w.c; const Elf_Shdr *relocsec = getSection(Rel.w.b); if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { @@ -1451,10 +1430,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Result) const { uint32_t symbolIdx; const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { @@ -1479,10 +1457,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, + uint64_t &Result) const { uint64_t offset; const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { @@ -1502,10 +1479,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationOffset(DataRefImpl Rel, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, + uint64_t &Result) const { uint64_t offset; const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { @@ -1525,10 +1501,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationType(DataRefImpl Rel, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, + uint64_t &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { default : @@ -1548,10 +1523,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> #define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ case ELF::enum: res = #enum; break; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); uint32_t type; StringRef res; @@ -1890,10 +1864,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> #undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationAdditionalInfo( + DataRefImpl Rel, int64_t &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { default : @@ -1909,10 +1882,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationValueString( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); uint8_t type; StringRef res; @@ -1980,20 +1952,21 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> } // Verify that the last byte in the string table in a null. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::VerifyStrTab(const Elf_Shdr *sh) const { +template<class ELFT> +void ELFObjectFile<ELFT>::VerifyStrTab(const Elf_Shdr *sh) const { const char *strtab = (const char*)base() + sh->sh_offset; if (strtab[sh->sh_size - 1] != 0) // FIXME: Proper error handling. report_fatal_error("String table must end with a null terminator!"); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::ELFObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(getELFType(target_endianness == support::little, is64Bits), - Object, ec) +template<class ELFT> +ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) + : ObjectFile(getELFType( + static_cast<endianness>(ELFT::TargetEndianness) == support::little, + ELFT::Is64Bits), + Object, + ec) , isDyldELFObject(false) , SectionHeaderTable(0) , dot_shstrtab_sec(0) @@ -2151,9 +2124,8 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> } // Get the symbol table index in the symtab section given a symbol -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolIndex(const Elf_Sym *Sym) const { +template<class ELFT> +uint64_t ELFObjectFile<ELFT>::getSymbolIndex(const Elf_Sym *Sym) const { assert(SymbolTableSections.size() == 1 && "Only one symbol table supported!"); const Elf_Shdr *SymTab = *SymbolTableSections.begin(); uintptr_t SymLoc = uintptr_t(Sym); @@ -2165,9 +2137,8 @@ uint64_t ELFObjectFile<target_endianness, max_alignment, is64Bits> return SymOffset / SymTab->sh_entsize; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::begin_symbols() const { +template<class ELFT> +symbol_iterator ELFObjectFile<ELFT>::begin_symbols() const { DataRefImpl SymbolData; if (SymbolTableSections.size() <= 1) { SymbolData.d.a = std::numeric_limits<uint32_t>::max(); @@ -2179,18 +2150,16 @@ symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> return symbol_iterator(SymbolRef(SymbolData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::end_symbols() const { +template<class ELFT> +symbol_iterator ELFObjectFile<ELFT>::end_symbols() const { DataRefImpl SymbolData; SymbolData.d.a = std::numeric_limits<uint32_t>::max(); SymbolData.d.b = std::numeric_limits<uint32_t>::max(); return symbol_iterator(SymbolRef(SymbolData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::begin_dynamic_symbols() const { +template<class ELFT> +symbol_iterator ELFObjectFile<ELFT>::begin_dynamic_symbols() const { DataRefImpl SymbolData; if (SymbolTableSections[0] == NULL) { SymbolData.d.a = std::numeric_limits<uint32_t>::max(); @@ -2202,26 +2171,23 @@ symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> return symbol_iterator(SymbolRef(SymbolData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::end_dynamic_symbols() const { +template<class ELFT> +symbol_iterator ELFObjectFile<ELFT>::end_dynamic_symbols() const { DataRefImpl SymbolData; SymbolData.d.a = std::numeric_limits<uint32_t>::max(); SymbolData.d.b = std::numeric_limits<uint32_t>::max(); return symbol_iterator(SymbolRef(SymbolData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -section_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::begin_sections() const { +template<class ELFT> +section_iterator ELFObjectFile<ELFT>::begin_sections() const { DataRefImpl ret; ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); return section_iterator(SectionRef(ret, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -section_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::end_sections() const { +template<class ELFT> +section_iterator ELFObjectFile<ELFT>::end_sections() const { DataRefImpl ret; ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff @@ -2229,10 +2195,9 @@ section_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> return section_iterator(SectionRef(ret, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -typename ELFObjectFile<target_endianness, max_alignment, is64Bits>::dyn_iterator -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::begin_dynamic_table() const { +template<class ELFT> +typename ELFObjectFile<ELFT>::dyn_iterator +ELFObjectFile<ELFT>::begin_dynamic_table() const { DataRefImpl DynData; if (dot_dynamic_sec == NULL || dot_dynamic_sec->sh_size == 0) { DynData.d.a = std::numeric_limits<uint32_t>::max(); @@ -2242,19 +2207,17 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> return dyn_iterator(DynRef(DynData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -typename ELFObjectFile<target_endianness, max_alignment, is64Bits>::dyn_iterator -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::end_dynamic_table() const { +template<class ELFT> +typename ELFObjectFile<ELFT>::dyn_iterator +ELFObjectFile<ELFT>::end_dynamic_table() const { DataRefImpl DynData; DynData.d.a = std::numeric_limits<uint32_t>::max(); return dyn_iterator(DynRef(DynData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getDynNext(DataRefImpl DynData, - DynRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getDynNext(DataRefImpl DynData, + DynRef &Result) const { ++DynData.d.a; // Check to see if we are at the end of .dynamic @@ -2267,9 +2230,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> StringRef -ELFObjectFile<target_endianness, max_alignment, is64Bits>::getLoadName() const { +ELFObjectFile<ELFT>::getLoadName() const { if (!dt_soname) { // Find the DT_SONAME entry dyn_iterator it = begin_dynamic_table(); @@ -2293,9 +2256,8 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits>::getLoadName() const { return dt_soname; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -library_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::begin_libraries_needed() const { +template<class ELFT> +library_iterator ELFObjectFile<ELFT>::begin_libraries_needed() const { // Find the first DT_NEEDED entry dyn_iterator i = begin_dynamic_table(); dyn_iterator e = end_dynamic_table(); @@ -2311,10 +2273,9 @@ library_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> return library_iterator(LibraryRef(i->getRawDataRefImpl(), this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const { // Use the same DataRefImpl format as DynRef. dyn_iterator i = dyn_iterator(DynRef(Data, this)); dyn_iterator e = end_dynamic_table(); @@ -2340,9 +2301,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getLibraryPath(DataRefImpl Data, StringRef &Res) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getLibraryPath(DataRefImpl Data, + StringRef &Res) const { dyn_iterator i = dyn_iterator(DynRef(Data, this)); if (i == end_dynamic_table()) report_fatal_error("getLibraryPath() called on iterator end"); @@ -2361,23 +2322,20 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -library_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::end_libraries_needed() const { +template<class ELFT> +library_iterator ELFObjectFile<ELFT>::end_libraries_needed() const { dyn_iterator e = end_dynamic_table(); // Use the same DataRefImpl format as DynRef. return library_iterator(LibraryRef(e->getRawDataRefImpl(), this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -uint8_t ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getBytesInAddress() const { - return is64Bits ? 8 : 4; +template<class ELFT> +uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const { + return ELFT::Is64Bits ? 8 : 4; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -StringRef ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getFileFormatName() const { +template<class ELFT> +StringRef ELFObjectFile<ELFT>::getFileFormatName() const { switch(Header->e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: switch(Header->e_machine) { @@ -2409,9 +2367,8 @@ StringRef ELFObjectFile<target_endianness, max_alignment, is64Bits> } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -unsigned ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getArch() const { +template<class ELFT> +unsigned ELFObjectFile<ELFT>::getArch() const { switch(Header->e_machine) { case ELF::EM_386: return Triple::x86; @@ -2422,7 +2379,7 @@ unsigned ELFObjectFile<target_endianness, max_alignment, is64Bits> case ELF::EM_HEXAGON: return Triple::hexagon; case ELF::EM_MIPS: - return (target_endianness == support::little) ? + return (ELFT::TargetEndianness == support::little) ? Triple::mipsel : Triple::mips; case ELF::EM_PPC64: return Triple::ppc64; @@ -2431,9 +2388,8 @@ unsigned ELFObjectFile<target_endianness, max_alignment, is64Bits> } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getNumSections() const { +template<class ELFT> +uint64_t ELFObjectFile<ELFT>::getNumSections() const { assert(Header && "Header not initialized!"); if (Header->e_shnum == ELF::SHN_UNDEF) { assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); @@ -2442,10 +2398,9 @@ uint64_t ELFObjectFile<target_endianness, max_alignment, is64Bits> return Header->e_shnum; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> uint64_t -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getStringTableIndex() const { +ELFObjectFile<ELFT>::getStringTableIndex() const { if (Header->e_shnum == ELF::SHN_UNDEF) { if (Header->e_shstrndx == ELF::SHN_HIRESERVE) return SectionHeaderTable->sh_link; @@ -2455,62 +2410,50 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> return Header->e_shstrndx; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> template<typename T> inline const T * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getEntry(uint16_t Section, uint32_t Entry) const { +ELFObjectFile<ELFT>::getEntry(uint16_t Section, uint32_t Entry) const { return getEntry<T>(getSection(Section), Entry); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> template<typename T> inline const T * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { +ELFObjectFile<ELFT>::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { return reinterpret_cast<const T *>( base() + Section->sh_offset + (Entry * Section->sh_entsize)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Sym * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbol(DataRefImpl Symb) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Sym * +ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const { return getEntry<Elf_Sym>(SymbolTableSections[Symb.d.b], Symb.d.a); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Dyn * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getDyn(DataRefImpl DynData) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Dyn * +ELFObjectFile<ELFT>::getDyn(DataRefImpl DynData) const { return getEntry<Elf_Dyn>(dot_dynamic_sec, DynData.d.a); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Rel * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRel(DataRefImpl Rel) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Rel * +ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { return getEntry<Elf_Rel>(Rel.w.b, Rel.w.c); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Rela * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRela(DataRefImpl Rela) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Rela * +ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { return getEntry<Elf_Rela>(Rela.w.b, Rela.w.c); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Shdr * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSection(DataRefImpl Symb) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Shdr * +ELFObjectFile<ELFT>::getSection(DataRefImpl Symb) const { const Elf_Shdr *sec = getSection(Symb.d.b); if (sec->sh_type != ELF::SHT_SYMTAB || sec->sh_type != ELF::SHT_DYNSYM) // FIXME: Proper error handling. @@ -2518,11 +2461,9 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> return sec; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Shdr * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSection(uint32_t index) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Shdr * +ELFObjectFile<ELFT>::getSection(uint32_t index) const { if (index == 0) return 0; if (!SectionHeaderTable || index >= getNumSections()) @@ -2534,17 +2475,15 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> + (index * Header->e_shentsize)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const char *ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getString(uint32_t section, - ELF::Elf32_Word offset) const { +template<class ELFT> +const char *ELFObjectFile<ELFT>::getString(uint32_t section, + ELF::Elf32_Word offset) const { return getString(getSection(section), offset); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const char *ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getString(const Elf_Shdr *section, - ELF::Elf32_Word offset) const { +template<class ELFT> +const char *ELFObjectFile<ELFT>::getString(const Elf_Shdr *section, + ELF::Elf32_Word offset) const { assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); if (offset >= section->sh_size) // FIXME: Proper error handling. @@ -2552,11 +2491,10 @@ const char *ELFObjectFile<target_endianness, max_alignment, is64Bits> return (const char *)base() + section->sh_offset + offset; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolName(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolName(const Elf_Shdr *section, + const Elf_Sym *symb, + StringRef &Result) const { if (symb->st_name == 0) { const Elf_Shdr *section = getSection(symb); if (!section) @@ -2576,20 +2514,18 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionName(const Elf_Shdr *section, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionName(const Elf_Shdr *section, + StringRef &Result) const { Result = StringRef(getString(dot_shstrtab_sec, section->sh_name)); return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Version, - bool &IsDefault) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *symb, + StringRef &Version, + bool &IsDefault) const { // Handle non-dynamic symbols. if (section != SymbolTableSections[0]) { // Non-dynamic symbols can have versions in their names @@ -2667,51 +2603,43 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline DynRefImpl<target_endianness, max_alignment, is64Bits> - ::DynRefImpl(DataRefImpl DynP, const OwningType *Owner) +template<class ELFT> +inline DynRefImpl<ELFT>::DynRefImpl(DataRefImpl DynP, const OwningType *Owner) : DynPimpl(DynP) , OwningObject(Owner) {} -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline bool DynRefImpl<target_endianness, max_alignment, is64Bits> - ::operator==(const DynRefImpl &Other) const { +template<class ELFT> +inline bool DynRefImpl<ELFT>::operator==(const DynRefImpl &Other) const { return DynPimpl == Other.DynPimpl; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline bool DynRefImpl<target_endianness, max_alignment, is64Bits> - ::operator <(const DynRefImpl &Other) const { +template<class ELFT> +inline bool DynRefImpl<ELFT>::operator <(const DynRefImpl &Other) const { return DynPimpl < Other.DynPimpl; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline error_code DynRefImpl<target_endianness, max_alignment, is64Bits> - ::getNext(DynRefImpl &Result) const { +template<class ELFT> +inline error_code DynRefImpl<ELFT>::getNext(DynRefImpl &Result) const { return OwningObject->getDynNext(DynPimpl, Result); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline int64_t DynRefImpl<target_endianness, max_alignment, is64Bits> - ::getTag() const { +template<class ELFT> +inline int64_t DynRefImpl<ELFT>::getTag() const { return OwningObject->getDyn(DynPimpl)->d_tag; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline uint64_t DynRefImpl<target_endianness, max_alignment, is64Bits> - ::getVal() const { +template<class ELFT> +inline uint64_t DynRefImpl<ELFT>::getVal() const { return OwningObject->getDyn(DynPimpl)->d_un.d_val; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline uint64_t DynRefImpl<target_endianness, max_alignment, is64Bits> - ::getPtr() const { +template<class ELFT> +inline uint64_t DynRefImpl<ELFT>::getPtr() const { return OwningObject->getDyn(DynPimpl)->d_un.d_ptr; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline DataRefImpl DynRefImpl<target_endianness, max_alignment, is64Bits> - ::getRawDataRefImpl() const { +template<class ELFT> +inline DataRefImpl DynRefImpl<ELFT>::getRawDataRefImpl() const { return DynPimpl; } @@ -2722,23 +2650,23 @@ static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, StringRef &Version, bool &IsDefault) { // Little-endian 32-bit - if (const ELFObjectFile<support::little, 4, false> *ELFObj = - dyn_cast<ELFObjectFile<support::little, 4, false> >(Obj)) + if (const ELFObjectFile<ELFType<support::little, 4, false> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::little, 4, false> > >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 32-bit - if (const ELFObjectFile<support::big, 4, false> *ELFObj = - dyn_cast<ELFObjectFile<support::big, 4, false> >(Obj)) + if (const ELFObjectFile<ELFType<support::big, 4, false> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::big, 4, false> > >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Little-endian 64-bit - if (const ELFObjectFile<support::little, 8, true> *ELFObj = - dyn_cast<ELFObjectFile<support::little, 8, true> >(Obj)) + if (const ELFObjectFile<ELFType<support::little, 8, true> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::little, 8, true> > >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 64-bit - if (const ELFObjectFile<support::big, 8, true> *ELFObj = - dyn_cast<ELFObjectFile<support::big, 8, true> >(Obj)) + if (const ELFObjectFile<ELFType<support::big, 8, true> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::big, 8, true> > >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h index a17d58dae2..001cb6540a 100644 --- a/include/llvm/Object/MachOFormat.h +++ b/include/llvm/Object/MachOFormat.h @@ -64,7 +64,10 @@ namespace mach { CSARM_V7 = 9, CSARM_V7F = 10, CSARM_V7S = 11, - CSARM_V7K = 12 + CSARM_V7K = 12, + CSARM_V6M = 14, + CSARM_V7M = 15, + CSARM_V7EM = 16 }; /// \brief PowerPC Machine Subtypes. diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index e639a2cfa1..7e855b2f10 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -95,6 +95,12 @@ #define LLVM_OVERRIDE #endif +#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define LLVM_CONSTEXPR constexpr +#else +# define LLVM_CONSTEXPR +#endif + /// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked /// into a shared library, then the class should be private to the library and /// not accessible from outside it. Can also be used to mark variables and diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index b87ad75389..fcd7ce272a 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -1523,9 +1523,8 @@ Value *SCEVExpander::expand(const SCEV *S) { } // Check to see if we already expanded this here. - std::map<std::pair<const SCEV *, Instruction *>, - AssertingVH<Value> >::iterator I = - InsertedExpressions.find(std::make_pair(S, InsertPt)); + std::map<std::pair<const SCEV *, Instruction *>, TrackingVH<Value> >::iterator + I = InsertedExpressions.find(std::make_pair(S, InsertPt)); if (I != InsertedExpressions.end()) return I->second; diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 359c4cf8e4..a82410ae6a 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -5100,16 +5100,26 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) { // If we haven't found a load, we can't narrow it. Don't transform one with // multiple uses, this would require adding a new load. - if (!isa<LoadSDNode>(N0) || !N0.hasOneUse() || - // Don't change the width of a volatile load. - cast<LoadSDNode>(N0)->isVolatile()) + if (!isa<LoadSDNode>(N0) || !N0.hasOneUse()) + return SDValue(); + + // Don't change the width of a volatile load. + LoadSDNode *LN0 = cast<LoadSDNode>(N0); + if (LN0->isVolatile()) return SDValue(); // Verify that we are actually reducing a load width here. - if (cast<LoadSDNode>(N0)->getMemoryVT().getSizeInBits() < EVTBits) + if (LN0->getMemoryVT().getSizeInBits() < EVTBits) + return SDValue(); + + // For the transform to be legal, the load must produce only two values + // (the value loaded and the chain). Don't transform a pre-increment + // load, for example, which produces an extra value. Otherwise the + // transformation is not equivalent, and the downstream logic to replace + // uses gets things wrong. + if (LN0->getNumValues() > 2) return SDValue(); - LoadSDNode *LN0 = cast<LoadSDNode>(N0); EVT PtrType = N0.getOperand(1).getValueType(); if (PtrType == MVT::Untyped || PtrType.isExtended()) diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index ef5f589896..6f71ffb2fa 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -893,7 +893,8 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, /// from Src into IntVal, which is assumed to be wide enough and to hold zero. static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) { assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!"); - uint8_t *Dst = (uint8_t *)IntVal.getRawData(); + uint8_t *Dst = reinterpret_cast<uint8_t *>( + const_cast<uint64_t *>(IntVal.getRawData())); if (sys::isLittleEndianHost()) // Little-endian host - the destination must be ordered from LSB to MSB. diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp index 353bebf84a..66aeb772dd 100644 --- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -72,15 +72,20 @@ namespace { /// getBlockAfter - Return the memory block immediately after this one. /// MemoryRangeHeader &getBlockAfter() const { - return *(MemoryRangeHeader*)((char*)this+BlockSize); + return *reinterpret_cast<MemoryRangeHeader *>( + reinterpret_cast<char*>( + const_cast<MemoryRangeHeader *>(this))+BlockSize); } /// getFreeBlockBefore - If the block before this one is free, return it, /// otherwise return null. FreeRangeHeader *getFreeBlockBefore() const { if (PrevAllocated) return 0; - intptr_t PrevSize = ((intptr_t *)this)[-1]; - return (FreeRangeHeader*)((char*)this-PrevSize); + intptr_t PrevSize = reinterpret_cast<intptr_t *>( + const_cast<MemoryRangeHeader *>(this))[-1]; + return reinterpret_cast<FreeRangeHeader *>( + reinterpret_cast<char*>( + const_cast<MemoryRangeHeader *>(this))-PrevSize); } /// FreeBlock - Turn an allocated block into a free block, adjusting diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 1524b48c54..b8537b1f2f 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -28,8 +28,6 @@ using namespace llvm; using namespace llvm::object; -using support::endianness; - namespace { static inline @@ -40,22 +38,22 @@ error_code check(error_code Err) { return Err; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> class DyldELFObject - : public ELFObjectFile<target_endianness, max_alignment, is64Bits> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + : public ELFObjectFile<ELFT> { + LLVM_ELF_IMPORT_TYPES(ELFT) - typedef Elf_Shdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Shdr; - typedef Elf_Sym_Impl<target_endianness, max_alignment, is64Bits> Elf_Sym; + typedef Elf_Shdr_Impl<ELFT> Elf_Shdr; + typedef Elf_Sym_Impl<ELFT> Elf_Sym; typedef - Elf_Rel_Impl<target_endianness, max_alignment, is64Bits, false> Elf_Rel; + Elf_Rel_Impl<ELFT, false> Elf_Rel; typedef - Elf_Rel_Impl<target_endianness, max_alignment, is64Bits, true> Elf_Rela; + Elf_Rel_Impl<ELFT, true> Elf_Rela; - typedef Elf_Ehdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Ehdr; + typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr; typedef typename ELFDataTypeTypedefHelper< - target_endianness, max_alignment, is64Bits>::value_type addr_type; + ELFT>::value_type addr_type; public: DyldELFObject(MemoryBuffer *Wrapper, error_code &ec); @@ -65,25 +63,25 @@ public: // Methods for type inquiry through isa, cast and dyn_cast static inline bool classof(const Binary *v) { - return (isa<ELFObjectFile<target_endianness, max_alignment, is64Bits> >(v) + return (isa<ELFObjectFile<ELFT> >(v) && classof(cast<ELFObjectFile - <target_endianness, max_alignment, is64Bits> >(v))); + <ELFT> >(v))); } static inline bool classof( - const ELFObjectFile<target_endianness, max_alignment, is64Bits> *v) { + const ELFObjectFile<ELFT> *v) { return v->isDyldType(); } }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> class ELFObjectImage : public ObjectImageCommon { protected: - DyldELFObject<target_endianness, max_alignment, is64Bits> *DyldObj; + DyldELFObject<ELFT> *DyldObj; bool Registered; public: ELFObjectImage(ObjectBuffer *Input, - DyldELFObject<target_endianness, max_alignment, is64Bits> *Obj) + DyldELFObject<ELFT> *Obj) : ObjectImageCommon(Input, Obj), DyldObj(Obj), Registered(false) {} @@ -119,16 +117,15 @@ class ELFObjectImage : public ObjectImageCommon { // The MemoryBuffer passed into this constructor is just a wrapper around the // actual memory. Ultimately, the Binary parent class will take ownership of // this MemoryBuffer object but not the underlying memory. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -DyldELFObject<target_endianness, max_alignment, is64Bits> - ::DyldELFObject(MemoryBuffer *Wrapper, error_code &ec) - : ELFObjectFile<target_endianness, max_alignment, is64Bits>(Wrapper, ec) { +template<class ELFT> +DyldELFObject<ELFT>::DyldELFObject(MemoryBuffer *Wrapper, error_code &ec) + : ELFObjectFile<ELFT>(Wrapper, ec) { this->isDyldELFObject = true; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void DyldELFObject<target_endianness, max_alignment, is64Bits> - ::updateSectionAddress(const SectionRef &Sec, uint64_t Addr) { +template<class ELFT> +void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec, + uint64_t Addr) { DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); Elf_Shdr *shdr = const_cast<Elf_Shdr*>( reinterpret_cast<const Elf_Shdr *>(ShdrRef.p)); @@ -138,13 +135,12 @@ void DyldELFObject<target_endianness, max_alignment, is64Bits> shdr->sh_addr = static_cast<addr_type>(Addr); } -template<endianness target_endianness, std::size_t max_align, bool is64Bits> -void DyldELFObject<target_endianness, max_align, is64Bits> - ::updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr){ +template<class ELFT> +void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef, + uint64_t Addr) { Elf_Sym *sym = const_cast<Elf_Sym*>( - ELFObjectFile<target_endianness, max_align, is64Bits> - ::getSymbol(SymRef.getRawDataRefImpl())); + ELFObjectFile<ELFT>::getSymbol(SymRef.getRawDataRefImpl())); // This assumes the address passed in matches the target address bitness // The template-based type cast handles everything else. @@ -164,24 +160,28 @@ ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) { error_code ec; if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) { - DyldELFObject<support::little, 4, false> *Obj = - new DyldELFObject<support::little, 4, false>(Buffer->getMemBuffer(), ec); - return new ELFObjectImage<support::little, 4, false>(Buffer, Obj); + DyldELFObject<ELFType<support::little, 4, false> > *Obj = + new DyldELFObject<ELFType<support::little, 4, false> >( + Buffer->getMemBuffer(), ec); + return new ELFObjectImage<ELFType<support::little, 4, false> >(Buffer, Obj); } else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) { - DyldELFObject<support::big, 4, false> *Obj = - new DyldELFObject<support::big, 4, false>(Buffer->getMemBuffer(), ec); - return new ELFObjectImage<support::big, 4, false>(Buffer, Obj); + DyldELFObject<ELFType<support::big, 4, false> > *Obj = + new DyldELFObject<ELFType<support::big, 4, false> >( + Buffer->getMemBuffer(), ec); + return new ELFObjectImage<ELFType<support::big, 4, false> >(Buffer, Obj); } else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) { - DyldELFObject<support::big, 8, true> *Obj = - new DyldELFObject<support::big, 8, true>(Buffer->getMemBuffer(), ec); - return new ELFObjectImage<support::big, 8, true>(Buffer, Obj); + DyldELFObject<ELFType<support::big, 8, true> > *Obj = + new DyldELFObject<ELFType<support::big, 8, true> >( + Buffer->getMemBuffer(), ec); + return new ELFObjectImage<ELFType<support::big, 8, true> >(Buffer, Obj); } else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { - DyldELFObject<support::little, 8, true> *Obj = - new DyldELFObject<support::little, 8, true>(Buffer->getMemBuffer(), ec); - return new ELFObjectImage<support::little, 8, true>(Buffer, Obj); + DyldELFObject<ELFType<support::little, 8, true> > *Obj = + new DyldELFObject<ELFType<support::little, 8, true> >( + Buffer->getMemBuffer(), ec); + return new ELFObjectImage<ELFType<support::little, 8, true> >(Buffer, Obj); } else llvm_unreachable("Unexpected ELF format"); diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 26398ce851..aba0fc92f2 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -2386,11 +2386,11 @@ CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty, CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore) { - assert(S->getType()->isPointerTy() && "Invalid cast"); - assert((Ty->isIntegerTy() || Ty->isPointerTy()) && + assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast"); + assert((Ty->isIntOrIntVectorTy() || Ty->isPtrOrPtrVectorTy()) && "Invalid cast"); - if (Ty->isIntegerTy()) + if (Ty->isIntOrIntVectorTy()) return Create(Instruction::PtrToInt, S, Ty, Name, InsertBefore); return Create(Instruction::BitCast, S, Ty, Name, InsertBefore); } diff --git a/lib/IR/Use.cpp b/lib/IR/Use.cpp index 481cbab7c2..1d343e8030 100644 --- a/lib/IR/Use.cpp +++ b/lib/IR/Use.cpp @@ -139,7 +139,7 @@ User *Use::getUser() const { const UserRef *ref = reinterpret_cast<const UserRef*>(End); return ref->getInt() ? ref->getPointer() - : (User*)End; + : reinterpret_cast<User*>(const_cast<Use*>(End)); } } // End llvm namespace diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 4252764f7a..2488a7de16 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -200,6 +200,8 @@ namespace { E = M.named_metadata_end(); I != E; ++I) visitNamedMDNode(*I); + visitModuleFlags(M); + // If the module is broken, abort at this time. return abortIfBroken(); } @@ -240,6 +242,9 @@ namespace { void visitGlobalAlias(GlobalAlias &GA); void visitNamedMDNode(NamedMDNode &NMD); void visitMDNode(MDNode &MD, Function *F); + void visitModuleFlags(Module &M); + void visitModuleFlag(MDNode *Op, DenseMap<MDString*, MDNode*> &SeenIDs, + SmallVectorImpl<MDNode*> &Requirements); void visitFunction(Function &F); void visitBasicBlock(BasicBlock &BB); using InstVisitor<Verifier>::visit; @@ -521,6 +526,86 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) { } } +void Verifier::visitModuleFlags(Module &M) { + const NamedMDNode *Flags = M.getModuleFlagsMetadata(); + if (!Flags) return; + + // Scan each flag, and track the flags and requirements. + DenseMap<MDString*, MDNode*> SeenIDs; + SmallVector<MDNode*, 16> Requirements; + for (unsigned I = 0, E = Flags->getNumOperands(); I != E; ++I) { + visitModuleFlag(Flags->getOperand(I), SeenIDs, Requirements); + } + + // Validate that the requirements in the module are valid. + for (unsigned I = 0, E = Requirements.size(); I != E; ++I) { + MDNode *Requirement = Requirements[I]; + MDString *Flag = cast<MDString>(Requirement->getOperand(0)); + Value *ReqValue = Requirement->getOperand(1); + + MDNode *Op = SeenIDs.lookup(Flag); + if (!Op) { + CheckFailed("invalid requirement on flag, flag is not present in module", + Flag); + continue; + } + + if (Op->getOperand(2) != ReqValue) { + CheckFailed(("invalid requirement on flag, " + "flag does not have the required value"), + Flag); + continue; + } + } +} + +void Verifier::visitModuleFlag(MDNode *Op, DenseMap<MDString*, MDNode*>&SeenIDs, + SmallVectorImpl<MDNode*> &Requirements) { + // Each module flag should have three arguments, the merge behavior (a + // constant int), the flag ID (an MDString), and the value. + Assert1(Op->getNumOperands() == 3, + "incorrect number of operands in module flag", Op); + ConstantInt *Behavior = dyn_cast<ConstantInt>(Op->getOperand(0)); + MDString *ID = dyn_cast<MDString>(Op->getOperand(1)); + Assert1(Behavior, + "invalid behavior operand in module flag (expected constant integer)", + Op->getOperand(0)); + unsigned BehaviorValue = Behavior->getZExtValue(); + Assert1((Module::Error <= BehaviorValue && + BehaviorValue <= Module::Override), + "invalid behavior operand in module flag (unexpected constant)", + Op->getOperand(0)); + Assert1(ID, + "invalid ID operand in module flag (expected metadata string)", + Op->getOperand(1)); + + // Unless this is a "requires" flag, check the ID is unique. + if (BehaviorValue != Module::Require) { + bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second; + Assert1(Inserted, + "module flag identifiers must be unique (or of 'require' type)", + ID); + } + + // If this is a "requires" flag, sanity check the value. + if (BehaviorValue == Module::Require) { + // The value should itself be an MDNode with two operands, a flag ID (an + // MDString), and a value. + MDNode *Value = dyn_cast<MDNode>(Op->getOperand(2)); + Assert1(Value && Value->getNumOperands() == 2, + "invalid value for 'require' module flag (expected metadata pair)", + Op->getOperand(2)); + Assert1(isa<MDString>(Value->getOperand(0)), + ("invalid value for 'require' module flag " + "(first value operand should be a string)"), + Value->getOperand(0)); + + // Append it to the list of requirements, to check once all module flags are + // scanned. + Requirements.push_back(Value); + } +} + // VerifyParameterAttrs - Check the given attributes for an argument or return // value of the specified type. The value V is printed in error messages. void Verifier::VerifyParameterAttrs(Attribute Attrs, Type *Ty, diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index e69b819cca..15a4a1e24b 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -1021,19 +1021,10 @@ categorizeModuleFlagNodes(const NamedMDNode *ModFlags, for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) { MDNode *Op = ModFlags->getOperand(I); - assert(Op->getNumOperands() == 3 && "Invalid module flag metadata!"); - assert(isa<ConstantInt>(Op->getOperand(0)) && - "Module flag's first operand must be an integer!"); - assert(isa<MDString>(Op->getOperand(1)) && - "Module flag's second operand must be an MDString!"); - ConstantInt *Behavior = cast<ConstantInt>(Op->getOperand(0)); MDString *ID = cast<MDString>(Op->getOperand(1)); Value *Val = Op->getOperand(2); switch (Behavior->getZExtValue()) { - default: - assert(false && "Invalid behavior in module flag metadata!"); - break; case Module::Error: { MDNode *&ErrNode = ErrorNode[ID]; if (!ErrNode) ErrNode = Op; @@ -1146,8 +1137,6 @@ bool ModuleLinker::linkModuleFlagsMetadata() { for (SmallSetVector<MDNode*, 8>::iterator II = Set.begin(), IE = Set.end(); II != IE; ++II) { MDNode *Node = *II; - assert(isa<MDNode>(Node->getOperand(2)) && - "Module flag's third operand must be an MDNode!"); MDNode *Val = cast<MDNode>(Node->getOperand(2)); MDString *ReqID = cast<MDString>(Val->getOperand(0)); diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 5fdc57ad30..e5d4995e16 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -38,6 +38,8 @@ STATISTIC(EmittedRelaxableFragments, "Number of emitted assembler fragments - relaxable"); STATISTIC(EmittedDataFragments, "Number of emitted assembler fragments - data"); +STATISTIC(EmittedCompactEncodedInstFragments, + "Number of emitted assembler fragments - compact encoded inst"); STATISTIC(EmittedAlignFragments, "Number of emitted assembler fragments - align"); STATISTIC(EmittedFillFragments, @@ -222,6 +224,11 @@ MCEncodedFragment::~MCEncodedFragment() { /* *** */ +MCEncodedFragmentWithFixups::~MCEncodedFragmentWithFixups() { +} + +/* *** */ + MCSectionData::MCSectionData() : Section(0) {} MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) @@ -388,6 +395,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, switch (F.getKind()) { case MCFragment::FT_Data: case MCFragment::FT_Relaxable: + case MCFragment::FT_CompactEncodedInst: return cast<MCEncodedFragment>(F).getContents().size(); case MCFragment::FT_Fill: return cast<MCFillFragment>(F).getSize(); @@ -458,7 +466,7 @@ void MCAsmLayout::layoutFragment(MCFragment *F) { // // // BundlePadding - // ||| + // ||| // ------------------------------------- // Prev |##########| F | // ------------------------------------- @@ -497,6 +505,9 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment &F) { MCObjectWriter *OW = &Asm.getWriter(); + // FIXME: Embed in fragments instead? + uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F); + // Should NOP padding be written out before this fragment? unsigned BundlePadding = F.getBundlePadding(); if (BundlePadding > 0) { @@ -505,6 +516,22 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, assert(F.hasInstructions() && "Writing bundle padding for a fragment without instructions"); + unsigned TotalLength = BundlePadding + static_cast<unsigned>(FragmentSize); + if (F.alignToBundleEnd() && TotalLength > Asm.getBundleAlignSize()) { + // If the padding itself crosses a bundle boundary, it must be emitted + // in 2 pieces, since even nop instructions must not cross boundaries. + // v--------------v <- BundleAlignSize + // v---------v <- BundlePadding + // ---------------------------- + // | Prev |####|####| F | + // ---------------------------- + // ^-------------------^ <- TotalLength + unsigned DistanceToBoundary = TotalLength - Asm.getBundleAlignSize(); + if (!Asm.getBackend().writeNopData(DistanceToBoundary, OW)) + report_fatal_error("unable to write NOP sequence of " + + Twine(DistanceToBoundary) + " bytes"); + BundlePadding -= DistanceToBoundary; + } if (!Asm.getBackend().writeNopData(BundlePadding, OW)) report_fatal_error("unable to write NOP sequence of " + Twine(BundlePadding) + " bytes"); @@ -517,8 +544,6 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, ++stats::EmittedFragments; - // FIXME: Embed in fragments instead? - uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F); switch (F.getKind()) { case MCFragment::FT_Align: { ++stats::EmittedAlignFragments; @@ -570,6 +595,11 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, writeFragmentContents(F, OW); break; + case MCFragment::FT_CompactEncodedInst: + ++stats::EmittedCompactEncodedInstFragments; + writeFragmentContents(F, OW); + break; + case MCFragment::FT_Fill: { ++stats::EmittedFillFragments; MCFillFragment &FF = cast<MCFillFragment>(F); @@ -742,9 +772,10 @@ void MCAssembler::Finish() { for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) { for (MCSectionData::iterator it2 = it->begin(), ie2 = it->end(); it2 != ie2; ++it2) { - MCEncodedFragment *F = dyn_cast<MCEncodedFragment>(it2); + MCEncodedFragmentWithFixups *F = + dyn_cast<MCEncodedFragmentWithFixups>(it2); if (F) { - for (MCEncodedFragment::fixup_iterator it3 = F->fixup_begin(), + for (MCEncodedFragmentWithFixups::fixup_iterator it3 = F->fixup_begin(), ie3 = F->fixup_end(); it3 != ie3; ++it3) { MCFixup &Fixup = *it3; uint64_t FixedValue = handleFixup(Layout, *F, Fixup); @@ -954,6 +985,8 @@ void MCFragment::dump() { switch (getKind()) { case MCFragment::FT_Align: OS << "MCAlignFragment"; break; case MCFragment::FT_Data: OS << "MCDataFragment"; break; + case MCFragment::FT_CompactEncodedInst: + OS << "MCCompactEncodedInstFragment"; break; case MCFragment::FT_Fill: OS << "MCFillFragment"; break; case MCFragment::FT_Relaxable: OS << "MCRelaxableFragment"; break; case MCFragment::FT_Org: OS << "MCOrgFragment"; break; @@ -1001,6 +1034,19 @@ void MCFragment::dump() { } break; } + case MCFragment::FT_CompactEncodedInst: { + const MCCompactEncodedInstFragment *CEIF = + cast<MCCompactEncodedInstFragment>(this); + OS << "\n "; + OS << " Contents:["; + const SmallVectorImpl<char> &Contents = CEIF->getContents(); + for (unsigned i = 0, e = Contents.size(); i != e; ++i) { + if (i) OS << ","; + OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF); + } + OS << "] (" << Contents.size() << " bytes)"; + break; + } case MCFragment::FT_Fill: { const MCFillFragment *FF = cast<MCFillFragment>(this); OS << " Value:" << FF->getValue() << " ValueSize:" << FF->getValueSize() @@ -1094,7 +1140,9 @@ void MCAssembler::dump() { // anchors for MC*Fragment vtables void MCEncodedFragment::anchor() { } +void MCEncodedFragmentWithFixups::anchor() { } void MCDataFragment::anchor() { } +void MCCompactEncodedInstFragment::anchor() { } void MCRelaxableFragment::anchor() { } void MCAlignFragment::anchor() { } void MCFillFragment::anchor() { } diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index cae73be298..e5b749e28b 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -371,8 +371,10 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) { // data fragment). // // If bundling is enabled: - // - If we're not in a bundle-locked group, emit the instruction into a data - // fragment of its own. + // - If we're not in a bundle-locked group, emit the instruction into a + // fragment of its own. If there are no fixups registered for the + // instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a + // MCDataFragment. // - If we're in a bundle-locked group, append the instruction to the current // data fragment because we want all the instructions in a group to get into // the same fragment. Be careful not to do that for the first instruction in @@ -383,6 +385,14 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) { MCSectionData *SD = getCurrentSectionData(); if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst()) DF = getOrCreateDataFragment(); + else if (!SD->isBundleLocked() && Fixups.size() == 0) { + // Optimize memory usage by emitting the instruction to a + // MCCompactEncodedInstFragment when not in a bundle-locked group and + // there are no fixups registered. + MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(SD); + CEIF->getContents().append(Code.begin(), Code.end()); + return; + } else { DF = new MCDataFragment(SD); if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) { diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 45aaa2ec75..43c872b809 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -50,26 +50,11 @@ MCAsmParserSemaCallback::~MCAsmParserSemaCallback() {} namespace { -/// \brief Helper class for tracking macro definitions. -typedef std::vector<MCAsmMacroArgument> MacroArguments; -typedef std::pair<StringRef, MCAsmMacroArgument> MacroParameter; -typedef std::vector<MacroParameter> MacroParameters; - -struct Macro { - StringRef Name; - StringRef Body; - MacroParameters Parameters; - -public: - Macro(StringRef N, StringRef B, const MacroParameters &P) : - Name(N), Body(B), Parameters(P) {} -}; - /// \brief Helper class for storing information about an active macro /// instantiation. struct MacroInstantiation { /// The macro being instantiated. - const Macro *TheMacro; + const MCAsmMacro *TheMacro; /// The macro instantiation with substitutions. MemoryBuffer *Instantiation; @@ -84,7 +69,7 @@ struct MacroInstantiation { SMLoc ExitLoc; public: - MacroInstantiation(const Macro *M, SMLoc IL, int EB, SMLoc EL, + MacroInstantiation(const MCAsmMacro *M, SMLoc IL, int EB, SMLoc EL, MemoryBuffer *I); }; @@ -115,8 +100,6 @@ struct ParseStatementInfo { /// \brief The concrete assembly parser instance. class AsmParser : public MCAsmParser { - friend class GenericAsmParser; - AsmParser(const AsmParser &) LLVM_DELETED_FUNCTION; void operator=(const AsmParser &) LLVM_DELETED_FUNCTION; private: @@ -127,7 +110,6 @@ private: SourceMgr &SrcMgr; SourceMgr::DiagHandlerTy SavedDiagHandler; void *SavedDiagContext; - MCAsmParserExtension *GenericParser; MCAsmParserExtension *PlatformParser; /// This is the current buffer index we're lexing from as managed by the @@ -137,14 +119,15 @@ private: AsmCond TheCondState; std::vector<AsmCond> TheCondStack; - /// DirectiveMap - This is a table handlers for directives. Each handler is - /// invoked after the directive identifier is read and is responsible for - /// parsing and validating the rest of the directive. The handler is passed - /// in the directive name and the location of the directive keyword. - StringMap<std::pair<MCAsmParserExtension*, DirectiveHandler> > DirectiveMap; + /// ExtensionDirectiveMap - maps directive names to handler methods in parser + /// extensions. Extensions register themselves in this map by calling + /// AddDirectiveHandler. + typedef std::pair<MCAsmParserExtension*, DirectiveHandler> + ExtensionDirectiveHandler; + StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap; /// MacroMap - Map of currently defined macros. - StringMap<Macro*> MacroMap; + StringMap<MCAsmMacro*> MacroMap; /// ActiveMacros - Stack of active macro instantiations. std::vector<MacroInstantiation*> ActiveMacros; @@ -180,7 +163,7 @@ public: virtual void AddDirectiveHandler(MCAsmParserExtension *Object, StringRef Directive, DirectiveHandler Handler) { - DirectiveMap[Directive] = std::make_pair(Object, Handler); + ExtensionDirectiveMap[Directive] = std::make_pair(Object, Handler); } public: @@ -225,6 +208,9 @@ public: virtual bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc); virtual bool ParseAbsoluteExpression(int64_t &Res); + bool ParseMacroArgument(MCAsmMacroArgument &MA, + AsmToken::TokenKind &ArgumentDelimiter); + /// ParseIdentifier - Parse an identifier or string (as a quoted identifier) /// and set \p Res to the identifier contents. virtual bool ParseIdentifier(StringRef &Res); @@ -233,6 +219,14 @@ public: virtual bool MacrosEnabled() {return MacrosEnabledFlag;} virtual void SetMacrosEnabled(bool flag) {MacrosEnabledFlag = flag;} + virtual const MCAsmMacro* LookupMacro(StringRef Name); + virtual void DefineMacro(StringRef Name, const MCAsmMacro& Macro); + virtual void UndefineMacro(StringRef Name); + + virtual bool InsideMacroInstantiation() {return !ActiveMacros.empty();} + virtual bool HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc); + void HandleMacroExit(); + virtual void CheckForValidSection(); /// } @@ -242,12 +236,10 @@ private: void EatToEndOfLine(); bool ParseCppHashLineFilenameComment(const SMLoc &L); - bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M); bool expandMacro(raw_svector_ostream &OS, StringRef Body, - const MacroParameters &Parameters, - const MacroArguments &A, + const MCAsmMacroParameters &Parameters, + const MCAsmMacroArguments &A, const SMLoc &L); - void HandleMacroExit(); void PrintMacroInstantiations(); void PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, @@ -270,9 +262,7 @@ private: /// location. void JumpToLoc(SMLoc Loc, int InBuffer=-1); - bool ParseMacroArgument(MCAsmMacroArgument &MA, - AsmToken::TokenKind &ArgumentDelimiter); - bool ParseMacroArguments(const Macro *M, MacroArguments &A); + bool ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A); /// \brief Parse up to the end of statement and a return the contents from the /// current token until the end of the statement; the current token on exit @@ -291,8 +281,9 @@ private: bool ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc); bool ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc); - // Directive Parsing. + bool ParseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); + // Generic (target and platform independent) directive parsing. enum DirectiveKind { DK_NO_DIRECTIVE, // Placeholder DK_SET, DK_EQU, DK_EQUIV, DK_ASCII, DK_ASCIZ, DK_STRING, DK_BYTE, DK_SHORT, @@ -306,10 +297,21 @@ private: DK_WEAK_DEF_CAN_BE_HIDDEN, DK_COMM, DK_COMMON, DK_LCOMM, DK_ABORT, DK_INCLUDE, DK_INCBIN, DK_CODE16, DK_CODE16GCC, DK_REPT, DK_IRP, DK_IRPC, DK_IF, DK_IFB, DK_IFNB, DK_IFC, DK_IFNC, DK_IFDEF, DK_IFNDEF, DK_IFNOTDEF, - DK_ELSEIF, DK_ELSE, DK_ENDIF + DK_ELSEIF, DK_ELSE, DK_ENDIF, + DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS, + DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA, + DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER, + DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA, + DK_CFI_REMEMBER_STATE, DK_CFI_RESTORE_STATE, DK_CFI_SAME_VALUE, + DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED, + DK_CFI_REGISTER, + DK_MACROS_ON, DK_MACROS_OFF, DK_MACRO, DK_ENDM, DK_ENDMACRO, DK_PURGEM, + DK_SLEB128, DK_ULEB128 }; - StringMap<DirectiveKind> DirectiveKindMapping; + /// DirectiveKindMap - Maps directive name --> DirectiveKind enum, for + /// directives parsed by this class. + StringMap<DirectiveKind> DirectiveKindMap; // ".ascii", ".asciz", ".string" bool ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); @@ -323,6 +325,38 @@ private: // ".align{,32}", ".p2align{,w,l}" bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize); + // ".file", ".line", ".loc", ".stabs" + bool ParseDirectiveFile(SMLoc DirectiveLoc); + bool ParseDirectiveLine(); + bool ParseDirectiveLoc(); + bool ParseDirectiveStabs(); + + // .cfi directives + bool ParseDirectiveCFIRegister(SMLoc DirectiveLoc); + bool ParseDirectiveCFISections(); + bool ParseDirectiveCFIStartProc(); + bool ParseDirectiveCFIEndProc(); + bool ParseDirectiveCFIDefCfaOffset(); + bool ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc); + bool ParseDirectiveCFIAdjustCfaOffset(); + bool ParseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc); + bool ParseDirectiveCFIOffset(SMLoc DirectiveLoc); + bool ParseDirectiveCFIRelOffset(SMLoc DirectiveLoc); + bool ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality); + bool ParseDirectiveCFIRememberState(); + bool ParseDirectiveCFIRestoreState(); + bool ParseDirectiveCFISameValue(SMLoc DirectiveLoc); + bool ParseDirectiveCFIRestore(SMLoc DirectiveLoc); + bool ParseDirectiveCFIEscape(); + bool ParseDirectiveCFISignalFrame(); + bool ParseDirectiveCFIUndefined(SMLoc DirectiveLoc); + + // macro directives + bool ParseDirectivePurgeMacro(SMLoc DirectiveLoc); + bool ParseDirectiveEndMacro(StringRef Directive); + bool ParseDirectiveMacro(SMLoc DirectiveLoc); + bool ParseDirectiveMacrosOnOff(StringRef Directive); + // ".bundle_align_mode" bool ParseDirectiveBundleAlignMode(); // ".bundle_lock" @@ -330,6 +364,12 @@ private: // ".bundle_unlock" bool ParseDirectiveBundleUnlock(); + // ".space", ".skip" + bool ParseDirectiveSpace(StringRef IDVal); + + // .sleb128 (Signed=true) and .uleb128 (Signed=false) + bool ParseDirectiveLEB128(bool Signed); + /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which /// accepts a single symbol (which should be a label or an external). bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr); @@ -359,8 +399,8 @@ private: MCSymbolRefExpr::VariantKind Variant); // Macro-like directives - Macro *ParseMacroLikeBody(SMLoc DirectiveLoc); - void InstantiateMacroLikeBody(Macro *M, SMLoc DirectiveLoc, + MCAsmMacro *ParseMacroLikeBody(SMLoc DirectiveLoc); + void InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, raw_svector_ostream &OS); bool ParseDirectiveRept(SMLoc DirectiveLoc); // ".rept" bool ParseDirectiveIrp(SMLoc DirectiveLoc); // ".irp" @@ -370,125 +410,8 @@ private: // "_emit" bool ParseDirectiveEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info); - void initializeDirectiveKindMapping(); -}; - -/// \brief Generic implementation of directive handling, etc. which is shared -/// (or the default, at least) for all assembler parsers. -class GenericAsmParser : public MCAsmParserExtension { - template<bool (GenericAsmParser::*Handler)(StringRef, SMLoc)> - void AddDirectiveHandler(StringRef Directive) { - getParser().AddDirectiveHandler(this, Directive, - HandleDirective<GenericAsmParser, Handler>); - } -public: - GenericAsmParser() {} - - AsmParser &getParser() { - return (AsmParser&) this->MCAsmParserExtension::getParser(); - } - - virtual void Initialize(MCAsmParser &Parser) { - // Call the base implementation. - this->MCAsmParserExtension::Initialize(Parser); - - // Debugging directives. - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveFile>(".file"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLine>(".line"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLoc>(".loc"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveStabs>(".stabs"); - - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveSpace>(".space"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveSpace>(".skip"); - - // CFI directives. - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFISections>( - ".cfi_sections"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIStartProc>( - ".cfi_startproc"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIEndProc>( - ".cfi_endproc"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfa>( - ".cfi_def_cfa"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaOffset>( - ".cfi_def_cfa_offset"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset>( - ".cfi_adjust_cfa_offset"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaRegister>( - ".cfi_def_cfa_register"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIOffset>( - ".cfi_offset"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIRelOffset>( - ".cfi_rel_offset"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_personality"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_lsda"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIRememberState>(".cfi_remember_state"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIRestoreState>(".cfi_restore_state"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFISameValue>(".cfi_same_value"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIRestore>(".cfi_restore"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIEscape>(".cfi_escape"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFISignalFrame>(".cfi_signal_frame"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIUndefined>(".cfi_undefined"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIRegister>(".cfi_register"); - - // Macro directives. - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>( - ".macros_on"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>( - ".macros_off"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacro>(".macro"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveEndMacro>(".endm"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveEndMacro>(".endmacro"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectivePurgeMacro>(".purgem"); - - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLEB128>(".sleb128"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLEB128>(".uleb128"); - } - - bool ParseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); - - bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveStabs(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveSpace(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFISections(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIStartProc(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIDefCfa(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIDefCfaOffset(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIAdjustCfaOffset(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIDefCfaRegister(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIRelOffset(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIPersonalityOrLsda(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIRememberState(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIRestoreState(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFISameValue(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIRestore(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIEscape(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFISignalFrame(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIUndefined(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIRegister(StringRef, SMLoc DirectiveLoc); - - bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveEndMacro(StringRef, SMLoc DirectiveLoc); - bool ParseDirectivePurgeMacro(StringRef, SMLoc DirectiveLoc); - - bool ParseDirectiveLEB128(StringRef, SMLoc); + void initializeDirectiveKindMap(); }; - } namespace llvm { @@ -504,7 +427,7 @@ enum { DEFAULT_ADDRSPACE = 0 }; AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM), - GenericParser(new GenericAsmParser), PlatformParser(0), + PlatformParser(0), CurBuffer(0), MacrosEnabledFlag(true), CppHashLineNumber(0), AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) { // Save the old handler. @@ -514,9 +437,6 @@ AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, SrcMgr.setDiagHandler(DiagHandler, this); Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); - // Initialize the generic parser. - GenericParser->Initialize(*this); - // Initialize the platform / file format parser. // // FIXME: This is a hack, we need to (majorly) cleanup how these objects are @@ -533,19 +453,18 @@ AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, PlatformParser->Initialize(*this); } - initializeDirectiveKindMapping(); + initializeDirectiveKindMap(); } AsmParser::~AsmParser() { assert(ActiveMacros.empty() && "Unexpected active macro instantiation!"); // Destroy any macros. - for (StringMap<Macro*>::iterator it = MacroMap.begin(), + for (StringMap<MCAsmMacro*>::iterator it = MacroMap.begin(), ie = MacroMap.end(); it != ie; ++it) delete it->getValue(); delete PlatformParser; - delete GenericParser; } void AsmParser::PrintMacroInstantiations() { @@ -1182,10 +1101,10 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // have to do this so that .endif isn't skipped in a ".if 0" block for // example. StringMap<DirectiveKind>::const_iterator DirKindIt = - DirectiveKindMapping.find(IDVal); + DirectiveKindMap.find(IDVal); DirectiveKind DirKind = - (DirKindIt == DirectiveKindMapping.end()) ? DK_NO_DIRECTIVE : - DirKindIt->getValue(); + (DirKindIt == DirectiveKindMap.end()) ? DK_NO_DIRECTIVE : + DirKindIt->getValue(); switch (DirKind) { default: break; @@ -1278,16 +1197,39 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // If macros are enabled, check to see if this is a macro instantiation. if (MacrosEnabled()) - if (const Macro *M = MacroMap.lookup(IDVal)) - return HandleMacroEntry(IDVal, IDLoc, M); + if (const MCAsmMacro *M = LookupMacro(IDVal)) { + return HandleMacroEntry(M, IDLoc); + } // Otherwise, we have a normal instruction or directive. + + // Directives start with "." if (IDVal[0] == '.' && IDVal != ".") { - - // Target hook for parsing target specific directives. + // There are several entities interested in parsing directives: + // + // 1. The target-specific assembly parser. Some directives are target + // specific or may potentially behave differently on certain targets. + // 2. Asm parser extensions. For example, platform-specific parsers + // (like the ELF parser) register themselves as extensions. + // 3. The generic directive parser implemented by this class. These are + // all the directives that behave in a target and platform independent + // manner, or at least have a default behavior that's shared between + // all targets and platforms. + + // First query the target-specific parser. It will return 'true' if it + // isn't interested in this directive. if (!getTargetParser().ParseDirective(ID)) return false; + // Next, check the extention directive map to see if any extension has + // registered itself to parse this directive. + std::pair<MCAsmParserExtension*, DirectiveHandler> Handler = + ExtensionDirectiveMap.lookup(IDVal); + if (Handler.first) + return (*Handler.second)(Handler.first, IDVal, IDLoc); + + // Finally, if no one else is interested in this directive, it must be + // generic and familiar to this class. switch (DirKind) { default: break; @@ -1397,14 +1339,71 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { return ParseDirectiveBundleLock(); case DK_BUNDLE_UNLOCK: return ParseDirectiveBundleUnlock(); + case DK_SLEB128: + return ParseDirectiveLEB128(true); + case DK_ULEB128: + return ParseDirectiveLEB128(false); + case DK_SPACE: + case DK_SKIP: + return ParseDirectiveSpace(IDVal); + case DK_FILE: + return ParseDirectiveFile(IDLoc); + case DK_LINE: + return ParseDirectiveLine(); + case DK_LOC: + return ParseDirectiveLoc(); + case DK_STABS: + return ParseDirectiveStabs(); + case DK_CFI_SECTIONS: + return ParseDirectiveCFISections(); + case DK_CFI_STARTPROC: + return ParseDirectiveCFIStartProc(); + case DK_CFI_ENDPROC: + return ParseDirectiveCFIEndProc(); + case DK_CFI_DEF_CFA: + return ParseDirectiveCFIDefCfa(IDLoc); + case DK_CFI_DEF_CFA_OFFSET: + return ParseDirectiveCFIDefCfaOffset(); + case DK_CFI_ADJUST_CFA_OFFSET: + return ParseDirectiveCFIAdjustCfaOffset(); + case DK_CFI_DEF_CFA_REGISTER: + return ParseDirectiveCFIDefCfaRegister(IDLoc); + case DK_CFI_OFFSET: + return ParseDirectiveCFIOffset(IDLoc); + case DK_CFI_REL_OFFSET: + return ParseDirectiveCFIRelOffset(IDLoc); + case DK_CFI_PERSONALITY: + return ParseDirectiveCFIPersonalityOrLsda(true); + case DK_CFI_LSDA: + return ParseDirectiveCFIPersonalityOrLsda(false); + case DK_CFI_REMEMBER_STATE: + return ParseDirectiveCFIRememberState(); + case DK_CFI_RESTORE_STATE: + return ParseDirectiveCFIRestoreState(); + case DK_CFI_SAME_VALUE: + return ParseDirectiveCFISameValue(IDLoc); + case DK_CFI_RESTORE: + return ParseDirectiveCFIRestore(IDLoc); + case DK_CFI_ESCAPE: + return ParseDirectiveCFIEscape(); + case DK_CFI_SIGNAL_FRAME: + return ParseDirectiveCFISignalFrame(); + case DK_CFI_UNDEFINED: + return ParseDirectiveCFIUndefined(IDLoc); + case DK_CFI_REGISTER: + return ParseDirectiveCFIRegister(IDLoc); + case DK_MACROS_ON: + case DK_MACROS_OFF: + return ParseDirectiveMacrosOnOff(IDVal); + case DK_MACRO: + return ParseDirectiveMacro(IDLoc); + case DK_ENDM: + case DK_ENDMACRO: + return ParseDirectiveEndMacro(IDVal); + case DK_PURGEM: + return ParseDirectivePurgeMacro(IDLoc); } - // Look up the handler in the extension handler table. - std::pair<MCAsmParserExtension*, DirectiveHandler> Handler = - DirectiveMap.lookup(IDVal); - if (Handler.first) - return (*Handler.second)(Handler.first, IDVal, IDLoc); - return Error(IDLoc, "unknown directive"); } @@ -1590,8 +1589,8 @@ static bool isIdentifierChar(char c) { } bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, - const MacroParameters &Parameters, - const MacroArguments &A, + const MCAsmMacroParameters &Parameters, + const MCAsmMacroArguments &A, const SMLoc &L) { unsigned NParameters = Parameters.size(); if (NParameters != 0 && NParameters != A.size()) @@ -1690,7 +1689,7 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, return false; } -MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, +MacroInstantiation::MacroInstantiation(const MCAsmMacro *M, SMLoc IL, int EB, SMLoc EL, MemoryBuffer *I) : TheMacro(M), Instantiation(I), InstantiationLoc(IL), ExitBuffer(EB), @@ -1807,7 +1806,7 @@ bool AsmParser::ParseMacroArgument(MCAsmMacroArgument &MA, } // Parse the macro instantiation arguments. -bool AsmParser::ParseMacroArguments(const Macro *M, MacroArguments &A) { +bool AsmParser::ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A) { const unsigned NParameters = M ? M->Parameters.size() : 0; // Argument delimiter is initially unknown. It will be set by // ParseMacroArgument() @@ -1851,14 +1850,30 @@ bool AsmParser::ParseMacroArguments(const Macro *M, MacroArguments &A) { return TokError("Too many arguments"); } -bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc, - const Macro *M) { +const MCAsmMacro* AsmParser::LookupMacro(StringRef Name) { + StringMap<MCAsmMacro*>::iterator I = MacroMap.find(Name); + return (I == MacroMap.end()) ? NULL : I->getValue(); +} + +void AsmParser::DefineMacro(StringRef Name, const MCAsmMacro& Macro) { + MacroMap[Name] = new MCAsmMacro(Macro); +} + +void AsmParser::UndefineMacro(StringRef Name) { + StringMap<MCAsmMacro*>::iterator I = MacroMap.find(Name); + if (I != MacroMap.end()) { + delete I->getValue(); + MacroMap.erase(I); + } +} + +bool AsmParser::HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { // Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate // this, although we should protect against infinite loops. if (ActiveMacros.size() == 20) return TokError("macros cannot be nested more than 20 levels deep"); - MacroArguments A; + MCAsmMacroArguments A; if (ParseMacroArguments(M, A)) return true; @@ -1877,7 +1892,7 @@ bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc, if (expandMacro(OS, Body, M->Parameters, A, getTok().getLoc())) return true; - // We include the .endmacro in the buffer as our queue to exit the macro + // We include the .endmacro in the buffer as our cue to exit the macro // instantiation. OS << ".endmacro\n"; @@ -2425,507 +2440,10 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { return false; } - -/// ParseDirectiveBundleAlignMode -/// ::= {.bundle_align_mode} expression -bool AsmParser::ParseDirectiveBundleAlignMode() { - CheckForValidSection(); - - // Expect a single argument: an expression that evaluates to a constant - // in the inclusive range 0-30. - SMLoc ExprLoc = getLexer().getLoc(); - int64_t AlignSizePow2; - if (ParseAbsoluteExpression(AlignSizePow2)) - return true; - else if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token after expression in" - " '.bundle_align_mode' directive"); - else if (AlignSizePow2 < 0 || AlignSizePow2 > 30) - return Error(ExprLoc, - "invalid bundle alignment size (expected between 0 and 30)"); - - Lex(); - - // Because of AlignSizePow2's verified range we can safely truncate it to - // unsigned. - getStreamer().EmitBundleAlignMode(static_cast<unsigned>(AlignSizePow2)); - return false; -} - -/// ParseDirectiveBundleLock -/// ::= {.bundle_lock} [align_to_end] -bool AsmParser::ParseDirectiveBundleLock() { - CheckForValidSection(); - bool AlignToEnd = false; - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - StringRef Option; - SMLoc Loc = getTok().getLoc(); - const char *kInvalidOptionError = - "invalid option for '.bundle_lock' directive"; - - if (ParseIdentifier(Option)) - return Error(Loc, kInvalidOptionError); - - if (Option != "align_to_end") - return Error(Loc, kInvalidOptionError); - else if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(Loc, - "unexpected token after '.bundle_lock' directive option"); - AlignToEnd = true; - } - - Lex(); - - getStreamer().EmitBundleLock(AlignToEnd); - return false; -} - -/// ParseDirectiveBundleLock -/// ::= {.bundle_lock} -bool AsmParser::ParseDirectiveBundleUnlock() { - CheckForValidSection(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.bundle_unlock' directive"); - Lex(); - - getStreamer().EmitBundleUnlock(); - return false; -} - -/// ParseDirectiveSymbolAttribute -/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] -bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { - if (getLexer().isNot(AsmToken::EndOfStatement)) { - for (;;) { - StringRef Name; - SMLoc Loc = getTok().getLoc(); - - if (ParseIdentifier(Name)) - return Error(Loc, "expected identifier in directive"); - - MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); - - // Assembler local symbols don't make any sense here. Complain loudly. - if (Sym->isTemporary()) - return Error(Loc, "non-local symbol required in directive"); - - getStreamer().EmitSymbolAttribute(Sym, Attr); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - } - } - - Lex(); - return false; -} - -/// ParseDirectiveComm -/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] -bool AsmParser::ParseDirectiveComm(bool IsLocal) { - CheckForValidSection(); - - SMLoc IDLoc = getLexer().getLoc(); - StringRef Name; - if (ParseIdentifier(Name)) - return TokError("expected identifier in directive"); - - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - int64_t Size; - SMLoc SizeLoc = getLexer().getLoc(); - if (ParseAbsoluteExpression(Size)) - return true; - - int64_t Pow2Alignment = 0; - SMLoc Pow2AlignmentLoc; - if (getLexer().is(AsmToken::Comma)) { - Lex(); - Pow2AlignmentLoc = getLexer().getLoc(); - if (ParseAbsoluteExpression(Pow2Alignment)) - return true; - - LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType(); - if (IsLocal && LCOMM == LCOMM::NoAlignment) - return Error(Pow2AlignmentLoc, "alignment not supported on this target"); - - // If this target takes alignments in bytes (not log) validate and convert. - if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) || - (IsLocal && LCOMM == LCOMM::ByteAlignment)) { - if (!isPowerOf2_64(Pow2Alignment)) - return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); - Pow2Alignment = Log2_64(Pow2Alignment); - } - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.comm' or '.lcomm' directive"); - - Lex(); - - // NOTE: a size of zero for a .comm should create a undefined symbol - // but a size of .lcomm creates a bss symbol of size zero. - if (Size < 0) - return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " - "be less than zero"); - - // NOTE: The alignment in the directive is a power of 2 value, the assembler - // may internally end up wanting an alignment in bytes. - // FIXME: Diagnose overflow. - if (Pow2Alignment < 0) - return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " - "alignment, can't be less than zero"); - - if (!Sym->isUndefined()) - return Error(IDLoc, "invalid symbol redefinition"); - - // Create the Symbol as a common or local common with Size and Pow2Alignment - if (IsLocal) { - getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment); - return false; - } - - getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment); - return false; -} - -/// ParseDirectiveAbort -/// ::= .abort [... message ...] -bool AsmParser::ParseDirectiveAbort() { - // FIXME: Use loc from directive. - SMLoc Loc = getLexer().getLoc(); - - StringRef Str = ParseStringToEndOfStatement(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.abort' directive"); - - Lex(); - - if (Str.empty()) - Error(Loc, ".abort detected. Assembly stopping."); - else - Error(Loc, ".abort '" + Str + "' detected. Assembly stopping."); - // FIXME: Actually abort assembly here. - - return false; -} - -/// ParseDirectiveInclude -/// ::= .include "filename" -bool AsmParser::ParseDirectiveInclude() { - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in '.include' directive"); - - std::string Filename = getTok().getString(); - SMLoc IncludeLoc = getLexer().getLoc(); - Lex(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.include' directive"); - - // Strip the quotes. - Filename = Filename.substr(1, Filename.size()-2); - - // Attempt to switch the lexer to the included file before consuming the end - // of statement to avoid losing it when we switch. - if (EnterIncludeFile(Filename)) { - Error(IncludeLoc, "Could not find include file '" + Filename + "'"); - return true; - } - - return false; -} - -/// ParseDirectiveIncbin -/// ::= .incbin "filename" -bool AsmParser::ParseDirectiveIncbin() { - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in '.incbin' directive"); - - std::string Filename = getTok().getString(); - SMLoc IncbinLoc = getLexer().getLoc(); - Lex(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.incbin' directive"); - - // Strip the quotes. - Filename = Filename.substr(1, Filename.size()-2); - - // Attempt to process the included file. - if (ProcessIncbinFile(Filename)) { - Error(IncbinLoc, "Could not find incbin file '" + Filename + "'"); - return true; - } - - return false; -} - -/// ParseDirectiveIf -/// ::= .if expression -bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - if (TheCondState.Ignore) { - EatToEndOfStatement(); - } else { - int64_t ExprValue; - if (ParseAbsoluteExpression(ExprValue)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.if' directive"); - - Lex(); - - TheCondState.CondMet = ExprValue; - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// ParseDirectiveIfb -/// ::= .ifb string -bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - - if (TheCondState.Ignore) { - EatToEndOfStatement(); - } else { - StringRef Str = ParseStringToEndOfStatement(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.ifb' directive"); - - Lex(); - - TheCondState.CondMet = ExpectBlank == Str.empty(); - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// ParseDirectiveIfc -/// ::= .ifc string1, string2 -bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - - if (TheCondState.Ignore) { - EatToEndOfStatement(); - } else { - StringRef Str1 = ParseStringToComma(); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.ifc' directive"); - - Lex(); - - StringRef Str2 = ParseStringToEndOfStatement(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.ifc' directive"); - - Lex(); - - TheCondState.CondMet = ExpectEqual == (Str1 == Str2); - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// ParseDirectiveIfdef -/// ::= .ifdef symbol -bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { - StringRef Name; - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - - if (TheCondState.Ignore) { - EatToEndOfStatement(); - } else { - if (ParseIdentifier(Name)) - return TokError("expected identifier after '.ifdef'"); - - Lex(); - - MCSymbol *Sym = getContext().LookupSymbol(Name); - - if (expect_defined) - TheCondState.CondMet = (Sym != NULL && !Sym->isUndefined()); - else - TheCondState.CondMet = (Sym == NULL || Sym->isUndefined()); - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// ParseDirectiveElseIf -/// ::= .elseif expression -bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { - if (TheCondState.TheCond != AsmCond::IfCond && - TheCondState.TheCond != AsmCond::ElseIfCond) - Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or " - " an .elseif"); - TheCondState.TheCond = AsmCond::ElseIfCond; - - bool LastIgnoreState = false; - if (!TheCondStack.empty()) - LastIgnoreState = TheCondStack.back().Ignore; - if (LastIgnoreState || TheCondState.CondMet) { - TheCondState.Ignore = true; - EatToEndOfStatement(); - } - else { - int64_t ExprValue; - if (ParseAbsoluteExpression(ExprValue)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.elseif' directive"); - - Lex(); - TheCondState.CondMet = ExprValue; - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// ParseDirectiveElse -/// ::= .else -bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.else' directive"); - - Lex(); - - if (TheCondState.TheCond != AsmCond::IfCond && - TheCondState.TheCond != AsmCond::ElseIfCond) - Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an " - ".elseif"); - TheCondState.TheCond = AsmCond::ElseCond; - bool LastIgnoreState = false; - if (!TheCondStack.empty()) - LastIgnoreState = TheCondStack.back().Ignore; - if (LastIgnoreState || TheCondState.CondMet) - TheCondState.Ignore = true; - else - TheCondState.Ignore = false; - - return false; -} - -/// ParseDirectiveEndIf -/// ::= .endif -bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.endif' directive"); - - Lex(); - - if ((TheCondState.TheCond == AsmCond::NoCond) || - TheCondStack.empty()) - Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or " - ".else"); - if (!TheCondStack.empty()) { - TheCondState = TheCondStack.back(); - TheCondStack.pop_back(); - } - - return false; -} - -void AsmParser::initializeDirectiveKindMapping() { - DirectiveKindMapping[".set"] = DK_SET; - DirectiveKindMapping[".equ"] = DK_EQU; - DirectiveKindMapping[".equiv"] = DK_EQUIV; - DirectiveKindMapping[".ascii"] = DK_ASCII; - DirectiveKindMapping[".asciz"] = DK_ASCIZ; - DirectiveKindMapping[".string"] = DK_STRING; - DirectiveKindMapping[".byte"] = DK_BYTE; - DirectiveKindMapping[".short"] = DK_SHORT; - DirectiveKindMapping[".value"] = DK_VALUE; - DirectiveKindMapping[".2byte"] = DK_2BYTE; - DirectiveKindMapping[".long"] = DK_LONG; - DirectiveKindMapping[".int"] = DK_INT; - DirectiveKindMapping[".4byte"] = DK_4BYTE; - DirectiveKindMapping[".quad"] = DK_QUAD; - DirectiveKindMapping[".8byte"] = DK_8BYTE; - DirectiveKindMapping[".single"] = DK_SINGLE; - DirectiveKindMapping[".float"] = DK_FLOAT; - DirectiveKindMapping[".double"] = DK_DOUBLE; - DirectiveKindMapping[".align"] = DK_ALIGN; - DirectiveKindMapping[".align32"] = DK_ALIGN32; - DirectiveKindMapping[".balign"] = DK_BALIGN; - DirectiveKindMapping[".balignw"] = DK_BALIGNW; - DirectiveKindMapping[".balignl"] = DK_BALIGNL; - DirectiveKindMapping[".p2align"] = DK_P2ALIGN; - DirectiveKindMapping[".p2alignw"] = DK_P2ALIGNW; - DirectiveKindMapping[".p2alignl"] = DK_P2ALIGNL; - DirectiveKindMapping[".org"] = DK_ORG; - DirectiveKindMapping[".fill"] = DK_FILL; - DirectiveKindMapping[".zero"] = DK_ZERO; - DirectiveKindMapping[".extern"] = DK_EXTERN; - DirectiveKindMapping[".globl"] = DK_GLOBL; - DirectiveKindMapping[".global"] = DK_GLOBAL; - DirectiveKindMapping[".indirect_symbol"] = DK_INDIRECT_SYMBOL; - DirectiveKindMapping[".lazy_reference"] = DK_LAZY_REFERENCE; - DirectiveKindMapping[".no_dead_strip"] = DK_NO_DEAD_STRIP; - DirectiveKindMapping[".symbol_resolver"] = DK_SYMBOL_RESOLVER; - DirectiveKindMapping[".private_extern"] = DK_PRIVATE_EXTERN; - DirectiveKindMapping[".reference"] = DK_REFERENCE; - DirectiveKindMapping[".weak_definition"] = DK_WEAK_DEFINITION; - DirectiveKindMapping[".weak_reference"] = DK_WEAK_REFERENCE; - DirectiveKindMapping[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN; - DirectiveKindMapping[".comm"] = DK_COMM; - DirectiveKindMapping[".common"] = DK_COMMON; - DirectiveKindMapping[".lcomm"] = DK_LCOMM; - DirectiveKindMapping[".abort"] = DK_ABORT; - DirectiveKindMapping[".include"] = DK_INCLUDE; - DirectiveKindMapping[".incbin"] = DK_INCBIN; - DirectiveKindMapping[".code16"] = DK_CODE16; - DirectiveKindMapping[".code16gcc"] = DK_CODE16GCC; - DirectiveKindMapping[".rept"] = DK_REPT; - DirectiveKindMapping[".irp"] = DK_IRP; - DirectiveKindMapping[".irpc"] = DK_IRPC; - DirectiveKindMapping[".endr"] = DK_ENDR; - DirectiveKindMapping[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE; - DirectiveKindMapping[".bundle_lock"] = DK_BUNDLE_LOCK; - DirectiveKindMapping[".bundle_unlock"] = DK_BUNDLE_UNLOCK; - DirectiveKindMapping[".if"] = DK_IF; - DirectiveKindMapping[".ifb"] = DK_IFB; - DirectiveKindMapping[".ifnb"] = DK_IFNB; - DirectiveKindMapping[".ifc"] = DK_IFC; - DirectiveKindMapping[".ifnc"] = DK_IFNC; - DirectiveKindMapping[".ifdef"] = DK_IFDEF; - DirectiveKindMapping[".ifndef"] = DK_IFNDEF; - DirectiveKindMapping[".ifnotdef"] = DK_IFNOTDEF; - DirectiveKindMapping[".elseif"] = DK_ELSEIF; - DirectiveKindMapping[".else"] = DK_ELSE; - DirectiveKindMapping[".endif"] = DK_ENDIF; -} - /// ParseDirectiveFile /// ::= .file [number] filename /// ::= .file number directory filename -bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveFile(SMLoc DirectiveLoc) { // FIXME: I'm not sure what this is. int64_t FileNumber = -1; SMLoc FileNumberLoc = getLexer().getLoc(); @@ -2977,7 +2495,7 @@ bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { /// ParseDirectiveLine /// ::= .line [number] -bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveLine() { if (getLexer().isNot(AsmToken::EndOfStatement)) { if (getLexer().isNot(AsmToken::Integer)) return TokError("unexpected token in '.line' directive"); @@ -2995,7 +2513,6 @@ bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) { return false; } - /// ParseDirectiveLoc /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end] /// [epilogue_begin] [is_stmt VALUE] [isa VALUE] @@ -3003,8 +2520,7 @@ bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) { /// a .file directive, the second number is the line number and optionally the /// third number is a column position (zero if not specified). The remaining /// optional items are .loc sub-directives. -bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { - +bool AsmParser::ParseDirectiveLoc() { if (getLexer().isNot(AsmToken::Integer)) return TokError("unexpected token in '.loc' directive"); int64_t FileNumber = getTok().getIntVal(); @@ -3040,7 +2556,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { StringRef Name; SMLoc Loc = getTok().getLoc(); - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("unexpected token in '.loc' directive"); if (Name == "basic_block") @@ -3052,7 +2568,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { else if (Name == "is_stmt") { Loc = getTok().getLoc(); const MCExpr *Value; - if (getParser().ParseExpression(Value)) + if (ParseExpression(Value)) return true; // The expression must be the constant 0 or 1. if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { @@ -3071,7 +2587,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { else if (Name == "isa") { Loc = getTok().getLoc(); const MCExpr *Value; - if (getParser().ParseExpression(Value)) + if (ParseExpression(Value)) return true; // The expression must be a constant greater or equal to 0. if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { @@ -3085,7 +2601,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { } } else if (Name == "discriminator") { - if (getParser().ParseAbsoluteExpression(Discriminator)) + if (ParseAbsoluteExpression(Discriminator)) return true; } else { @@ -3105,53 +2621,18 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { /// ParseDirectiveStabs /// ::= .stabs string, number, number, number -bool GenericAsmParser::ParseDirectiveStabs(StringRef Directive, - SMLoc DirectiveLoc) { - return TokError("unsupported directive '" + Directive + "'"); -} - -/// ParseDirectiveSpace -/// ::= .space expression [ , expression ] -bool GenericAsmParser::ParseDirectiveSpace(StringRef, SMLoc DirectiveLoc) { - getParser().CheckForValidSection(); - - int64_t NumBytes; - if (getParser().ParseAbsoluteExpression(NumBytes)) - return true; - - int64_t FillExpr = 0; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.space' directive"); - Lex(); - - if (getParser().ParseAbsoluteExpression(FillExpr)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.space' directive"); - } - - Lex(); - - if (NumBytes <= 0) - return TokError("invalid number of bytes in '.space' directive"); - - // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. - getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE); - - return false; +bool AsmParser::ParseDirectiveStabs() { + return TokError("unsupported directive '.stabs'"); } /// ParseDirectiveCFISections /// ::= .cfi_sections section [, section] -bool GenericAsmParser::ParseDirectiveCFISections(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFISections() { StringRef Name; bool EH = false; bool Debug = false; - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("Expected an identifier"); if (Name == ".eh_frame") @@ -3162,7 +2643,7 @@ bool GenericAsmParser::ParseDirectiveCFISections(StringRef, if (getLexer().is(AsmToken::Comma)) { Lex(); - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("Expected an identifier"); if (Name == ".eh_frame") @@ -3172,45 +2653,41 @@ bool GenericAsmParser::ParseDirectiveCFISections(StringRef, } getStreamer().EmitCFISections(EH, Debug); - return false; } /// ParseDirectiveCFIStartProc /// ::= .cfi_startproc -bool GenericAsmParser::ParseDirectiveCFIStartProc(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIStartProc() { getStreamer().EmitCFIStartProc(); return false; } /// ParseDirectiveCFIEndProc /// ::= .cfi_endproc -bool GenericAsmParser::ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIEndProc() { getStreamer().EmitCFIEndProc(); return false; } /// ParseRegisterOrRegisterNumber - parse register name or number. -bool GenericAsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, - SMLoc DirectiveLoc) { +bool AsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, + SMLoc DirectiveLoc) { unsigned RegNo; if (getLexer().isNot(AsmToken::Integer)) { - if (getParser().getTargetParser().ParseRegister(RegNo, DirectiveLoc, - DirectiveLoc)) + if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc)) return true; Register = getContext().getRegisterInfo().getDwarfRegNum(RegNo, true); } else - return getParser().ParseAbsoluteExpression(Register); + return ParseAbsoluteExpression(Register); return false; } /// ParseDirectiveCFIDefCfa /// ::= .cfi_def_cfa register, offset -bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; @@ -3220,7 +2697,7 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef, Lex(); int64_t Offset = 0; - if (getParser().ParseAbsoluteExpression(Offset)) + if (ParseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIDefCfa(Register, Offset); @@ -3229,22 +2706,39 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef, /// ParseDirectiveCFIDefCfaOffset /// ::= .cfi_def_cfa_offset offset -bool GenericAsmParser::ParseDirectiveCFIDefCfaOffset(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIDefCfaOffset() { int64_t Offset = 0; - if (getParser().ParseAbsoluteExpression(Offset)) + if (ParseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIDefCfaOffset(Offset); return false; } +/// ParseDirectiveCFIRegister +/// ::= .cfi_register register, register +bool AsmParser::ParseDirectiveCFIRegister(SMLoc DirectiveLoc) { + int64_t Register1 = 0; + if (ParseRegisterOrRegisterNumber(Register1, DirectiveLoc)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Register2 = 0; + if (ParseRegisterOrRegisterNumber(Register2, DirectiveLoc)) + return true; + + getStreamer().EmitCFIRegister(Register1, Register2); + return false; +} + /// ParseDirectiveCFIAdjustCfaOffset /// ::= .cfi_adjust_cfa_offset adjustment -bool GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIAdjustCfaOffset() { int64_t Adjustment = 0; - if (getParser().ParseAbsoluteExpression(Adjustment)) + if (ParseAbsoluteExpression(Adjustment)) return true; getStreamer().EmitCFIAdjustCfaOffset(Adjustment); @@ -3253,8 +2747,7 @@ bool GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset(StringRef, /// ParseDirectiveCFIDefCfaRegister /// ::= .cfi_def_cfa_register register -bool GenericAsmParser::ParseDirectiveCFIDefCfaRegister(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; @@ -3265,7 +2758,7 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfaRegister(StringRef, /// ParseDirectiveCFIOffset /// ::= .cfi_offset register, offset -bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIOffset(SMLoc DirectiveLoc) { int64_t Register = 0; int64_t Offset = 0; @@ -3276,7 +2769,7 @@ bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { return TokError("unexpected token in directive"); Lex(); - if (getParser().ParseAbsoluteExpression(Offset)) + if (ParseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIOffset(Register, Offset); @@ -3285,8 +2778,7 @@ bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { /// ParseDirectiveCFIRelOffset /// ::= .cfi_rel_offset register, offset -bool GenericAsmParser::ParseDirectiveCFIRelOffset(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) @@ -3297,7 +2789,7 @@ bool GenericAsmParser::ParseDirectiveCFIRelOffset(StringRef, Lex(); int64_t Offset = 0; - if (getParser().ParseAbsoluteExpression(Offset)) + if (ParseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIRelOffset(Register, Offset); @@ -3327,12 +2819,12 @@ static bool isValidEncoding(int64_t Encoding) { } /// ParseDirectiveCFIPersonalityOrLsda +/// IsPersonality true for cfi_personality, false for cfi_lsda /// ::= .cfi_personality encoding, [symbol_name] /// ::= .cfi_lsda encoding, [symbol_name] -bool GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { int64_t Encoding = 0; - if (getParser().ParseAbsoluteExpression(Encoding)) + if (ParseAbsoluteExpression(Encoding)) return true; if (Encoding == dwarf::DW_EH_PE_omit) return false; @@ -3345,70 +2837,61 @@ bool GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda(StringRef IDVal, Lex(); StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("expected identifier in directive"); MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); - if (IDVal == ".cfi_personality") + if (IsPersonality) getStreamer().EmitCFIPersonality(Sym, Encoding); - else { - assert(IDVal == ".cfi_lsda"); + else getStreamer().EmitCFILsda(Sym, Encoding); - } return false; } /// ParseDirectiveCFIRememberState /// ::= .cfi_remember_state -bool GenericAsmParser::ParseDirectiveCFIRememberState(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIRememberState() { getStreamer().EmitCFIRememberState(); return false; } /// ParseDirectiveCFIRestoreState /// ::= .cfi_remember_state -bool GenericAsmParser::ParseDirectiveCFIRestoreState(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIRestoreState() { getStreamer().EmitCFIRestoreState(); return false; } /// ParseDirectiveCFISameValue /// ::= .cfi_same_value register -bool GenericAsmParser::ParseDirectiveCFISameValue(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFISameValue(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; getStreamer().EmitCFISameValue(Register); - return false; } /// ParseDirectiveCFIRestore /// ::= .cfi_restore register -bool GenericAsmParser::ParseDirectiveCFIRestore(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIRestore(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; getStreamer().EmitCFIRestore(Register); - return false; } /// ParseDirectiveCFIEscape /// ::= .cfi_escape expression[,...] -bool GenericAsmParser::ParseDirectiveCFIEscape(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIEscape() { std::string Values; int64_t CurrValue; - if (getParser().ParseAbsoluteExpression(CurrValue)) + if (ParseAbsoluteExpression(CurrValue)) return true; Values.push_back((uint8_t)CurrValue); @@ -3416,7 +2899,7 @@ bool GenericAsmParser::ParseDirectiveCFIEscape(StringRef IDVal, while (getLexer().is(AsmToken::Comma)) { Lex(); - if (getParser().ParseAbsoluteExpression(CurrValue)) + if (ParseAbsoluteExpression(CurrValue)) return true; Values.push_back((uint8_t)CurrValue); @@ -3428,89 +2911,59 @@ bool GenericAsmParser::ParseDirectiveCFIEscape(StringRef IDVal, /// ParseDirectiveCFISignalFrame /// ::= .cfi_signal_frame -bool GenericAsmParser::ParseDirectiveCFISignalFrame(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFISignalFrame() { if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(getLexer().getLoc(), - "unexpected token in '" + Directive + "' directive"); + "unexpected token in '.cfi_signal_frame'"); getStreamer().EmitCFISignalFrame(); - return false; } /// ParseDirectiveCFIUndefined /// ::= .cfi_undefined register -bool GenericAsmParser::ParseDirectiveCFIUndefined(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIUndefined(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; getStreamer().EmitCFIUndefined(Register); - - return false; -} - -/// ParseDirectiveCFIRegister -/// ::= .cfi_register register, register -bool GenericAsmParser::ParseDirectiveCFIRegister(StringRef Directive, - SMLoc DirectiveLoc) { - int64_t Register1 = 0; - - if (ParseRegisterOrRegisterNumber(Register1, DirectiveLoc)) - return true; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - int64_t Register2 = 0; - - if (ParseRegisterOrRegisterNumber(Register2, DirectiveLoc)) - return true; - - getStreamer().EmitCFIRegister(Register1, Register2); - return false; } /// ParseDirectiveMacrosOnOff /// ::= .macros_on /// ::= .macros_off -bool GenericAsmParser::ParseDirectiveMacrosOnOff(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveMacrosOnOff(StringRef Directive) { if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(getLexer().getLoc(), "unexpected token in '" + Directive + "' directive"); - getParser().SetMacrosEnabled(Directive == ".macros_on"); - + SetMacrosEnabled(Directive == ".macros_on"); return false; } /// ParseDirectiveMacro /// ::= .macro name [parameters] -bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("expected identifier in '.macro' directive"); - MacroParameters Parameters; + MCAsmMacroParameters Parameters; // Argument delimiter is initially unknown. It will be set by // ParseMacroArgument() AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof; if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { - MacroParameter Parameter; - if (getParser().ParseIdentifier(Parameter.first)) + MCAsmMacroParameter Parameter; + if (ParseIdentifier(Parameter.first)) return TokError("expected identifier in '.macro' directive"); if (getLexer().is(AsmToken::Equal)) { Lex(); - if (getParser().ParseMacroArgument(Parameter.second, ArgumentDelimiter)) + if (ParseMacroArgument(Parameter.second, ArgumentDelimiter)) return true; } @@ -3547,32 +3000,31 @@ bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive, } // Otherwise, scan til the end of the statement. - getParser().EatToEndOfStatement(); + EatToEndOfStatement(); } - if (getParser().MacroMap.lookup(Name)) { + if (LookupMacro(Name)) { return Error(DirectiveLoc, "macro '" + Name + "' is already defined"); } const char *BodyStart = StartToken.getLoc().getPointer(); const char *BodyEnd = EndToken.getLoc().getPointer(); StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); - getParser().MacroMap[Name] = new Macro(Name, Body, Parameters); + DefineMacro(Name, MCAsmMacro(Name, Body, Parameters)); return false; } /// ParseDirectiveEndMacro /// ::= .endm /// ::= .endmacro -bool GenericAsmParser::ParseDirectiveEndMacro(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveEndMacro(StringRef Directive) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '" + Directive + "' directive"); // If we are inside a macro instantiation, terminate the current // instantiation. - if (!getParser().ActiveMacros.empty()) { - getParser().HandleMacroExit(); + if (InsideMacroInstantiation()) { + HandleMacroExit(); return false; } @@ -3584,37 +3036,136 @@ bool GenericAsmParser::ParseDirectiveEndMacro(StringRef Directive, /// ParseDirectivePurgeMacro /// ::= .purgem -bool GenericAsmParser::ParseDirectivePurgeMacro(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectivePurgeMacro(SMLoc DirectiveLoc) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("expected identifier in '.purgem' directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.purgem' directive"); - StringMap<Macro*>::iterator I = getParser().MacroMap.find(Name); - if (I == getParser().MacroMap.end()) + if (!LookupMacro(Name)) return Error(DirectiveLoc, "macro '" + Name + "' is not defined"); - // Undefine the macro. - delete I->getValue(); - getParser().MacroMap.erase(I); + UndefineMacro(Name); return false; } -bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) { - getParser().CheckForValidSection(); +/// ParseDirectiveBundleAlignMode +/// ::= {.bundle_align_mode} expression +bool AsmParser::ParseDirectiveBundleAlignMode() { + CheckForValidSection(); + + // Expect a single argument: an expression that evaluates to a constant + // in the inclusive range 0-30. + SMLoc ExprLoc = getLexer().getLoc(); + int64_t AlignSizePow2; + if (ParseAbsoluteExpression(AlignSizePow2)) + return true; + else if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token after expression in" + " '.bundle_align_mode' directive"); + else if (AlignSizePow2 < 0 || AlignSizePow2 > 30) + return Error(ExprLoc, + "invalid bundle alignment size (expected between 0 and 30)"); + + Lex(); + + // Because of AlignSizePow2's verified range we can safely truncate it to + // unsigned. + getStreamer().EmitBundleAlignMode(static_cast<unsigned>(AlignSizePow2)); + return false; +} + +/// ParseDirectiveBundleLock +/// ::= {.bundle_lock} [align_to_end] +bool AsmParser::ParseDirectiveBundleLock() { + CheckForValidSection(); + bool AlignToEnd = false; + + if (getLexer().isNot(AsmToken::EndOfStatement)) { + StringRef Option; + SMLoc Loc = getTok().getLoc(); + const char *kInvalidOptionError = + "invalid option for '.bundle_lock' directive"; + + if (ParseIdentifier(Option)) + return Error(Loc, kInvalidOptionError); + + if (Option != "align_to_end") + return Error(Loc, kInvalidOptionError); + else if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(Loc, + "unexpected token after '.bundle_lock' directive option"); + AlignToEnd = true; + } + + Lex(); + + getStreamer().EmitBundleLock(AlignToEnd); + return false; +} + +/// ParseDirectiveBundleLock +/// ::= {.bundle_lock} +bool AsmParser::ParseDirectiveBundleUnlock() { + CheckForValidSection(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.bundle_unlock' directive"); + Lex(); + + getStreamer().EmitBundleUnlock(); + return false; +} + +/// ParseDirectiveSpace +/// ::= (.skip | .space) expression [ , expression ] +bool AsmParser::ParseDirectiveSpace(StringRef IDVal) { + CheckForValidSection(); + + int64_t NumBytes; + if (ParseAbsoluteExpression(NumBytes)) + return true; + + int64_t FillExpr = 0; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); + Lex(); + + if (ParseAbsoluteExpression(FillExpr)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); + } + + Lex(); + + if (NumBytes <= 0) + return TokError("invalid number of bytes in '" + + Twine(IDVal) + "' directive"); + + // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. + getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE); + + return false; +} +/// ParseDirectiveLEB128 +/// ::= (.sleb128 | .uleb128) expression +bool AsmParser::ParseDirectiveLEB128(bool Signed) { + CheckForValidSection(); const MCExpr *Value; - if (getParser().ParseExpression(Value)) + if (ParseExpression(Value)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - if (DirName[1] == 's') + if (Signed) getStreamer().EmitSLEB128Value(Value); else getStreamer().EmitULEB128Value(Value); @@ -3622,7 +3173,469 @@ bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) { return false; } -Macro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) { +/// ParseDirectiveSymbolAttribute +/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] +bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + StringRef Name; + SMLoc Loc = getTok().getLoc(); + + if (ParseIdentifier(Name)) + return Error(Loc, "expected identifier in directive"); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + // Assembler local symbols don't make any sense here. Complain loudly. + if (Sym->isTemporary()) + return Error(Loc, "non-local symbol required in directive"); + + getStreamer().EmitSymbolAttribute(Sym, Attr); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + +/// ParseDirectiveComm +/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] +bool AsmParser::ParseDirectiveComm(bool IsLocal) { + CheckForValidSection(); + + SMLoc IDLoc = getLexer().getLoc(); + StringRef Name; + if (ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Size; + SMLoc SizeLoc = getLexer().getLoc(); + if (ParseAbsoluteExpression(Size)) + return true; + + int64_t Pow2Alignment = 0; + SMLoc Pow2AlignmentLoc; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + Pow2AlignmentLoc = getLexer().getLoc(); + if (ParseAbsoluteExpression(Pow2Alignment)) + return true; + + LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType(); + if (IsLocal && LCOMM == LCOMM::NoAlignment) + return Error(Pow2AlignmentLoc, "alignment not supported on this target"); + + // If this target takes alignments in bytes (not log) validate and convert. + if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) || + (IsLocal && LCOMM == LCOMM::ByteAlignment)) { + if (!isPowerOf2_64(Pow2Alignment)) + return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); + Pow2Alignment = Log2_64(Pow2Alignment); + } + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.comm' or '.lcomm' directive"); + + Lex(); + + // NOTE: a size of zero for a .comm should create a undefined symbol + // but a size of .lcomm creates a bss symbol of size zero. + if (Size < 0) + return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " + "be less than zero"); + + // NOTE: The alignment in the directive is a power of 2 value, the assembler + // may internally end up wanting an alignment in bytes. + // FIXME: Diagnose overflow. + if (Pow2Alignment < 0) + return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " + "alignment, can't be less than zero"); + + if (!Sym->isUndefined()) + return Error(IDLoc, "invalid symbol redefinition"); + + // Create the Symbol as a common or local common with Size and Pow2Alignment + if (IsLocal) { + getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment); + return false; + } + + getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment); + return false; +} + +/// ParseDirectiveAbort +/// ::= .abort [... message ...] +bool AsmParser::ParseDirectiveAbort() { + // FIXME: Use loc from directive. + SMLoc Loc = getLexer().getLoc(); + + StringRef Str = ParseStringToEndOfStatement(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.abort' directive"); + + Lex(); + + if (Str.empty()) + Error(Loc, ".abort detected. Assembly stopping."); + else + Error(Loc, ".abort '" + Str + "' detected. Assembly stopping."); + // FIXME: Actually abort assembly here. + + return false; +} + +/// ParseDirectiveInclude +/// ::= .include "filename" +bool AsmParser::ParseDirectiveInclude() { + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in '.include' directive"); + + std::string Filename = getTok().getString(); + SMLoc IncludeLoc = getLexer().getLoc(); + Lex(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.include' directive"); + + // Strip the quotes. + Filename = Filename.substr(1, Filename.size()-2); + + // Attempt to switch the lexer to the included file before consuming the end + // of statement to avoid losing it when we switch. + if (EnterIncludeFile(Filename)) { + Error(IncludeLoc, "Could not find include file '" + Filename + "'"); + return true; + } + + return false; +} + +/// ParseDirectiveIncbin +/// ::= .incbin "filename" +bool AsmParser::ParseDirectiveIncbin() { + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in '.incbin' directive"); + + std::string Filename = getTok().getString(); + SMLoc IncbinLoc = getLexer().getLoc(); + Lex(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.incbin' directive"); + + // Strip the quotes. + Filename = Filename.substr(1, Filename.size()-2); + + // Attempt to process the included file. + if (ProcessIncbinFile(Filename)) { + Error(IncbinLoc, "Could not find incbin file '" + Filename + "'"); + return true; + } + + return false; +} + +/// ParseDirectiveIf +/// ::= .if expression +bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + if (TheCondState.Ignore) { + EatToEndOfStatement(); + } else { + int64_t ExprValue; + if (ParseAbsoluteExpression(ExprValue)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.if' directive"); + + Lex(); + + TheCondState.CondMet = ExprValue; + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveIfb +/// ::= .ifb string +bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + + if (TheCondState.Ignore) { + EatToEndOfStatement(); + } else { + StringRef Str = ParseStringToEndOfStatement(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.ifb' directive"); + + Lex(); + + TheCondState.CondMet = ExpectBlank == Str.empty(); + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveIfc +/// ::= .ifc string1, string2 +bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + + if (TheCondState.Ignore) { + EatToEndOfStatement(); + } else { + StringRef Str1 = ParseStringToComma(); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.ifc' directive"); + + Lex(); + + StringRef Str2 = ParseStringToEndOfStatement(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.ifc' directive"); + + Lex(); + + TheCondState.CondMet = ExpectEqual == (Str1 == Str2); + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveIfdef +/// ::= .ifdef symbol +bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { + StringRef Name; + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + + if (TheCondState.Ignore) { + EatToEndOfStatement(); + } else { + if (ParseIdentifier(Name)) + return TokError("expected identifier after '.ifdef'"); + + Lex(); + + MCSymbol *Sym = getContext().LookupSymbol(Name); + + if (expect_defined) + TheCondState.CondMet = (Sym != NULL && !Sym->isUndefined()); + else + TheCondState.CondMet = (Sym == NULL || Sym->isUndefined()); + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveElseIf +/// ::= .elseif expression +bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { + if (TheCondState.TheCond != AsmCond::IfCond && + TheCondState.TheCond != AsmCond::ElseIfCond) + Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or " + " an .elseif"); + TheCondState.TheCond = AsmCond::ElseIfCond; + + bool LastIgnoreState = false; + if (!TheCondStack.empty()) + LastIgnoreState = TheCondStack.back().Ignore; + if (LastIgnoreState || TheCondState.CondMet) { + TheCondState.Ignore = true; + EatToEndOfStatement(); + } + else { + int64_t ExprValue; + if (ParseAbsoluteExpression(ExprValue)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.elseif' directive"); + + Lex(); + TheCondState.CondMet = ExprValue; + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveElse +/// ::= .else +bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.else' directive"); + + Lex(); + + if (TheCondState.TheCond != AsmCond::IfCond && + TheCondState.TheCond != AsmCond::ElseIfCond) + Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an " + ".elseif"); + TheCondState.TheCond = AsmCond::ElseCond; + bool LastIgnoreState = false; + if (!TheCondStack.empty()) + LastIgnoreState = TheCondStack.back().Ignore; + if (LastIgnoreState || TheCondState.CondMet) + TheCondState.Ignore = true; + else + TheCondState.Ignore = false; + + return false; +} + +/// ParseDirectiveEndIf +/// ::= .endif +bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.endif' directive"); + + Lex(); + + if ((TheCondState.TheCond == AsmCond::NoCond) || + TheCondStack.empty()) + Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or " + ".else"); + if (!TheCondStack.empty()) { + TheCondState = TheCondStack.back(); + TheCondStack.pop_back(); + } + + return false; +} + +void AsmParser::initializeDirectiveKindMap() { + DirectiveKindMap[".set"] = DK_SET; + DirectiveKindMap[".equ"] = DK_EQU; + DirectiveKindMap[".equiv"] = DK_EQUIV; + DirectiveKindMap[".ascii"] = DK_ASCII; + DirectiveKindMap[".asciz"] = DK_ASCIZ; + DirectiveKindMap[".string"] = DK_STRING; + DirectiveKindMap[".byte"] = DK_BYTE; + DirectiveKindMap[".short"] = DK_SHORT; + DirectiveKindMap[".value"] = DK_VALUE; + DirectiveKindMap[".2byte"] = DK_2BYTE; + DirectiveKindMap[".long"] = DK_LONG; + DirectiveKindMap[".int"] = DK_INT; + DirectiveKindMap[".4byte"] = DK_4BYTE; + DirectiveKindMap[".quad"] = DK_QUAD; + DirectiveKindMap[".8byte"] = DK_8BYTE; + DirectiveKindMap[".single"] = DK_SINGLE; + DirectiveKindMap[".float"] = DK_FLOAT; + DirectiveKindMap[".double"] = DK_DOUBLE; + DirectiveKindMap[".align"] = DK_ALIGN; + DirectiveKindMap[".align32"] = DK_ALIGN32; + DirectiveKindMap[".balign"] = DK_BALIGN; + DirectiveKindMap[".balignw"] = DK_BALIGNW; + DirectiveKindMap[".balignl"] = DK_BALIGNL; + DirectiveKindMap[".p2align"] = DK_P2ALIGN; + DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW; + DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL; + DirectiveKindMap[".org"] = DK_ORG; + DirectiveKindMap[".fill"] = DK_FILL; + DirectiveKindMap[".zero"] = DK_ZERO; + DirectiveKindMap[".extern"] = DK_EXTERN; + DirectiveKindMap[".globl"] = DK_GLOBL; + DirectiveKindMap[".global"] = DK_GLOBAL; + DirectiveKindMap[".indirect_symbol"] = DK_INDIRECT_SYMBOL; + DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE; + DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP; + DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER; + DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN; + DirectiveKindMap[".reference"] = DK_REFERENCE; + DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION; + DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE; + DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN; + DirectiveKindMap[".comm"] = DK_COMM; + DirectiveKindMap[".common"] = DK_COMMON; + DirectiveKindMap[".lcomm"] = DK_LCOMM; + DirectiveKindMap[".abort"] = DK_ABORT; + DirectiveKindMap[".include"] = DK_INCLUDE; + DirectiveKindMap[".incbin"] = DK_INCBIN; + DirectiveKindMap[".code16"] = DK_CODE16; + DirectiveKindMap[".code16gcc"] = DK_CODE16GCC; + DirectiveKindMap[".rept"] = DK_REPT; + DirectiveKindMap[".irp"] = DK_IRP; + DirectiveKindMap[".irpc"] = DK_IRPC; + DirectiveKindMap[".endr"] = DK_ENDR; + DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE; + DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK; + DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK; + DirectiveKindMap[".if"] = DK_IF; + DirectiveKindMap[".ifb"] = DK_IFB; + DirectiveKindMap[".ifnb"] = DK_IFNB; + DirectiveKindMap[".ifc"] = DK_IFC; + DirectiveKindMap[".ifnc"] = DK_IFNC; + DirectiveKindMap[".ifdef"] = DK_IFDEF; + DirectiveKindMap[".ifndef"] = DK_IFNDEF; + DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF; + DirectiveKindMap[".elseif"] = DK_ELSEIF; + DirectiveKindMap[".else"] = DK_ELSE; + DirectiveKindMap[".endif"] = DK_ENDIF; + DirectiveKindMap[".skip"] = DK_SKIP; + DirectiveKindMap[".space"] = DK_SPACE; + DirectiveKindMap[".file"] = DK_FILE; + DirectiveKindMap[".line"] = DK_LINE; + DirectiveKindMap[".loc"] = DK_LOC; + DirectiveKindMap[".stabs"] = DK_STABS; + DirectiveKindMap[".sleb128"] = DK_SLEB128; + DirectiveKindMap[".uleb128"] = DK_ULEB128; + DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS; + DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC; + DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC; + DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA; + DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET; + DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET; + DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER; + DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET; + DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET; + DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY; + DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA; + DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE; + DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE; + DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE; + DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE; + DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE; + DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME; + DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED; + DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER; + DirectiveKindMap[".macros_on"] = DK_MACROS_ON; + DirectiveKindMap[".macros_off"] = DK_MACROS_OFF; + DirectiveKindMap[".macro"] = DK_MACRO; + DirectiveKindMap[".endm"] = DK_ENDM; + DirectiveKindMap[".endmacro"] = DK_ENDMACRO; + DirectiveKindMap[".purgem"] = DK_PURGEM; +} + + +MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) { AsmToken EndToken, StartToken = getTok(); unsigned NestLevel = 0; @@ -3663,11 +3676,11 @@ Macro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) { // We Are Anonymous. StringRef Name; - MacroParameters Parameters; - return new Macro(Name, Body, Parameters); + MCAsmMacroParameters Parameters; + return new MCAsmMacro(Name, Body, Parameters); } -void AsmParser::InstantiateMacroLikeBody(Macro *M, SMLoc DirectiveLoc, +void AsmParser::InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, raw_svector_ostream &OS) { OS << ".endr\n"; @@ -3703,15 +3716,15 @@ bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) { Lex(); // Lex the rept definition. - Macro *M = ParseMacroLikeBody(DirectiveLoc); + MCAsmMacro *M = ParseMacroLikeBody(DirectiveLoc); if (!M) return true; // Macro instantiation is lexical, unfortunately. We construct a new buffer // to hold the macro body with substitutions. SmallString<256> Buf; - MacroParameters Parameters; - MacroArguments A; + MCAsmMacroParameters Parameters; + MCAsmMacroArguments A; raw_svector_ostream OS(Buf); while (Count--) { if (expandMacro(OS, M->Body, Parameters, A, getTok().getLoc())) @@ -3725,8 +3738,8 @@ bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) { /// ParseDirectiveIrp /// ::= .irp symbol,values bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) { - MacroParameters Parameters; - MacroParameter Parameter; + MCAsmMacroParameters Parameters; + MCAsmMacroParameter Parameter; if (ParseIdentifier(Parameter.first)) return TokError("expected identifier in '.irp' directive"); @@ -3738,7 +3751,7 @@ bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) { Lex(); - MacroArguments A; + MCAsmMacroArguments A; if (ParseMacroArguments(0, A)) return true; @@ -3746,7 +3759,7 @@ bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) { Lex(); // Lex the irp definition. - Macro *M = ParseMacroLikeBody(DirectiveLoc); + MCAsmMacro *M = ParseMacroLikeBody(DirectiveLoc); if (!M) return true; @@ -3755,8 +3768,8 @@ bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) { SmallString<256> Buf; raw_svector_ostream OS(Buf); - for (MacroArguments::iterator i = A.begin(), e = A.end(); i != e; ++i) { - MacroArguments Args; + for (MCAsmMacroArguments::iterator i = A.begin(), e = A.end(); i != e; ++i) { + MCAsmMacroArguments Args; Args.push_back(*i); if (expandMacro(OS, M->Body, Parameters, Args, getTok().getLoc())) @@ -3771,8 +3784,8 @@ bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) { /// ParseDirectiveIrpc /// ::= .irpc symbol,values bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) { - MacroParameters Parameters; - MacroParameter Parameter; + MCAsmMacroParameters Parameters; + MCAsmMacroParameter Parameter; if (ParseIdentifier(Parameter.first)) return TokError("expected identifier in '.irpc' directive"); @@ -3784,7 +3797,7 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) { Lex(); - MacroArguments A; + MCAsmMacroArguments A; if (ParseMacroArguments(0, A)) return true; @@ -3795,7 +3808,7 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) { Lex(); // Lex the irpc definition. - Macro *M = ParseMacroLikeBody(DirectiveLoc); + MCAsmMacro *M = ParseMacroLikeBody(DirectiveLoc); if (!M) return true; @@ -3810,7 +3823,7 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) { MCAsmMacroArgument Arg; Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I+1))); - MacroArguments Args; + MCAsmMacroArguments Args; Args.push_back(Arg); if (expandMacro(OS, M->Body, Parameters, Args, getTok().getLoc())) @@ -3959,15 +3972,13 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned NumExprs = NumOutputs + NumInputs; OpDecls.resize(NumExprs); Constraints.resize(NumExprs); - // FIXME: Constraints are hard coded to 'm', but we need an 'r' - // constraint for addressof. This needs to be cleaned up! for (unsigned i = 0; i < NumOutputs; ++i) { OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]); - Constraints[i] = OutputDeclsAddressOf[i] ? "=r" : OutputConstraints[i]; + Constraints[i] = OutputConstraints[i]; } for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) { OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]); - Constraints[j] = InputDeclsAddressOf[i] ? "r" : InputConstraints[i]; + Constraints[j] = InputConstraints[i]; } } diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 2c8c1b16d1..160053dabd 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -28,30 +28,30 @@ ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) if (MaxAlignment >= 4) - return new ELFObjectFile<support::little, 4, false>(Object, ec); + return new ELFObjectFile<ELFType<support::little, 4, false> >(Object, ec); else if (MaxAlignment >= 2) - return new ELFObjectFile<support::little, 2, false>(Object, ec); + return new ELFObjectFile<ELFType<support::little, 2, false> >(Object, ec); else llvm_unreachable("Invalid alignment for ELF file!"); else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) if (MaxAlignment >= 4) - return new ELFObjectFile<support::big, 4, false>(Object, ec); + return new ELFObjectFile<ELFType<support::big, 4, false> >(Object, ec); else if (MaxAlignment >= 2) - return new ELFObjectFile<support::big, 2, false>(Object, ec); + return new ELFObjectFile<ELFType<support::big, 2, false> >(Object, ec); else llvm_unreachable("Invalid alignment for ELF file!"); else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) if (MaxAlignment >= 8) - return new ELFObjectFile<support::big, 8, true>(Object, ec); + return new ELFObjectFile<ELFType<support::big, 8, true> >(Object, ec); else if (MaxAlignment >= 2) - return new ELFObjectFile<support::big, 2, true>(Object, ec); + return new ELFObjectFile<ELFType<support::big, 2, true> >(Object, ec); else llvm_unreachable("Invalid alignment for ELF file!"); else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { if (MaxAlignment >= 8) - return new ELFObjectFile<support::little, 8, true>(Object, ec); + return new ELFObjectFile<ELFType<support::little, 8, true> >(Object, ec); else if (MaxAlignment >= 2) - return new ELFObjectFile<support::little, 2, true>(Object, ec); + return new ELFObjectFile<ELFType<support::little, 2, true> >(Object, ec); else llvm_unreachable("Invalid alignment for ELF file!"); } diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp index a64db1c60f..529bdf97e5 100644 --- a/lib/Object/MachOObject.cpp +++ b/lib/Object/MachOObject.cpp @@ -44,7 +44,8 @@ static void ReadInMemoryStruct(const MachOObject &MOO, } // Check whether we can return a direct pointer. - struct_type *Ptr = (struct_type *) (Buffer.data() + Base); + struct_type *Ptr = reinterpret_cast<struct_type *>( + const_cast<char *>(Buffer.data() + Base)); if (!MOO.isSwappedEndian()) { Res = Ptr; return; diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 41594dc578..b76cdd3a76 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -11,6 +11,7 @@ #include "MCTargetDesc/ARMAddressingModes.h" #include "MCTargetDesc/ARMBaseInfo.h" #include "MCTargetDesc/ARMFixupKinds.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCAsmBackend.h" #include "MCTargetDesc/ARMMCNaCl.h" // @LOCALMOD #include "llvm/MC/MCAssembler.h" @@ -678,25 +679,20 @@ MCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT, StringRef Triple TheTriple(TT); if (TheTriple.isOSDarwin()) { - if (TheTriple.getArchName() == "armv4t" || - TheTriple.getArchName() == "thumbv4t") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V4T); - else if (TheTriple.getArchName() == "armv5e" || - TheTriple.getArchName() == "thumbv5e") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V5TEJ); - else if (TheTriple.getArchName() == "armv6" || - TheTriple.getArchName() == "thumbv6") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6); - else if (TheTriple.getArchName() == "armv7f" || - TheTriple.getArchName() == "thumbv7f") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7F); - else if (TheTriple.getArchName() == "armv7k" || - TheTriple.getArchName() == "thumbv7k") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7K); - else if (TheTriple.getArchName() == "armv7s" || - TheTriple.getArchName() == "thumbv7s") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7S); - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7); + object::mach::CPUSubtypeARM CS = + StringSwitch<object::mach::CPUSubtypeARM>(TheTriple.getArchName()) + .Cases("armv4t", "thumbv4t", object::mach::CSARM_V4T) + .Cases("armv5e", "thumbv5e",object::mach::CSARM_V5TEJ) + .Cases("armv6", "thumbv6", object::mach::CSARM_V6) + .Cases("armv6m", "thumbv6m", object::mach::CSARM_V6M) + .Cases("armv7em", "thumbv7em", object::mach::CSARM_V7EM) + .Cases("armv7f", "thumbv7f", object::mach::CSARM_V7F) + .Cases("armv7k", "thumbv7k", object::mach::CSARM_V7K) + .Cases("armv7m", "thumbv7m", object::mach::CSARM_V7M) + .Cases("armv7s", "thumbv7s", object::mach::CSARM_V7S) + .Default(object::mach::CSARM_V7); + + return new DarwinARMAsmBackend(T, TT, CS); } if (TheTriple.isOSWindows()) diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp index 16cec5cfe5..1a0e581051 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -1016,8 +1016,8 @@ SDValue HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op, DebugLoc dl = Op.getDebugLoc(); Result = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), Offset); - HexagonTargetObjectFile &TLOF = - (HexagonTargetObjectFile&)getObjFileLowering(); + const HexagonTargetObjectFile &TLOF = + static_cast<const HexagonTargetObjectFile &>(getObjFileLowering()); if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), Result); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 3fe30b0b49..c39d3fad3b 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -119,7 +119,13 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, Type = ELF::R_MIPS_64; break; case FK_GPRel_4: - Type = ELF::R_MIPS_GPREL32; + if (isN64()) { + Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type); + Type = setRType2((unsigned)ELF::R_MIPS_64, Type); + Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type); + } + else + Type = ELF::R_MIPS_GPREL32; break; case Mips::fixup_Mips_GPREL16: Type = ELF::R_MIPS_GPREL16; diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index 52fa95b182..a24de60cd9 100644 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/lib/Target/Mips/MipsCodeEmitter.cpp @@ -120,9 +120,12 @@ class MipsCodeEmitter : public MachineFunctionPass { char MipsCodeEmitter::ID = 0; bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) { - JTI = ((MipsTargetMachine&) MF.getTarget()).getJITInfo(); - II = ((const MipsTargetMachine&) MF.getTarget()).getInstrInfo(); - TD = ((const MipsTargetMachine&) MF.getTarget()).getDataLayout(); + MipsTargetMachine &Target = static_cast<MipsTargetMachine &>( + const_cast<TargetMachine &>(MF.getTarget())); + + JTI = Target.getJITInfo(); + II = Target.getInstrInfo(); + TD = Target.getDataLayout(); Subtarget = &TM.getSubtarget<MipsSubtarget> (); MCPEs = &MF.getConstantPool()->getConstants(); MJTEs = 0; diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 5ce258ed0f..05bb1e37e5 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -684,115 +684,298 @@ static unsigned getIntelMemOperandSize(StringRef OpStr) { return Size; } +enum IntelBracExprState { + IBES_START, + IBES_LBRAC, + IBES_RBRAC, + IBES_REGISTER, + IBES_REGISTER_STAR, + IBES_REGISTER_STAR_INTEGER, + IBES_INTEGER, + IBES_INTEGER_STAR, + IBES_INDEX_REGISTER, + IBES_IDENTIFIER, + IBES_DISP_EXPR, + IBES_MINUS, + IBES_ERROR +}; + +class IntelBracExprStateMachine { + IntelBracExprState State; + unsigned BaseReg, IndexReg, Scale; + int64_t Disp; + + unsigned TmpReg; + int64_t TmpInteger; + + bool isPlus; + +public: + IntelBracExprStateMachine(MCAsmParser &parser) : + State(IBES_START), BaseReg(0), IndexReg(0), Scale(1), Disp(0), + TmpReg(0), TmpInteger(0), isPlus(true) {} + + unsigned getBaseReg() { return BaseReg; } + unsigned getIndexReg() { return IndexReg; } + unsigned getScale() { return Scale; } + int64_t getDisp() { return Disp; } + bool isValidEndState() { return State == IBES_RBRAC; } + + void onPlus() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_INTEGER: + State = IBES_START; + if (isPlus) + Disp += TmpInteger; + else + Disp -= TmpInteger; + break; + case IBES_REGISTER: + State = IBES_START; + // If we already have a BaseReg, then assume this is the IndexReg with a + // scale of 1. + if (!BaseReg) { + BaseReg = TmpReg; + } else { + assert (!IndexReg && "BaseReg/IndexReg already set!"); + IndexReg = TmpReg; + Scale = 1; + } + break; + case IBES_INDEX_REGISTER: + State = IBES_START; + break; + } + isPlus = true; + } + void onMinus() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_START: + State = IBES_MINUS; + break; + case IBES_INTEGER: + State = IBES_START; + if (isPlus) + Disp += TmpInteger; + else + Disp -= TmpInteger; + break; + case IBES_REGISTER: + State = IBES_START; + // If we already have a BaseReg, then assume this is the IndexReg with a + // scale of 1. + if (!BaseReg) { + BaseReg = TmpReg; + } else { + assert (!IndexReg && "BaseReg/IndexReg already set!"); + IndexReg = TmpReg; + Scale = 1; + } + break; + case IBES_INDEX_REGISTER: + State = IBES_START; + break; + } + isPlus = false; + } + void onRegister(unsigned Reg) { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_START: + State = IBES_REGISTER; + TmpReg = Reg; + break; + case IBES_INTEGER_STAR: + assert (!IndexReg && "IndexReg already set!"); + State = IBES_INDEX_REGISTER; + IndexReg = Reg; + Scale = TmpInteger; + break; + } + } + void onDispExpr() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_START: + State = IBES_DISP_EXPR; + break; + } + } + void onInteger(int64_t TmpInt) { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_START: + State = IBES_INTEGER; + TmpInteger = TmpInt; + break; + case IBES_MINUS: + State = IBES_INTEGER; + TmpInteger = TmpInt; + break; + case IBES_REGISTER_STAR: + assert (!IndexReg && "IndexReg already set!"); + State = IBES_INDEX_REGISTER; + IndexReg = TmpReg; + Scale = TmpInt; + break; + } + } + void onStar() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_INTEGER: + State = IBES_INTEGER_STAR; + break; + case IBES_REGISTER: + State = IBES_REGISTER_STAR; + break; + } + } + void onLBrac() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_RBRAC: + State = IBES_START; + isPlus = true; + break; + } + } + void onRBrac() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_DISP_EXPR: + State = IBES_RBRAC; + break; + case IBES_INTEGER: + State = IBES_RBRAC; + if (isPlus) + Disp += TmpInteger; + else + Disp -= TmpInteger; + break; + case IBES_REGISTER: + State = IBES_RBRAC; + // If we already have a BaseReg, then assume this is the IndexReg with a + // scale of 1. + if (!BaseReg) { + BaseReg = TmpReg; + } else { + assert (!IndexReg && "BaseReg/IndexReg already set!"); + IndexReg = TmpReg; + Scale = 1; + } + break; + case IBES_INDEX_REGISTER: + State = IBES_RBRAC; + break; + } + } +}; + X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, unsigned Size) { - unsigned BaseReg = 0, IndexReg = 0, Scale = 1; const AsmToken &Tok = Parser.getTok(); SMLoc Start = Tok.getLoc(), End = Tok.getEndLoc(); - const MCExpr *Disp = MCConstantExpr::Create(0, getContext()); - // Parse [ BaseReg + Scale*IndexReg + Disp ] or [ symbol ] - // Eat '[' if (getLexer().isNot(AsmToken::LBrac)) return ErrorOperand(Start, "Expected '[' token!"); Parser.Lex(); + unsigned TmpReg = 0; + + // Try to handle '[' 'symbol' ']' if (getLexer().is(AsmToken::Identifier)) { - // Parse BaseReg - if (ParseRegister(BaseReg, Start, End)) { - // Handle '[' 'symbol' ']' - if (getParser().ParseExpression(Disp, End)) return 0; + if (ParseRegister(TmpReg, Start, End)) { + const MCExpr *Disp; + if (getParser().ParseExpression(Disp, End)) + return 0; + if (getLexer().isNot(AsmToken::RBrac)) return ErrorOperand(Parser.getTok().getLoc(), "Expected ']' token!"); End = Parser.getTok().getEndLoc(); Parser.Lex(); return X86Operand::CreateMem(Disp, Start, End, Size); } - } else if (getLexer().is(AsmToken::Integer)) { - int64_t Val = Tok.getIntVal(); - Parser.Lex(); - SMLoc Loc = Tok.getLoc(); - if (getLexer().is(AsmToken::RBrac)) { - // Handle '[' number ']' - End = Parser.getTok().getEndLoc(); - Parser.Lex(); - const MCExpr *Disp = MCConstantExpr::Create(Val, getContext()); - if (SegReg) - return X86Operand::CreateMem(SegReg, Disp, 0, 0, Scale, - Start, End, Size); - return X86Operand::CreateMem(Disp, Start, End, Size); - } else if (getLexer().is(AsmToken::Star)) { - // Handle '[' Scale*IndexReg ']' - Parser.Lex(); - SMLoc IdxRegLoc = Tok.getLoc(); - if (ParseRegister(IndexReg, IdxRegLoc, End)) - return ErrorOperand(IdxRegLoc, "Expected register"); - Scale = Val; - } else - return ErrorOperand(Loc, "Unexpected token"); } - // Parse ][ as a plus. - bool ExpectRBrac = true; - if (getLexer().is(AsmToken::RBrac)) { - ExpectRBrac = false; - End = Parser.getTok().getEndLoc(); - Parser.Lex(); - } + // Parse [ BaseReg + Scale*IndexReg + Disp ]. + bool Done = false; + IntelBracExprStateMachine SM(Parser); + + // If we parsed a register, then the end loc has already been set and + // the identifier has already been lexed. We also need to update the + // state. + if (TmpReg) + SM.onRegister(TmpReg); + + const MCExpr *Disp = 0; + while (!Done) { + bool UpdateLocLex = true; - if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus) || - getLexer().is(AsmToken::LBrac)) { - ExpectRBrac = true; - bool isPlus = getLexer().is(AsmToken::Plus) || - getLexer().is(AsmToken::LBrac); - Parser.Lex(); - SMLoc PlusLoc = Tok.getLoc(); - if (getLexer().is(AsmToken::Integer)) { + // The period in the dot operator (e.g., [ebx].foo.bar) is parsed as an + // identifier. Don't try an parse it as a register. + if (Tok.getString().startswith(".")) + break; + + switch (getLexer().getKind()) { + default: { + if (SM.isValidEndState()) { + Done = true; + break; + } + return ErrorOperand(Tok.getLoc(), "Unexpected token!"); + } + case AsmToken::Identifier: { + // This could be a register or a displacement expression. + if(!ParseRegister(TmpReg, Start, End)) { + SM.onRegister(TmpReg); + UpdateLocLex = false; + break; + } else if (!getParser().ParseExpression(Disp, End)) { + SM.onDispExpr(); + UpdateLocLex = false; + break; + } + return ErrorOperand(Tok.getLoc(), "Unexpected identifier!"); + } + case AsmToken::Integer: { int64_t Val = Tok.getIntVal(); - Parser.Lex(); - if (getLexer().is(AsmToken::Star)) { - Parser.Lex(); - SMLoc IdxRegLoc = Tok.getLoc(); - if (ParseRegister(IndexReg, IdxRegLoc, End)) - return ErrorOperand(IdxRegLoc, "Expected register"); - Scale = Val; - } else if (getLexer().is(AsmToken::RBrac)) { - const MCExpr *ValExpr = MCConstantExpr::Create(Val, getContext()); - Disp = isPlus ? ValExpr : MCConstantExpr::Create(0-Val, getContext()); - } else - return ErrorOperand(PlusLoc, "unexpected token after +"); - } else if (getLexer().is(AsmToken::Identifier)) { - // This could be an index register or a displacement expression. - if (!IndexReg) - ParseRegister(IndexReg, Start, End); - else if (getParser().ParseExpression(Disp, End)) - return 0; + SM.onInteger(Val); + break; } - } - - // Parse ][ as a plus. - if (getLexer().is(AsmToken::RBrac)) { - ExpectRBrac = false; - End = Parser.getTok().getEndLoc(); - Parser.Lex(); - if (getLexer().is(AsmToken::LBrac)) { - ExpectRBrac = true; - Parser.Lex(); - if (getParser().ParseExpression(Disp, End)) - return 0; + case AsmToken::Plus: SM.onPlus(); break; + case AsmToken::Minus: SM.onMinus(); break; + case AsmToken::Star: SM.onStar(); break; + case AsmToken::LBrac: SM.onLBrac(); break; + case AsmToken::RBrac: SM.onRBrac(); break; + } + if (!Done && UpdateLocLex) { + End = Tok.getLoc(); + Parser.Lex(); // Consume the token. } - } else if (ExpectRBrac) { - if (getParser().ParseExpression(Disp, End)) - return 0; } - if (ExpectRBrac) { - if (getLexer().isNot(AsmToken::RBrac)) - return ErrorOperand(End, "expected ']' token!"); - End = Parser.getTok().getEndLoc(); - Parser.Lex(); - } + if (!Disp) + Disp = MCConstantExpr::Create(SM.getDisp(), getContext()); // Parse the dot operator (e.g., [ebx].foo.bar). if (Tok.getString().startswith(".")) { @@ -806,10 +989,18 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, Disp = NewDisp; } + int BaseReg = SM.getBaseReg(); + int IndexReg = SM.getIndexReg(); + // handle [-42] - if (!BaseReg && !IndexReg) - return X86Operand::CreateMem(Disp, Start, End, Size); + if (!BaseReg && !IndexReg) { + if (!SegReg) + return X86Operand::CreateMem(Disp, Start, End); + else + return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, Start, End, Size); + } + int Scale = SM.getScale(); return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, Start, End, Size); } diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h index a36b1e6b9e..1f6a3a5e33 100644 --- a/lib/Transforms/InstCombine/InstCombine.h +++ b/lib/Transforms/InstCombine/InstCombine.h @@ -27,7 +27,7 @@ namespace llvm { class DbgDeclareInst; class MemIntrinsic; class MemSetInst; - + /// SelectPatternFlavor - We can match a variety of different patterns for /// select operations. enum SelectPatternFlavor { @@ -36,7 +36,7 @@ enum SelectPatternFlavor { SPF_SMAX, SPF_UMAX //SPF_ABS - TODO. }; - + /// getComplexity: Assign a complexity or rank value to LLVM Values... /// 0 -> undef, 1 -> Const, 2 -> Other, 3 -> Arg, 3 -> Unary, 4 -> OtherInst static inline unsigned getComplexity(Value *V) { @@ -51,23 +51,23 @@ static inline unsigned getComplexity(Value *V) { return isa<Constant>(V) ? (isa<UndefValue>(V) ? 0 : 1) : 2; } - + /// InstCombineIRInserter - This is an IRBuilder insertion helper that works /// just like the normal insertion helper, but also adds any new instructions /// to the instcombine worklist. -class LLVM_LIBRARY_VISIBILITY InstCombineIRInserter +class LLVM_LIBRARY_VISIBILITY InstCombineIRInserter : public IRBuilderDefaultInserter<true> { InstCombineWorklist &Worklist; public: InstCombineIRInserter(InstCombineWorklist &WL) : Worklist(WL) {} - + void InsertHelper(Instruction *I, const Twine &Name, BasicBlock *BB, BasicBlock::iterator InsertPt) const { IRBuilderDefaultInserter<true>::InsertHelper(I, Name, BB, InsertPt); Worklist.Add(I); } }; - + /// InstCombiner - The -instcombine pass. class LLVM_LIBRARY_VISIBILITY InstCombiner : public FunctionPass, @@ -85,7 +85,7 @@ public: /// instructions into the worklist when they are created. typedef IRBuilder<true, TargetFolder, InstCombineIRInserter> BuilderTy; BuilderTy *Builder; - + static char ID; // Pass identification, replacement for typeid InstCombiner() : FunctionPass(ID), TD(0), Builder(0) { MinimizeSize = false; @@ -94,7 +94,7 @@ public: public: virtual bool runOnFunction(Function &F); - + bool DoOneIteration(Function &F, unsigned ItNum); virtual void getAnalysisUsage(AnalysisUsage &AU) const; @@ -212,10 +212,10 @@ private: bool ShouldChangeType(Type *From, Type *To) const; Value *dyn_castNegVal(Value *V) const; Value *dyn_castFNegVal(Value *V, bool NoSignedZero=false) const; - Type *FindElementAtOffset(Type *Ty, int64_t Offset, + Type *FindElementAtOffset(Type *Ty, int64_t Offset, SmallVectorImpl<Value*> &NewIndices); Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI); - + /// ShouldOptimizeCast - Return true if the cast from "V to Ty" actually /// results in any code being generated and is interesting to optimize out. If /// the cast can be eliminated by some other simple transformation, we prefer @@ -247,7 +247,7 @@ public: return New; } - // InsertNewInstWith - same as InsertNewInstBefore, but also sets the + // InsertNewInstWith - same as InsertNewInstBefore, but also sets the // debug loc. // Instruction *InsertNewInstWith(Instruction *New, Instruction &Old) { @@ -263,10 +263,10 @@ public: // Instruction *ReplaceInstUsesWith(Instruction &I, Value *V) { Worklist.AddUsersToWorkList(I); // Add all modified instrs to worklist. - + // If we are replacing the instruction with itself, this must be in a // segment of unreachable code, so just clobber the instruction. - if (&I == V) + if (&I == V) V = UndefValue::get(I.getType()); DEBUG(errs() << "IC: Replacing " << I << "\n" @@ -296,13 +296,13 @@ public: MadeIRChange = true; return 0; // Don't do anything with FI } - + void ComputeMaskedBits(Value *V, APInt &KnownZero, APInt &KnownOne, unsigned Depth = 0) const { return llvm::ComputeMaskedBits(V, KnownZero, KnownOne, TD, Depth); } - - bool MaskedValueIsZero(Value *V, const APInt &Mask, + + bool MaskedValueIsZero(Value *V, const APInt &Mask, unsigned Depth = 0) const { return llvm::MaskedValueIsZero(V, Mask, TD, Depth); } @@ -325,10 +325,10 @@ private: /// SimplifyDemandedUseBits - Attempts to replace V with a simpler value /// based on the demanded bits. - Value *SimplifyDemandedUseBits(Value *V, APInt DemandedMask, + Value *SimplifyDemandedUseBits(Value *V, APInt DemandedMask, APInt& KnownZero, APInt& KnownOne, unsigned Depth); - bool SimplifyDemandedBits(Use &U, APInt DemandedMask, + bool SimplifyDemandedBits(Use &U, APInt DemandedMask, APInt& KnownZero, APInt& KnownOne, unsigned Depth=0); /// Helper routine of SimplifyDemandedUseBits. It tries to simplify demanded @@ -336,15 +336,15 @@ private: Value *SimplifyShrShlDemandedBits(Instruction *Lsr, Instruction *Sftl, APInt DemandedMask, APInt &KnownZero, APInt &KnownOne); - + /// SimplifyDemandedInstructionBits - Inst is an integer instruction that /// SimplifyDemandedBits knows about. See if the instruction has any /// properties that allow us to simplify its operands. bool SimplifyDemandedInstructionBits(Instruction &Inst); - + Value *SimplifyDemandedVectorElts(Value *V, APInt DemandedElts, APInt& UndefElts, unsigned Depth = 0); - + // FoldOpIntoPhi - Given a binary operator, cast instruction, or select // which has a PHI node as operand #0, see if we can fold the instruction // into the PHI (which is only possible if all operands to the PHI are @@ -360,10 +360,10 @@ private: Instruction *FoldPHIArgGEPIntoPHI(PHINode &PN); Instruction *FoldPHIArgLoadIntoPHI(PHINode &PN); - + Instruction *OptAndOp(Instruction *Op, ConstantInt *OpRHS, ConstantInt *AndRHS, BinaryOperator &TheAnd); - + Value *FoldLogicalPlusAnd(Value *LHS, Value *RHS, ConstantInt *Mask, bool isSub, Instruction &I); Value *InsertRangeTest(Value *V, Constant *Lo, Constant *Hi, @@ -382,8 +382,8 @@ private: Value *Descale(Value *Val, APInt Scale, bool &NoSignedWrap); }; - - + + } // end namespace llvm. #endif diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index f07c58d7d0..03be8ef6fb 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -66,10 +66,12 @@ namespace { bool insaneIntVal(int V) { return V > 4 || V < -4; } APFloat *getFpValPtr(void) { return reinterpret_cast<APFloat*>(&FpValBuf.buffer[0]); } + const APFloat *getFpValPtr(void) const + { return reinterpret_cast<const APFloat*>(&FpValBuf.buffer[0]); } const APFloat &getFpVal(void) const { assert(IsFp && BufHasFpVal && "Incorret state"); - return *reinterpret_cast<const APFloat*>(&FpValBuf.buffer[0]); + return *getFpValPtr(); } APFloat &getFpVal(void) diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index c782032c45..0c0864f2c0 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -739,7 +739,7 @@ static bool CanEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear) { } Instruction *InstCombiner::visitZExt(ZExtInst &CI) { - // If this zero extend is only used by a truncate, let the truncate by + // If this zero extend is only used by a truncate, let the truncate be // eliminated before we try to optimize this zext. if (CI.hasOneUse() && isa<TruncInst>(CI.use_back())) return 0; diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index d0f43928c3..8e4267f898 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -377,6 +377,8 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) { if (Value *V = SimplifyFMulInst(Op0, Op1, I.getFastMathFlags(), TD)) return ReplaceInstUsesWith(I, V); + bool AllowReassociate = I.hasUnsafeAlgebra(); + // Simplify mul instructions with a constant RHS. if (isa<Constant>(Op1)) { // Try to fold constant mul into select arguments. @@ -389,7 +391,7 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) { return NV; ConstantFP *C = dyn_cast<ConstantFP>(Op1); - if (C && I.hasUnsafeAlgebra() && C->getValueAPF().isNormal()) { + if (C && AllowReassociate && C->getValueAPF().isNormal()) { // Let MDC denote an expression in one of these forms: // X * C, C/X, X/C, where C is a constant. // @@ -430,7 +432,7 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) { BinaryOperator::CreateFAdd(M0, M1) : BinaryOperator::CreateFSub(M0, M1); Instruction *RI = cast<Instruction>(R); - RI->setHasUnsafeAlgebra(true); + RI->copyFastMathFlags(&I); return RI; } } @@ -438,9 +440,6 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) { } } - if (Value *Op0v = dyn_castFNegVal(Op0)) // -X * -Y = X*Y - if (Value *Op1v = dyn_castFNegVal(Op1)) - return BinaryOperator::CreateFMul(Op0v, Op1v); // Under unsafe algebra do: // X * log2(0.5*Y) = X*log2(Y) - X @@ -469,36 +468,66 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) { } } - // X * cond ? 1.0 : 0.0 => cond ? X : 0.0 - if (I.hasNoNaNs() && I.hasNoSignedZeros()) { - Value *V0 = I.getOperand(0); - Value *V1 = I.getOperand(1); - Value *Cond, *SLHS, *SRHS; - bool Match = false; - - if (match(V0, m_Select(m_Value(Cond), m_Value(SLHS), m_Value(SRHS)))) { - Match = true; - } else if (match(V1, m_Select(m_Value(Cond), m_Value(SLHS), - m_Value(SRHS)))) { - Match = true; - std::swap(V0, V1); + // Handle symmetric situation in a 2-iteration loop + Value *Opnd0 = Op0; + Value *Opnd1 = Op1; + for (int i = 0; i < 2; i++) { + bool IgnoreZeroSign = I.hasNoSignedZeros(); + if (BinaryOperator::isFNeg(Opnd0, IgnoreZeroSign)) { + Value *N0 = dyn_castFNegVal(Opnd0, IgnoreZeroSign); + Value *N1 = dyn_castFNegVal(Opnd1, IgnoreZeroSign); + + // -X * -Y => X*Y + if (N1) + return BinaryOperator::CreateFMul(N0, N1); + + if (Opnd0->hasOneUse()) { + // -X * Y => -(X*Y) (Promote negation as high as possible) + Value *T = Builder->CreateFMul(N0, Opnd1); + cast<Instruction>(T)->setDebugLoc(I.getDebugLoc()); + Instruction *Neg = BinaryOperator::CreateFNeg(T); + if (I.getFastMathFlags().any()) { + cast<Instruction>(T)->copyFastMathFlags(&I); + Neg->copyFastMathFlags(&I); + } + return Neg; + } } - if (Match) { - ConstantFP *C0 = dyn_cast<ConstantFP>(SLHS); - ConstantFP *C1 = dyn_cast<ConstantFP>(SRHS); - - if (C0 && C1 && - ((C0->isZero() && C1->isExactlyValue(1.0)) || - (C1->isZero() && C0->isExactlyValue(1.0)))) { - Value *T; - if (C0->isZero()) - T = Builder->CreateSelect(Cond, SLHS, V1); - else - T = Builder->CreateSelect(Cond, V1, SRHS); - return ReplaceInstUsesWith(I, T); + // (X*Y) * X => (X*X) * Y where Y != X + // The purpose is two-fold: + // 1) to form a power expression (of X). + // 2) potentially shorten the critical path: After transformation, the + // latency of the instruction Y is amortized by the expression of X*X, + // and therefore Y is in a "less critical" position compared to what it + // was before the transformation. + // + if (AllowReassociate) { + Value *Opnd0_0, *Opnd0_1; + if (Opnd0->hasOneUse() && + match(Opnd0, m_FMul(m_Value(Opnd0_0), m_Value(Opnd0_1)))) { + Value *Y = 0; + if (Opnd0_0 == Opnd1 && Opnd0_1 != Opnd1) + Y = Opnd0_1; + else if (Opnd0_1 == Opnd1 && Opnd0_0 != Opnd1) + Y = Opnd0_0; + + if (Y) { + Instruction *T = cast<Instruction>(Builder->CreateFMul(Opnd1, Opnd1)); + T->copyFastMathFlags(&I); + T->setDebugLoc(I.getDebugLoc()); + + Instruction *R = BinaryOperator::CreateFMul(T, Y); + R->copyFastMathFlags(&I); + return R; + } } } + + if (!isa<Constant>(Op1)) + std::swap(Opnd0, Opnd1); + else + break; } return Changed ? &I : 0; @@ -784,21 +813,140 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) { return 0; } +/// CvtFDivConstToReciprocal tries to convert X/C into X*1/C if C not a special +/// FP value and: +/// 1) 1/C is exact, or +/// 2) reciprocal is allowed. +/// If the convertion was successful, the simplified expression "X * 1/C" is +/// returned; otherwise, NULL is returned. +/// +static Instruction *CvtFDivConstToReciprocal(Value *Dividend, + ConstantFP *Divisor, + bool AllowReciprocal) { + const APFloat &FpVal = Divisor->getValueAPF(); + APFloat Reciprocal(FpVal.getSemantics()); + bool Cvt = FpVal.getExactInverse(&Reciprocal); + + if (!Cvt && AllowReciprocal && FpVal.isNormal()) { + Reciprocal = APFloat(FpVal.getSemantics(), 1.0f); + (void)Reciprocal.divide(FpVal, APFloat::rmNearestTiesToEven); + Cvt = !Reciprocal.isDenormal(); + } + + if (!Cvt) + return 0; + + ConstantFP *R; + R = ConstantFP::get(Dividend->getType()->getContext(), Reciprocal); + return BinaryOperator::CreateFMul(Dividend, R); +} + Instruction *InstCombiner::visitFDiv(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); if (Value *V = SimplifyFDivInst(Op0, Op1, TD)) return ReplaceInstUsesWith(I, V); + bool AllowReassociate = I.hasUnsafeAlgebra(); + bool AllowReciprocal = I.hasAllowReciprocal(); + if (ConstantFP *Op1C = dyn_cast<ConstantFP>(Op1)) { - const APFloat &Op1F = Op1C->getValueAPF(); - - // If the divisor has an exact multiplicative inverse we can turn the fdiv - // into a cheaper fmul. - APFloat Reciprocal(Op1F.getSemantics()); - if (Op1F.getExactInverse(&Reciprocal)) { - ConstantFP *RFP = ConstantFP::get(Builder->getContext(), Reciprocal); - return BinaryOperator::CreateFMul(Op0, RFP); + if (AllowReassociate) { + ConstantFP *C1 = 0; + ConstantFP *C2 = Op1C; + Value *X; + Instruction *Res = 0; + + if (match(Op0, m_FMul(m_Value(X), m_ConstantFP(C1)))) { + // (X*C1)/C2 => X * (C1/C2) + // + Constant *C = ConstantExpr::getFDiv(C1, C2); + const APFloat &F = cast<ConstantFP>(C)->getValueAPF(); + if (F.isNormal() && !F.isDenormal()) + Res = BinaryOperator::CreateFMul(X, C); + } else if (match(Op0, m_FDiv(m_Value(X), m_ConstantFP(C1)))) { + // (X/C1)/C2 => X /(C2*C1) [=> X * 1/(C2*C1) if reciprocal is allowed] + // + Constant *C = ConstantExpr::getFMul(C1, C2); + const APFloat &F = cast<ConstantFP>(C)->getValueAPF(); + if (F.isNormal() && !F.isDenormal()) { + Res = CvtFDivConstToReciprocal(X, cast<ConstantFP>(C), + AllowReciprocal); + if (!Res) + Res = BinaryOperator::CreateFDiv(X, C); + } + } + + if (Res) { + Res->setFastMathFlags(I.getFastMathFlags()); + return Res; + } + } + + // X / C => X * 1/C + if (Instruction *T = CvtFDivConstToReciprocal(Op0, Op1C, AllowReciprocal)) + return T; + + return 0; + } + + if (AllowReassociate && isa<ConstantFP>(Op0)) { + ConstantFP *C1 = cast<ConstantFP>(Op0), *C2; + Constant *Fold = 0; + Value *X; + bool CreateDiv = true; + + // C1 / (X*C2) => (C1/C2) / X + if (match(Op1, m_FMul(m_Value(X), m_ConstantFP(C2)))) + Fold = ConstantExpr::getFDiv(C1, C2); + else if (match(Op1, m_FDiv(m_Value(X), m_ConstantFP(C2)))) { + // C1 / (X/C2) => (C1*C2) / X + Fold = ConstantExpr::getFMul(C1, C2); + } else if (match(Op1, m_FDiv(m_ConstantFP(C2), m_Value(X)))) { + // C1 / (C2/X) => (C1/C2) * X + Fold = ConstantExpr::getFDiv(C1, C2); + CreateDiv = false; + } + + if (Fold) { + const APFloat &FoldC = cast<ConstantFP>(Fold)->getValueAPF(); + if (FoldC.isNormal() && !FoldC.isDenormal()) { + Instruction *R = CreateDiv ? + BinaryOperator::CreateFDiv(Fold, X) : + BinaryOperator::CreateFMul(X, Fold); + R->setFastMathFlags(I.getFastMathFlags()); + return R; + } + } + return 0; + } + + if (AllowReassociate) { + Value *X, *Y; + Value *NewInst = 0; + Instruction *SimpR = 0; + + if (Op0->hasOneUse() && match(Op0, m_FDiv(m_Value(X), m_Value(Y)))) { + // (X/Y) / Z => X / (Y*Z) + // + if (!isa<ConstantFP>(Y) || !isa<ConstantFP>(Op1)) { + NewInst = Builder->CreateFMul(Y, Op1); + SimpR = BinaryOperator::CreateFDiv(X, NewInst); + } + } else if (Op1->hasOneUse() && match(Op1, m_FDiv(m_Value(X), m_Value(Y)))) { + // Z / (X/Y) => Z*Y / X + // + if (!isa<ConstantFP>(Y) || !isa<ConstantFP>(Op0)) { + NewInst = Builder->CreateFMul(Op0, Y); + SimpR = BinaryOperator::CreateFDiv(NewInst, X); + } + } + + if (NewInst) { + if (Instruction *T = dyn_cast<Instruction>(NewInst)) + T->setDebugLoc(I.getDebugLoc()); + SimpR->setFastMathFlags(I.getFastMathFlags()); + return SimpR; } } diff --git a/lib/Transforms/InstCombine/InstCombineWorklist.h b/lib/Transforms/InstCombine/InstCombineWorklist.h index 57ed9e32bb..49efce5c4f 100644 --- a/lib/Transforms/InstCombine/InstCombineWorklist.h +++ b/lib/Transforms/InstCombine/InstCombineWorklist.h @@ -19,20 +19,20 @@ #include "llvm/Support/raw_ostream.h" namespace llvm { - + /// InstCombineWorklist - This is the worklist management logic for /// InstCombine. class LLVM_LIBRARY_VISIBILITY InstCombineWorklist { SmallVector<Instruction*, 256> Worklist; DenseMap<Instruction*, unsigned> WorklistMap; - + void operator=(const InstCombineWorklist&RHS) LLVM_DELETED_FUNCTION; InstCombineWorklist(const InstCombineWorklist&) LLVM_DELETED_FUNCTION; public: InstCombineWorklist() {} - + bool isEmpty() const { return Worklist.empty(); } - + /// Add - Add the specified instruction to the worklist if it isn't already /// in it. void Add(Instruction *I) { @@ -41,12 +41,12 @@ public: Worklist.push_back(I); } } - + void AddValue(Value *V) { if (Instruction *I = dyn_cast<Instruction>(V)) Add(I); } - + /// AddInitialGroup - Add the specified batch of stuff in reverse order. /// which should only be done when the worklist is empty and when the group /// has no duplicates. @@ -61,25 +61,25 @@ public: Worklist.push_back(I); } } - + // Remove - remove I from the worklist if it exists. void Remove(Instruction *I) { DenseMap<Instruction*, unsigned>::iterator It = WorklistMap.find(I); if (It == WorklistMap.end()) return; // Not in worklist. - + // Don't bother moving everything down, just null out the slot. Worklist[It->second] = 0; - + WorklistMap.erase(It); } - + Instruction *RemoveOne() { Instruction *I = Worklist.back(); Worklist.pop_back(); WorklistMap.erase(I); return I; } - + /// AddUsersToWorkList - When an instruction is simplified, add all users of /// the instruction to the work lists because they might get more simplified /// now. @@ -89,18 +89,18 @@ public: UI != UE; ++UI) Add(cast<Instruction>(*UI)); } - - + + /// Zap - check that the worklist is empty and nuke the backing store for /// the map if it is large. void Zap() { assert(WorklistMap.empty() && "Worklist empty, but map not?"); - + // Do an explicit clear, this shrinks the map if needed. WorklistMap.clear(); } }; - + } // end namespace llvm. #endif diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 76da970682..db0de4d797 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -574,7 +574,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { if (IntegerType *IT = dyn_cast<IntegerType>(OrigTy)) return IT; if (VectorType *VT = dyn_cast<VectorType>(OrigTy)) { - uint32_t EltSize = MS.TD->getTypeStoreSizeInBits(VT->getElementType()); + uint32_t EltSize = MS.TD->getTypeSizeInBits(VT->getElementType()); return VectorType::get(IntegerType::get(*MS.C, EltSize), VT->getNumElements()); } @@ -586,7 +586,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { DEBUG(dbgs() << "getShadowTy: " << *ST << " ===> " << *Res << "\n"); return Res; } - uint32_t TypeSize = MS.TD->getTypeStoreSizeInBits(OrigTy); + uint32_t TypeSize = MS.TD->getTypeSizeInBits(OrigTy); return IntegerType::get(*MS.C, TypeSize); } @@ -1127,10 +1127,13 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { Value *B = I.getOperand(1); Value *Sa = getShadow(A); Value *Sb = getShadow(B); - if (A->getType()->isPointerTy()) - A = IRB.CreatePointerCast(A, MS.IntptrTy); - if (B->getType()->isPointerTy()) - B = IRB.CreatePointerCast(B, MS.IntptrTy); + + // Get rid of pointers and vectors of pointers. + // For ints (and vectors of ints), types of A and Sa match, + // and this is a no-op. + A = IRB.CreatePointerCast(A, Sa->getType()); + B = IRB.CreatePointerCast(B, Sb->getType()); + // A == B <==> (C = A^B) == 0 // A != B <==> (C = A^B) != 0 // Sc = Sa | Sb diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp index 8330e8468f..ba99d2e662 100644 --- a/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -37,12 +37,12 @@ void llvm::DeleteDeadBlock(BasicBlock *BB) { // Can delete self loop. BB->getSinglePredecessor() == BB) && "Block is not dead!"); TerminatorInst *BBTerm = BB->getTerminator(); - + // Loop through all of our successors and make sure they know that one // of their predecessors is going away. for (unsigned i = 0, e = BBTerm->getNumSuccessors(); i != e; ++i) BBTerm->getSuccessor(i)->removePredecessor(BB); - + // Zap all the instructions in the block. while (!BB->empty()) { Instruction &I = BB->back(); @@ -55,7 +55,7 @@ void llvm::DeleteDeadBlock(BasicBlock *BB) { I.replaceAllUsesWith(UndefValue::get(I.getType())); BB->getInstList().pop_back(); } - + // Zap the block! BB->eraseFromParent(); } @@ -66,25 +66,25 @@ void llvm::DeleteDeadBlock(BasicBlock *BB) { /// when the block has exactly one predecessor. void llvm::FoldSingleEntryPHINodes(BasicBlock *BB, Pass *P) { if (!isa<PHINode>(BB->begin())) return; - + AliasAnalysis *AA = 0; MemoryDependenceAnalysis *MemDep = 0; if (P) { AA = P->getAnalysisIfAvailable<AliasAnalysis>(); MemDep = P->getAnalysisIfAvailable<MemoryDependenceAnalysis>(); } - + while (PHINode *PN = dyn_cast<PHINode>(BB->begin())) { if (PN->getIncomingValue(0) != PN) PN->replaceAllUsesWith(PN->getIncomingValue(0)); else PN->replaceAllUsesWith(UndefValue::get(PN->getType())); - + if (MemDep) MemDep->removeInstruction(PN); // Memdep updates AA itself. else if (AA && isa<PointerType>(PN->getType())) AA->deleteValue(PN); - + PN->eraseFromParent(); } } @@ -115,7 +115,7 @@ bool llvm::DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI) { bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P) { // Don't merge away blocks who have their address taken. if (BB->hasAddressTaken()) return false; - + // Can't merge if there are multiple predecessors, or no predecessors. BasicBlock *PredBB = BB->getUniquePredecessor(); if (!PredBB) return false; @@ -124,7 +124,7 @@ bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P) { if (PredBB == BB) return false; // Don't break invokes. if (isa<InvokeInst>(PredBB->getTerminator())) return false; - + succ_iterator SI(succ_begin(PredBB)), SE(succ_end(PredBB)); BasicBlock *OnlySucc = BB; for (; SI != SE; ++SI) @@ -132,7 +132,7 @@ bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P) { OnlySucc = 0; // There are multiple distinct successors! break; } - + // Can't merge if there are multiple successors. if (!OnlySucc) return false; @@ -149,21 +149,21 @@ bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P) { // Begin by getting rid of unneeded PHIs. if (isa<PHINode>(BB->front())) FoldSingleEntryPHINodes(BB, P); - + // Delete the unconditional branch from the predecessor... PredBB->getInstList().pop_back(); - + // Make all PHI nodes that referred to BB now refer to Pred as their // source... BB->replaceAllUsesWith(PredBB); - + // Move all definitions in the successor to the predecessor... PredBB->getInstList().splice(PredBB->end(), BB->getInstList()); - + // Inherit predecessors name if it exists. if (!PredBB->hasName()) PredBB->takeName(BB); - + // Finally, erase the old block and update dominator info. if (P) { if (DominatorTree *DT = P->getAnalysisIfAvailable<DominatorTree>()) { @@ -176,16 +176,16 @@ bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P) { DT->eraseNode(BB); } - + if (LoopInfo *LI = P->getAnalysisIfAvailable<LoopInfo>()) LI->removeBlock(BB); - + if (MemoryDependenceAnalysis *MD = P->getAnalysisIfAvailable<MemoryDependenceAnalysis>()) MD->invalidateCachedPredecessors(); } } - + BB->eraseFromParent(); return true; } @@ -251,11 +251,11 @@ unsigned llvm::GetSuccessorNumber(BasicBlock *BB, BasicBlock *Succ) { } } -/// SplitEdge - Split the edge connecting specified block. Pass P must -/// not be NULL. +/// SplitEdge - Split the edge connecting specified block. Pass P must +/// not be NULL. BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, Pass *P) { unsigned SuccNum = GetSuccessorNumber(BB, Succ); - + // If this is a critical edge, let SplitCriticalEdge do it. TerminatorInst *LatchTerm = BB->getTerminator(); if (SplitCriticalEdge(LatchTerm, SuccNum, P)) @@ -271,11 +271,11 @@ BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, Pass *P) { SP = NULL; return SplitBlock(Succ, Succ->begin(), P); } - + // Otherwise, if BB has a single successor, split it at the bottom of the // block. assert(BB->getTerminator()->getNumSuccessors() == 1 && - "Should have a single succ!"); + "Should have a single succ!"); return SplitBlock(BB, BB->getTerminator(), P); } @@ -301,12 +301,12 @@ BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P) { if (DomTreeNode *OldNode = DT->getNode(Old)) { std::vector<DomTreeNode *> Children; for (DomTreeNode::iterator I = OldNode->begin(), E = OldNode->end(); - I != E; ++I) + I != E; ++I) Children.push_back(*I); DomTreeNode *NewNode = DT->addNewBlock(New,Old); for (std::vector<DomTreeNode *>::iterator I = Children.begin(), - E = Children.end(); I != E; ++I) + E = Children.end(); I != E; ++I) DT->changeImmediateDominator(*I, NewNode); } } @@ -424,7 +424,7 @@ static void UpdatePHINodes(BasicBlock *OrigBB, BasicBlock *NewBB, PHINode *NewPHI = PHINode::Create(PN->getType(), Preds.size(), PN->getName() + ".ph", BI); if (AA) AA->copyValue(PN, NewPHI); - + // Move all of the PHI values for 'Preds' to the new PHI. for (unsigned i = 0, e = Preds.size(); i != e; ++i) { Value *V = PN->removeIncomingValue(Preds[i], false); @@ -451,16 +451,16 @@ static void UpdatePHINodes(BasicBlock *OrigBB, BasicBlock *NewBB, /// preserve LoopSimplify (because it's complicated to handle the case where one /// of the edges being split is an exit of a loop with other exits). /// -BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB, +BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock*> Preds, const char *Suffix, Pass *P) { // Create new basic block, insert right before the original block. BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), BB->getName()+Suffix, BB->getParent(), BB); - + // The new block unconditionally branches to the old block. BranchInst *BI = BranchInst::Create(BB, NewBB); - + // Move the edges from Preds to point to NewBB instead of BB. for (unsigned i = 0, e = Preds.size(); i != e; ++i) { // This is slightly more strict than necessary; the minimum requirement @@ -497,13 +497,13 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB, /// block gets the remaining predecessors of OrigBB. The landingpad instruction /// OrigBB is clone into both of the new basic blocks. The new blocks are given /// the suffixes 'Suffix1' and 'Suffix2', and are returned in the NewBBs vector. -/// +/// /// This currently updates the LLVM IR, AliasAnalysis, DominatorTree, /// DominanceFrontier, LoopInfo, and LCCSA but no other analyses. In particular, /// it does not preserve LoopSimplify (because it's complicated to handle the /// case where one of the edges being split is an exit of a loop with other /// exits). -/// +/// void llvm::SplitLandingPadPredecessors(BasicBlock *OrigBB, ArrayRef<BasicBlock*> Preds, const char *Suffix1, const char *Suffix2, @@ -608,11 +608,11 @@ void llvm::FindFunctionBackedges(const Function &F, const BasicBlock *BB = &F.getEntryBlock(); if (succ_begin(BB) == succ_end(BB)) return; - + SmallPtrSet<const BasicBlock*, 8> Visited; SmallVector<std::pair<const BasicBlock*, succ_const_iterator>, 8> VisitStack; SmallPtrSet<const BasicBlock*, 8> InStack; - + Visited.insert(BB); VisitStack.push_back(std::make_pair(BB, succ_begin(BB))); InStack.insert(BB); @@ -620,7 +620,7 @@ void llvm::FindFunctionBackedges(const Function &F, std::pair<const BasicBlock*, succ_const_iterator> &Top = VisitStack.back(); const BasicBlock *ParentBB = Top.first; succ_const_iterator &I = Top.second; - + bool FoundNew = false; while (I != succ_end(ParentBB)) { BB = *I++; @@ -632,7 +632,7 @@ void llvm::FindFunctionBackedges(const Function &F, if (InStack.count(BB)) Result.push_back(std::make_pair(ParentBB, BB)); } - + if (FoundNew) { // Go down one level if there is a unvisited successor. InStack.insert(BB); @@ -641,7 +641,7 @@ void llvm::FindFunctionBackedges(const Function &F, // Go up one level. InStack.erase(VisitStack.pop_back_val().first); } - } while (!VisitStack.empty()); + } while (!VisitStack.empty()); } /// FoldReturnIntoUncondBranch - This method duplicates the specified return @@ -655,7 +655,7 @@ ReturnInst *llvm::FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, // Clone the return and add it to the end of the predecessor. Instruction *NewRet = RI->clone(); Pred->getInstList().push_back(NewRet); - + // If the return instruction returns a value, and if the value was a // PHI node in "BB", propagate the right value into the return. for (User::op_iterator i = NewRet->op_begin(), e = NewRet->op_end(); @@ -679,7 +679,7 @@ ReturnInst *llvm::FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, } } } - + // Update any PHI nodes in the returning block to realize that we no // longer branch to them. BB->removePredecessor(Pred); diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index 464ed97506..bc8e1217be 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -2633,7 +2633,7 @@ LoopVectorizationCostModel::selectVectorizationFactor(bool OptForSize, if (MaxVectorSize == 0) { DEBUG(dbgs() << "LV: The target has no vector registers.\n"); - return 1; + MaxVectorSize = 1; } assert(MaxVectorSize <= 32 && "Did not expect to pack so many elements" diff --git a/test/CodeGen/PowerPC/load-shift-combine.ll b/test/CodeGen/PowerPC/load-shift-combine.ll new file mode 100644 index 0000000000..a5d1224864 --- /dev/null +++ b/test/CodeGen/PowerPC/load-shift-combine.ll @@ -0,0 +1,34 @@ +; RUN: llc < %s + +; This used to cause a crash. A standard load is converted to a pre-increment +; load. Later the pre-increment load is combined with a subsequent SRL to +; produce a smaller load. This transform invalidly created a standard load +; and propagated the produced value into uses of both produced values of the +; pre-increment load. The result was a crash when attempting to process an +; add with a token-chain operand. + +%struct.Info = type { i32, i32, i8*, i8*, i8*, [32 x i8*], i64, [32 x i64], i64, i64, i64, [32 x i64] } +%struct.S1847 = type { [12 x i8], [4 x i8], [8 x i8], [4 x i8], [8 x i8], [2 x i8], i8, [4 x i64], i8, [3 x i8], [4 x i8], i8, i16, [4 x %struct.anon.76], i16, i8, i8* } +%struct.anon.76 = type { i32 } +@info = common global %struct.Info zeroinitializer, align 8 +@fails = common global i32 0, align 4 +@a1847 = external global [5 x %struct.S1847] +define void @test1847() nounwind { +entry: + %j = alloca i32, align 4 + %0 = load i64* getelementptr inbounds (%struct.Info* @info, i32 0, i32 8), align 8 + %1 = load i32* @fails, align 4 + %bf.load1 = load i96* bitcast (%struct.S1847* getelementptr inbounds ([5 x %struct.S1847]* @a1847, i32 0, i64 2) to i96*), align 8 + %bf.clear2 = and i96 %bf.load1, 302231454903657293676543 + %bf.set3 = or i96 %bf.clear2, -38383394772764476296921088 + store i96 %bf.set3, i96* bitcast (%struct.S1847* getelementptr inbounds ([5 x %struct.S1847]* @a1847, i32 0, i64 2) to i96*), align 8 + %2 = load i32* %j, align 4 + %3 = load i32* %j, align 4 + %inc11 = add nsw i32 %3, 1 + store i32 %inc11, i32* %j, align 4 + %bf.load15 = load i96* bitcast (%struct.S1847* getelementptr inbounds ([5 x %struct.S1847]* @a1847, i32 0, i64 2) to i96*), align 8 + %bf.clear16 = and i96 %bf.load15, -18446744069414584321 + %bf.set17 = or i96 %bf.clear16, 18446743532543672320 + store i96 %bf.set17, i96* bitcast (%struct.S1847* getelementptr inbounds ([5 x %struct.S1847]* @a1847, i32 0, i64 2) to i96*), align 8 + ret void +} diff --git a/test/Instrumentation/MemorySanitizer/msan_basic.ll b/test/Instrumentation/MemorySanitizer/msan_basic.ll index cd90f8836a..641a3a26f4 100644 --- a/test/Instrumentation/MemorySanitizer/msan_basic.ll +++ b/test/Instrumentation/MemorySanitizer/msan_basic.ll @@ -362,6 +362,22 @@ define zeroext i1 @ICmpSLE(i32 %x) nounwind uwtable readnone { ; CHECK: ret i1 +; Check that we propagate shadow for x<0, x>=0, etc (i.e. sign bit tests) +; of the vector arguments. + +define <2 x i1> @ICmpSLT_vector(<2 x i32*> %x) nounwind uwtable readnone { + %1 = icmp slt <2 x i32*> %x, zeroinitializer + ret <2 x i1> %1 +} + +; CHECK: @ICmpSLT_vector +; CHECK: icmp slt <2 x i64> +; CHECK-NOT: call void @__msan_warning +; CHECK: icmp slt <2 x i32*> +; CHECK-NOT: call void @__msan_warning +; CHECK: ret <2 x i1> + + ; Check that loads of shadow have the same aligment as the original loads. ; Check that loads of origin have the aligment of max(4, original alignment). diff --git a/test/MC/Mips/elf-gprel-32-64.ll b/test/MC/Mips/elf-gprel-32-64.ll new file mode 100644 index 0000000000..b94682214d --- /dev/null +++ b/test/MC/Mips/elf-gprel-32-64.ll @@ -0,0 +1,37 @@ +; RUN: llc -filetype=obj -march=mips64el -mcpu=mips64 %s -o - \ +; RUN: | elf-dump --dump-section-data \ +; RUN: | FileCheck %s + +define i32 @test(i32 %c) nounwind { +entry: + switch i32 %c, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb2 + i32 2, label %sw.bb5 + i32 3, label %sw.bb8 + ] + +sw.bb: + br label %return +sw.bb2: + br label %return +sw.bb5: + br label %return +sw.bb8: + br label %return +sw.default: + br label %return + +return: + %retval.0 = phi i32 [ -1, %sw.default ], [ 7, %sw.bb8 ], [ 2, %sw.bb5 ], [ 3, %sw.bb2 ], [ 1, %sw.bb ] + ret i32 %retval.0 +} + +; Check that the appropriate relocations were created. + +; R_MIPS_GPREL32/R_MIPS_64/R_MIPS_NONE +; CHECK: (('sh_name', 0x{{[a-z0-9]+}}) # '.rela.rodata' +; CHECK: ('r_type3', 0x00) +; CHECK-NEXT: ('r_type2', 0x12) +; CHECK-NEXT: ('r_type', 0x0c) + diff --git a/test/MC/X86/AlignedBundling/autogen-inst-offset-align-to-end.s b/test/MC/X86/AlignedBundling/autogen-inst-offset-align-to-end.s index 7fbb71bd4d..fbf5b52944 100644 --- a/test/MC/X86/AlignedBundling/autogen-inst-offset-align-to-end.s +++ b/test/MC/X86/AlignedBundling/autogen-inst-offset-align-to-end.s @@ -354,6 +354,7 @@ INSTRLEN_2_OFFSET_15: .endr .bundle_unlock # CHECK: 3ef: nop +# CHECK: 3f0: nop # CHECK: 3fe: incl .align 32, 0x90 @@ -517,6 +518,7 @@ INSTRLEN_3_OFFSET_14: .endr .bundle_unlock # CHECK: 5ce: nop +# CHECK: 5d0: nop # CHECK: 5dd: incl .align 32, 0x90 @@ -528,6 +530,7 @@ INSTRLEN_3_OFFSET_15: .endr .bundle_unlock # CHECK: 5ef: nop +# CHECK: 5f0: nop # CHECK: 5fd: incl .align 32, 0x90 @@ -680,6 +683,7 @@ INSTRLEN_4_OFFSET_13: .endr .bundle_unlock # CHECK: 7ad: nop +# CHECK: 7b0: nop # CHECK: 7bc: incl .align 32, 0x90 @@ -691,6 +695,7 @@ INSTRLEN_4_OFFSET_14: .endr .bundle_unlock # CHECK: 7ce: nop +# CHECK: 7d0: nop # CHECK: 7dc: incl .align 32, 0x90 @@ -702,6 +707,7 @@ INSTRLEN_4_OFFSET_15: .endr .bundle_unlock # CHECK: 7ef: nop +# CHECK: 7f0: nop # CHECK: 7fc: incl .align 32, 0x90 @@ -843,6 +849,7 @@ INSTRLEN_5_OFFSET_12: .endr .bundle_unlock # CHECK: 98c: nop +# CHECK: 990: nop # CHECK: 99b: incl .align 32, 0x90 @@ -854,6 +861,7 @@ INSTRLEN_5_OFFSET_13: .endr .bundle_unlock # CHECK: 9ad: nop +# CHECK: 9b0: nop # CHECK: 9bb: incl .align 32, 0x90 @@ -865,6 +873,7 @@ INSTRLEN_5_OFFSET_14: .endr .bundle_unlock # CHECK: 9ce: nop +# CHECK: 9d0: nop # CHECK: 9db: incl .align 32, 0x90 @@ -876,6 +885,7 @@ INSTRLEN_5_OFFSET_15: .endr .bundle_unlock # CHECK: 9ef: nop +# CHECK: 9f0: nop # CHECK: 9fb: incl .align 32, 0x90 @@ -1006,6 +1016,7 @@ INSTRLEN_6_OFFSET_11: .endr .bundle_unlock # CHECK: b6b: nop +# CHECK: b70: nop # CHECK: b7a: incl .align 32, 0x90 @@ -1017,6 +1028,7 @@ INSTRLEN_6_OFFSET_12: .endr .bundle_unlock # CHECK: b8c: nop +# CHECK: b90: nop # CHECK: b9a: incl .align 32, 0x90 @@ -1028,6 +1040,7 @@ INSTRLEN_6_OFFSET_13: .endr .bundle_unlock # CHECK: bad: nop +# CHECK: bb0: nop # CHECK: bba: incl .align 32, 0x90 @@ -1039,6 +1052,7 @@ INSTRLEN_6_OFFSET_14: .endr .bundle_unlock # CHECK: bce: nop +# CHECK: bd0: nop # CHECK: bda: incl .align 32, 0x90 @@ -1050,6 +1064,7 @@ INSTRLEN_6_OFFSET_15: .endr .bundle_unlock # CHECK: bef: nop +# CHECK: bf0: nop # CHECK: bfa: incl .align 32, 0x90 @@ -1169,6 +1184,7 @@ INSTRLEN_7_OFFSET_10: .endr .bundle_unlock # CHECK: d4a: nop +# CHECK: d50: nop # CHECK: d59: incl .align 32, 0x90 @@ -1180,6 +1196,7 @@ INSTRLEN_7_OFFSET_11: .endr .bundle_unlock # CHECK: d6b: nop +# CHECK: d70: nop # CHECK: d79: incl .align 32, 0x90 @@ -1191,6 +1208,7 @@ INSTRLEN_7_OFFSET_12: .endr .bundle_unlock # CHECK: d8c: nop +# CHECK: d90: nop # CHECK: d99: incl .align 32, 0x90 @@ -1202,6 +1220,7 @@ INSTRLEN_7_OFFSET_13: .endr .bundle_unlock # CHECK: dad: nop +# CHECK: db0: nop # CHECK: db9: incl .align 32, 0x90 @@ -1213,6 +1232,7 @@ INSTRLEN_7_OFFSET_14: .endr .bundle_unlock # CHECK: dce: nop +# CHECK: dd0: nop # CHECK: dd9: incl .align 32, 0x90 @@ -1224,6 +1244,7 @@ INSTRLEN_7_OFFSET_15: .endr .bundle_unlock # CHECK: def: nop +# CHECK: df0: nop # CHECK: df9: incl .align 32, 0x90 @@ -1332,6 +1353,7 @@ INSTRLEN_8_OFFSET_9: .endr .bundle_unlock # CHECK: f29: nop +# CHECK: f30: nop # CHECK: f38: incl .align 32, 0x90 @@ -1343,6 +1365,7 @@ INSTRLEN_8_OFFSET_10: .endr .bundle_unlock # CHECK: f4a: nop +# CHECK: f50: nop # CHECK: f58: incl .align 32, 0x90 @@ -1354,6 +1377,7 @@ INSTRLEN_8_OFFSET_11: .endr .bundle_unlock # CHECK: f6b: nop +# CHECK: f70: nop # CHECK: f78: incl .align 32, 0x90 @@ -1365,6 +1389,7 @@ INSTRLEN_8_OFFSET_12: .endr .bundle_unlock # CHECK: f8c: nop +# CHECK: f90: nop # CHECK: f98: incl .align 32, 0x90 @@ -1376,6 +1401,7 @@ INSTRLEN_8_OFFSET_13: .endr .bundle_unlock # CHECK: fad: nop +# CHECK: fb0: nop # CHECK: fb8: incl .align 32, 0x90 @@ -1387,6 +1413,7 @@ INSTRLEN_8_OFFSET_14: .endr .bundle_unlock # CHECK: fce: nop +# CHECK: fd0: nop # CHECK: fd8: incl .align 32, 0x90 @@ -1398,6 +1425,7 @@ INSTRLEN_8_OFFSET_15: .endr .bundle_unlock # CHECK: fef: nop +# CHECK: ff0: nop # CHECK: ff8: incl .align 32, 0x90 @@ -1495,6 +1523,7 @@ INSTRLEN_9_OFFSET_8: .endr .bundle_unlock # CHECK: 1108: nop +# CHECK: 1110: nop # CHECK: 1117: incl .align 32, 0x90 @@ -1506,6 +1535,7 @@ INSTRLEN_9_OFFSET_9: .endr .bundle_unlock # CHECK: 1129: nop +# CHECK: 1130: nop # CHECK: 1137: incl .align 32, 0x90 @@ -1517,6 +1547,7 @@ INSTRLEN_9_OFFSET_10: .endr .bundle_unlock # CHECK: 114a: nop +# CHECK: 1150: nop # CHECK: 1157: incl .align 32, 0x90 @@ -1528,6 +1559,7 @@ INSTRLEN_9_OFFSET_11: .endr .bundle_unlock # CHECK: 116b: nop +# CHECK: 1170: nop # CHECK: 1177: incl .align 32, 0x90 @@ -1539,6 +1571,7 @@ INSTRLEN_9_OFFSET_12: .endr .bundle_unlock # CHECK: 118c: nop +# CHECK: 1190: nop # CHECK: 1197: incl .align 32, 0x90 @@ -1550,6 +1583,7 @@ INSTRLEN_9_OFFSET_13: .endr .bundle_unlock # CHECK: 11ad: nop +# CHECK: 11b0: nop # CHECK: 11b7: incl .align 32, 0x90 @@ -1561,6 +1595,7 @@ INSTRLEN_9_OFFSET_14: .endr .bundle_unlock # CHECK: 11ce: nop +# CHECK: 11d0: nop # CHECK: 11d7: incl .align 32, 0x90 @@ -1572,6 +1607,7 @@ INSTRLEN_9_OFFSET_15: .endr .bundle_unlock # CHECK: 11ef: nop +# CHECK: 11f0: nop # CHECK: 11f7: incl .align 32, 0x90 @@ -1658,6 +1694,7 @@ INSTRLEN_10_OFFSET_7: .endr .bundle_unlock # CHECK: 12e7: nop +# CHECK: 12f0: nop # CHECK: 12f6: incl .align 32, 0x90 @@ -1669,6 +1706,7 @@ INSTRLEN_10_OFFSET_8: .endr .bundle_unlock # CHECK: 1308: nop +# CHECK: 1310: nop # CHECK: 1316: incl .align 32, 0x90 @@ -1680,6 +1718,7 @@ INSTRLEN_10_OFFSET_9: .endr .bundle_unlock # CHECK: 1329: nop +# CHECK: 1330: nop # CHECK: 1336: incl .align 32, 0x90 @@ -1691,6 +1730,7 @@ INSTRLEN_10_OFFSET_10: .endr .bundle_unlock # CHECK: 134a: nop +# CHECK: 1350: nop # CHECK: 1356: incl .align 32, 0x90 @@ -1702,6 +1742,7 @@ INSTRLEN_10_OFFSET_11: .endr .bundle_unlock # CHECK: 136b: nop +# CHECK: 1370: nop # CHECK: 1376: incl .align 32, 0x90 @@ -1713,6 +1754,7 @@ INSTRLEN_10_OFFSET_12: .endr .bundle_unlock # CHECK: 138c: nop +# CHECK: 1390: nop # CHECK: 1396: incl .align 32, 0x90 @@ -1724,6 +1766,7 @@ INSTRLEN_10_OFFSET_13: .endr .bundle_unlock # CHECK: 13ad: nop +# CHECK: 13b0: nop # CHECK: 13b6: incl .align 32, 0x90 @@ -1735,6 +1778,7 @@ INSTRLEN_10_OFFSET_14: .endr .bundle_unlock # CHECK: 13ce: nop +# CHECK: 13d0: nop # CHECK: 13d6: incl .align 32, 0x90 @@ -1746,6 +1790,7 @@ INSTRLEN_10_OFFSET_15: .endr .bundle_unlock # CHECK: 13ef: nop +# CHECK: 13f0: nop # CHECK: 13f6: incl .align 32, 0x90 @@ -1821,6 +1866,7 @@ INSTRLEN_11_OFFSET_6: .endr .bundle_unlock # CHECK: 14c6: nop +# CHECK: 14d0: nop # CHECK: 14d5: incl .align 32, 0x90 @@ -1832,6 +1878,7 @@ INSTRLEN_11_OFFSET_7: .endr .bundle_unlock # CHECK: 14e7: nop +# CHECK: 14f0: nop # CHECK: 14f5: incl .align 32, 0x90 @@ -1843,6 +1890,7 @@ INSTRLEN_11_OFFSET_8: .endr .bundle_unlock # CHECK: 1508: nop +# CHECK: 1510: nop # CHECK: 1515: incl .align 32, 0x90 @@ -1854,6 +1902,7 @@ INSTRLEN_11_OFFSET_9: .endr .bundle_unlock # CHECK: 1529: nop +# CHECK: 1530: nop # CHECK: 1535: incl .align 32, 0x90 @@ -1865,6 +1914,7 @@ INSTRLEN_11_OFFSET_10: .endr .bundle_unlock # CHECK: 154a: nop +# CHECK: 1550: nop # CHECK: 1555: incl .align 32, 0x90 @@ -1876,6 +1926,7 @@ INSTRLEN_11_OFFSET_11: .endr .bundle_unlock # CHECK: 156b: nop +# CHECK: 1570: nop # CHECK: 1575: incl .align 32, 0x90 @@ -1887,6 +1938,7 @@ INSTRLEN_11_OFFSET_12: .endr .bundle_unlock # CHECK: 158c: nop +# CHECK: 1590: nop # CHECK: 1595: incl .align 32, 0x90 @@ -1898,6 +1950,7 @@ INSTRLEN_11_OFFSET_13: .endr .bundle_unlock # CHECK: 15ad: nop +# CHECK: 15b0: nop # CHECK: 15b5: incl .align 32, 0x90 @@ -1909,6 +1962,7 @@ INSTRLEN_11_OFFSET_14: .endr .bundle_unlock # CHECK: 15ce: nop +# CHECK: 15d0: nop # CHECK: 15d5: incl .align 32, 0x90 @@ -1920,6 +1974,7 @@ INSTRLEN_11_OFFSET_15: .endr .bundle_unlock # CHECK: 15ef: nop +# CHECK: 15f0: nop # CHECK: 15f5: incl .align 32, 0x90 @@ -1984,6 +2039,7 @@ INSTRLEN_12_OFFSET_5: .endr .bundle_unlock # CHECK: 16a5: nop +# CHECK: 16b0: nop # CHECK: 16b4: incl .align 32, 0x90 @@ -1995,6 +2051,7 @@ INSTRLEN_12_OFFSET_6: .endr .bundle_unlock # CHECK: 16c6: nop +# CHECK: 16d0: nop # CHECK: 16d4: incl .align 32, 0x90 @@ -2006,6 +2063,7 @@ INSTRLEN_12_OFFSET_7: .endr .bundle_unlock # CHECK: 16e7: nop +# CHECK: 16f0: nop # CHECK: 16f4: incl .align 32, 0x90 @@ -2017,6 +2075,7 @@ INSTRLEN_12_OFFSET_8: .endr .bundle_unlock # CHECK: 1708: nop +# CHECK: 1710: nop # CHECK: 1714: incl .align 32, 0x90 @@ -2028,6 +2087,7 @@ INSTRLEN_12_OFFSET_9: .endr .bundle_unlock # CHECK: 1729: nop +# CHECK: 1730: nop # CHECK: 1734: incl .align 32, 0x90 @@ -2039,6 +2099,7 @@ INSTRLEN_12_OFFSET_10: .endr .bundle_unlock # CHECK: 174a: nop +# CHECK: 1750: nop # CHECK: 1754: incl .align 32, 0x90 @@ -2050,6 +2111,7 @@ INSTRLEN_12_OFFSET_11: .endr .bundle_unlock # CHECK: 176b: nop +# CHECK: 1770: nop # CHECK: 1774: incl .align 32, 0x90 @@ -2061,6 +2123,7 @@ INSTRLEN_12_OFFSET_12: .endr .bundle_unlock # CHECK: 178c: nop +# CHECK: 1790: nop # CHECK: 1794: incl .align 32, 0x90 @@ -2072,6 +2135,7 @@ INSTRLEN_12_OFFSET_13: .endr .bundle_unlock # CHECK: 17ad: nop +# CHECK: 17b0: nop # CHECK: 17b4: incl .align 32, 0x90 @@ -2083,6 +2147,7 @@ INSTRLEN_12_OFFSET_14: .endr .bundle_unlock # CHECK: 17ce: nop +# CHECK: 17d0: nop # CHECK: 17d4: incl .align 32, 0x90 @@ -2094,6 +2159,7 @@ INSTRLEN_12_OFFSET_15: .endr .bundle_unlock # CHECK: 17ef: nop +# CHECK: 17f0: nop # CHECK: 17f4: incl .align 32, 0x90 @@ -2147,6 +2213,7 @@ INSTRLEN_13_OFFSET_4: .endr .bundle_unlock # CHECK: 1884: nop +# CHECK: 1890: nop # CHECK: 1893: incl .align 32, 0x90 @@ -2158,6 +2225,7 @@ INSTRLEN_13_OFFSET_5: .endr .bundle_unlock # CHECK: 18a5: nop +# CHECK: 18b0: nop # CHECK: 18b3: incl .align 32, 0x90 @@ -2169,6 +2237,7 @@ INSTRLEN_13_OFFSET_6: .endr .bundle_unlock # CHECK: 18c6: nop +# CHECK: 18d0: nop # CHECK: 18d3: incl .align 32, 0x90 @@ -2180,6 +2249,7 @@ INSTRLEN_13_OFFSET_7: .endr .bundle_unlock # CHECK: 18e7: nop +# CHECK: 18f0: nop # CHECK: 18f3: incl .align 32, 0x90 @@ -2191,6 +2261,7 @@ INSTRLEN_13_OFFSET_8: .endr .bundle_unlock # CHECK: 1908: nop +# CHECK: 1910: nop # CHECK: 1913: incl .align 32, 0x90 @@ -2202,6 +2273,7 @@ INSTRLEN_13_OFFSET_9: .endr .bundle_unlock # CHECK: 1929: nop +# CHECK: 1930: nop # CHECK: 1933: incl .align 32, 0x90 @@ -2213,6 +2285,7 @@ INSTRLEN_13_OFFSET_10: .endr .bundle_unlock # CHECK: 194a: nop +# CHECK: 1950: nop # CHECK: 1953: incl .align 32, 0x90 @@ -2224,6 +2297,7 @@ INSTRLEN_13_OFFSET_11: .endr .bundle_unlock # CHECK: 196b: nop +# CHECK: 1970: nop # CHECK: 1973: incl .align 32, 0x90 @@ -2235,6 +2309,7 @@ INSTRLEN_13_OFFSET_12: .endr .bundle_unlock # CHECK: 198c: nop +# CHECK: 1990: nop # CHECK: 1993: incl .align 32, 0x90 @@ -2246,6 +2321,7 @@ INSTRLEN_13_OFFSET_13: .endr .bundle_unlock # CHECK: 19ad: nop +# CHECK: 19b0: nop # CHECK: 19b3: incl .align 32, 0x90 @@ -2257,6 +2333,7 @@ INSTRLEN_13_OFFSET_14: .endr .bundle_unlock # CHECK: 19ce: nop +# CHECK: 19d0: nop # CHECK: 19d3: incl .align 32, 0x90 @@ -2268,6 +2345,7 @@ INSTRLEN_13_OFFSET_15: .endr .bundle_unlock # CHECK: 19ef: nop +# CHECK: 19f0: nop # CHECK: 19f3: incl .align 32, 0x90 @@ -2310,6 +2388,7 @@ INSTRLEN_14_OFFSET_3: .endr .bundle_unlock # CHECK: 1a63: nop +# CHECK: 1a70: nop # CHECK: 1a72: incl .align 32, 0x90 @@ -2321,6 +2400,7 @@ INSTRLEN_14_OFFSET_4: .endr .bundle_unlock # CHECK: 1a84: nop +# CHECK: 1a90: nop # CHECK: 1a92: incl .align 32, 0x90 @@ -2332,6 +2412,7 @@ INSTRLEN_14_OFFSET_5: .endr .bundle_unlock # CHECK: 1aa5: nop +# CHECK: 1ab0: nop # CHECK: 1ab2: incl .align 32, 0x90 @@ -2343,6 +2424,7 @@ INSTRLEN_14_OFFSET_6: .endr .bundle_unlock # CHECK: 1ac6: nop +# CHECK: 1ad0: nop # CHECK: 1ad2: incl .align 32, 0x90 @@ -2354,6 +2436,7 @@ INSTRLEN_14_OFFSET_7: .endr .bundle_unlock # CHECK: 1ae7: nop +# CHECK: 1af0: nop # CHECK: 1af2: incl .align 32, 0x90 @@ -2365,6 +2448,7 @@ INSTRLEN_14_OFFSET_8: .endr .bundle_unlock # CHECK: 1b08: nop +# CHECK: 1b10: nop # CHECK: 1b12: incl .align 32, 0x90 @@ -2376,6 +2460,7 @@ INSTRLEN_14_OFFSET_9: .endr .bundle_unlock # CHECK: 1b29: nop +# CHECK: 1b30: nop # CHECK: 1b32: incl .align 32, 0x90 @@ -2387,6 +2472,7 @@ INSTRLEN_14_OFFSET_10: .endr .bundle_unlock # CHECK: 1b4a: nop +# CHECK: 1b50: nop # CHECK: 1b52: incl .align 32, 0x90 @@ -2398,6 +2484,7 @@ INSTRLEN_14_OFFSET_11: .endr .bundle_unlock # CHECK: 1b6b: nop +# CHECK: 1b70: nop # CHECK: 1b72: incl .align 32, 0x90 @@ -2409,6 +2496,7 @@ INSTRLEN_14_OFFSET_12: .endr .bundle_unlock # CHECK: 1b8c: nop +# CHECK: 1b90: nop # CHECK: 1b92: incl .align 32, 0x90 @@ -2420,6 +2508,7 @@ INSTRLEN_14_OFFSET_13: .endr .bundle_unlock # CHECK: 1bad: nop +# CHECK: 1bb0: nop # CHECK: 1bb2: incl .align 32, 0x90 @@ -2431,6 +2520,7 @@ INSTRLEN_14_OFFSET_14: .endr .bundle_unlock # CHECK: 1bce: nop +# CHECK: 1bd0: nop # CHECK: 1bd2: incl .align 32, 0x90 @@ -2442,6 +2532,7 @@ INSTRLEN_14_OFFSET_15: .endr .bundle_unlock # CHECK: 1bef: nop +# CHECK: 1bf0: nop # CHECK: 1bf2: incl .align 32, 0x90 @@ -2473,6 +2564,7 @@ INSTRLEN_15_OFFSET_2: .endr .bundle_unlock # CHECK: 1c42: nop +# CHECK: 1c50: nop # CHECK: 1c51: incl .align 32, 0x90 @@ -2484,6 +2576,7 @@ INSTRLEN_15_OFFSET_3: .endr .bundle_unlock # CHECK: 1c63: nop +# CHECK: 1c70: nop # CHECK: 1c71: incl .align 32, 0x90 @@ -2495,6 +2588,7 @@ INSTRLEN_15_OFFSET_4: .endr .bundle_unlock # CHECK: 1c84: nop +# CHECK: 1c90: nop # CHECK: 1c91: incl .align 32, 0x90 @@ -2506,6 +2600,7 @@ INSTRLEN_15_OFFSET_5: .endr .bundle_unlock # CHECK: 1ca5: nop +# CHECK: 1cb0: nop # CHECK: 1cb1: incl .align 32, 0x90 @@ -2517,6 +2612,7 @@ INSTRLEN_15_OFFSET_6: .endr .bundle_unlock # CHECK: 1cc6: nop +# CHECK: 1cd0: nop # CHECK: 1cd1: incl .align 32, 0x90 @@ -2528,6 +2624,7 @@ INSTRLEN_15_OFFSET_7: .endr .bundle_unlock # CHECK: 1ce7: nop +# CHECK: 1cf0: nop # CHECK: 1cf1: incl .align 32, 0x90 @@ -2539,6 +2636,7 @@ INSTRLEN_15_OFFSET_8: .endr .bundle_unlock # CHECK: 1d08: nop +# CHECK: 1d10: nop # CHECK: 1d11: incl .align 32, 0x90 @@ -2550,6 +2648,7 @@ INSTRLEN_15_OFFSET_9: .endr .bundle_unlock # CHECK: 1d29: nop +# CHECK: 1d30: nop # CHECK: 1d31: incl .align 32, 0x90 @@ -2561,6 +2660,7 @@ INSTRLEN_15_OFFSET_10: .endr .bundle_unlock # CHECK: 1d4a: nop +# CHECK: 1d50: nop # CHECK: 1d51: incl .align 32, 0x90 @@ -2572,6 +2672,7 @@ INSTRLEN_15_OFFSET_11: .endr .bundle_unlock # CHECK: 1d6b: nop +# CHECK: 1d70: nop # CHECK: 1d71: incl .align 32, 0x90 @@ -2583,6 +2684,7 @@ INSTRLEN_15_OFFSET_12: .endr .bundle_unlock # CHECK: 1d8c: nop +# CHECK: 1d90: nop # CHECK: 1d91: incl .align 32, 0x90 @@ -2594,6 +2696,7 @@ INSTRLEN_15_OFFSET_13: .endr .bundle_unlock # CHECK: 1dad: nop +# CHECK: 1db0: nop # CHECK: 1db1: incl .align 32, 0x90 @@ -2605,6 +2708,7 @@ INSTRLEN_15_OFFSET_14: .endr .bundle_unlock # CHECK: 1dce: nop +# CHECK: 1dd0: nop # CHECK: 1dd1: incl .align 32, 0x90 @@ -2616,6 +2720,7 @@ INSTRLEN_15_OFFSET_15: .endr .bundle_unlock # CHECK: 1def: nop +# CHECK: 1df0: nop # CHECK: 1df1: incl .align 32, 0x90 diff --git a/test/MC/X86/intel-syntax.s b/test/MC/X86/intel-syntax.s index 7edd26a138..8bfa58a4be 100644 --- a/test/MC/X86/intel-syntax.s +++ b/test/MC/X86/intel-syntax.s @@ -56,13 +56,195 @@ _main: // CHECK: fld %st(0) fld ST(0) // CHECK: movl %fs:(%rdi), %eax - mov EAX, DWORD PTR FS:[RDI] -// CHECK: leal (,%rdi,4), %r8d - lea R8D, DWORD PTR [4*RDI] -// CHECK: movl _fnan(,%ecx,4), %ecx - mov ECX, DWORD PTR [4*ECX + _fnan] -// CHECK: movq %fs:320, %rax - mov RAX, QWORD PTR FS:[320] -// CHECK: vpgatherdd %xmm8, (%r15,%xmm9,2), %xmm1 - vpgatherdd XMM10, DWORD PTR [R15 + 2*XMM9], XMM8 + mov EAX, DWORD PTR FS:[RDI] +// CHECK: leal (,%rdi,4), %r8d + lea R8D, DWORD PTR [4*RDI] +// CHECK: movl _fnan(,%ecx,4), %ecx + mov ECX, DWORD PTR [4*ECX + _fnan] +// CHECK: movq %fs:320, %rax + mov RAX, QWORD PTR FS:[320] +// CHECK: vpgatherdd %xmm8, (%r15,%xmm9,2), %xmm1 + vpgatherdd XMM10, DWORD PTR [R15 + 2*XMM9], XMM8 +// CHECK: movsd -8, %xmm5 + movsd XMM5, QWORD PTR [-8] +// CHECK: movl %ecx, (%eax) + mov [eax], ecx +// CHECK: movl %ecx, (,%ebx,4) + mov [4*ebx], ecx + // CHECK: movl %ecx, (,%ebx,4) + mov [ebx*4], ecx +// CHECK: movl %ecx, 1024 + mov [1024], ecx +// CHECK: movl %ecx, 4132 + mov [0x1024], ecx +// CHECK: movl %ecx, 32 + mov [16 + 16], ecx +// CHECK: movl %ecx, 0 + mov [16 - 16], ecx +// CHECK: movl %ecx, 32 + mov [16][16], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [eax + 4*ebx], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [eax + ebx*4], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [4*ebx + eax], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [ebx*4 + eax], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [eax][4*ebx], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [eax][ebx*4], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [4*ebx][eax], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [ebx*4][eax], ecx +// CHECK: movl %ecx, 12(%eax) + mov [eax + 12], ecx +// CHECK: movl %ecx, 12(%eax) + mov [12 + eax], ecx +// CHECK: movl %ecx, 32(%eax) + mov [eax + 16 + 16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16 + eax + 16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16 + 16 + eax], ecx +// CHECK: movl %ecx, 12(%eax) + mov [eax][12], ecx +// CHECK: movl %ecx, 12(%eax) + mov [12][eax], ecx +// CHECK: movl %ecx, 32(%eax) + mov [eax][16 + 16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [eax + 16][16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [eax][16][16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16][eax + 16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16 + eax][16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16][16 + eax], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16 + 16][eax], ecx +// CHECK: movl %ecx, 32(%eax) + mov [eax][16][16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16][eax][16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16][16][eax], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [4*ebx + 16], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [ebx*4 + 16], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [4*ebx][16], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [ebx*4][16], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [16 + 4*ebx], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [16 + ebx*4], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [16][4*ebx], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [16][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 4*ebx + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 16 + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx + eax + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx + 16 + eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][4*ebx + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][16 + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx][eax + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx][16 + eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 4*ebx][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 16][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx + eax][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx + 16][eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][4*ebx][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][16][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx][eax][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx][16][eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + ebx*4 + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 16 + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4 + eax + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4 + 16 + eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][ebx*4 + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][16 + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4][eax + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4][16 + eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + ebx*4][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 16][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4 + eax][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4 + 16][eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][ebx*4][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][16][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4][eax][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4][16][eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax][ebx*4], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax][ebx*4 - 16], ecx ret diff --git a/test/Transforms/InstCombine/fast-math.ll b/test/Transforms/InstCombine/fast-math.ll index df0455a203..88e19e343a 100644 --- a/test/Transforms/InstCombine/fast-math.ll +++ b/test/Transforms/InstCombine/fast-math.ll @@ -130,37 +130,6 @@ define double @fail2(double %f1, double %f2) { ; CHECK: ret } -; rdar://12753946: x * cond ? 1.0 : 0.0 => cond ? x : 0.0 -define double @select1(i32 %cond, double %x, double %y) { - %tobool = icmp ne i32 %cond, 0 - %cond1 = select i1 %tobool, double 1.000000e+00, double 0.000000e+00 - %mul = fmul nnan nsz double %cond1, %x - %add = fadd double %mul, %y - ret double %add -; CHECK: @select1 -; CHECK: select i1 %tobool, double %x, double 0.000000e+00 -} - -define double @select2(i32 %cond, double %x, double %y) { - %tobool = icmp ne i32 %cond, 0 - %cond1 = select i1 %tobool, double 0.000000e+00, double 1.000000e+00 - %mul = fmul nnan nsz double %cond1, %x - %add = fadd double %mul, %y - ret double %add -; CHECK: @select2 -; CHECK: select i1 %tobool, double 0.000000e+00, double %x -} - -define double @select3(i32 %cond, double %x, double %y) { - %tobool = icmp ne i32 %cond, 0 - %cond1 = select i1 %tobool, double 0.000000e+00, double 2.000000e+00 - %mul = fmul nnan nsz double %cond1, %x - %add = fadd double %mul, %y - ret double %add -; CHECK: @select3 -; CHECK: fmul nnan nsz double %cond1, %x -} - ; ========================================================================= ; ; Testing-cases about fmul begin @@ -243,6 +212,25 @@ define float @fmul5(float %f1, float %f2) { ; CHECK: fdiv fast float %f1, 0x47E8000000000000 } +; (X*Y) * X => (X*X) * Y +define float @fmul6(float %f1, float %f2) { + %mul = fmul float %f1, %f2 + %mul1 = fmul fast float %mul, %f1 + ret float %mul1 +; CHECK: @fmul6 +; CHECK: fmul fast float %f1, %f1 +} + +; "(X*Y) * X => (X*X) * Y" is disabled if "X*Y" has multiple uses +define float @fmul7(float %f1, float %f2) { + %mul = fmul float %f1, %f2 + %mul1 = fmul fast float %mul, %f1 + %add = fadd float %mul1, %mul + ret float %add +; CHECK: @fmul7 +; CHECK: fmul fast float %mul, %f1 +} + ; ========================================================================= ; ; Testing-cases about negation @@ -256,3 +244,98 @@ define float @fneg1(float %f1, float %f2) { ; CHECK: @fneg1 ; CHECK: fmul float %f1, %f2 } + +; ========================================================================= +; +; Testing-cases about div +; +; ========================================================================= + +; X/C1 / C2 => X * (1/(C2*C1)) +define float @fdiv1(float %x) { + %div = fdiv float %x, 0x3FF3333340000000 + %div1 = fdiv fast float %div, 0x4002666660000000 + ret float %div1 +; 0x3FF3333340000000 = 1.2f +; 0x4002666660000000 = 2.3f +; 0x3FD7303B60000000 = 0.36231884057971014492 +; CHECK: @fdiv1 +; CHECK: fmul fast float %x, 0x3FD7303B60000000 +} + +; X*C1 / C2 => X * (C1/C2) +define float @fdiv2(float %x) { + %mul = fmul float %x, 0x3FF3333340000000 + %div1 = fdiv fast float %mul, 0x4002666660000000 + ret float %div1 + +; 0x3FF3333340000000 = 1.2f +; 0x4002666660000000 = 2.3f +; 0x3FE0B21660000000 = 0.52173918485641479492 +; CHECK: @fdiv2 +; CHECK: fmul fast float %x, 0x3FE0B21660000000 +} + +; "X/C1 / C2 => X * (1/(C2*C1))" is disabled (for now) is C2/C1 is a denormal +; +define float @fdiv3(float %x) { + %div = fdiv float %x, 0x47EFFFFFE0000000 + %div1 = fdiv fast float %div, 0x4002666660000000 + ret float %div1 +; CHECK: @fdiv3 +; CHECK: fdiv float %x, 0x47EFFFFFE0000000 +} + +; "X*C1 / C2 => X * (C1/C2)" is disabled if C1/C2 is a denormal +define float @fdiv4(float %x) { + %mul = fmul float %x, 0x47EFFFFFE0000000 + %div = fdiv float %mul, 0x3FC99999A0000000 + ret float %div +; CHECK: @fdiv4 +; CHECK: fmul float %x, 0x47EFFFFFE0000000 +} + +; (X/Y)/Z = > X/(Y*Z) +define float @fdiv5(float %f1, float %f2, float %f3) { + %t1 = fdiv float %f1, %f2 + %t2 = fdiv fast float %t1, %f3 + ret float %t2 +; CHECK: @fdiv5 +; CHECK: fmul float %f2, %f3 +} + +; Z/(X/Y) = > (Z*Y)/X +define float @fdiv6(float %f1, float %f2, float %f3) { + %t1 = fdiv float %f1, %f2 + %t2 = fdiv fast float %f3, %t1 + ret float %t2 +; CHECK: @fdiv6 +; CHECK: fmul float %f3, %f2 +} + +; C1/(X*C2) => (C1/C2) / X +define float @fdiv7(float %x) { + %t1 = fmul float %x, 3.0e0 + %t2 = fdiv fast float 15.0e0, %t1 + ret float %t2 +; CHECK: @fdiv7 +; CHECK: fdiv fast float 5.000000e+00, %x +} + +; C1/(X/C2) => (C1*C2) / X +define float @fdiv8(float %x) { + %t1 = fdiv float %x, 3.0e0 + %t2 = fdiv fast float 15.0e0, %t1 + ret float %t2 +; CHECK: @fdiv8 +; CHECK: fdiv fast float 4.500000e+01, %x +} + +; C1/(C2/X) => (C1/C2) * X +define float @fdiv9(float %x) { + %t1 = fdiv float 3.0e0, %x + %t2 = fdiv fast float 15.0e0, %t1 + ret float %t2 +; CHECK: @fdiv9 +; CHECK: fmul fast float %x, 5.000000e+00 +} diff --git a/test/Transforms/InstCombine/fmul.ll b/test/Transforms/InstCombine/fmul.ll new file mode 100644 index 0000000000..3671b4c699 --- /dev/null +++ b/test/Transforms/InstCombine/fmul.ll @@ -0,0 +1,72 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +; (-0.0 - X) * C => X * -C +define float @test1(float %x) { + %sub = fsub float -0.000000e+00, %x + %mul = fmul float %sub, 2.0e+1 + ret float %mul + +; CHECK: @test1 +; CHECK: fmul float %x, -2.000000e+01 +} + +; (0.0 - X) * C => X * -C +define float @test2(float %x) { + %sub = fsub nsz float 0.000000e+00, %x + %mul = fmul float %sub, 2.0e+1 + ret float %mul + +; CHECK: @test2 +; CHECK: fmul float %x, -2.000000e+01 +} + +; (-0.0 - X) * (-0.0 - Y) => X * Y +define float @test3(float %x, float %y) { + %sub1 = fsub float -0.000000e+00, %x + %sub2 = fsub float -0.000000e+00, %y + %mul = fmul float %sub1, %sub2 + ret float %mul +; CHECK: @test3 +; CHECK: fmul float %x, %y +} + +; (0.0 - X) * (0.0 - Y) => X * Y +define float @test4(float %x, float %y) { + %sub1 = fsub nsz float 0.000000e+00, %x + %sub2 = fsub nsz float 0.000000e+00, %y + %mul = fmul float %sub1, %sub2 + ret float %mul +; CHECK: @test4 +; CHECK: fmul float %x, %y +} + +; (-0.0 - X) * Y => -0.0 - (X * Y) +define float @test5(float %x, float %y) { + %sub1 = fsub float -0.000000e+00, %x + %mul = fmul float %sub1, %y + ret float %mul +; CHECK: @test5 +; CHECK: %1 = fmul float %x, %y +; CHECK: %mul = fsub float -0.000000e+00, %1 +} + +; (0.0 - X) * Y => 0.0 - (X * Y) +define float @test6(float %x, float %y) { + %sub1 = fsub nsz float 0.000000e+00, %x + %mul = fmul float %sub1, %y + ret float %mul +; CHECK: @test6 +; CHECK: %1 = fmul float %x, %y +; CHECK: %mul = fsub float -0.000000e+00, %1 +} + +; "(-0.0 - X) * Y => -0.0 - (X * Y)" is disabled if expression "-0.0 - X" +; has multiple uses. +define float @test7(float %x, float %y) { + %sub1 = fsub float -0.000000e+00, %x + %mul = fmul float %sub1, %y + %mul2 = fmul float %mul, %sub1 + ret float %mul2 +; CHECK: @test7 +; CHECK: fsub float -0.000000e+00, %x +} diff --git a/test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll b/test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll new file mode 100644 index 0000000000..8fbddf8ae4 --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll @@ -0,0 +1,84 @@ +; RUN: opt -loop-reduce -S < %s | FileCheck %s +; +; LTO of clang, which mistakenly uses no TargetLoweringInfo, causes a +; miscompile. ReuseOrCreateCast replace ptrtoint operand with undef. +; Reproducing the miscompile requires no triple, hence no "TTI". +; rdar://13007381 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +; Verify that nothing uses the "dead" ptrtoint from "undef". +; CHECK: @VerifyDiagnosticConsumerTest +; CHECK: bb: +; CHECK: %0 = ptrtoint i8* undef to i64 +; CHECK-NOT: %0 +; CHECK: .lr.ph +; CHECK-NOT: %0 +; CHECK: sub i64 %7, %tmp6 +; CHECK-NOT: %0 +; CHECK: ret void +define void @VerifyDiagnosticConsumerTest() unnamed_addr nounwind uwtable align 2 { +bb: + %tmp3 = call i8* @getCharData() nounwind + %tmp4 = call i8* @getCharData() nounwind + %tmp5 = ptrtoint i8* %tmp4 to i64 + %tmp6 = ptrtoint i8* %tmp3 to i64 + %tmp7 = sub i64 %tmp5, %tmp6 + br i1 undef, label %bb87, label %.preheader + +.preheader: ; preds = %bb10, %bb + br i1 undef, label %_ZNK4llvm9StringRef4findEcm.exit42.thread, label %bb10 + +bb10: ; preds = %.preheader + br i1 undef, label %_ZNK4llvm9StringRef4findEcm.exit42, label %.preheader + +_ZNK4llvm9StringRef4findEcm.exit42: ; preds = %bb10 + br i1 undef, label %_ZNK4llvm9StringRef4findEcm.exit42.thread, label %.lr.ph + +_ZNK4llvm9StringRef4findEcm.exit42.thread: ; preds = %_ZNK4llvm9StringRef4findEcm.exit42, %.preheader + unreachable + +.lr.ph: ; preds = %_ZNK4llvm9StringRef4findEcm.exit42 + br label %bb36 + +_ZNK4llvm9StringRef4findEcm.exit.loopexit: ; preds = %bb63 + %tmp21 = icmp eq i64 %i.0.i, -1 + br i1 %tmp21, label %_ZNK4llvm9StringRef4findEcm.exit._crit_edge, label %bb36 + +_ZNK4llvm9StringRef4findEcm.exit._crit_edge: ; preds = %bb61, %_ZNK4llvm9StringRef4findEcm.exit.loopexit + unreachable + +bb36: ; preds = %_ZNK4llvm9StringRef4findEcm.exit.loopexit, %.lr.ph + %loc.063 = phi i64 [ undef, %.lr.ph ], [ %i.0.i, %_ZNK4llvm9StringRef4findEcm.exit.loopexit ] + switch i8 undef, label %bb57 [ + i8 10, label %bb48 + i8 13, label %bb48 + ] + +bb48: ; preds = %bb36, %bb36 + br label %bb58 + +bb57: ; preds = %bb36 + br label %bb58 + +bb58: ; preds = %bb57, %bb48 + %tmp59 = icmp ugt i64 %tmp7, undef + %tmp60 = select i1 %tmp59, i64 undef, i64 %tmp7 + br label %bb61 + +bb61: ; preds = %bb63, %bb58 + %i.0.i = phi i64 [ %tmp60, %bb58 ], [ %tmp67, %bb63 ] + %tmp62 = icmp eq i64 %i.0.i, %tmp7 + br i1 %tmp62, label %_ZNK4llvm9StringRef4findEcm.exit._crit_edge, label %bb63 + +bb63: ; preds = %bb61 + %tmp64 = getelementptr inbounds i8* %tmp3, i64 %i.0.i + %tmp65 = load i8* %tmp64, align 1 + %tmp67 = add i64 %i.0.i, 1 + br i1 undef, label %_ZNK4llvm9StringRef4findEcm.exit.loopexit, label %bb61 + +bb87: ; preds = %bb + ret void +} + +declare i8* @getCharData() diff --git a/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll b/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll index 9e02d92a6f..449dc16d50 100644 --- a/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll +++ b/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll @@ -4,12 +4,12 @@ ; LSR should properly handle the post-inc offset when folding the ; non-IV operand of an icmp into the IV. -; CHECK: %3 = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast -; CHECK: %4 = lshr i64 %3, 1 -; CHECK: %5 = mul i64 %4, 2 +; CHECK: [[r1:%[a-z0-9]+]] = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast +; CHECK: [[r2:%[a-z0-9]+]] = lshr i64 [[r1]], 1 +; CHECK: [[r3:%[a-z0-9]+]] = mul i64 [[r2]], 2 ; CHECK: br label %for.body ; CHECK: for.body: -; CHECK: %lsr.iv2 = phi i64 [ %lsr.iv.next, %for.body ], [ %5, %for.body.lr.ph ] +; CHECK: %lsr.iv2 = phi i64 [ %lsr.iv.next, %for.body ], [ [[r3]], %for.body.lr.ph ] ; CHECK: %lsr.iv.next = add i64 %lsr.iv2, -2 ; CHECK: %lsr.iv.next3 = inttoptr i64 %lsr.iv.next to i16* ; CHECK: %cmp27 = icmp eq i16* %lsr.iv.next3, null diff --git a/test/Verifier/module-flags-1.ll b/test/Verifier/module-flags-1.ll new file mode 100644 index 0000000000..94e9817115 --- /dev/null +++ b/test/Verifier/module-flags-1.ll @@ -0,0 +1,51 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s + +; Check that module flags are structurally correct. +; +; CHECK: incorrect number of operands in module flag +; CHECK: metadata !0 +!0 = metadata !{ i32 1 } +; CHECK: invalid behavior operand in module flag (expected constant integer) +; CHECK: metadata !"foo" +!1 = metadata !{ metadata !"foo", metadata !"foo", i32 42 } +; CHECK: invalid behavior operand in module flag (unexpected constant) +; CHECK: i32 999 +!2 = metadata !{ i32 999, metadata !"foo", i32 43 } +; CHECK: invalid ID operand in module flag (expected metadata string) +; CHECK: i32 1 +!3 = metadata !{ i32 1, i32 1, i32 44 } +; CHECK: invalid value for 'require' module flag (expected metadata pair) +; CHECK: i32 45 +!4 = metadata !{ i32 3, metadata !"bla", i32 45 } +; CHECK: invalid value for 'require' module flag (expected metadata pair) +; CHECK: metadata ! +!5 = metadata !{ i32 3, metadata !"bla", metadata !{ i32 46 } } +; CHECK: invalid value for 'require' module flag (first value operand should be a string) +; CHECK: i32 47 +!6 = metadata !{ i32 3, metadata !"bla", metadata !{ i32 47, i32 48 } } + +; Check that module flags only have unique IDs. +; +; CHECK: module flag identifiers must be unique (or of 'require' type) +!7 = metadata !{ i32 1, metadata !"foo", i32 49 } +!8 = metadata !{ i32 2, metadata !"foo", i32 50 } +; CHECK-NOT: module flag identifiers must be unique +!9 = metadata !{ i32 2, metadata !"bar", i32 51 } +!10 = metadata !{ i32 3, metadata !"bar", metadata !{ metadata !"bar", i32 51 } } + +; Check that any 'require' module flags are valid. +; CHECK: invalid requirement on flag, flag is not present in module +!11 = metadata !{ i32 3, metadata !"bar", + metadata !{ metadata !"no-such-flag", i32 52 } } +; CHECK: invalid requirement on flag, flag does not have the required value +!12 = metadata !{ i32 1, metadata !"flag-0", i32 53 } +!13 = metadata !{ i32 3, metadata !"bar", + metadata !{ metadata !"flag-0", i32 54 } } +; CHECK-NOT: invalid requirement on flag, flag is not present in module +; CHECK-NOT: invalid requirement on flag, flag does not have the required value +!14 = metadata !{ i32 1, metadata !"flag-1", i32 55 } +!15 = metadata !{ i32 3, metadata !"bar", + metadata !{ metadata !"flag-1", i32 55 } } + +!llvm.module.flags = !{ + !0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15 } diff --git a/tools/llvm-objdump/ELFDump.cpp b/tools/llvm-objdump/ELFDump.cpp index a635fefc3b..b96d5ba11a 100644 --- a/tools/llvm-objdump/ELFDump.cpp +++ b/tools/llvm-objdump/ELFDump.cpp @@ -22,10 +22,10 @@ using namespace llvm; using namespace llvm::object; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> void printProgramHeaders( - const ELFObjectFile<target_endianness, max_alignment, is64Bits> *o) { - typedef ELFObjectFile<target_endianness, max_alignment, is64Bits> ELFO; + const ELFObjectFile<ELFT> *o) { + typedef ELFObjectFile<ELFT> ELFO; outs() << "Program Header:\n"; for (typename ELFO::Elf_Phdr_Iter pi = o->begin_program_headers(), pe = o->end_program_headers(); @@ -44,7 +44,7 @@ void printProgramHeaders( outs() << " UNKNOWN "; } - const char *Fmt = is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " "; + const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " "; outs() << "off " << format(Fmt, (uint64_t)pi->p_offset) @@ -68,22 +68,22 @@ void printProgramHeaders( void llvm::printELFFileHeader(const object::ObjectFile *Obj) { // Little-endian 32-bit - if (const ELFObjectFile<support::little, 4, false> *ELFObj = - dyn_cast<ELFObjectFile<support::little, 4, false> >(Obj)) + if (const ELFObjectFile<ELFType<support::little, 4, false> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::little, 4, false> > >(Obj)) printProgramHeaders(ELFObj); // Big-endian 32-bit - if (const ELFObjectFile<support::big, 4, false> *ELFObj = - dyn_cast<ELFObjectFile<support::big, 4, false> >(Obj)) + if (const ELFObjectFile<ELFType<support::big, 4, false> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::big, 4, false> > >(Obj)) printProgramHeaders(ELFObj); // Little-endian 64-bit - if (const ELFObjectFile<support::little, 8, true> *ELFObj = - dyn_cast<ELFObjectFile<support::little, 8, true> >(Obj)) + if (const ELFObjectFile<ELFType<support::little, 8, true> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::little, 8, true> > >(Obj)) printProgramHeaders(ELFObj); // Big-endian 64-bit - if (const ELFObjectFile<support::big, 8, true> *ELFObj = - dyn_cast<ELFObjectFile<support::big, 8, true> >(Obj)) + if (const ELFObjectFile<ELFType<support::big, 8, true> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::big, 8, true> > >(Obj)) printProgramHeaders(ELFObj); } diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index e4e4c4d6f7..7b89f81aa4 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -535,6 +535,7 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule); codeGenPasses->add(new DataLayout(*_target->getDataLayout())); + _target->addAnalysisPasses(*codeGenPasses); formatted_raw_ostream Out(out); diff --git a/unittests/IR/WaymarkTest.cpp b/unittests/IR/WaymarkTest.cpp index 69fc4da5a6..0fe0a431b2 100644 --- a/unittests/IR/WaymarkTest.cpp +++ b/unittests/IR/WaymarkTest.cpp @@ -44,9 +44,9 @@ TEST(WaymarkTest, TwoBit) { Use* many = (Use*)calloc(sizeof(Use), 8212 + 1); ASSERT_TRUE(many); Use::initTags(many, many + 8212); - for (const Use *U = many, *Ue = many + 8212 - 1; U != Ue; ++U) + for (Use *U = many, *Ue = many + 8212 - 1; U != Ue; ++U) { - EXPECT_EQ((User*)(Ue + 1), U->getUser()); + EXPECT_EQ(reinterpret_cast<User *>(Ue + 1), U->getUser()); } } diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index a4b0694bc0..6d62d6b1ff 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -1727,7 +1727,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, << " default: llvm_unreachable(\"invalid conversion entry!\");\n" << " case CVT_Reg:\n" << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n" - << " Operands[*(p + 1)]->setConstraint(\"m\");\n" + << " Operands[*(p + 1)]->setConstraint(\"r\");\n" << " ++NumMCOperands;\n" << " break;\n" << " case CVT_Tied:\n" @@ -1830,9 +1830,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Add a handler for the operand number lookup. OpOS << " case " << Name << ":\n" - << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n" - << " Operands[*(p + 1)]->setConstraint(\"m\");\n" - << " NumMCOperands += " << OpInfo.MINumOperands << ";\n" + << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"; + + if (Op.Class->isRegisterClass()) + OpOS << " Operands[*(p + 1)]->setConstraint(\"r\");\n"; + else + OpOS << " Operands[*(p + 1)]->setConstraint(\"m\");\n"; + OpOS << " NumMCOperands += " << OpInfo.MINumOperands << ";\n" << " break;\n"; break; } diff --git a/utils/testgen/mc-bundling-x86-gen.py b/utils/testgen/mc-bundling-x86-gen.py index 832e841602..5c1c6c4562 100644 --- a/utils/testgen/mc-bundling-x86-gen.py +++ b/utils/testgen/mc-bundling-x86-gen.py @@ -1,3 +1,4 @@ + #!/usr/bin/python # Auto-generates an exhaustive and repetitive test for correct bundle-locked @@ -40,7 +41,7 @@ def print_bundle_locked_sequence(len, align_to_end=False): def generate(align_to_end=False): print(PREAMBLE) - + ntest = 0 for instlen in range(1, BUNDLE_SIZE + 1): for offset in range(0, BUNDLE_SIZE): @@ -56,13 +57,15 @@ def generate(align_to_end=False): base_offset = ntest * 2 * BUNDLE_SIZE inst_orig_offset = base_offset + offset # had it not been padded... - def print_check(adjusted_offset=None): + def print_check(adjusted_offset=None, nop_split_offset=None): if adjusted_offset is not None: print('# CHECK: {0:x}: nop'.format(inst_orig_offset)) + if nop_split_offset is not None: + print('# CHECK: {0:x}: nop'.format(nop_split_offset)) print('# CHECK: {0:x}: incl'.format(adjusted_offset)) else: print('# CHECK: {0:x}: incl'.format(inst_orig_offset)) - + if align_to_end: if offset + instlen == BUNDLE_SIZE: # No padding needed @@ -72,9 +75,13 @@ def generate(align_to_end=False): offset_to_end = base_offset + (BUNDLE_SIZE - instlen) print_check(offset_to_end) else: # offset + instlen > BUNDLE_SIZE - # Pad to end at next bundle boundary + # Pad to end at next bundle boundary, splitting the nop sequence + # at the nearest bundle boundary + offset_to_nearest_bundle = base_offset + BUNDLE_SIZE offset_to_end = base_offset + (BUNDLE_SIZE * 2 - instlen) - print_check(offset_to_end) + if offset_to_nearest_bundle == offset_to_end: + offset_to_nearest_bundle = None + print_check(offset_to_end, offset_to_nearest_bundle) else: if offset + instlen > BUNDLE_SIZE: # Padding needed @@ -94,5 +101,3 @@ if __name__ == '__main__': help='generate .bundle_lock with align_to_end option') args = argparser.parse_args() generate(align_to_end=args.align_to_end) - - |