aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2013-01-31 10:07:41 -0800
committerDerek Schuff <dschuff@chromium.org>2013-01-31 10:07:41 -0800
commit3d5de9e56f3e5af59772bdf2cbedb0903d938bb8 (patch)
tree300b7a72c61b009f0122ec1d8a155672c74459fd
parent659ebb8c18832df528effd5c970bfde7662ea368 (diff)
parent9ccb76998f741a7d3f0f217392a783dfb99c6e87 (diff)
Cherry-pick r174067
-rw-r--r--CODE_OWNERS.TXT4
-rw-r--r--autoconf/configure.ac19
-rwxr-xr-xconfigure14
-rw-r--r--docs/LangRef.rst49
-rw-r--r--include/llvm/ADT/StringMap.h4
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpander.h4
-rw-r--r--include/llvm/IR/Instructions.h2
-rw-r--r--include/llvm/MC/MCAssembler.h105
-rw-r--r--include/llvm/MC/MCParser/MCAsmParser.h44
-rw-r--r--include/llvm/Object/ELF.h908
-rw-r--r--include/llvm/Object/MachOFormat.h5
-rw-r--r--include/llvm/Support/Compiler.h6
-rw-r--r--lib/Analysis/ScalarEvolutionExpander.cpp5
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp20
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp3
-rw-r--r--lib/ExecutionEngine/JIT/JITMemoryManager.cpp11
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp82
-rw-r--r--lib/IR/Instructions.cpp6
-rw-r--r--lib/IR/Use.cpp2
-rw-r--r--lib/IR/Verifier.cpp85
-rw-r--r--lib/Linker/LinkModules.cpp11
-rw-r--r--lib/MC/MCAssembler.cpp58
-rw-r--r--lib/MC/MCELFStreamer.cpp14
-rw-r--r--lib/MC/MCParser/AsmParser.cpp1731
-rw-r--r--lib/Object/ELFObjectFile.cpp16
-rw-r--r--lib/Object/MachOObject.cpp3
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp34
-rw-r--r--lib/Target/Hexagon/HexagonISelLowering.cpp4
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp8
-rw-r--r--lib/Target/Mips/MipsCodeEmitter.cpp9
-rw-r--r--lib/Target/X86/AsmParser/X86AsmParser.cpp363
-rw-r--r--lib/Transforms/InstCombine/InstCombine.h50
-rw-r--r--lib/Transforms/InstCombine/InstCombineAddSub.cpp4
-rw-r--r--lib/Transforms/InstCombine/InstCombineCasts.cpp2
-rw-r--r--lib/Transforms/InstCombine/InstCombineMulDivRem.cpp226
-rw-r--r--lib/Transforms/InstCombine/InstCombineWorklist.h30
-rw-r--r--lib/Transforms/Instrumentation/MemorySanitizer.cpp15
-rw-r--r--lib/Transforms/Utils/BasicBlockUtils.cpp76
-rw-r--r--lib/Transforms/Vectorize/LoopVectorize.cpp2
-rw-r--r--test/CodeGen/PowerPC/load-shift-combine.ll34
-rw-r--r--test/Instrumentation/MemorySanitizer/msan_basic.ll16
-rw-r--r--test/MC/Mips/elf-gprel-32-64.ll37
-rw-r--r--test/MC/X86/AlignedBundling/autogen-inst-offset-align-to-end.s105
-rw-r--r--test/MC/X86/intel-syntax.s200
-rw-r--r--test/Transforms/InstCombine/fast-math.ll145
-rw-r--r--test/Transforms/InstCombine/fmul.ll72
-rw-r--r--test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll84
-rw-r--r--test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll8
-rw-r--r--test/Verifier/module-flags-1.ll51
-rw-r--r--tools/llvm-objdump/ELFDump.cpp24
-rw-r--r--tools/lto/LTOCodeGenerator.cpp1
-rw-r--r--unittests/IR/WaymarkTest.cpp4
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp12
-rw-r--r--utils/testgen/mc-bundling-x86-gen.py19
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=
diff --git a/configure b/configure
index 4a2e36ca40..c3c1e06112 100755
--- a/configure
+++ b/configure
@@ -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)
-
-