diff options
473 files changed, 11300 insertions, 9062 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7063640..216e0f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -304,6 +304,7 @@ add_subdirectory(lib/Linker) add_subdirectory(lib/Analysis) add_subdirectory(lib/Analysis/IPA) add_subdirectory(lib/MC) +add_subdirectory(lib/MC/MCParser) add_subdirectory(test) add_subdirectory(utils/FileCheck) @@ -66,7 +66,8 @@ ifeq ($(MAKECMDGOALS),tools-only) endif ifeq ($(MAKECMDGOALS),install-clang) - DIRS := tools/clang/tools/driver tools/clang/lib/Headers tools/clang/docs + DIRS := tools/clang/tools/driver tools/clang/lib/Headers \ + tools/clang/lib/Runtime tools/clang/docs OPTIONAL_DIRS := NO_INSTALL = 1 endif diff --git a/Makefile.rules b/Makefile.rules index 49ecb1e..3d436c4 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -439,6 +439,17 @@ else endif endif +ifeq ($(HOST_OS),MingW) + # Work around PR4957 + CPP.Defines += -D__NO_CTYPE_INLINE + ifeq ($(LLVM_CROSS_COMPILING),1) + # Work around http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=525016 + ifdef TOOLNAME + LD.Flags += -Wl,--allow-multiple-definition + endif + endif +endif + CXX.Flags += -Woverloaded-virtual CPP.BaseFlags += $(CPP.Defines) AR.Flags := cru @@ -457,15 +468,6 @@ ifeq ($(ARCH),Alpha) LD.Flags += -Wl,--no-relax endif -ifeq ($(HOST_OS),MingW) - ifeq ($(LLVM_CROSS_COMPILING),1) - # Work around http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=525016 - ifdef TOOLNAME - LD.Flags += -Wl,--allow-multiple-definition - endif - endif -endif - ifdef ENABLE_EXPENSIVE_CHECKS # GNU libstdc++ uses RTTI if you define _GLIBCXX_DEBUG, which we did above. # See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40160 @@ -1351,17 +1353,17 @@ DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.d.tmp" \ DEPEND_MOVEFILE = then $(MV) -f "$(ObjDir)/$*.d.tmp" "$(ObjDir)/$*.d"; \ else $(RM) "$(ObjDir)/$*.d.tmp"; exit 1; fi -$(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_SRC_DIR)/Makefile $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ $(DEPEND_MOVEFILE) -$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_SRC_DIR)/Makefile $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ $(DEPEND_MOVEFILE) -$(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_SRC_DIR)/Makefile $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) $(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ $(DEPEND_MOVEFILE) diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml index 37d0fd7..25e47ab 100644 --- a/bindings/ocaml/llvm/llvm.ml +++ b/bindings/ocaml/llvm/llvm.ml @@ -93,7 +93,6 @@ module Attribute = struct | Noredzone | Noimplicitfloat | Naked - | Inlinehint end module Icmp = struct @@ -848,7 +847,7 @@ module ModuleProvider = struct = "LLVMCreateModuleProviderForExistingModule" external dispose : llmoduleprovider -> unit = "llvm_dispose_module_provider" end - + (*===-- Memory buffers ----------------------------------------------------===*) diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli index a7c2bcf..c703ef7 100644 --- a/bindings/ocaml/llvm/llvm.mli +++ b/bindings/ocaml/llvm/llvm.mli @@ -143,7 +143,6 @@ module Attribute : sig | Noredzone | Noimplicitfloat | Naked - | Inlinehint end (** The predicate for an integer comparison ([icmp]) instruction. diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c index 8868d07..6cc475d 100644 --- a/bindings/ocaml/llvm/llvm_ocaml.c +++ b/bindings/ocaml/llvm/llvm_ocaml.c @@ -112,9 +112,9 @@ CAMLprim LLVMContextRef llvm_global_context(value Unit) { /*===-- Modules -----------------------------------------------------------===*/ -/* string -> llmodule */ -CAMLprim LLVMModuleRef llvm_create_module(value ModuleID) { - return LLVMModuleCreateWithName(String_val(ModuleID)); +/* llcontext -> string -> llmodule */ +CAMLprim LLVMModuleRef llvm_create_module(LLVMContextRef C, value ModuleID) { + return LLVMModuleCreateWithNameInContext(String_val(ModuleID), C); } /* llmodule -> unit */ diff --git a/cmake/modules/LLVMLibDeps.cmake b/cmake/modules/LLVMLibDeps.cmake index bc2f45b..e1c470f 100644 --- a/cmake/modules/LLVMLibDeps.cmake +++ b/cmake/modules/LLVMLibDeps.cmake @@ -1,4 +1,4 @@ -set(MSVC_LIB_DEPS_LLVMARMAsmParser LLVMARMInfo LLVMMC) +set(MSVC_LIB_DEPS_LLVMARMAsmParser LLVMARMInfo LLVMMCParser LLVMSupport) set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMARMCodeGen LLVMARMInfo LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget) set(MSVC_LIB_DEPS_LLVMARMCodeGen LLVMARMInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget) set(MSVC_LIB_DEPS_LLVMARMInfo LLVMSupport) @@ -14,7 +14,7 @@ set(MSVC_LIB_DEPS_LLVMBitWriter LLVMCore LLVMSupport LLVMSystem) set(MSVC_LIB_DEPS_LLVMBlackfinAsmPrinter LLVMAsmPrinter LLVMBlackfinInfo LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget) set(MSVC_LIB_DEPS_LLVMBlackfinCodeGen LLVMBlackfinInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget) set(MSVC_LIB_DEPS_LLVMBlackfinInfo LLVMSupport) -set(MSVC_LIB_DEPS_LLVMCBackend LLVMAnalysis LLVMCBackendInfo LLVMCodeGen LLVMCore LLVMScalarOpts LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils LLVMipa) +set(MSVC_LIB_DEPS_LLVMCBackend LLVMAnalysis LLVMCBackendInfo LLVMCodeGen LLVMCore LLVMMC LLVMScalarOpts LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils LLVMipa) set(MSVC_LIB_DEPS_LLVMCBackendInfo LLVMSupport) set(MSVC_LIB_DEPS_LLVMCellSPUAsmPrinter LLVMAsmPrinter LLVMCellSPUInfo LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget) set(MSVC_LIB_DEPS_LLVMCellSPUCodeGen LLVMCellSPUInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget) @@ -27,9 +27,10 @@ set(MSVC_LIB_DEPS_LLVMExecutionEngine LLVMCore LLVMSupport LLVMSystem LLVMTarget set(MSVC_LIB_DEPS_LLVMInstCombine LLVMAnalysis LLVMCore LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils) set(MSVC_LIB_DEPS_LLVMInstrumentation LLVMAnalysis LLVMCore LLVMSupport LLVMSystem LLVMTransformUtils) set(MSVC_LIB_DEPS_LLVMInterpreter LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMSupport LLVMSystem LLVMTarget) -set(MSVC_LIB_DEPS_LLVMJIT LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMMC LLVMSupport LLVMSystem LLVMTarget) +set(MSVC_LIB_DEPS_LLVMJIT LLVMAnalysis LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMMC LLVMSupport LLVMSystem LLVMTarget) set(MSVC_LIB_DEPS_LLVMLinker LLVMArchive LLVMBitReader LLVMCore LLVMSupport LLVMSystem) set(MSVC_LIB_DEPS_LLVMMC LLVMSupport LLVMSystem) +set(MSVC_LIB_DEPS_LLVMMCParser LLVMMC LLVMSupport) set(MSVC_LIB_DEPS_LLVMMSIL LLVMAnalysis LLVMCodeGen LLVMCore LLVMMSILInfo LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils LLVMipa) set(MSVC_LIB_DEPS_LLVMMSILInfo LLVMSupport) set(MSVC_LIB_DEPS_LLVMMSP430AsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMSP430Info LLVMSupport LLVMSystem LLVMTarget) @@ -56,8 +57,8 @@ set(MSVC_LIB_DEPS_LLVMSystemZCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDA set(MSVC_LIB_DEPS_LLVMSystemZInfo LLVMSupport) set(MSVC_LIB_DEPS_LLVMTarget LLVMCore LLVMMC LLVMSupport) set(MSVC_LIB_DEPS_LLVMTransformUtils LLVMAnalysis LLVMCore LLVMSupport LLVMSystem LLVMTarget LLVMipa) -set(MSVC_LIB_DEPS_LLVMX86AsmParser LLVMMC LLVMX86Info) -set(MSVC_LIB_DEPS_LLVMX86AsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget LLVMX86CodeGen LLVMX86Info) +set(MSVC_LIB_DEPS_LLVMX86AsmParser LLVMMC LLVMMCParser LLVMSupport LLVMX86Info) +set(MSVC_LIB_DEPS_LLVMX86AsmPrinter LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget LLVMX86CodeGen LLVMX86Info) set(MSVC_LIB_DEPS_LLVMX86CodeGen LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget LLVMX86Info) set(MSVC_LIB_DEPS_LLVMX86Disassembler LLVMMC LLVMSupport LLVMX86Info) set(MSVC_LIB_DEPS_LLVMX86Info LLVMSupport) diff --git a/docs/BitCodeFormat.html b/docs/BitCodeFormat.html index 7a46d90..7413752 100644 --- a/docs/BitCodeFormat.html +++ b/docs/BitCodeFormat.html @@ -138,8 +138,7 @@ bitcode, while application-specific programs will want to look at all four.</p> A bitstream literally consists of a stream of bits, which are read in order starting with the least significant bit of each byte. The stream is made up of a number of primitive values that encode a stream of unsigned integer values. -These -integers are are encoded in two ways: either as <a href="#fixedwidth">Fixed +These integers are encoded in two ways: either as <a href="#fixedwidth">Fixed Width Integers</a> or as <a href="#variablewidth">Variable Width Integers</a>. </p> @@ -1158,7 +1157,7 @@ fields of <tt>FUNCTION</tt> records.</p> src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a> <a href="mailto:sabre@nondot.org">Chris Lattner</a><br> <a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br> -Last modified: $Date: 2009-10-29 05:25:46 +0100 (Thu, 29 Oct 2009) $ +Last modified: $Date: 2010-01-20 18:53:51 +0100 (Wed, 20 Jan 2010) $ </address> </body> </html> diff --git a/docs/LangRef.html b/docs/LangRef.html index 6ea0ead..cbb7d56 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -924,9 +924,9 @@ define [<a href="#linkage">linkage</a>] [<a href="#visibility">visibility</a>] <div class="doc_text"> -<p>Named metadata is a collection of metadata. <a href="#metadata"> Metadata </a> - node and null are the only valid named metadata operands. - Metadata strings are not allowed as an named metadata operand.</p> +<p>Named metadata is a collection of metadata. <a href="#metadata">Metadata + nodes</a> (but not metadata strings) and null are the only valid operands for + a named metadata.</p> <h5>Syntax:</h5> <div class="doc_code"> @@ -1083,11 +1083,6 @@ define void @f() optsize { ... } function into callers whenever possible, ignoring any active inlining size threshold for this caller.</dd> - <dt><tt><b>inlinehint</b></tt></dt> - <dd>This attribute indicates that the source code contained a hint that inlining - this function is desirable (such as the "inline" keyword in C/C++). It - is just a hint; it imposes no requirements on the inliner.</dd> - <dt><tt><b>noinline</b></tt></dt> <dd>This attribute indicates that the inliner should never inline this function in any situation. This attribute may not be used together with @@ -2340,41 +2335,6 @@ has undefined behavior.</p> </div> -<!-- ======================================================================= --> -<div class="doc_subsection"><a name="metadata">Metadata Nodes and Metadata Strings</a> -</div> - -<div class="doc_text"> - -<p>Metadata provides a way to attach arbitrary data to the instruction - stream without affecting the behaviour of the program. There are two - metadata primitives, strings and nodes. All metadata has the - <tt>metadata</tt> type and is identified in syntax by a preceding exclamation - point ('<tt>!</tt>').</p> - -<p>A metadata string is a string surrounded by double quotes. It can contain - any character by escaping non-printable characters with "\xx" where "xx" is - the two digit hex code. For example: "<tt>!"test\00"</tt>".</p> - -<p>Metadata nodes are represented with notation similar to structure constants - (a comma separated list of elements, surrounded by braces and preceded by an - exclamation point). For example: "<tt>!{ metadata !"test\00", i32 - 10}</tt>".</p> - -<p>A metadata node will attempt to track changes to the values it holds. In the - event that a value is deleted, it will be replaced with a typeless - "<tt>null</tt>", such as "<tt>metadata !{null, i32 10}</tt>".</p> - -<p>A <a href="#namedmetadatastructure">named metadata</a> is a collection of - metadata nodes. For example: "<tt>!foo = metadata !{!4, !3}</tt>". - -<p>Optimizations may rely on metadata to provide additional information about - the program that isn't available in the instructions, or that isn't easily - computable. Similarly, the code generator may expect a certain metadata - format to be used to express debugging information.</p> - -</div> - <!-- *********************************************************************** --> <div class="doc_section"> <a name="othervalues">Other Values</a> </div> <!-- *********************************************************************** --> @@ -2444,6 +2404,35 @@ call void asm alignstack "eieio", ""() </div> +<!-- ======================================================================= --> +<div class="doc_subsection"><a name="metadata">Metadata Nodes and Metadata + Strings</a> +</div> + +<div class="doc_text"> + +<p>LLVM IR allows metadata to be attached to instructions in the program that + can convey extra information about the code to the optimizers and code + generator. One example application of metadata is source-level debug + information. There are two metadata primitives: strings and nodes. All + metadata has the <tt>metadata</tt> type and is identified in syntax by a + preceding exclamation point ('<tt>!</tt>').</p> + +<p>A metadata string is a string surrounded by double quotes. It can contain + any character by escaping non-printable characters with "\xx" where "xx" is + the two digit hex code. For example: "<tt>!"test\00"</tt>".</p> + +<p>Metadata nodes are represented with notation similar to structure constants + (a comma separated list of elements, surrounded by braces and preceded by an + exclamation point). For example: "<tt>!{ metadata !"test\00", i32 + 10}</tt>". Metadata nodes can have any values as their operand.</p> + +<p>A <a href="#namedmetadatastructure">named metadata</a> is a collection of + metadata nodes, which can be looked up in the module symbol table. For + example: "<tt>!foo = metadata !{!4, !3}</tt>". + +</div> + <!-- *********************************************************************** --> <div class="doc_section"> @@ -2840,6 +2829,9 @@ IfUnequal: block to the "normal" label. If the callee unwinds then no return value is available.</p> +<p>Note that the code generator does not yet completely support unwind, and +that the invoke/unwind semantics are likely to change in future versions.</p> + <h5>Example:</h5> <pre> %retval = invoke i32 @Test(i32 15) to label %Continue @@ -2876,6 +2868,9 @@ Instruction</a> </div> specified by the <tt>invoke</tt> instruction. If there is no <tt>invoke</tt> instruction in the dynamic call chain, undefined behavior results.</p> +<p>Note that the code generator does not yet completely support unwind, and +that the invoke/unwind semantics are likely to change in future versions.</p> + </div> <!-- _______________________________________________________________________ --> @@ -7350,7 +7345,7 @@ LLVM</a>.</p> <a href="mailto:sabre@nondot.org">Chris Lattner</a><br> <a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br> - Last modified: $Date: 2010-01-11 20:35:55 +0100 (Mon, 11 Jan 2010) $ + Last modified: $Date: 2010-01-15 22:50:19 +0100 (Fri, 15 Jan 2010) $ </address> </body> diff --git a/docs/ReleaseNotes.html b/docs/ReleaseNotes.html index aff0836..03a3545 100644 --- a/docs/ReleaseNotes.html +++ b/docs/ReleaseNotes.html @@ -59,6 +59,7 @@ Almost dead code. lib/Transforms/IPO/MergeFunctions.cpp => consider for 2.8. llvm/Analysis/PointerTracking.h => Edwin wants this, consider for 2.8. ABCD, SCCVN, GEPSplitterPass + MSIL backend? --> @@ -1349,7 +1350,7 @@ lists</a>.</p> src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a> <a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br> - Last modified: $Date: 2010-01-09 23:30:40 +0100 (Sat, 09 Jan 2010) $ + Last modified: $Date: 2010-01-16 22:25:13 +0100 (Sat, 16 Jan 2010) $ </address> </body> diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 6879205..d57c250 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -117,8 +117,7 @@ typedef enum { LLVMNoCaptureAttribute = 1<<21, LLVMNoRedZoneAttribute = 1<<22, LLVMNoImplicitFloatAttribute = 1<<23, - LLVMNakedAttribute = 1<<24, - LLVMInlineHintAttribute = 1<<25 + LLVMNakedAttribute = 1<<24 } LLVMAttribute; typedef enum { @@ -1008,7 +1007,7 @@ namespace llvm { \ template<typename T> \ inline T *unwrap(ref P) { \ - T *Q = dynamic_cast<T*>(unwrap(P)); \ + T *Q = (T*)unwrap(P); \ assert(Q && "Invalid cast!"); \ return Q; \ } diff --git a/include/llvm/ADT/DenseMapInfo.h b/include/llvm/ADT/DenseMapInfo.h index 6b494ef..41197a1 100644 --- a/include/llvm/ADT/DenseMapInfo.h +++ b/include/llvm/ADT/DenseMapInfo.h @@ -92,6 +92,19 @@ template<> struct DenseMapInfo<unsigned long long> { } }; +// Provide DenseMapInfo for long longs. +template<> struct DenseMapInfo<long long> { + static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } + static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } + static unsigned getHashValue(const long long& Val) { + return (unsigned)(Val * 37LL); + } + static bool isEqual(const long long& LHS, + const long long& RHS) { + return LHS == RHS; + } +}; + // Provide DenseMapInfo for all pairs whose members have info. template<typename T, typename U> struct DenseMapInfo<std::pair<T, U> > { diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index fc9fe8b..1b3f1a9 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -217,7 +217,7 @@ public: // Utility methods. //===--------------------------------------------------===// - inline unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) { ID.AddPointer(M.Root); diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index 676a198..ac06a40 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -51,13 +51,11 @@ public: /// getLeft - Returns a pointer to the left subtree. This value /// is NULL if there is no left subtree. - ImutAVLTree *getLeft() const { - return reinterpret_cast<ImutAVLTree*>(Left & ~LeftFlags); - } + ImutAVLTree *getLeft() const { return Left; } /// getRight - Returns a pointer to the right subtree. This value is /// NULL if there is no right subtree. - ImutAVLTree* getRight() const { return Right; } + ImutAVLTree *getRight() const { return Right; } /// getHeight - Returns the height of the tree. A tree with no subtrees /// has a height of 1. @@ -190,23 +188,22 @@ public: unsigned HL = getLeft() ? getLeft()->verify() : 0; unsigned HR = getRight() ? getRight()->verify() : 0; - assert (getHeight() == ( HL > HR ? HL : HR ) + 1 - && "Height calculation wrong."); - - assert ((HL > HR ? HL-HR : HR-HL) <= 2 - && "Balancing invariant violated."); + assert(getHeight() == ( HL > HR ? HL : HR ) + 1 + && "Height calculation wrong"); + assert((HL > HR ? HL-HR : HR-HL) <= 2 + && "Balancing invariant violated"); - assert (!getLeft() - || ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), - ImutInfo::KeyOfValue(getValue())) - && "Value in left child is not less that current value."); + assert(!getLeft() + || ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), + ImutInfo::KeyOfValue(getValue())) + && "Value in left child is not less that current value"); - assert (!getRight() - || ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), - ImutInfo::KeyOfValue(getRight()->getValue())) - && "Current value is not less that value of right child."); + assert(!getRight() + || ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(getRight()->getValue())) + && "Current value is not less that value of right child"); return getHeight(); } @@ -221,9 +218,11 @@ public: //===----------------------------------------------------===// private: - uintptr_t Left; + ImutAVLTree* Left; ImutAVLTree* Right; - unsigned Height; + unsigned Height : 28; + unsigned Mutable : 1; + unsigned CachedDigest : 1; value_type Value; uint32_t Digest; @@ -232,15 +231,12 @@ private: //===----------------------------------------------------===// private: - - enum { Mutable = 0x1, NoCachedDigest = 0x2, LeftFlags = 0x3 }; - /// ImutAVLTree - Internal constructor that is only called by /// ImutAVLFactory. - ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height) - : Left(reinterpret_cast<uintptr_t>(l) | (Mutable | NoCachedDigest)), - Right(r), Height(height), Value(v), Digest(0) {} - + ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, + unsigned height) + : Left(l), Right(r), Height(height), Mutable(true), CachedDigest(false), + Value(v), Digest(0) {} /// isMutable - Returns true if the left and right subtree references /// (as well as height) can be changed. If this method returns false, @@ -248,11 +244,11 @@ private: /// object should always have this method return true. Further, if this /// method returns false for an instance of ImutAVLTree, all subtrees /// will also have this method return false. The converse is not true. - bool isMutable() const { return Left & Mutable; } + bool isMutable() const { return Mutable; } /// hasCachedDigest - Returns true if the digest for this tree is cached. /// This can only be true if the tree is immutable. - bool hasCachedDigest() const { return !(Left & NoCachedDigest); } + bool hasCachedDigest() const { return CachedDigest; } //===----------------------------------------------------===// // Mutating operations. A tree root can be manipulated as @@ -269,13 +265,13 @@ private: /// it is an error to call setLeft(), setRight(), and setHeight(). void MarkImmutable() { assert(isMutable() && "Mutable flag already removed."); - Left &= ~Mutable; + Mutable = false; } /// MarkedCachedDigest - Clears the NoCachedDigest flag for a tree. void MarkedCachedDigest() { assert(!hasCachedDigest() && "NoCachedDigest flag already removed."); - Left &= ~NoCachedDigest; + CachedDigest = true; } /// setLeft - Changes the reference of the left subtree. Used internally @@ -283,7 +279,8 @@ private: void setLeft(ImutAVLTree* NewLeft) { assert(isMutable() && "Only a mutable tree can have its left subtree changed."); - Left = reinterpret_cast<uintptr_t>(NewLeft) | LeftFlags; + Left = NewLeft; + CachedDigest = false; } /// setRight - Changes the reference of the right subtree. Used internally @@ -293,9 +290,7 @@ private: "Only a mutable tree can have its right subtree changed."); Right = NewRight; - // Set the NoCachedDigest flag. - Left = Left | NoCachedDigest; - + CachedDigest = false; } /// setHeight - Changes the height of the tree. Used internally by @@ -397,7 +392,7 @@ public: private: bool isEmpty(TreeTy* T) const { return !T; } - unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; } + unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; } TreeTy* Left(TreeTy* T) const { return T->getLeft(); } TreeTy* Right(TreeTy* T) const { return T->getRight(); } value_type_ref Value(TreeTy* T) const { return T->Value; } @@ -405,7 +400,7 @@ private: unsigned IncrementHeight(TreeTy* L, TreeTy* R) const { unsigned hl = Height(L); unsigned hr = Height(R); - return ( hl > hr ? hl : hr ) + 1; + return (hl > hr ? hl : hr) + 1; } static bool CompareTreeWithSection(TreeTy* T, @@ -434,17 +429,17 @@ private: TreeTy* CreateNode(TreeTy* L, value_type_ref V, TreeTy* R) { BumpPtrAllocator& A = getAllocator(); TreeTy* T = (TreeTy*) A.Allocate<TreeTy>(); - new (T) TreeTy(L,R,V,IncrementHeight(L,R)); + new (T) TreeTy(L, R, V, IncrementHeight(L,R)); return T; } TreeTy* CreateNode(TreeTy* L, TreeTy* OldTree, TreeTy* R) { - assert (!isEmpty(OldTree)); + assert(!isEmpty(OldTree)); if (OldTree->isMutable()) { OldTree->setLeft(L); OldTree->setRight(R); - OldTree->setHeight(IncrementHeight(L,R)); + OldTree->setHeight(IncrementHeight(L, R)); return OldTree; } else @@ -459,8 +454,7 @@ private: unsigned hr = Height(R); if (hl > hr + 2) { - assert (!isEmpty(L) && - "Left tree cannot be empty to have a height >= 2."); + assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2"); TreeTy* LL = Left(L); TreeTy* LR = Right(L); @@ -468,8 +462,7 @@ private: if (Height(LL) >= Height(LR)) return CreateNode(LL, L, CreateNode(LR,V,R)); - assert (!isEmpty(LR) && - "LR cannot be empty because it has a height >= 1."); + assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1"); TreeTy* LRL = Left(LR); TreeTy* LRR = Right(LR); @@ -477,8 +470,7 @@ private: return CreateNode(CreateNode(LL,L,LRL), LR, CreateNode(LRR,V,R)); } else if (hr > hl + 2) { - assert (!isEmpty(R) && - "Right tree cannot be empty to have a height >= 2."); + assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2"); TreeTy* RL = Left(R); TreeTy* RR = Right(R); @@ -486,8 +478,7 @@ private: if (Height(RR) >= Height(RL)) return CreateNode(CreateNode(L,V,RL), R, RR); - assert (!isEmpty(RL) && - "RL cannot be empty because it has a height >= 1."); + assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1"); TreeTy* RLL = Left(RL); TreeTy* RLR = Right(RL); @@ -505,7 +496,7 @@ private: if (isEmpty(T)) return CreateNode(T, V, T); - assert (!T->isMutable()); + assert(!T->isMutable()); key_type_ref K = ImutInfo::KeyOfValue(V); key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); @@ -526,7 +517,7 @@ private: if (isEmpty(T)) return T; - assert (!T->isMutable()); + assert(!T->isMutable()); key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); @@ -548,7 +539,7 @@ private: } TreeTy* RemoveMinBinding(TreeTy* T, TreeTy*& NodeRemoved) { - assert (!isEmpty(T)); + assert(!isEmpty(T)); if (isEmpty(Left(T))) { NodeRemoved = T; @@ -641,12 +632,12 @@ public: } TreeTy* operator*() const { - assert (!stack.empty()); + assert(!stack.empty()); return reinterpret_cast<TreeTy*>(stack.back() & ~Flags); } uintptr_t getVisitState() { - assert (!stack.empty()); + assert(!stack.empty()); return stack.back() & Flags; } @@ -658,7 +649,7 @@ public: } void SkipToParent() { - assert (!stack.empty()); + assert(!stack.empty()); stack.pop_back(); if (stack.empty()) @@ -672,7 +663,7 @@ public: stack.back() |= VisitedRight; break; default: - assert (false && "Unreachable."); + assert(false && "Unreachable."); } } @@ -690,10 +681,10 @@ public: inline bool operator!=(const _Self& x) const { return !operator==(x); } _Self& operator++() { - assert (!stack.empty()); + assert(!stack.empty()); TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); - assert (Current); + assert(Current); switch (getVisitState()) { case VisitedNone: @@ -717,17 +708,17 @@ public: break; default: - assert (false && "Unreachable."); + assert(false && "Unreachable."); } return *this; } _Self& operator--() { - assert (!stack.empty()); + assert(!stack.empty()); TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); - assert (Current); + assert(Current); switch (getVisitState()) { case VisitedNone: @@ -752,7 +743,7 @@ public: break; default: - assert (false && "Unreachable."); + assert(false && "Unreachable."); } return *this; @@ -1051,7 +1042,7 @@ public: // Utility methods. //===--------------------------------------------------===// - inline unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } static inline void Profile(FoldingSetNodeID& ID, const ImmutableSet& S) { ID.AddPointer(S.Root); diff --git a/include/llvm/Analysis/DOTGraphTraitsPass.h b/include/llvm/Analysis/DOTGraphTraitsPass.h new file mode 100644 index 0000000..4828eba --- /dev/null +++ b/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -0,0 +1,83 @@ +//===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Templates to create dotty viewer and printer passes for GraphTraits graphs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOT_GRAPHTRAITS_PASS_H +#define LLVM_ANALYSIS_DOT_GRAPHTRAITS_PASS_H + +#include "llvm/Pass.h" +#include "llvm/Analysis/CFGPrinter.h" + +namespace llvm { +template <class Analysis, bool Simple> +struct DOTGraphTraitsViewer : public FunctionPass { + std::string Name; + + DOTGraphTraitsViewer(std::string GraphName, const void *ID) : FunctionPass(ID) { + Name = GraphName; + } + + virtual bool runOnFunction(Function &F) { + Analysis *Graph; + std::string Title, GraphName; + Graph = &getAnalysis<Analysis>(); + GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); + Title = GraphName + " for '" + F.getNameStr() + "' function"; + ViewGraph(Graph, Name, Simple, Title); + + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<Analysis>(); + } +}; + +template <class Analysis, bool Simple> +struct DOTGraphTraitsPrinter : public FunctionPass { + + std::string Name; + + DOTGraphTraitsPrinter(std::string GraphName, const void *ID) + : FunctionPass(ID) { + Name = GraphName; + } + + virtual bool runOnFunction(Function &F) { + Analysis *Graph; + std::string Filename = Name + "." + F.getNameStr() + ".dot"; + errs() << "Writing '" << Filename << "'..."; + + std::string ErrorInfo; + raw_fd_ostream File(Filename.c_str(), ErrorInfo); + Graph = &getAnalysis<Analysis>(); + + std::string Title, GraphName; + GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); + Title = GraphName + " for '" + F.getNameStr() + "' function"; + + if (ErrorInfo.empty()) + WriteGraph(File, Graph, Simple, Name, Title); + else + errs() << " error opening file for writing!"; + errs() << "\n"; + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<Analysis>(); + } +}; +} +#endif diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h index cc9514c..150d3ee 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/Analysis/DebugInfo.h @@ -475,7 +475,7 @@ namespace llvm { /// is not associated with any DWARF tag. class DILocation : public DIDescriptor { public: - explicit DILocation(MDNode *N) : DIDescriptor(N) { ; } + explicit DILocation(MDNode *N) : DIDescriptor(N) { } unsigned getLineNumber() const { return getUnsignedField(0); } unsigned getColumnNumber() const { return getUnsignedField(1); } @@ -587,7 +587,7 @@ namespace llvm { StringRef DisplayName, StringRef LinkageName, DICompileUnit CompileUnit, unsigned LineNo, - DIType Type, bool isLocalToUnit, + DIType Ty, bool isLocalToUnit, bool isDefinition, unsigned VK = 0, unsigned VIndex = 0, @@ -603,21 +603,21 @@ namespace llvm { StringRef DisplayName, StringRef LinkageName, DICompileUnit CompileUnit, - unsigned LineNo, DIType Type, bool isLocalToUnit, + unsigned LineNo, DIType Ty, bool isLocalToUnit, bool isDefinition, llvm::GlobalVariable *GV); /// CreateVariable - Create a new descriptor for the specified variable. DIVariable CreateVariable(unsigned Tag, DIDescriptor Context, StringRef Name, DICompileUnit CompileUnit, unsigned LineNo, - DIType Type); + DIType Ty); /// CreateComplexVariable - Create a new descriptor for the specified /// variable which has a complex address expression for its address. DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Context, const std::string &Name, DICompileUnit CompileUnit, unsigned LineNo, - DIType Type, + DIType Ty, SmallVector<Value *, 9> &addr); /// CreateLexicalBlock - This creates a descriptor for a lexical block @@ -656,13 +656,6 @@ namespace llvm { Constant *GetTagConstant(unsigned TAG); }; - /// Finds the dbg.declare intrinsic corresponding to this value if any. - /// It looks through pointer casts too. - const DbgDeclareInst *findDbgDeclare(const Value *V); - - /// Find the debug info descriptor corresponding to this global variable. - Value *findDbgGlobalDeclare(GlobalVariable *V); - bool getLocationInfo(const Value *V, std::string &DisplayName, std::string &Type, unsigned &LineNo, std::string &File, std::string &Dir); diff --git a/include/llvm/Analysis/DominatorInternals.h b/include/llvm/Analysis/DominatorInternals.h index 5ecb348..8cea96d 100644 --- a/include/llvm/Analysis/DominatorInternals.h +++ b/include/llvm/Analysis/DominatorInternals.h @@ -262,29 +262,17 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, DT.Info[W]; // Step #2: Calculate the semidominators of all vertices - bool HasChildOutsideDFS = false; // initialize the semi dominator to point to the parent node WInfo.Semi = WInfo.Parent; for (typename GraphTraits<Inverse<NodeT> >::ChildIteratorType CI = GraphTraits<Inverse<NodeT> >::child_begin(W), - E = GraphTraits<Inverse<NodeT> >::child_end(W); CI != E; ++CI) { + E = GraphTraits<Inverse<NodeT> >::child_end(W); CI != E; ++CI) if (DT.Info.count(*CI)) { // Only if this predecessor is reachable! unsigned SemiU = DT.Info[Eval<GraphT>(DT, *CI)].Semi; if (SemiU < WInfo.Semi) WInfo.Semi = SemiU; } - else { - // if the child has no DFS number it is not post-dominated by any exit, - // and so is the current block. - HasChildOutsideDFS = true; - } - } - - // if some child has no DFS number it is not post-dominated by any exit, - // and so is the current block. - if (DT.isPostDominator() && HasChildOutsideDFS) - WInfo.Semi = 0; DT.Info[DT.Vertex[WInfo.Semi]].Bucket.push_back(W); diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index fcd9caa..50f7d45 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -212,6 +212,11 @@ public: /// value of the OperandValToReplace of the given IVStrideUse. const SCEV *getReplacementExpr(const IVStrideUse &U) const; + /// getCanonicalExpr - Return a SCEV expression which computes the + /// value of the SCEV of the given IVStrideUse, ignoring the + /// isUseOfPostIncrementedValue flag. + const SCEV *getCanonicalExpr(const IVStrideUse &U) const; + void print(raw_ostream &OS, const Module* = 0) const; /// dump - This method is used for debugging. diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h index 2dceccb..10ff103 100644 --- a/include/llvm/Analysis/LoopPass.h +++ b/include/llvm/Analysis/LoopPass.h @@ -28,8 +28,8 @@ class PMStack; class LoopPass : public Pass { public: - explicit LoopPass(intptr_t pid) : Pass(pid) {} - explicit LoopPass(void *pid) : Pass(pid) {} + explicit LoopPass(intptr_t pid) : Pass(PT_Loop, pid) {} + explicit LoopPass(void *pid) : Pass(PT_Loop, pid) {} // runOnLoop - This method should be implemented by the subclass to perform // whatever action is necessary for the specified Loop. @@ -94,6 +94,9 @@ public: return "Loop Pass Manager"; } + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + /// Print passes managed by this manager void dumpPassStructure(unsigned Offset); diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 6f57c74..e281971 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -167,7 +167,7 @@ namespace llvm { }; friend class SCEVCallbackVH; - friend struct SCEVExpander; + friend class SCEVExpander; /// F - The function we are analyzing. /// @@ -181,6 +181,10 @@ namespace llvm { /// TargetData *TD; + /// DT - The dominator tree. + /// + DominatorTree *DT; + /// CouldNotCompute - This SCEV is used to represent unknown trip /// counts and things. SCEVCouldNotCompute CouldNotCompute; diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index bbdd043..01df503 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -26,19 +26,47 @@ namespace llvm { /// Clients should create an instance of this class when rewriting is needed, /// and destroy it when finished to allow the release of the associated /// memory. - struct SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> { + class SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> { + public: ScalarEvolution &SE; + + private: std::map<std::pair<const SCEV *, Instruction *>, AssertingVH<Value> > InsertedExpressions; std::set<Value*> InsertedValues; + /// PostIncLoop - When non-null, expanded addrecs referring to the given + /// loop expanded in post-inc mode. For example, expanding {1,+,1}<L> in + /// post-inc mode returns the add instruction that adds one to the phi + /// for {0,+,1}<L>, as opposed to a new phi starting at 1. This is only + /// supported in non-canonical mode. + const Loop *PostIncLoop; + + /// IVIncInsertPos - When this is non-null, addrecs expanded in the + /// loop it indicates should be inserted with increments at + /// IVIncInsertPos. + const Loop *IVIncInsertLoop; + + /// IVIncInsertPos - When expanding addrecs in the IVIncInsertLoop loop, + /// insert the IV increment at this position. + Instruction *IVIncInsertPos; + + /// CanonicalMode - When true, expressions are expanded in "canonical" + /// form. In particular, addrecs are expanded as arithmetic based on + /// a canonical induction variable. When false, expression are expanded + /// in a more literal form. + bool CanonicalMode; + + protected: typedef IRBuilder<true, TargetFolder> BuilderType; BuilderType Builder; friend struct SCEVVisitor<SCEVExpander, Value*>; public: + /// SCEVExpander - Construct a SCEVExpander in "canonical" mode. explicit SCEVExpander(ScalarEvolution &se) - : SE(se), Builder(se.getContext(), TargetFolder(se.TD)) {} + : SE(se), PostIncLoop(0), IVIncInsertLoop(0), CanonicalMode(true), + Builder(se.getContext(), TargetFolder(se.TD)) {} /// clear - Erase the contents of the InsertedExpressions map so that users /// trying to expand the same expression into multiple BasicBlocks or @@ -54,11 +82,36 @@ namespace llvm { /// expandCodeFor - Insert code to directly compute the specified SCEV /// expression into the program. The inserted code is inserted into the /// specified block. - Value *expandCodeFor(const SCEV *SH, const Type *Ty, Instruction *IP) { + Value *expandCodeFor(const SCEV *SH, const Type *Ty, Instruction *I) { + BasicBlock::iterator IP = I; + while (isInsertedInstruction(IP)) ++IP; Builder.SetInsertPoint(IP->getParent(), IP); return expandCodeFor(SH, Ty); } + /// setIVIncInsertPos - Set the current IV increment loop and position. + void setIVIncInsertPos(const Loop *L, Instruction *Pos) { + assert(!CanonicalMode && + "IV increment positions are not supported in CanonicalMode"); + IVIncInsertLoop = L; + IVIncInsertPos = Pos; + } + + /// setPostInc - If L is non-null, enable post-inc expansion for addrecs + /// referring to the given loop. If L is null, disable post-inc expansion + /// completely. Post-inc expansion is only supported in non-canonical + /// mode. + void setPostInc(const Loop *L) { + assert(!CanonicalMode && + "Post-inc expansion is not supported in CanonicalMode"); + PostIncLoop = L; + } + + /// disableCanonicalMode - Disable the behavior of expanding expressions in + /// canonical form rather than in a more literal form. Non-canonical mode + /// is useful for late optimization passes. + void disableCanonicalMode() { CanonicalMode = false; } + private: LLVMContext &getContext() const { return SE.getContext(); } @@ -121,6 +174,16 @@ namespace llvm { Value *visitUnknown(const SCEVUnknown *S) { return S->getValue(); } + + void rememberInstruction(Value *I) { + if (!PostIncLoop) InsertedValues.insert(I); + } + + Value *expandAddRecExprLiterally(const SCEVAddRecExpr *); + PHINode *getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, + const Loop *L, + const Type *ExpandTy, + const Type *IntTy); }; } diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 2c50350..64b8b0b 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -295,6 +295,13 @@ namespace llvm { public: virtual const char *getOperationStr() const { return " + "; } + virtual const Type *getType() const { + // Use the type of the last operand, which is likely to be a pointer + // type, if there is one. This doesn't usually matter, but it can help + // reduce casts when the expressions are expanded. + return getOperand(getNumOperands() - 1)->getType(); + } + /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVAddExpr *S) { return true; } static inline bool classof(const SCEV *S) { diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h index 068f81f..7fa5d4a 100644 --- a/include/llvm/Attributes.h +++ b/include/llvm/Attributes.h @@ -58,8 +58,6 @@ const Attributes NoRedZone = 1<<22; /// disable redzone const Attributes NoImplicitFloat = 1<<23; /// disable implicit floating point /// instructions. const Attributes Naked = 1<<24; ///< Naked function -const Attributes InlineHint = 1<<25; ///< source said inlining was - ///desirable /// @brief Attributes that only apply to function parameters. const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; @@ -68,7 +66,7 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; /// be used on return values or function parameters. const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq | - NoRedZone | NoImplicitFloat | Naked | InlineHint; + NoRedZone | NoImplicitFloat | Naked; /// @brief Parameter attributes that do not apply to vararg call arguments. const Attributes VarArgsIncompatible = StructRet; diff --git a/include/llvm/CallGraphSCCPass.h b/include/llvm/CallGraphSCCPass.h index fc9feda..feab763 100644 --- a/include/llvm/CallGraphSCCPass.h +++ b/include/llvm/CallGraphSCCPass.h @@ -32,8 +32,8 @@ class PMStack; struct CallGraphSCCPass : public Pass { - explicit CallGraphSCCPass(intptr_t pid) : Pass(pid) {} - explicit CallGraphSCCPass(void *pid) : Pass(pid) {} + explicit CallGraphSCCPass(intptr_t pid) : Pass(PT_CallGraphSCC, pid) {} + explicit CallGraphSCCPass(void *pid) : Pass(PT_CallGraphSCC, pid) {} /// doInitialization - This method is called before the SCC's of the program /// has been processed, allowing the pass to do initialization as necessary. diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 9a07e31..377096c 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -48,10 +48,12 @@ namespace llvm { class MCSection; class MCStreamer; class MCSymbol; + class MDNode; class DwarfWriter; class Mangler; class MCAsmInfo; class TargetLoweringObjectFile; + class Twine; class Type; class formatted_raw_ostream; @@ -131,10 +133,10 @@ namespace llvm { /// Mangler *Mang; - /// Cache of mangled name for current function. This is recalculated at the + /// The symbol for the current function. This is recalculated at the /// beginning of each call to runOnMachineFunction(). /// - std::string CurrentFnName; + MCSymbol *CurrentFnSym; /// getCurrentSection() - Return the current section we are emitting to. const MCSection *getCurrentSection() const; @@ -151,7 +153,7 @@ namespace llvm { mutable unsigned Counter; // Private state for processDebugLoc() - mutable DebugLocTuple PrevDLT; + mutable const MDNode *PrevDLT; protected: explicit AsmPrinter(formatted_raw_ostream &o, TargetMachine &TM, @@ -213,10 +215,6 @@ namespace llvm { unsigned AsmVariant, const char *ExtraCode); - /// PrintGlobalVariable - Emit the specified global variable and its - /// initializer to the output stream. - virtual void PrintGlobalVariable(const GlobalVariable *GV) = 0; - /// SetupMachineFunction - This should be called when a new MachineFunction /// is being processed from runOnMachineFunction. void SetupMachineFunction(MachineFunction &MF); @@ -238,6 +236,9 @@ namespace llvm { /// void EmitJumpTableInfo(MachineJumpTableInfo *MJTI, MachineFunction &MF); + /// EmitGlobalVariable - Emit the specified global variable to the .s file. + virtual void EmitGlobalVariable(const GlobalVariable *GV); + /// EmitSpecialLLVMGlobal - Check to see if the specified global is a /// special global used by LLVM. If so, emit it and return true, otherwise /// do nothing and return false. @@ -245,39 +246,9 @@ namespace llvm { public: //===------------------------------------------------------------------===// - /// LEB 128 number encoding. - - /// PrintULEB128 - Print a series of hexidecimal values(separated by commas) - /// representing an unsigned leb128 value. - void PrintULEB128(unsigned Value) const; - - /// PrintSLEB128 - Print a series of hexidecimal values(separated by commas) - /// representing a signed leb128 value. - void PrintSLEB128(int Value) const; - - //===------------------------------------------------------------------===// // Emission and print routines // - /// PrintHex - Print a value as a hexidecimal value. - /// - void PrintHex(int Value) const; - - /// EOL - Print a newline character to asm stream. If a comment is present - /// then it will be printed first. Comments should not contain '\n'. - void EOL() const; - void EOL(const std::string &Comment) const; - void EOL(const char* Comment) const; - void EOL(const char *Comment, unsigned Encoding) const; - - /// EmitULEB128Bytes - Emit an assembler byte data directive to compose an - /// unsigned leb128 value. - void EmitULEB128Bytes(unsigned Value) const; - - /// EmitSLEB128Bytes - print an assembler byte data directive to compose a - /// signed leb128 value. - void EmitSLEB128Bytes(int Value) const; - /// EmitInt8 - Emit a byte directive and value. /// void EmitInt8(int Value) const; @@ -294,14 +265,8 @@ namespace llvm { /// void EmitInt64(uint64_t Value) const; - /// EmitString - Emit a string with quotes and a null terminator. - /// Special characters are emitted properly. - /// @verbatim (Eg. '\t') @endverbatim - void EmitString(const StringRef String) const; - void EmitString(const char *String, unsigned Size) const; - /// EmitFile - Emit a .file directive. - void EmitFile(unsigned Number, const std::string &Name) const; + void EmitFile(unsigned Number, StringRef Name) const; //===------------------------------------------------------------------===// @@ -336,13 +301,32 @@ namespace llvm { /// EmitComments - Pretty-print comments for instructions void EmitComments(const MachineInstr &MI) const; - /// EmitComments - Pretty-print comments for basic blocks - void EmitComments(const MachineBasicBlock &MBB) const; + /// GetGlobalValueSymbol - Return the MCSymbol for the specified global + /// value. + MCSymbol *GetGlobalValueSymbol(const GlobalValue *GV) const; + + /// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with + /// global value name as its base, with the specified suffix, and where the + /// symbol is forced to have private linkage if ForcePrivate is true. + MCSymbol *GetSymbolWithGlobalValueBase(const GlobalValue *GV, + StringRef Suffix, + bool ForcePrivate = true) const; + + /// GetExternalSymbolSymbol - Return the MCSymbol for the specified + /// ExternalSymbol. + MCSymbol *GetExternalSymbolSymbol(StringRef Sym) const; + /// GetMBBSymbol - Return the MCSymbol corresponding to the specified basic /// block label. MCSymbol *GetMBBSymbol(unsigned MBBID) const; + /// GetCPISymbol - Return the symbol for the specified constant pool entry. + MCSymbol *GetCPISymbol(unsigned CPID) const; + + /// GetJTISymbol - Return the symbol for the specified jump table entry. + MCSymbol *GetJTISymbol(unsigned JTID, bool isLinkerPrivate = false) const; + /// GetBlockAddressSymbol - Return the MCSymbol used to satisfy BlockAddress /// uses of the specified basic block. MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA, @@ -355,22 +339,14 @@ namespace llvm { /// MachineBasicBlock, an alignment (if present) and a comment describing /// it if appropriate. void EmitBasicBlockStart(const MachineBasicBlock *MBB) const; - protected: - /// EmitZeros - Emit a block of zeros. - /// - void EmitZeros(uint64_t NumZeros, unsigned AddrSpace = 0) const; - - /// EmitString - Emit a zero-byte-terminated string constant. - /// - virtual void EmitString(const ConstantArray *CVA) const; - - /// EmitConstantValueOnly - Print out the specified constant, without a - /// storage class. Only constants of first-class type are allowed here. - void EmitConstantValueOnly(const Constant *CV); - + + + // Data emission. + /// EmitGlobalConstant - Print a general LLVM constant to the .s file. void EmitGlobalConstant(const Constant* CV, unsigned AddrSpace = 0); - + + protected: virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); /// processDebugLoc - Processes the debug information of each machine @@ -398,26 +374,16 @@ namespace llvm { const MachineBasicBlock *MBB, unsigned uid) const; - /// printDataDirective - This method prints the asm directive for the - /// specified type. - void printDataDirective(const Type *type, unsigned AddrSpace = 0); - /// printVisibility - This prints visibility information about symbol, if /// this is suported by the target. - void printVisibility(const std::string& Name, unsigned Visibility) const; - + void printVisibility(MCSymbol *Sym, unsigned Visibility) const; + /// printOffset - This is just convenient handler for printing offsets. void printOffset(int64_t Offset) const; private: void EmitLLVMUsedList(Constant *List); void EmitXXStructorList(Constant *List); - void EmitGlobalConstantStruct(const ConstantStruct* CVS, - unsigned AddrSpace); - void EmitGlobalConstantArray(const ConstantArray* CVA, unsigned AddrSpace); - void EmitGlobalConstantVector(const ConstantVector* CP); - void EmitGlobalConstantFP(const ConstantFP* CFP, unsigned AddrSpace); - void EmitGlobalConstantLargeInt(const ConstantInt* CI, unsigned AddrSpace); GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C); }; } diff --git a/include/llvm/CodeGen/FileWriters.h b/include/llvm/CodeGen/FileWriters.h index a913d21..9dba838 100644 --- a/include/llvm/CodeGen/FileWriters.h +++ b/include/llvm/CodeGen/FileWriters.h @@ -20,11 +20,17 @@ namespace llvm { class ObjectCodeEmitter; class TargetMachine; class raw_ostream; + class formatted_raw_ostream; + class MachineFunctionPass; + class MCAsmInfo; + class MCCodeEmitter; ObjectCodeEmitter *AddELFWriter(PassManagerBase &FPM, raw_ostream &O, TargetMachine &TM); - ObjectCodeEmitter *AddMachOWriter(PassManagerBase &FPM, raw_ostream &O, - TargetMachine &TM); + MachineFunctionPass *createMachOWriter(formatted_raw_ostream &O, + TargetMachine &TM, + const MCAsmInfo *T, + MCCodeEmitter *MCE); } // end llvm namespace diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 5608c99..27947e8 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -44,6 +44,7 @@ namespace { (void) llvm::createBURRListDAGScheduler(NULL, llvm::CodeGenOpt::Default); (void) llvm::createTDRRListDAGScheduler(NULL, llvm::CodeGenOpt::Default); + (void) llvm::createSourceListDAGScheduler(NULL,llvm::CodeGenOpt::Default); (void) llvm::createTDListDAGScheduler(NULL, llvm::CodeGenOpt::Default); (void) llvm::createFastDAGScheduler(NULL, llvm::CodeGenOpt::Default); (void) llvm::createDefaultScheduler(NULL, llvm::CodeGenOpt::Default); diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 6b4c640..20644c1 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -337,6 +337,10 @@ public: MachineBasicBlock *DestB, bool isCond); + /// findDebugLoc - find the next valid DebugLoc starting at MBBI, skipping + /// any DEBUG_VALUE instructions. Return UnknownLoc if there is none. + DebugLoc findDebugLoc(MachineBasicBlock::iterator &MBBI); + // Debugging methods. void dump() const; void print(raw_ostream &OS) const; diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index a12a55a..6ca51bf 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -26,6 +26,7 @@ namespace llvm { +class DILocation; class Value; class Function; class MachineRegisterInfo; @@ -174,9 +175,6 @@ public: AlignOf<Ty>::Alignment)); MFInfo = new (Loc) Ty(*this); } - - assert((void*)dynamic_cast<Ty*>(MFInfo) == (void*)MFInfo && - "Invalid concrete type or multiple inheritence for getInfo"); return static_cast<Ty*>(MFInfo); } @@ -368,8 +366,8 @@ public: // Debug location. // - /// getDebugLocTuple - Get the DebugLocTuple for a given DebugLoc object. - DebugLocTuple getDebugLocTuple(DebugLoc DL) const; + /// getDILocation - Get the DILocation for a given DebugLoc object. + DILocation getDILocation(DebugLoc DL) const; /// getDefaultDebugLoc - Get the default debug location for the machine /// function. diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index e9b645b..d365029 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -172,9 +172,6 @@ public: Ty &getObjFileInfo() { if (ObjFileMMI == 0) ObjFileMMI = new Ty(*this); - - assert((void*)dynamic_cast<Ty*>(ObjFileMMI) == (void*)ObjFileMMI && - "Invalid concrete type or multiple inheritence for getInfo"); return *static_cast<Ty*>(ObjFileMMI); } diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 907c25a..07d886d 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -453,11 +453,9 @@ public: Op.setTargetFlags(TargetFlags); return Op; } - static MachineOperand CreateMetadata(MDNode *Meta, - unsigned char TargetFlags = 0) { + static MachineOperand CreateMetadata(MDNode *Meta) { MachineOperand Op(MachineOperand::MO_Metadata); Op.Contents.MD = Meta; - Op.setTargetFlags(TargetFlags); return Op; } diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 2203f8c..7e0da3f 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -195,10 +195,6 @@ namespace llvm { /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. FunctionPass *createSjLjEHPass(const TargetLowering *tli); - /// createMaxStackAlignmentCalculatorPass() - Determine the maximum required - /// alignment for a function. - FunctionPass* createMaxStackAlignmentCalculatorPass(); - } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/SchedulerRegistry.h b/include/llvm/CodeGen/SchedulerRegistry.h index 1cf64a0..cf3274f 100644 --- a/include/llvm/CodeGen/SchedulerRegistry.h +++ b/include/llvm/CodeGen/SchedulerRegistry.h @@ -73,6 +73,11 @@ ScheduleDAGSDNodes *createBURRListDAGScheduler(SelectionDAGISel *IS, ScheduleDAGSDNodes *createTDRRListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level OptLevel); +/// createBURRListDAGScheduler - This creates a bottom up register usage +/// reduction list scheduler that schedules in source code order when possible. +ScheduleDAGSDNodes *createSourceListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + /// createTDListDAGScheduler - This creates a top-down list scheduler with /// a hazard recognizer. ScheduleDAGSDNodes *createTDListDAGScheduler(SelectionDAGISel *IS, diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index d55dd7f..33ebd00 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -63,6 +63,10 @@ enum CombineLevel { NoIllegalOperations // Combine may only create legal operations and types. }; +class SelectionDAG; +void checkForCycles(const SDNode *N); +void checkForCycles(const SelectionDAG *DAG); + /// SelectionDAG class - This is used to represent a portion of an LLVM function /// in a low-level Data Dependence DAG representation suitable for instruction /// selection. This DAG is constructed as the first step of instruction @@ -204,7 +208,12 @@ public: const SDValue &setRoot(SDValue N) { assert((!N.getNode() || N.getValueType() == MVT::Other) && "DAG root value is not a chain!"); - return Root = N; + if (N.getNode()) + checkForCycles(N.getNode()); + Root = N; + if (N.getNode()) + checkForCycles(this); + return Root; } /// Combine - This iterates over the nodes in the SelectionDAG, folding diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 7b1931a..45a9d40 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -44,6 +44,8 @@ template <typename T> struct DenseMapInfo; template <typename T> struct simplify_type; template <typename T> struct ilist_traits; +void checkForCycles(const SDNode *N); + /// SDVTList - This represents a list of ValueType's that has been intern'd by /// a SelectionDAG. Instances of this simple value class are returned by /// SelectionDAG::getVTList(...). @@ -1285,11 +1287,56 @@ public: void print_details(raw_ostream &OS, const SelectionDAG *G) const; void print(raw_ostream &OS, const SelectionDAG *G = 0) const; void printr(raw_ostream &OS, const SelectionDAG *G = 0) const; + + /// printrFull - Print a SelectionDAG node and all children down to + /// the leaves. The given SelectionDAG allows target-specific nodes + /// to be printed in human-readable form. Unlike printr, this will + /// print the whole DAG, including children that appear multiple + /// times. + /// + void printrFull(raw_ostream &O, const SelectionDAG *G = 0) const; + + /// printrWithDepth - Print a SelectionDAG node and children up to + /// depth "depth." The given SelectionDAG allows target-specific + /// nodes to be printed in human-readable form. Unlike printr, this + /// will print children that appear multiple times wherever they are + /// used. + /// + void printrWithDepth(raw_ostream &O, const SelectionDAG *G = 0, + unsigned depth = 100) const; + + + /// dump - Dump this node, for debugging. void dump() const; + + /// dumpr - Dump (recursively) this node and its use-def subgraph. void dumpr() const; + + /// dump - Dump this node, for debugging. + /// The given SelectionDAG allows target-specific nodes to be printed + /// in human-readable form. void dump(const SelectionDAG *G) const; + + /// dumpr - Dump (recursively) this node and its use-def subgraph. + /// The given SelectionDAG allows target-specific nodes to be printed + /// in human-readable form. void dumpr(const SelectionDAG *G) const; + /// dumprFull - printrFull to dbgs(). The given SelectionDAG allows + /// target-specific nodes to be printed in human-readable form. + /// Unlike dumpr, this will print the whole DAG, including children + /// that appear multiple times. + /// + void dumprFull(const SelectionDAG *G = 0) const; + + /// dumprWithDepth - printrWithDepth to dbgs(). The given + /// SelectionDAG allows target-specific nodes to be printed in + /// human-readable form. Unlike dumpr, this will print children + /// that appear multiple times wherever they are used. + /// + void dumprWithDepth(const SelectionDAG *G = 0, unsigned depth = 100) const; + + static bool classof(const SDNode *) { return true; } /// Profile - Gather unique data for the node. @@ -1318,6 +1365,7 @@ protected: OperandList[i].setUser(this); OperandList[i].setInitial(Ops[i]); } + checkForCycles(this); } /// This constructor adds no operands itself; operands can be @@ -1334,6 +1382,7 @@ protected: Ops[0].setInitial(Op0); NumOperands = 1; OperandList = Ops; + checkForCycles(this); } /// InitOperands - Initialize the operands list of this with 2 operands. @@ -1344,6 +1393,7 @@ protected: Ops[1].setInitial(Op1); NumOperands = 2; OperandList = Ops; + checkForCycles(this); } /// InitOperands - Initialize the operands list of this with 3 operands. @@ -1357,6 +1407,7 @@ protected: Ops[2].setInitial(Op2); NumOperands = 3; OperandList = Ops; + checkForCycles(this); } /// InitOperands - Initialize the operands list of this with 4 operands. @@ -1372,6 +1423,7 @@ protected: Ops[3].setInitial(Op3); NumOperands = 4; OperandList = Ops; + checkForCycles(this); } /// InitOperands - Initialize the operands list of this with N operands. @@ -1382,6 +1434,7 @@ protected: } NumOperands = N; OperandList = Ops; + checkForCycles(this); } /// DropOperands - Release the operands and set this node to have diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h index 85aaa7f..b5cc659 100644 --- a/include/llvm/InstrTypes.h +++ b/include/llvm/InstrTypes.h @@ -652,8 +652,7 @@ public: /// This class is the base class for the comparison instructions. /// @brief Abstract base class of comparison instructions. -// FIXME: why not derive from BinaryOperator? -class CmpInst: public Instruction { +class CmpInst : public Instruction { void *operator new(size_t, unsigned); // DO NOT IMPLEMENT CmpInst(); // do not implement protected: @@ -665,6 +664,7 @@ protected: Value *LHS, Value *RHS, const Twine &Name, BasicBlock *InsertAtEnd); + virtual void Anchor() const; // Out of line virtual method. public: /// This enumeration lists the possible predicates for CmpInst subclasses. /// Values in the range 0-31 are reserved for FCmpInst, while values in the diff --git a/include/llvm/IntrinsicInst.h b/include/llvm/IntrinsicInst.h index f40e8cc..d86b33e 100644 --- a/include/llvm/IntrinsicInst.h +++ b/include/llvm/IntrinsicInst.h @@ -25,7 +25,6 @@ #define LLVM_INTRINSICINST_H #include "llvm/Constants.h" -#include "llvm/Metadata.h" #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" @@ -83,12 +82,7 @@ namespace llvm { /// class DbgDeclareInst : public DbgInfoIntrinsic { public: - Value *getAddress() const { - if (MDNode* MD = dyn_cast<MDNode>(getOperand(1))) - return MD->getOperand(0); - else - return NULL; - } + Value *getAddress() const; MDNode *getVariable() const { return cast<MDNode>(getOperand(2)); } // Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/LinkAllVMCore.h b/include/llvm/LinkAllVMCore.h index 2145bf8..6cf2c4b 100644 --- a/include/llvm/LinkAllVMCore.h +++ b/include/llvm/LinkAllVMCore.h @@ -32,7 +32,6 @@ #include "llvm/System/Signals.h" #include "llvm/System/TimeValue.h" #include "llvm/Support/Dwarf.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/SlowOperationInformer.h" #include <cstdlib> @@ -46,10 +45,9 @@ namespace { // to know that getenv() never returns -1, this will do the job. if (std::getenv("bar") != (char*) -1) return; - llvm::Module* M = new llvm::Module("", llvm::getGlobalContext()); + (void)new llvm::Module("", llvm::getGlobalContext()); (void)new llvm::UnreachableInst(llvm::getGlobalContext()); (void) llvm::createVerifierPass(); - (void) new llvm::Mangler(*M,""); } } ForceVMCoreLinking; } diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index fb69630..5e31dfe 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -16,9 +16,13 @@ #ifndef LLVM_TARGET_ASM_INFO_H #define LLVM_TARGET_ASM_INFO_H +#include "llvm/MC/MCDirectives.h" #include <cassert> namespace llvm { + class MCSection; + class MCContext; + /// MCAsmInfo - This class is intended to be used as a base class for asm /// properties and features specific to the target. namespace ExceptionHandling { enum ExceptionsType { None, Dwarf, SjLj }; } @@ -29,15 +33,20 @@ namespace llvm { // Properties to be set by the target writer, used to configure asm printer. // - /// ZeroFillDirective - Directive for emitting a global to the ZeroFill - /// section on this target. Null if this target doesn't support zerofill. - const char *ZeroFillDirective; // Default is null. - - /// NonexecutableStackDirective - Directive for declaring to the - /// linker and beyond that the emitted code does not require stack - /// memory to be executable. - const char *NonexecutableStackDirective; // Default is null. - + /// HasSubsectionsViaSymbols - True if this target has the MachO + /// .subsections_via_symbols directive. + bool HasSubsectionsViaSymbols; // Default is false. + + /// HasMachoZeroFillDirective - True if this is a MachO target that supports + /// the macho-specific .zerofill directive for emitting BSS Symbols. + bool HasMachoZeroFillDirective; // Default is false. + + /// HasStaticCtorDtorReferenceInStaticMode - True if the compiler should + /// emit a ".reference .constructors_used" or ".reference .destructors_used" + /// directive after the a static ctor/dtor list. This directive is only + /// emitted in Static relocation model. + bool HasStaticCtorDtorReferenceInStaticMode; // Default is false. + /// NeedsSet - True if target asm treats expressions in data directives /// as linktime-relocatable. For assembly-time computation, we need to /// use a .set. Thus: @@ -107,7 +116,6 @@ namespace llvm { /// "\t.zero\t" and "\t.space\t". If this is set to null, the /// Data*bitsDirective's will be used to emit zero bytes. const char *ZeroDirective; // Defaults to "\t.zero\t" - const char *ZeroDirectiveSuffix; // Defaults to "" /// AsciiDirective - This directive allows emission of an ascii string with /// the standard C escape characters embedded into it. @@ -183,15 +191,10 @@ namespace llvm { /// the assembler to set the value of a variable to some expression. const char *SetDirective; // Defaults to null. - /// LCOMMDirective - This is the name of a directive (if supported) that can - /// be used to efficiently declare a local (internal) block of zero - /// initialized data in the .bss/.data section. The syntax expected is: - /// @verbatim <LCOMMDirective> SYMBOLNAME LENGTHINBYTES, ALIGNMENT - /// @endverbatim - const char *LCOMMDirective; // Defaults to null. + /// HasLCOMMDirective - This is true if the target supports the .lcomm + /// directive. + bool HasLCOMMDirective; // Defaults to false. - const char *COMMDirective; // Defaults to "\t.comm\t". - /// COMMDirectiveTakesAlignment - True if COMMDirective take a third /// argument that specifies the alignment of the declaration. bool COMMDirectiveTakesAlignment; // Defaults to true. @@ -204,10 +207,9 @@ namespace llvm { /// .file directive, this is true for ELF targets. bool HasSingleParameterDotFile; // Defaults to true. - /// UsedDirective - This directive, if non-null, is used to declare a global - /// as being used somehow that the assembler can't see. This prevents dead - /// code elimination on some targets. - const char *UsedDirective; // Defaults to NULL. + /// HasNoDeadStrip - True if this target supports the MachO .no_dead_strip + /// directive. + bool HasNoDeadStrip; // Defaults to false. /// WeakRefDirective - This directive, if non-null, is used to declare a /// global as being a weak undefined symbol. @@ -216,14 +218,18 @@ namespace llvm { /// WeakDefDirective - This directive, if non-null, is used to declare a /// global as being a weak defined symbol. const char *WeakDefDirective; // Defaults to NULL. + + /// LinkOnceDirective - This directive, if non-null is used to declare a + /// global as being a weak defined symbol. This is used on cygwin/mingw. + const char *LinkOnceDirective; // Defaults to NULL. - /// HiddenDirective - This directive, if non-null, is used to declare a - /// global or function as having hidden visibility. - const char *HiddenDirective; // Defaults to "\t.hidden\t". + /// HiddenVisibilityAttr - This attribute, if not MCSA_Invalid, is used to + /// declare a symbol as having hidden visibility. + MCSymbolAttr HiddenVisibilityAttr; // Defaults to MCSA_Hidden. - /// ProtectedDirective - This directive, if non-null, is used to declare a - /// global or function as having protected visibility. - const char *ProtectedDirective; // Defaults to "\t.protected\t". + /// ProtectedVisibilityAttr - This attribute, if not MCSA_Invalid, is used + /// to declare a symbol as having protected visibility. + MCSymbolAttr ProtectedVisibilityAttr; // Defaults to MCSA_Protected //===--- Dwarf Emission Directives -----------------------------------===// @@ -279,14 +285,12 @@ namespace llvm { explicit MCAsmInfo(); virtual ~MCAsmInfo(); - /// getSLEB128Size - Compute the number of bytes required for a signed - /// leb128 value. + // FIXME: move these methods to DwarfPrinter when the JIT stops using them. static unsigned getSLEB128Size(int Value); - - /// getULEB128Size - Compute the number of bytes required for an unsigned - /// leb128 value. static unsigned getULEB128Size(unsigned Value); + bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } + // Data directive accessors. // const char *getData8bitsDirective(unsigned AS = 0) const { @@ -302,6 +306,12 @@ namespace llvm { return AS == 0 ? Data64bitsDirective : getDataASDirective(64, AS); } + /// getNonexecutableStackSection - Targets can implement this method to + /// specify a section to switch to if the translation unit doesn't have any + /// trampolines that require an executable stack. + virtual MCSection *getNonexecutableStackSection(MCContext &Ctx) const { + return 0; + } bool usesSunStyleELFSectionSwitchSyntax() const { return SunStyleELFSectionSwitchSyntax; @@ -313,11 +323,9 @@ namespace llvm { // Accessors. // - const char *getZeroFillDirective() const { - return ZeroFillDirective; - } - const char *getNonexecutableStackDirective() const { - return NonexecutableStackDirective; + bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } + bool hasStaticCtorDtorReferenceInStaticMode() const { + return HasStaticCtorDtorReferenceInStaticMode; } bool needsSet() const { return NeedsSet; @@ -364,9 +372,6 @@ namespace llvm { const char *getZeroDirective() const { return ZeroDirective; } - const char *getZeroDirectiveSuffix() const { - return ZeroDirectiveSuffix; - } const char *getAsciiDirective() const { return AsciiDirective; } @@ -394,35 +399,20 @@ namespace llvm { const char *getSetDirective() const { return SetDirective; } - const char *getLCOMMDirective() const { - return LCOMMDirective; - } - const char *getCOMMDirective() const { - return COMMDirective; - } + bool hasLCOMMDirective() const { return HasLCOMMDirective; } bool getCOMMDirectiveTakesAlignment() const { return COMMDirectiveTakesAlignment; } - bool hasDotTypeDotSizeDirective() const { - return HasDotTypeDotSizeDirective; - } - bool hasSingleParameterDotFile() const { - return HasSingleParameterDotFile; - } - const char *getUsedDirective() const { - return UsedDirective; - } - const char *getWeakRefDirective() const { - return WeakRefDirective; - } - const char *getWeakDefDirective() const { - return WeakDefDirective; - } - const char *getHiddenDirective() const { - return HiddenDirective; - } - const char *getProtectedDirective() const { - return ProtectedDirective; + bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} + bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } + bool hasNoDeadStrip() const { return HasNoDeadStrip; } + const char *getWeakRefDirective() const { return WeakRefDirective; } + const char *getWeakDefDirective() const { return WeakDefDirective; } + const char *getLinkOnceDirective() const { return LinkOnceDirective; } + + MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;} + MCSymbolAttr getProtectedVisibilityAttr() const { + return ProtectedVisibilityAttr; } bool isAbsoluteDebugSectionOffsets() const { return AbsoluteDebugSectionOffsets; diff --git a/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h new file mode 100644 index 0000000..57ce75d --- /dev/null +++ b/include/llvm/MC/MCDirectives.h @@ -0,0 +1,44 @@ +//===- MCDirectives.h - Enums for directives on various targets -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines various enums that represent target-specific directives. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCDIRECTIVES_H +#define LLVM_MC_MCDIRECTIVES_H + +namespace llvm { + +enum MCSymbolAttr { + MCSA_Invalid = 0, /// Not a valid directive. + + // Various directives in alphabetical order. + MCSA_Global, /// .globl + MCSA_Hidden, /// .hidden (ELF) + MCSA_IndirectSymbol, /// .indirect_symbol (MachO) + MCSA_Internal, /// .internal (ELF) + MCSA_LazyReference, /// .lazy_reference (MachO) + MCSA_Local, /// .local (ELF) + MCSA_NoDeadStrip, /// .no_dead_strip (MachO) + MCSA_PrivateExtern, /// .private_extern (MachO) + MCSA_Protected, /// .protected (ELF) + MCSA_Reference, /// .reference (MachO) + MCSA_Weak, /// .weak + MCSA_WeakDefinition, /// .weak_definition (MachO) + MCSA_WeakReference /// .weak_reference (MachO) +}; + +enum MCAssemblerFlag { + MCAF_SubsectionsViaSymbols /// .subsections_via_symbols (MachO) +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 13d40ec..73d5f8e 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -51,7 +51,7 @@ public: /// @name Utility Methods /// @{ - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; void dump() const; /// @} @@ -75,6 +75,11 @@ public: static bool classof(const MCExpr *) { return true; } }; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { + E.print(OS); + return OS; +} //// MCConstantExpr - Represent a constant integer expression. class MCConstantExpr : public MCExpr { diff --git a/include/llvm/MC/MCParser/AsmCond.h b/include/llvm/MC/MCParser/AsmCond.h new file mode 100644 index 0000000..92a115e --- /dev/null +++ b/include/llvm/MC/MCParser/AsmCond.h @@ -0,0 +1,40 @@ +//===- AsmCond.h - Assembly file conditional assembly ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ASMCOND_H +#define ASMCOND_H + +namespace llvm { + +/// AsmCond - Class to support conditional assembly +/// +/// The conditional assembly feature (.if, .else, .elseif and .endif) is +/// implemented with AsmCond that tells us what we are in the middle of +/// processing. Ignore can be either true or false. When true we are ignoring +/// the block of code in the middle of a conditional. + +class AsmCond { +public: + enum ConditionalAssemblyType { + NoCond, // no conditional is being processed + IfCond, // inside if conditional + ElseIfCond, // inside elseif conditional + ElseCond // inside else conditional + }; + + ConditionalAssemblyType TheCond; + bool CondMet; + bool Ignore; + + AsmCond() : TheCond(NoCond), CondMet(false), Ignore(false) {} +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h new file mode 100644 index 0000000..cf6eefb --- /dev/null +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -0,0 +1,72 @@ +//===- AsmLexer.h - Lexer for Assembly Files --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class declares the lexer for assembly files. +// +//===----------------------------------------------------------------------===// + +#ifndef ASMLEXER_H +#define ASMLEXER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/System/DataTypes.h" +#include <string> +#include <cassert> + +namespace llvm { +class MemoryBuffer; +class SMLoc; +class MCAsmInfo; + +/// AsmLexer - Lexer class for assembly files. +class AsmLexer : public MCAsmLexer { + const MCAsmInfo &MAI; + + const char *CurPtr; + const MemoryBuffer *CurBuf; + + const char *TokStart; + + void operator=(const AsmLexer&); // DO NOT IMPLEMENT + AsmLexer(const AsmLexer&); // DO NOT IMPLEMENT + +protected: + /// LexToken - Read the next token and return its code. + virtual AsmToken LexToken(); + +public: + AsmLexer(const MCAsmInfo &MAI); + ~AsmLexer(); + + void setBuffer(const MemoryBuffer *buf, const char *ptr = NULL); + + SMLoc getLoc() const; + + StringRef LexUntilEndOfStatement(); + + bool isAtStartOfComment(char Char); + + const MCAsmInfo &getMAI() const { return MAI; } + +private: + int getNextChar(); + AsmToken ReturnError(const char *Loc, const std::string &Msg); + + AsmToken LexIdentifier(); + AsmToken LexSlash(); + AsmToken LexLineComment(); + AsmToken LexDigit(); + AsmToken LexQuote(); +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCParser/AsmParser.h b/include/llvm/MC/MCParser/AsmParser.h new file mode 100644 index 0000000..f82584c --- /dev/null +++ b/include/llvm/MC/MCParser/AsmParser.h @@ -0,0 +1,178 @@ +//===- AsmParser.h - Parser for Assembly Files ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class declares the parser for assembly files. +// +//===----------------------------------------------------------------------===// + +#ifndef ASMPARSER_H +#define ASMPARSER_H + +#include <vector> +#include "llvm/MC/MCParser/AsmLexer.h" +#include "llvm/MC/MCParser/AsmCond.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/ADT/StringMap.h" + +namespace llvm { +class AsmCond; +class AsmToken; +class MCContext; +class MCExpr; +class MCInst; +class MCStreamer; +class MCAsmInfo; +class MCValue; +class SourceMgr; +class TargetAsmParser; +class Twine; + +class AsmParser : public MCAsmParser { +private: + AsmLexer Lexer; + MCContext &Ctx; + MCStreamer &Out; + SourceMgr &SrcMgr; + TargetAsmParser *TargetParser; + + /// This is the current buffer index we're lexing from as managed by the + /// SourceMgr object. + int CurBuffer; + + AsmCond TheCondState; + std::vector<AsmCond> TheCondStack; + + // FIXME: Figure out where this should leave, the code is a copy of that which + // is also used by TargetLoweringObjectFile. + mutable void *SectionUniquingMap; + + /// 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<bool(AsmParser::*)(StringRef, SMLoc)> DirectiveMap; +public: + AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, + const MCAsmInfo &_MAI); + ~AsmParser(); + + bool Run(); + + + void AddDirectiveHandler(StringRef Directive, + bool (AsmParser::*Handler)(StringRef, SMLoc)) { + DirectiveMap[Directive] = Handler; + } +public: + TargetAsmParser &getTargetParser() const { return *TargetParser; } + void setTargetParser(TargetAsmParser &P) { TargetParser = &P; } + + /// @name MCAsmParser Interface + /// { + + virtual MCAsmLexer &getLexer() { return Lexer; } + virtual MCContext &getContext() { return Ctx; } + virtual MCStreamer &getStreamer() { return Out; } + + virtual void Warning(SMLoc L, const Twine &Meg); + virtual bool Error(SMLoc L, const Twine &Msg); + + const AsmToken &Lex(); + + bool ParseExpression(const MCExpr *&Res); + virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc); + virtual bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc); + virtual bool ParseAbsoluteExpression(int64_t &Res); + + /// } + +private: + MCSymbol *CreateSymbol(StringRef Name); + + // FIXME: See comment on SectionUniquingMap. + const MCSection *getMachOSection(const StringRef &Segment, + const StringRef &Section, + unsigned TypeAndAttributes, + unsigned Reserved2, + SectionKind Kind) const; + + bool ParseStatement(); + + bool TokError(const char *Msg); + + void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type) const; + + /// EnterIncludeFile - Enter the specified file. This returns true on failure. + bool EnterIncludeFile(const std::string &Filename); + + bool ParseConditionalAssemblyDirectives(StringRef Directive, + SMLoc DirectiveLoc); + void EatToEndOfStatement(); + + bool ParseAssignment(const StringRef &Name); + + bool ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc); + bool ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc); + bool ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc); + + /// ParseIdentifier - Parse an identifier or string (as a quoted identifier) + /// and set \arg Res to the identifier contents. + bool ParseIdentifier(StringRef &Res); + + // Directive Parsing. + bool ParseDirectiveDarwinSection(); // Darwin specific ".section". + bool ParseDirectiveSectionSwitch(const char *Segment, const char *Section, + unsigned TAA = 0, unsigned ImplicitAlign = 0, + unsigned StubSize = 0); + bool ParseDirectiveAscii(bool ZeroTerminated); // ".ascii", ".asciiz" + bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ... + bool ParseDirectiveFill(); // ".fill" + bool ParseDirectiveSpace(); // ".space" + bool ParseDirectiveSet(); // ".set" + bool ParseDirectiveOrg(); // ".org" + // ".align{,32}", ".p2align{,w,l}" + bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize); + + /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which + /// accepts a single symbol (which should be a label or an external). + bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr); + bool ParseDirectiveDarwinSymbolDesc(); // Darwin specific ".desc" + bool ParseDirectiveDarwinLsym(); // Darwin specific ".lsym" + + bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm" + bool ParseDirectiveDarwinZerofill(); // Darwin specific ".zerofill" + + // Darwin specific ".subsections_via_symbols" + bool ParseDirectiveDarwinSubsectionsViaSymbols(); + // Darwin specific .dump and .load + bool ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump); + + bool ParseDirectiveAbort(); // ".abort" + bool ParseDirectiveInclude(); // ".include" + + bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if" + bool ParseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif" + bool ParseDirectiveElse(SMLoc DirectiveLoc); // ".else" + bool ParseDirectiveEndIf(SMLoc DirectiveLoc); // .endif + + bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc); // ".file" + bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc); // ".line" + bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc); // ".loc" + + /// ParseEscapedString - Parse the current token as a string which may include + /// escaped characters and return the string contents. + bool ParseEscapedString(std::string &Data); +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index e9a6e3f..043c363 100644 --- a/include/llvm/MC/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -12,11 +12,11 @@ #include "llvm/ADT/StringRef.h" #include "llvm/System/DataTypes.h" +#include "llvm/Support/SMLoc.h" namespace llvm { class MCAsmLexer; class MCInst; -class SMLoc; class Target; /// AsmToken - Target independent representation for an assembler token. @@ -33,6 +33,9 @@ public: // Integer values. Integer, + // Register values (stored in IntVal). Only used by TargetAsmLexer. + Register, + // No-value. EndOfStatement, Colon, @@ -96,6 +99,13 @@ public: assert(Kind == Integer && "This token isn't an integer!"); return IntVal; } + + /// getRegVal - Get the register number for the current token, which should + /// be a register. + unsigned getRegVal() const { + assert(Kind == Register && "This token isn't a register!"); + return static_cast<unsigned>(IntVal); + } }; /// MCAsmLexer - Generic assembler lexer interface, for use by target specific @@ -103,6 +113,10 @@ public: class MCAsmLexer { /// The current token, stored in the base class for faster access. AsmToken CurTok; + + /// The location and description of the current error + SMLoc ErrLoc; + std::string Err; MCAsmLexer(const MCAsmLexer &); // DO NOT IMPLEMENT void operator=(const MCAsmLexer &); // DO NOT IMPLEMENT @@ -110,7 +124,12 @@ protected: // Can only create subclasses. MCAsmLexer(); virtual AsmToken LexToken() = 0; - + + void SetError(const SMLoc &errLoc, const std::string &err) { + ErrLoc = errLoc; + Err = err; + } + public: virtual ~MCAsmLexer(); @@ -126,6 +145,16 @@ public: const AsmToken &getTok() { return CurTok; } + + /// getErrLoc - Get the current error location + const SMLoc &getErrLoc() { + return ErrLoc; + } + + /// getErr - Get the current error string + const std::string &getErr() { + return Err; + } /// getKind - Get the kind of current token. AsmToken::TokenKind getKind() const { return CurTok.getKind(); } diff --git a/include/llvm/MC/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index d530093..843c692 100644 --- a/include/llvm/MC/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -13,6 +13,7 @@ #include "llvm/System/DataTypes.h" namespace llvm { +class AsmToken; class MCAsmLexer; class MCContext; class MCExpr; @@ -50,20 +51,28 @@ public: /// clients. virtual bool Error(SMLoc L, const Twine &Msg) = 0; + /// Lex - Get the next AsmToken in the stream, possibly handling file + /// inclusion first. + virtual const AsmToken &Lex() = 0; + + /// getTok - Get the current AsmToken from the stream. + const AsmToken &getTok(); + /// ParseExpression - Parse an arbitrary expression. /// /// @param Res - The value of the expression. The result is undefined /// on error. /// @result - False on success. - virtual bool ParseExpression(const MCExpr *&Res) = 0; - + virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; + bool ParseExpression(const MCExpr *&Res); + /// ParseParenExpression - Parse an arbitrary expression, assuming that an /// initial '(' has already been consumed. /// /// @param Res - The value of the expression. The result is undefined /// on error. /// @result - False on success. - virtual bool ParseParenExpression(const MCExpr *&Res) = 0; + virtual bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; /// ParseAbsoluteExpression - Parse an expression which must evaluate to an /// absolute value. diff --git a/include/llvm/MC/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 7c2f5be..7c2f5be 100644 --- a/include/llvm/MC/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 4ec745f..2dccf5c 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -31,7 +31,7 @@ class MCSectionELF : public MCSection { unsigned Flags; /// IsExplicit - Indicates that this section comes from globals with an - /// explicit section specfied. + /// explicit section specified. bool IsExplicit; protected: @@ -47,8 +47,7 @@ public: /// ShouldOmitSectionDirective - Decides whether a '.section' directive /// should be printed before the section name - bool ShouldOmitSectionDirective(const char *Name, - const MCAsmInfo &MAI) const; + bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; /// ShouldPrintSectionType - Only prints the section type if supported bool ShouldPrintSectionType(unsigned Ty) const; diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 5febed7..2bcb594 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -15,6 +15,7 @@ #define LLVM_MC_MCSTREAMER_H #include "llvm/System/DataTypes.h" +#include "llvm/MC/MCDirectives.h" namespace llvm { class MCAsmInfo; @@ -26,7 +27,9 @@ namespace llvm { class MCSection; class MCSymbol; class StringRef; + class Twine; class raw_ostream; + class formatted_raw_ostream; /// MCStreamer - Streaming machine code generation interface. This interface /// is intended to provide a programatic interface that is very similar to the @@ -38,30 +41,6 @@ namespace llvm { /// a .s file, and implementations that write out .o files of various formats. /// class MCStreamer { - public: - enum SymbolAttr { - Global, /// .globl - Hidden, /// .hidden (ELF) - IndirectSymbol, /// .indirect_symbol (Apple) - Internal, /// .internal (ELF) - LazyReference, /// .lazy_reference (Apple) - NoDeadStrip, /// .no_dead_strip (Apple) - PrivateExtern, /// .private_extern (Apple) - Protected, /// .protected (ELF) - Reference, /// .reference (Apple) - Weak, /// .weak - WeakDefinition, /// .weak_definition (Apple) - WeakReference, /// .weak_reference (Apple) - - SymbolAttrFirst = Global, - SymbolAttrLast = WeakReference - }; - - enum AssemblerFlag { - SubsectionsViaSymbols /// .subsections_via_symbols (Apple) - }; - - private: MCContext &Context; MCStreamer(const MCStreamer&); // DO NOT IMPLEMENT @@ -79,6 +58,28 @@ namespace llvm { MCContext &getContext() const { return Context; } + /// @name Assembly File Formatting. + /// @{ + + /// AddComment - Add a comment that can be emitted to the generated .s + /// file if applicable as a QoI issue to make the output of the compiler + /// more readable. This only affects the MCAsmStreamer, and only when + /// verbose assembly output is enabled. + /// + /// If the comment includes embedded \n's, they will each get the comment + /// prefix as appropriate. The added comment should not end with a \n. + virtual void AddComment(const Twine &T) {} + + /// GetCommentOS - Return a raw_ostream that comments can be written to. + /// Unlike AddComment, you are required to terminate comments with \n if you + /// use this method. + virtual raw_ostream &GetCommentOS(); + + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. + virtual void AddBlankLine() {} + + /// @} + /// @name Symbol & Section Management /// @{ @@ -103,7 +104,7 @@ namespace llvm { virtual void EmitLabel(MCSymbol *Symbol) = 0; /// EmitAssemblerFlag - Note in the output the specified @param Flag - virtual void EmitAssemblerFlag(AssemblerFlag Flag) = 0; + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; /// EmitAssignment - Emit an assignment of @param Value to @param Symbol. /// @@ -120,7 +121,7 @@ namespace llvm { /// EmitSymbolAttribute - Add the given @param Attribute to @param Symbol. virtual void EmitSymbolAttribute(MCSymbol *Symbol, - SymbolAttr Attribute) = 0; + MCSymbolAttr Attribute) = 0; /// EmitSymbolDesc - Set the @param DescValue for the @param Symbol. /// @@ -128,15 +129,21 @@ namespace llvm { /// @param DescValue - The value to set into the n_desc field. virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; - /// EmitCommonSymbol - Emit a common or local common symbol. + /// EmitCommonSymbol - Emit a common symbol. /// /// @param Symbol - The common symbol to emit. /// @param Size - The size of the common symbol. /// @param ByteAlignment - The alignment of the symbol if - /// non-zero. This must be a power of 2 on some targets. - virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, + /// non-zero. This must be a power of 2. + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) = 0; + /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) = 0; + /// EmitZerofill - Emit a the zerofill section and an option symbol. /// /// @param Section - The zerofill section to create and or to put the symbol @@ -155,7 +162,7 @@ namespace llvm { /// /// This is used to implement assembler directives such as .byte, .ascii, /// etc. - virtual void EmitBytes(StringRef Data) = 0; + virtual void EmitBytes(StringRef Data, unsigned AddrSpace) = 0; /// EmitValue - Emit the expression @param Value into the output as a native /// integer of the given @param Size bytes. @@ -166,8 +173,25 @@ namespace llvm { /// @param Value - The value to emit. /// @param Size - The size of the integer (in bytes) to emit. This must /// match a native machine width. - virtual void EmitValue(const MCExpr *Value, unsigned Size) = 0; + virtual void EmitValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) = 0; + /// EmitIntValue - Special case of EmitValue that avoids the client having + /// to pass in a MCExpr for constant integers. + virtual void EmitIntValue(uint64_t Value, unsigned Size,unsigned AddrSpace); + + /// EmitFill - Emit NumBytes bytes worth of the value specified by + /// FillValue. This implements directives such as '.space'. + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, + unsigned AddrSpace); + + /// EmitZeros - Emit NumBytes worth of zeros. This is a convenience + /// function that just wraps EmitFill. + void EmitZeros(uint64_t NumBytes, unsigned AddrSpace) { + EmitFill(NumBytes, 0, AddrSpace); + } + + /// EmitValueToAlignment - Emit some number of copies of @param Value until /// the byte alignment @param ByteAlignment is reached. /// @@ -217,8 +241,9 @@ namespace llvm { /// createAsmStreamer - Create a machine code streamer which will print out /// assembly for the native target, suitable for compiling with a native /// assembler. - MCStreamer *createAsmStreamer(MCContext &Ctx, raw_ostream &OS, - const MCAsmInfo &MAI, + MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + const MCAsmInfo &MAI, bool isLittleEndian, + bool isVerboseAsm, MCInstPrinter *InstPrint = 0, MCCodeEmitter *CE = 0); diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index eb59453..e770604 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -19,14 +19,14 @@ #include "llvm/System/DataTypes.h" namespace llvm { - class MCAsmInfo; class MCExpr; class MCSection; class MCContext; class raw_ostream; /// MCSymbol - Instances of this class represent a symbol name in the MC file, - /// and MCSymbols are created and unique'd by the MCContext class. + /// and MCSymbols are created and unique'd by the MCContext class. MCSymbols + /// should only be constructed with valid names for the object file. /// /// If the symbol is defined/emitted into the current translation unit, the /// Section member is set to indicate what section it lives in. Otherwise, if @@ -53,7 +53,7 @@ namespace llvm { /// typically does not survive in the .o file's symbol table. Usually /// "Lfoo" or ".foo". unsigned IsTemporary : 1; - + private: // MCContext creates and uniques these. friend class MCContext; MCSymbol(StringRef _Name, bool _IsTemporary) @@ -132,17 +132,16 @@ namespace llvm { /// @} /// print - Print the value to the stream \arg OS. - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; /// dump - Print the value to stderr. void dump() const; - - /// printMangledName - Print the specified string in mangled form if it uses - /// any unusual characters. - static void printMangledName(StringRef Str, raw_ostream &OS, - const MCAsmInfo *MAI); }; + inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { + Sym.print(OS); + return OS; + } } // end namespace llvm #endif diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index 4f5ab31..8aa73f3 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -20,6 +20,7 @@ namespace llvm { class MCSymbol; +class MCAsmInfo; class raw_ostream; /// MCValue - This represents an "assembler immediate". In its most general diff --git a/include/llvm/MC/SectionKind.h b/include/llvm/MC/SectionKind.h index 945cff7..c9557f2 100644 --- a/include/llvm/MC/SectionKind.h +++ b/include/llvm/MC/SectionKind.h @@ -87,6 +87,18 @@ class SectionKind { /// BSS - Zero initialized writeable data. BSS, + + /// BSSLocal - This is BSS (zero initialized and writable) data + /// which has local linkage. + BSSLocal, + + /// BSSExtern - This is BSS data with normal external linkage. + BSSExtern, + + /// Common - Data with common linkage. These represent tentative + /// definitions, which always have a zero initializer and are never + /// marked 'constant'. + Common, /// DataRel - This is the most general form of data that is written /// to by the program, it can have random relocations to arbitrary @@ -158,10 +170,14 @@ public: bool isThreadData() const { return K == ThreadData; } bool isGlobalWriteableData() const { - return isBSS() || isDataRel() || isReadOnlyWithRel(); + return isBSS() || isCommon() || isDataRel() || isReadOnlyWithRel(); } - bool isBSS() const { return K == BSS; } + bool isBSS() const { return K == BSS || K == BSSLocal || K == BSSExtern; } + bool isBSSLocal() const { return K == BSSLocal; } + bool isBSSExtern() const { return K == BSSExtern; } + + bool isCommon() const { return K == Common; } bool isDataRel() const { return K == DataRel || K == DataRelLocal || K == DataNoRel; @@ -207,6 +223,9 @@ public: static SectionKind getThreadBSS() { return get(ThreadBSS); } static SectionKind getThreadData() { return get(ThreadData); } static SectionKind getBSS() { return get(BSS); } + static SectionKind getBSSLocal() { return get(BSSLocal); } + static SectionKind getBSSExtern() { return get(BSSExtern); } + static SectionKind getCommon() { return get(Common); } static SectionKind getDataRel() { return get(DataRel); } static SectionKind getDataRelLocal() { return get(DataRelLocal); } static SectionKind getDataNoRel() { return get(DataNoRel); } diff --git a/include/llvm/Metadata.h b/include/llvm/Metadata.h index 179010b..f1e7a22 100644 --- a/include/llvm/Metadata.h +++ b/include/llvm/Metadata.h @@ -31,26 +31,10 @@ template<typename ValueSubClass, typename ItemParentClass> //===----------------------------------------------------------------------===// -// MetadataBase - A base class for MDNode and MDString. -class MetadataBase : public Value { -protected: - MetadataBase(const Type *Ty, unsigned scid) - : Value(Ty, scid) {} - -public: - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const MetadataBase *) { return true; } - static bool classof(const Value *V) { - return V->getValueID() == MDStringVal || V->getValueID() == MDNodeVal; - } -}; - -//===----------------------------------------------------------------------===// /// MDString - a single uniqued string. /// These are used to efficiently contain a byte sequence for metadata. /// MDString is always unnamd. -class MDString : public MetadataBase { +class MDString : public Value { MDString(const MDString &); // DO NOT IMPLEMENT StringRef Str; @@ -87,7 +71,7 @@ class MDNodeOperand; //===----------------------------------------------------------------------===// /// MDNode - a tuple of other values. -class MDNode : public MetadataBase, public FoldingSetNode { +class MDNode : public Value, public FoldingSetNode { MDNode(const MDNode &); // DO NOT IMPLEMENT void operator=(const MDNode &); // DO NOT IMPLEMENT friend class MDNodeOperand; @@ -154,8 +138,9 @@ public: // getFunction - If this metadata is function-local and recursively has a // function-local operand, return the first such operand's parent function. - // Otherwise, return null. - Function *getFunction() const; + // Otherwise, return null. getFunction() should not be used for performance- + // critical code because it recursively visits all the MDNode's operands. + const Function *getFunction() const; // destroy - Delete this node. Only when there are no uses. void destroy(); diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index f3e4dfd..ab08afb 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -64,6 +64,16 @@ enum PassManagerType { PMT_Last }; +// Different types of passes. +enum PassKind { + PT_BasicBlock, + PT_Loop, + PT_Function, + PT_CallGraphSCC, + PT_Module, + PT_PassManager +}; + //===----------------------------------------------------------------------===// /// Pass interface - Implemented by all 'passes'. Subclass this if you are an /// interprocedural optimization or you do not fit into any of the more @@ -72,19 +82,23 @@ enum PassManagerType { class Pass { AnalysisResolver *Resolver; // Used to resolve analysis intptr_t PassID; - + PassKind Kind; void operator=(const Pass&); // DO NOT IMPLEMENT Pass(const Pass &); // DO NOT IMPLEMENT public: - explicit Pass(intptr_t pid) : Resolver(0), PassID(pid) { + explicit Pass(PassKind K, intptr_t pid) : Resolver(0), PassID(pid), Kind(K) { assert(pid && "pid cannot be 0"); } - explicit Pass(const void *pid) : Resolver(0), PassID((intptr_t)pid) { + explicit Pass(PassKind K, const void *pid) + : Resolver(0), PassID((intptr_t)pid), Kind(K) { assert(pid && "pid cannot be 0"); } virtual ~Pass(); + + PassKind getPassKind() const { return Kind; } + /// getPassName - Return a nice clean name for a pass. This usually /// implemented in terms of the name that is registered by one of the /// Registration templates, but can be overloaded directly. @@ -118,7 +132,7 @@ public: // Access AnalysisResolver inline void setResolver(AnalysisResolver *AR) { - assert (!Resolver && "Resolver is already set"); + assert(!Resolver && "Resolver is already set"); Resolver = AR; } inline AnalysisResolver *getResolver() { @@ -145,6 +159,16 @@ public: /// virtual void releaseMemory(); + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it should + /// override this to adjust the this pointer as needed for the specified pass + /// info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + return this; + } + virtual ImmutablePass *getAsImmutablePass() { return 0; } + virtual PMDataManager *getAsPMDataManager() { return 0; } + /// verifyAnalysis() - This member can be implemented by a analysis pass to /// check state of analysis information. virtual void verifyAnalysis() const; @@ -219,8 +243,8 @@ public: /// Return what kind of Pass Manager can manage this pass. virtual PassManagerType getPotentialPassManagerType() const; - explicit ModulePass(intptr_t pid) : Pass(pid) {} - explicit ModulePass(const void *pid) : Pass(pid) {} + explicit ModulePass(intptr_t pid) : Pass(PT_Module, pid) {} + explicit ModulePass(const void *pid) : Pass(PT_Module, pid) {} // Force out-of-line virtual method. virtual ~ModulePass(); }; @@ -241,6 +265,8 @@ public: /// virtual void initializePass(); + virtual ImmutablePass *getAsImmutablePass() { return this; } + /// ImmutablePasses are never run. /// bool runOnModule(Module &) { return false; } @@ -264,8 +290,8 @@ public: /// class FunctionPass : public Pass { public: - explicit FunctionPass(intptr_t pid) : Pass(pid) {} - explicit FunctionPass(const void *pid) : Pass(pid) {} + explicit FunctionPass(intptr_t pid) : Pass(PT_Function, pid) {} + explicit FunctionPass(const void *pid) : Pass(PT_Function, pid) {} /// doInitialization - Virtual method overridden by subclasses to do /// any necessary per-module initialization. @@ -314,8 +340,8 @@ public: /// class BasicBlockPass : public Pass { public: - explicit BasicBlockPass(intptr_t pid) : Pass(pid) {} - explicit BasicBlockPass(const void *pid) : Pass(pid) {} + explicit BasicBlockPass(intptr_t pid) : Pass(PT_BasicBlock, pid) {} + explicit BasicBlockPass(const void *pid) : Pass(PT_BasicBlock, pid) {} /// doInitialization - Virtual method overridden by subclasses to do /// any necessary per-module initialization. diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h index 5864fad..d59be3c 100644 --- a/include/llvm/PassAnalysisSupport.h +++ b/include/llvm/PassAnalysisSupport.h @@ -19,15 +19,13 @@ #ifndef LLVM_PASS_ANALYSIS_SUPPORT_H #define LLVM_PASS_ANALYSIS_SUPPORT_H -#include <vector> #include "llvm/Pass.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include <vector> namespace llvm { -class StringRef; - //===----------------------------------------------------------------------===// // AnalysisUsage - Represent the analysis usage information of a pass. This // tracks analyses that the pass REQUIRES (must be available when the pass @@ -192,8 +190,15 @@ AnalysisType *Pass::getAnalysisIfAvailable() const { const PassInfo *PI = getClassPassInfo<AnalysisType>(); if (PI == 0) return 0; - return dynamic_cast<AnalysisType*> - (Resolver->getAnalysisIfAvailable(PI, true)); + + Pass *ResultPass = Resolver->getAnalysisIfAvailable(PI, true); + if (ResultPass == 0) return 0; + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially + // adjust the return pointer (because the class may multiply inherit, once + // from pass, once from AnalysisType). + return (AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI); } /// getAnalysis<AnalysisType>() - This function is used by subclasses to get @@ -202,8 +207,7 @@ AnalysisType *Pass::getAnalysisIfAvailable() const { /// template<typename AnalysisType> AnalysisType &Pass::getAnalysis() const { - assert(Resolver &&"Pass has not been inserted into a PassManager object!"); - + assert(Resolver && "Pass has not been inserted into a PassManager object!"); return getAnalysisID<AnalysisType>(getClassPassInfo<AnalysisType>()); } @@ -220,13 +224,10 @@ AnalysisType &Pass::getAnalysisID(const PassInfo *PI) const { "'required' by pass!"); // Because the AnalysisType may not be a subclass of pass (for - // AnalysisGroups), we must use dynamic_cast here to potentially adjust the - // return pointer (because the class may multiply inherit, once from pass, - // once from AnalysisType). - // - AnalysisType *Result = dynamic_cast<AnalysisType*>(ResultPass); - assert(Result && "Pass does not implement interface required!"); - return *Result; + // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially + // adjust the return pointer (because the class may multiply inherit, once + // from pass, once from AnalysisType). + return *(AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI); } /// getAnalysis<AnalysisType>() - This function is used by subclasses to get @@ -248,16 +249,13 @@ AnalysisType &Pass::getAnalysisID(const PassInfo *PI, Function &F) { // should be a small number, we just do a linear search over a (dense) // vector. Pass *ResultPass = Resolver->findImplPass(this, PI, F); - assert (ResultPass && "Unable to find requested analysis info"); + assert(ResultPass && "Unable to find requested analysis info"); // Because the AnalysisType may not be a subclass of pass (for - // AnalysisGroups), we must use dynamic_cast here to potentially adjust the - // return pointer (because the class may multiply inherit, once from pass, - // once from AnalysisType). - // - AnalysisType *Result = dynamic_cast<AnalysisType*>(ResultPass); - assert(Result && "Pass does not implement interface required!"); - return *Result; + // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially + // adjust the return pointer (because the class may multiply inherit, once + // from pass, once from AnalysisType). + return *(AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI); } } // End llvm namespace diff --git a/include/llvm/PassManagers.h b/include/llvm/PassManagers.h index dffc24a..443a9e0 100644 --- a/include/llvm/PassManagers.h +++ b/include/llvm/PassManagers.h @@ -273,6 +273,8 @@ public: } virtual ~PMDataManager(); + + virtual Pass *getAsPass() = 0; /// Augment AvailableAnalysis by adding analysis made available by pass P. void recordAvailableAnalysis(Pass *P); @@ -413,7 +415,6 @@ private: /// function. class FPPassManager : public ModulePass, public PMDataManager { - public: static char ID; explicit FPPassManager(int Depth) @@ -435,6 +436,9 @@ public: /// bool doFinalization(Module &M); + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + /// Pass Manager itself does not invalidate any analysis info. void getAnalysisUsage(AnalysisUsage &Info) const { Info.setPreservesAll(); diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h index d7f3097..b229989 100644 --- a/include/llvm/PassSupport.h +++ b/include/llvm/PassSupport.h @@ -82,6 +82,11 @@ public: /// TODO : Rename intptr_t getTypeInfo() const { return PassID; } + /// Return true if this PassID implements the specified ID pointer. + bool isPassID(void *IDPtr) const { + return PassID == (intptr_t)IDPtr; + } + /// isAnalysisGroup - Return true if this is an analysis group, not a normal /// pass. /// diff --git a/include/llvm/Support/CFG.h b/include/llvm/Support/CFG.h index 90b95bf..3875f0b 100644 --- a/include/llvm/Support/CFG.h +++ b/include/llvm/Support/CFG.h @@ -149,8 +149,8 @@ public: } inline bool operator>(const _Self& x) const { - return idx > x.idx; assert(Term == x.Term && "Cannot compare iterators of different blocks!"); + return idx > x.idx; } inline _Self& operator+=(int Right) { diff --git a/include/llvm/Support/DebugLoc.h b/include/llvm/Support/DebugLoc.h index 6814f63..32631fc 100644 --- a/include/llvm/Support/DebugLoc.h +++ b/include/llvm/Support/DebugLoc.h @@ -21,29 +21,6 @@ namespace llvm { class MDNode; - /// DebugLocTuple - Debug location tuple of filename id, line and column. - /// - struct DebugLocTuple { - MDNode *Scope; - MDNode *InlinedAtLoc; - unsigned Line, Col; - - DebugLocTuple() - : Scope(0), InlinedAtLoc(0), Line(~0U), Col(~0U) {} - - DebugLocTuple(MDNode *n, MDNode *i, unsigned l, unsigned c) - : Scope(n), InlinedAtLoc(i), Line(l), Col(c) {} - - bool operator==(const DebugLocTuple &DLT) const { - return Scope == DLT.Scope && - InlinedAtLoc == DLT.InlinedAtLoc && - Line == DLT.Line && Col == DLT.Col; - } - bool operator!=(const DebugLocTuple &DLT) const { - return !(*this == DLT); - } - }; - /// DebugLoc - Debug location id. This is carried by SDNode and MachineInstr /// to index into a vector of unique debug location tuples. class DebugLoc { @@ -65,40 +42,16 @@ namespace llvm { bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } }; - // Specialize DenseMapInfo for DebugLocTuple. - template<> struct DenseMapInfo<DebugLocTuple> { - static inline DebugLocTuple getEmptyKey() { - return DebugLocTuple(0, 0, ~0U, ~0U); - } - static inline DebugLocTuple getTombstoneKey() { - return DebugLocTuple((MDNode*)~1U, (MDNode*)~1U, ~1U, ~1U); - } - static unsigned getHashValue(const DebugLocTuple &Val) { - return DenseMapInfo<MDNode*>::getHashValue(Val.Scope) ^ - DenseMapInfo<MDNode*>::getHashValue(Val.InlinedAtLoc) ^ - DenseMapInfo<unsigned>::getHashValue(Val.Line) ^ - DenseMapInfo<unsigned>::getHashValue(Val.Col); - } - static bool isEqual(const DebugLocTuple &LHS, const DebugLocTuple &RHS) { - return LHS.Scope == RHS.Scope && - LHS.InlinedAtLoc == RHS.InlinedAtLoc && - LHS.Line == RHS.Line && - LHS.Col == RHS.Col; - } - }; - template <> struct isPodLike<DebugLocTuple> {static const bool value = true;}; - - - /// DebugLocTracker - This class tracks debug location information. + /// DebugLocTracker - This class tracks debug location information. /// struct DebugLocTracker { /// DebugLocations - A vector of unique DebugLocTuple's. /// - std::vector<DebugLocTuple> DebugLocations; + std::vector<MDNode *> DebugLocations; /// DebugIdMap - This maps DebugLocTuple's to indices into the /// DebugLocations vector. - DenseMap<DebugLocTuple, unsigned> DebugIdMap; + DenseMap<MDNode *, unsigned> DebugIdMap; DebugLocTracker() {} }; diff --git a/include/llvm/Support/Mangler.h b/include/llvm/Support/Mangler.h deleted file mode 100644 index aa230d4..0000000 --- a/include/llvm/Support/Mangler.h +++ /dev/null @@ -1,142 +0,0 @@ -//===-- llvm/Support/Mangler.h - Self-contained name mangler ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Unified name mangler for various backends. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_MANGLER_H -#define LLVM_SUPPORT_MANGLER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" -#include <string> - -namespace llvm { -class Twine; -class Type; -class Module; -class Value; -class GlobalValue; -template <typename T> class SmallVectorImpl; - -class Mangler { -public: - enum ManglerPrefixTy { - Default, ///< Emit default string before each symbol. - Private, ///< Emit "private" prefix before each symbol. - LinkerPrivate ///< Emit "linker private" prefix before each symbol. - }; - -private: - /// Prefix - This string is added to each symbol that is emitted, unless the - /// symbol is marked as not needing this prefix. - const char *Prefix; - - /// PrivatePrefix - This string is emitted before each symbol with private - /// linkage. - const char *PrivatePrefix; - - /// LinkerPrivatePrefix - This string is emitted before each symbol with - /// "linker_private" linkage. - const char *LinkerPrivatePrefix; - - /// UseQuotes - If this is set, the target accepts global names in quotes, - /// e.g. "foo bar" is a legal name. This syntax is used instead of escaping - /// the space character. By default, this is false. - bool UseQuotes; - - /// SymbolsCanStartWithDigit - If this is set, the target allows symbols to - /// start with digits (e.g., "0x0021"). By default, this is false. - bool SymbolsCanStartWithDigit; - - /// AnonGlobalIDs - We need to give global values the same name every time - /// they are mangled. This keeps track of the number we give to anonymous - /// ones. - /// - DenseMap<const GlobalValue*, unsigned> AnonGlobalIDs; - - /// NextAnonGlobalID - This simple counter is used to unique value names. - /// - unsigned NextAnonGlobalID; - - /// AcceptableChars - This bitfield contains a one for each character that is - /// allowed to be part of an unmangled name. - unsigned AcceptableChars[256 / 32]; - -public: - // Mangler ctor - if a prefix is specified, it will be prepended onto all - // symbols. - Mangler(Module &M, const char *Prefix = "", const char *privatePrefix = "", - const char *linkerPrivatePrefix = ""); - - /// setUseQuotes - If UseQuotes is set to true, this target accepts quoted - /// strings for assembler labels. - void setUseQuotes(bool Val) { UseQuotes = Val; } - - /// setSymbolsCanStartWithDigit - If SymbolsCanStartWithDigit is set to true, - /// this target allows symbols to start with digits. - void setSymbolsCanStartWithDigit(bool Val) { SymbolsCanStartWithDigit = Val; } - - /// Acceptable Characters - This allows the target to specify which characters - /// are acceptable to the assembler without being mangled. By default we - /// allow letters, numbers, '_', '$', '.', which is what GAS accepts, and '@'. - void markCharAcceptable(unsigned char X) { - AcceptableChars[X/32] |= 1 << (X&31); - } - void markCharUnacceptable(unsigned char X) { - AcceptableChars[X/32] &= ~(1 << (X&31)); - } - bool isCharAcceptable(unsigned char X) const { - return (AcceptableChars[X/32] & (1 << (X&31))) != 0; - } - - /// getMangledName - Returns the mangled name of V, an LLVM Value, - /// in the current module. If 'Suffix' is specified, the name ends with the - /// specified suffix. If 'ForcePrivate' is specified, the label is specified - /// to have a private label prefix. - /// - /// FIXME: This is deprecated, new code should use getNameWithPrefix and use - /// MCSymbol printing to handle quotes or not etc. - /// - std::string getMangledName(const GlobalValue *V, const char *Suffix = "", - bool ForcePrivate = false); - - /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix - /// and the specified global variable's name. If the global variable doesn't - /// have a name, this fills in a unique name for the global. - void getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV, - bool isImplicitlyPrivate); - - /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix - /// and the specified name as the global variable name. GVName must not be - /// empty. - void getNameWithPrefix(SmallVectorImpl<char> &OutName, const Twine &GVName, - ManglerPrefixTy PrefixTy = Mangler::Default); - -private: - /// makeNameProper - We don't want identifier names with ., space, or - /// - in them, so we mangle these characters into the strings "d_", - /// "s_", and "D_", respectively. This is a very simple mangling that - /// doesn't guarantee unique names for values. getValueName already - /// does this for you, so there's no point calling it on the result - /// from getValueName. - /// - /// FIXME: This is deprecated, new code should use getNameWithPrefix and use - /// MCSymbol printing to handle quotes or not etc. - /// - void makeNameProper(SmallVectorImpl<char> &OutName, - const Twine &Name, - ManglerPrefixTy PrefixTy = Mangler::Default); - -}; - -} // End llvm namespace - -#endif // LLVM_SUPPORT_MANGLER_H diff --git a/include/llvm/Support/PassNameParser.h b/include/llvm/Support/PassNameParser.h index ea4fe01..cdca978 100644 --- a/include/llvm/Support/PassNameParser.h +++ b/include/llvm/Support/PassNameParser.h @@ -41,7 +41,9 @@ class PassNameParser : public PassRegistrationListener, cl::Option *Opt; public: PassNameParser() : Opt(0) {} - + virtual ~PassNameParser(); + + void initialize(cl::Option &O) { Opt = &O; cl::parser<const PassInfo*>::initialize(O); diff --git a/include/llvm/Support/SMLoc.h b/include/llvm/Support/SMLoc.h new file mode 100644 index 0000000..967bf14 --- /dev/null +++ b/include/llvm/Support/SMLoc.h @@ -0,0 +1,44 @@ +//===- SMLoc.h - Source location for use with diagnostics -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SMLoc class. This class encapsulates a location in +// source code for use in diagnostics. +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_SMLOC_H +#define SUPPORT_SMLOC_H + +namespace llvm { + +// SMLoc - Represents a location in source code. +class SMLoc { + const char *Ptr; +public: + SMLoc() : Ptr(0) {} + SMLoc(const SMLoc &RHS) : Ptr(RHS.Ptr) {} + + bool isValid() const { return Ptr != 0; } + + bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; } + bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; } + + const char *getPointer() const { return Ptr; } + + static SMLoc getFromPointer(const char *Ptr) { + SMLoc L; + L.Ptr = Ptr; + return L; + } +}; + +} + +#endif + diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index b695ff1..5433a00 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file declares the SMLoc, SMDiagnostic and SourceMgr classes. This +// This file declares the SMDiagnostic and SourceMgr classes. This // provides a simple substrate for diagnostics, #include handling, and other low // level things for simple parsers. // @@ -16,6 +16,8 @@ #ifndef SUPPORT_SOURCEMGR_H #define SUPPORT_SOURCEMGR_H +#include "llvm/Support/SMLoc.h" + #include <string> #include <vector> #include <cassert> @@ -25,26 +27,6 @@ namespace llvm { class SourceMgr; class SMDiagnostic; class raw_ostream; - -class SMLoc { - const char *Ptr; -public: - SMLoc() : Ptr(0) {} - SMLoc(const SMLoc &RHS) : Ptr(RHS.Ptr) {} - - bool isValid() const { return Ptr != 0; } - - bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; } - bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; } - - const char *getPointer() const { return Ptr; } - - static SMLoc getFromPointer(const char *Ptr) { - SMLoc L; - L.Ptr = Ptr; - return L; - } -}; /// SourceMgr - This owns the files read by a parser, handles include stacks, /// and handles diagnostic wrangling. diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index d3c45c2..0f227cc 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -456,6 +456,11 @@ public: explicit raw_svector_ostream(SmallVectorImpl<char> &O); ~raw_svector_ostream(); + /// resync - This is called when the SmallVector we're appending to is changed + /// outside of the raw_svector_ostream's control. It is only safe to do this + /// if the raw_svector_ostream has previously been flushed. + void resync(); + /// str - Flushes the stream contents to the target vector and return a /// StringRef for the vector contents. StringRef str(); diff --git a/include/llvm/System/Host.h b/include/llvm/System/Host.h index 6de1a4a..4fbf5c1 100644 --- a/include/llvm/System/Host.h +++ b/include/llvm/System/Host.h @@ -14,6 +14,7 @@ #ifndef LLVM_SYSTEM_HOST_H #define LLVM_SYSTEM_HOST_H +#include "llvm/ADT/StringMap.h" #include <string> namespace llvm { @@ -47,6 +48,18 @@ namespace sys { /// /// \return - The host CPU name, or empty if the CPU could not be determined. std::string getHostCPUName(); + + /// getHostCPUFeatures - Get the LLVM names for the host CPU features. + /// The particular format of the names are target dependent, and suitable for + /// passing as -mattr to the target which matches the host. + /// + /// \param Features - A string mapping feature names to either + /// true (if enabled) or false (if disabled). This routine makes no guarantees + /// about exactly which features may appear in this map, except that they are + /// all valid LLVM feature names. + /// + /// \return - True on success. + bool getHostCPUFeatures(StringMap<bool> &Features); } } diff --git a/include/llvm/Target/Mangler.h b/include/llvm/Target/Mangler.h new file mode 100644 index 0000000..04de4e9 --- /dev/null +++ b/include/llvm/Target/Mangler.h @@ -0,0 +1,75 @@ +//===-- llvm/Support/Mangler.h - Self-contained name mangler ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Unified name mangler for various backends. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MANGLER_H +#define LLVM_SUPPORT_MANGLER_H + +#include "llvm/ADT/DenseMap.h" +#include <string> + +namespace llvm { +class StringRef; +class Twine; +class Value; +class GlobalValue; +template <typename T> class SmallVectorImpl; +class MCAsmInfo; + +class Mangler { +public: + enum ManglerPrefixTy { + Default, ///< Emit default string before each symbol. + Private, ///< Emit "private" prefix before each symbol. + LinkerPrivate ///< Emit "linker private" prefix before each symbol. + }; + +private: + const MCAsmInfo &MAI; + + /// AnonGlobalIDs - We need to give global values the same name every time + /// they are mangled. This keeps track of the number we give to anonymous + /// ones. + /// + DenseMap<const GlobalValue*, unsigned> AnonGlobalIDs; + + /// NextAnonGlobalID - This simple counter is used to unique value names. + /// + unsigned NextAnonGlobalID; + +public: + // Mangler ctor - if a prefix is specified, it will be prepended onto all + // symbols. + Mangler(const MCAsmInfo &mai) : MAI(mai), NextAnonGlobalID(1) {} + + /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix + /// and the specified global variable's name. If the global variable doesn't + /// have a name, this fills in a unique name for the global. + void getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV, + bool isImplicitlyPrivate); + + /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix + /// and the specified name as the global variable name. GVName must not be + /// empty. + void getNameWithPrefix(SmallVectorImpl<char> &OutName, const Twine &GVName, + ManglerPrefixTy PrefixTy = Mangler::Default); + + /// getNameWithPrefix - Return the name of the appropriate prefix + /// and the specified global variable's name. If the global variable doesn't + /// have a name, this fills in a unique name for the global. + std::string getNameWithPrefix(const GlobalValue *GV, + bool isImplicitlyPrivate = false); +}; + +} // End llvm namespace + +#endif // LLVM_SUPPORT_MANGLER_H diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 206e42e..354e743 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -479,7 +479,7 @@ def COPY_TO_REGCLASS : Instruction { } def DEBUG_VALUE : Instruction { let OutOperandList = (ops); - let InOperandList = (ops unknown:$value, i64imm:$offset, unknown:$meta); + let InOperandList = (ops variable_ops); let AsmString = "DEBUG_VALUE"; let Namespace = "TargetInstrInfo"; let isAsCheapAsAMove = 1; diff --git a/include/llvm/Target/TargetAsmLexer.h b/include/llvm/Target/TargetAsmLexer.h new file mode 100644 index 0000000..daba1ba --- /dev/null +++ b/include/llvm/Target/TargetAsmLexer.h @@ -0,0 +1,79 @@ +//===-- llvm/Target/TargetAsmLexer.h - Target Assembly Lexer ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETASMLEXER_H +#define LLVM_TARGET_TARGETASMLEXER_H + +#include "llvm/MC/MCParser/MCAsmLexer.h" + +namespace llvm { +class Target; + +/// TargetAsmLexer - Generic interface to target specific assembly lexers. +class TargetAsmLexer { + /// The current token + AsmToken CurTok; + + /// The location and description of the current error + SMLoc ErrLoc; + std::string Err; + + TargetAsmLexer(const TargetAsmLexer &); // DO NOT IMPLEMENT + void operator=(const TargetAsmLexer &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + TargetAsmLexer(const Target &); + + virtual AsmToken LexToken() = 0; + + void SetError(const SMLoc &errLoc, const std::string &err) { + ErrLoc = errLoc; + Err = err; + } + + /// TheTarget - The Target that this machine was created for. + const Target &TheTarget; + +public: + virtual ~TargetAsmLexer(); + + const Target &getTarget() const { return TheTarget; } + + /// Lex - Consume the next token from the input stream and return it. + const AsmToken &Lex() { + return CurTok = LexToken(); + } + + /// getTok - Get the current (last) lexed token. + const AsmToken &getTok() { + return CurTok; + } + + /// getErrLoc - Get the current error location + const SMLoc &getErrLoc() { + return ErrLoc; + } + + /// getErr - Get the current error string + const std::string &getErr() { + return Err; + } + + /// getKind - Get the kind of current token. + AsmToken::TokenKind getKind() const { return CurTok.getKind(); } + + /// is - Check if the current token has kind \arg K. + bool is(AsmToken::TokenKind K) const { return CurTok.is(K); } + + /// isNot - Check if the current token has kind \arg K. + bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetAsmParser.h b/include/llvm/Target/TargetAsmParser.h index 1d3da8b..da9ba2b 100644 --- a/include/llvm/Target/TargetAsmParser.h +++ b/include/llvm/Target/TargetAsmParser.h @@ -11,7 +11,6 @@ #define LLVM_TARGET_TARGETPARSER_H namespace llvm { -class MCAsmParser; class MCInst; class StringRef; class Target; diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 8e2157e..7144fe0 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -486,6 +486,30 @@ public: unsigned *LoadRegIndex = 0) const { return 0; } + + /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler + /// to determine if two loads are loading from the same base address. It + /// should only return true if the base pointers are the same and the + /// only differences between the two addresses are the offset. It also returns + /// the offsets by reference. + virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, + int64_t &Offset1, int64_t &Offset2) const { + return false; + } + + /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to + /// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should + /// be scheduled togther. On some targets if two loads are loading from + /// addresses in the same cache line, it's better if they are scheduled + /// together. This function takes two integers that represent the load offsets + /// from the common base address. It returns true if it decides it's desirable + /// to schedule the two loads together. "NumLoads" is the number of loads that + /// have already been scheduled after Load1. + virtual bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, + int64_t Offset1, int64_t Offset2, + unsigned NumLoads) const { + return false; + } /// ReverseBranchCondition - Reverses the branch condition of the specified /// condition list, returning false on success and true if it cannot be diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 3dd7471..d3e5cf2 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -258,6 +258,8 @@ class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { const MCSection *ConstDataCoalSection; const MCSection *ConstDataSection; const MCSection *DataCoalSection; + const MCSection *DataCommonSection; + const MCSection *DataBSSSection; const MCSection *FourByteConstantSection; const MCSection *EightByteConstantSection; const MCSection *SixteenByteConstantSection; diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 84cd5b4..4db3d3e 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -81,6 +81,14 @@ namespace CodeGenOpt { }; } +// Specify if we should encode the LSDA pointer in the FDE as 4- or 8-bytes. +namespace DwarfLSDAEncoding { + enum Encoding { + Default, + FourByte, + EightByte + }; +} //===----------------------------------------------------------------------===// /// @@ -129,10 +137,7 @@ public: /// TargetSubtarget. In debug builds, it verifies that the object being /// returned is of the correct type. template<typename STC> const STC &getSubtarget() const { - const TargetSubtarget *TST = getSubtargetImpl(); - assert(TST && dynamic_cast<const STC*>(TST) && - "Not the right kind of subtarget!"); - return *static_cast<const STC*>(TST); + return *static_cast<const STC*>(getSubtargetImpl()); } /// getRegisterInfo - If register information is available, return it. If @@ -192,6 +197,20 @@ public: /// is false. static void setAsmVerbosityDefault(bool); + /// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are + /// 4-byte, 8-byte, and target default. The CIE is hard-coded to indicate that + /// the LSDA pointer in the FDE section is an "sdata4", and should be encoded + /// as a 4-byte pointer by default. However, some systems may require a + /// different size due to bugs or other conditions. We will default to a + /// 4-byte encoding unless the system tells us otherwise. + /// + /// FIXME: This call-back isn't good! We should be using the correct encoding + /// regardless of the system. However, there are some systems which have bugs + /// that prevent this from occuring. + virtual DwarfLSDAEncoding::Encoding getLSDAEncoding() const { + return DwarfLSDAEncoding::Default; + } + /// CodeGenFileType - These enums are meant to be passed into /// addPassesToEmitFile to indicate what type of file to emit. enum CodeGenFileType { @@ -452,6 +471,14 @@ public: bool addAssemblyEmitter(PassManagerBase &, CodeGenOpt::Level, bool /* VerboseAsmDefault */, formatted_raw_ostream &); + + /// addObjectFileEmitter - Helper function which creates a target specific + /// object files emitter, if available. This interface is temporary, for + /// bringing up MCAssembler-based object file emitters. + /// + /// \return Returns 'false' on success. + bool addObjectFileEmitter(PassManagerBase &, CodeGenOpt::Level, + formatted_raw_ostream &); }; } // End llvm namespace diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index 167e1d1..d3aa867 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -31,6 +31,7 @@ namespace llvm { class MCAsmInfo; class MCDisassembler; class MCInstPrinter; + class TargetAsmLexer; class TargetAsmParser; class TargetMachine; class formatted_raw_ostream; @@ -59,8 +60,9 @@ namespace llvm { TargetMachine &TM, const MCAsmInfo *MAI, bool VerboseAsm); - typedef TargetAsmParser *(*AsmParserCtorTy)(const Target &T, - MCAsmParser &P); + typedef TargetAsmLexer *(*AsmLexerCtorTy)(const Target &T, + const MCAsmInfo &MAI); + typedef TargetAsmParser *(*AsmParserCtorTy)(const Target &T,MCAsmParser &P); typedef const MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T); typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, unsigned SyntaxVariant, @@ -97,8 +99,12 @@ namespace llvm { /// if registered. AsmPrinterCtorTy AsmPrinterCtorFn; - /// AsmParserCtorFn - Construction function for this target's AsmParser, + /// AsmLexerCtorFn - Construction function for this target's TargetAsmLexer, /// if registered. + AsmLexerCtorTy AsmLexerCtorFn; + + /// AsmParserCtorFn - Construction function for this target's + /// TargetAsmParser, if registered. AsmParserCtorTy AsmParserCtorFn; /// MCDisassemblerCtorFn - Construction function for this target's @@ -191,6 +197,14 @@ namespace llvm { return AsmPrinterCtorFn(OS, TM, MAI, Verbose); } + /// createAsmLexer - Create a target specific assembly lexer. + /// + TargetAsmLexer *createAsmLexer(const MCAsmInfo &MAI) const { + if (!AsmLexerCtorFn) + return 0; + return AsmLexerCtorFn(*this, MAI); + } + /// createAsmParser - Create a target specific assembly parser. /// /// \arg Parser - The target independent parser implementation to use for @@ -358,6 +372,20 @@ namespace llvm { T.AsmPrinterCtorFn = Fn; } + /// RegisterAsmLexer - Register a TargetAsmLexer implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmPrinter for the target. + static void RegisterAsmLexer(Target &T, Target::AsmLexerCtorTy Fn) { + if (!T.AsmLexerCtorFn) + T.AsmLexerCtorFn = Fn; + } + /// RegisterAsmParser - Register a TargetAsmParser implementation for the /// given target. /// @@ -524,6 +552,26 @@ namespace llvm { } }; + /// RegisterAsmLexer - Helper template for registering a target specific + /// assembly lexer, for use in the target machine initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooAsmLexer() { + /// extern Target TheFooTarget; + /// RegisterAsmLexer<FooAsmLexer> X(TheFooTarget); + /// } + template<class AsmLexerImpl> + struct RegisterAsmLexer { + RegisterAsmLexer(Target &T) { + TargetRegistry::RegisterAsmLexer(T, &Allocator); + } + + private: + static TargetAsmLexer *Allocator(const Target &T, const MCAsmInfo &MAI) { + return new AsmLexerImpl(T, MAI); + } + }; + /// RegisterAsmParser - Helper template for registering a target specific /// assembly parser, for use in the target machine initialization /// function. Usage: diff --git a/include/llvm/Transforms/IPO/InlinerPass.h b/include/llvm/Transforms/IPO/InlinerPass.h index 5d00f42..dc5e644 100644 --- a/include/llvm/Transforms/IPO/InlinerPass.h +++ b/include/llvm/Transforms/IPO/InlinerPass.h @@ -51,6 +51,12 @@ struct Inliner : public CallGraphSCCPass { /// unsigned getInlineThreshold() const { return InlineThreshold; } + /// Calculate the inline threshold for given Caller. This threshold is lower + /// if Caller is marked with OptimizeForSize and -inline-threshold is not + /// given on the comand line. + /// + unsigned getInlineThreshold(Function* Caller) const; + /// getInlineCost - This method must be implemented by the subclass to /// determine the cost of inlining the specified call site. If the cost /// returned is greater than the current inline threshold, the call site is diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index 0b8147e..f6d9f82 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -27,7 +27,6 @@ class PHINode; class AllocaInst; class ConstantExpr; class TargetData; -class DbgInfoIntrinsic; template<typename T> class SmallVectorImpl; @@ -154,12 +153,6 @@ AllocaInst *DemoteRegToStack(Instruction &X, /// The phi node is deleted and it returns the pointer to the alloca inserted. AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = 0); -/// OnlyUsedByDbgIntrinsics - Return true if the instruction I is only used -/// by DbgIntrinsics. If DbgInUses is specified then the vector is filled -/// with DbgInfoIntrinsic that use the instruction I. -bool OnlyUsedByDbgInfoIntrinsics(Instruction *I, - SmallVectorImpl<DbgInfoIntrinsic *> *DbgInUses = 0); - } // End llvm namespace #endif diff --git a/lib/Analysis/AliasAnalysisCounter.cpp b/lib/Analysis/AliasAnalysisCounter.cpp index ae28b55..761cd46 100644 --- a/lib/Analysis/AliasAnalysisCounter.cpp +++ b/lib/Analysis/AliasAnalysisCounter.cpp @@ -31,7 +31,6 @@ namespace { class AliasAnalysisCounter : public ModulePass, public AliasAnalysis { unsigned No, May, Must; unsigned NoMR, JustRef, JustMod, MR; - const char *Name; Module *M; public: static char ID; // Class identification, replacement for typeinfo @@ -49,7 +48,7 @@ namespace { unsigned MRSum = NoMR+JustRef+JustMod+MR; if (AASum + MRSum) { // Print a report if any counted queries occurred... errs() << "\n===== Alias Analysis Counter Report =====\n" - << " Analysis counted: " << Name << "\n" + << " Analysis counted:\n" << " " << AASum << " Total Alias Queries Performed\n"; if (AASum) { printLine("no alias", No, AASum); @@ -75,7 +74,6 @@ namespace { bool runOnModule(Module &M) { this->M = &M; InitializeAliasAnalysis(this); - Name = dynamic_cast<Pass*>(&getAnalysis<AliasAnalysis>())->getPassName(); return false; } @@ -85,6 +83,16 @@ namespace { AU.setPreservesAll(); } + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&AliasAnalysis::ID)) + return (AliasAnalysis*)this; + return this; + } + // FIXME: We could count these too... bool pointsToConstantMemory(const Value *P) { return getAnalysis<AliasAnalysis>().pointsToConstantMemory(P); diff --git a/lib/Analysis/AliasDebugger.cpp b/lib/Analysis/AliasDebugger.cpp index 6868e3f..88c2875 100644 --- a/lib/Analysis/AliasDebugger.cpp +++ b/lib/Analysis/AliasDebugger.cpp @@ -71,6 +71,16 @@ namespace { AU.setPreservesAll(); // Does not transform code } + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&AliasAnalysis::ID)) + return (AliasAnalysis*)this; + return this; + } + //------------------------------------------------ // Implement the AliasAnalysis API // diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index b2983c7..36b831c 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -153,6 +153,16 @@ namespace { virtual void deleteValue(Value *V) {} virtual void copyValue(Value *From, Value *To) {} + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it should + /// override this to adjust the this pointer as needed for the specified pass + /// info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&AliasAnalysis::ID)) + return (AliasAnalysis*)this; + return this; + } }; } // End of anonymous namespace @@ -192,6 +202,16 @@ namespace { /// global) or not. bool pointsToConstantMemory(const Value *P); + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it should + /// override this to adjust the this pointer as needed for the specified pass + /// info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&AliasAnalysis::ID)) + return (AliasAnalysis*)this; + return this; + } + private: // VisitedPHIs - Track PHI nodes visited by a aliasCheck() call. SmallPtrSet<const Value*, 16> VisitedPHIs; diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp index 59ba807..4ba837a 100644 --- a/lib/Analysis/DebugInfo.cpp +++ b/lib/Analysis/DebugInfo.cpp @@ -599,7 +599,7 @@ void DIVariable::dump() const { //===----------------------------------------------------------------------===// DIFactory::DIFactory(Module &m) - : M(m), VMContext(M.getContext()), DeclareFn(0) {} + : M(m), VMContext(M.getContext()), DeclareFn(0), ValueFn(0) {} Constant *DIFactory::GetTagConstant(unsigned TAG) { assert((TAG & LLVMDebugVersionMask) == 0 && @@ -854,7 +854,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context, StringRef DisplayName, StringRef LinkageName, DICompileUnit CompileUnit, - unsigned LineNo, DIType Type, + unsigned LineNo, DIType Ty, bool isLocalToUnit, bool isDefinition, unsigned VK, unsigned VIndex, @@ -869,7 +869,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context, MDString::get(VMContext, LinkageName), CompileUnit.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Type.getNode(), + Ty.getNode(), ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK), @@ -911,7 +911,7 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, StringRef DisplayName, StringRef LinkageName, DICompileUnit CompileUnit, - unsigned LineNo, DIType Type,bool isLocalToUnit, + unsigned LineNo, DIType Ty,bool isLocalToUnit, bool isDefinition, llvm::GlobalVariable *Val) { Value *Elts[] = { GetTagConstant(dwarf::DW_TAG_variable), @@ -922,7 +922,7 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, MDString::get(VMContext, LinkageName), CompileUnit.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Type.getNode(), + Ty.getNode(), ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), Val @@ -943,14 +943,14 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context, StringRef Name, DICompileUnit CompileUnit, unsigned LineNo, - DIType Type) { + DIType Ty) { Value *Elts[] = { GetTagConstant(Tag), Context.getNode(), MDString::get(VMContext, Name), CompileUnit.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Type.getNode(), + Ty.getNode(), }; return DIVariable(MDNode::get(VMContext, &Elts[0], 6)); } @@ -962,14 +962,15 @@ DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context, const std::string &Name, DICompileUnit CompileUnit, unsigned LineNo, - DIType Type, SmallVector<Value *, 9> &addr) { + DIType Ty, + SmallVector<Value *, 9> &addr) { SmallVector<Value *, 9> Elts; Elts.push_back(GetTagConstant(Tag)); Elts.push_back(Context.getNode()); Elts.push_back(MDString::get(VMContext, Name)); Elts.push_back(CompileUnit.getNode()); Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)); - Elts.push_back(Type.getNode()); + Elts.push_back(Ty.getNode()); Elts.insert(Elts.end(), addr.begin(), addr.end()); return DIVariable(MDNode::get(VMContext, &Elts[0], 6+addr.size())); @@ -1035,8 +1036,8 @@ Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D, if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - Value *Elts[] = { Storage }; - Value *Args[] = { MDNode::get(Storage->getContext(), Elts, 1), D.getNode() }; + Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), + D.getNode() }; return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore); } @@ -1046,8 +1047,8 @@ Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D, if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - Value *Elts[] = { Storage }; - Value *Args[] = { MDNode::get(Storage->getContext(), Elts, 1), D.getNode() }; + Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), + D.getNode() }; return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd); } @@ -1059,8 +1060,7 @@ Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - Value *Elts[] = { V }; - Value *Args[] = { MDNode::get(V->getContext(), Elts, 1), + Value *Args[] = { MDNode::get(V->getContext(), &V, 1), ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), D.getNode() }; return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore); @@ -1074,8 +1074,7 @@ Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - Value *Elts[] = { V }; - Value *Args[] = { MDNode::get(V->getContext(), Elts, 1), + Value *Args[] = { MDNode::get(V->getContext(), &V, 1), ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), D.getNode() }; return CallInst::Create(ValueFn, Args, Args+3, "", InsertAtEnd); @@ -1139,9 +1138,9 @@ void DebugInfoFinder::processType(DIType DT) { if (!DA.isNull()) for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { DIDescriptor D = DA.getElement(i); - DIType TypeE = DIType(D.getNode()); - if (!TypeE.isNull()) - processType(TypeE); + DIType TyE = DIType(D.getNode()); + if (!TyE.isNull()) + processType(TyE); else processSubprogram(DISubprogram(D.getNode())); } @@ -1234,7 +1233,8 @@ bool DebugInfoFinder::addSubprogram(DISubprogram SP) { return true; } -Value *llvm::findDbgGlobalDeclare(GlobalVariable *V) { +/// Find the debug info descriptor corresponding to this global variable. +static Value *findDbgGlobalDeclare(GlobalVariable *V) { const Module *M = V->getParent(); NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"); if (!NMD) @@ -1252,7 +1252,7 @@ Value *llvm::findDbgGlobalDeclare(GlobalVariable *V) { /// Finds the llvm.dbg.declare intrinsic corresponding to this value if any. /// It looks through pointer casts too. -const DbgDeclareInst *llvm::findDbgDeclare(const Value *V) { +static const DbgDeclareInst *findDbgDeclare(const Value *V) { V = V->stripPointerCasts(); if (!isa<Instruction>(V) && !isa<Argument>(V)) @@ -1320,23 +1320,15 @@ bool llvm::getLocationInfo(const Value *V, std::string &DisplayName, /// from DILocation. DebugLoc llvm::ExtractDebugLocation(DILocation &Loc, DebugLocTracker &DebugLocInfo) { - DebugLoc DL; - MDNode *Context = Loc.getScope().getNode(); - MDNode *InlinedLoc = NULL; - if (!Loc.getOrigLocation().isNull()) - InlinedLoc = Loc.getOrigLocation().getNode(); - // If this location is already tracked then use it. - DebugLocTuple Tuple(Context, InlinedLoc, Loc.getLineNumber(), - Loc.getColumnNumber()); - DenseMap<DebugLocTuple, unsigned>::iterator II - = DebugLocInfo.DebugIdMap.find(Tuple); + DenseMap<MDNode *, unsigned>::iterator II + = DebugLocInfo.DebugIdMap.find(Loc.getNode()); if (II != DebugLocInfo.DebugIdMap.end()) return DebugLoc::get(II->second); // Add a new location entry. unsigned Id = DebugLocInfo.DebugLocations.size(); - DebugLocInfo.DebugLocations.push_back(Tuple); - DebugLocInfo.DebugIdMap[Tuple] = Id; + DebugLocInfo.DebugLocations.push_back(Loc.getNode()); + DebugLocInfo.DebugIdMap[Loc.getNode()] = Id; return DebugLoc::get(Id); } diff --git a/lib/Analysis/DomPrinter.cpp b/lib/Analysis/DomPrinter.cpp index 32b8994..3af687a 100644 --- a/lib/Analysis/DomPrinter.cpp +++ b/lib/Analysis/DomPrinter.cpp @@ -19,10 +19,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/DomPrinter.h" -#include "llvm/Pass.h" -#include "llvm/Function.h" -#include "llvm/Analysis/CFGPrinter.h" + #include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/DOTGraphTraitsPass.h" #include "llvm/Analysis/PostDominators.h" using namespace llvm; @@ -110,29 +109,29 @@ struct GenericGraphViewer : public FunctionPass { }; struct DomViewer - : public GenericGraphViewer<DominatorTree, false> { + : public DOTGraphTraitsViewer<DominatorTree, false> { static char ID; - DomViewer() : GenericGraphViewer<DominatorTree, false>("dom", &ID){} + DomViewer() : DOTGraphTraitsViewer<DominatorTree, false>("dom", &ID){} }; struct DomOnlyViewer - : public GenericGraphViewer<DominatorTree, true> { + : public DOTGraphTraitsViewer<DominatorTree, true> { static char ID; - DomOnlyViewer() : GenericGraphViewer<DominatorTree, true>("domonly", &ID){} + DomOnlyViewer() : DOTGraphTraitsViewer<DominatorTree, true>("domonly", &ID){} }; struct PostDomViewer - : public GenericGraphViewer<PostDominatorTree, false> { + : public DOTGraphTraitsViewer<PostDominatorTree, false> { static char ID; PostDomViewer() : - GenericGraphViewer<PostDominatorTree, false>("postdom", &ID){} + DOTGraphTraitsViewer<PostDominatorTree, false>("postdom", &ID){} }; struct PostDomOnlyViewer - : public GenericGraphViewer<PostDominatorTree, true> { + : public DOTGraphTraitsViewer<PostDominatorTree, true> { static char ID; PostDomOnlyViewer() : - GenericGraphViewer<PostDominatorTree, true>("postdomonly", &ID){} + DOTGraphTraitsViewer<PostDominatorTree, true>("postdomonly", &ID){} }; } // end anonymous namespace @@ -155,67 +154,30 @@ RegisterPass<PostDomOnlyViewer> D("view-postdom-only", "(with no function bodies)"); namespace { -template <class Analysis, bool OnlyBBS> -struct GenericGraphPrinter : public FunctionPass { - - std::string Name; - - GenericGraphPrinter(std::string GraphName, const void *ID) - : FunctionPass(ID) { - Name = GraphName; - } - - virtual bool runOnFunction(Function &F) { - Analysis *Graph; - std::string Filename = Name + "." + F.getNameStr() + ".dot"; - errs() << "Writing '" << Filename << "'..."; - - std::string ErrorInfo; - raw_fd_ostream File(Filename.c_str(), ErrorInfo); - Graph = &getAnalysis<Analysis>(); - - std::string Title, GraphName; - GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); - Title = GraphName + " for '" + F.getNameStr() + "' function"; - - if (ErrorInfo.empty()) - WriteGraph(File, Graph, OnlyBBS, Name, Title); - else - errs() << " error opening file for writing!"; - errs() << "\n"; - return false; - } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<Analysis>(); - } -}; - struct DomPrinter - : public GenericGraphPrinter<DominatorTree, false> { + : public DOTGraphTraitsPrinter<DominatorTree, false> { static char ID; - DomPrinter() : GenericGraphPrinter<DominatorTree, false>("dom", &ID) {} + DomPrinter() : DOTGraphTraitsPrinter<DominatorTree, false>("dom", &ID) {} }; struct DomOnlyPrinter - : public GenericGraphPrinter<DominatorTree, true> { + : public DOTGraphTraitsPrinter<DominatorTree, true> { static char ID; - DomOnlyPrinter() : GenericGraphPrinter<DominatorTree, true>("domonly", &ID) {} + DomOnlyPrinter() : DOTGraphTraitsPrinter<DominatorTree, true>("domonly", &ID) {} }; struct PostDomPrinter - : public GenericGraphPrinter<PostDominatorTree, false> { + : public DOTGraphTraitsPrinter<PostDominatorTree, false> { static char ID; PostDomPrinter() : - GenericGraphPrinter<PostDominatorTree, false>("postdom", &ID) {} + DOTGraphTraitsPrinter<PostDominatorTree, false>("postdom", &ID) {} }; struct PostDomOnlyPrinter - : public GenericGraphPrinter<PostDominatorTree, true> { + : public DOTGraphTraitsPrinter<PostDominatorTree, true> { static char ID; PostDomOnlyPrinter() : - GenericGraphPrinter<PostDominatorTree, true>("postdomonly", &ID) {} + DOTGraphTraitsPrinter<PostDominatorTree, true>("postdomonly", &ID) {} }; } // end anonymous namespace diff --git a/lib/Analysis/IPA/Andersens.cpp b/lib/Analysis/IPA/Andersens.cpp index 28c66af..4180206 100644 --- a/lib/Analysis/IPA/Andersens.cpp +++ b/lib/Analysis/IPA/Andersens.cpp @@ -475,6 +475,16 @@ namespace { AU.setPreservesAll(); // Does not transform code } + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&AliasAnalysis::ID)) + return (AliasAnalysis*)this; + return this; + } + //------------------------------------------------ // Implement the AliasAnalysis API // diff --git a/lib/Analysis/IPA/CallGraph.cpp b/lib/Analysis/IPA/CallGraph.cpp index a826177..8c43aa1 100644 --- a/lib/Analysis/IPA/CallGraph.cpp +++ b/lib/Analysis/IPA/CallGraph.cpp @@ -26,7 +26,7 @@ namespace { //===----------------------------------------------------------------------===// // BasicCallGraph class definition // -class BasicCallGraph : public CallGraph, public ModulePass { +class BasicCallGraph : public ModulePass, public CallGraph { // Root is root of the call graph, or the external node if a 'main' function // couldn't be found. // @@ -82,6 +82,16 @@ public: destroy(); } + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it should + /// override this to adjust the this pointer as needed for the specified pass + /// info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&CallGraph::ID)) + return (CallGraph*)this; + return this; + } + CallGraphNode* getExternalCallingNode() const { return ExternalCallingNode; } CallGraphNode* getCallsExternalNode() const { return CallsExternalNode; } diff --git a/lib/Analysis/IPA/CallGraphSCCPass.cpp b/lib/Analysis/IPA/CallGraphSCCPass.cpp index 5504b9b..0e333d1 100644 --- a/lib/Analysis/IPA/CallGraphSCCPass.cpp +++ b/lib/Analysis/IPA/CallGraphSCCPass.cpp @@ -57,6 +57,9 @@ public: return "CallGraph Pass Manager"; } + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + // Print passes managed by this manager void dumpPassStructure(unsigned Offset) { errs().indent(Offset*2) << "Call Graph SCC Pass Manager\n"; @@ -90,7 +93,10 @@ char CGPassManager::ID = 0; bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC, CallGraph &CG, bool &CallGraphUpToDate) { bool Changed = false; - if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass*>(P)) { + PMDataManager *PM = P->getAsPMDataManager(); + + if (PM == 0) { + CallGraphSCCPass *CGSP = (CallGraphSCCPass*)P; if (!CallGraphUpToDate) { RefreshCallGraph(CurSCC, CG, false); CallGraphUpToDate = true; @@ -110,8 +116,10 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC, return Changed; } - FPPassManager *FPP = dynamic_cast<FPPassManager *>(P); - assert(FPP && "Invalid CGPassManager member"); + + assert(PM->getPassManagerType() == PMT_FunctionPassManager && + "Invalid CGPassManager member"); + FPPassManager *FPP = (FPPassManager*)P; // Run pass P on all functions in the current SCC. for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) { @@ -360,14 +368,13 @@ bool CGPassManager::runOnModule(Module &M) { /// Initialize CG bool CGPassManager::doInitialization(CallGraph &CG) { bool Changed = false; - for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { - Pass *P = getContainedPass(Index); - if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass *>(P)) { - Changed |= CGSP->doInitialization(CG); + for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) { + if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) { + assert(PM->getPassManagerType() == PMT_FunctionPassManager && + "Invalid CGPassManager member"); + Changed |= ((FPPassManager*)PM)->doInitialization(CG.getModule()); } else { - FPPassManager *FP = dynamic_cast<FPPassManager *>(P); - assert (FP && "Invalid CGPassManager member"); - Changed |= FP->doInitialization(CG.getModule()); + Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doInitialization(CG); } } return Changed; @@ -376,14 +383,13 @@ bool CGPassManager::doInitialization(CallGraph &CG) { /// Finalize CG bool CGPassManager::doFinalization(CallGraph &CG) { bool Changed = false; - for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { - Pass *P = getContainedPass(Index); - if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass *>(P)) { - Changed |= CGSP->doFinalization(CG); + for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) { + if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) { + assert(PM->getPassManagerType() == PMT_FunctionPassManager && + "Invalid CGPassManager member"); + Changed |= ((FPPassManager*)PM)->doFinalization(CG.getModule()); } else { - FPPassManager *FP = dynamic_cast<FPPassManager *>(P); - assert (FP && "Invalid CGPassManager member"); - Changed |= FP->doFinalization(CG.getModule()); + Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doFinalization(CG); } } return Changed; @@ -397,13 +403,14 @@ void CallGraphSCCPass::assignPassManager(PMStack &PMS, PMS.top()->getPassManagerType() > PMT_CallGraphPassManager) PMS.pop(); - assert (!PMS.empty() && "Unable to handle Call Graph Pass"); - CGPassManager *CGP = dynamic_cast<CGPassManager *>(PMS.top()); - - // Create new Call Graph SCC Pass Manager if it does not exist. - if (!CGP) { - - assert (!PMS.empty() && "Unable to create Call Graph Pass Manager"); + assert(!PMS.empty() && "Unable to handle Call Graph Pass"); + CGPassManager *CGP; + + if (PMS.top()->getPassManagerType() == PMT_CallGraphPassManager) + CGP = (CGPassManager*)PMS.top(); + else { + // Create new Call Graph SCC Pass Manager if it does not exist. + assert(!PMS.empty() && "Unable to create Call Graph Pass Manager"); PMDataManager *PMD = PMS.top(); // [1] Create new Call Graph Pass Manager @@ -415,7 +422,7 @@ void CallGraphSCCPass::assignPassManager(PMStack &PMS, // [3] Assign manager to manage this new manager. This may create // and push new managers into PMS - Pass *P = dynamic_cast<Pass *>(CGP); + Pass *P = CGP; TPM->schedulePass(P); // [4] Push new manager into PMS diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp index a979a99..e803a48 100644 --- a/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/lib/Analysis/IPA/GlobalsModRef.cpp @@ -145,6 +145,16 @@ namespace { virtual void deleteValue(Value *V); virtual void copyValue(Value *From, Value *To); + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&AliasAnalysis::ID)) + return (AliasAnalysis*)this; + return this; + } + private: /// getFunctionInfo - Return the function info for the function, or null if /// we don't have anything useful to say about it. diff --git a/lib/Analysis/IPA/Makefile b/lib/Analysis/IPA/Makefile index adacb16..da719ba 100644 --- a/lib/Analysis/IPA/Makefile +++ b/lib/Analysis/IPA/Makefile @@ -10,5 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMipa BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti + include $(LEVEL)/Makefile.common diff --git a/lib/Analysis/IVUsers.cpp b/lib/Analysis/IVUsers.cpp index 26c0c9e..38611cc 100644 --- a/lib/Analysis/IVUsers.cpp +++ b/lib/Analysis/IVUsers.cpp @@ -324,12 +324,19 @@ const SCEV *IVUsers::getReplacementExpr(const IVStrideUse &U) const { // the actual replacement value. if (U.isUseOfPostIncrementedValue()) RetVal = SE->getAddExpr(RetVal, U.getParent()->Stride); - // Evaluate the expression out of the loop, if possible. - if (!L->contains(U.getUser())) { - const SCEV *ExitVal = SE->getSCEVAtScope(RetVal, L->getParentLoop()); - if (ExitVal->isLoopInvariant(L)) - RetVal = ExitVal; - } + return RetVal; +} + +/// getCanonicalExpr - Return a SCEV expression which computes the +/// value of the SCEV of the given IVStrideUse, ignoring the +/// isUseOfPostIncrementedValue flag. +const SCEV *IVUsers::getCanonicalExpr(const IVStrideUse &U) const { + // Start with zero. + const SCEV *RetVal = SE->getIntegerSCEV(0, U.getParent()->Stride->getType()); + // Create the basic add recurrence. + RetVal = SE->getAddRecExpr(RetVal, U.getParent()->Stride, L); + // Add the offset in a separate step, because it may be loop-variant. + RetVal = SE->getAddExpr(RetVal, U.getOffset()); return RetVal; } diff --git a/lib/Analysis/LoopPass.cpp b/lib/Analysis/LoopPass.cpp index 43463cd..2d613f6 100644 --- a/lib/Analysis/LoopPass.cpp +++ b/lib/Analysis/LoopPass.cpp @@ -147,8 +147,7 @@ void LPPassManager::redoLoop(Loop *L) { void LPPassManager::cloneBasicBlockSimpleAnalysis(BasicBlock *From, BasicBlock *To, Loop *L) { for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { - Pass *P = getContainedPass(Index); - LoopPass *LP = dynamic_cast<LoopPass *>(P); + LoopPass *LP = (LoopPass *)getContainedPass(Index); LP->cloneBasicBlockAnalysis(From, To, L); } } @@ -163,8 +162,7 @@ void LPPassManager::deleteSimpleAnalysisValue(Value *V, Loop *L) { } } for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { - Pass *P = getContainedPass(Index); - LoopPass *LP = dynamic_cast<LoopPass *>(P); + LoopPass *LP = (LoopPass *)getContainedPass(Index); LP->deleteAnalysisValue(V, L); } } @@ -206,10 +204,8 @@ bool LPPassManager::runOnFunction(Function &F) { I != E; ++I) { Loop *L = *I; for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { - Pass *P = getContainedPass(Index); - LoopPass *LP = dynamic_cast<LoopPass *>(P); - if (LP) - Changed |= LP->doInitialization(L, *this); + LoopPass *P = (LoopPass*)getContainedPass(Index); + Changed |= P->doInitialization(L, *this); } } @@ -222,7 +218,7 @@ bool LPPassManager::runOnFunction(Function &F) { // Run all passes on the current Loop. for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { - Pass *P = getContainedPass(Index); + LoopPass *P = (LoopPass*)getContainedPass(Index); dumpPassInfo(P, EXECUTION_MSG, ON_LOOP_MSG, CurrentLoop->getHeader()->getNameStr()); @@ -230,12 +226,10 @@ bool LPPassManager::runOnFunction(Function &F) { initializeAnalysisImpl(P); - LoopPass *LP = dynamic_cast<LoopPass *>(P); - assert(LP && "Invalid LPPassManager member"); { - PassManagerPrettyStackEntry X(LP, *CurrentLoop->getHeader()); + PassManagerPrettyStackEntry X(P, *CurrentLoop->getHeader()); Timer *T = StartPassTimer(P); - Changed |= LP->runOnLoop(CurrentLoop, *this); + Changed |= P->runOnLoop(CurrentLoop, *this); StopPassTimer(P, T); } @@ -256,7 +250,7 @@ bool LPPassManager::runOnFunction(Function &F) { StopPassTimer(LI, T); // Then call the regular verifyAnalysis functions. - verifyPreservedAnalysis(LP); + verifyPreservedAnalysis(P); } removeNotPreservedAnalysis(P); @@ -289,10 +283,8 @@ bool LPPassManager::runOnFunction(Function &F) { // Finalization for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { - Pass *P = getContainedPass(Index); - LoopPass *LP = dynamic_cast <LoopPass *>(P); - if (LP) - Changed |= LP->doFinalization(); + LoopPass *P = (LoopPass *)getContainedPass(Index); + Changed |= P->doFinalization(); } return Changed; @@ -325,12 +317,11 @@ void LoopPass::preparePassManager(PMStack &PMS) { PMS.top()->getPassManagerType() > PMT_LoopPassManager) PMS.pop(); - LPPassManager *LPPM = dynamic_cast<LPPassManager *>(PMS.top()); - // If this pass is destroying high level information that is used // by other passes that are managed by LPM then do not insert // this pass in current LPM. Use new LPPassManager. - if (LPPM && !LPPM->preserveHigherLevelAnalysis(this)) + if (PMS.top()->getPassManagerType() == PMT_LoopPassManager && + !PMS.top()->preserveHigherLevelAnalysis(this)) PMS.pop(); } @@ -342,11 +333,11 @@ void LoopPass::assignPassManager(PMStack &PMS, PMS.top()->getPassManagerType() > PMT_LoopPassManager) PMS.pop(); - LPPassManager *LPPM = dynamic_cast<LPPassManager *>(PMS.top()); - - // Create new Loop Pass Manager if it does not exist. - if (!LPPM) { - + LPPassManager *LPPM; + if (PMS.top()->getPassManagerType() == PMT_LoopPassManager) + LPPM = (LPPassManager*)PMS.top(); + else { + // Create new Loop Pass Manager if it does not exist. assert (!PMS.empty() && "Unable to create Loop Pass Manager"); PMDataManager *PMD = PMS.top(); @@ -360,7 +351,7 @@ void LoopPass::assignPassManager(PMStack &PMS, // [3] Assign manager to manage this new manager. This may create // and push new managers into PMS - Pass *P = dynamic_cast<Pass *>(LPPM); + Pass *P = LPPM->getAsPass(); TPM->schedulePass(P); // [4] Push new manager into PMS diff --git a/lib/Analysis/Makefile b/lib/Analysis/Makefile index 4af6d35..f61b8aa 100644 --- a/lib/Analysis/Makefile +++ b/lib/Analysis/Makefile @@ -11,6 +11,7 @@ LEVEL = ../.. LIBRARYNAME = LLVMAnalysis DIRS = IPA BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Analysis/ProfileEstimatorPass.cpp b/lib/Analysis/ProfileEstimatorPass.cpp index cf9311a..bce6b31 100644 --- a/lib/Analysis/ProfileEstimatorPass.cpp +++ b/lib/Analysis/ProfileEstimatorPass.cpp @@ -55,6 +55,16 @@ namespace { /// run - Estimate the profile information from the specified file. virtual bool runOnFunction(Function &F); + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&ProfileInfo::ID)) + return (ProfileInfo*)this; + return this; + } + virtual void recurseBasicBlock(BasicBlock *BB); void inline printEdgeWeight(Edge); diff --git a/lib/Analysis/ProfileInfo.cpp b/lib/Analysis/ProfileInfo.cpp index afd86b1..85531be 100644 --- a/lib/Analysis/ProfileInfo.cpp +++ b/lib/Analysis/ProfileInfo.cpp @@ -1079,6 +1079,20 @@ namespace { struct NoProfileInfo : public ImmutablePass, public ProfileInfo { static char ID; // Class identification, replacement for typeinfo NoProfileInfo() : ImmutablePass(&ID) {} + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&ProfileInfo::ID)) + return (ProfileInfo*)this; + return this; + } + + virtual const char *getPassName() const { + return "NoProfileInfo"; + } }; } // End of anonymous namespace diff --git a/lib/Analysis/ProfileInfoLoaderPass.cpp b/lib/Analysis/ProfileInfoLoaderPass.cpp index d8c511f..ac9ed52 100644 --- a/lib/Analysis/ProfileInfoLoaderPass.cpp +++ b/lib/Analysis/ProfileInfoLoaderPass.cpp @@ -63,6 +63,16 @@ namespace { virtual void readEdgeOrRemember(Edge, Edge&, unsigned &, double &); virtual void readEdge(ProfileInfo::Edge, std::vector<unsigned>&); + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&ProfileInfo::ID)) + return (ProfileInfo*)this; + return this; + } + /// run - Load the profile information from the specified file. virtual bool runOnModule(Module &M); }; diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 4d85ce4..2f44913 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -1089,6 +1089,15 @@ const SCEV *ScalarEvolution::getAnyExtendExpr(const SCEV *Op, if (!isa<SCEVSignExtendExpr>(SExt)) return SExt; + // Force the cast to be folded into the operands of an addrec. + if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Op)) { + SmallVector<const SCEV *, 4> Ops; + for (SCEVAddRecExpr::op_iterator I = AR->op_begin(), E = AR->op_end(); + I != E; ++I) + Ops.push_back(getAnyExtendExpr(*I, Ty)); + return getAddRecExpr(Ops, AR->getLoop()); + } + // If the expression is obviously signed, use the sext cast value. if (isa<SCEVSMaxExpr>(Op)) return SExt; @@ -1204,6 +1213,17 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops, "SCEVAddExpr operand types don't match!"); #endif + // If HasNSW is true and all the operands are non-negative, infer HasNUW. + if (!HasNUW && HasNSW) { + bool All = true; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (!isKnownNonNegative(Ops[i])) { + All = false; + break; + } + if (All) HasNUW = true; + } + // Sort by complexity, this groups all similar expression types together. GroupByComplexity(Ops, LI); @@ -1521,21 +1541,24 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops, for (unsigned i = 0, e = Ops.size(); i != e; ++i) ID.AddPointer(Ops[i]); void *IP = 0; - if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; - SCEVAddExpr *S = SCEVAllocator.Allocate<SCEVAddExpr>(); - new (S) SCEVAddExpr(ID, Ops); - UniqueSCEVs.InsertNode(S, IP); + SCEVAddExpr *S = + static_cast<SCEVAddExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); + if (!S) { + S = SCEVAllocator.Allocate<SCEVAddExpr>(); + new (S) SCEVAddExpr(ID, Ops); + UniqueSCEVs.InsertNode(S, IP); + } if (HasNUW) S->setHasNoUnsignedWrap(true); if (HasNSW) S->setHasNoSignedWrap(true); return S; } - /// getMulExpr - Get a canonical multiply expression, or something simpler if /// possible. const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops, bool HasNUW, bool HasNSW) { assert(!Ops.empty() && "Cannot get empty mul!"); + if (Ops.size() == 1) return Ops[0]; #ifndef NDEBUG for (unsigned i = 1, e = Ops.size(); i != e; ++i) assert(getEffectiveSCEVType(Ops[i]->getType()) == @@ -1543,6 +1566,17 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops, "SCEVMulExpr operand types don't match!"); #endif + // If HasNSW is true and all the operands are non-negative, infer HasNUW. + if (!HasNUW && HasNSW) { + bool All = true; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (!isKnownNonNegative(Ops[i])) { + All = false; + break; + } + if (All) HasNUW = true; + } + // Sort by complexity, this groups all similar expression types together. GroupByComplexity(Ops, LI); @@ -1558,7 +1592,6 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops, return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)), getMulExpr(LHSC, Add->getOperand(1))); - ++Idx; while (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(Ops[Idx])) { // We found two constants, fold them together! @@ -1578,6 +1611,22 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops, } else if (cast<SCEVConstant>(Ops[0])->getValue()->isZero()) { // If we have a multiply of zero, it will always be zero. return Ops[0]; + } else if (Ops[0]->isAllOnesValue()) { + // If we have a mul by -1 of an add, try distributing the -1 among the + // add operands. + if (Ops.size() == 2) + if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[1])) { + SmallVector<const SCEV *, 4> NewOps; + bool AnyFolded = false; + for (SCEVAddRecExpr::op_iterator I = Add->op_begin(), E = Add->op_end(); + I != E; ++I) { + const SCEV *Mul = getMulExpr(Ops[0], *I); + if (!isa<SCEVMulExpr>(Mul)) AnyFolded = true; + NewOps.push_back(Mul); + } + if (AnyFolded) + return getAddExpr(NewOps); + } } } @@ -1644,7 +1693,9 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops, // It's tempting to propagate the NSW flag here, but nsw multiplication // is not associative so this isn't necessarily safe. - const SCEV *NewRec = getAddRecExpr(NewOps, AddRec->getLoop()); + const SCEV *NewRec = getAddRecExpr(NewOps, AddRec->getLoop(), + HasNUW && AddRec->hasNoUnsignedWrap(), + /*HasNSW=*/false); // If all of the other operands were loop invariant, we are done. if (Ops.size() == 1) return NewRec; @@ -1698,10 +1749,13 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops, for (unsigned i = 0, e = Ops.size(); i != e; ++i) ID.AddPointer(Ops[i]); void *IP = 0; - if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; - SCEVMulExpr *S = SCEVAllocator.Allocate<SCEVMulExpr>(); - new (S) SCEVMulExpr(ID, Ops); - UniqueSCEVs.InsertNode(S, IP); + SCEVMulExpr *S = + static_cast<SCEVMulExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); + if (!S) { + S = SCEVAllocator.Allocate<SCEVMulExpr>(); + new (S) SCEVMulExpr(ID, Ops); + UniqueSCEVs.InsertNode(S, IP); + } if (HasNUW) S->setHasNoUnsignedWrap(true); if (HasNSW) S->setHasNoSignedWrap(true); return S; @@ -1844,10 +1898,24 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands, return getAddRecExpr(Operands, L, HasNUW, HasNSW); // {X,+,0} --> X } + // If HasNSW is true and all the operands are non-negative, infer HasNUW. + if (!HasNUW && HasNSW) { + bool All = true; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + if (!isKnownNonNegative(Operands[i])) { + All = false; + break; + } + if (All) HasNUW = true; + } + // Canonicalize nested AddRecs in by nesting them in order of loop depth. if (const SCEVAddRecExpr *NestedAR = dyn_cast<SCEVAddRecExpr>(Operands[0])) { const Loop *NestedLoop = NestedAR->getLoop(); - if (L->getLoopDepth() < NestedLoop->getLoopDepth()) { + if (L->contains(NestedLoop->getHeader()) ? + (L->getLoopDepth() < NestedLoop->getLoopDepth()) : + (!NestedLoop->contains(L->getHeader()) && + DT->dominates(L->getHeader(), NestedLoop->getHeader()))) { SmallVector<const SCEV *, 4> NestedOperands(NestedAR->op_begin(), NestedAR->op_end()); Operands[0] = NestedAR->getStart(); @@ -1877,6 +1945,8 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands, } } + // Okay, it looks like we really DO need an addrec expr. Check to see if we + // already have one, otherwise create a new one. FoldingSetNodeID ID; ID.AddInteger(scAddRecExpr); ID.AddInteger(Operands.size()); @@ -1884,10 +1954,13 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands, ID.AddPointer(Operands[i]); ID.AddPointer(L); void *IP = 0; - if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; - SCEVAddRecExpr *S = SCEVAllocator.Allocate<SCEVAddRecExpr>(); - new (S) SCEVAddRecExpr(ID, Operands, L); - UniqueSCEVs.InsertNode(S, IP); + SCEVAddRecExpr *S = + static_cast<SCEVAddRecExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); + if (!S) { + S = SCEVAllocator.Allocate<SCEVAddRecExpr>(); + new (S) SCEVAddRecExpr(ID, Operands, L); + UniqueSCEVs.InsertNode(S, IP); + } if (HasNUW) S->setHasNoUnsignedWrap(true); if (HasNSW) S->setHasNoSignedWrap(true); return S; @@ -2525,31 +2598,28 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) { if (Accum->isLoopInvariant(L) || (isa<SCEVAddRecExpr>(Accum) && cast<SCEVAddRecExpr>(Accum)->getLoop() == L)) { + bool HasNUW = false; + bool HasNSW = false; + + // If the increment doesn't overflow, then neither the addrec nor + // the post-increment will overflow. + if (const AddOperator *OBO = dyn_cast<AddOperator>(BEValueV)) { + if (OBO->hasNoUnsignedWrap()) + HasNUW = true; + if (OBO->hasNoSignedWrap()) + HasNSW = true; + } + const SCEV *StartVal = getSCEV(PN->getIncomingValue(IncomingEdge)); - const SCEVAddRecExpr *PHISCEV = - cast<SCEVAddRecExpr>(getAddRecExpr(StartVal, Accum, L)); - - // If the increment doesn't overflow, then neither the addrec nor the - // post-increment will overflow. - if (const AddOperator *OBO = dyn_cast<AddOperator>(BEValueV)) - if (OBO->getOperand(0) == PN && - getSCEV(OBO->getOperand(1)) == - PHISCEV->getStepRecurrence(*this)) { - const SCEVAddRecExpr *PostInc = PHISCEV->getPostIncExpr(*this); - if (OBO->hasNoUnsignedWrap()) { - const_cast<SCEVAddRecExpr *>(PHISCEV) - ->setHasNoUnsignedWrap(true); - const_cast<SCEVAddRecExpr *>(PostInc) - ->setHasNoUnsignedWrap(true); - } - if (OBO->hasNoSignedWrap()) { - const_cast<SCEVAddRecExpr *>(PHISCEV) - ->setHasNoSignedWrap(true); - const_cast<SCEVAddRecExpr *>(PostInc) - ->setHasNoSignedWrap(true); - } - } + const SCEV *PHISCEV = + getAddRecExpr(StartVal, Accum, L, HasNUW, HasNSW); + + // Since the no-wrap flags are on the increment, they apply to the + // post-incremented value as well. + if (Accum->isLoopInvariant(L)) + (void)getAddRecExpr(getAddExpr(StartVal, Accum), + Accum, L, HasNUW, HasNSW); // Okay, for the entire analysis of this edge we assumed the PHI // to be symbolic. We now need to go back and purge all of the @@ -2781,26 +2851,29 @@ ScalarEvolution::getUnsignedRange(const SCEV *S) { if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) { const SCEV *T = getBackedgeTakenCount(AddRec->getLoop()); const SCEVConstant *Trip = dyn_cast<SCEVConstant>(T); - if (!Trip) return FullSet; + ConstantRange ConservativeResult = FullSet; + + // If there's no unsigned wrap, the value will never be less than its + // initial value. + if (AddRec->hasNoUnsignedWrap()) + if (const SCEVConstant *C = dyn_cast<SCEVConstant>(AddRec->getStart())) + ConservativeResult = + ConstantRange(C->getValue()->getValue(), + APInt(getTypeSizeInBits(C->getType()), 0)); // TODO: non-affine addrec - if (AddRec->isAffine()) { + if (Trip && AddRec->isAffine()) { const Type *Ty = AddRec->getType(); const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop()); if (getTypeSizeInBits(MaxBECount->getType()) <= getTypeSizeInBits(Ty)) { MaxBECount = getNoopOrZeroExtend(MaxBECount, Ty); const SCEV *Start = AddRec->getStart(); - const SCEV *Step = AddRec->getStepRecurrence(*this); const SCEV *End = AddRec->evaluateAtIteration(MaxBECount, *this); // Check for overflow. - // TODO: This is very conservative. - if (!(Step->isOne() && - isKnownPredicate(ICmpInst::ICMP_ULT, Start, End)) && - !(Step->isAllOnesValue() && - isKnownPredicate(ICmpInst::ICMP_UGT, Start, End))) - return FullSet; + if (!AddRec->hasNoUnsignedWrap()) + return ConservativeResult; ConstantRange StartRange = getUnsignedRange(Start); ConstantRange EndRange = getUnsignedRange(End); @@ -2809,10 +2882,12 @@ ScalarEvolution::getUnsignedRange(const SCEV *S) { APInt Max = APIntOps::umax(StartRange.getUnsignedMax(), EndRange.getUnsignedMax()); if (Min.isMinValue() && Max.isMaxValue()) - return FullSet; + return ConservativeResult; return ConstantRange(Min, Max+1); } } + + return ConservativeResult; } if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) { @@ -2891,26 +2966,39 @@ ScalarEvolution::getSignedRange(const SCEV *S) { if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) { const SCEV *T = getBackedgeTakenCount(AddRec->getLoop()); const SCEVConstant *Trip = dyn_cast<SCEVConstant>(T); - if (!Trip) return FullSet; + ConstantRange ConservativeResult = FullSet; + + // If there's no signed wrap, and all the operands have the same sign or + // zero, the value won't ever change sign. + if (AddRec->hasNoSignedWrap()) { + bool AllNonNeg = true; + bool AllNonPos = true; + for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) { + if (!isKnownNonNegative(AddRec->getOperand(i))) AllNonNeg = false; + if (!isKnownNonPositive(AddRec->getOperand(i))) AllNonPos = false; + } + unsigned BitWidth = getTypeSizeInBits(AddRec->getType()); + if (AllNonNeg) + ConservativeResult = ConstantRange(APInt(BitWidth, 0), + APInt::getSignedMinValue(BitWidth)); + else if (AllNonPos) + ConservativeResult = ConstantRange(APInt::getSignedMinValue(BitWidth), + APInt(BitWidth, 1)); + } // TODO: non-affine addrec - if (AddRec->isAffine()) { + if (Trip && AddRec->isAffine()) { const Type *Ty = AddRec->getType(); const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop()); if (getTypeSizeInBits(MaxBECount->getType()) <= getTypeSizeInBits(Ty)) { MaxBECount = getNoopOrZeroExtend(MaxBECount, Ty); const SCEV *Start = AddRec->getStart(); - const SCEV *Step = AddRec->getStepRecurrence(*this); const SCEV *End = AddRec->evaluateAtIteration(MaxBECount, *this); // Check for overflow. - // TODO: This is very conservative. - if (!(Step->isOne() && - isKnownPredicate(ICmpInst::ICMP_SLT, Start, End)) && - !(Step->isAllOnesValue() && - isKnownPredicate(ICmpInst::ICMP_SGT, Start, End))) - return FullSet; + if (!AddRec->hasNoSignedWrap()) + return ConservativeResult; ConstantRange StartRange = getSignedRange(Start); ConstantRange EndRange = getSignedRange(End); @@ -2919,15 +3007,19 @@ ScalarEvolution::getSignedRange(const SCEV *S) { APInt Max = APIntOps::smax(StartRange.getSignedMax(), EndRange.getSignedMax()); if (Min.isMinSignedValue() && Max.isMaxSignedValue()) - return FullSet; + return ConservativeResult; return ConstantRange(Min, Max+1); } } + + return ConservativeResult; } if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) { // For a SCEVUnknown, ask ValueTracking. unsigned BitWidth = getTypeSizeInBits(U->getType()); + if (!U->getValue()->getType()->isInteger() && !TD) + return FullSet; unsigned NS = ComputeNumSignBits(U->getValue(), TD); if (NS == 1) return FullSet; @@ -5167,6 +5259,7 @@ ScalarEvolution::ScalarEvolution() bool ScalarEvolution::runOnFunction(Function &F) { this->F = &F; LI = &getAnalysis<LoopInfo>(); + DT = &getAnalysis<DominatorTree>(); TD = getAnalysisIfAvailable<TargetData>(); return false; } @@ -5183,6 +5276,7 @@ void ScalarEvolution::releaseMemory() { void ScalarEvolution::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequiredTransitive<LoopInfo>(); + AU.addRequiredTransitive<DominatorTree>(); } bool ScalarEvolution::hasLoopInvariantBackedgeTakenCount(const Loop *L) { diff --git a/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp index ef0e97b..498c4a8 100644 --- a/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp +++ b/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp @@ -32,6 +32,16 @@ namespace { static char ID; // Class identification, replacement for typeinfo ScalarEvolutionAliasAnalysis() : FunctionPass(&ID), SE(0) {} + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const PassInfo *PI) { + if (PI->isPassID(&AliasAnalysis::ID)) + return (AliasAnalysis*)this; + return this; + } + private: virtual void getAnalysisUsage(AnalysisUsage &AU) const; virtual bool runOnFunction(Function &F); diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index 7157d47..a72f58f 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -81,7 +81,7 @@ Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) { Instruction *I = CastInst::Create(Op, V, Ty, V->getName(), A->getParent()->getEntryBlock().begin()); - InsertedValues.insert(I); + rememberInstruction(I); return I; } @@ -98,14 +98,16 @@ Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) { It = cast<InvokeInst>(I)->getNormalDest()->begin(); while (isa<PHINode>(It)) ++It; if (It != BasicBlock::iterator(CI)) { - // Recreate the cast at the beginning of the entry block. + // Recreate the cast after the user. // The old cast is left in place in case it is being used // as an insert point. Instruction *NewCI = CastInst::Create(Op, V, Ty, "", It); NewCI->takeName(CI); CI->replaceAllUsesWith(NewCI); + rememberInstruction(NewCI); return NewCI; } + rememberInstruction(CI); return CI; } } @@ -114,7 +116,7 @@ Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) { IP = II->getNormalDest()->begin(); while (isa<PHINode>(IP)) ++IP; Instruction *CI = CastInst::Create(Op, V, Ty, V->getName(), IP); - InsertedValues.insert(CI); + rememberInstruction(CI); return CI; } @@ -144,7 +146,7 @@ Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode, // If we haven't found this binop, insert it. Value *BO = Builder.CreateBinOp(Opcode, LHS, RHS, "tmp"); - InsertedValues.insert(BO); + rememberInstruction(BO); return BO; } @@ -323,7 +325,7 @@ static void SplitAddRecs(SmallVectorImpl<const SCEV *> &Ops, /// http://llvm.org/docs/LangRef.html#pointeraliasing /// for details. /// -/// Design note: The correctness of using getelmeentptr here depends on +/// Design note: The correctness of using getelementptr here depends on /// ScalarEvolution not recognizing inttoptr and ptrtoint operators, as /// they may introduce pointer arithmetic which may not be safely converted /// into getelementptr. @@ -491,22 +493,39 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, // Emit a GEP. Value *GEP = Builder.CreateGEP(V, Idx, "uglygep"); - InsertedValues.insert(GEP); + rememberInstruction(GEP); return GEP; } // Insert a pretty getelementptr. Note that this GEP is not marked inbounds, // because ScalarEvolution may have changed the address arithmetic to // compute a value which is beyond the end of the allocated object. - Value *GEP = Builder.CreateGEP(V, + Value *Casted = V; + if (V->getType() != PTy) + Casted = InsertNoopCastOfTo(Casted, PTy); + Value *GEP = Builder.CreateGEP(Casted, GepIndices.begin(), GepIndices.end(), "scevgep"); Ops.push_back(SE.getUnknown(GEP)); - InsertedValues.insert(GEP); + rememberInstruction(GEP); return expand(SE.getAddExpr(Ops)); } +/// isNonConstantNegative - Return true if the specified scev is negated, but +/// not a constant. +static bool isNonConstantNegative(const SCEV *F) { + const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(F); + if (!Mul) return false; + + // If there is a constant factor, it will be first. + const SCEVConstant *SC = dyn_cast<SCEVConstant>(Mul->getOperand(0)); + if (!SC) return false; + + // Return true if the value is negative, this matches things like (-42 * V). + return SC->getValue()->getValue().isNegative(); +} + Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { int NumOperands = S->getNumOperands(); const Type *Ty = SE.getEffectiveSCEVType(S->getType()); @@ -539,8 +558,14 @@ Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { // Emit a bunch of add instructions for (int i = NumOperands-1; i >= 0; --i) { if (i == PIdx) continue; - Value *W = expandCodeFor(S->getOperand(i), Ty); - V = InsertBinop(Instruction::Add, V, W); + const SCEV *Op = S->getOperand(i); + if (isNonConstantNegative(Op)) { + Value *W = expandCodeFor(SE.getNegativeSCEV(Op), Ty); + V = InsertBinop(Instruction::Sub, V, W); + } else { + Value *W = expandCodeFor(Op, Ty); + V = InsertBinop(Instruction::Add, V, W); + } } return V; } @@ -603,7 +628,175 @@ static void ExposePointerBase(const SCEV *&Base, const SCEV *&Rest, } } +/// getAddRecExprPHILiterally - Helper for expandAddRecExprLiterally. Expand +/// the base addrec, which is the addrec without any non-loop-dominating +/// values, and return the PHI. +PHINode * +SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, + const Loop *L, + const Type *ExpandTy, + const Type *IntTy) { + // Reuse a previously-inserted PHI, if present. + for (BasicBlock::iterator I = L->getHeader()->begin(); + PHINode *PN = dyn_cast<PHINode>(I); ++I) + if (isInsertedInstruction(PN) && SE.getSCEV(PN) == Normalized) + return PN; + + // Save the original insertion point so we can restore it when we're done. + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + + // Expand code for the start value. + Value *StartV = expandCodeFor(Normalized->getStart(), ExpandTy, + L->getHeader()->begin()); + + // Expand code for the step value. Insert instructions right before the + // terminator corresponding to the back-edge. Do this before creating the PHI + // so that PHI reuse code doesn't see an incomplete PHI. If the stride is + // negative, insert a sub instead of an add for the increment (unless it's a + // constant, because subtracts of constants are canonicalized to adds). + const SCEV *Step = Normalized->getStepRecurrence(SE); + bool isPointer = isa<PointerType>(ExpandTy); + bool isNegative = !isPointer && isNonConstantNegative(Step); + if (isNegative) + Step = SE.getNegativeSCEV(Step); + Value *StepV = expandCodeFor(Step, IntTy, L->getHeader()->begin()); + + // Create the PHI. + Builder.SetInsertPoint(L->getHeader(), L->getHeader()->begin()); + PHINode *PN = Builder.CreatePHI(ExpandTy, "lsr.iv"); + rememberInstruction(PN); + + // Create the step instructions and populate the PHI. + BasicBlock *Header = L->getHeader(); + for (pred_iterator HPI = pred_begin(Header), HPE = pred_end(Header); + HPI != HPE; ++HPI) { + BasicBlock *Pred = *HPI; + + // Add a start value. + if (!L->contains(Pred)) { + PN->addIncoming(StartV, Pred); + continue; + } + + // Create a step value and add it to the PHI. If IVIncInsertLoop is + // non-null and equal to the addrec's loop, insert the instructions + // at IVIncInsertPos. + Instruction *InsertPos = L == IVIncInsertLoop ? + IVIncInsertPos : Pred->getTerminator(); + Builder.SetInsertPoint(InsertPos->getParent(), InsertPos); + Value *IncV; + // If the PHI is a pointer, use a GEP, otherwise use an add or sub. + if (isPointer) { + const PointerType *GEPPtrTy = cast<PointerType>(ExpandTy); + // If the step isn't constant, don't use an implicitly scaled GEP, because + // that would require a multiply inside the loop. + if (!isa<ConstantInt>(StepV)) + GEPPtrTy = PointerType::get(Type::getInt1Ty(SE.getContext()), + GEPPtrTy->getAddressSpace()); + const SCEV *const StepArray[1] = { SE.getSCEV(StepV) }; + IncV = expandAddToGEP(StepArray, StepArray+1, GEPPtrTy, IntTy, PN); + if (IncV->getType() != PN->getType()) { + IncV = Builder.CreateBitCast(IncV, PN->getType(), "tmp"); + rememberInstruction(IncV); + } + } else { + IncV = isNegative ? + Builder.CreateSub(PN, StepV, "lsr.iv.next") : + Builder.CreateAdd(PN, StepV, "lsr.iv.next"); + rememberInstruction(IncV); + } + PN->addIncoming(IncV, Pred); + } + + // Restore the original insert point. + if (SaveInsertBB) + Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt); + + // Remember this PHI, even in post-inc mode. + InsertedValues.insert(PN); + + return PN; +} + +Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { + const Type *STy = S->getType(); + const Type *IntTy = SE.getEffectiveSCEVType(STy); + const Loop *L = S->getLoop(); + + // Determine a normalized form of this expression, which is the expression + // before any post-inc adjustment is made. + const SCEVAddRecExpr *Normalized = S; + if (L == PostIncLoop) { + const SCEV *Step = S->getStepRecurrence(SE); + Normalized = cast<SCEVAddRecExpr>(SE.getMinusSCEV(S, Step)); + } + + // Strip off any non-loop-dominating component from the addrec start. + const SCEV *Start = Normalized->getStart(); + const SCEV *PostLoopOffset = 0; + if (!Start->properlyDominates(L->getHeader(), SE.DT)) { + PostLoopOffset = Start; + Start = SE.getIntegerSCEV(0, Normalized->getType()); + Normalized = + cast<SCEVAddRecExpr>(SE.getAddRecExpr(Start, + Normalized->getStepRecurrence(SE), + Normalized->getLoop())); + } + + // Strip off any non-loop-dominating component from the addrec step. + const SCEV *Step = Normalized->getStepRecurrence(SE); + const SCEV *PostLoopScale = 0; + if (!Step->hasComputableLoopEvolution(L) && + !Step->dominates(L->getHeader(), SE.DT)) { + PostLoopScale = Step; + Step = SE.getIntegerSCEV(1, Normalized->getType()); + Normalized = + cast<SCEVAddRecExpr>(SE.getAddRecExpr(Start, Step, + Normalized->getLoop())); + } + + // Expand the core addrec. If we need post-loop scaling, force it to + // expand to an integer type to avoid the need for additional casting. + const Type *ExpandTy = PostLoopScale ? IntTy : STy; + PHINode *PN = getAddRecExprPHILiterally(Normalized, L, ExpandTy, IntTy); + + // Accomodate post-inc mode, if necessary. + Value *Result; + if (L != PostIncLoop) + Result = PN; + else { + // In PostInc mode, use the post-incremented value. + BasicBlock *LatchBlock = L->getLoopLatch(); + assert(LatchBlock && "PostInc mode requires a unique loop latch!"); + Result = PN->getIncomingValueForBlock(LatchBlock); + } + + // Re-apply any non-loop-dominating scale. + if (PostLoopScale) { + Result = Builder.CreateMul(Result, + expandCodeFor(PostLoopScale, IntTy)); + rememberInstruction(Result); + } + + // Re-apply any non-loop-dominating offset. + if (PostLoopOffset) { + if (const PointerType *PTy = dyn_cast<PointerType>(ExpandTy)) { + const SCEV *const OffsetArray[1] = { PostLoopOffset }; + Result = expandAddToGEP(OffsetArray, OffsetArray+1, PTy, IntTy, Result); + } else { + Result = Builder.CreateAdd(Result, + expandCodeFor(PostLoopOffset, IntTy)); + rememberInstruction(Result); + } + } + + return Result; +} + Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { + if (!CanonicalMode) return expandAddRecExprLiterally(S); + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); const Loop *L = S->getLoop(); @@ -681,17 +874,17 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { // specified loop. BasicBlock *Header = L->getHeader(); PHINode *PN = PHINode::Create(Ty, "indvar", Header->begin()); - InsertedValues.insert(PN); + rememberInstruction(PN); Constant *One = ConstantInt::get(Ty, 1); for (pred_iterator HPI = pred_begin(Header), HPE = pred_end(Header); HPI != HPE; ++HPI) if (L->contains(*HPI)) { - // Insert a unit add instruction right before the terminator corresponding - // to the back-edge. + // Insert a unit add instruction right before the terminator + // corresponding to the back-edge. Instruction *Add = BinaryOperator::CreateAdd(PN, One, "indvar.next", (*HPI)->getTerminator()); - InsertedValues.insert(Add); + rememberInstruction(Add); PN->addIncoming(Add, *HPI); } else { PN->addIncoming(Constant::getNullValue(Ty), *HPI); @@ -738,7 +931,7 @@ Value *SCEVExpander::visitTruncateExpr(const SCEVTruncateExpr *S) { Value *V = expandCodeFor(S->getOperand(), SE.getEffectiveSCEVType(S->getOperand()->getType())); Value *I = Builder.CreateTrunc(V, Ty, "tmp"); - InsertedValues.insert(I); + rememberInstruction(I); return I; } @@ -747,7 +940,7 @@ Value *SCEVExpander::visitZeroExtendExpr(const SCEVZeroExtendExpr *S) { Value *V = expandCodeFor(S->getOperand(), SE.getEffectiveSCEVType(S->getOperand()->getType())); Value *I = Builder.CreateZExt(V, Ty, "tmp"); - InsertedValues.insert(I); + rememberInstruction(I); return I; } @@ -756,7 +949,7 @@ Value *SCEVExpander::visitSignExtendExpr(const SCEVSignExtendExpr *S) { Value *V = expandCodeFor(S->getOperand(), SE.getEffectiveSCEVType(S->getOperand()->getType())); Value *I = Builder.CreateSExt(V, Ty, "tmp"); - InsertedValues.insert(I); + rememberInstruction(I); return I; } @@ -772,9 +965,9 @@ Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) { } Value *RHS = expandCodeFor(S->getOperand(i), Ty); Value *ICmp = Builder.CreateICmpSGT(LHS, RHS, "tmp"); - InsertedValues.insert(ICmp); + rememberInstruction(ICmp); Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "smax"); - InsertedValues.insert(Sel); + rememberInstruction(Sel); LHS = Sel; } // In the case of mixed integer and pointer types, cast the @@ -796,9 +989,9 @@ Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) { } Value *RHS = expandCodeFor(S->getOperand(i), Ty); Value *ICmp = Builder.CreateICmpUGT(LHS, RHS, "tmp"); - InsertedValues.insert(ICmp); + rememberInstruction(ICmp); Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "umax"); - InsertedValues.insert(Sel); + rememberInstruction(Sel); LHS = Sel; } // In the case of mixed integer and pointer types, cast the @@ -863,7 +1056,8 @@ Value *SCEVExpander::expand(const SCEV *S) { Value *V = visit(S); // Remember the expanded value for this SCEV at this location. - InsertedExpressions[std::make_pair(S, InsertPt)] = V; + if (!PostIncLoop) + InsertedExpressions[std::make_pair(S, InsertPt)] = V; Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt); return V; diff --git a/lib/Archive/Makefile b/lib/Archive/Makefile index da97804..1256e1c 100644 --- a/lib/Archive/Makefile +++ b/lib/Archive/Makefile @@ -9,6 +9,7 @@ LEVEL = ../.. LIBRARYNAME = LLVMArchive +CXXFLAGS = -fno-rtti # We only want an archive so only those modules actually used by a tool are # included. diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 8ad658d..2a926d2 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -558,7 +558,6 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(readnone); KEYWORD(readonly); - KEYWORD(inlinehint); KEYWORD(noinline); KEYWORD(alwaysinline); KEYWORD(optsize); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index e4039ab..04a5263c 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -947,7 +947,6 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { case lltok::kw_noinline: Attrs |= Attribute::NoInline; break; case lltok::kw_readnone: Attrs |= Attribute::ReadNone; break; case lltok::kw_readonly: Attrs |= Attribute::ReadOnly; break; - case lltok::kw_inlinehint: Attrs |= Attribute::InlineHint; break; case lltok::kw_alwaysinline: Attrs |= Attribute::AlwaysInline; break; case lltok::kw_optsize: Attrs |= Attribute::OptimizeForSize; break; case lltok::kw_ssp: Attrs |= Attribute::StackProtect; break; diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index bea0593..85c07ff 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -29,7 +29,6 @@ namespace llvm { class Instruction; class Constant; class GlobalValue; - class MetadataBase; class MDString; class MDNode; diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 7f1807c..80eb194 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -85,7 +85,6 @@ namespace lltok { kw_readnone, kw_readonly, - kw_inlinehint, kw_noinline, kw_alwaysinline, kw_optsize, diff --git a/lib/AsmParser/Makefile b/lib/AsmParser/Makefile index 995bb0e..7b53a87 100644 --- a/lib/AsmParser/Makefile +++ b/lib/AsmParser/Makefile @@ -10,5 +10,6 @@ LEVEL = ../.. LIBRARYNAME := LLVMAsmParser BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/AsmParser/Parser.cpp b/lib/AsmParser/Parser.cpp index 331a233..aac4027 100644 --- a/lib/AsmParser/Parser.cpp +++ b/lib/AsmParser/Parser.cpp @@ -45,7 +45,8 @@ Module *llvm::ParseAssemblyFile(const std::string &Filename, SMDiagnostic &Err, MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr); if (F == 0) { Err = SMDiagnostic("", -1, -1, - "Could not open input file '" + Filename + "'", ""); + "Could not open input file '" + Filename + "': " + + ErrorStr, ""); return 0; } diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index aabbc90..2549a51 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1167,7 +1167,7 @@ bool BitcodeReader::ParseConstants() { Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy); - if (OpTy->isFloatingPoint()) + if (OpTy->isFPOrFPVector()) V = ConstantExpr::getFCmp(Record[3], Op0, Op1); else V = ConstantExpr::getICmp(Record[3], Op0, Op1); diff --git a/lib/Bitcode/Reader/Makefile b/lib/Bitcode/Reader/Makefile index 59af8d53..0aae3bf 100644 --- a/lib/Bitcode/Reader/Makefile +++ b/lib/Bitcode/Reader/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMBitReader BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Bitcode/Writer/Makefile b/lib/Bitcode/Writer/Makefile index 7b0bd72..5f9742e 100644 --- a/lib/Bitcode/Writer/Makefile +++ b/lib/Bitcode/Writer/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMBitWriter BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp index cb139e5..c46d735 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -140,7 +140,7 @@ void ValueEnumerator::setInstructionID(const Instruction *I) { } unsigned ValueEnumerator::getValueID(const Value *V) const { - if (isa<MetadataBase>(V)) { + if (isa<MDNode>(V) || isa<MDString>(V)) { ValueMapType::const_iterator I = MDValueMap.find(V); assert(I != MDValueMap.end() && "Value not in slotcalculator!"); return I->second-1; @@ -229,7 +229,8 @@ void ValueEnumerator::EnumerateNamedMDNode(const NamedMDNode *MD) { MDValueMap[MD] = Values.size(); } -void ValueEnumerator::EnumerateMetadata(const MetadataBase *MD) { +void ValueEnumerator::EnumerateMetadata(const Value *MD) { + assert((isa<MDNode>(MD) || isa<MDString>(MD)) && "Invalid metadata kind"); // Check to see if it's already in! unsigned &MDValueID = MDValueMap[MD]; if (MDValueID) { @@ -262,8 +263,8 @@ void ValueEnumerator::EnumerateMetadata(const MetadataBase *MD) { void ValueEnumerator::EnumerateValue(const Value *V) { assert(!V->getType()->isVoidTy() && "Can't insert void values!"); - if (const MetadataBase *MB = dyn_cast<MetadataBase>(V)) - return EnumerateMetadata(MB); + if (isa<MDNode>(V) || isa<MDString>(V)) + return EnumerateMetadata(V); else if (const NamedMDNode *NMD = dyn_cast<NamedMDNode>(V)) return EnumerateNamedMDNode(NMD); diff --git a/lib/Bitcode/Writer/ValueEnumerator.h b/lib/Bitcode/Writer/ValueEnumerator.h index c50fe9c..4f8ebf5 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.h +++ b/lib/Bitcode/Writer/ValueEnumerator.h @@ -127,7 +127,7 @@ public: private: void OptimizeConstants(unsigned CstStart, unsigned CstEnd); - void EnumerateMetadata(const MetadataBase *MD); + void EnumerateMetadata(const Value *MD); void EnumerateNamedMDNode(const NamedMDNode *NMD); void EnumerateValue(const Value *V); void EnumerateType(const Type *T); diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 876f628..f4d8864 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -16,6 +16,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/Constants.h" #include "llvm/Module.h" +#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -23,18 +24,19 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" @@ -43,7 +45,6 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" #include <cerrno> using namespace llvm; @@ -51,6 +52,15 @@ static cl::opt<cl::boolOrDefault> AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), cl::init(cl::BOU_UNSET)); +static bool getVerboseAsm(bool VDef) { + switch (AsmVerbose) { + default: + case cl::BOU_UNSET: return VDef; + case cl::BOU_TRUE: return true; + case cl::BOU_FALSE: return false; + } +} + char AsmPrinter::ID = 0; AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm, const MCAsmInfo *T, bool VDef) @@ -59,16 +69,13 @@ AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm, OutContext(*new MCContext()), // FIXME: Pass instprinter to streamer. - OutStreamer(*createAsmStreamer(OutContext, O, *T, 0)), + OutStreamer(*createAsmStreamer(OutContext, O, *T, + TM.getTargetData()->isLittleEndian(), + getVerboseAsm(VDef), 0)), - LastMI(0), LastFn(0), Counter(~0U), - PrevDLT(0, 0, ~0U, ~0U) { + LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) { DW = 0; MMI = 0; - switch (AsmVerbose) { - case cl::BOU_UNSET: VerboseAsm = VDef; break; - case cl::BOU_TRUE: VerboseAsm = true; break; - case cl::BOU_FALSE: VerboseAsm = false; break; - } + VerboseAsm = getVerboseAsm(VDef); } AsmPrinter::~AsmPrinter() { @@ -103,22 +110,15 @@ bool AsmPrinter::doInitialization(Module &M) { const_cast<TargetLoweringObjectFile&>(getObjFileLowering()) .Initialize(OutContext, TM); - Mang = new Mangler(M, MAI->getGlobalPrefix(), MAI->getPrivateGlobalPrefix(), - MAI->getLinkerPrivateGlobalPrefix()); - - if (MAI->doesAllowQuotesInName()) - Mang->setUseQuotes(true); - - if (MAI->doesAllowNameToStartWithDigit()) - Mang->setSymbolsCanStartWithDigit(true); + Mang = new Mangler(*MAI); // Allow the target to emit any magic that it wants at the start of the file. EmitStartOfAsmFile(M); if (MAI->hasSingleParameterDotFile()) { - /* Very minimal debug info. It is ignored if we emit actual - debug info. If we don't, this at least helps the user find where - a function came from. */ + // Very minimal debug info. It is ignored if we emit actual + // debug info. If we don't, this at least helps the user find where + // a function came from. O << "\t.file\t\"" << M.getModuleIdentifier() << "\"\n"; } @@ -144,11 +144,148 @@ bool AsmPrinter::doInitialization(Module &M) { return false; } +/// EmitGlobalVariable - Emit the specified global variable to the .s file. +void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { + if (!GV->hasInitializer()) // External globals require no code. + return; + + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(GV)) + return; + + MCSymbol *GVSym = GetGlobalValueSymbol(GV); + printVisibility(GVSym, GV->getVisibility()); + + if (MAI->hasDotTypeDotSizeDirective()) { + O << "\t.type\t" << *GVSym; + if (MAI->getCommentString()[0] != '@') + O << ",@object\n"; + else + O << ",%object\n"; + } + + SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); + + const TargetData *TD = TM.getTargetData(); + unsigned Size = TD->getTypeAllocSize(GV->getType()->getElementType()); + unsigned AlignLog = TD->getPreferredAlignmentLog(GV); + + // Handle common and BSS local symbols (.lcomm). + if (GVKind.isCommon() || GVKind.isBSSLocal()) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + + if (VerboseAsm) { + WriteAsOperand(OutStreamer.GetCommentOS(), GV, + /*PrintType=*/false, GV->getParent()); + OutStreamer.GetCommentOS() << '\n'; + } + + // Handle common symbols. + if (GVKind.isCommon()) { + // .comm _foo, 42, 4 + OutStreamer.EmitCommonSymbol(GVSym, Size, 1 << AlignLog); + return; + } + + // Handle local BSS symbols. + if (MAI->hasMachoZeroFillDirective()) { + const MCSection *TheSection = + getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM); + // .zerofill __DATA, __bss, _foo, 400, 5 + OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog); + return; + } + + if (MAI->hasLCOMMDirective()) { + // .lcomm _foo, 42 + OutStreamer.EmitLocalCommonSymbol(GVSym, Size); + return; + } + + // .local _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Local); + // .comm _foo, 42, 4 + OutStreamer.EmitCommonSymbol(GVSym, Size, 1 << AlignLog); + return; + } + + const MCSection *TheSection = + getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM); + + // Handle the zerofill directive on darwin, which is a special form of BSS + // emission. + if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective()) { + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + // .zerofill __DATA, __common, _foo, 400, 5 + OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog); + return; + } + + OutStreamer.SwitchSection(TheSection); + + // TODO: Factor into an 'emit linkage' thing that is shared with function + // bodies. + switch (GV->getLinkage()) { + case GlobalValue::CommonLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::LinkerPrivateLinkage: + if (MAI->getWeakDefDirective() != 0) { + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + // .weak_definition _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition); + } else if (const char *LinkOnce = MAI->getLinkOnceDirective()) { + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + // .linkonce same_size + O << LinkOnce; + } else { + // .weak _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); + } + break; + case GlobalValue::DLLExportLinkage: + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol. + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + break; + case GlobalValue::PrivateLinkage: + case GlobalValue::InternalLinkage: + break; + default: + llvm_unreachable("Unknown linkage type!"); + } + + EmitAlignment(AlignLog, GV); + if (VerboseAsm) { + WriteAsOperand(OutStreamer.GetCommentOS(), GV, + /*PrintType=*/false, GV->getParent()); + OutStreamer.GetCommentOS() << '\n'; + } + OutStreamer.EmitLabel(GVSym); + + EmitGlobalConstant(GV->getInitializer()); + + if (MAI->hasDotTypeDotSizeDirective()) + O << "\t.size\t" << *GVSym << ", " << Size << '\n'; + + OutStreamer.AddBlankLine(); +} + + bool AsmPrinter::doFinalization(Module &M) { // Emit global variables. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) - PrintGlobalVariable(I); + EmitGlobalVariable(I); // Emit final debug information. if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) @@ -164,35 +301,37 @@ bool AsmPrinter::doFinalization(Module &M) { // Print out module-level global variables here. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { - if (I->hasExternalWeakLinkage()) - O << MAI->getWeakRefDirective() << Mang->getMangledName(I) << '\n'; + if (!I->hasExternalWeakLinkage()) continue; + OutStreamer.EmitSymbolAttribute(GetGlobalValueSymbol(I), + MCSA_WeakReference); } for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) { - if (I->hasExternalWeakLinkage()) - O << MAI->getWeakRefDirective() << Mang->getMangledName(I) << '\n'; + if (!I->hasExternalWeakLinkage()) continue; + OutStreamer.EmitSymbolAttribute(GetGlobalValueSymbol(I), + MCSA_WeakReference); } } if (MAI->getSetDirective()) { - O << '\n'; + OutStreamer.AddBlankLine(); for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { - std::string Name = Mang->getMangledName(I); + MCSymbol *Name = GetGlobalValueSymbol(I); const GlobalValue *GV = cast<GlobalValue>(I->getAliasedGlobal()); - std::string Target = Mang->getMangledName(GV); + MCSymbol *Target = GetGlobalValueSymbol(GV); if (I->hasExternalLinkage() || !MAI->getWeakRefDirective()) - O << "\t.globl\t" << Name << '\n'; + OutStreamer.EmitSymbolAttribute(Name, MCSA_Global); else if (I->hasWeakLinkage()) - O << MAI->getWeakRefDirective() << Name << '\n'; - else if (!I->hasLocalLinkage()) - llvm_unreachable("Invalid alias linkage"); + OutStreamer.EmitSymbolAttribute(Name, MCSA_WeakReference); + else + assert(I->hasLocalLinkage() && "Invalid alias linkage"); printVisibility(Name, I->getVisibility()); - O << MAI->getSetDirective() << ' ' << Name << ", " << Target << '\n'; + O << MAI->getSetDirective() << ' ' << *Name << ", " << *Target << '\n'; } } @@ -206,9 +345,8 @@ bool AsmPrinter::doFinalization(Module &M) { // to be executable. Some targets have a directive to declare this. Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline"); if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty()) - if (MAI->getNonexecutableStackDirective()) - O << MAI->getNonexecutableStackDirective() << '\n'; - + if (MCSection *S = MAI->getNonexecutableStackSection(OutContext)) + OutStreamer.SwitchSection(S); // Allow the target to emit any magic that it wants at the end of the file, // after everything else has gone out. @@ -222,8 +360,8 @@ bool AsmPrinter::doFinalization(Module &M) { } void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { - // What's my mangled name? - CurrentFnName = Mang->getMangledName(MF.getFunction()); + // Get the function symbol. + CurrentFnSym = GetGlobalValueSymbol(MF.getFunction()); IncrementFunctionNumber(); if (VerboseAsm) @@ -307,19 +445,20 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { // Emit inter-object padding for alignment. unsigned AlignMask = CPE.getAlignment() - 1; unsigned NewOffset = (Offset + AlignMask) & ~AlignMask; - EmitZeros(NewOffset - Offset); + OutStreamer.EmitFill(NewOffset - Offset, 0/*fillval*/, 0/*addrspace*/); const Type *Ty = CPE.getType(); Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty); - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' - << CPI << ':'; + // Emit the label with a comment on it. if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " constant "; - WriteTypeSymbolic(O, CPE.getType(), MF->getFunction()->getParent()); + OutStreamer.GetCommentOS() << "constant pool "; + WriteTypeSymbolic(OutStreamer.GetCommentOS(), CPE.getType(), + MF->getFunction()->getParent()); + OutStreamer.GetCommentOS() << '\n'; } - O << '\n'; + OutStreamer.EmitLabel(GetCPISymbol(CPI)); + if (CPE.isMachineConstantPoolEntry()) EmitMachineConstantPoolValue(CPE.Val.MachineCPVal); else @@ -381,14 +520,11 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, // before each jump table. The first label is never referenced, but tells // the assembler and linker the extents of the jump table object. The // second label is actually referenced by the code. - if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0]) { - O << MAI->getLinkerPrivateGlobalPrefix() - << "JTI" << getFunctionNumber() << '_' << i << ":\n"; - } - - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << i << ":\n"; - + if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0]) + OutStreamer.EmitLabel(GetJTISymbol(i, true)); + + OutStreamer.EmitLabel(GetJTISymbol(i)); + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { printPICJumpTableEntry(MJTI, JTBBs[ii], i); O << '\n'; @@ -418,17 +554,16 @@ void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, // If we're emitting non-PIC code, then emit the entries as direct // references to the target basic blocks. if (!isPIC) { - GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MBB->getNumber()); } else if (MAI->getSetDirective()) { O << MAI->getPrivateGlobalPrefix() << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber(); } else { - GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MBB->getNumber()); // If the arch uses custom Jump Table directives, don't calc relative to - // JT + // JT. if (!HadJTEntryDirective) - O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" - << getFunctionNumber() << '_' << uid; + O << '-' << *GetJTISymbol(uid); } } @@ -438,7 +573,7 @@ void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, /// do nothing and return false. bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { if (GV->getName() == "llvm.used") { - if (MAI->getUsedDirective() != 0) // No need to emit this at all. + if (MAI->hasNoDeadStrip()) // No need to emit this at all. EmitLLVMUsedList(GV->getInitializer()); return true; } @@ -458,6 +593,13 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { OutStreamer.SwitchSection(getObjFileLowering().getStaticCtorSection()); EmitAlignment(Align, 0); EmitXXStructorList(GV->getInitializer()); + + if (TM.getRelocationModel() == Reloc::Static && + MAI->hasStaticCtorDtorReferenceInStaticMode()) { + StringRef Sym(".constructors_used"); + OutStreamer.EmitSymbolAttribute(OutContext.GetOrCreateSymbol(Sym), + MCSA_Reference); + } return true; } @@ -465,6 +607,13 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { OutStreamer.SwitchSection(getObjFileLowering().getStaticDtorSection()); EmitAlignment(Align, 0); EmitXXStructorList(GV->getInitializer()); + + if (TM.getRelocationModel() == Reloc::Static && + MAI->hasStaticCtorDtorReferenceInStaticMode()) { + StringRef Sym(".destructors_used"); + OutStreamer.EmitSymbolAttribute(OutContext.GetOrCreateSymbol(Sym), + MCSA_Reference); + } return true; } @@ -475,8 +624,6 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { /// global in the specified llvm.used list for which emitUsedDirectiveFor /// is true, as being used with this directive. void AsmPrinter::EmitLLVMUsedList(Constant *List) { - const char *Directive = MAI->getUsedDirective(); - // Should be an array of 'i8*'. ConstantArray *InitList = dyn_cast<ConstantArray>(List); if (InitList == 0) return; @@ -484,11 +631,9 @@ void AsmPrinter::EmitLLVMUsedList(Constant *List) { for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { const GlobalValue *GV = dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts()); - if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang)) { - O << Directive; - EmitConstantValueOnly(InitList->getOperand(i)); - O << '\n'; - } + if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang)) + OutStreamer.EmitSymbolAttribute(GetGlobalValueSymbol(GV), + MCSA_NoDeadStrip); } } @@ -510,189 +655,35 @@ void AsmPrinter::EmitXXStructorList(Constant *List) { } } - -//===----------------------------------------------------------------------===// -/// LEB 128 number encoding. - -/// PrintULEB128 - Print a series of hexadecimal values (separated by commas) -/// representing an unsigned leb128 value. -void AsmPrinter::PrintULEB128(unsigned Value) const { - char Buffer[20]; - do { - unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); - Value >>= 7; - if (Value) Byte |= 0x80; - O << "0x" << utohex_buffer(Byte, Buffer+20); - if (Value) O << ", "; - } while (Value); -} - -/// PrintSLEB128 - Print a series of hexadecimal values (separated by commas) -/// representing a signed leb128 value. -void AsmPrinter::PrintSLEB128(int Value) const { - int Sign = Value >> (8 * sizeof(Value) - 1); - bool IsMore; - char Buffer[20]; - - do { - unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); - Value >>= 7; - IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; - if (IsMore) Byte |= 0x80; - O << "0x" << utohex_buffer(Byte, Buffer+20); - if (IsMore) O << ", "; - } while (IsMore); -} - //===--------------------------------------------------------------------===// // Emission and print routines // -/// PrintHex - Print a value as a hexadecimal value. -/// -void AsmPrinter::PrintHex(int Value) const { - char Buffer[20]; - O << "0x" << utohex_buffer(static_cast<unsigned>(Value), Buffer+20); -} - -/// EOL - Print a newline character to asm stream. If a comment is present -/// then it will be printed first. Comments should not contain '\n'. -void AsmPrinter::EOL() const { - O << '\n'; -} - -void AsmPrinter::EOL(const std::string &Comment) const { - if (VerboseAsm && !Comment.empty()) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << ' ' - << Comment; - } - O << '\n'; -} - -void AsmPrinter::EOL(const char* Comment) const { - if (VerboseAsm && *Comment) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << ' ' - << Comment; - } - O << '\n'; -} - -static const char *DecodeDWARFEncoding(unsigned Encoding) { - switch (Encoding) { - case dwarf::DW_EH_PE_absptr: - return "absptr"; - case dwarf::DW_EH_PE_omit: - return "omit"; - case dwarf::DW_EH_PE_pcrel: - return "pcrel"; - case dwarf::DW_EH_PE_udata4: - return "udata4"; - case dwarf::DW_EH_PE_udata8: - return "udata8"; - case dwarf::DW_EH_PE_sdata4: - return "sdata4"; - case dwarf::DW_EH_PE_sdata8: - return "sdata8"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: - return "pcrel udata4"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: - return "pcrel sdata4"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: - return "pcrel udata8"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: - return "pcrel sdata8"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: - return "indirect pcrel udata4"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: - return "indirect pcrel sdata4"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: - return "indirect pcrel udata8"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: - return "indirect pcrel sdata8"; - } - - return 0; -} - -void AsmPrinter::EOL(const char *Comment, unsigned Encoding) const { - if (VerboseAsm && *Comment) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << ' ' - << Comment; - - if (const char *EncStr = DecodeDWARFEncoding(Encoding)) - O << " (" << EncStr << ')'; - } - O << '\n'; -} - -/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an -/// unsigned leb128 value. -void AsmPrinter::EmitULEB128Bytes(unsigned Value) const { - if (MAI->hasLEB128()) { - O << "\t.uleb128\t" - << Value; - } else { - O << MAI->getData8bitsDirective(); - PrintULEB128(Value); - } -} - -/// EmitSLEB128Bytes - print an assembler byte data directive to compose a -/// signed leb128 value. -void AsmPrinter::EmitSLEB128Bytes(int Value) const { - if (MAI->hasLEB128()) { - O << "\t.sleb128\t" - << Value; - } else { - O << MAI->getData8bitsDirective(); - PrintSLEB128(Value); - } -} - /// EmitInt8 - Emit a byte directive and value. /// void AsmPrinter::EmitInt8(int Value) const { - O << MAI->getData8bitsDirective(); - PrintHex(Value & 0xFF); + OutStreamer.EmitIntValue(Value, 1, 0/*addrspace*/); } /// EmitInt16 - Emit a short directive and value. /// void AsmPrinter::EmitInt16(int Value) const { - O << MAI->getData16bitsDirective(); - PrintHex(Value & 0xFFFF); + OutStreamer.EmitIntValue(Value, 2, 0/*addrspace*/); } /// EmitInt32 - Emit a long directive and value. /// void AsmPrinter::EmitInt32(int Value) const { - O << MAI->getData32bitsDirective(); - PrintHex(Value); + OutStreamer.EmitIntValue(Value, 4, 0/*addrspace*/); } /// EmitInt64 - Emit a long long directive and value. /// void AsmPrinter::EmitInt64(uint64_t Value) const { - if (MAI->getData64bitsDirective()) { - O << MAI->getData64bitsDirective(); - PrintHex(Value); - } else { - if (TM.getTargetData()->isBigEndian()) { - EmitInt32(unsigned(Value >> 32)); O << '\n'; - EmitInt32(unsigned(Value)); - } else { - EmitInt32(unsigned(Value)); O << '\n'; - EmitInt32(unsigned(Value >> 32)); - } - } + OutStreamer.EmitIntValue(Value, 8, 0/*addrspace*/); } + /// toOctal - Convert the low order bits of X into an octal digit. /// static inline char toOctal(int X) { @@ -725,31 +716,8 @@ static void printStringChar(formatted_raw_ostream &O, unsigned char C) { } } -/// EmitString - Emit a string with quotes and a null terminator. -/// Special characters are emitted properly. -/// \literal (Eg. '\t') \endliteral -void AsmPrinter::EmitString(const StringRef String) const { - EmitString(String.data(), String.size()); -} - -void AsmPrinter::EmitString(const char *String, unsigned Size) const { - const char* AscizDirective = MAI->getAscizDirective(); - if (AscizDirective) - O << AscizDirective; - else - O << MAI->getAsciiDirective(); - O << '\"'; - for (unsigned i = 0; i < Size; ++i) - printStringChar(O, String[i]); - if (AscizDirective) - O << '\"'; - else - O << "\\0\""; -} - - /// EmitFile - Emit a .file directive. -void AsmPrinter::EmitFile(unsigned Number, const std::string &Name) const { +void AsmPrinter::EmitFile(unsigned Number, StringRef Name) const { O << "\t.file\t" << Number << " \""; for (unsigned i = 0, N = Name.size(); i < N; ++i) printStringChar(O, Name[i]); @@ -788,52 +756,26 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV, OutStreamer.EmitValueToAlignment(1 << NumBits, FillValue, 1, 0); } -/// EmitZeros - Emit a block of zeros. +/// LowerConstant - Lower the specified LLVM Constant to an MCExpr. /// -void AsmPrinter::EmitZeros(uint64_t NumZeros, unsigned AddrSpace) const { - if (NumZeros) { - if (MAI->getZeroDirective()) { - O << MAI->getZeroDirective() << NumZeros; - if (MAI->getZeroDirectiveSuffix()) - O << MAI->getZeroDirectiveSuffix(); - O << '\n'; - } else { - for (; NumZeros; --NumZeros) - O << MAI->getData8bitsDirective(AddrSpace) << "0\n"; - } - } -} - -// Print out the specified constant, without a storage class. Only the -// constants valid in constant expressions can occur here. -void AsmPrinter::EmitConstantValueOnly(const Constant *CV) { - if (CV->isNullValue() || isa<UndefValue>(CV)) { - O << '0'; - return; - } - - if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { - O << CI->getZExtValue(); - return; - } +static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { + MCContext &Ctx = AP.OutContext; - if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) { - // This is a constant address for a global variable or function. Use the - // name of the variable or function as the address value. - O << Mang->getMangledName(GV); - return; - } + if (CV->isNullValue() || isa<UndefValue>(CV)) + return MCConstantExpr::Create(0, Ctx); + + if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) + return MCConstantExpr::Create(CI->getZExtValue(), Ctx); - if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) { - GetBlockAddressSymbol(BA)->print(O, MAI); - return; - } + if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) + return MCSymbolRefExpr::Create(AP.GetGlobalValueSymbol(GV), Ctx); + if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) + return MCSymbolRefExpr::Create(AP.GetBlockAddressSymbol(BA), Ctx); const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV); if (CE == 0) { - llvm_unreachable("Unknown constant value!"); - O << '0'; - return; + llvm_unreachable("Unknown constant value to lower!"); + return MCConstantExpr::Create(0, Ctx); } switch (CE->getOpcode()) { @@ -845,406 +787,214 @@ void AsmPrinter::EmitConstantValueOnly(const Constant *CV) { case Instruction::SIToFP: case Instruction::FPToUI: case Instruction::FPToSI: - default: - llvm_unreachable("FIXME: Don't support this constant cast expr"); + default: llvm_unreachable("FIXME: Don't support this constant cast expr"); case Instruction::GetElementPtr: { - // generate a symbolic expression for the byte address - const TargetData *TD = TM.getTargetData(); - const Constant *ptrVal = CE->getOperand(0); - SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end()); - int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0], - idxVec.size()); + const TargetData &TD = *AP.TM.getTargetData(); + // Generate a symbolic expression for the byte address + const Constant *PtrVal = CE->getOperand(0); + SmallVector<Value*, 8> IdxVec(CE->op_begin()+1, CE->op_end()); + int64_t Offset = TD.getIndexedOffset(PtrVal->getType(), &IdxVec[0], + IdxVec.size()); + + const MCExpr *Base = LowerConstant(CE->getOperand(0), AP); if (Offset == 0) - return EmitConstantValueOnly(ptrVal); + return Base; // Truncate/sext the offset to the pointer size. - if (TD->getPointerSizeInBits() != 64) { - int SExtAmount = 64-TD->getPointerSizeInBits(); + if (TD.getPointerSizeInBits() != 64) { + int SExtAmount = 64-TD.getPointerSizeInBits(); Offset = (Offset << SExtAmount) >> SExtAmount; } - if (Offset) - O << '('; - EmitConstantValueOnly(ptrVal); - if (Offset > 0) - O << ") + " << Offset; - else - O << ") - " << -Offset; - return; + return MCBinaryExpr::CreateAdd(Base, MCConstantExpr::Create(Offset, Ctx), + Ctx); } + + case Instruction::Trunc: + // We emit the value and depend on the assembler to truncate the generated + // expression properly. This is important for differences between + // blockaddress labels. Since the two labels are in the same function, it + // is reasonable to treat their delta as a 32-bit value. + // FALL THROUGH. case Instruction::BitCast: - return EmitConstantValueOnly(CE->getOperand(0)); + return LowerConstant(CE->getOperand(0), AP); case Instruction::IntToPtr: { + const TargetData &TD = *AP.TM.getTargetData(); // Handle casts to pointers by changing them into casts to the appropriate // integer type. This promotes constant folding and simplifies this code. - const TargetData *TD = TM.getTargetData(); Constant *Op = CE->getOperand(0); - Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()), + Op = ConstantExpr::getIntegerCast(Op, TD.getIntPtrType(CV->getContext()), false/*ZExt*/); - return EmitConstantValueOnly(Op); + return LowerConstant(Op, AP); } case Instruction::PtrToInt: { + const TargetData &TD = *AP.TM.getTargetData(); // Support only foldable casts to/from pointers that can be eliminated by // changing the pointer to the appropriately sized integer type. Constant *Op = CE->getOperand(0); const Type *Ty = CE->getType(); - const TargetData *TD = TM.getTargetData(); + + const MCExpr *OpExpr = LowerConstant(Op, AP); // We can emit the pointer value into this slot if the slot is an - // integer slot greater or equal to the size of the pointer. - if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType())) - return EmitConstantValueOnly(Op); - - O << "(("; - EmitConstantValueOnly(Op); - APInt ptrMask = - APInt::getAllOnesValue(TD->getTypeAllocSizeInBits(Op->getType())); - - SmallString<40> S; - ptrMask.toStringUnsigned(S); - O << ") & " << S.str() << ')'; - return; + // integer slot equal to the size of the pointer. + if (TD.getTypeAllocSize(Ty) == TD.getTypeAllocSize(Op->getType())) + return OpExpr; + + // Otherwise the pointer is smaller than the resultant integer, mask off + // the high bits so we are sure to get a proper truncation if the input is + // a constant expr. + unsigned InBits = TD.getTypeAllocSizeInBits(Op->getType()); + const MCExpr *MaskExpr = MCConstantExpr::Create(~0ULL >> (64-InBits), Ctx); + return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx); } - case Instruction::Trunc: - // We emit the value and depend on the assembler to truncate the generated - // expression properly. This is important for differences between - // blockaddress labels. Since the two labels are in the same function, it - // is reasonable to treat their delta as a 32-bit value. - return EmitConstantValueOnly(CE->getOperand(0)); - case Instruction::Add: case Instruction::Sub: case Instruction::And: case Instruction::Or: - case Instruction::Xor: - O << '('; - EmitConstantValueOnly(CE->getOperand(0)); - O << ')'; + case Instruction::Xor: { + const MCExpr *LHS = LowerConstant(CE->getOperand(0), AP); + const MCExpr *RHS = LowerConstant(CE->getOperand(1), AP); switch (CE->getOpcode()) { - case Instruction::Add: - O << " + "; - break; - case Instruction::Sub: - O << " - "; - break; - case Instruction::And: - O << " & "; - break; - case Instruction::Or: - O << " | "; - break; - case Instruction::Xor: - O << " ^ "; - break; - default: - break; + default: llvm_unreachable("Unknown binary operator constant cast expr"); + case Instruction::Add: return MCBinaryExpr::CreateAdd(LHS, RHS, Ctx); + case Instruction::Sub: return MCBinaryExpr::CreateSub(LHS, RHS, Ctx); + case Instruction::And: return MCBinaryExpr::CreateAnd(LHS, RHS, Ctx); + case Instruction::Or: return MCBinaryExpr::CreateOr (LHS, RHS, Ctx); + case Instruction::Xor: return MCBinaryExpr::CreateXor(LHS, RHS, Ctx); } - O << '('; - EmitConstantValueOnly(CE->getOperand(1)); - O << ')'; - break; } -} - -/// printAsCString - Print the specified array as a C compatible string, only if -/// the predicate isString is true. -/// -static void printAsCString(formatted_raw_ostream &O, const ConstantArray *CVA, - unsigned LastElt) { - assert(CVA->isString() && "Array is not string compatible!"); - - O << '\"'; - for (unsigned i = 0; i != LastElt; ++i) { - unsigned char C = - (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getZExtValue(); - printStringChar(O, C); } - O << '\"'; } -/// EmitString - Emit a zero-byte-terminated string constant. -/// -void AsmPrinter::EmitString(const ConstantArray *CVA) const { - unsigned NumElts = CVA->getNumOperands(); - if (MAI->getAscizDirective() && NumElts && - cast<ConstantInt>(CVA->getOperand(NumElts-1))->getZExtValue() == 0) { - O << MAI->getAscizDirective(); - printAsCString(O, CVA, NumElts-1); - } else { - O << MAI->getAsciiDirective(); - printAsCString(O, CVA, NumElts); +static void EmitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace, + AsmPrinter &AP) { + if (AddrSpace != 0 || !CA->isString()) { + // Not a string. Print the values in successive locations + for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) + AP.EmitGlobalConstant(CA->getOperand(i), AddrSpace); + return; } - O << '\n'; -} + + // Otherwise, it can be emitted as .ascii. + SmallVector<char, 128> TmpVec; + TmpVec.reserve(CA->getNumOperands()); + for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) + TmpVec.push_back(cast<ConstantInt>(CA->getOperand(i))->getZExtValue()); -void AsmPrinter::EmitGlobalConstantArray(const ConstantArray *CVA, - unsigned AddrSpace) { - if (CVA->isString()) { - EmitString(CVA); - } else { // Not a string. Print the values in successive locations - for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i) - EmitGlobalConstant(CVA->getOperand(i), AddrSpace); - } + AP.OutStreamer.EmitBytes(StringRef(TmpVec.data(), TmpVec.size()), AddrSpace); } -void AsmPrinter::EmitGlobalConstantVector(const ConstantVector *CP) { - const VectorType *PTy = CP->getType(); - - for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I) - EmitGlobalConstant(CP->getOperand(I)); +static void EmitGlobalConstantVector(const ConstantVector *CV, + unsigned AddrSpace, AsmPrinter &AP) { + for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i) + AP.EmitGlobalConstant(CV->getOperand(i), AddrSpace); } -void AsmPrinter::EmitGlobalConstantStruct(const ConstantStruct *CVS, - unsigned AddrSpace) { +static void EmitGlobalConstantStruct(const ConstantStruct *CS, + unsigned AddrSpace, AsmPrinter &AP) { // Print the fields in successive locations. Pad to align if needed! - const TargetData *TD = TM.getTargetData(); - unsigned Size = TD->getTypeAllocSize(CVS->getType()); - const StructLayout *cvsLayout = TD->getStructLayout(CVS->getType()); - uint64_t sizeSoFar = 0; - for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) { - const Constant* field = CVS->getOperand(i); + const TargetData *TD = AP.TM.getTargetData(); + unsigned Size = TD->getTypeAllocSize(CS->getType()); + const StructLayout *Layout = TD->getStructLayout(CS->getType()); + uint64_t SizeSoFar = 0; + for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) { + const Constant *Field = CS->getOperand(i); // Check if padding is needed and insert one or more 0s. - uint64_t fieldSize = TD->getTypeAllocSize(field->getType()); - uint64_t padSize = ((i == e-1 ? Size : cvsLayout->getElementOffset(i+1)) - - cvsLayout->getElementOffset(i)) - fieldSize; - sizeSoFar += fieldSize + padSize; + uint64_t FieldSize = TD->getTypeAllocSize(Field->getType()); + uint64_t PadSize = ((i == e-1 ? Size : Layout->getElementOffset(i+1)) + - Layout->getElementOffset(i)) - FieldSize; + SizeSoFar += FieldSize + PadSize; // Now print the actual field value. - EmitGlobalConstant(field, AddrSpace); + AP.EmitGlobalConstant(Field, AddrSpace); // Insert padding - this may include padding to increase the size of the // current field up to the ABI size (if the struct is not packed) as well // as padding to ensure that the next field starts at the right offset. - EmitZeros(padSize, AddrSpace); + AP.OutStreamer.EmitZeros(PadSize, AddrSpace); } - assert(sizeSoFar == cvsLayout->getSizeInBytes() && + assert(SizeSoFar == Layout->getSizeInBytes() && "Layout of constant struct may be incorrect!"); } -void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP, - unsigned AddrSpace) { +static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, + AsmPrinter &AP) { // FP Constants are printed as integer constants to avoid losing - // precision... - LLVMContext &Context = CFP->getContext(); - const TargetData *TD = TM.getTargetData(); + // precision. if (CFP->getType()->isDoubleTy()) { - double Val = CFP->getValueAPF().convertToDouble(); // for comment only - uint64_t i = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); - if (MAI->getData64bitsDirective(AddrSpace)) { - O << MAI->getData64bitsDirective(AddrSpace) << i; - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " double " << Val; - } - O << '\n'; - } else if (TD->isBigEndian()) { - O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " most significant word of double " << Val; - } - O << '\n'; - O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " least significant word of double " << Val; - } - O << '\n'; - } else { - O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " least significant word of double " << Val; - } - O << '\n'; - O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " most significant word of double " << Val; - } - O << '\n'; + if (AP.VerboseAsm) { + double Val = CFP->getValueAPF().convertToDouble(); + AP.OutStreamer.GetCommentOS() << "double " << Val << '\n'; } + + uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); + AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace); return; } if (CFP->getType()->isFloatTy()) { - float Val = CFP->getValueAPF().convertToFloat(); // for comment only - O << MAI->getData32bitsDirective(AddrSpace) - << CFP->getValueAPF().bitcastToAPInt().getZExtValue(); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " float " << Val; + if (AP.VerboseAsm) { + float Val = CFP->getValueAPF().convertToFloat(); + AP.OutStreamer.GetCommentOS() << "float " << Val << '\n'; } - O << '\n'; + uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); + AP.OutStreamer.EmitIntValue(Val, 4, AddrSpace); return; } if (CFP->getType()->isX86_FP80Ty()) { // all long double variants are printed as hex // api needed to prevent premature destruction - APInt api = CFP->getValueAPF().bitcastToAPInt(); - const uint64_t *p = api.getRawData(); - // Convert to double so we can print the approximate val as a comment. - APFloat DoubleVal = CFP->getValueAPF(); - bool ignored; - DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, - &ignored); - if (TD->isBigEndian()) { - O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " most significant halfword of x86_fp80 ~" - << DoubleVal.convertToDouble(); - } - O << '\n'; - O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " next halfword"; - } - O << '\n'; - O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " next halfword"; - } - O << '\n'; - O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " next halfword"; - } - O << '\n'; - O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " least significant halfword"; - } - O << '\n'; - } else { - O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " least significant halfword of x86_fp80 ~" - << DoubleVal.convertToDouble(); - } - O << '\n'; - O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " next halfword"; - } - O << '\n'; - O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " next halfword"; - } - O << '\n'; - O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " next halfword"; - } - O << '\n'; - O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " most significant halfword"; - } - O << '\n'; + APInt API = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t *p = API.getRawData(); + if (AP.VerboseAsm) { + // Convert to double so we can print the approximate val as a comment. + APFloat DoubleVal = CFP->getValueAPF(); + bool ignored; + DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, + &ignored); + AP.OutStreamer.GetCommentOS() << "x86_fp80 ~= " + << DoubleVal.convertToDouble() << '\n'; } - EmitZeros(TD->getTypeAllocSize(Type::getX86_FP80Ty(Context)) - - TD->getTypeStoreSize(Type::getX86_FP80Ty(Context)), AddrSpace); + + if (AP.TM.getTargetData()->isBigEndian()) { + AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace); + AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); + } else { + AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); + AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace); + } + + // Emit the tail padding for the long double. + const TargetData &TD = *AP.TM.getTargetData(); + AP.OutStreamer.EmitZeros(TD.getTypeAllocSize(CFP->getType()) - + TD.getTypeStoreSize(CFP->getType()), AddrSpace); return; } - if (CFP->getType()->isPPC_FP128Ty()) { - // all long double variants are printed as hex - // api needed to prevent premature destruction - APInt api = CFP->getValueAPF().bitcastToAPInt(); - const uint64_t *p = api.getRawData(); - if (TD->isBigEndian()) { - O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " most significant word of ppc_fp128"; - } - O << '\n'; - O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " next word"; - } - O << '\n'; - O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " next word"; - } - O << '\n'; - O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " least significant word"; - } - O << '\n'; - } else { - O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " least significant word of ppc_fp128"; - } - O << '\n'; - O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " next word"; - } - O << '\n'; - O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " next word"; - } - O << '\n'; - O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << " most significant word"; - } - O << '\n'; - } - return; - } else llvm_unreachable("Floating point constant type not handled"); + assert(CFP->getType()->isPPC_FP128Ty() && + "Floating point constant type not handled"); + // All long double variants are printed as hex api needed to prevent + // premature destruction. + APInt API = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t *p = API.getRawData(); + if (AP.TM.getTargetData()->isBigEndian()) { + AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); + AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace); + } else { + AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace); + AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); + } } -void AsmPrinter::EmitGlobalConstantLargeInt(const ConstantInt *CI, - unsigned AddrSpace) { - const TargetData *TD = TM.getTargetData(); +static void EmitGlobalConstantLargeInt(const ConstantInt *CI, + unsigned AddrSpace, AsmPrinter &AP) { + const TargetData *TD = AP.TM.getTargetData(); unsigned BitWidth = CI->getBitWidth(); assert((BitWidth & 63) == 0 && "only support multiples of 64-bits"); @@ -1253,100 +1003,58 @@ void AsmPrinter::EmitGlobalConstantLargeInt(const ConstantInt *CI, // quantities at a time. const uint64_t *RawData = CI->getValue().getRawData(); for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) { - uint64_t Val; - if (TD->isBigEndian()) - Val = RawData[e - i - 1]; - else - Val = RawData[i]; - - if (MAI->getData64bitsDirective(AddrSpace)) { - O << MAI->getData64bitsDirective(AddrSpace) << Val << '\n'; - continue; - } - - // Emit two 32-bit chunks, order depends on endianness. - unsigned FirstChunk = unsigned(Val), SecondChunk = unsigned(Val >> 32); - const char *FirstName = " least", *SecondName = " most"; - if (TD->isBigEndian()) { - std::swap(FirstChunk, SecondChunk); - std::swap(FirstName, SecondName); - } - - O << MAI->getData32bitsDirective(AddrSpace) << FirstChunk; - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << FirstName << " significant half of i64 " << Val; - } - O << '\n'; - - O << MAI->getData32bitsDirective(AddrSpace) << SecondChunk; - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() - << SecondName << " significant half of i64 " << Val; - } - O << '\n'; + uint64_t Val = TD->isBigEndian() ? RawData[e - i - 1] : RawData[i]; + AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace); } } /// EmitGlobalConstant - Print a general LLVM constant to the .s file. void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) { - const TargetData *TD = TM.getTargetData(); - const Type *type = CV->getType(); - unsigned Size = TD->getTypeAllocSize(type); - - if (CV->isNullValue() || isa<UndefValue>(CV)) { - EmitZeros(Size, AddrSpace); - return; - } - - if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) { - EmitGlobalConstantArray(CVA , AddrSpace); - return; - } - - if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) { - EmitGlobalConstantStruct(CVS, AddrSpace); - return; + if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) { + uint64_t Size = TM.getTargetData()->getTypeAllocSize(CV->getType()); + return OutStreamer.EmitZeros(Size, AddrSpace); } - if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) { - EmitGlobalConstantFP(CFP, AddrSpace); - return; - } - if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { - // If we can directly emit an 8-byte constant, do it. - if (Size == 8) - if (const char *Data64Dir = MAI->getData64bitsDirective(AddrSpace)) { - O << Data64Dir << CI->getZExtValue() << '\n'; - return; - } - - // Small integers are handled below; large integers are handled here. - if (Size > 4) { - EmitGlobalConstantLargeInt(CI, AddrSpace); + unsigned Size = TM.getTargetData()->getTypeAllocSize(CV->getType()); + switch (Size) { + case 1: + case 2: + case 4: + case 8: + if (VerboseAsm) + OutStreamer.GetCommentOS() << format("0x%llx\n", CI->getZExtValue()); + OutStreamer.EmitIntValue(CI->getZExtValue(), Size, AddrSpace); + return; + default: + EmitGlobalConstantLargeInt(CI, AddrSpace, *this); return; } } - if (const ConstantVector *CP = dyn_cast<ConstantVector>(CV)) { - EmitGlobalConstantVector(CP); - return; - } + if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) + return EmitGlobalConstantArray(CVA, AddrSpace, *this); + + if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) + return EmitGlobalConstantStruct(CVS, AddrSpace, *this); - printDataDirective(type, AddrSpace); - EmitConstantValueOnly(CV); - if (VerboseAsm) { - if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { - SmallString<40> S; - CI->getValue().toStringUnsigned(S, 16); - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " 0x" << S.str(); - } + if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) + return EmitGlobalConstantFP(CFP, AddrSpace, *this); + + if (const ConstantVector *V = dyn_cast<ConstantVector>(CV)) + return EmitGlobalConstantVector(V, AddrSpace, *this); + + if (isa<ConstantPointerNull>(CV)) { + unsigned Size = TM.getTargetData()->getTypeAllocSize(CV->getType()); + OutStreamer.EmitIntValue(0, Size, AddrSpace); + return; } - O << '\n'; + + // Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it + // thread the streamer with EmitValue. + OutStreamer.EmitValue(LowerConstant(CV, *this), + TM.getTargetData()->getTypeAllocSize(CV->getType()), + AddrSpace); } void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { @@ -1397,22 +1105,21 @@ void AsmPrinter::processDebugLoc(const MachineInstr *MI, DebugLoc DL = MI->getDebugLoc(); if (DL.isUnknown()) return; - DebugLocTuple CurDLT = MF->getDebugLocTuple(DL); - if (CurDLT.Scope == 0) + DILocation CurDLT = MF->getDILocation(DL); + if (CurDLT.getScope().isNull()) return; - if (BeforePrintingInsn) { - if (CurDLT != PrevDLT) { - unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col, - CurDLT.Scope); - printLabel(L); - O << '\n'; - DW->BeginScope(MI, L); - PrevDLT = CurDLT; - } - } else { + if (!BeforePrintingInsn) { // After printing instruction DW->EndScope(MI); + } else if (CurDLT.getNode() != PrevDLT) { + unsigned L = DW->RecordSourceLine(CurDLT.getLineNumber(), + CurDLT.getColumnNumber(), + CurDLT.getScope().getNode()); + printLabel(L); + O << '\n'; + DW->BeginScope(MI, L); + PrevDLT = CurDLT.getNode(); } } @@ -1587,9 +1294,8 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { unsigned OpFlags = MI->getOperand(OpNo).getImm(); ++OpNo; // Skip over the ID number. - if (Modifier[0]=='l') // labels are target independent - GetMBBSymbol(MI->getOperand(OpNo).getMBB() - ->getNumber())->print(O, MAI); + if (Modifier[0] == 'l') // labels are target independent + O << *GetMBBSymbol(MI->getOperand(OpNo).getMBB()->getNumber()); else { AsmPrinter *AP = const_cast<AsmPrinter*>(this); if ((OpFlags & 7) == 4) { @@ -1604,8 +1310,7 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { if (Error) { std::string msg; raw_string_ostream Msg(msg); - Msg << "Invalid operand found in inline asm: '" - << AsmStr << "'\n"; + Msg << "Invalid operand found in inline asm: '" << AsmStr << "'\n"; MI->print(Msg); llvm_report_error(Msg.str()); } @@ -1694,10 +1399,121 @@ MCSymbol *AsmPrinter::GetMBBSymbol(unsigned MBBID) const { SmallString<60> Name; raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BB" << getFunctionNumber() << '_' << MBBID; - return OutContext.GetOrCreateSymbol(Name.str()); } +/// GetCPISymbol - Return the symbol for the specified constant pool entry. +MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { + SmallString<60> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "CPI" + << getFunctionNumber() << '_' << CPID; + return OutContext.GetOrCreateSymbol(Name.str()); +} + +/// GetJTISymbol - Return the symbol for the specified jump table entry. +MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const { + const char *Prefix = isLinkerPrivate ? MAI->getLinkerPrivateGlobalPrefix() : + MAI->getPrivateGlobalPrefix(); + SmallString<60> Name; + raw_svector_ostream(Name) << Prefix << "JTI" << getFunctionNumber() << '_' + << JTID; + return OutContext.GetOrCreateSymbol(Name.str()); +} + +/// GetGlobalValueSymbol - Return the MCSymbol for the specified global +/// value. +MCSymbol *AsmPrinter::GetGlobalValueSymbol(const GlobalValue *GV) const { + SmallString<60> NameStr; + Mang->getNameWithPrefix(NameStr, GV, false); + return OutContext.GetOrCreateSymbol(NameStr.str()); +} + +/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with +/// global value name as its base, with the specified suffix, and where the +/// symbol is forced to have private linkage if ForcePrivate is true. +MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV, + StringRef Suffix, + bool ForcePrivate) const { + SmallString<60> NameStr; + Mang->getNameWithPrefix(NameStr, GV, ForcePrivate); + NameStr.append(Suffix.begin(), Suffix.end()); + return OutContext.GetOrCreateSymbol(NameStr.str()); +} + +/// GetExternalSymbolSymbol - Return the MCSymbol for the specified +/// ExternalSymbol. +MCSymbol *AsmPrinter::GetExternalSymbolSymbol(StringRef Sym) const { + SmallString<60> NameStr; + Mang->getNameWithPrefix(NameStr, Sym); + return OutContext.GetOrCreateSymbol(NameStr.str()); +} + + + +/// PrintParentLoopComment - Print comments about parent loops of this one. +static void PrintParentLoopComment(raw_ostream &OS, const MachineLoop *Loop, + unsigned FunctionNumber) { + if (Loop == 0) return; + PrintParentLoopComment(OS, Loop->getParentLoop(), FunctionNumber); + OS.indent(Loop->getLoopDepth()*2) + << "Parent Loop BB" << FunctionNumber << "_" + << Loop->getHeader()->getNumber() + << " Depth=" << Loop->getLoopDepth() << '\n'; +} + + +/// PrintChildLoopComment - Print comments about child loops within +/// the loop for this basic block, with nesting. +static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop, + unsigned FunctionNumber) { + // Add child loop information + for (MachineLoop::iterator CL = Loop->begin(), E = Loop->end();CL != E; ++CL){ + OS.indent((*CL)->getLoopDepth()*2) + << "Child Loop BB" << FunctionNumber << "_" + << (*CL)->getHeader()->getNumber() << " Depth " << (*CL)->getLoopDepth() + << '\n'; + PrintChildLoopComment(OS, *CL, FunctionNumber); + } +} + +/// EmitComments - Pretty-print comments for basic blocks. +static void PrintBasicBlockLoopComments(const MachineBasicBlock &MBB, + const MachineLoopInfo *LI, + const AsmPrinter &AP) { + // Add loop depth information + const MachineLoop *Loop = LI->getLoopFor(&MBB); + if (Loop == 0) return; + + MachineBasicBlock *Header = Loop->getHeader(); + assert(Header && "No header for loop"); + + // If this block is not a loop header, just print out what is the loop header + // and return. + if (Header != &MBB) { + AP.OutStreamer.AddComment(" in Loop: Header=BB" + + Twine(AP.getFunctionNumber())+"_" + + Twine(Loop->getHeader()->getNumber())+ + " Depth="+Twine(Loop->getLoopDepth())); + return; + } + + // Otherwise, it is a loop header. Print out information about child and + // parent loops. + raw_ostream &OS = AP.OutStreamer.GetCommentOS(); + + PrintParentLoopComment(OS, Loop->getParentLoop(), AP.getFunctionNumber()); + + OS << "=>"; + OS.indent(Loop->getLoopDepth()*2-2); + + OS << "This "; + if (Loop->empty()) + OS << "Inner "; + OS << "Loop Header: Depth=" + Twine(Loop->getLoopDepth()) << '\n'; + + PrintChildLoopComment(OS, Loop, AP.getFunctionNumber()); +} + /// EmitBasicBlockStart - This method prints the label for the specified /// MachineBasicBlock, an alignment (if present) and a comment describing @@ -1713,38 +1529,33 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { // forward references to labels without knowing what their numbers // will be. if (MBB->hasAddressTaken()) { - GetBlockAddressSymbol(MBB->getBasicBlock()->getParent(), - MBB->getBasicBlock())->print(O, MAI); - O << ':'; - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " Address Taken"; - } - O << '\n'; + const BasicBlock *BB = MBB->getBasicBlock(); + if (VerboseAsm) + OutStreamer.AddComment("Address Taken"); + OutStreamer.EmitLabel(GetBlockAddressSymbol(BB->getParent(), BB)); } // Print the main label for the block. if (MBB->pred_empty() || MBB->isOnlyReachableByFallthrough()) { - if (VerboseAsm) + if (VerboseAsm) { + // NOTE: Want this comment at start of line. O << MAI->getCommentString() << " BB#" << MBB->getNumber() << ':'; + if (const BasicBlock *BB = MBB->getBasicBlock()) + if (BB->hasName()) + OutStreamer.AddComment("%" + BB->getName()); + + PrintBasicBlockLoopComments(*MBB, LI, *this); + OutStreamer.AddBlankLine(); + } } else { - GetMBBSymbol(MBB->getNumber())->print(O, MAI); - O << ':'; - if (!VerboseAsm) - O << '\n'; - } - - // Print some comments to accompany the label. - if (VerboseAsm) { - if (const BasicBlock *BB = MBB->getBasicBlock()) - if (BB->hasName()) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, BB, /*PrintType=*/false); - } + if (VerboseAsm) { + if (const BasicBlock *BB = MBB->getBasicBlock()) + if (BB->hasName()) + OutStreamer.AddComment("%" + BB->getName()); + PrintBasicBlockLoopComments(*MBB, LI, *this); + } - EmitComments(*MBB); - O << '\n'; + OutStreamer.EmitLabel(GetMBBSymbol(MBB->getNumber())); } } @@ -1756,10 +1567,9 @@ void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, return; O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() - << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; - GetMBBSymbol(MBB->getNumber())->print(O, MAI); - O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << uid << '\n'; + << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',' + << *GetMBBSymbol(MBB->getNumber()) + << '-' << *GetJTISymbol(uid) << '\n'; } void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2, @@ -1769,64 +1579,27 @@ void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2, O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() << getFunctionNumber() << '_' << uid << '_' << uid2 - << "_set_" << MBB->getNumber() << ','; - GetMBBSymbol(MBB->getNumber())->print(O, MAI); - O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << "_set_" << MBB->getNumber() << ',' + << *GetMBBSymbol(MBB->getNumber()) + << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << uid << '_' << uid2 << '\n'; } -/// printDataDirective - This method prints the asm directive for the -/// specified type. -void AsmPrinter::printDataDirective(const Type *type, unsigned AddrSpace) { - const TargetData *TD = TM.getTargetData(); - switch (type->getTypeID()) { - case Type::FloatTyID: case Type::DoubleTyID: - case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: - assert(0 && "Should have already output floating point constant."); - default: - assert(0 && "Can't handle printing this type of thing"); - case Type::IntegerTyID: { - unsigned BitWidth = cast<IntegerType>(type)->getBitWidth(); - if (BitWidth <= 8) - O << MAI->getData8bitsDirective(AddrSpace); - else if (BitWidth <= 16) - O << MAI->getData16bitsDirective(AddrSpace); - else if (BitWidth <= 32) - O << MAI->getData32bitsDirective(AddrSpace); - else if (BitWidth <= 64) { - assert(MAI->getData64bitsDirective(AddrSpace) && - "Target cannot handle 64-bit constant exprs!"); - O << MAI->getData64bitsDirective(AddrSpace); - } else { - llvm_unreachable("Target cannot handle given data directive width!"); - } +void AsmPrinter::printVisibility(MCSymbol *Sym, unsigned Visibility) const { + MCSymbolAttr Attr = MCSA_Invalid; + + switch (Visibility) { + default: break; + case GlobalValue::HiddenVisibility: + Attr = MAI->getHiddenVisibilityAttr(); break; - } - case Type::PointerTyID: - if (TD->getPointerSize() == 8) { - assert(MAI->getData64bitsDirective(AddrSpace) && - "Target cannot handle 64-bit pointer exprs!"); - O << MAI->getData64bitsDirective(AddrSpace); - } else if (TD->getPointerSize() == 2) { - O << MAI->getData16bitsDirective(AddrSpace); - } else if (TD->getPointerSize() == 1) { - O << MAI->getData8bitsDirective(AddrSpace); - } else { - O << MAI->getData32bitsDirective(AddrSpace); - } + case GlobalValue::ProtectedVisibility: + Attr = MAI->getProtectedVisibilityAttr(); break; } -} -void AsmPrinter::printVisibility(const std::string& Name, - unsigned Visibility) const { - if (Visibility == GlobalValue::HiddenVisibility) { - if (const char *Directive = MAI->getHiddenDirective()) - O << Directive << Name << '\n'; - } else if (Visibility == GlobalValue::ProtectedVisibility) { - if (const char *Directive = MAI->getProtectedDirective()) - O << Directive << Name << '\n'; - } + if (Attr != MCSA_Invalid) + OutStreamer.EmitSymbolAttribute(Sym, Attr); } void AsmPrinter::printOffset(int64_t Offset) const { @@ -1856,8 +1629,8 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { return GMP; } - errs() << "no GCMetadataPrinter registered for GC: " << Name << "\n"; - llvm_unreachable(0); + llvm_report_error("no GCMetadataPrinter registered for GC: " + Twine(Name)); + return 0; } /// EmitComments - Pretty-print comments for instructions @@ -1868,20 +1641,20 @@ void AsmPrinter::EmitComments(const MachineInstr &MI) const { bool Newline = false; if (!MI.getDebugLoc().isUnknown()) { - DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc()); + DILocation DLT = MF->getDILocation(MI.getDebugLoc()); // Print source line info. O.PadToColumn(MAI->getCommentColumn()); O << MAI->getCommentString() << ' '; - DIScope Scope(DLT.Scope); + DIScope Scope = DLT.getScope(); // Omit the directory, because it's likely to be long and uninteresting. if (!Scope.isNull()) O << Scope.getFilename(); else O << "<unknown>"; - O << ':' << DLT.Line; - if (DLT.Col != 0) - O << ':' << DLT.Col; + O << ':' << DLT.getLineNumber(); + if (DLT.getColumnNumber() != 0) + O << ':' << DLT.getColumnNumber(); Newline = true; } @@ -1943,80 +1716,3 @@ void AsmPrinter::EmitComments(const MachineInstr &MI) const { } } -/// PrintChildLoopComment - Print comments about child loops within -/// the loop for this basic block, with nesting. -/// -static void PrintChildLoopComment(formatted_raw_ostream &O, - const MachineLoop *loop, - const MCAsmInfo *MAI, - int FunctionNumber) { - // Add child loop information - for(MachineLoop::iterator cl = loop->begin(), - clend = loop->end(); - cl != clend; - ++cl) { - MachineBasicBlock *Header = (*cl)->getHeader(); - assert(Header && "No header for loop"); - - O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - - O << MAI->getCommentString(); - O.indent(((*cl)->getLoopDepth()-1)*2) - << " Child Loop BB" << FunctionNumber << "_" - << Header->getNumber() << " Depth " << (*cl)->getLoopDepth(); - - PrintChildLoopComment(O, *cl, MAI, FunctionNumber); - } -} - -/// EmitComments - Pretty-print comments for basic blocks -void AsmPrinter::EmitComments(const MachineBasicBlock &MBB) const { - if (VerboseAsm) { - // Add loop depth information - const MachineLoop *loop = LI->getLoopFor(&MBB); - - if (loop) { - // Print a newline after bb# annotation. - O << "\n"; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " Loop Depth " << loop->getLoopDepth() - << '\n'; - - O.PadToColumn(MAI->getCommentColumn()); - - MachineBasicBlock *Header = loop->getHeader(); - assert(Header && "No header for loop"); - - if (Header == &MBB) { - O << MAI->getCommentString() << " Loop Header"; - PrintChildLoopComment(O, loop, MAI, getFunctionNumber()); - } - else { - O << MAI->getCommentString() << " Loop Header is BB" - << getFunctionNumber() << "_" << loop->getHeader()->getNumber(); - } - - if (loop->empty()) { - O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " Inner Loop"; - } - - // Add parent loop information - for (const MachineLoop *CurLoop = loop->getParentLoop(); - CurLoop; - CurLoop = CurLoop->getParentLoop()) { - MachineBasicBlock *Header = CurLoop->getHeader(); - assert(Header && "No header for loop"); - - O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString(); - O.indent((CurLoop->getLoopDepth()-1)*2) - << " Inside Loop BB" << getFunctionNumber() << "_" - << Header->getNumber() << " Depth " << CurLoop->getLoopDepth(); - } - } - } -} diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index b85e11a..349e0ac 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -13,12 +13,16 @@ #include "DIE.h" #include "DwarfPrinter.h" +#include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" +#include "llvm/Support/FormattedStream.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -49,31 +53,33 @@ void DIEAbbrev::Profile(FoldingSetNodeID &ID) const { /// Emit - Print the abbreviation using the specified asm printer. /// -void DIEAbbrev::Emit(const AsmPrinter *Asm) const { +void DIEAbbrev::Emit(const DwarfPrinter *DP) const { // Emit its Dwarf tag type. - Asm->EmitULEB128Bytes(Tag); - Asm->EOL(dwarf::TagString(Tag)); + // FIXME: Doing work even in non-asm-verbose runs. + DP->EmitULEB128(Tag, dwarf::TagString(Tag)); // Emit whether it has children DIEs. - Asm->EmitULEB128Bytes(ChildrenFlag); - Asm->EOL(dwarf::ChildrenString(ChildrenFlag)); + // FIXME: Doing work even in non-asm-verbose runs. + DP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag)); // For each attribute description. for (unsigned i = 0, N = Data.size(); i < N; ++i) { const DIEAbbrevData &AttrData = Data[i]; // Emit attribute type. - Asm->EmitULEB128Bytes(AttrData.getAttribute()); - Asm->EOL(dwarf::AttributeString(AttrData.getAttribute())); + // FIXME: Doing work even in non-asm-verbose runs. + DP->EmitULEB128(AttrData.getAttribute(), + dwarf::AttributeString(AttrData.getAttribute())); // Emit form type. - Asm->EmitULEB128Bytes(AttrData.getForm()); - Asm->EOL(dwarf::FormEncodingString(AttrData.getForm())); + // FIXME: Doing work even in non-asm-verbose runs. + DP->EmitULEB128(AttrData.getForm(), + dwarf::FormEncodingString(AttrData.getForm())); } // Mark end of abbreviation. - Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(1)"); - Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(2)"); + DP->EmitULEB128(0, "EOM(1)"); + DP->EmitULEB128(0, "EOM(2)"); } #ifndef NDEBUG @@ -182,22 +188,24 @@ void DIEValue::dump() { /// EmitValue - Emit integer of appropriate size. /// -void DIEInteger::EmitValue(Dwarf *D, unsigned Form) const { +void DIEInteger::EmitValue(DwarfPrinter *D, unsigned Form) const { const AsmPrinter *Asm = D->getAsm(); + unsigned Size = ~0U; switch (Form) { case dwarf::DW_FORM_flag: // Fall thru case dwarf::DW_FORM_ref1: // Fall thru - case dwarf::DW_FORM_data1: Asm->EmitInt8(Integer); break; + case dwarf::DW_FORM_data1: Size = 1; break; case dwarf::DW_FORM_ref2: // Fall thru - case dwarf::DW_FORM_data2: Asm->EmitInt16(Integer); break; + case dwarf::DW_FORM_data2: Size = 2; break; case dwarf::DW_FORM_ref4: // Fall thru - case dwarf::DW_FORM_data4: Asm->EmitInt32(Integer); break; + case dwarf::DW_FORM_data4: Size = 4; break; case dwarf::DW_FORM_ref8: // Fall thru - case dwarf::DW_FORM_data8: Asm->EmitInt64(Integer); break; - case dwarf::DW_FORM_udata: Asm->EmitULEB128Bytes(Integer); break; - case dwarf::DW_FORM_sdata: Asm->EmitSLEB128Bytes(Integer); break; + case dwarf::DW_FORM_data8: Size = 8; break; + case dwarf::DW_FORM_udata: D->EmitULEB128(Integer); return; + case dwarf::DW_FORM_sdata: D->EmitSLEB128(Integer, ""); return; default: llvm_unreachable("DIE Value form not supported yet"); } + Asm->OutStreamer.EmitIntValue(Integer, Size, 0/*addrspace*/); } /// SizeOf - Determine size of integer value in bytes. @@ -233,8 +241,10 @@ void DIEInteger::print(raw_ostream &O) { /// EmitValue - Emit string value. /// -void DIEString::EmitValue(Dwarf *D, unsigned Form) const { - D->getAsm()->EmitString(Str); +void DIEString::EmitValue(DwarfPrinter *D, unsigned Form) const { + D->getAsm()->OutStreamer.EmitBytes(Str, /*addrspace*/0); + // Emit nul terminator. + D->getAsm()->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); } #ifndef NDEBUG @@ -249,7 +259,7 @@ void DIEString::print(raw_ostream &O) { /// EmitValue - Emit label value. /// -void DIEDwarfLabel::EmitValue(Dwarf *D, unsigned Form) const { +void DIEDwarfLabel::EmitValue(DwarfPrinter *D, unsigned Form) const { bool IsSmall = Form == dwarf::DW_FORM_data4; D->EmitReference(Label, false, IsSmall); } @@ -274,9 +284,9 @@ void DIEDwarfLabel::print(raw_ostream &O) { /// EmitValue - Emit label value. /// -void DIEObjectLabel::EmitValue(Dwarf *D, unsigned Form) const { +void DIEObjectLabel::EmitValue(DwarfPrinter *D, unsigned Form) const { bool IsSmall = Form == dwarf::DW_FORM_data4; - D->EmitReference(Label, false, IsSmall); + D->EmitReference(Sym, false, IsSmall); } /// SizeOf - Determine size of label value in bytes. @@ -288,7 +298,7 @@ unsigned DIEObjectLabel::SizeOf(const TargetData *TD, unsigned Form) const { #ifndef NDEBUG void DIEObjectLabel::print(raw_ostream &O) { - O << "Obj: " << Label; + O << "Obj: " << Sym->getName(); } #endif @@ -298,7 +308,7 @@ void DIEObjectLabel::print(raw_ostream &O) { /// EmitValue - Emit delta value. /// -void DIESectionOffset::EmitValue(Dwarf *D, unsigned Form) const { +void DIESectionOffset::EmitValue(DwarfPrinter *D, unsigned Form) const { bool IsSmall = Form == dwarf::DW_FORM_data4; D->EmitSectionOffset(Label.getTag(), Section.getTag(), Label.getNumber(), Section.getNumber(), @@ -328,7 +338,7 @@ void DIESectionOffset::print(raw_ostream &O) { /// EmitValue - Emit delta value. /// -void DIEDelta::EmitValue(Dwarf *D, unsigned Form) const { +void DIEDelta::EmitValue(DwarfPrinter *D, unsigned Form) const { bool IsSmall = Form == dwarf::DW_FORM_data4; D->EmitDifference(LabelHi, LabelLo, IsSmall); } @@ -355,7 +365,7 @@ void DIEDelta::print(raw_ostream &O) { /// EmitValue - Emit debug information entry offset. /// -void DIEEntry::EmitValue(Dwarf *D, unsigned Form) const { +void DIEEntry::EmitValue(DwarfPrinter *D, unsigned Form) const { D->getAsm()->EmitInt32(Entry->getOffset()); } @@ -383,19 +393,19 @@ unsigned DIEBlock::ComputeSize(const TargetData *TD) { /// EmitValue - Emit block data. /// -void DIEBlock::EmitValue(Dwarf *D, unsigned Form) const { +void DIEBlock::EmitValue(DwarfPrinter *D, unsigned Form) const { const AsmPrinter *Asm = D->getAsm(); switch (Form) { case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break; case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; - case dwarf::DW_FORM_block: Asm->EmitULEB128Bytes(Size); break; + case dwarf::DW_FORM_block: D->EmitULEB128(Size); break; default: llvm_unreachable("Improper form for block"); break; } const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData(); for (unsigned i = 0, N = Values.size(); i < N; ++i) { - Asm->EOL(); + Asm->O << '\n'; Values[i]->EmitValue(D, AbbrevData[i].getForm()); } } diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index a6dc9b6..af90289 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -23,8 +23,9 @@ namespace llvm { class AsmPrinter; - class Dwarf; + class DwarfPrinter; class TargetData; + class MCSymbol; //===--------------------------------------------------------------------===// /// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a @@ -100,7 +101,7 @@ namespace llvm { /// Emit - Print the abbreviation using the specified asm printer. /// - void Emit(const AsmPrinter *Asm) const; + void Emit(const DwarfPrinter *DP) const; #ifndef NDEBUG void print(raw_ostream &O); @@ -221,7 +222,7 @@ namespace llvm { /// EmitValue - Emit value via the Dwarf writer. /// - virtual void EmitValue(Dwarf *D, unsigned Form) const = 0; + virtual void EmitValue(DwarfPrinter *D, unsigned Form) const = 0; /// SizeOf - Return the size of a value in bytes. /// @@ -261,7 +262,7 @@ namespace llvm { /// EmitValue - Emit integer of appropriate size. /// - virtual void EmitValue(Dwarf *D, unsigned Form) const; + virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; /// SizeOf - Determine size of integer value in bytes. /// @@ -287,7 +288,7 @@ namespace llvm { /// EmitValue - Emit string value. /// - virtual void EmitValue(Dwarf *D, unsigned Form) const; + virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; /// SizeOf - Determine size of string value in bytes. /// @@ -314,7 +315,7 @@ namespace llvm { /// EmitValue - Emit label value. /// - virtual void EmitValue(Dwarf *D, unsigned Form) const; + virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; /// SizeOf - Determine size of label value in bytes. /// @@ -333,14 +334,14 @@ namespace llvm { /// DIEObjectLabel - A label to an object in code or data. // class DIEObjectLabel : public DIEValue { - const std::string Label; + const MCSymbol *Sym; public: - explicit DIEObjectLabel(const std::string &L) - : DIEValue(isAsIsLabel), Label(L) {} + explicit DIEObjectLabel(const MCSymbol *S) + : DIEValue(isAsIsLabel), Sym(S) {} /// EmitValue - Emit label value. /// - virtual void EmitValue(Dwarf *D, unsigned Form) const; + virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; /// SizeOf - Determine size of label value in bytes. /// @@ -373,7 +374,7 @@ namespace llvm { /// EmitValue - Emit section offset. /// - virtual void EmitValue(Dwarf *D, unsigned Form) const; + virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; /// SizeOf - Determine size of section offset value in bytes. /// @@ -402,7 +403,7 @@ namespace llvm { /// EmitValue - Emit delta value. /// - virtual void EmitValue(Dwarf *D, unsigned Form) const; + virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; /// SizeOf - Determine size of delta value in bytes. /// @@ -431,7 +432,7 @@ namespace llvm { /// EmitValue - Emit debug information entry offset. /// - virtual void EmitValue(Dwarf *D, unsigned Form) const; + virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; /// SizeOf - Determine size of debug information entry in bytes. /// @@ -473,7 +474,7 @@ namespace llvm { /// EmitValue - Emit block data. /// - virtual void EmitValue(Dwarf *D, unsigned Form) const; + virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; /// SizeOf - Determine size of block data in bytes. /// diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 15f37ae..513987f 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -18,6 +18,7 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetLoweringObjectFile.h" @@ -25,7 +26,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Mangler.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/Timer.h" #include "llvm/System/Path.h" using namespace llvm; @@ -56,12 +57,12 @@ class CompileUnit { /// GVToDieMap - Tracks the mapping of unit level debug informaton /// variables to debug information entries. /// FIXME : Rename GVToDieMap -> NodeToDieMap - ValueMap<MDNode *, DIE *> GVToDieMap; + DenseMap<MDNode *, DIE *> GVToDieMap; /// GVToDIEEntryMap - Tracks the mapping of unit level debug informaton /// descriptors to debug information entries using a DIEEntry proxy. /// FIXME : Rename - ValueMap<MDNode *, DIEEntry *> GVToDIEEntryMap; + DenseMap<MDNode *, DIEEntry *> GVToDIEEntryMap; /// Globals - A map of globally visible named entities for this unit. /// @@ -108,7 +109,7 @@ public: /// getDIEEntry - Returns the debug information entry for the speciefied /// debug variable. DIEEntry *getDIEEntry(MDNode *N) { - ValueMap<MDNode *, DIEEntry *>::iterator I = GVToDIEEntryMap.find(N); + DenseMap<MDNode *, DIEEntry *>::iterator I = GVToDIEEntryMap.find(N); if (I == GVToDIEEntryMap.end()) return NULL; return I->second; @@ -165,7 +166,7 @@ public: class DbgScope { DbgScope *Parent; // Parent to this scope. DIDescriptor Desc; // Debug info descriptor for scope. - WeakVH InlinedAtLocation; // Location at which scope is inlined. + MDNode * InlinedAtLocation; // Location at which scope is inlined. bool AbstractScope; // Abstract Scope unsigned StartLabelID; // Label ID of the beginning of scope. unsigned EndLabelID; // Label ID of the end of scope. @@ -274,7 +275,7 @@ DbgScope::~DbgScope() { } // end llvm namespace DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) - : Dwarf(OS, A, T, "dbg"), ModuleCU(0), + : DwarfPrinter(OS, A, T, "dbg"), ModuleCU(0), AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(), DIEValues(), StringPool(), SectionSourceLines(), didInitial(false), shouldEmit(false), @@ -343,7 +344,7 @@ void DwarfDebug::addSInt(DIE *Die, unsigned Attribute, /// addString - Add a string attribute data and value. DIEString only /// keeps string reference. void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form, - const StringRef String) { + StringRef String) { DIEValue *Value = new DIEString(String); DIEValues.push_back(Value); Die->addValue(Attribute, Form, Value); @@ -361,8 +362,8 @@ void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form, /// addObjectLabel - Add an non-Dwarf label attribute data and value. /// void DwarfDebug::addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form, - const std::string &Label) { - DIEValue *Value = new DIEObjectLabel(Label); + const MCSymbol *Sym) { + DIEValue *Value = new DIEObjectLabel(Sym); DIEValues.push_back(Value); Die->addValue(Attribute, Form, Value); } @@ -1162,7 +1163,8 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) { addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); addUInt(Block, 0, dwarf::DW_FORM_data1, SP.getVirtualIndex()); addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block); - ContainingTypeMap.insert(std::make_pair(SPDie, WeakVH(SP.getContainingType().getNode()))); + ContainingTypeMap.insert(std::make_pair(SPDie, + SP.getContainingType().getNode())); } if (MakeDecl || !SP.isDefinition()) { @@ -1379,7 +1381,7 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { InlinedSubprogramDIEs.insert(OriginDIE); // Track the start label for this inlined function. - ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator + DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator I = InlineInfo.find(InlinedSP.getNode()); if (I == InlineInfo.end()) { @@ -1665,14 +1667,14 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) { DIEBlock *Block = new DIEBlock(); addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); addObjectLabel(Block, 0, dwarf::DW_FORM_udata, - Asm->Mang->getMangledName(DI_GV.getGlobal())); + Asm->GetGlobalValueSymbol(DI_GV.getGlobal())); addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); ModuleCU->addDie(VariableSpecDIE); } else { DIEBlock *Block = new DIEBlock(); addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); addObjectLabel(Block, 0, dwarf::DW_FORM_udata, - Asm->Mang->getMangledName(DI_GV.getGlobal())); + Asm->GetGlobalValueSymbol(DI_GV.getGlobal())); addBlock(VariableDie, dwarf::DW_AT_location, 0, Block); } addToContextOwner(VariableDie, GVContext); @@ -1770,13 +1772,15 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) { for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) { // Remember source id starts at 1. std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(i); + // FIXME: don't use sys::path for this! This should not depend on the + // host. sys::Path FullPath(getSourceDirectoryName(Id.first)); bool AppendOk = FullPath.appendComponent(getSourceFileName(Id.second)); assert(AppendOk && "Could not append filename to directory!"); AppendOk = false; Asm->EmitFile(i, FullPath.str()); - Asm->EOL(); + Asm->O << '\n'; } } @@ -1808,7 +1812,7 @@ void DwarfDebug::endModule() { TE = TopLevelDIEsVector.end(); TI != TE; ++TI) ModuleCU->getCUDie()->addChild(*TI); - for (DenseMap<DIE *, WeakVH>::iterator CI = ContainingTypeMap.begin(), + for (DenseMap<DIE *, MDNode *>::iterator CI = ContainingTypeMap.begin(), CE = ContainingTypeMap.end(); CI != CE; ++CI) { DIE *SPDie = CI->first; MDNode *N = dyn_cast_or_null<MDNode>(CI->second); @@ -1906,8 +1910,7 @@ void DwarfDebug::collectVariableInfo() { MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), VE = VMap.end(); VI != VE; ++VI) { - MetadataBase *MB = VI->first; - MDNode *Var = dyn_cast_or_null<MDNode>(MB); + MDNode *Var = VI->first; if (!Var) continue; DIVariable DV (Var); std::pair< unsigned, MDNode *> VP = VI->second; @@ -2000,13 +2003,14 @@ bool DwarfDebug::extractScopeInformation(MachineFunction *MF) { MIIndexMap[MInsn] = MIIndex++; DebugLoc DL = MInsn->getDebugLoc(); if (DL.isUnknown()) continue; - DebugLocTuple DLT = MF->getDebugLocTuple(DL); - if (!DLT.Scope) continue; + DILocation DLT = MF->getDILocation(DL); + DIScope DLTScope = DLT.getScope(); + if (DLTScope.isNull()) continue; // There is no need to create another DIE for compile unit. For all // other scopes, create one DbgScope now. This will be translated // into a scope DIE at the end. - if (DIDescriptor(DLT.Scope).isCompileUnit()) continue; - createDbgScope(DLT.Scope, DLT.InlinedAtLoc); + if (DLTScope.isCompileUnit()) continue; + createDbgScope(DLTScope.getNode(), DLT.getOrigLocation().getNode()); } } @@ -2019,13 +2023,15 @@ bool DwarfDebug::extractScopeInformation(MachineFunction *MF) { const MachineInstr *MInsn = II; DebugLoc DL = MInsn->getDebugLoc(); if (DL.isUnknown()) continue; - DebugLocTuple DLT = MF->getDebugLocTuple(DL); - if (!DLT.Scope) continue; + DILocation DLT = MF->getDILocation(DL); + DIScope DLTScope = DLT.getScope(); + if (DLTScope.isNull()) continue; // There is no need to create another DIE for compile unit. For all // other scopes, create one DbgScope now. This will be translated // into a scope DIE at the end. - if (DIDescriptor(DLT.Scope).isCompileUnit()) continue; - DbgScope *Scope = getUpdatedDbgScope(DLT.Scope, MInsn, DLT.InlinedAtLoc); + if (DLTScope.isCompileUnit()) continue; + DbgScope *Scope = getUpdatedDbgScope(DLTScope.getNode(), MInsn, + DLT.getOrigLocation().getNode()); Scope->setLastInsn(MInsn); } } @@ -2038,10 +2044,18 @@ bool DwarfDebug::extractScopeInformation(MachineFunction *MF) { // Each scope has first instruction and last instruction to mark beginning // and end of a scope respectively. Create an inverse map that list scopes // starts (and ends) with an instruction. One instruction may start (or end) - // multiple scopes. - for (ValueMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(), - DE = DbgScopeMap.end(); DI != DE; ++DI) { - DbgScope *S = DI->second; + // multiple scopes. Ignore scopes that are not reachable. + SmallVector<DbgScope *, 4> WorkList; + WorkList.push_back(CurrentFnDbgScope); + while (!WorkList.empty()) { + DbgScope *S = WorkList.back(); WorkList.pop_back(); + + SmallVector<DbgScope *, 4> &Children = S->getScopes(); + if (!Children.empty()) + for (SmallVector<DbgScope *, 4>::iterator SI = Children.begin(), + SE = Children.end(); SI != SE; ++SI) + WorkList.push_back(*SI); + if (S->isAbstractScope()) continue; const MachineInstr *MI = S->getFirstInsn(); @@ -2090,13 +2104,16 @@ void DwarfDebug::beginFunction(MachineFunction *MF) { // function. DebugLoc FDL = MF->getDefaultDebugLoc(); if (!FDL.isUnknown()) { - DebugLocTuple DLT = MF->getDebugLocTuple(FDL); + DILocation DLT = MF->getDILocation(FDL); unsigned LabelID = 0; - DISubprogram SP = getDISubprogram(DLT.Scope); + DISubprogram SP = getDISubprogram(DLT.getScope().getNode()); if (!SP.isNull()) - LabelID = recordSourceLine(SP.getLineNumber(), 0, DLT.Scope); + LabelID = recordSourceLine(SP.getLineNumber(), 0, + DLT.getScope().getNode()); else - LabelID = recordSourceLine(DLT.Line, DLT.Col, DLT.Scope); + LabelID = recordSourceLine(DLT.getLineNumber(), + DLT.getColumnNumber(), + DLT.getScope().getNode()); Asm->printLabel(LabelID); O << '\n'; } @@ -2142,14 +2159,12 @@ void DwarfDebug::endFunction(MachineFunction *MF) { } // Clear debug info - if (CurrentFnDbgScope) { - CurrentFnDbgScope = NULL; - DbgScopeMap.clear(); - DbgScopeBeginMap.clear(); - DbgScopeEndMap.clear(); - ConcreteScopes.clear(); - AbstractScopesList.clear(); - } + CurrentFnDbgScope = NULL; + DbgScopeMap.clear(); + DbgScopeBeginMap.clear(); + DbgScopeEndMap.clear(); + ConcreteScopes.clear(); + AbstractScopesList.clear(); Lines.clear(); if (TimePassesIsEnabled) @@ -2332,19 +2347,15 @@ void DwarfDebug::emitDIE(DIE *Die) { unsigned AbbrevNumber = Die->getAbbrevNumber(); const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; - Asm->EOL(); + Asm->O << '\n'; // Emit the code (index) for the abbreviation. - Asm->EmitULEB128Bytes(AbbrevNumber); - - if (Asm->isVerbose()) - Asm->EOL(std::string("Abbrev [" + - utostr(AbbrevNumber) + - "] 0x" + utohexstr(Die->getOffset()) + - ":0x" + utohexstr(Die->getSize()) + " " + - dwarf::TagString(Abbrev->getTag()))); - else - Asm->EOL(); + if (Asm->VerboseAsm) + Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" + + Twine::utohexstr(Die->getOffset()) + ":0x" + + Twine::utohexstr(Die->getSize()) + " " + + dwarf::TagString(Abbrev->getTag())); + EmitULEB128(AbbrevNumber); SmallVector<DIEValue*, 32> &Values = Die->getValues(); const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData(); @@ -2372,7 +2383,7 @@ void DwarfDebug::emitDIE(DIE *Die) { break; } - Asm->EOL(dwarf::AttributeString(Attr)); + EOL(dwarf::AttributeString(Attr)); } // Emit the DIE children if any. @@ -2382,7 +2393,7 @@ void DwarfDebug::emitDIE(DIE *Die) { for (unsigned j = 0, M = Children.size(); j < M; ++j) emitDIE(Children[j]); - Asm->EmitInt8(0); Asm->EOL("End Of Children Mark"); + Asm->EmitInt8(0); EOL("End Of Children Mark"); } } @@ -2404,21 +2415,20 @@ void DwarfDebug::emitDebugInfo() { sizeof(int8_t) + // Pointer Size (in bytes) sizeof(int32_t); // FIXME - extra pad for gdb bug. - Asm->EmitInt32(ContentSize); Asm->EOL("Length of Compilation Unit Info"); - Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number"); + Asm->EmitInt32(ContentSize); EOL("Length of Compilation Unit Info"); + Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number"); EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false); - Asm->EOL("Offset Into Abbrev. Section"); - Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)"); + EOL("Offset Into Abbrev. Section"); + Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)"); emitDIE(Die); // FIXME - extra padding for gdb bug. - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); EOL("Extra Pad For GDB"); EmitLabel("info_end", ModuleCU->getID()); - - Asm->EOL(); + Asm->O << '\n'; } /// emitAbbreviations - Emit the abbreviation section. @@ -2438,20 +2448,18 @@ void DwarfDebug::emitAbbreviations() const { const DIEAbbrev *Abbrev = Abbreviations[i]; // Emit the abbrevations code (base 1 index.) - Asm->EmitULEB128Bytes(Abbrev->getNumber()); - Asm->EOL("Abbreviation Code"); + EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); // Emit the abbreviations data. - Abbrev->Emit(Asm); - - Asm->EOL(); + Abbrev->Emit(this); + Asm->O << '\n'; } // Mark end of abbreviations. - Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(3)"); + EmitULEB128(0, "EOM(3)"); EmitLabel("abbrev_end", 0); - Asm->EOL(); + Asm->O << '\n'; } } @@ -2460,15 +2468,15 @@ void DwarfDebug::emitAbbreviations() const { /// void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { // Define last address of section. - Asm->EmitInt8(0); Asm->EOL("Extended Op"); - Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size"); - Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address"); - EmitReference("section_end", SectionEnd); Asm->EOL("Section end label"); + Asm->EmitInt8(0); EOL("Extended Op"); + Asm->EmitInt8(TD->getPointerSize() + 1); EOL("Op size"); + Asm->EmitInt8(dwarf::DW_LNE_set_address); EOL("DW_LNE_set_address"); + EmitReference("section_end", SectionEnd); EOL("Section end label"); // Mark end of matrix. - Asm->EmitInt8(0); Asm->EOL("DW_LNE_end_sequence"); - Asm->EmitULEB128Bytes(1); Asm->EOL(); - Asm->EmitInt8(1); Asm->EOL(); + Asm->EmitInt8(0); EOL("DW_LNE_end_sequence"); + Asm->EmitInt8(1); + Asm->EmitInt8(1); } /// emitDebugLines - Emit source line information. @@ -2490,59 +2498,55 @@ void DwarfDebug::emitDebugLines() { // Construct the section header. EmitDifference("line_end", 0, "line_begin", 0, true); - Asm->EOL("Length of Source Line Info"); + EOL("Length of Source Line Info"); EmitLabel("line_begin", 0); - Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number"); + Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number"); EmitDifference("line_prolog_end", 0, "line_prolog_begin", 0, true); - Asm->EOL("Prolog Length"); + EOL("Prolog Length"); EmitLabel("line_prolog_begin", 0); - Asm->EmitInt8(1); Asm->EOL("Minimum Instruction Length"); - - Asm->EmitInt8(1); Asm->EOL("Default is_stmt_start flag"); - - Asm->EmitInt8(MinLineDelta); Asm->EOL("Line Base Value (Special Opcodes)"); - - Asm->EmitInt8(MaxLineDelta); Asm->EOL("Line Range Value (Special Opcodes)"); - - Asm->EmitInt8(-MinLineDelta); Asm->EOL("Special Opcode Base"); + Asm->EmitInt8(1); EOL("Minimum Instruction Length"); + Asm->EmitInt8(1); EOL("Default is_stmt_start flag"); + Asm->EmitInt8(MinLineDelta); EOL("Line Base Value (Special Opcodes)"); + Asm->EmitInt8(MaxLineDelta); EOL("Line Range Value (Special Opcodes)"); + Asm->EmitInt8(-MinLineDelta); EOL("Special Opcode Base"); // Line number standard opcode encodings argument count - Asm->EmitInt8(0); Asm->EOL("DW_LNS_copy arg count"); - Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_pc arg count"); - Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_line arg count"); - Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_file arg count"); - Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_column arg count"); - Asm->EmitInt8(0); Asm->EOL("DW_LNS_negate_stmt arg count"); - Asm->EmitInt8(0); Asm->EOL("DW_LNS_set_basic_block arg count"); - Asm->EmitInt8(0); Asm->EOL("DW_LNS_const_add_pc arg count"); - Asm->EmitInt8(1); Asm->EOL("DW_LNS_fixed_advance_pc arg count"); + Asm->EmitInt8(0); EOL("DW_LNS_copy arg count"); + Asm->EmitInt8(1); EOL("DW_LNS_advance_pc arg count"); + Asm->EmitInt8(1); EOL("DW_LNS_advance_line arg count"); + Asm->EmitInt8(1); EOL("DW_LNS_set_file arg count"); + Asm->EmitInt8(1); EOL("DW_LNS_set_column arg count"); + Asm->EmitInt8(0); EOL("DW_LNS_negate_stmt arg count"); + Asm->EmitInt8(0); EOL("DW_LNS_set_basic_block arg count"); + Asm->EmitInt8(0); EOL("DW_LNS_const_add_pc arg count"); + Asm->EmitInt8(1); EOL("DW_LNS_fixed_advance_pc arg count"); // Emit directories. for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) { - Asm->EmitString(getSourceDirectoryName(DI)); - Asm->EOL("Directory"); + const std::string &Dir = getSourceDirectoryName(DI); + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Directory"); + Asm->OutStreamer.EmitBytes(StringRef(Dir.c_str(), Dir.size()+1), 0); } - Asm->EmitInt8(0); Asm->EOL("End of directories"); + Asm->EmitInt8(0); EOL("End of directories"); // Emit files. for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) { // Remember source id starts at 1. std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(SI); - Asm->EmitString(getSourceFileName(Id.second)); - Asm->EOL("Source"); - Asm->EmitULEB128Bytes(Id.first); - Asm->EOL("Directory #"); - Asm->EmitULEB128Bytes(0); - Asm->EOL("Mod date"); - Asm->EmitULEB128Bytes(0); - Asm->EOL("File size"); + const std::string &FN = getSourceFileName(Id.second); + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Source"); + Asm->OutStreamer.EmitBytes(StringRef(FN.c_str(), FN.size()+1), 0); + + EmitULEB128(Id.first, "Directory #"); + EmitULEB128(0, "Mod date"); + EmitULEB128(0, "File size"); } - Asm->EmitInt8(0); Asm->EOL("End of files"); + Asm->EmitInt8(0); EOL("End of files"); EmitLabel("line_prolog_end", 0); @@ -2558,7 +2562,7 @@ void DwarfDebug::emitDebugLines() { O << '\t' << MAI->getCommentString() << " Section" << S->getName() << '\n'; }*/ - Asm->EOL(); + Asm->O << '\n'; // Dwarf assumes we start with first line of first source file. unsigned Source = 1; @@ -2573,7 +2577,7 @@ void DwarfDebug::emitDebugLines() { if (LineInfo.getLine() == 0) continue; if (!Asm->isVerbose()) - Asm->EOL(); + Asm->O << '\n'; else { std::pair<unsigned, unsigned> SourceID = getSourceDirectoryAndFileIds(LineInfo.getSourceID()); @@ -2584,16 +2588,16 @@ void DwarfDebug::emitDebugLines() { } // Define the line address. - Asm->EmitInt8(0); Asm->EOL("Extended Op"); - Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size"); - Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address"); - EmitReference("label", LabelID); Asm->EOL("Location label"); + Asm->EmitInt8(0); EOL("Extended Op"); + Asm->EmitInt8(TD->getPointerSize() + 1); EOL("Op size"); + Asm->EmitInt8(dwarf::DW_LNE_set_address); EOL("DW_LNE_set_address"); + EmitReference("label", LabelID); EOL("Location label"); // If change of source, then switch to the new source. if (Source != LineInfo.getSourceID()) { Source = LineInfo.getSourceID(); - Asm->EmitInt8(dwarf::DW_LNS_set_file); Asm->EOL("DW_LNS_set_file"); - Asm->EmitULEB128Bytes(Source); Asm->EOL("New Source"); + Asm->EmitInt8(dwarf::DW_LNS_set_file); EOL("DW_LNS_set_file"); + EmitULEB128(Source, "New Source"); } // If change of line. @@ -2608,17 +2612,17 @@ void DwarfDebug::emitDebugLines() { // If delta is small enough and in range... if (Delta >= 0 && Delta < (MaxLineDelta - 1)) { // ... then use fast opcode. - Asm->EmitInt8(Delta - MinLineDelta); Asm->EOL("Line Delta"); + Asm->EmitInt8(Delta - MinLineDelta); EOL("Line Delta"); } else { // ... otherwise use long hand. Asm->EmitInt8(dwarf::DW_LNS_advance_line); - Asm->EOL("DW_LNS_advance_line"); - Asm->EmitSLEB128Bytes(Offset); Asm->EOL("Line Offset"); - Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy"); + EOL("DW_LNS_advance_line"); + EmitSLEB128(Offset, "Line Offset"); + Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy"); } } else { // Copy the previous row (different address or source) - Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy"); + Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy"); } } @@ -2632,7 +2636,7 @@ void DwarfDebug::emitDebugLines() { emitEndOfLineMatrix(1); EmitLabel("line_end", 0); - Asm->EOL(); + Asm->O << '\n'; } /// emitCommonDebugFrame - Emit common frame info into a debug frame section. @@ -2653,21 +2657,19 @@ void DwarfDebug::emitCommonDebugFrame() { EmitLabel("debug_frame_common", 0); EmitDifference("debug_frame_common_end", 0, "debug_frame_common_begin", 0, true); - Asm->EOL("Length of Common Information Entry"); + EOL("Length of Common Information Entry"); EmitLabel("debug_frame_common_begin", 0); Asm->EmitInt32((int)dwarf::DW_CIE_ID); - Asm->EOL("CIE Identifier Tag"); + EOL("CIE Identifier Tag"); Asm->EmitInt8(dwarf::DW_CIE_VERSION); - Asm->EOL("CIE Version"); - Asm->EmitString(""); - Asm->EOL("CIE Augmentation"); - Asm->EmitULEB128Bytes(1); - Asm->EOL("CIE Code Alignment Factor"); - Asm->EmitSLEB128Bytes(stackGrowth); - Asm->EOL("CIE Data Alignment Factor"); + EOL("CIE Version"); + Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator. + EOL("CIE Augmentation"); + EmitULEB128(1, "CIE Code Alignment Factor"); + EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false)); - Asm->EOL("CIE RA Column"); + EOL("CIE RA Column"); std::vector<MachineMove> Moves; RI->getInitialFrameState(Moves); @@ -2676,8 +2678,7 @@ void DwarfDebug::emitCommonDebugFrame() { Asm->EmitAlignment(2, 0, 0, false); EmitLabel("debug_frame_common_end", 0); - - Asm->EOL(); + Asm->O << '\n'; } /// emitFunctionDebugFrame - Emit per function frame info into a debug frame @@ -2693,27 +2694,26 @@ DwarfDebug::emitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){ EmitDifference("debug_frame_end", DebugFrameInfo.Number, "debug_frame_begin", DebugFrameInfo.Number, true); - Asm->EOL("Length of Frame Information Entry"); + EOL("Length of Frame Information Entry"); EmitLabel("debug_frame_begin", DebugFrameInfo.Number); EmitSectionOffset("debug_frame_common", "section_debug_frame", 0, 0, true, false); - Asm->EOL("FDE CIE offset"); + EOL("FDE CIE offset"); EmitReference("func_begin", DebugFrameInfo.Number); - Asm->EOL("FDE initial location"); + EOL("FDE initial location"); EmitDifference("func_end", DebugFrameInfo.Number, "func_begin", DebugFrameInfo.Number); - Asm->EOL("FDE address range"); + EOL("FDE address range"); EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves, false); Asm->EmitAlignment(2, 0, 0, false); EmitLabel("debug_frame_end", DebugFrameInfo.Number); - - Asm->EOL(); + Asm->O << '\n'; } /// emitDebugPubNames - Emit visible names into a debug pubnames section. @@ -2725,19 +2725,19 @@ void DwarfDebug::emitDebugPubNames() { EmitDifference("pubnames_end", ModuleCU->getID(), "pubnames_begin", ModuleCU->getID(), true); - Asm->EOL("Length of Public Names Info"); + EOL("Length of Public Names Info"); EmitLabel("pubnames_begin", ModuleCU->getID()); - Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version"); + Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF Version"); EmitSectionOffset("info_begin", "section_info", ModuleCU->getID(), 0, true, false); - Asm->EOL("Offset of Compilation Unit Info"); + EOL("Offset of Compilation Unit Info"); EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(), true); - Asm->EOL("Compilation Unit Length"); + EOL("Compilation Unit Length"); const StringMap<DIE*> &Globals = ModuleCU->getGlobals(); for (StringMap<DIE*>::const_iterator @@ -2745,14 +2745,16 @@ void DwarfDebug::emitDebugPubNames() { const char *Name = GI->getKeyData(); DIE * Entity = GI->second; - Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset"); - Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name"); + Asm->EmitInt32(Entity->getOffset()); EOL("DIE offset"); + + if (Asm->VerboseAsm) + Asm->OutStreamer.AddComment("External Name"); + Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0); } - Asm->EmitInt32(0); Asm->EOL("End Mark"); + Asm->EmitInt32(0); EOL("End Mark"); EmitLabel("pubnames_end", ModuleCU->getID()); - - Asm->EOL(); + Asm->O << '\n'; } void DwarfDebug::emitDebugPubTypes() { @@ -2761,19 +2763,19 @@ void DwarfDebug::emitDebugPubTypes() { Asm->getObjFileLowering().getDwarfPubTypesSection()); EmitDifference("pubtypes_end", ModuleCU->getID(), "pubtypes_begin", ModuleCU->getID(), true); - Asm->EOL("Length of Public Types Info"); + EOL("Length of Public Types Info"); EmitLabel("pubtypes_begin", ModuleCU->getID()); - Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version"); + Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF Version"); EmitSectionOffset("info_begin", "section_info", ModuleCU->getID(), 0, true, false); - Asm->EOL("Offset of Compilation ModuleCU Info"); + EOL("Offset of Compilation ModuleCU Info"); EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(), true); - Asm->EOL("Compilation ModuleCU Length"); + EOL("Compilation ModuleCU Length"); const StringMap<DIE*> &Globals = ModuleCU->getGlobalTypes(); for (StringMap<DIE*>::const_iterator @@ -2781,14 +2783,15 @@ void DwarfDebug::emitDebugPubTypes() { const char *Name = GI->getKeyData(); DIE * Entity = GI->second; - Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset"); - Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name"); + Asm->EmitInt32(Entity->getOffset()); EOL("DIE offset"); + + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("External Name"); + Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)), 0); } - Asm->EmitInt32(0); Asm->EOL("End Mark"); + Asm->EmitInt32(0); EOL("End Mark"); EmitLabel("pubtypes_end", ModuleCU->getID()); - - Asm->EOL(); + Asm->O << '\n'; } /// emitDebugStr - Emit visible names into a debug str section. @@ -2808,10 +2811,10 @@ void DwarfDebug::emitDebugStr() { // Emit the string itself. const std::string &String = StringPool[StringID]; - Asm->EmitString(String); Asm->EOL(); + Asm->OutStreamer.EmitBytes(StringRef(String.c_str(), String.size()+1), 0); } - Asm->EOL(); + Asm->O << '\n'; } } @@ -2821,7 +2824,6 @@ void DwarfDebug::emitDebugLoc() { // Start the dwarf loc section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfLocSection()); - Asm->EOL(); } /// EmitDebugARanges - Emit visible names into a debug aranges section. @@ -2836,29 +2838,27 @@ void DwarfDebug::EmitDebugARanges() { CompileUnit *Unit = GetBaseCompileUnit(); // Don't include size of length - Asm->EmitInt32(0x1c); Asm->EOL("Length of Address Ranges Info"); + Asm->EmitInt32(0x1c); EOL("Length of Address Ranges Info"); - Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version"); + Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version"); EmitReference("info_begin", Unit->getID()); - Asm->EOL("Offset of Compilation Unit Info"); + EOL("Offset of Compilation Unit Info"); - Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Size of Address"); + Asm->EmitInt8(TD->getPointerSize()); EOL("Size of Address"); - Asm->EmitInt8(0); Asm->EOL("Size of Segment Descriptor"); + Asm->EmitInt8(0); EOL("Size of Segment Descriptor"); - Asm->EmitInt16(0); Asm->EOL("Pad (1)"); - Asm->EmitInt16(0); Asm->EOL("Pad (2)"); + Asm->EmitInt16(0); EOL("Pad (1)"); + Asm->EmitInt16(0); EOL("Pad (2)"); // Range 1 - EmitReference("text_begin", 0); Asm->EOL("Address"); - EmitDifference("text_end", 0, "text_begin", 0, true); Asm->EOL("Length"); + EmitReference("text_begin", 0); EOL("Address"); + EmitDifference("text_end", 0, "text_begin", 0, true); EOL("Length"); - Asm->EmitInt32(0); Asm->EOL("EOM (1)"); - Asm->EmitInt32(0); Asm->EOL("EOM (2)"); + Asm->EmitInt32(0); EOL("EOM (1)"); + Asm->EmitInt32(0); EOL("EOM (2)"); #endif - - Asm->EOL(); } /// emitDebugRanges - Emit visible names into a debug ranges section. @@ -2867,7 +2867,6 @@ void DwarfDebug::emitDebugRanges() { // Start the dwarf ranges section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfRangesSection()); - Asm->EOL(); } /// emitDebugMacInfo - Emit visible names into a debug macinfo section. @@ -2877,7 +2876,6 @@ void DwarfDebug::emitDebugMacInfo() { Asm->getObjFileLowering().getDwarfMacroInfoSection()) { // Start the dwarf macinfo section. Asm->OutStreamer.SwitchSection(LineInfo); - Asm->EOL(); } } @@ -2908,53 +2906,54 @@ void DwarfDebug::emitDebugInlineInfo() { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfDebugInlineSection()); - Asm->EOL(); + EmitDifference("debug_inlined_end", 1, "debug_inlined_begin", 1, true); - Asm->EOL("Length of Debug Inlined Information Entry"); + EOL("Length of Debug Inlined Information Entry"); EmitLabel("debug_inlined_begin", 1); - Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version"); - Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)"); + Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version"); + Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)"); for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(), E = InlinedSPNodes.end(); I != E; ++I) { MDNode *Node = *I; - ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II + DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II = InlineInfo.find(Node); SmallVector<InlineInfoLabels, 4> &Labels = II->second; DISubprogram SP(Node); StringRef LName = SP.getLinkageName(); StringRef Name = SP.getName(); - if (LName.empty()) - Asm->EmitString(Name); - else + if (LName.empty()) { + Asm->OutStreamer.EmitBytes(Name, 0); + Asm->OutStreamer.EmitIntValue(0, 1, 0); // nul terminator. + } else EmitSectionOffset("string", "section_str", - StringPool.idFor(getRealLinkageName(LName)), false, true); + StringPool.idFor(getRealLinkageName(LName)), false, true); - Asm->EOL("MIPS linkage name"); + EOL("MIPS linkage name"); EmitSectionOffset("string", "section_str", StringPool.idFor(Name), false, true); - Asm->EOL("Function name"); - Asm->EmitULEB128Bytes(Labels.size()); Asm->EOL("Inline count"); + EOL("Function name"); + EmitULEB128(Labels.size(), "Inline count"); for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(), LE = Labels.end(); LI != LE; ++LI) { DIE *SP = LI->second; - Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset"); + Asm->EmitInt32(SP->getOffset()); EOL("DIE offset"); if (TD->getPointerSize() == sizeof(int32_t)) O << MAI->getData32bitsDirective(); else O << MAI->getData64bitsDirective(); - PrintLabelName("label", LI->first); Asm->EOL("low_pc"); + PrintLabelName("label", LI->first); EOL("low_pc"); } } EmitLabel("debug_inlined_end", 1); - Asm->EOL(); + Asm->O << '\n'; } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 2b8164e..e723621 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -20,7 +20,7 @@ #include "llvm/CodeGen/MachineLocation.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/ValueMap.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringMap.h" @@ -57,7 +57,7 @@ public: unsigned getLabelID() const { return LabelID; } }; -class DwarfDebug : public Dwarf { +class DwarfDebug : public DwarfPrinter { //===--------------------------------------------------------------------===// // Attributes used to construct specific Dwarf sections. // @@ -136,25 +136,25 @@ class DwarfDebug : public Dwarf { /// DbgScopeMap - Tracks the scopes in the current function. /// - ValueMap<MDNode *, DbgScope *> DbgScopeMap; + DenseMap<MDNode *, DbgScope *> DbgScopeMap; /// ConcreteScopes - Tracks the concrete scopees in the current function. /// These scopes are also included in DbgScopeMap. - ValueMap<MDNode *, DbgScope *> ConcreteScopes; + DenseMap<MDNode *, DbgScope *> ConcreteScopes; /// AbstractScopes - Tracks the abstract scopes a module. These scopes are /// not included DbgScopeMap. - ValueMap<MDNode *, DbgScope *> AbstractScopes; + DenseMap<MDNode *, DbgScope *> AbstractScopes; SmallVector<DbgScope *, 4>AbstractScopesList; /// AbstractVariables - Collection on abstract variables. - ValueMap<MDNode *, DbgVariable *> AbstractVariables; + DenseMap<MDNode *, DbgVariable *> AbstractVariables; /// InliendSubprogramDIEs - Collection of subprgram DIEs that are marked /// (at the end of the module) as DW_AT_inline. SmallPtrSet<DIE *, 4> InlinedSubprogramDIEs; - DenseMap<DIE *, WeakVH> ContainingTypeMap; + DenseMap<DIE *, MDNode *> ContainingTypeMap; /// AbstractSubprogramDIEs - Collection of abstruct subprogram DIEs. SmallPtrSet<DIE *, 4> AbstractSubprogramDIEs; @@ -176,7 +176,7 @@ class DwarfDebug : public Dwarf { /// InlineInfo - Keep track of inlined functions and their location. This /// information is used to populate debug_inlined section. typedef std::pair<unsigned, DIE *> InlineInfoLabels; - ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo; + DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo; SmallVector<MDNode *, 4> InlinedSPNodes; /// CompileUnitOffsets - A vector of the offsets of the compile units. This is @@ -256,7 +256,7 @@ class DwarfDebug : public Dwarf { /// addObjectLabel - Add an non-Dwarf label attribute data and value. /// void addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form, - const std::string &Label); + const MCSymbol *Sym); /// addSectionOffset - Add a section offset label attribute data and value. /// diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index d01f300..2ae16c0 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -22,22 +22,23 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" -#include "llvm/Support/Mangler.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" using namespace llvm; DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) - : Dwarf(OS, A, T, "eh"), shouldEmitTable(false), shouldEmitMoves(false), + : DwarfPrinter(OS, A, T, "eh"), shouldEmitTable(false),shouldEmitMoves(false), shouldEmitTableModule(false), shouldEmitMovesModule(false), ExceptionTimer(0) { if (TimePassesIsEnabled) @@ -114,14 +115,14 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // Define the eh frame length. EmitDifference("eh_frame_common_end", Index, "eh_frame_common_begin", Index, true); - Asm->EOL("Length of Common Information Entry"); + EOL("Length of Common Information Entry"); // EH frame header. EmitLabel("eh_frame_common_begin", Index); - Asm->EmitInt32((int)0); - Asm->EOL("CIE Identifier Tag"); - Asm->EmitInt8(dwarf::DW_CIE_VERSION); - Asm->EOL("CIE Version"); + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("CIE Identifier Tag"); + Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DW_CIE_VERSION"); + Asm->OutStreamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1/*size*/, 0/*addr*/); // The personality presence indicates that language specific information will // show up in the eh frame. Find out how we are supposed to lower the @@ -145,7 +146,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { unsigned LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; unsigned FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - char Augmentation[5] = { 0 }; + char Augmentation[6] = { 0 }; unsigned AugmentationSize = 0; char *APtr = Augmentation + 1; @@ -170,22 +171,17 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { if (APtr != Augmentation + 1) Augmentation[0] = 'z'; - Asm->EmitString(Augmentation); - Asm->EOL("CIE Augmentation"); + Asm->OutStreamer.EmitBytes(StringRef(Augmentation, strlen(Augmentation)+1),0); + EOL("CIE Augmentation"); // Round out reader. - Asm->EmitULEB128Bytes(1); - Asm->EOL("CIE Code Alignment Factor"); - Asm->EmitSLEB128Bytes(stackGrowth); - Asm->EOL("CIE Data Alignment Factor"); + EmitULEB128(1, "CIE Code Alignment Factor"); + EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); - Asm->EOL("CIE Return Address Column"); + EOL("CIE Return Address Column"); - Asm->EmitULEB128Bytes(AugmentationSize); - Asm->EOL("Augmentation Size"); - - Asm->EmitInt8(PerEncoding); - Asm->EOL("Personality", PerEncoding); + EmitULEB128(AugmentationSize, "Augmentation Size"); + EmitEncodingByte(PerEncoding, "Personality"); // If there is a personality, we need to indicate the function's location. if (PersonalityRef) { @@ -193,15 +189,11 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { PersonalityRef = CreateLabelDiff(PersonalityRef, "personalityref_addr", Index); - O << MAI->getData32bitsDirective(); - PersonalityRef->print(O, MAI); - Asm->EOL("Personality"); - - Asm->EmitInt8(LSDAEncoding); - Asm->EOL("LSDA Encoding", LSDAEncoding); + O << MAI->getData32bitsDirective() << *PersonalityRef; + EOL("Personality"); - Asm->EmitInt8(FDEEncoding); - Asm->EOL("FDE Encoding", FDEEncoding); + EmitEncodingByte(LSDAEncoding, "LSDA"); + EmitEncodingByte(FDEEncoding, "FDE"); } // Indicate locations of general callee saved registers in frame. @@ -214,8 +206,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // holes which confuse readers of eh_frame. Asm->EmitAlignment(TD->getPointerSize() == 4 ? 2 : 3, 0, 0, false); EmitLabel("eh_frame_common_end", Index); - - Asm->EOL(); + Asm->O << '\n'; } /// EmitFDE - Emit the Frame Description Entry (FDE) for the function. @@ -231,16 +222,17 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // corresponding function is static, this should not be externally visible. if (!TheFunc->hasLocalLinkage()) if (const char *GlobalEHDirective = MAI->getGlobalEHDirective()) - O << GlobalEHDirective << EHFrameInfo.FnName << '\n'; + O << GlobalEHDirective << *EHFrameInfo.FunctionEHSym << '\n'; // If corresponding function is weak definition, this should be too. if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective()) - O << MAI->getWeakDefDirective() << EHFrameInfo.FnName << '\n'; + O << MAI->getWeakDefDirective() << *EHFrameInfo.FunctionEHSym << '\n'; // If corresponding function is hidden, this should be too. if (TheFunc->hasHiddenVisibility()) - if (const char *HiddenDirective = MAI->getHiddenDirective()) - O << HiddenDirective << EHFrameInfo.FnName << '\n' ; + if (MCSymbolAttr HiddenAttr = MAI->getHiddenVisibilityAttr()) + Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, + HiddenAttr); // If there are no calls then you can't unwind. This may mean we can omit the // EH Frame, but some environments do not handle weak absolute symbols. If @@ -250,19 +242,20 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { (!TheFunc->isWeakForLinker() || !MAI->getWeakDefDirective() || MAI->getSupportsWeakOmittedEHFrame())) { - O << EHFrameInfo.FnName << " = 0\n"; + O << *EHFrameInfo.FunctionEHSym << " = 0\n"; // This name has no connection to the function, so it might get // dead-stripped when the function is not, erroneously. Prohibit // dead-stripping unconditionally. - if (const char *UsedDirective = MAI->getUsedDirective()) - O << UsedDirective << EHFrameInfo.FnName << "\n\n"; + if (MAI->hasNoDeadStrip()) + Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, + MCSA_NoDeadStrip); } else { - O << EHFrameInfo.FnName << ":\n"; + O << *EHFrameInfo.FunctionEHSym << ":\n"; // EH frame header. EmitDifference("eh_frame_end", EHFrameInfo.Number, "eh_frame_begin", EHFrameInfo.Number, true); - Asm->EOL("Length of Frame Information Entry"); + EOL("Length of Frame Information Entry"); EmitLabel("eh_frame_begin", EHFrameInfo.Number); @@ -270,34 +263,39 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { EHFrameInfo.Number, EHFrameInfo.PersonalityIndex, true, true, false); - Asm->EOL("FDE CIE offset"); + EOL("FDE CIE offset"); EmitReference("eh_func_begin", EHFrameInfo.Number, true, true); - Asm->EOL("FDE initial location"); + EOL("FDE initial location"); EmitDifference("eh_func_end", EHFrameInfo.Number, "eh_func_begin", EHFrameInfo.Number, true); - Asm->EOL("FDE address range"); + EOL("FDE address range"); // If there is a personality and landing pads then point to the language // specific data area in the exception table. if (MMI->getPersonalities()[0] != NULL) { - bool is4Byte = TD->getPointerSize() == sizeof(int32_t); - Asm->EmitULEB128Bytes(is4Byte ? 4 : 8); - Asm->EOL("Augmentation size"); + if (Asm->TM.getLSDAEncoding() != DwarfLSDAEncoding::EightByte) { + EmitULEB128(4, "Augmentation size"); - if (EHFrameInfo.hasLandingPads) - EmitReference("exception", EHFrameInfo.Number, true, false); - else { - if (is4Byte) - Asm->EmitInt32((int)0); + if (EHFrameInfo.hasLandingPads) + EmitReference("exception", EHFrameInfo.Number, true, true); else - Asm->EmitInt64((int)0); + Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); + } else { + EmitULEB128(TD->getPointerSize(), "Augmentation size"); + + if (EHFrameInfo.hasLandingPads) { + EmitReference("exception", EHFrameInfo.Number, true, false); + } else { + Asm->OutStreamer.EmitIntValue(0, TD->getPointerSize(), + 0/*addrspace*/); + } } - Asm->EOL("Language Specific Data Area"); + + EOL("Language Specific Data Area"); } else { - Asm->EmitULEB128Bytes(0); - Asm->EOL("Augmentation size"); + EmitULEB128(0, "Augmentation size"); } // Indicate locations of function specific callee saved registers in frame. @@ -317,11 +315,11 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // on unused functions (calling undefined externals) being dead-stripped to // link correctly. Yes, there really is. if (MMI->isUsedFunction(EHFrameInfo.function)) - if (const char *UsedDirective = MAI->getUsedDirective()) - O << UsedDirective << EHFrameInfo.FnName << "\n\n"; + if (MAI->hasNoDeadStrip()) + Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, + MCSA_NoDeadStrip); } - - Asm->EOL(); + Asm->O << '\n'; } /// SharedTypeIds - How many leading type ids two landing pads have in common. @@ -765,7 +763,7 @@ void DwarfException::EmitExceptionTable() { for (unsigned i = 0; i != SizeAlign; ++i) { Asm->EmitInt8(0); - Asm->EOL("Padding"); + EOL("Padding"); } EmitLabel("exception", SubprogramCount); @@ -778,23 +776,16 @@ void DwarfException::EmitExceptionTable() { } // Emit the header. - Asm->EmitInt8(dwarf::DW_EH_PE_omit); - Asm->EOL("@LPStart format", dwarf::DW_EH_PE_omit); + EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); + EmitEncodingByte(TTypeFormat, "@TType"); - Asm->EmitInt8(TTypeFormat); - Asm->EOL("@TType format", TTypeFormat); - - if (HaveTTData) { - Asm->EmitULEB128Bytes(TyOffset); - Asm->EOL("@TType base offset"); - } + if (HaveTTData) + EmitULEB128(TyOffset, "@TType base offset"); // SjLj Exception handling if (IsSJLJ) { - Asm->EmitInt8(dwarf::DW_EH_PE_udata4); - Asm->EOL("Call site format", dwarf::DW_EH_PE_udata4); - Asm->EmitULEB128Bytes(SizeSites); - Asm->EOL("Call site table length"); + EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); + EmitULEB128(SizeSites, "Call site table length"); // Emit the landing pad site information. unsigned idx = 0; @@ -804,14 +795,12 @@ void DwarfException::EmitExceptionTable() { // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. - Asm->EmitULEB128Bytes(idx); - Asm->EOL("Landing pad"); + EmitULEB128(idx, "Landing pad"); // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of // the action table), and 0 indicates that there are no actions. - Asm->EmitULEB128Bytes(S.Action); - Asm->EOL("Action"); + EmitULEB128(S.Action, "Action"); } } else { // DWARF Exception handling @@ -836,10 +825,8 @@ void DwarfException::EmitExceptionTable() { // supposed to throw. // Emit the landing pad call site table. - Asm->EmitInt8(dwarf::DW_EH_PE_udata4); - Asm->EOL("Call site format", dwarf::DW_EH_PE_udata4); - Asm->EmitULEB128Bytes(SizeSites); - Asm->EOL("Call site table size"); + EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); + EmitULEB128(SizeSites, "Call site table size"); for (SmallVectorImpl<CallSiteEntry>::const_iterator I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { @@ -860,7 +847,7 @@ void DwarfException::EmitExceptionTable() { // the start of the procedure fragment. EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, true, true); - Asm->EOL("Region start"); + EOL("Region start"); if (!S.EndLabel) EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, @@ -868,23 +855,22 @@ void DwarfException::EmitExceptionTable() { else EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); - Asm->EOL("Region length"); + EOL("Region length"); // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. if (!S.PadLabel) - Asm->EmitInt32(0); + Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); else EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, true, true); - Asm->EOL("Landing pad"); + EOL("Landing pad"); // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of // the action table), and 0 indicates that there are no actions. - Asm->EmitULEB128Bytes(S.Action); - Asm->EOL("Action"); + EmitULEB128(S.Action, "Action"); } } @@ -897,17 +883,13 @@ void DwarfException::EmitExceptionTable() { // // Used by the runtime to match the type of the thrown exception to the // type of the catch clauses or the types in the exception specification. - - Asm->EmitSLEB128Bytes(Action.ValueForTypeID); - Asm->EOL("TypeInfo index"); + EmitSLEB128(Action.ValueForTypeID, "TypeInfo index"); // Action Record // // Self-relative signed displacement in bytes of the next action record, // or 0 if there is no next action record. - - Asm->EmitSLEB128Bytes(Action.NextAction); - Asm->EOL("Next action"); + EmitSLEB128(Action.NextAction, "Next action"); } // Emit the Catch TypeInfos. @@ -916,24 +898,19 @@ void DwarfException::EmitExceptionTable() { const GlobalVariable *GV = *I; PrintRelDirective(); - if (GV) { - O << Asm->Mang->getMangledName(GV); - } else { + if (GV) + O << *Asm->GetGlobalValueSymbol(GV); + else O << "0x0"; - } - Asm->EOL("TypeInfo"); + EOL("TypeInfo"); } // Emit the Exception Specifications. for (std::vector<unsigned>::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { unsigned TypeID = *I; - Asm->EmitULEB128Bytes(TypeID); - if (TypeID != 0) - Asm->EOL("Exception specification"); - else - Asm->EOL(); + EmitULEB128(TypeID, TypeID != 0 ? "Exception specification" : 0); } Asm->EmitAlignment(2, 0, 0, false); @@ -1008,12 +985,12 @@ void DwarfException::EndFunction() { EmitLabel("eh_func_end", SubprogramCount); EmitExceptionTable(); - std::string FunctionEHName = - Asm->Mang->getMangledName(MF->getFunction(), ".eh", - Asm->MAI->is_EHSymbolPrivate()); + MCSymbol *FunctionEHSym = + Asm->GetSymbolWithGlobalValueBase(MF->getFunction(), ".eh", + Asm->MAI->is_EHSymbolPrivate()); // Save EH frame information - EHFrames.push_back(FunctionEHFrameInfo(FunctionEHName, SubprogramCount, + EHFrames.push_back(FunctionEHFrameInfo(FunctionEHSym, SubprogramCount, MMI->getPersonalityIndex(), MF->getFrameInfo()->hasCalls(), !MMI->getLandingPads().empty(), diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index aa01c5b..3921e91 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -32,21 +32,21 @@ class raw_ostream; //===----------------------------------------------------------------------===// /// DwarfException - Emits Dwarf exception handling directives. /// -class DwarfException : public Dwarf { +class DwarfException : public DwarfPrinter { struct FunctionEHFrameInfo { - std::string FnName; + MCSymbol *FunctionEHSym; // L_foo.eh unsigned Number; unsigned PersonalityIndex; bool hasCalls; bool hasLandingPads; std::vector<MachineMove> Moves; - const Function * function; + const Function *function; - FunctionEHFrameInfo(const std::string &FN, unsigned Num, unsigned P, + FunctionEHFrameInfo(MCSymbol *EHSym, unsigned Num, unsigned P, bool hC, bool hL, const std::vector<MachineMove> &M, const Function *f): - FnName(FN), Number(Num), PersonalityIndex(P), + FunctionEHSym(EHSym), Number(Num), PersonalityIndex(P), hasCalls(hC), hasLandingPads(hL), Moves(M), function (f) { } }; diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp index 20b959b..d204bba 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp @@ -18,21 +18,22 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/ADT/StringExtras.h" using namespace llvm; -Dwarf::Dwarf(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, - const char *flavor) +DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, + const char *flavor) : O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()), RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL), SubprogramCount(0), Flavor(flavor), SetCounter(1) {} -void Dwarf::PrintRelDirective(bool Force32Bit, bool isInSection) const { +void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const { if (isInSection && MAI->getDwarfSectionOffsetDirective()) O << MAI->getDwarfSectionOffsetDirective(); else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t)) @@ -41,14 +42,125 @@ void Dwarf::PrintRelDirective(bool Force32Bit, bool isInSection) const { O << MAI->getData64bitsDirective(); } +/// EOL - Print a newline character to asm stream. If a comment is present +/// then it will be printed first. Comments should not contain '\n'. +void DwarfPrinter::EOL(const Twine &Comment) const { + if (Asm->VerboseAsm && !Comment.isTriviallyEmpty()) { + Asm->O.PadToColumn(MAI->getCommentColumn()); + Asm->O << Asm->MAI->getCommentString() << ' ' << Comment; + } + Asm->O << '\n'; +} + +static const char *DecodeDWARFEncoding(unsigned Encoding) { + switch (Encoding) { + case dwarf::DW_EH_PE_absptr: return "absptr"; + case dwarf::DW_EH_PE_omit: return "omit"; + case dwarf::DW_EH_PE_pcrel: return "pcrel"; + case dwarf::DW_EH_PE_udata4: return "udata4"; + case dwarf::DW_EH_PE_udata8: return "udata8"; + case dwarf::DW_EH_PE_sdata4: return "sdata4"; + case dwarf::DW_EH_PE_sdata8: return "sdata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: + return "indirect pcrel udata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: + return "indirect pcrel sdata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: + return "indirect pcrel udata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: + return "indirect pcrel sdata8"; + } + + return "<unknown encoding>"; +} + +/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an +/// encoding. If verbose assembly output is enabled, we output comments +/// describing the encoding. Desc is an optional string saying what the +/// encoding is specifying (e.g. "LSDA"). +void DwarfPrinter::EmitEncodingByte(unsigned Val, const char *Desc) { + if (Asm->VerboseAsm) { + if (Desc != 0) + Asm->OutStreamer.AddComment(Twine(Desc)+" Encoding = " + + Twine(DecodeDWARFEncoding(Val))); + else + Asm->OutStreamer.AddComment(Twine("Encoding = ") + + DecodeDWARFEncoding(Val)); + } + + Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); +} + +/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. +void DwarfPrinter::EmitCFAByte(unsigned Val) { + if (Asm->VerboseAsm) { + if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64) + Asm->OutStreamer.AddComment("DW_CFA_offset + Reg (" + + Twine(Val-dwarf::DW_CFA_offset) + ")"); + else + Asm->OutStreamer.AddComment(dwarf::CallFrameString(Val)); + } + Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); +} + +/// EmitSLEB128 - emit the specified signed leb128 value. +void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const { + if (Asm->VerboseAsm && Desc) + Asm->OutStreamer.AddComment(Desc); + + if (MAI->hasLEB128()) { + O << "\t.sleb128\t" << Value; + Asm->OutStreamer.AddBlankLine(); + return; + } + + // If we don't have .sleb128, emit as .bytes. + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + + Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); + } while (IsMore); +} + +/// EmitULEB128 - emit the specified signed leb128 value. +void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc) const { + if (Asm->VerboseAsm && Desc) + Asm->OutStreamer.AddComment(Desc); + + if (MAI->hasLEB128()) { + O << "\t.uleb128\t" << Value; + Asm->OutStreamer.AddBlankLine(); + return; + } + + // If we don't have .uleb128, emit as .bytes. + do { + unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); + Value >>= 7; + if (Value) Byte |= 0x80; + Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); + } while (Value); +} + + /// PrintLabelName - Print label name in form used by Dwarf writer. /// -void Dwarf::PrintLabelName(const char *Tag, unsigned Number) const { +void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const { O << MAI->getPrivateGlobalPrefix() << Tag; if (Number) O << Number; } -void Dwarf::PrintLabelName(const char *Tag, unsigned Number, - const char *Suffix) const { +void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number, + const char *Suffix) const { O << MAI->getPrivateGlobalPrefix() << Tag; if (Number) O << Number; O << Suffix; @@ -56,32 +168,39 @@ void Dwarf::PrintLabelName(const char *Tag, unsigned Number, /// EmitLabel - Emit location label for internal use by Dwarf. /// -void Dwarf::EmitLabel(const char *Tag, unsigned Number) const { +void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const { PrintLabelName(Tag, Number); O << ":\n"; } /// EmitReference - Emit a reference to a label. /// -void Dwarf::EmitReference(const char *Tag, unsigned Number, - bool IsPCRelative, bool Force32Bit) const { +void DwarfPrinter::EmitReference(const char *Tag, unsigned Number, + bool IsPCRelative, bool Force32Bit) const { PrintRelDirective(Force32Bit); PrintLabelName(Tag, Number); if (IsPCRelative) O << "-" << MAI->getPCSymbol(); } -void Dwarf::EmitReference(const std::string &Name, bool IsPCRelative, - bool Force32Bit) const { +void DwarfPrinter::EmitReference(const std::string &Name, bool IsPCRelative, + bool Force32Bit) const { PrintRelDirective(Force32Bit); O << Name; if (IsPCRelative) O << "-" << MAI->getPCSymbol(); } +void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative, + bool Force32Bit) const { + PrintRelDirective(Force32Bit); + O << *Sym; + if (IsPCRelative) O << "-" << MAI->getPCSymbol(); +} + /// EmitDifference - Emit the difference between two labels. Some assemblers do /// not behave with absolute expressions with data directives, so there is an /// option (needsSet) to use an intermediary set expression. -void Dwarf::EmitDifference(const char *TagHi, unsigned NumberHi, - const char *TagLo, unsigned NumberLo, - bool IsSmall) { +void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi, + const char *TagLo, unsigned NumberLo, + bool IsSmall) { if (MAI->needsSet()) { O << "\t.set\t"; PrintLabelName("set", SetCounter, Flavor); @@ -102,10 +221,11 @@ void Dwarf::EmitDifference(const char *TagHi, unsigned NumberHi, } } -void Dwarf::EmitSectionOffset(const char* Label, const char* Section, - unsigned LabelNumber, unsigned SectionNumber, - bool IsSmall, bool isEH, - bool useSet) { +void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section, + unsigned LabelNumber, + unsigned SectionNumber, + bool IsSmall, bool isEH, + bool useSet) { bool printAbsolute = false; if (isEH) printAbsolute = MAI->isAbsoluteEHSectionOffsets(); @@ -140,8 +260,9 @@ void Dwarf::EmitSectionOffset(const char* Label, const char* Section, /// EmitFrameMoves - Emit frame instructions to describe the layout of the /// frame. -void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, - const std::vector<MachineMove> &Moves, bool isEH) { +void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, + const std::vector<MachineMove> &Moves, + bool isEH) { int stackGrowth = Asm->TM.getFrameInfo()->getStackGrowthDirection() == TargetFrameInfo::StackGrowsUp ? @@ -164,10 +285,9 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, // Advance row if new location. if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) { - Asm->EmitInt8(dwarf::DW_CFA_advance_loc4); - Asm->EOL("DW_CFA_advance_loc4"); + EmitCFAByte(dwarf::DW_CFA_advance_loc4); EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true); - Asm->EOL(); + Asm->O << '\n'; BaseLabelID = LabelID; BaseLabel = "label"; @@ -178,29 +298,22 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { if (!Src.isReg()) { if (Src.getReg() == MachineLocation::VirtualFP) { - Asm->EmitInt8(dwarf::DW_CFA_def_cfa_offset); - Asm->EOL("DW_CFA_def_cfa_offset"); + EmitCFAByte(dwarf::DW_CFA_def_cfa_offset); } else { - Asm->EmitInt8(dwarf::DW_CFA_def_cfa); - Asm->EOL("DW_CFA_def_cfa"); - Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), isEH)); - Asm->EOL("Register"); + EmitCFAByte(dwarf::DW_CFA_def_cfa); + EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register"); } int Offset = -Src.getOffset(); - - Asm->EmitULEB128Bytes(Offset); - Asm->EOL("Offset"); + EmitULEB128(Offset, "Offset"); } else { llvm_unreachable("Machine move not supported yet."); } } else if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { if (Dst.isReg()) { - Asm->EmitInt8(dwarf::DW_CFA_def_cfa_register); - Asm->EOL("DW_CFA_def_cfa_register"); - Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), isEH)); - Asm->EOL("Register"); + EmitCFAByte(dwarf::DW_CFA_def_cfa_register); + EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register"); } else { llvm_unreachable("Machine move not supported yet."); } @@ -209,27 +322,16 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, int Offset = Dst.getOffset() / stackGrowth; if (Offset < 0) { - Asm->EmitInt8(dwarf::DW_CFA_offset_extended_sf); - Asm->EOL("DW_CFA_offset_extended_sf"); - Asm->EmitULEB128Bytes(Reg); - Asm->EOL("Reg"); - Asm->EmitSLEB128Bytes(Offset); - Asm->EOL("Offset"); + EmitCFAByte(dwarf::DW_CFA_offset_extended_sf); + EmitULEB128(Reg, "Reg"); + EmitSLEB128(Offset, "Offset"); } else if (Reg < 64) { - Asm->EmitInt8(dwarf::DW_CFA_offset + Reg); - if (Asm->isVerbose()) - Asm->EOL("DW_CFA_offset + Reg (" + utostr(Reg) + ")"); - else - Asm->EOL(); - Asm->EmitULEB128Bytes(Offset); - Asm->EOL("Offset"); + EmitCFAByte(dwarf::DW_CFA_offset + Reg); + EmitULEB128(Offset, "Offset"); } else { - Asm->EmitInt8(dwarf::DW_CFA_offset_extended); - Asm->EOL("DW_CFA_offset_extended"); - Asm->EmitULEB128Bytes(Reg); - Asm->EOL("Reg"); - Asm->EmitULEB128Bytes(Offset); - Asm->EOL("Offset"); + EmitCFAByte(dwarf::DW_CFA_offset_extended); + EmitULEB128(Reg, "Reg"); + EmitULEB128(Offset, "Offset"); } } } diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h index dedd695..86fe2ab 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.h @@ -17,135 +17,149 @@ #include "DwarfLabel.h" #include "llvm/CodeGen/MachineLocation.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/FormattedStream.h" #include <vector> namespace llvm { - class AsmPrinter; - class MachineFunction; - class MachineModuleInfo; - class Module; - class MCAsmInfo; - class TargetData; - class TargetRegisterInfo; - - class Dwarf { - protected: - //===-------------------------------------------------------------==---===// - // Core attributes used by the DWARF printer. - // - - /// O - Stream to .s file. - /// - raw_ostream &O; - - /// Asm - Target of Dwarf emission. - /// - AsmPrinter *Asm; - - /// MAI - Target asm information. - /// - const MCAsmInfo *MAI; - - /// TD - Target data. - /// - const TargetData *TD; - - /// RI - Register Information. - /// - const TargetRegisterInfo *RI; - - /// M - Current module. - /// - Module *M; - - /// MF - Current machine function. - /// - MachineFunction *MF; - - /// MMI - Collected machine module information. - /// - MachineModuleInfo *MMI; - - /// SubprogramCount - The running count of functions being compiled. - /// - unsigned SubprogramCount; - - /// Flavor - A unique string indicating what dwarf producer this is, used to - /// unique labels. - /// - const char * const Flavor; - - /// SetCounter - A unique number for each '.set' directive. - /// - unsigned SetCounter; - - Dwarf(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, - const char *flavor); - public: - //===------------------------------------------------------------------===// - // Accessors. - // - const AsmPrinter *getAsm() const { return Asm; } - MachineModuleInfo *getMMI() const { return MMI; } - const MCAsmInfo *getMCAsmInfo() const { return MAI; } - const TargetData *getTargetData() const { return TD; } - - void PrintRelDirective(bool Force32Bit = false, - bool isInSection = false) const; - - - /// PrintLabelName - Print label name in form used by Dwarf writer. - /// - void PrintLabelName(const DWLabel &Label) const { - PrintLabelName(Label.getTag(), Label.getNumber()); - } - void PrintLabelName(const char *Tag, unsigned Number) const; - void PrintLabelName(const char *Tag, unsigned Number, - const char *Suffix) const; - - /// EmitLabel - Emit location label for internal use by Dwarf. - /// - void EmitLabel(const DWLabel &Label) const { - EmitLabel(Label.getTag(), Label.getNumber()); - } - void EmitLabel(const char *Tag, unsigned Number) const; - - /// EmitReference - Emit a reference to a label. - /// - void EmitReference(const DWLabel &Label, bool IsPCRelative = false, - bool Force32Bit = false) const { - EmitReference(Label.getTag(), Label.getNumber(), - IsPCRelative, Force32Bit); - } - void EmitReference(const char *Tag, unsigned Number, - bool IsPCRelative = false, - bool Force32Bit = false) const; - void EmitReference(const std::string &Name, bool IsPCRelative = false, - bool Force32Bit = false) const; - - /// EmitDifference - Emit the difference between two labels. Some - /// assemblers do not behave with absolute expressions with data directives, - /// so there is an option (needsSet) to use an intermediary set expression. - void EmitDifference(const DWLabel &LabelHi, const DWLabel &LabelLo, - bool IsSmall = false) { - EmitDifference(LabelHi.getTag(), LabelHi.getNumber(), - LabelLo.getTag(), LabelLo.getNumber(), - IsSmall); - } - void EmitDifference(const char *TagHi, unsigned NumberHi, - const char *TagLo, unsigned NumberLo, - bool IsSmall = false); - - void EmitSectionOffset(const char* Label, const char* Section, - unsigned LabelNumber, unsigned SectionNumber, - bool IsSmall = false, bool isEH = false, - bool useSet = true); - - /// EmitFrameMoves - Emit frame instructions to describe the layout of the - /// frame. - void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, - const std::vector<MachineMove> &Moves, bool isEH); +class AsmPrinter; +class MachineFunction; +class MachineModuleInfo; +class Module; +class MCAsmInfo; +class TargetData; +class TargetRegisterInfo; +class MCSymbol; +class Twine; + +class DwarfPrinter { +protected: + //===-------------------------------------------------------------==---===// + // Core attributes used by the DWARF printer. + // + + /// O - Stream to .s file. + raw_ostream &O; + + /// Asm - Target of Dwarf emission. + AsmPrinter *Asm; + + /// MAI - Target asm information. + const MCAsmInfo *MAI; + + /// TD - Target data. + const TargetData *TD; + + /// RI - Register Information. + const TargetRegisterInfo *RI; + + /// M - Current module. + Module *M; + + /// MF - Current machine function. + MachineFunction *MF; + + /// MMI - Collected machine module information. + MachineModuleInfo *MMI; + + /// SubprogramCount - The running count of functions being compiled. + unsigned SubprogramCount; + + /// Flavor - A unique string indicating what dwarf producer this is, used to + /// unique labels. + const char * const Flavor; + + /// SetCounter - A unique number for each '.set' directive. + unsigned SetCounter; + + DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, + const char *flavor); +public: + + //===------------------------------------------------------------------===// + // Accessors. + // + const AsmPrinter *getAsm() const { return Asm; } + MachineModuleInfo *getMMI() const { return MMI; } + const MCAsmInfo *getMCAsmInfo() const { return MAI; } + const TargetData *getTargetData() const { return TD; } + + void PrintRelDirective(bool Force32Bit = false, + bool isInSection = false) const; + + /// EOL - Print a newline character to asm stream. If a comment is present + /// then it will be printed first. Comments should not contain '\n'. + void EOL(const Twine &Comment) const; + + /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an + /// encoding. If verbose assembly output is enabled, we output comments + /// describing the encoding. Desc is a string saying what the encoding is + /// specifying (e.g. "LSDA"). + void EmitEncodingByte(unsigned Val, const char *Desc); + + /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. + void EmitCFAByte(unsigned Val); + + + /// EmitSLEB128 - emit the specified signed leb128 value. + void EmitSLEB128(int Value, const char *Desc) const; + + /// EmitULEB128 - emit the specified unsigned leb128 value. + void EmitULEB128(unsigned Value, const char *Desc = 0) const; + + + /// PrintLabelName - Print label name in form used by Dwarf writer. + /// + void PrintLabelName(const DWLabel &Label) const { + PrintLabelName(Label.getTag(), Label.getNumber()); + } + void PrintLabelName(const char *Tag, unsigned Number) const; + void PrintLabelName(const char *Tag, unsigned Number, + const char *Suffix) const; + + /// EmitLabel - Emit location label for internal use by Dwarf. + /// + void EmitLabel(const DWLabel &Label) const { + EmitLabel(Label.getTag(), Label.getNumber()); + } + void EmitLabel(const char *Tag, unsigned Number) const; + + /// EmitReference - Emit a reference to a label. + /// + void EmitReference(const DWLabel &Label, bool IsPCRelative = false, + bool Force32Bit = false) const { + EmitReference(Label.getTag(), Label.getNumber(), + IsPCRelative, Force32Bit); + } + void EmitReference(const char *Tag, unsigned Number, + bool IsPCRelative = false, + bool Force32Bit = false) const; + void EmitReference(const std::string &Name, bool IsPCRelative = false, + bool Force32Bit = false) const; + void EmitReference(const MCSymbol *Sym, bool IsPCRelative = false, + bool Force32Bit = false) const; + + /// EmitDifference - Emit the difference between two labels. Some + /// assemblers do not behave with absolute expressions with data directives, + /// so there is an option (needsSet) to use an intermediary set expression. + void EmitDifference(const DWLabel &LabelHi, const DWLabel &LabelLo, + bool IsSmall = false) { + EmitDifference(LabelHi.getTag(), LabelHi.getNumber(), + LabelLo.getTag(), LabelLo.getNumber(), + IsSmall); + } + void EmitDifference(const char *TagHi, unsigned NumberHi, + const char *TagLo, unsigned NumberLo, + bool IsSmall = false); + + void EmitSectionOffset(const char* Label, const char* Section, + unsigned LabelNumber, unsigned SectionNumber, + bool IsSmall = false, bool isEH = false, + bool useSet = true); + + /// EmitFrameMoves - Emit frame instructions to describe the layout of the + /// frame. + void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, + const std::vector<MachineMove> &Moves, bool isEH); }; } // end llvm namespace diff --git a/lib/CodeGen/AsmPrinter/Makefile b/lib/CodeGen/AsmPrinter/Makefile index 8f65d8d..b0071d0 100644 --- a/lib/CodeGen/AsmPrinter/Makefile +++ b/lib/CodeGen/AsmPrinter/Makefile @@ -1,4 +1,4 @@ -##===- lib/CodeGen/SelectionDAG/Makefile -------------------*- Makefile -*-===## +##===- lib/CodeGen/AsmPrinter/Makefile ---------------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -6,8 +6,9 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMAsmPrinter -PARALLEL_DIRS = +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index 9286ad5..3531ed6 100644 --- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -21,7 +21,7 @@ #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/FormattedStream.h" using namespace llvm; namespace { @@ -105,8 +105,7 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); EmitCamlGlobal(getModule(), OS, AP, MAI, "data_end"); - OS << AddressDirective << 0; // FIXME: Why does ocaml emit this?? - AP.EOL(); + OS << AddressDirective << 0 << '\n'; // FIXME: Why does ocaml emit this?? AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); EmitCamlGlobal(getModule(), OS, AP, MAI, "frametable"); @@ -140,14 +139,11 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, } OS << AddressDirective - << MAI.getPrivateGlobalPrefix() << "label" << J->Num; - AP.EOL("call return address"); + << MAI.getPrivateGlobalPrefix() << "label" << J->Num << '\n'; AP.EmitInt16(FrameSize); - AP.EOL("stack frame size"); AP.EmitInt16(LiveCount); - AP.EOL("live root count"); for (GCFunctionInfo::live_iterator K = FI.live_begin(J), KE = FI.live_end(J); K != KE; ++K) { @@ -155,8 +151,7 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, "GC root stack offset is outside of fixed stack frame and out " "of range for ocaml GC!"); - OS << "\t.word\t" << K->StackOffset; - AP.EOL("stack offset"); + AP.EmitInt32(K->StackOffset); } AP.EmitAlignment(AddressAlignLog); diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index 6bc808c..17072d3 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -21,7 +21,6 @@ add_llvm_library(LLVMCodeGen LiveStackAnalysis.cpp LiveVariables.cpp LowerSubregs.cpp - MachOCodeEmitter.cpp MachOWriter.cpp MachineBasicBlock.cpp MachineDominators.cpp @@ -38,7 +37,6 @@ add_llvm_library(LLVMCodeGen MachineSSAUpdater.cpp MachineSink.cpp MachineVerifier.cpp - MaxStackAlignment.cpp ObjectCodeEmitter.cpp OcamlGC.cpp OptimizeExts.cpp diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp index 9b516ed..39fc85e 100644 --- a/lib/CodeGen/DwarfEHPrepare.cpp +++ b/lib/CodeGen/DwarfEHPrepare.cpp @@ -21,6 +21,7 @@ #include "llvm/IntrinsicInst.h" #include "llvm/Module.h" #include "llvm/Pass.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" @@ -114,6 +115,9 @@ FunctionPass *llvm::createDwarfEHPass(const TargetLowering *tli, bool fast) { bool DwarfEHPrepare::NormalizeLandingPads() { bool Changed = false; + const MCAsmInfo *MAI = TLI->getTargetMachine().getMCAsmInfo(); + bool usingSjLjEH = MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { TerminatorInst *TI = I->getTerminator(); if (!isa<InvokeInst>(TI)) @@ -125,9 +129,18 @@ bool DwarfEHPrepare::NormalizeLandingPads() { // Check that only invoke unwind edges end at the landing pad. bool OnlyUnwoundTo = true; + bool SwitchOK = usingSjLjEH; for (pred_iterator PI = pred_begin(LPad), PE = pred_end(LPad); PI != PE; ++PI) { TerminatorInst *PT = (*PI)->getTerminator(); + // The SjLj dispatch block uses a switch instruction. This is effectively + // an unwind edge, so we can disregard it here. There will only ever + // be one dispatch, however, so if there are multiple switches, one + // of them truly is a normal edge, not an unwind edge. + if (SwitchOK && isa<SwitchInst>(PT)) { + SwitchOK = false; + continue; + } if (!isa<InvokeInst>(PT) || LPad == PT->getSuccessor(0)) { OnlyUnwoundTo = false; break; diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index 5e5f589..de45e09 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -45,6 +45,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetELFWriterInfo.h" #include "llvm/Target/TargetLowering.h" @@ -52,9 +53,8 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/raw_ostream.h" - +#include "llvm/ADT/SmallString.h" using namespace llvm; char ELFWriter::ID = 0; @@ -119,7 +119,7 @@ bool ELFWriter::doInitialization(Module &M) { // Initialize TargetLoweringObjectFile. const_cast<TargetLoweringObjectFile&>(TLOF).Initialize(OutContext, TM); - Mang = new Mangler(M); + Mang = new Mangler(*MAI); // ELF Header // ---------- @@ -703,10 +703,6 @@ bool ELFWriter::doFinalization(Module &M) { I != E; ++I) SymbolList.push_back(ELFSym::getExtSym(*I)); - // Emit non-executable stack note - if (MAI->getNonexecutableStackDirective()) - getNonExecStackSection(); - // Emit a symbol for each section created until now, skip null section for (unsigned i = 1, e = SectionList.size(); i < e; ++i) { ELFSection &ES = *SectionList[i]; @@ -906,9 +902,11 @@ void ELFWriter::EmitStringTable(const std::string &ModuleName) { ELFSym &Sym = *(*I); std::string Name; - if (Sym.isGlobalValue()) - Name.append(Mang->getMangledName(Sym.getGlobalValue())); - else if (Sym.isExternalSym()) + if (Sym.isGlobalValue()) { + SmallString<40> NameStr; + Mang->getNameWithPrefix(NameStr, Sym.getGlobalValue(), false); + Name.append(NameStr.begin(), NameStr.end()); + } else if (Sym.isExternalSym()) Name.append(Sym.getExternalSymbol()); else if (Sym.isFileType()) Name.append(ModuleName); diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 2b5fd2c..837e184 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -17,6 +17,7 @@ #include "llvm/Assembly/PrintModulePass.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/FileWriters.h" #include "llvm/CodeGen/GCStrategy.h" #include "llvm/CodeGen/MachineFunctionAnalysis.h" #include "llvm/Target/TargetOptions.h" @@ -38,6 +39,8 @@ static cl::opt<bool> DisableBranchFold("disable-branch-fold", cl::Hidden, cl::desc("Disable branch folding")); static cl::opt<bool> DisableTailDuplicate("disable-tail-duplicate", cl::Hidden, cl::desc("Disable tail duplication")); +static cl::opt<bool> DisableEarlyTailDup("disable-early-taildup", cl::Hidden, + cl::desc("Disable pre-register allocation tail duplication")); static cl::opt<bool> DisableCodePlace("disable-code-place", cl::Hidden, cl::desc("Disable code placement")); static cl::opt<bool> DisableSSC("disable-ssc", cl::Hidden, @@ -76,9 +79,6 @@ EnableFastISelOption("fast-isel", cl::Hidden, static cl::opt<bool> EnableSplitGEPGVN("split-gep-gvn", cl::Hidden, cl::desc("Split GEPs and run no-load GVN")); -static cl::opt<bool> PreAllocTailDup("pre-regalloc-taildup", cl::Hidden, - cl::desc("Pre-register allocation tail duplication")); - LLVMTargetMachine::LLVMTargetMachine(const Target &T, const std::string &TargetTriple) : TargetMachine(T) { @@ -115,12 +115,11 @@ LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, return FileModel::Error; return FileModel::AsmFile; case TargetMachine::ObjectFile: - if (getMachOWriterInfo()) + if (!addObjectFileEmitter(PM, OptLevel, Out)) return FileModel::MachOFile; else if (getELFWriterInfo()) - return FileModel::ElfFile; + return FileModel::ElfFile; } - return FileModel::Error; } @@ -137,6 +136,17 @@ bool LLVMTargetMachine::addAssemblyEmitter(PassManagerBase &PM, return false; } +bool LLVMTargetMachine::addObjectFileEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + formatted_raw_ostream &Out) { + MCCodeEmitter *Emitter = getTarget().createCodeEmitter(*this); + if (!Emitter) + return true; + + PM.add(createMachOWriter(Out, *this, getMCAsmInfo(), Emitter)); + return false; +} + /// addPassesToEmitFileFinish - If the passes to emit the specified file had to /// be split up (e.g., to add an object writer pass), this method can be used to /// finish up adding passes to emit the file, if necessary. @@ -340,8 +350,7 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, } // Pre-ra tail duplication. - if (OptLevel != CodeGenOpt::None && - !DisableTailDuplicate && PreAllocTailDup) { + if (OptLevel != CodeGenOpt::None && !DisableEarlyTailDup) { PM.add(createTailDuplicatePass(true)); printAndVerify(PM, "After Pre-RegAlloc TailDuplicate", /* allowDoubleDefs= */ true); diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index e0e2ec8..8746bf9 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -140,7 +140,10 @@ void LiveIntervals::printInstrs(raw_ostream &OS) const { << ":\t\t# derived from " << mbbi->getName() << "\n"; for (MachineBasicBlock::iterator mii = mbbi->begin(), mie = mbbi->end(); mii != mie; ++mii) { - OS << getInstructionIndex(mii) << '\t' << *mii; + if (mii->getOpcode()==TargetInstrInfo::DEBUG_VALUE) + OS << SlotIndex::getEmptyKey() << '\t' << *mii; + else + OS << getInstructionIndex(mii) << '\t' << *mii; } } } @@ -672,8 +675,6 @@ void LiveIntervals::computeIntervals() { SlotIndex MIIndex = getMBBStartIdx(MBB); DEBUG(dbgs() << MBB->getName() << ":\n"); - MachineBasicBlock::iterator MI = MBB->begin(), miEnd = MBB->end(); - // Create intervals for live-ins to this BB first. for (MachineBasicBlock::const_livein_iterator LI = MBB->livein_begin(), LE = MBB->livein_end(); LI != LE; ++LI) { @@ -689,8 +690,11 @@ void LiveIntervals::computeIntervals() { if (getInstructionFromIndex(MIIndex) == 0) MIIndex = indexes_->getNextNonNullIndex(MIIndex); - for (; MI != miEnd; ++MI) { + for (MachineBasicBlock::iterator MI = MBB->begin(), miEnd = MBB->end(); + MI != miEnd; ++MI) { DEBUG(dbgs() << MIIndex << "\t" << *MI); + if (MI->getOpcode()==TargetInstrInfo::DEBUG_VALUE) + continue; // Handle defs. for (int i = MI->getNumOperands() - 1; i >= 0; --i) { diff --git a/lib/CodeGen/MachO.h b/lib/CodeGen/MachO.h deleted file mode 100644 index f2b40fe..0000000 --- a/lib/CodeGen/MachO.h +++ /dev/null @@ -1,412 +0,0 @@ -//=== MachO.h - Mach-O structures and constants -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines MachO . -// -//===----------------------------------------------------------------------===// - -#ifndef MACHO_H -#define MACHO_H - -#include "llvm/CodeGen/BinaryObject.h" -#include <string> -#include <vector> - -namespace llvm { - -class GlobalValue; -class MCAsmInfo; - -/// MachOSym - This struct contains information about each symbol that is -/// added to logical symbol table for the module. This is eventually -/// turned into a real symbol table in the file. -struct MachOSym { - const GlobalValue *GV; // The global value this corresponds to. - std::string GVName; // The mangled name of the global value. - uint32_t n_strx; // index into the string table - uint8_t n_type; // type flag - uint8_t n_sect; // section number or NO_SECT - int16_t n_desc; // see <mach-o/stab.h> - uint64_t n_value; // value for this symbol (or stab offset) - - // Constants for the n_sect field - // see <mach-o/nlist.h> - enum { NO_SECT = 0 }; // symbol is not in any section - - // Constants for the n_type field - // see <mach-o/nlist.h> - enum { N_UNDF = 0x0, // undefined, n_sect == NO_SECT - N_ABS = 0x2, // absolute, n_sect == NO_SECT - N_SECT = 0xe, // defined in section number n_sect - N_PBUD = 0xc, // prebound undefined (defined in a dylib) - N_INDR = 0xa // indirect - }; - // The following bits are OR'd into the types above. For example, a type - // of 0x0f would be an external N_SECT symbol (0x0e | 0x01). - enum { N_EXT = 0x01, // external symbol bit - N_PEXT = 0x10 // private external symbol bit - }; - - // Constants for the n_desc field - // see <mach-o/loader.h> - enum { REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0, - REFERENCE_FLAG_UNDEFINED_LAZY = 1, - REFERENCE_FLAG_DEFINED = 2, - REFERENCE_FLAG_PRIVATE_DEFINED = 3, - REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4, - REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5 - }; - enum { N_NO_DEAD_STRIP = 0x0020, // symbol is not to be dead stripped - N_WEAK_REF = 0x0040, // symbol is weak referenced - N_WEAK_DEF = 0x0080 // coalesced symbol is a weak definition - }; - - MachOSym(const GlobalValue *gv, std::string name, uint8_t sect, - const MCAsmInfo *MAI); - - struct SymCmp { - // FIXME: this does not appear to be sorting 'f' after 'F' - bool operator()(const MachOSym &LHS, const MachOSym &RHS) { - return LHS.GVName < RHS.GVName; - } - }; - - - /// PartitionByLocal - Simple boolean predicate that returns true if Sym is - /// a local symbol rather than an external symbol. - - static inline bool PartitionByLocal(const MachOSym &Sym) { - return (Sym.n_type & (MachOSym::N_EXT | MachOSym::N_PEXT)) == 0; - } - - /// PartitionByDefined - Simple boolean predicate that returns true if Sym is - /// defined in this module. - - static inline bool PartitionByDefined(const MachOSym &Sym) { - // FIXME: Do N_ABS or N_INDR count as defined? - return (Sym.n_type & MachOSym::N_SECT) == MachOSym::N_SECT; - } - -}; // end struct MachOSym - -/// MachOHeader - This struct contains the header information about a -/// specific architecture type/subtype pair that is emitted to the file. - -struct MachOHeader { - uint32_t magic; // mach magic number identifier - uint32_t filetype; // type of file - uint32_t ncmds; // number of load commands - uint32_t sizeofcmds; // the size of all the load commands - uint32_t flags; // flags - uint32_t reserved; // 64-bit only - - /// HeaderData - The actual data for the header which we are building - /// up for emission to the file. - std::vector<unsigned char> HeaderData; - - // Constants for the filetype field - // see <mach-o/loader.h> for additional info on the various types - enum { MH_OBJECT = 1, // relocatable object file - MH_EXECUTE = 2, // demand paged executable file - MH_FVMLIB = 3, // fixed VM shared library file - MH_CORE = 4, // core file - MH_PRELOAD = 5, // preloaded executable file - MH_DYLIB = 6, // dynamically bound shared library - MH_DYLINKER = 7, // dynamic link editor - MH_BUNDLE = 8, // dynamically bound bundle file - MH_DYLIB_STUB = 9, // shared library stub for static linking only - MH_DSYM = 10 // companion file wiht only debug sections - }; - - // Constants for the flags field - enum { MH_NOUNDEFS = 1 << 0, - // the object file has no undefined references - MH_INCRLINK = 1 << 1, - // the object file is the output of an incremental link against - // a base file and cannot be link edited again - MH_DYLDLINK = 1 << 2, - // the object file is input for the dynamic linker and cannot be - // statically link edited again. - MH_BINDATLOAD = 1 << 3, - // the object file's undefined references are bound by the - // dynamic linker when loaded. - MH_PREBOUND = 1 << 4, - // the file has its dynamic undefined references prebound - MH_SPLIT_SEGS = 1 << 5, - // the file has its read-only and read-write segments split - // see <mach/shared_memory_server.h> - MH_LAZY_INIT = 1 << 6, - // the shared library init routine is to be run lazily via - // catching memory faults to its writable segments (obsolete) - MH_TWOLEVEL = 1 << 7, - // the image is using two-level namespace bindings - MH_FORCE_FLAT = 1 << 8, - // the executable is forcing all images to use flat namespace - // bindings. - MH_NOMULTIDEFS = 1 << 8, - // this umbrella guarantees no multiple definitions of symbols - // in its sub-images so the two-level namespace hints can - // always be used. - MH_NOFIXPREBINDING = 1 << 10, - // do not have dyld notify the prebidning agent about this - // executable. - MH_PREBINDABLE = 1 << 11, - // the binary is not prebound but can have its prebinding - // redone. only used when MH_PREBOUND is not set. - MH_ALLMODSBOUND = 1 << 12, - // indicates that this binary binds to all two-level namespace - // modules of its dependent libraries. Only used when - // MH_PREBINDABLE and MH_TWOLEVEL are both set. - MH_SUBSECTIONS_VIA_SYMBOLS = 1 << 13, - // safe to divide up the sections into sub-sections via symbols - // for dead code stripping. - MH_CANONICAL = 1 << 14, - // the binary has been canonicalized via the unprebind operation - MH_WEAK_DEFINES = 1 << 15, - // the final linked image contains external weak symbols - MH_BINDS_TO_WEAK = 1 << 16, - // the final linked image uses weak symbols - MH_ALLOW_STACK_EXECUTION = 1 << 17 - // When this bit is set, all stacks in the task will be given - // stack execution privilege. Only used in MH_EXECUTE filetype - }; - - MachOHeader() : magic(0), filetype(0), ncmds(0), sizeofcmds(0), flags(0), - reserved(0) {} - - /// cmdSize - This routine returns the size of the MachOSection as written - /// to disk, depending on whether the destination is a 64 bit Mach-O file. - unsigned cmdSize(bool is64Bit) const { - if (is64Bit) - return 8 * sizeof(uint32_t); - else - return 7 * sizeof(uint32_t); - } - - /// setMagic - This routine sets the appropriate value for the 'magic' - /// field based on pointer size and endianness. - void setMagic(bool isLittleEndian, bool is64Bit) { - if (isLittleEndian) - if (is64Bit) magic = 0xcffaedfe; - else magic = 0xcefaedfe; - else - if (is64Bit) magic = 0xfeedfacf; - else magic = 0xfeedface; - } - -}; // end struct MachOHeader - -/// MachOSegment - This struct contains the necessary information to -/// emit the load commands for each section in the file. -struct MachOSegment { - uint32_t cmd; // LC_SEGMENT or LC_SEGMENT_64 - uint32_t cmdsize; // Total size of this struct and section commands - std::string segname; // segment name - uint64_t vmaddr; // address of this segment - uint64_t vmsize; // size of this segment, may be larger than filesize - uint64_t fileoff; // offset in file - uint64_t filesize; // amount to read from file - uint32_t maxprot; // maximum VM protection - uint32_t initprot; // initial VM protection - uint32_t nsects; // number of sections in this segment - uint32_t flags; // flags - - // The following constants are getting pulled in by one of the - // system headers, which creates a neat clash with the enum. -#if !defined(VM_PROT_NONE) -#define VM_PROT_NONE 0x00 -#endif -#if !defined(VM_PROT_READ) -#define VM_PROT_READ 0x01 -#endif -#if !defined(VM_PROT_WRITE) -#define VM_PROT_WRITE 0x02 -#endif -#if !defined(VM_PROT_EXECUTE) -#define VM_PROT_EXECUTE 0x04 -#endif -#if !defined(VM_PROT_ALL) -#define VM_PROT_ALL 0x07 -#endif - - // Constants for the vm protection fields - // see <mach-o/vm_prot.h> - enum { SEG_VM_PROT_NONE = VM_PROT_NONE, - SEG_VM_PROT_READ = VM_PROT_READ, // read permission - SEG_VM_PROT_WRITE = VM_PROT_WRITE, // write permission - SEG_VM_PROT_EXECUTE = VM_PROT_EXECUTE, - SEG_VM_PROT_ALL = VM_PROT_ALL - }; - - // Constants for the cmd field - // see <mach-o/loader.h> - enum { LC_SEGMENT = 0x01, // segment of this file to be mapped - LC_SEGMENT_64 = 0x19 // 64-bit segment of this file to be mapped - }; - - /// cmdSize - This routine returns the size of the MachOSection as written - /// to disk, depending on whether the destination is a 64 bit Mach-O file. - unsigned cmdSize(bool is64Bit) const { - if (is64Bit) - return 6 * sizeof(uint32_t) + 4 * sizeof(uint64_t) + 16; - else - return 10 * sizeof(uint32_t) + 16; // addresses only 32 bits - } - - MachOSegment(const std::string &seg, bool is64Bit) - : cmd(is64Bit ? LC_SEGMENT_64 : LC_SEGMENT), cmdsize(0), segname(seg), - vmaddr(0), vmsize(0), fileoff(0), filesize(0), maxprot(VM_PROT_ALL), - initprot(VM_PROT_ALL), nsects(0), flags(0) { } -}; - -/// MachOSection - This struct contains information about each section in a -/// particular segment that is emitted to the file. This is eventually -/// turned into the SectionCommand in the load command for a particlar -/// segment. - -struct MachOSection : public BinaryObject { - std::string sectname; // name of this section, - std::string segname; // segment this section goes in - uint64_t addr; // memory address of this section - uint32_t offset; // file offset of this section - uint32_t align; // section alignment (power of 2) - uint32_t reloff; // file offset of relocation entries - uint32_t nreloc; // number of relocation entries - uint32_t flags; // flags (section type and attributes) - uint32_t reserved1; // reserved (for offset or index) - uint32_t reserved2; // reserved (for count or sizeof) - uint32_t reserved3; // reserved (64 bit only) - - /// A unique number for this section, which will be used to match symbols - /// to the correct section. - uint32_t Index; - - /// RelocBuffer - A buffer to hold the mach-o relocations before we write - /// them out at the appropriate location in the file. - std::vector<unsigned char> RelocBuffer; - - // Constants for the section types (low 8 bits of flags field) - // see <mach-o/loader.h> - enum { S_REGULAR = 0, - // regular section - S_ZEROFILL = 1, - // zero fill on demand section - S_CSTRING_LITERALS = 2, - // section with only literal C strings - S_4BYTE_LITERALS = 3, - // section with only 4 byte literals - S_8BYTE_LITERALS = 4, - // section with only 8 byte literals - S_LITERAL_POINTERS = 5, - // section with only pointers to literals - S_NON_LAZY_SYMBOL_POINTERS = 6, - // section with only non-lazy symbol pointers - S_LAZY_SYMBOL_POINTERS = 7, - // section with only lazy symbol pointers - S_SYMBOL_STUBS = 8, - // section with only symbol stubs - // byte size of stub in the reserved2 field - S_MOD_INIT_FUNC_POINTERS = 9, - // section with only function pointers for initialization - S_MOD_TERM_FUNC_POINTERS = 10, - // section with only function pointers for termination - S_COALESCED = 11, - // section contains symbols that are coalesced - S_GB_ZEROFILL = 12, - // zero fill on demand section (that can be larger than 4GB) - S_INTERPOSING = 13, - // section with only pairs of function pointers for interposing - S_16BYTE_LITERALS = 14 - // section with only 16 byte literals - }; - - // Constants for the section flags (high 24 bits of flags field) - // see <mach-o/loader.h> - enum { S_ATTR_PURE_INSTRUCTIONS = 1 << 31, - // section contains only true machine instructions - S_ATTR_NO_TOC = 1 << 30, - // section contains coalesced symbols that are not to be in a - // ranlib table of contents - S_ATTR_STRIP_STATIC_SYMS = 1 << 29, - // ok to strip static symbols in this section in files with the - // MY_DYLDLINK flag - S_ATTR_NO_DEAD_STRIP = 1 << 28, - // no dead stripping - S_ATTR_LIVE_SUPPORT = 1 << 27, - // blocks are live if they reference live blocks - S_ATTR_SELF_MODIFYING_CODE = 1 << 26, - // used with i386 code stubs written on by dyld - S_ATTR_DEBUG = 1 << 25, - // a debug section - S_ATTR_SOME_INSTRUCTIONS = 1 << 10, - // section contains some machine instructions - S_ATTR_EXT_RELOC = 1 << 9, - // section has external relocation entries - S_ATTR_LOC_RELOC = 1 << 8 - // section has local relocation entries - }; - - /// cmdSize - This routine returns the size of the MachOSection as written - /// to disk, depending on whether the destination is a 64 bit Mach-O file. - unsigned cmdSize(bool is64Bit) const { - if (is64Bit) - return 7 * sizeof(uint32_t) + 2 * sizeof(uint64_t) + 32; - else - return 9 * sizeof(uint32_t) + 32; // addresses only 32 bits - } - - MachOSection(const std::string &seg, const std::string §) - : BinaryObject(), sectname(sect), segname(seg), addr(0), offset(0), - align(2), reloff(0), nreloc(0), flags(0), reserved1(0), reserved2(0), - reserved3(0) { } - -}; // end struct MachOSection - -/// MachOSymTab - This struct contains information about the offsets and -/// size of symbol table information. -/// segment. -struct MachODySymTab { - uint32_t cmd; // LC_DYSYMTAB - uint32_t cmdsize; // sizeof(MachODySymTab) - uint32_t ilocalsym; // index to local symbols - uint32_t nlocalsym; // number of local symbols - uint32_t iextdefsym; // index to externally defined symbols - uint32_t nextdefsym; // number of externally defined symbols - uint32_t iundefsym; // index to undefined symbols - uint32_t nundefsym; // number of undefined symbols - uint32_t tocoff; // file offset to table of contents - uint32_t ntoc; // number of entries in table of contents - uint32_t modtaboff; // file offset to module table - uint32_t nmodtab; // number of module table entries - uint32_t extrefsymoff; // offset to referenced symbol table - uint32_t nextrefsyms; // number of referenced symbol table entries - uint32_t indirectsymoff; // file offset to the indirect symbol table - uint32_t nindirectsyms; // number of indirect symbol table entries - uint32_t extreloff; // offset to external relocation entries - uint32_t nextrel; // number of external relocation entries - uint32_t locreloff; // offset to local relocation entries - uint32_t nlocrel; // number of local relocation entries - - // Constants for the cmd field - // see <mach-o/loader.h> - enum { LC_DYSYMTAB = 0x0B // dynamic link-edit symbol table info - }; - - MachODySymTab() : cmd(LC_DYSYMTAB), cmdsize(20 * sizeof(uint32_t)), - ilocalsym(0), nlocalsym(0), iextdefsym(0), nextdefsym(0), - iundefsym(0), nundefsym(0), tocoff(0), ntoc(0), modtaboff(0), - nmodtab(0), extrefsymoff(0), nextrefsyms(0), indirectsymoff(0), - nindirectsyms(0), extreloff(0), nextrel(0), locreloff(0), nlocrel(0) {} - -}; // end struct MachODySymTab - -} // end namespace llvm - -#endif - diff --git a/lib/CodeGen/MachOCodeEmitter.cpp b/lib/CodeGen/MachOCodeEmitter.cpp deleted file mode 100644 index 1318477..0000000 --- a/lib/CodeGen/MachOCodeEmitter.cpp +++ /dev/null @@ -1,193 +0,0 @@ -//===-- MachOEmitter.cpp - Target-independent Mach-O Emitter code --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "MachO.h" -#include "MachOWriter.h" -#include "MachOCodeEmitter.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Function.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/CodeGen/MachineRelocation.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Mangler.h" -#include "llvm/Support/OutputBuffer.h" -#include <vector> - -//===----------------------------------------------------------------------===// -// MachOCodeEmitter Implementation -//===----------------------------------------------------------------------===// - -namespace llvm { - -MachOCodeEmitter::MachOCodeEmitter(MachOWriter &mow, MachOSection &mos) : - ObjectCodeEmitter(&mos), MOW(mow), TM(MOW.TM) { - is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; - isLittleEndian = TM.getTargetData()->isLittleEndian(); - MAI = TM.getMCAsmInfo(); -} - -/// startFunction - This callback is invoked when a new machine function is -/// about to be emitted. - -void MachOCodeEmitter::startFunction(MachineFunction &MF) { - const TargetData *TD = TM.getTargetData(); - const Function *F = MF.getFunction(); - - // Align the output buffer to the appropriate alignment, power of 2. - unsigned FnAlign = F->getAlignment(); - unsigned TDAlign = TD->getPrefTypeAlignment(F->getType()); - unsigned Align = Log2_32(std::max(FnAlign, TDAlign)); - assert(!(Align & (Align-1)) && "Alignment is not a power of two!"); - - // Get the Mach-O Section that this function belongs in. - MachOSection *MOS = MOW.getTextSection(); - - // Upgrade the section alignment if required. - if (MOS->align < Align) MOS->align = Align; - - MOS->emitAlignment(Align); - - // Create symbol for function entry - const GlobalValue *FuncV = MF.getFunction(); - MachOSym FnSym(FuncV, MOW.Mang->getMangledName(FuncV), MOS->Index, MAI); - FnSym.n_value = getCurrentPCOffset(); - - // add it to the symtab. - MOW.SymbolTable.push_back(FnSym); -} - -/// finishFunction - This callback is invoked after the function is completely -/// finished. - -bool MachOCodeEmitter::finishFunction(MachineFunction &MF) { - - // Get the Mach-O Section that this function belongs in. - MachOSection *MOS = MOW.getTextSection(); - - // Emit constant pool to appropriate section(s) - emitConstantPool(MF.getConstantPool()); - - // Emit jump tables to appropriate section - emitJumpTables(MF.getJumpTableInfo()); - - // If we have emitted any relocations to function-specific objects such as - // basic blocks, constant pools entries, or jump tables, record their - // addresses now so that we can rewrite them with the correct addresses - // later. - for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { - MachineRelocation &MR = Relocations[i]; - intptr_t Addr; - - if (MR.isBasicBlock()) { - Addr = getMachineBasicBlockAddress(MR.getBasicBlock()); - MR.setConstantVal(MOS->Index); - MR.setResultPointer((void*)Addr); - } else if (MR.isJumpTableIndex()) { - Addr = getJumpTableEntryAddress(MR.getJumpTableIndex()); - MR.setConstantVal(MOW.getJumpTableSection()->Index); - MR.setResultPointer((void*)Addr); - } else if (MR.isConstantPoolIndex()) { - Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex()); - MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]); - MR.setResultPointer((void*)Addr); - } else if (MR.isGlobalValue()) { - // FIXME: This should be a set or something that uniques - MOW.PendingGlobals.push_back(MR.getGlobalValue()); - } else { - llvm_unreachable("Unhandled relocation type"); - } - MOS->addRelocation(MR); - } - Relocations.clear(); - - // Clear per-function data structures. - CPLocations.clear(); - CPSections.clear(); - JTLocations.clear(); - MBBLocations.clear(); - - return false; -} - -/// emitConstantPool - For each constant pool entry, figure out which section -/// the constant should live in, allocate space for it, and emit it to the -/// Section data buffer. -void MachOCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { - const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants(); - if (CP.empty()) return; - - // FIXME: handle PIC codegen - assert(TM.getRelocationModel() != Reloc::PIC_ && - "PIC codegen not yet handled for mach-o jump tables!"); - - // Although there is no strict necessity that I am aware of, we will do what - // gcc for OS X does and put each constant pool entry in a section of constant - // objects of a certain size. That means that float constants go in the - // literal4 section, and double objects go in literal8, etc. - // - // FIXME: revisit this decision if we ever do the "stick everything into one - // "giant object for PIC" optimization. - for (unsigned i = 0, e = CP.size(); i != e; ++i) { - const Type *Ty = CP[i].getType(); - unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); - - MachOSection *Sec = MOW.getConstSection(CP[i].Val.ConstVal); - OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian); - - CPLocations.push_back(Sec->size()); - CPSections.push_back(Sec->Index); - - // Allocate space in the section for the global. - // FIXME: need alignment? - // FIXME: share between here and AddSymbolToSection? - for (unsigned j = 0; j < Size; ++j) - SecDataOut.outbyte(0); - - MachOWriter::InitMem(CP[i].Val.ConstVal, CPLocations[i], - TM.getTargetData(), Sec); - } -} - -/// emitJumpTables - Emit all the jump tables for a given jump table info -/// record to the appropriate section. -void MachOCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { - const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); - if (JT.empty()) return; - - // FIXME: handle PIC codegen - assert(TM.getRelocationModel() != Reloc::PIC_ && - "PIC codegen not yet handled for mach-o jump tables!"); - - MachOSection *Sec = MOW.getJumpTableSection(); - unsigned TextSecIndex = MOW.getTextSection()->Index; - OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian); - - for (unsigned i = 0, e = JT.size(); i != e; ++i) { - // For each jump table, record its offset from the start of the section, - // reserve space for the relocations to the MBBs, and add the relocations. - const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs; - JTLocations.push_back(Sec->size()); - for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { - MachineRelocation MR(MOW.GetJTRelocation(Sec->size(), MBBs[mi])); - MR.setResultPointer((void *)JTLocations[i]); - MR.setConstantVal(TextSecIndex); - Sec->addRelocation(MR); - SecDataOut.outaddr(0); - } - } -} - -} // end namespace llvm - diff --git a/lib/CodeGen/MachOCodeEmitter.h b/lib/CodeGen/MachOCodeEmitter.h deleted file mode 100644 index 4752446..0000000 --- a/lib/CodeGen/MachOCodeEmitter.h +++ /dev/null @@ -1,69 +0,0 @@ -//===-- MachOEmitter.h - Target-independent Mach-O Emitter class ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef MACHOCODEEMITTER_H -#define MACHOCODEEMITTER_H - -#include "llvm/CodeGen/ObjectCodeEmitter.h" -#include <map> - -namespace llvm { - -class MachOWriter; - -/// MachOCodeEmitter - This class is used by the MachOWriter to emit the code -/// for functions to the Mach-O file. - -class MachOCodeEmitter : public ObjectCodeEmitter { - MachOWriter &MOW; - - /// Target machine description. - TargetMachine &TM; - - /// is64Bit/isLittleEndian - This information is inferred from the target - /// machine directly, indicating what header values and flags to set. - bool is64Bit, isLittleEndian; - - const MCAsmInfo *MAI; - - /// Relocations - These are the relocations that the function needs, as - /// emitted. - std::vector<MachineRelocation> Relocations; - - std::map<uint64_t, uintptr_t> Labels; - -public: - MachOCodeEmitter(MachOWriter &mow, MachOSection &mos); - - virtual void startFunction(MachineFunction &MF); - virtual bool finishFunction(MachineFunction &MF); - - virtual void addRelocation(const MachineRelocation &MR) { - Relocations.push_back(MR); - } - - void emitConstantPool(MachineConstantPool *MCP); - void emitJumpTables(MachineJumpTableInfo *MJTI); - - virtual void emitLabel(uint64_t LabelID) { - Labels[LabelID] = getCurrentPCOffset(); - } - - virtual uintptr_t getLabelAddress(uint64_t Label) const { - return Labels.find(Label)->second; - } - - virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { } - -}; // end class MachOCodeEmitter - -} // end namespace llvm - -#endif - diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp index 337eab1..e8bbe21 100644 --- a/lib/CodeGen/MachOWriter.cpp +++ b/lib/CodeGen/MachOWriter.cpp @@ -22,33 +22,31 @@ // //===----------------------------------------------------------------------===// -#include "MachO.h" #include "MachOWriter.h" -#include "MachOCodeEmitter.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/FileWriters.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetMachOWriterInfo.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Mangler.h" -#include "llvm/Support/OutputBuffer.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +using namespace llvm; -namespace llvm { - -/// AddMachOWriter - Concrete function to add the Mach-O writer to the function -/// pass manager. -ObjectCodeEmitter *AddMachOWriter(PassManagerBase &PM, - raw_ostream &O, - TargetMachine &TM) { - MachOWriter *MOW = new MachOWriter(O, TM); - PM.add(MOW); - return MOW->getObjectCodeEmitter(); +namespace llvm { +MachineFunctionPass *createMachOWriter(formatted_raw_ostream &O, + TargetMachine &TM, + const MCAsmInfo *T, + MCCodeEmitter *MCE) { + return new MachOWriter(O, TM, T, MCE); +} } //===----------------------------------------------------------------------===// @@ -57,722 +55,71 @@ ObjectCodeEmitter *AddMachOWriter(PassManagerBase &PM, char MachOWriter::ID = 0; -MachOWriter::MachOWriter(raw_ostream &o, TargetMachine &tm) - : MachineFunctionPass(&ID), O(o), TM(tm) { - is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; - isLittleEndian = TM.getTargetData()->isLittleEndian(); - - MAI = TM.getMCAsmInfo(); - - // Create the machine code emitter object for this target. - MachOCE = new MachOCodeEmitter(*this, *getTextSection(true)); +MachOWriter::MachOWriter(formatted_raw_ostream &o, TargetMachine &tm, + const MCAsmInfo *T, MCCodeEmitter *MCE) + : MachineFunctionPass(&ID), O(o), TM(tm), MAI(T), MCCE(MCE), + OutContext(*new MCContext()), + OutStreamer(*createMachOStreamer(OutContext, O, MCCE)) { } MachOWriter::~MachOWriter() { - delete MachOCE; + delete &OutStreamer; + delete &OutContext; + delete MCCE; } bool MachOWriter::doInitialization(Module &M) { - // Set the magic value, now that we know the pointer size and endianness - Header.setMagic(isLittleEndian, is64Bit); - - // Set the file type - // FIXME: this only works for object files, we do not support the creation - // of dynamic libraries or executables at this time. - Header.filetype = MachOHeader::MH_OBJECT; + // Initialize TargetLoweringObjectFile. + TM.getTargetLowering()->getObjFileLowering().Initialize(OutContext, TM); - Mang = new Mangler(M); - return false; -} - -bool MachOWriter::runOnMachineFunction(MachineFunction &MF) { return false; } /// doFinalization - Now that the module has been completely processed, emit /// the Mach-O file to 'O'. bool MachOWriter::doFinalization(Module &M) { - // FIXME: we don't handle debug info yet, we should probably do that. - // Okay, the.text section has been completed, build the .data, .bss, and - // "common" sections next. - - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) - EmitGlobal(I); - - // Emit the header and load commands. - EmitHeaderAndLoadCommands(); - - // Emit the various sections and their relocation info. - EmitSections(); - EmitRelocations(); - - // Write the symbol table and the string table to the end of the file. - O.write((char*)&SymT[0], SymT.size()); - O.write((char*)&StrT[0], StrT.size()); - - // We are done with the abstract symbols. - SectionList.clear(); - SymbolTable.clear(); - DynamicSymbolTable.clear(); - - // Release the name mangler object. - delete Mang; Mang = 0; + OutStreamer.Finish(); return false; } -// getConstSection - Get constant section for Constant 'C' -MachOSection *MachOWriter::getConstSection(Constant *C) { - const ConstantArray *CVA = dyn_cast<ConstantArray>(C); - if (CVA && CVA->isCString()) - return getSection("__TEXT", "__cstring", - MachOSection::S_CSTRING_LITERALS); - - const Type *Ty = C->getType(); - if (Ty->isPrimitiveType() || Ty->isInteger()) { - unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); - switch(Size) { - default: break; // Fall through to __TEXT,__const - case 4: - return getSection("__TEXT", "__literal4", - MachOSection::S_4BYTE_LITERALS); - case 8: - return getSection("__TEXT", "__literal8", - MachOSection::S_8BYTE_LITERALS); - case 16: - return getSection("__TEXT", "__literal16", - MachOSection::S_16BYTE_LITERALS); - } - } - return getSection("__TEXT", "__const"); -} - -// getJumpTableSection - Select the Jump Table section -MachOSection *MachOWriter::getJumpTableSection() { - if (TM.getRelocationModel() == Reloc::PIC_) - return getTextSection(false); - else - return getSection("__TEXT", "__const"); -} - -// getSection - Return the section with the specified name, creating a new -// section if one does not already exist. -MachOSection *MachOWriter::getSection(const std::string &seg, - const std::string §, - unsigned Flags /* = 0 */ ) { - MachOSection *MOS = SectionLookup[seg+sect]; - if (MOS) return MOS; - - MOS = new MachOSection(seg, sect); - SectionList.push_back(MOS); - MOS->Index = SectionList.size(); - MOS->flags = MachOSection::S_REGULAR | Flags; - SectionLookup[seg+sect] = MOS; - return MOS; -} - -// getTextSection - Return text section with different flags for code/data -MachOSection *MachOWriter::getTextSection(bool isCode /* = true */ ) { - if (isCode) - return getSection("__TEXT", "__text", - MachOSection::S_ATTR_PURE_INSTRUCTIONS | - MachOSection::S_ATTR_SOME_INSTRUCTIONS); - else - return getSection("__TEXT", "__text"); -} - -MachOSection *MachOWriter::getBSSSection() { - return getSection("__DATA", "__bss", MachOSection::S_ZEROFILL); -} - -// GetJTRelocation - Get a relocation a new BB relocation based -// on target information. -MachineRelocation MachOWriter::GetJTRelocation(unsigned Offset, - MachineBasicBlock *MBB) const { - return TM.getMachOWriterInfo()->GetJTRelocation(Offset, MBB); -} - -// GetTargetRelocation - Returns the number of relocations. -unsigned MachOWriter::GetTargetRelocation(MachineRelocation &MR, - unsigned FromIdx, unsigned ToAddr, - unsigned ToIndex, OutputBuffer &RelocOut, - OutputBuffer &SecOut, bool Scattered, - bool Extern) { - return TM.getMachOWriterInfo()->GetTargetRelocation(MR, FromIdx, ToAddr, - ToIndex, RelocOut, - SecOut, Scattered, - Extern); -} - -void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { - const Type *Ty = GV->getType()->getElementType(); - unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); - unsigned Align = TM.getTargetData()->getPreferredAlignment(GV); - - // Reserve space in the .bss section for this symbol while maintaining the - // desired section alignment, which must be at least as much as required by - // this symbol. - OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian); - - if (Align) { - Align = Log2_32(Align); - Sec->align = std::max(unsigned(Sec->align), Align); - - Sec->emitAlignment(Sec->align); - } - // Globals without external linkage apparently do not go in the symbol table. - if (!GV->hasLocalLinkage()) { - MachOSym Sym(GV, Mang->getMangledName(GV), Sec->Index, MAI); - Sym.n_value = Sec->size(); - SymbolTable.push_back(Sym); - } - - // Record the offset of the symbol, and then allocate space for it. - // FIXME: remove when we have unified size + output buffer - - // Now that we know what section the GlovalVariable is going to be emitted - // into, update our mappings. - // FIXME: We may also need to update this when outputting non-GlobalVariable - // GlobalValues such as functions. - - GVSection[GV] = Sec; - GVOffset[GV] = Sec->size(); - - // Allocate space in the section for the global. - for (unsigned i = 0; i < Size; ++i) - SecDataOut.outbyte(0); -} - -void MachOWriter::EmitGlobal(GlobalVariable *GV) { - const Type *Ty = GV->getType()->getElementType(); - unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); - bool NoInit = !GV->hasInitializer(); - - // If this global has a zero initializer, it is part of the .bss or common - // section. - if (NoInit || GV->getInitializer()->isNullValue()) { - // If this global is part of the common block, add it now. Variables are - // part of the common block if they are zero initialized and allowed to be - // merged with other symbols. - if (NoInit || GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() || - GV->hasCommonLinkage()) { - MachOSym ExtOrCommonSym(GV, Mang->getMangledName(GV), - MachOSym::NO_SECT, MAI); - // For undefined (N_UNDF) external (N_EXT) types, n_value is the size in - // bytes of the symbol. - ExtOrCommonSym.n_value = Size; - SymbolTable.push_back(ExtOrCommonSym); - // Remember that we've seen this symbol - GVOffset[GV] = Size; - return; - } - // Otherwise, this symbol is part of the .bss section. - MachOSection *BSS = getBSSSection(); - AddSymbolToSection(BSS, GV); - return; - } - - // Scalar read-only data goes in a literal section if the scalar is 4, 8, or - // 16 bytes, or a cstring. Other read only data goes into a regular const - // section. Read-write data goes in the data section. - MachOSection *Sec = GV->isConstant() ? getConstSection(GV->getInitializer()) : - getDataSection(); - AddSymbolToSection(Sec, GV); - InitMem(GV->getInitializer(), GVOffset[GV], TM.getTargetData(), Sec); -} - - - -void MachOWriter::EmitHeaderAndLoadCommands() { - // Step #0: Fill in the segment load command size, since we need it to figure - // out the rest of the header fields - - MachOSegment SEG("", is64Bit); - SEG.nsects = SectionList.size(); - SEG.cmdsize = SEG.cmdSize(is64Bit) + - SEG.nsects * SectionList[0]->cmdSize(is64Bit); - - // Step #1: calculate the number of load commands. We always have at least - // one, for the LC_SEGMENT load command, plus two for the normal - // and dynamic symbol tables, if there are any symbols. - Header.ncmds = SymbolTable.empty() ? 1 : 3; - - // Step #2: calculate the size of the load commands - Header.sizeofcmds = SEG.cmdsize; - if (!SymbolTable.empty()) - Header.sizeofcmds += SymTab.cmdsize + DySymTab.cmdsize; - - // Step #3: write the header to the file - // Local alias to shortenify coming code. - std::vector<unsigned char> &FH = Header.HeaderData; - OutputBuffer FHOut(FH, is64Bit, isLittleEndian); - - FHOut.outword(Header.magic); - FHOut.outword(TM.getMachOWriterInfo()->getCPUType()); - FHOut.outword(TM.getMachOWriterInfo()->getCPUSubType()); - FHOut.outword(Header.filetype); - FHOut.outword(Header.ncmds); - FHOut.outword(Header.sizeofcmds); - FHOut.outword(Header.flags); - if (is64Bit) - FHOut.outword(Header.reserved); - - // Step #4: Finish filling in the segment load command and write it out - for (std::vector<MachOSection*>::iterator I = SectionList.begin(), - E = SectionList.end(); I != E; ++I) - SEG.filesize += (*I)->size(); - - SEG.vmsize = SEG.filesize; - SEG.fileoff = Header.cmdSize(is64Bit) + Header.sizeofcmds; - - FHOut.outword(SEG.cmd); - FHOut.outword(SEG.cmdsize); - FHOut.outstring(SEG.segname, 16); - FHOut.outaddr(SEG.vmaddr); - FHOut.outaddr(SEG.vmsize); - FHOut.outaddr(SEG.fileoff); - FHOut.outaddr(SEG.filesize); - FHOut.outword(SEG.maxprot); - FHOut.outword(SEG.initprot); - FHOut.outword(SEG.nsects); - FHOut.outword(SEG.flags); - - // Step #5: Finish filling in the fields of the MachOSections - uint64_t currentAddr = 0; - for (std::vector<MachOSection*>::iterator I = SectionList.begin(), - E = SectionList.end(); I != E; ++I) { - MachOSection *MOS = *I; - MOS->addr = currentAddr; - MOS->offset = currentAddr + SEG.fileoff; - // FIXME: do we need to do something with alignment here? - currentAddr += MOS->size(); - } - - // Step #6: Emit the symbol table to temporary buffers, so that we know the - // size of the string table when we write the next load command. This also - // sorts and assigns indices to each of the symbols, which is necessary for - // emitting relocations to externally-defined objects. - BufferSymbolAndStringTable(); - - // Step #7: Calculate the number of relocations for each section and write out - // the section commands for each section - currentAddr += SEG.fileoff; - for (std::vector<MachOSection*>::iterator I = SectionList.begin(), - E = SectionList.end(); I != E; ++I) { - MachOSection *MOS = *I; - - // Convert the relocations to target-specific relocations, and fill in the - // relocation offset for this section. - CalculateRelocations(*MOS); - MOS->reloff = MOS->nreloc ? currentAddr : 0; - currentAddr += MOS->nreloc * 8; - - // write the finalized section command to the output buffer - FHOut.outstring(MOS->sectname, 16); - FHOut.outstring(MOS->segname, 16); - FHOut.outaddr(MOS->addr); - FHOut.outaddr(MOS->size()); - FHOut.outword(MOS->offset); - FHOut.outword(MOS->align); - FHOut.outword(MOS->reloff); - FHOut.outword(MOS->nreloc); - FHOut.outword(MOS->flags); - FHOut.outword(MOS->reserved1); - FHOut.outword(MOS->reserved2); - if (is64Bit) - FHOut.outword(MOS->reserved3); - } - - // Step #8: Emit LC_SYMTAB/LC_DYSYMTAB load commands - SymTab.symoff = currentAddr; - SymTab.nsyms = SymbolTable.size(); - SymTab.stroff = SymTab.symoff + SymT.size(); - SymTab.strsize = StrT.size(); - FHOut.outword(SymTab.cmd); - FHOut.outword(SymTab.cmdsize); - FHOut.outword(SymTab.symoff); - FHOut.outword(SymTab.nsyms); - FHOut.outword(SymTab.stroff); - FHOut.outword(SymTab.strsize); - - // FIXME: set DySymTab fields appropriately - // We should probably just update these in BufferSymbolAndStringTable since - // thats where we're partitioning up the different kinds of symbols. - FHOut.outword(DySymTab.cmd); - FHOut.outword(DySymTab.cmdsize); - FHOut.outword(DySymTab.ilocalsym); - FHOut.outword(DySymTab.nlocalsym); - FHOut.outword(DySymTab.iextdefsym); - FHOut.outword(DySymTab.nextdefsym); - FHOut.outword(DySymTab.iundefsym); - FHOut.outword(DySymTab.nundefsym); - FHOut.outword(DySymTab.tocoff); - FHOut.outword(DySymTab.ntoc); - FHOut.outword(DySymTab.modtaboff); - FHOut.outword(DySymTab.nmodtab); - FHOut.outword(DySymTab.extrefsymoff); - FHOut.outword(DySymTab.nextrefsyms); - FHOut.outword(DySymTab.indirectsymoff); - FHOut.outword(DySymTab.nindirectsyms); - FHOut.outword(DySymTab.extreloff); - FHOut.outword(DySymTab.nextrel); - FHOut.outword(DySymTab.locreloff); - FHOut.outword(DySymTab.nlocrel); - - O.write((char*)&FH[0], FH.size()); -} - -/// EmitSections - Now that we have constructed the file header and load -/// commands, emit the data for each section to the file. -void MachOWriter::EmitSections() { - for (std::vector<MachOSection*>::iterator I = SectionList.begin(), - E = SectionList.end(); I != E; ++I) - // Emit the contents of each section - if ((*I)->size()) - O.write((char*)&(*I)->getData()[0], (*I)->size()); -} - -/// EmitRelocations - emit relocation data from buffer. -void MachOWriter::EmitRelocations() { - for (std::vector<MachOSection*>::iterator I = SectionList.begin(), - E = SectionList.end(); I != E; ++I) - // Emit the relocation entry data for each section. - if ((*I)->RelocBuffer.size()) - O.write((char*)&(*I)->RelocBuffer[0], (*I)->RelocBuffer.size()); -} - -/// BufferSymbolAndStringTable - Sort the symbols we encountered and assign them -/// each a string table index so that they appear in the correct order in the -/// output file. -void MachOWriter::BufferSymbolAndStringTable() { - // The order of the symbol table is: - // 1. local symbols - // 2. defined external symbols (sorted by name) - // 3. undefined external symbols (sorted by name) - - // Before sorting the symbols, check the PendingGlobals for any undefined - // globals that need to be put in the symbol table. - for (std::vector<GlobalValue*>::iterator I = PendingGlobals.begin(), - E = PendingGlobals.end(); I != E; ++I) { - if (GVOffset[*I] == 0 && GVSection[*I] == 0) { - MachOSym UndfSym(*I, Mang->getMangledName(*I), MachOSym::NO_SECT, MAI); - SymbolTable.push_back(UndfSym); - GVOffset[*I] = -1; - } - } - - // Sort the symbols by name, so that when we partition the symbols by scope - // of definition, we won't have to sort by name within each partition. - std::sort(SymbolTable.begin(), SymbolTable.end(), MachOSym::SymCmp()); - - // Parition the symbol table entries so that all local symbols come before - // all symbols with external linkage. { 1 | 2 3 } - std::partition(SymbolTable.begin(), SymbolTable.end(), - MachOSym::PartitionByLocal); - - // Advance iterator to beginning of external symbols and partition so that - // all external symbols defined in this module come before all external - // symbols defined elsewhere. { 1 | 2 | 3 } - for (std::vector<MachOSym>::iterator I = SymbolTable.begin(), - E = SymbolTable.end(); I != E; ++I) { - if (!MachOSym::PartitionByLocal(*I)) { - std::partition(I, E, MachOSym::PartitionByDefined); - break; - } - } - - // Calculate the starting index for each of the local, extern defined, and - // undefined symbols, as well as the number of each to put in the LC_DYSYMTAB - // load command. - for (std::vector<MachOSym>::iterator I = SymbolTable.begin(), - E = SymbolTable.end(); I != E; ++I) { - if (MachOSym::PartitionByLocal(*I)) { - ++DySymTab.nlocalsym; - ++DySymTab.iextdefsym; - ++DySymTab.iundefsym; - } else if (MachOSym::PartitionByDefined(*I)) { - ++DySymTab.nextdefsym; - ++DySymTab.iundefsym; - } else { - ++DySymTab.nundefsym; - } - } - - // Write out a leading zero byte when emitting string table, for n_strx == 0 - // which means an empty string. - OutputBuffer StrTOut(StrT, is64Bit, isLittleEndian); - StrTOut.outbyte(0); - - // The order of the string table is: - // 1. strings for external symbols - // 2. strings for local symbols - // Since this is the opposite order from the symbol table, which we have just - // sorted, we can walk the symbol table backwards to output the string table. - for (std::vector<MachOSym>::reverse_iterator I = SymbolTable.rbegin(), - E = SymbolTable.rend(); I != E; ++I) { - if (I->GVName == "") { - I->n_strx = 0; - } else { - I->n_strx = StrT.size(); - StrTOut.outstring(I->GVName, I->GVName.length()+1); - } - } - - OutputBuffer SymTOut(SymT, is64Bit, isLittleEndian); - - unsigned index = 0; - for (std::vector<MachOSym>::iterator I = SymbolTable.begin(), - E = SymbolTable.end(); I != E; ++I, ++index) { - // Add the section base address to the section offset in the n_value field - // to calculate the full address. - // FIXME: handle symbols where the n_value field is not the address - GlobalValue *GV = const_cast<GlobalValue*>(I->GV); - if (GV && GVSection[GV]) - I->n_value += GVSection[GV]->addr; - if (GV && (GVOffset[GV] == -1)) - GVOffset[GV] = index; - - // Emit nlist to buffer - SymTOut.outword(I->n_strx); - SymTOut.outbyte(I->n_type); - SymTOut.outbyte(I->n_sect); - SymTOut.outhalf(I->n_desc); - SymTOut.outaddr(I->n_value); - } -} - -/// CalculateRelocations - For each MachineRelocation in the current section, -/// calculate the index of the section containing the object to be relocated, -/// and the offset into that section. From this information, create the -/// appropriate target-specific MachORelocation type and add buffer it to be -/// written out after we are finished writing out sections. -void MachOWriter::CalculateRelocations(MachOSection &MOS) { - std::vector<MachineRelocation> Relocations = MOS.getRelocations(); - for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { - MachineRelocation &MR = Relocations[i]; - unsigned TargetSection = MR.getConstantVal(); - unsigned TargetAddr = 0; - unsigned TargetIndex = 0; - - // This is a scattered relocation entry if it points to a global value with - // a non-zero offset. - bool Scattered = false; - bool Extern = false; - - // Since we may not have seen the GlobalValue we were interested in yet at - // the time we emitted the relocation for it, fix it up now so that it - // points to the offset into the correct section. - if (MR.isGlobalValue()) { - GlobalValue *GV = MR.getGlobalValue(); - MachOSection *MOSPtr = GVSection[GV]; - intptr_t Offset = GVOffset[GV]; - - // If we have never seen the global before, it must be to a symbol - // defined in another module (N_UNDF). - if (!MOSPtr) { - // FIXME: need to append stub suffix - Extern = true; - TargetAddr = 0; - TargetIndex = GVOffset[GV]; - } else { - Scattered = TargetSection != 0; - TargetSection = MOSPtr->Index; - } - MR.setResultPointer((void*)Offset); - } - - // If the symbol is locally defined, pass in the address of the section and - // the section index to the code which will generate the target relocation. - if (!Extern) { - MachOSection &To = *SectionList[TargetSection - 1]; - TargetAddr = To.addr; - TargetIndex = To.Index; - } - - OutputBuffer RelocOut(MOS.RelocBuffer, is64Bit, isLittleEndian); - OutputBuffer SecOut(MOS.getData(), is64Bit, isLittleEndian); - - MOS.nreloc += GetTargetRelocation(MR, MOS.Index, TargetAddr, TargetIndex, - RelocOut, SecOut, Scattered, Extern); - } -} - -// InitMem - Write the value of a Constant to the specified memory location, -// converting it into bytes and relocations. -void MachOWriter::InitMem(const Constant *C, uintptr_t Offset, - const TargetData *TD, MachOSection* mos) { - typedef std::pair<const Constant*, intptr_t> CPair; - std::vector<CPair> WorkList; - uint8_t *Addr = &mos->getData()[0]; - - WorkList.push_back(CPair(C,(intptr_t)Addr + Offset)); - - intptr_t ScatteredOffset = 0; - - while (!WorkList.empty()) { - const Constant *PC = WorkList.back().first; - intptr_t PA = WorkList.back().second; - WorkList.pop_back(); - - if (isa<UndefValue>(PC)) { - continue; - } else if (const ConstantVector *CP = dyn_cast<ConstantVector>(PC)) { - unsigned ElementSize = - TD->getTypeAllocSize(CP->getType()->getElementType()); - for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) - WorkList.push_back(CPair(CP->getOperand(i), PA+i*ElementSize)); - } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(PC)) { - // - // FIXME: Handle ConstantExpression. See EE::getConstantValue() - // - switch (CE->getOpcode()) { - case Instruction::GetElementPtr: { - SmallVector<Value*, 8> Indices(CE->op_begin()+1, CE->op_end()); - ScatteredOffset = TD->getIndexedOffset(CE->getOperand(0)->getType(), - &Indices[0], Indices.size()); - WorkList.push_back(CPair(CE->getOperand(0), PA)); - break; - } - case Instruction::Add: - default: - dbgs() << "ConstantExpr not handled as global var init: " << *CE <<"\n"; - llvm_unreachable(0); - } - } else if (PC->getType()->isSingleValueType()) { - unsigned char *ptr = (unsigned char *)PA; - switch (PC->getType()->getTypeID()) { - case Type::IntegerTyID: { - unsigned NumBits = cast<IntegerType>(PC->getType())->getBitWidth(); - uint64_t val = cast<ConstantInt>(PC)->getZExtValue(); - if (NumBits <= 8) - ptr[0] = val; - else if (NumBits <= 16) { - if (TD->isBigEndian()) - val = ByteSwap_16(val); - ptr[0] = val; - ptr[1] = val >> 8; - } else if (NumBits <= 32) { - if (TD->isBigEndian()) - val = ByteSwap_32(val); - ptr[0] = val; - ptr[1] = val >> 8; - ptr[2] = val >> 16; - ptr[3] = val >> 24; - } else if (NumBits <= 64) { - if (TD->isBigEndian()) - val = ByteSwap_64(val); - ptr[0] = val; - ptr[1] = val >> 8; - ptr[2] = val >> 16; - ptr[3] = val >> 24; - ptr[4] = val >> 32; - ptr[5] = val >> 40; - ptr[6] = val >> 48; - ptr[7] = val >> 56; - } else { - llvm_unreachable("Not implemented: bit widths > 64"); +bool MachOWriter::runOnMachineFunction(MachineFunction &MF) { + const Function *F = MF.getFunction(); + TargetLoweringObjectFile &TLOF = TM.getTargetLowering()->getObjFileLowering(); + const MCSection *S = TLOF.SectionForGlobal(F, Mang, TM); + OutStreamer.SwitchSection(S); + + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block. + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MI = II; + MCInst OutMI; + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + MCOperand MCOp; + + switch (MO.getType()) { + default: + MI->dump(); + llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) continue; + MCOp = MCOperand::CreateReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::CreateImm(MO.getImm()); + break; } - break; - } - case Type::FloatTyID: { - uint32_t val = cast<ConstantFP>(PC)->getValueAPF().bitcastToAPInt(). - getZExtValue(); - if (TD->isBigEndian()) - val = ByteSwap_32(val); - ptr[0] = val; - ptr[1] = val >> 8; - ptr[2] = val >> 16; - ptr[3] = val >> 24; - break; - } - case Type::DoubleTyID: { - uint64_t val = cast<ConstantFP>(PC)->getValueAPF().bitcastToAPInt(). - getZExtValue(); - if (TD->isBigEndian()) - val = ByteSwap_64(val); - ptr[0] = val; - ptr[1] = val >> 8; - ptr[2] = val >> 16; - ptr[3] = val >> 24; - ptr[4] = val >> 32; - ptr[5] = val >> 40; - ptr[6] = val >> 48; - ptr[7] = val >> 56; - break; - } - case Type::PointerTyID: - if (isa<ConstantPointerNull>(PC)) - memset(ptr, 0, TD->getPointerSize()); - else if (const GlobalValue* GV = dyn_cast<GlobalValue>(PC)) { - // FIXME: what about function stubs? - mos->addRelocation(MachineRelocation::getGV(PA-(intptr_t)Addr, - MachineRelocation::VANILLA, - const_cast<GlobalValue*>(GV), - ScatteredOffset)); - ScatteredOffset = 0; - } else - llvm_unreachable("Unknown constant pointer type!"); - break; - default: - std::string msg; - raw_string_ostream Msg(msg); - Msg << "ERROR: Constant unimp for type: " << *PC->getType(); - llvm_report_error(Msg.str()); + OutMI.addOperand(MCOp); } - } else if (isa<ConstantAggregateZero>(PC)) { - memset((void*)PA, 0, (size_t)TD->getTypeAllocSize(PC->getType())); - } else if (const ConstantArray *CPA = dyn_cast<ConstantArray>(PC)) { - unsigned ElementSize = - TD->getTypeAllocSize(CPA->getType()->getElementType()); - for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i) - WorkList.push_back(CPair(CPA->getOperand(i), PA+i*ElementSize)); - } else if (const ConstantStruct *CPS = dyn_cast<ConstantStruct>(PC)) { - const StructLayout *SL = - TD->getStructLayout(cast<StructType>(CPS->getType())); - for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i) - WorkList.push_back(CPair(CPS->getOperand(i), - PA+SL->getElementOffset(i))); - } else { - dbgs() << "Bad Type: " << *PC->getType() << "\n"; - llvm_unreachable("Unknown constant type to initialize memory with!"); + + OutStreamer.EmitInstruction(OutMI); } } -} - -//===----------------------------------------------------------------------===// -// MachOSym Implementation -//===----------------------------------------------------------------------===// -MachOSym::MachOSym(const GlobalValue *gv, std::string name, uint8_t sect, - const MCAsmInfo *MAI) : - GV(gv), n_strx(0), n_type(sect == NO_SECT ? N_UNDF : N_SECT), n_sect(sect), - n_desc(0), n_value(0) { - - // FIXME: This is completely broken, it should use the mangler interface. - switch (GV->getLinkage()) { - default: - llvm_unreachable("Unexpected linkage type!"); - break; - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::CommonLinkage: - assert(!isa<Function>(gv) && "Unexpected linkage type for Function!"); - case GlobalValue::ExternalLinkage: - GVName = MAI->getGlobalPrefix() + name; - n_type |= GV->hasHiddenVisibility() ? N_PEXT : N_EXT; - break; - case GlobalValue::PrivateLinkage: - GVName = MAI->getPrivateGlobalPrefix() + name; - break; - case GlobalValue::LinkerPrivateLinkage: - GVName = MAI->getLinkerPrivateGlobalPrefix() + name; - break; - case GlobalValue::InternalLinkage: - GVName = MAI->getGlobalPrefix() + name; - break; - } + return false; } - -} // end namespace llvm diff --git a/lib/CodeGen/MachOWriter.h b/lib/CodeGen/MachOWriter.h index 9273f38..2e7e67d 100644 --- a/lib/CodeGen/MachOWriter.h +++ b/lib/CodeGen/MachOWriter.h @@ -15,191 +15,73 @@ #define MACHOWRITER_H #include "llvm/CodeGen/MachineFunctionPass.h" -#include <vector> -#include <map> +#include "llvm/Target/TargetMachine.h" namespace llvm { - class Constant; class GlobalVariable; class Mangler; - class MachineBasicBlock; - class MachineRelocation; - class MachOCodeEmitter; - struct MachODySymTab; - struct MachOHeader; - struct MachOSection; - struct MachOSym; - class TargetData; - class TargetMachine; - class MCAsmInfo; - class ObjectCodeEmitter; - class OutputBuffer; - class raw_ostream; - + class MCCodeEmitter; + class MCContext; + class MCStreamer; + /// MachOWriter - This class implements the common target-independent code for /// writing Mach-O files. Targets should derive a class from this to /// parameterize the output format. /// class MachOWriter : public MachineFunctionPass { - friend class MachOCodeEmitter; - public: static char ID; - ObjectCodeEmitter *getObjectCodeEmitter() { - return reinterpret_cast<ObjectCodeEmitter*>(MachOCE); - } - - MachOWriter(raw_ostream &O, TargetMachine &TM); - virtual ~MachOWriter(); - - virtual const char *getPassName() const { - return "Mach-O Writer"; - } - protected: /// Output stream to send the resultant object file to. /// - raw_ostream &O; + formatted_raw_ostream &O; /// Target machine description. /// TargetMachine &TM; - /// Mang - The object used to perform name mangling for this module. + /// Target Asm Printer information. /// - Mangler *Mang; - - /// MachOCE - The MachineCodeEmitter object that we are exposing to emit - /// machine code for functions to the .o file. - MachOCodeEmitter *MachOCE; - - /// is64Bit/isLittleEndian - This information is inferred from the target - /// machine directly, indicating what header values and flags to set. - bool is64Bit, isLittleEndian; - - // Target Asm Info const MCAsmInfo *MAI; - - /// Header - An instance of MachOHeader that we will update while we build - /// the file, and then emit during finalization. - MachOHeader Header; - + + /// MCCE - The MCCodeEmitter object that we are exposing to emit machine + /// code for functions to the .o file. + MCCodeEmitter *MCCE; + + /// OutContext - This is the context for the output file that we are + /// streaming. This owns all of the global MC-related objects for the + /// generated translation unit. + MCContext &OutContext; + + /// OutStreamer - This is the MCStreamer object for the file we are + /// generating. This contains the transient state for the current + /// translation unit that we are generating (such as the current section + /// etc). + MCStreamer &OutStreamer; + + /// Name-mangler for global names. + /// + Mangler *Mang; + /// doInitialization - Emit the file header and all of the global variables /// for the module to the Mach-O file. bool doInitialization(Module &M); - bool runOnMachineFunction(MachineFunction &MF); - /// doFinalization - Now that the module has been completely processed, emit /// the Mach-O file to 'O'. bool doFinalization(Module &M); - private: - - /// SectionList - This is the list of sections that we have emitted to the - /// file. Once the file has been completely built, the segment load command - /// SectionCommands are constructed from this info. - std::vector<MachOSection*> SectionList; - - /// SectionLookup - This is a mapping from section name to SectionList entry - std::map<std::string, MachOSection*> SectionLookup; - - /// GVSection - This is a mapping from a GlobalValue to a MachOSection, - /// to aid in emitting relocations. - std::map<GlobalValue*, MachOSection*> GVSection; - - /// GVOffset - This is a mapping from a GlobalValue to an offset from the - /// start of the section in which the GV resides, to aid in emitting - /// relocations. - std::map<GlobalValue*, intptr_t> GVOffset; - - /// getSection - Return the section with the specified name, creating a new - /// section if one does not already exist. - MachOSection *getSection(const std::string &seg, const std::string §, - unsigned Flags = 0); - - /// getTextSection - Return text section with different flags for code/data - MachOSection *getTextSection(bool isCode = true); - - MachOSection *getDataSection() { - return getSection("__DATA", "__data"); + bool runOnMachineFunction(MachineFunction &MF); + + public: + explicit MachOWriter(formatted_raw_ostream &O, TargetMachine &TM, + const MCAsmInfo *T, MCCodeEmitter *MCE); + + virtual ~MachOWriter(); + + virtual const char *getPassName() const { + return "Mach-O Writer"; } - - MachOSection *getBSSSection(); - MachOSection *getConstSection(Constant *C); - MachOSection *getJumpTableSection(); - - /// MachOSymTab - This struct contains information about the offsets and - /// size of symbol table information. - /// segment. - struct MachOSymTab { - uint32_t cmd; // LC_SYMTAB - uint32_t cmdsize; // sizeof( MachOSymTab ) - uint32_t symoff; // symbol table offset - uint32_t nsyms; // number of symbol table entries - uint32_t stroff; // string table offset - uint32_t strsize; // string table size in bytes - - // Constants for the cmd field - // see <mach-o/loader.h> - enum { LC_SYMTAB = 0x02 // link-edit stab symbol table info - }; - - MachOSymTab() : cmd(LC_SYMTAB), cmdsize(6 * sizeof(uint32_t)), symoff(0), - nsyms(0), stroff(0), strsize(0) { } - }; - - /// SymTab - The "stab" style symbol table information - MachOSymTab SymTab; - /// DySymTab - symbol table info for the dynamic link editor - MachODySymTab DySymTab; - - protected: - - /// SymbolTable - This is the list of symbols we have emitted to the file. - /// This actually gets rearranged before emission to the file (to put the - /// local symbols first in the list). - std::vector<MachOSym> SymbolTable; - - /// SymT - A buffer to hold the symbol table before we write it out at the - /// appropriate location in the file. - std::vector<unsigned char> SymT; - - /// StrT - A buffer to hold the string table before we write it out at the - /// appropriate location in the file. - std::vector<unsigned char> StrT; - - /// PendingSyms - This is a list of externally defined symbols that we have - /// been asked to emit, but have not seen a reference to. When a reference - /// is seen, the symbol will move from this list to the SymbolTable. - std::vector<GlobalValue*> PendingGlobals; - - /// DynamicSymbolTable - This is just a vector of indices into - /// SymbolTable to aid in emitting the DYSYMTAB load command. - std::vector<unsigned> DynamicSymbolTable; - - static void InitMem(const Constant *C, uintptr_t Offset, - const TargetData *TD, MachOSection* mos); - - private: - void AddSymbolToSection(MachOSection *MOS, GlobalVariable *GV); - void EmitGlobal(GlobalVariable *GV); - void EmitHeaderAndLoadCommands(); - void EmitSections(); - void EmitRelocations(); - void BufferSymbolAndStringTable(); - void CalculateRelocations(MachOSection &MOS); - - // GetJTRelocation - Get a relocation a new BB relocation based - // on target information. - MachineRelocation GetJTRelocation(unsigned Offset, - MachineBasicBlock *MBB) const; - - /// GetTargetRelocation - Returns the number of relocations. - unsigned GetTargetRelocation(MachineRelocation &MR, unsigned FromIdx, - unsigned ToAddr, unsigned ToIndex, - OutputBuffer &RelocOut, OutputBuffer &SecOut, - bool Scattered, bool Extern); }; } diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index e2ce642..9215bd5 100644 --- a/lib/CodeGen/MachineBasicBlock.cpp +++ b/lib/CodeGen/MachineBasicBlock.cpp @@ -378,7 +378,7 @@ bool MachineBasicBlock::canFallThrough() { MachineBasicBlock *TBB = 0, *FBB = 0; SmallVector<MachineOperand, 4> Cond; const TargetInstrInfo *TII = getParent()->getTarget().getInstrInfo(); - if (TII->AnalyzeBranch(*this, TBB, FBB, Cond, true)) { + if (TII->AnalyzeBranch(*this, TBB, FBB, Cond)) { // If we couldn't analyze the branch, examine the last instruction. // If the block doesn't end in a known control barrier, assume fallthrough // is possible. The isPredicable check is needed because this code can be @@ -524,7 +524,26 @@ bool MachineBasicBlock::CorrectExtraCFGEdges(MachineBasicBlock *DestA, return MadeChange; } +/// findDebugLoc - find the next valid DebugLoc starting at MBBI, skipping +/// any DEBUG_VALUE instructions. Return UnknownLoc if there is none. +DebugLoc +MachineBasicBlock::findDebugLoc(MachineBasicBlock::iterator &MBBI) { + DebugLoc DL; + MachineBasicBlock::iterator E = end(); + if (MBBI != E) { + // Skip debug declarations, we don't want a DebugLoc from them. + MachineBasicBlock::iterator MBBI2 = MBBI; + while (MBBI2 != E && + MBBI2->getOpcode()==TargetInstrInfo::DEBUG_VALUE) + MBBI2++; + if (MBBI2 != E) + DL = MBBI2->getDebugLoc(); + } + return DL; +} + void llvm::WriteAsOperand(raw_ostream &OS, const MachineBasicBlock *MBB, bool t) { OS << "BB#" << MBB->getNumber(); } + diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index ae9451c..1e3e314 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -26,6 +26,7 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLowering.h" @@ -426,12 +427,12 @@ unsigned MachineFunction::addLiveIn(unsigned PReg, return VReg; } -/// getDebugLocTuple - Get the DebugLocTuple for a given DebugLoc object. -DebugLocTuple MachineFunction::getDebugLocTuple(DebugLoc DL) const { +/// getDILocation - Get the DILocation for a given DebugLoc object. +DILocation MachineFunction::getDILocation(DebugLoc DL) const { unsigned Idx = DL.getIndex(); assert(Idx < DebugLocInfo.DebugLocations.size() && "Invalid index into debug locations!"); - return DebugLocInfo.DebugLocations[Idx]; + return DILocation(DebugLocInfo.DebugLocations[Idx]); } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index cf3e3e1..ef2fcee 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -1162,6 +1162,13 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { if (FirstOp) FirstOp = false; else OS << ","; OS << " "; + if (i < getDesc().NumOperands) { + const TargetOperandInfo &TOI = getDesc().OpInfo[i]; + if (TOI.isPredicate()) + OS << "pred:"; + if (TOI.isOptionalDef()) + OS << "opt:"; + } MO.print(OS, TM); } @@ -1189,17 +1196,17 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { // TODO: print InlinedAtLoc information - DebugLocTuple DLT = MF->getDebugLocTuple(debugLoc); - DIScope Scope(DLT.Scope); + DILocation DLT = MF->getDILocation(debugLoc); + DIScope Scope = DLT.getScope(); OS << " dbg:"; // Omit the directory, since it's usually long and uninteresting. if (!Scope.isNull()) OS << Scope.getFilename(); else OS << "<unknown>"; - OS << ':' << DLT.Line; - if (DLT.Col != 0) - OS << ':' << DLT.Col; + OS << ':' << DLT.getLineNumber(); + if (DLT.getColumnNumber() != 0) + OS << ':' << DLT.getColumnNumber(); } OS << "\n"; diff --git a/lib/CodeGen/Makefile b/lib/CodeGen/Makefile index 4ab3e3c..8c0204c 100644 --- a/lib/CodeGen/Makefile +++ b/lib/CodeGen/Makefile @@ -11,6 +11,7 @@ LEVEL = ../.. LIBRARYNAME = LLVMCodeGen PARALLEL_DIRS = SelectionDAG AsmPrinter BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/CodeGen/MaxStackAlignment.cpp b/lib/CodeGen/MaxStackAlignment.cpp deleted file mode 100644 index d327cfa..0000000 --- a/lib/CodeGen/MaxStackAlignment.cpp +++ /dev/null @@ -1,70 +0,0 @@ -//===-- MaxStackAlignment.cpp - Compute the required stack alignment -- ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass looks for vector register usage and aligned local objects to -// calculate the maximum required alignment for a function. This is used by -// targets which support it to determine if dynamic stack realignment is -// necessary. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" - -using namespace llvm; - -namespace { - struct MaximalStackAlignmentCalculator : public MachineFunctionPass { - static char ID; - MaximalStackAlignmentCalculator() : MachineFunctionPass(&ID) {} - - virtual bool runOnMachineFunction(MachineFunction &MF) { - MachineFrameInfo *FFI = MF.getFrameInfo(); - MachineRegisterInfo &RI = MF.getRegInfo(); - - // Calculate max stack alignment of all already allocated stack objects. - FFI->calculateMaxStackAlignment(); - unsigned MaxAlign = FFI->getMaxAlignment(); - - // Be over-conservative: scan over all vreg defs and find whether vector - // registers are used. If yes, there is probability that vector registers - // will be spilled and thus the stack needs to be aligned properly. - // FIXME: It would be better to only do this if a spill actually - // happens rather than conseratively aligning the stack regardless. - for (unsigned RegNum = TargetRegisterInfo::FirstVirtualRegister; - RegNum < RI.getLastVirtReg(); ++RegNum) - MaxAlign = std::max(MaxAlign, RI.getRegClass(RegNum)->getAlignment()); - - if (FFI->getMaxAlignment() == MaxAlign) - return false; - - FFI->setMaxAlignment(MaxAlign); - return true; - } - - virtual const char *getPassName() const { - return "Stack Alignment Requirements Auto-Detector"; - } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - MachineFunctionPass::getAnalysisUsage(AU); - } - }; - - char MaximalStackAlignmentCalculator::ID = 0; -} - -FunctionPass* -llvm::createMaxStackAlignmentCalculatorPass() { - return new MaximalStackAlignmentCalculator(); -} - diff --git a/lib/CodeGen/OptimizeExts.cpp b/lib/CodeGen/OptimizeExts.cpp index 625ff89..096f9d4 100644 --- a/lib/CodeGen/OptimizeExts.cpp +++ b/lib/CodeGen/OptimizeExts.cpp @@ -143,11 +143,23 @@ bool OptimizeExts::OptimizeInstr(MachineInstr *MI, MachineBasicBlock *MBB, // Now replace all uses. if (!Uses.empty()) { + SmallPtrSet<MachineBasicBlock*, 4> PHIBBs; + // Look for PHI uses of the extended result, we don't want to extend the + // liveness of a PHI input. It breaks all kinds of assumptions down + // stream. A PHI use is expected to be the kill of its source values. + UI = MRI->use_begin(DstReg); + for (MachineRegisterInfo::use_iterator UE = MRI->use_end(); UI != UE; + ++UI) + if (UI->getOpcode() == TargetInstrInfo::PHI) + PHIBBs.insert(UI->getParent()); + const TargetRegisterClass *RC = MRI->getRegClass(SrcReg); for (unsigned i = 0, e = Uses.size(); i != e; ++i) { MachineOperand *UseMO = Uses[i]; MachineInstr *UseMI = UseMO->getParent(); MachineBasicBlock *UseMBB = UseMI->getParent(); + if (PHIBBs.count(UseMBB)) + continue; unsigned NewVR = MRI->createVirtualRegister(RC); BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(), TII->get(TargetInstrInfo::EXTRACT_SUBREG), NewVR) diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 549527c..8883064 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1088,6 +1088,26 @@ SDValue DAGCombiner::visitADD(SDNode *N) { if (Result.getNode()) return Result; } + // fold (add x, shl(0 - y, n)) -> sub(x, shl(y, n)) + if (N1.getOpcode() == ISD::SHL && + N1.getOperand(0).getOpcode() == ISD::SUB) + if (ConstantSDNode *C = + dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(0))) + if (C->getAPIntValue() == 0) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0, + DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, + N1.getOperand(0).getOperand(1), + N1.getOperand(1))); + if (N0.getOpcode() == ISD::SHL && + N0.getOperand(0).getOpcode() == ISD::SUB) + if (ConstantSDNode *C = + dyn_cast<ConstantSDNode>(N0.getOperand(0).getOperand(0))) + if (C->getAPIntValue() == 0) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N1, + DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, + N0.getOperand(0).getOperand(1), + N0.getOperand(1))); + return SDValue(); } @@ -1176,6 +1196,9 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { if (N1C) return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0, DAG.getConstant(-N1C->getAPIntValue(), VT)); + // Canonicalize (sub -1, x) -> ~x, i.e. (xor x, -1) + if (N0C && N0C->isAllOnesValue()) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N1, N0); // fold (A+B)-A -> B if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1) return N0.getOperand(1); diff --git a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 4868c9e..dc7d82d 100644 --- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -35,7 +35,6 @@ #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 669d414..9c50936 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -24,7 +24,6 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" diff --git a/lib/CodeGen/SelectionDAG/Makefile b/lib/CodeGen/SelectionDAG/Makefile index 73f0b5d..4706e68 100644 --- a/lib/CodeGen/SelectionDAG/Makefile +++ b/lib/CodeGen/SelectionDAG/Makefile @@ -6,8 +6,9 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMSelectionDAG -PARALLEL_DIRS = +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp index 0c3c974c..ad8630a 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp @@ -22,7 +22,6 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index 1ad7919..dea5993 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -46,6 +46,11 @@ static RegisterScheduler tdrListrDAGScheduler("list-tdrr", "Top-down register reduction list scheduling", createTDRRListDAGScheduler); +static RegisterScheduler + sourceListDAGScheduler("source", + "Similar to list-burr but schedules in source " + "order when possible", + createSourceListDAGScheduler); namespace { //===----------------------------------------------------------------------===// @@ -931,6 +936,16 @@ namespace { bool operator()(const SUnit* left, const SUnit* right) const; }; + + struct src_ls_rr_sort : public std::binary_function<SUnit*, SUnit*, bool> { + RegReductionPriorityQueue<src_ls_rr_sort> *SPQ; + src_ls_rr_sort(RegReductionPriorityQueue<src_ls_rr_sort> *spq) + : SPQ(spq) {} + src_ls_rr_sort(const src_ls_rr_sort &RHS) + : SPQ(RHS.SPQ) {} + + bool operator()(const SUnit* left, const SUnit* right) const; + }; } // end anonymous namespace /// CalcNodeSethiUllmanNumber - Compute Sethi Ullman number. @@ -981,9 +996,9 @@ namespace { public: RegReductionPriorityQueue(const TargetInstrInfo *tii, - const TargetRegisterInfo *tri) : - Queue(SF(this)), currentQueueId(0), - TII(tii), TRI(tri), scheduleDAG(NULL) {} + const TargetRegisterInfo *tri) + : Queue(SF(this)), currentQueueId(0), + TII(tii), TRI(tri), scheduleDAG(NULL) {} void initNodes(std::vector<SUnit> &sunits) { SUnits = &sunits; @@ -1089,6 +1104,9 @@ namespace { typedef RegReductionPriorityQueue<td_ls_rr_sort> TDRegReductionPriorityQueue; + + typedef RegReductionPriorityQueue<src_ls_rr_sort> + SrcRegReductionPriorityQueue; } /// closestSucc - Returns the scheduled cycle of the successor which is @@ -1122,16 +1140,9 @@ static unsigned calcMaxScratches(const SUnit *SU) { return Scratches; } -// Bottom up -bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const { - unsigned LOrder = SPQ->getNodeOrdering(left); - unsigned ROrder = SPQ->getNodeOrdering(right); - - // Prefer an ordering where the lower the non-zero order number, the higher - // the preference. - if ((LOrder || ROrder) && LOrder != ROrder) - return LOrder != 0 && (LOrder < ROrder || ROrder == 0); - +template <typename RRSort> +static bool BURRSort(const SUnit *left, const SUnit *right, + const RegReductionPriorityQueue<RRSort> *SPQ) { unsigned LPriority = SPQ->getNodePriority(left); unsigned RPriority = SPQ->getNodePriority(right); if (LPriority != RPriority) @@ -1176,6 +1187,24 @@ bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const { return (left->NodeQueueId > right->NodeQueueId); } +// Bottom up +bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const { + return BURRSort(left, right, SPQ); +} + +// Source order, otherwise bottom up. +bool src_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const{ + unsigned LOrder = SPQ->getNodeOrdering(left); + unsigned ROrder = SPQ->getNodeOrdering(right); + + // Prefer an ordering where the lower the non-zero order number, the higher + // the preference. + if ((LOrder || ROrder) && LOrder != ROrder) + return LOrder != 0 && (LOrder < ROrder || ROrder == 0); + + return BURRSort(left, right, SPQ); +} + template<class SF> bool RegReductionPriorityQueue<SF>::canClobber(const SUnit *SU, const SUnit *Op) { @@ -1196,7 +1225,6 @@ RegReductionPriorityQueue<SF>::canClobber(const SUnit *SU, const SUnit *Op) { return false; } - /// hasCopyToRegUse - Return true if SU has a value successor that is a /// CopyToReg node. static bool hasCopyToRegUse(const SUnit *SU) { @@ -1544,3 +1572,17 @@ llvm::createTDRRListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) { PQ->setScheduleDAG(SD); return SD; } + +llvm::ScheduleDAGSDNodes * +llvm::createSourceListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) { + const TargetMachine &TM = IS->TM; + const TargetInstrInfo *TII = TM.getInstrInfo(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + + SrcRegReductionPriorityQueue *PQ = new SrcRegReductionPriorityQueue(TII, TRI); + + ScheduleDAGRRList *SD = + new ScheduleDAGRRList(*IS->MF, true, PQ); + PQ->setScheduleDAG(SD); + return SD; +} diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index aaaa2b3..b51c61b 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -20,10 +20,16 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtarget.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; +STATISTIC(LoadsClustered, "Number of loads clustered together"); + ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf) : ScheduleDAG(mf) { } @@ -75,6 +81,122 @@ static void CheckForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op, } } +static void AddFlags(SDNode *N, SDValue Flag, bool AddFlag, + SelectionDAG *DAG) { + SmallVector<EVT, 4> VTs; + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) + VTs.push_back(N->getValueType(i)); + if (AddFlag) + VTs.push_back(MVT::Flag); + SmallVector<SDValue, 4> Ops; + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + Ops.push_back(N->getOperand(i)); + if (Flag.getNode()) + Ops.push_back(Flag); + SDVTList VTList = DAG->getVTList(&VTs[0], VTs.size()); + DAG->MorphNodeTo(N, N->getOpcode(), VTList, &Ops[0], Ops.size()); +} + +/// ClusterNeighboringLoads - Force nearby loads together by "flagging" them. +/// This function finds loads of the same base and different offsets. If the +/// offsets are not far apart (target specific), it add MVT::Flag inputs and +/// outputs to ensure they are scheduled together and in order. This +/// optimization may benefit some targets by improving cache locality. +void ScheduleDAGSDNodes::ClusterNeighboringLoads() { + SmallPtrSet<SDNode*, 16> Visited; + SmallVector<int64_t, 4> Offsets; + DenseMap<long long, SDNode*> O2SMap; // Map from offset to SDNode. + for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(), + E = DAG->allnodes_end(); NI != E; ++NI) { + SDNode *Node = &*NI; + if (!Node || !Node->isMachineOpcode()) + continue; + + unsigned Opc = Node->getMachineOpcode(); + const TargetInstrDesc &TID = TII->get(Opc); + if (!TID.mayLoad()) + continue; + + SDNode *Chain = 0; + unsigned NumOps = Node->getNumOperands(); + if (Node->getOperand(NumOps-1).getValueType() == MVT::Other) + Chain = Node->getOperand(NumOps-1).getNode(); + if (!Chain) + continue; + + // Look for other loads of the same chain. Find loads that are loading from + // the same base pointer and different offsets. + Visited.clear(); + Offsets.clear(); + O2SMap.clear(); + bool Cluster = false; + SDNode *Base = Node; + int64_t BaseOffset; + for (SDNode::use_iterator I = Chain->use_begin(), E = Chain->use_end(); + I != E; ++I) { + SDNode *User = *I; + if (User == Node || !Visited.insert(User)) + continue; + int64_t Offset1, Offset2; + if (!TII->areLoadsFromSameBasePtr(Base, User, Offset1, Offset2) || + Offset1 == Offset2) + // FIXME: Should be ok if they addresses are identical. But earlier + // optimizations really should have eliminated one of the loads. + continue; + if (O2SMap.insert(std::make_pair(Offset1, Base)).second) + Offsets.push_back(Offset1); + O2SMap.insert(std::make_pair(Offset2, User)); + Offsets.push_back(Offset2); + if (Offset2 < Offset1) { + Base = User; + BaseOffset = Offset2; + } else { + BaseOffset = Offset1; + } + Cluster = true; + } + + if (!Cluster) + continue; + + // Sort them in increasing order. + std::sort(Offsets.begin(), Offsets.end()); + + // Check if the loads are close enough. + SmallVector<SDNode*, 4> Loads; + unsigned NumLoads = 0; + int64_t BaseOff = Offsets[0]; + SDNode *BaseLoad = O2SMap[BaseOff]; + Loads.push_back(BaseLoad); + for (unsigned i = 1, e = Offsets.size(); i != e; ++i) { + int64_t Offset = Offsets[i]; + SDNode *Load = O2SMap[Offset]; + if (!TII->shouldScheduleLoadsNear(BaseLoad, Load, BaseOff, Offset, + NumLoads)) + break; // Stop right here. Ignore loads that are further away. + Loads.push_back(Load); + ++NumLoads; + } + + if (NumLoads == 0) + continue; + + // Cluster loads by adding MVT::Flag outputs and inputs. This also + // ensure they are scheduled in order of increasing addresses. + SDNode *Lead = Loads[0]; + AddFlags(Lead, SDValue(0,0), true, DAG); + SDValue InFlag = SDValue(Lead, Lead->getNumValues()-1); + for (unsigned i = 1, e = Loads.size(); i != e; ++i) { + bool OutFlag = i < e-1; + SDNode *Load = Loads[i]; + AddFlags(Load, InFlag, OutFlag, DAG); + if (OutFlag) + InFlag = SDValue(Load, Load->getNumValues()-1); + ++LoadsClustered; + } + } +} + void ScheduleDAGSDNodes::BuildSchedUnits() { // During scheduling, the NodeId field of SDNode is used to map SDNodes // to their associated SUnits by holding SUnits table indices. A value @@ -232,6 +354,8 @@ void ScheduleDAGSDNodes::AddSchedEdges() { /// excludes nodes that aren't interesting to scheduling, and represents /// flagged together nodes with a single SUnit. void ScheduleDAGSDNodes::BuildSchedGraph(AliasAnalysis *AA) { + // Cluster loads from "near" addresses into combined SUnits. + ClusterNeighboringLoads(); // Populate the SUnits array. BuildSchedUnits(); // Compute all the scheduling dependencies between nodes. diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h index ebb31ac..6b829b6 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h @@ -108,6 +108,10 @@ namespace llvm { virtual void getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const; private: + /// ClusterNeighboringLoads - Cluster loads from "near" addresses into + /// combined SUnits. + void ClusterNeighboringLoads(); + /// BuildSchedUnits, AddSchedEdges - Helper functions for BuildSchedGraph. void BuildSchedUnits(); void AddSchedEdges(); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index cb1a0d6..f1b6f1e 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -593,7 +593,7 @@ void SelectionDAG::DeallocateNode(SDNode *N) { NodeAllocator.Deallocate(AllNodes.remove(N)); // Remove the ordering of this node. - if (Ordering) Ordering->remove(N); + Ordering->remove(N); } /// RemoveNodeFromCSEMaps - Take the specified node out of the CSE map that @@ -790,8 +790,7 @@ SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli) getVTList(MVT::Other)), Root(getEntryNode()), Ordering(0) { AllNodes.push_back(&EntryNode); - if (DisableScheduling) - Ordering = new SDNodeOrdering(); + Ordering = new SDNodeOrdering(); } void SelectionDAG::init(MachineFunction &mf, MachineModuleInfo *mmi, @@ -830,8 +829,7 @@ void SelectionDAG::clear() { EntryNode.UseList = 0; AllNodes.push_back(&EntryNode); Root = getEntryNode(); - if (DisableScheduling) - Ordering = new SDNodeOrdering(); + Ordering = new SDNodeOrdering(); } SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) { @@ -5172,6 +5170,7 @@ unsigned SelectionDAG::AssignTopologicalOrder() { // count of outstanding operands. for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ) { SDNode *N = I++; + checkForCycles(N); unsigned Degree = N->getNumOperands(); if (Degree == 0) { // A node with no uses, add it to the result array immediately. @@ -5179,6 +5178,7 @@ unsigned SelectionDAG::AssignTopologicalOrder() { allnodes_iterator Q = N; if (Q != SortedPos) SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(Q)); + assert(SortedPos != AllNodes.end() && "Overran node list"); ++SortedPos; } else { // Temporarily use the Node Id as scratch space for the degree count. @@ -5190,22 +5190,34 @@ unsigned SelectionDAG::AssignTopologicalOrder() { // such that by the time the end is reached all nodes will be sorted. for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ++I) { SDNode *N = I; + checkForCycles(N); + // N is in sorted position, so all its uses have one less operand + // that needs to be sorted. for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); UI != UE; ++UI) { SDNode *P = *UI; unsigned Degree = P->getNodeId(); + assert(Degree != 0 && "Invalid node degree"); --Degree; if (Degree == 0) { // All of P's operands are sorted, so P may sorted now. P->setNodeId(DAGSize++); if (P != SortedPos) SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(P)); + assert(SortedPos != AllNodes.end() && "Overran node list"); ++SortedPos; } else { // Update P's outstanding operand count. P->setNodeId(Degree); } } + if (I == SortedPos) { + allnodes_iterator J = I; + SDNode *S = ++J; + dbgs() << "Offending node:\n"; + S->dumprFull(); + assert(0 && "Overran sorted position"); + } } assert(SortedPos == AllNodes.end() && @@ -5227,14 +5239,13 @@ unsigned SelectionDAG::AssignTopologicalOrder() { /// AssignOrdering - Assign an order to the SDNode. void SelectionDAG::AssignOrdering(SDNode *SD, unsigned Order) { assert(SD && "Trying to assign an order to a null node!"); - if (Ordering) - Ordering->add(SD, Order); + Ordering->add(SD, Order); } /// GetOrdering - Get the order for the SDNode. unsigned SelectionDAG::GetOrdering(const SDNode *SD) const { assert(SD && "Trying to get the order of a null node!"); - return Ordering ? Ordering->getOrder(SD) : 0; + return Ordering->getOrder(SD); } @@ -5893,6 +5904,45 @@ void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const { print_details(OS, G); } +static void printrWithDepthHelper(raw_ostream &OS, const SDNode *N, + const SelectionDAG *G, unsigned depth, + unsigned indent) +{ + if (depth == 0) + return; + + OS.indent(indent); + + N->print(OS, G); + + if (depth < 1) + return; + + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + OS << '\n'; + printrWithDepthHelper(OS, N->getOperand(i).getNode(), G, depth-1, indent+2); + } +} + +void SDNode::printrWithDepth(raw_ostream &OS, const SelectionDAG *G, + unsigned depth) const { + printrWithDepthHelper(OS, this, G, depth, 0); +} + +void SDNode::printrFull(raw_ostream &OS, const SelectionDAG *G) const { + // Don't print impossibly deep things. + printrWithDepth(OS, G, 100); +} + +void SDNode::dumprWithDepth(const SelectionDAG *G, unsigned depth) const { + printrWithDepth(dbgs(), G, depth); +} + +void SDNode::dumprFull(const SelectionDAG *G) const { + // Don't print impossibly deep things. + dumprWithDepth(G, 100); +} + static void DumpNodes(const SDNode *N, unsigned indent, const SelectionDAG *G) { for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) if (N->getOperand(i).getNode()->hasOneUse()) @@ -6228,3 +6278,35 @@ bool ShuffleVectorSDNode::isSplatMask(const int *Mask, EVT VT) { return false; return true; } + +static void checkForCyclesHelper(const SDNode *N, + std::set<const SDNode *> &visited) { + if (visited.find(N) != visited.end()) { + dbgs() << "Offending node:\n"; + N->dumprFull(); + assert(0 && "Detected cycle in SelectionDAG"); + } + + std::set<const SDNode*>::iterator i; + bool inserted; + + tie(i, inserted) = visited.insert(N); + assert(inserted && "Missed cycle"); + + for(unsigned i = 0; i < N->getNumOperands(); ++i) { + checkForCyclesHelper(N->getOperand(i).getNode(), visited); + } + visited.erase(i); +} + +void llvm::checkForCycles(const llvm::SDNode *N) { +#ifdef XDEBUG + assert(N && "Checking nonexistant SDNode"); + std::set<const SDNode *> visited; + checkForCyclesHelper(N, visited); +#endif +} + +void llvm::checkForCycles(const llvm::SelectionDAG *DAG) { + checkForCycles(DAG->getRoot().getNode()); +} diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 5e3a3b5..23c7059 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -176,7 +176,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, assert(NumParts > 0 && "No parts to assemble!"); const TargetLowering &TLI = DAG.getTargetLoweringInfo(); SDValue Val = Parts[0]; - if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); if (NumParts > 1) { // Assemble the value from multiple parts. @@ -209,11 +209,9 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, Val = DAG.getNode(ISD::BUILD_PAIR, dl, RoundVT, Lo, Hi); - if (DisableScheduling) { - DAG.AssignOrdering(Lo.getNode(), Order); - DAG.AssignOrdering(Hi.getNode(), Order); - DAG.AssignOrdering(Val.getNode(), Order); - } + DAG.AssignOrdering(Lo.getNode(), Order); + DAG.AssignOrdering(Hi.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); if (RoundParts < NumParts) { // Assemble the trailing non-power-of-2 part. @@ -228,15 +226,15 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, std::swap(Lo, Hi); EVT TotalVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); Hi = DAG.getNode(ISD::ANY_EXTEND, dl, TotalVT, Hi); - if (DisableScheduling) DAG.AssignOrdering(Hi.getNode(), Order); + DAG.AssignOrdering(Hi.getNode(), Order); Hi = DAG.getNode(ISD::SHL, dl, TotalVT, Hi, DAG.getConstant(Lo.getValueType().getSizeInBits(), TLI.getPointerTy())); - if (DisableScheduling) DAG.AssignOrdering(Hi.getNode(), Order); + DAG.AssignOrdering(Hi.getNode(), Order); Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, TotalVT, Lo); - if (DisableScheduling) DAG.AssignOrdering(Lo.getNode(), Order); + DAG.AssignOrdering(Lo.getNode(), Order); Val = DAG.getNode(ISD::OR, dl, TotalVT, Lo, Hi); - if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); } } else if (ValueVT.isVector()) { // Handle a multi-element vector. @@ -277,7 +275,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, Val = DAG.getNode(IntermediateVT.isVector() ? ISD::CONCAT_VECTORS : ISD::BUILD_VECTOR, dl, ValueVT, &Ops[0], NumIntermediates); - if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); } else if (PartVT.isFloatingPoint()) { // FP split into multiple FP parts (for ppcf128) assert(ValueVT == EVT(MVT::ppcf128) && PartVT == EVT(MVT::f64) && @@ -289,11 +287,9 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, std::swap(Lo, Hi); Val = DAG.getNode(ISD::BUILD_PAIR, dl, ValueVT, Lo, Hi); - if (DisableScheduling) { - DAG.AssignOrdering(Hi.getNode(), Order); - DAG.AssignOrdering(Lo.getNode(), Order); - DAG.AssignOrdering(Val.getNode(), Order); - } + DAG.AssignOrdering(Hi.getNode(), Order); + DAG.AssignOrdering(Lo.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); } else { // FP split into integer parts (soft fp) assert(ValueVT.isFloatingPoint() && PartVT.isInteger() && @@ -312,8 +308,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, if (PartVT.isVector()) { assert(ValueVT.isVector() && "Unknown vector conversion!"); SDValue Res = DAG.getNode(ISD::BIT_CONVERT, dl, ValueVT, Val); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), Order); + DAG.AssignOrdering(Res.getNode(), Order); return Res; } @@ -322,8 +317,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, ValueVT.getVectorNumElements() == 1 && "Only trivial scalar-to-vector conversions should get here!"); SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, dl, ValueVT, Val); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), Order); + DAG.AssignOrdering(Res.getNode(), Order); return Res; } @@ -336,13 +330,13 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, if (AssertOp != ISD::DELETED_NODE) Val = DAG.getNode(AssertOp, dl, PartVT, Val, DAG.getValueType(ValueVT)); - if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); Val = DAG.getNode(ISD::TRUNCATE, dl, ValueVT, Val); - if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); return Val; } else { Val = DAG.getNode(ISD::ANY_EXTEND, dl, ValueVT, Val); - if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); return Val; } } @@ -352,18 +346,18 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, // FP_ROUND's are always exact here. Val = DAG.getNode(ISD::FP_ROUND, dl, ValueVT, Val, DAG.getIntPtrConstant(1)); - if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); return Val; } Val = DAG.getNode(ISD::FP_EXTEND, dl, ValueVT, Val); - if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); return Val; } if (PartVT.getSizeInBits() == ValueVT.getSizeInBits()) { Val = DAG.getNode(ISD::BIT_CONVERT, dl, ValueVT, Val); - if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); return Val; } @@ -420,7 +414,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, } } - if (DisableScheduling) DAG.AssignOrdering(Val.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); // The value may have changed - recompute ValueVT. ValueVT = Val.getValueType(); @@ -455,10 +449,8 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, ValueVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); Val = DAG.getNode(ISD::TRUNCATE, dl, ValueVT, Val); - if (DisableScheduling) { - DAG.AssignOrdering(OddVal.getNode(), Order); - DAG.AssignOrdering(Val.getNode(), Order); - } + DAG.AssignOrdering(OddVal.getNode(), Order); + DAG.AssignOrdering(Val.getNode(), Order); } // The number of parts is a power of 2. Repeatedly bisect the value using @@ -468,8 +460,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, ValueVT.getSizeInBits()), Val); - if (DisableScheduling) - DAG.AssignOrdering(Parts[0].getNode(), Order); + DAG.AssignOrdering(Parts[0].getNode(), Order); for (unsigned StepSize = NumParts; StepSize > 1; StepSize /= 2) { for (unsigned i = 0; i < NumParts; i += StepSize) { @@ -485,20 +476,16 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, ThisVT, Part0, DAG.getConstant(0, PtrVT)); - if (DisableScheduling) { - DAG.AssignOrdering(Part0.getNode(), Order); - DAG.AssignOrdering(Part1.getNode(), Order); - } + DAG.AssignOrdering(Part0.getNode(), Order); + DAG.AssignOrdering(Part1.getNode(), Order); if (ThisBits == PartBits && ThisVT != PartVT) { Part0 = DAG.getNode(ISD::BIT_CONVERT, dl, PartVT, Part0); Part1 = DAG.getNode(ISD::BIT_CONVERT, dl, PartVT, Part1); - if (DisableScheduling) { - DAG.AssignOrdering(Part0.getNode(), Order); - DAG.AssignOrdering(Part1.getNode(), Order); - } + DAG.AssignOrdering(Part0.getNode(), Order); + DAG.AssignOrdering(Part1.getNode(), Order); } } } @@ -524,9 +511,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, } } - if (DisableScheduling) - DAG.AssignOrdering(Val.getNode(), Order); - + DAG.AssignOrdering(Val.getNode(), Order); Parts[0] = Val; return; } @@ -555,8 +540,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, IntermediateVT, Val, DAG.getConstant(i, PtrVT)); - if (DisableScheduling) - DAG.AssignOrdering(Ops[i].getNode(), Order); + DAG.AssignOrdering(Ops[i].getNode(), Order); } // Split the intermediate operands into legal parts. @@ -717,8 +701,7 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) { SDValue Res = DAG.getMergeValues(&Constants[0], Constants.size(), getCurDebugLoc()); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return Res; } @@ -744,8 +727,7 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) { SDValue Res = DAG.getMergeValues(&Constants[0], NumElts, getCurDebugLoc()); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return Res; } @@ -776,9 +758,7 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) { // Create a BUILD_VECTOR node. SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), VT, &Ops[0], Ops.size()); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return NodeMap[V] = Res; } @@ -800,18 +780,19 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) { SDNodeOrder, Chain, NULL); } -/// Get the EVTs and ArgFlags collections that represent the return type -/// of the given function. This does not require a DAG or a return value, and -/// is suitable for use before any DAGs for the function are constructed. +/// Get the EVTs and ArgFlags collections that represent the legalized return +/// type of the given function. This does not require a DAG or a return value, +/// and is suitable for use before any DAGs for the function are constructed. static void getReturnInfo(const Type* ReturnType, Attributes attr, SmallVectorImpl<EVT> &OutVTs, SmallVectorImpl<ISD::ArgFlagsTy> &OutFlags, TargetLowering &TLI, SmallVectorImpl<uint64_t> *Offsets = 0) { SmallVector<EVT, 4> ValueVTs; - ComputeValueVTs(TLI, ReturnType, ValueVTs, Offsets); + ComputeValueVTs(TLI, ReturnType, ValueVTs); unsigned NumValues = ValueVTs.size(); - if ( NumValues == 0 ) return; + if (NumValues == 0) return; + unsigned Offset = 0; for (unsigned j = 0, f = NumValues; j != f; ++j) { EVT VT = ValueVTs[j]; @@ -834,6 +815,9 @@ static void getReturnInfo(const Type* ReturnType, unsigned NumParts = TLI.getNumRegisters(ReturnType->getContext(), VT); EVT PartVT = TLI.getRegisterType(ReturnType->getContext(), VT); + unsigned PartSize = TLI.getTargetData()->getTypeAllocSize( + PartVT.getTypeForEVT(ReturnType->getContext())); + // 'inreg' on function refers to return value ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); if (attr & Attribute::InReg) @@ -848,6 +832,11 @@ static void getReturnInfo(const Type* ReturnType, for (unsigned i = 0; i < NumParts; ++i) { OutVTs.push_back(PartVT); OutFlags.push_back(Flags); + if (Offsets) + { + Offsets->push_back(Offset); + Offset += PartSize; + } } } } @@ -886,17 +875,14 @@ void SelectionDAGBuilder::visitRet(ReturnInst &I) { SDValue(RetOp.getNode(), RetOp.getResNo() + i), Add, NULL, Offsets[i], false, 0); - if (DisableScheduling) { - DAG.AssignOrdering(Add.getNode(), SDNodeOrder); - DAG.AssignOrdering(Chains[i].getNode(), SDNodeOrder); - } + DAG.AssignOrdering(Add.getNode(), SDNodeOrder); + DAG.AssignOrdering(Chains[i].getNode(), SDNodeOrder); } Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, &Chains[0], NumValues); - if (DisableScheduling) - DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); + DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); } else { for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { SmallVector<EVT, 4> ValueVTs; @@ -962,9 +948,7 @@ void SelectionDAGBuilder::visitRet(ReturnInst &I) { // Update the DAG with the new chain value resulting from return lowering. DAG.setRoot(Chain); - - if (DisableScheduling) - DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); + DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); } /// CopyToExportRegsIfNeeded - If the given value has virtual registers @@ -1230,9 +1214,7 @@ void SelectionDAGBuilder::visitBr(BranchInst &I) { MVT::Other, getControlRoot(), DAG.getBasicBlock(Succ0MBB)); DAG.setRoot(V); - - if (DisableScheduling) - DAG.AssignOrdering(V.getNode(), SDNodeOrder); + DAG.AssignOrdering(V.getNode(), SDNodeOrder); } return; @@ -1339,8 +1321,7 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB) { } } - if (DisableScheduling) - DAG.AssignOrdering(Cond.getNode(), SDNodeOrder); + DAG.AssignOrdering(Cond.getNode(), SDNodeOrder); // Update successor info CurMBB->addSuccessor(CB.TrueBB); @@ -1359,17 +1340,13 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB) { std::swap(CB.TrueBB, CB.FalseBB); SDValue True = DAG.getConstant(1, Cond.getValueType()); Cond = DAG.getNode(ISD::XOR, dl, Cond.getValueType(), Cond, True); - - if (DisableScheduling) - DAG.AssignOrdering(Cond.getNode(), SDNodeOrder); + DAG.AssignOrdering(Cond.getNode(), SDNodeOrder); } SDValue BrCond = DAG.getNode(ISD::BRCOND, dl, MVT::Other, getControlRoot(), Cond, DAG.getBasicBlock(CB.TrueBB)); - - if (DisableScheduling) - DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); + DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); // If the branch was constant folded, fix up the CFG. if (BrCond.getOpcode() == ISD::BR) { @@ -1383,8 +1360,7 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB) { BrCond = DAG.getNode(ISD::BR, dl, MVT::Other, BrCond, DAG.getBasicBlock(CB.FalseBB)); - if (DisableScheduling) - DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); + DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); } } @@ -1404,11 +1380,9 @@ void SelectionDAGBuilder::visitJumpTable(JumpTable &JT) { Table, Index); DAG.setRoot(BrJumpTable); - if (DisableScheduling) { - DAG.AssignOrdering(Index.getNode(), SDNodeOrder); - DAG.AssignOrdering(Table.getNode(), SDNodeOrder); - DAG.AssignOrdering(BrJumpTable.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(Index.getNode(), SDNodeOrder); + DAG.AssignOrdering(Table.getNode(), SDNodeOrder); + DAG.AssignOrdering(BrJumpTable.getNode(), SDNodeOrder); } /// visitJumpTableHeader - This function emits necessary code to produce index @@ -1443,12 +1417,10 @@ void SelectionDAGBuilder::visitJumpTableHeader(JumpTable &JT, DAG.getConstant(JTH.Last-JTH.First,VT), ISD::SETUGT); - if (DisableScheduling) { - DAG.AssignOrdering(Sub.getNode(), SDNodeOrder); - DAG.AssignOrdering(SwitchOp.getNode(), SDNodeOrder); - DAG.AssignOrdering(CopyTo.getNode(), SDNodeOrder); - DAG.AssignOrdering(CMP.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(Sub.getNode(), SDNodeOrder); + DAG.AssignOrdering(SwitchOp.getNode(), SDNodeOrder); + DAG.AssignOrdering(CopyTo.getNode(), SDNodeOrder); + DAG.AssignOrdering(CMP.getNode(), SDNodeOrder); // Set NextBlock to be the MBB immediately after the current one, if any. // This is used to avoid emitting unnecessary branches to the next block. @@ -1462,15 +1434,12 @@ void SelectionDAGBuilder::visitJumpTableHeader(JumpTable &JT, MVT::Other, CopyTo, CMP, DAG.getBasicBlock(JT.Default)); - if (DisableScheduling) - DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); + DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); if (JT.MBB != NextBlock) { BrCond = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, BrCond, DAG.getBasicBlock(JT.MBB)); - - if (DisableScheduling) - DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); + DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); } DAG.setRoot(BrCond); @@ -1498,12 +1467,10 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B) { SDValue CopyTo = DAG.getCopyToReg(getControlRoot(), getCurDebugLoc(), B.Reg, ShiftOp); - if (DisableScheduling) { - DAG.AssignOrdering(Sub.getNode(), SDNodeOrder); - DAG.AssignOrdering(RangeCmp.getNode(), SDNodeOrder); - DAG.AssignOrdering(ShiftOp.getNode(), SDNodeOrder); - DAG.AssignOrdering(CopyTo.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(Sub.getNode(), SDNodeOrder); + DAG.AssignOrdering(RangeCmp.getNode(), SDNodeOrder); + DAG.AssignOrdering(ShiftOp.getNode(), SDNodeOrder); + DAG.AssignOrdering(CopyTo.getNode(), SDNodeOrder); // Set NextBlock to be the MBB immediately after the current one, if any. // This is used to avoid emitting unnecessary branches to the next block. @@ -1521,15 +1488,12 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B) { MVT::Other, CopyTo, RangeCmp, DAG.getBasicBlock(B.Default)); - if (DisableScheduling) - DAG.AssignOrdering(BrRange.getNode(), SDNodeOrder); + DAG.AssignOrdering(BrRange.getNode(), SDNodeOrder); if (MBB != NextBlock) { BrRange = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, CopyTo, DAG.getBasicBlock(MBB)); - - if (DisableScheduling) - DAG.AssignOrdering(BrRange.getNode(), SDNodeOrder); + DAG.AssignOrdering(BrRange.getNode(), SDNodeOrder); } DAG.setRoot(BrRange); @@ -1556,12 +1520,10 @@ void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB, AndOp, DAG.getConstant(0, TLI.getPointerTy()), ISD::SETNE); - if (DisableScheduling) { - DAG.AssignOrdering(ShiftOp.getNode(), SDNodeOrder); - DAG.AssignOrdering(SwitchVal.getNode(), SDNodeOrder); - DAG.AssignOrdering(AndOp.getNode(), SDNodeOrder); - DAG.AssignOrdering(AndCmp.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(ShiftOp.getNode(), SDNodeOrder); + DAG.AssignOrdering(SwitchVal.getNode(), SDNodeOrder); + DAG.AssignOrdering(AndOp.getNode(), SDNodeOrder); + DAG.AssignOrdering(AndCmp.getNode(), SDNodeOrder); CurMBB->addSuccessor(B.TargetBB); CurMBB->addSuccessor(NextMBB); @@ -1570,8 +1532,7 @@ void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB, MVT::Other, getControlRoot(), AndCmp, DAG.getBasicBlock(B.TargetBB)); - if (DisableScheduling) - DAG.AssignOrdering(BrAnd.getNode(), SDNodeOrder); + DAG.AssignOrdering(BrAnd.getNode(), SDNodeOrder); // Set NextBlock to be the MBB immediately after the current one, if any. // This is used to avoid emitting unnecessary branches to the next block. @@ -1583,9 +1544,7 @@ void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB, if (NextMBB != NextBlock) { BrAnd = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, BrAnd, DAG.getBasicBlock(NextMBB)); - - if (DisableScheduling) - DAG.AssignOrdering(BrAnd.getNode(), SDNodeOrder); + DAG.AssignOrdering(BrAnd.getNode(), SDNodeOrder); } DAG.setRoot(BrAnd); @@ -1615,9 +1574,7 @@ void SelectionDAGBuilder::visitInvoke(InvokeInst &I) { MVT::Other, getControlRoot(), DAG.getBasicBlock(Return)); DAG.setRoot(Branch); - - if (DisableScheduling) - DAG.AssignOrdering(Branch.getNode(), SDNodeOrder); + DAG.AssignOrdering(Branch.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitUnwind(UnwindInst &I) { @@ -2134,9 +2091,7 @@ void SelectionDAGBuilder::visitSwitch(SwitchInst &SI) { MVT::Other, getControlRoot(), DAG.getBasicBlock(Default)); DAG.setRoot(Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } return; @@ -2194,9 +2149,7 @@ void SelectionDAGBuilder::visitIndirectBr(IndirectBrInst &I) { MVT::Other, getControlRoot(), getValue(I.getAddress())); DAG.setRoot(Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitFSub(User &I) { @@ -2214,10 +2167,7 @@ void SelectionDAGBuilder::visitFSub(User &I) { SDValue Res = DAG.getNode(ISD::FNEG, getCurDebugLoc(), Op2.getValueType(), Op2); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return; } } @@ -2229,10 +2179,7 @@ void SelectionDAGBuilder::visitFSub(User &I) { SDValue Res = DAG.getNode(ISD::FNEG, getCurDebugLoc(), Op2.getValueType(), Op2); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return; } @@ -2245,9 +2192,7 @@ void SelectionDAGBuilder::visitBinary(User &I, unsigned OpCode) { SDValue Res = DAG.getNode(OpCode, getCurDebugLoc(), Op1.getValueType(), Op1, Op2); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitShift(User &I, unsigned Opcode) { @@ -2283,12 +2228,9 @@ void SelectionDAGBuilder::visitShift(User &I, unsigned Opcode) { SDValue Res = DAG.getNode(Opcode, getCurDebugLoc(), Op1.getValueType(), Op1, Op2); setValue(&I, Res); - - if (DisableScheduling) { - DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); - DAG.AssignOrdering(Op2.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); + DAG.AssignOrdering(Op2.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitICmp(User &I) { @@ -2304,9 +2246,7 @@ void SelectionDAGBuilder::visitICmp(User &I) { EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Opcode); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitFCmp(User &I) { @@ -2321,9 +2261,7 @@ void SelectionDAGBuilder::visitFCmp(User &I) { EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Condition); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitSelect(User &I) { @@ -2345,17 +2283,14 @@ void SelectionDAGBuilder::visitSelect(User &I) { SDValue(FalseVal.getNode(), FalseVal.getResNo() + i)); - if (DisableScheduling) - DAG.AssignOrdering(Values[i].getNode(), SDNodeOrder); + DAG.AssignOrdering(Values[i].getNode(), SDNodeOrder); } SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), DAG.getVTList(&ValueVTs[0], NumValues), &Values[0], NumValues); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitTrunc(User &I) { @@ -2364,9 +2299,7 @@ void SelectionDAGBuilder::visitTrunc(User &I) { EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), DestVT, N); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitZExt(User &I) { @@ -2376,9 +2309,7 @@ void SelectionDAGBuilder::visitZExt(User &I) { EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), DestVT, N); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitSExt(User &I) { @@ -2388,9 +2319,7 @@ void SelectionDAGBuilder::visitSExt(User &I) { EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getNode(ISD::SIGN_EXTEND, getCurDebugLoc(), DestVT, N); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitFPTrunc(User &I) { @@ -2400,9 +2329,7 @@ void SelectionDAGBuilder::visitFPTrunc(User &I) { SDValue Res = DAG.getNode(ISD::FP_ROUND, getCurDebugLoc(), DestVT, N, DAG.getIntPtrConstant(0)); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitFPExt(User &I){ @@ -2411,9 +2338,7 @@ void SelectionDAGBuilder::visitFPExt(User &I){ EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getNode(ISD::FP_EXTEND, getCurDebugLoc(), DestVT, N); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitFPToUI(User &I) { @@ -2422,9 +2347,7 @@ void SelectionDAGBuilder::visitFPToUI(User &I) { EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getNode(ISD::FP_TO_UINT, getCurDebugLoc(), DestVT, N); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitFPToSI(User &I) { @@ -2433,9 +2356,7 @@ void SelectionDAGBuilder::visitFPToSI(User &I) { EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getNode(ISD::FP_TO_SINT, getCurDebugLoc(), DestVT, N); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitUIToFP(User &I) { @@ -2444,9 +2365,7 @@ void SelectionDAGBuilder::visitUIToFP(User &I) { EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getNode(ISD::UINT_TO_FP, getCurDebugLoc(), DestVT, N); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitSIToFP(User &I){ @@ -2455,9 +2374,7 @@ void SelectionDAGBuilder::visitSIToFP(User &I){ EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getNode(ISD::SINT_TO_FP, getCurDebugLoc(), DestVT, N); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitPtrToInt(User &I) { @@ -2468,9 +2385,7 @@ void SelectionDAGBuilder::visitPtrToInt(User &I) { EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitIntToPtr(User &I) { @@ -2481,9 +2396,7 @@ void SelectionDAGBuilder::visitIntToPtr(User &I) { EVT DestVT = TLI.getValueType(I.getType()); SDValue Res = DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitBitCast(User &I) { @@ -2496,9 +2409,7 @@ void SelectionDAGBuilder::visitBitCast(User &I) { SDValue Res = DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), DestVT, N); // convert types. setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } else { setValue(&I, N); // noop cast. } @@ -2515,10 +2426,8 @@ void SelectionDAGBuilder::visitInsertElement(User &I) { InVec, InVal, InIdx); setValue(&I, Res); - if (DisableScheduling) { - DAG.AssignOrdering(InIdx.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(InIdx.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitExtractElement(User &I) { @@ -2530,10 +2439,8 @@ void SelectionDAGBuilder::visitExtractElement(User &I) { TLI.getValueType(I.getType()), InVec, InIdx); setValue(&I, Res); - if (DisableScheduling) { - DAG.AssignOrdering(InIdx.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(InIdx.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } @@ -2573,10 +2480,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { SDValue Res = DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, &Mask[0]); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return; } @@ -2590,10 +2494,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, getCurDebugLoc(), VT, Src1, Src2); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return; } @@ -2628,13 +2529,9 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { SDValue Res = DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, &MappedOps[0]); setValue(&I, Res); - - if (DisableScheduling) { - DAG.AssignOrdering(Src1.getNode(), SDNodeOrder); - DAG.AssignOrdering(Src2.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - } - + DAG.AssignOrdering(Src1.getNode(), SDNodeOrder); + DAG.AssignOrdering(Src2.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return; } @@ -2688,10 +2585,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { if (RangeUse[0] == 0 && RangeUse[1] == 0) { SDValue Res = DAG.getUNDEF(VT); setValue(&I, Res); // Vectors are not used. - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return; } else if (RangeUse[0] < 2 && RangeUse[1] < 2) { @@ -2704,8 +2598,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { Src = DAG.getNode(ISD::EXTRACT_SUBVECTOR, getCurDebugLoc(), VT, Src, DAG.getIntPtrConstant(StartIdx[Input])); - if (DisableScheduling) - DAG.AssignOrdering(Src.getNode(), SDNodeOrder); + DAG.AssignOrdering(Src.getNode(), SDNodeOrder); } // Calculate new mask. @@ -2723,10 +2616,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { SDValue Res = DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, &MappedOps[0]); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return; } } @@ -2753,18 +2643,14 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { DAG.getConstant(Idx - SrcNumElts, PtrVT)); Ops.push_back(Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } } SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), VT, &Ops[0], Ops.size()); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitInsertValue(InsertValueInst &I) { @@ -2807,9 +2693,7 @@ void SelectionDAGBuilder::visitInsertValue(InsertValueInst &I) { DAG.getVTList(&AggValueVTs[0], NumAggValues), &Values[0], NumAggValues); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitExtractValue(ExtractValueInst &I) { @@ -2839,9 +2723,7 @@ void SelectionDAGBuilder::visitExtractValue(ExtractValueInst &I) { DAG.getVTList(&ValValueVTs[0], NumValValues), &Values[0], NumValValues); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitGetElementPtr(User &I) { @@ -2858,9 +2740,7 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) { uint64_t Offset = TD->getStructLayout(StTy)->getElementOffset(Field); N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N, DAG.getIntPtrConstant(Offset)); - - if (DisableScheduling) - DAG.AssignOrdering(N.getNode(), SDNodeOrder); + DAG.AssignOrdering(N.getNode(), SDNodeOrder); } Ty = StTy->getElementType(Field); @@ -2885,11 +2765,8 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) { N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N, OffsVal); - if (DisableScheduling) { - DAG.AssignOrdering(OffsVal.getNode(), SDNodeOrder); - DAG.AssignOrdering(N.getNode(), SDNodeOrder); - } - + DAG.AssignOrdering(OffsVal.getNode(), SDNodeOrder); + DAG.AssignOrdering(N.getNode(), SDNodeOrder); continue; } @@ -2916,15 +2793,12 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) { N.getValueType(), IdxN, Scale); } - if (DisableScheduling) - DAG.AssignOrdering(IdxN.getNode(), SDNodeOrder); + DAG.AssignOrdering(IdxN.getNode(), SDNodeOrder); } N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N, IdxN); - - if (DisableScheduling) - DAG.AssignOrdering(N.getNode(), SDNodeOrder); + DAG.AssignOrdering(N.getNode(), SDNodeOrder); } } @@ -2949,14 +2823,11 @@ void SelectionDAGBuilder::visitAlloca(AllocaInst &I) { AllocSize, DAG.getConstant(TySize, AllocSize.getValueType())); - if (DisableScheduling) - DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); + DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); EVT IntPtr = TLI.getPointerTy(); AllocSize = DAG.getZExtOrTrunc(AllocSize, getCurDebugLoc(), IntPtr); - - if (DisableScheduling) - DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); + DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); // Handle alignment. If the requested alignment is less than or equal to // the stack alignment, ignore it. If the size is greater than or equal to @@ -2971,15 +2842,13 @@ void SelectionDAGBuilder::visitAlloca(AllocaInst &I) { AllocSize = DAG.getNode(ISD::ADD, getCurDebugLoc(), AllocSize.getValueType(), AllocSize, DAG.getIntPtrConstant(StackAlign-1)); - if (DisableScheduling) - DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); + DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); // Mask out the low bits for alignment purposes. AllocSize = DAG.getNode(ISD::AND, getCurDebugLoc(), AllocSize.getValueType(), AllocSize, DAG.getIntPtrConstant(~(uint64_t)(StackAlign-1))); - if (DisableScheduling) - DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); + DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); SDValue Ops[] = { getRoot(), AllocSize, DAG.getIntPtrConstant(Align) }; SDVTList VTs = DAG.getVTList(AllocSize.getValueType(), MVT::Other); @@ -2987,9 +2856,7 @@ void SelectionDAGBuilder::visitAlloca(AllocaInst &I) { VTs, Ops, 3); setValue(&I, DSA); DAG.setRoot(DSA.getValue(1)); - - if (DisableScheduling) - DAG.AssignOrdering(DSA.getNode(), SDNodeOrder); + DAG.AssignOrdering(DSA.getNode(), SDNodeOrder); // Inform the Frame Information that we have just allocated a variable-sized // object. @@ -3038,10 +2905,8 @@ void SelectionDAGBuilder::visitLoad(LoadInst &I) { Values[i] = L; Chains[i] = L.getValue(1); - if (DisableScheduling) { - DAG.AssignOrdering(A.getNode(), SDNodeOrder); - DAG.AssignOrdering(L.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(A.getNode(), SDNodeOrder); + DAG.AssignOrdering(L.getNode(), SDNodeOrder); } if (!ConstantMemory) { @@ -3052,17 +2917,14 @@ void SelectionDAGBuilder::visitLoad(LoadInst &I) { else PendingLoads.push_back(Chain); - if (DisableScheduling) - DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); + DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); } SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), DAG.getVTList(&ValueVTs[0], NumValues), &Values[0], NumValues); setValue(&I, Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } void SelectionDAGBuilder::visitStore(StoreInst &I) { @@ -3095,18 +2957,14 @@ void SelectionDAGBuilder::visitStore(StoreInst &I) { SDValue(Src.getNode(), Src.getResNo() + i), Add, PtrV, Offsets[i], isVolatile, Alignment); - if (DisableScheduling) { - DAG.AssignOrdering(Add.getNode(), SDNodeOrder); - DAG.AssignOrdering(Chains[i].getNode(), SDNodeOrder); - } + DAG.AssignOrdering(Add.getNode(), SDNodeOrder); + DAG.AssignOrdering(Chains[i].getNode(), SDNodeOrder); } SDValue Res = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, &Chains[0], NumValues); DAG.setRoot(Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } /// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC @@ -3177,8 +3035,7 @@ void SelectionDAGBuilder::visitTargetIntrinsic(CallInst &I, VTs, &Ops[0], Ops.size()); } - if (DisableScheduling) - DAG.AssignOrdering(Result.getNode(), SDNodeOrder); + DAG.AssignOrdering(Result.getNode(), SDNodeOrder); if (HasChain) { SDValue Chain = Result.getValue(Result.getNode()->getNumValues()-1); @@ -3192,9 +3049,7 @@ void SelectionDAGBuilder::visitTargetIntrinsic(CallInst &I, if (const VectorType *PTy = dyn_cast<VectorType>(I.getType())) { EVT VT = TLI.getValueType(PTy); Result = DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), VT, Result); - - if (DisableScheduling) - DAG.AssignOrdering(Result.getNode(), SDNodeOrder); + DAG.AssignOrdering(Result.getNode(), SDNodeOrder); } setValue(&I, Result); @@ -3215,12 +3070,9 @@ GetSignificand(SelectionDAG &DAG, SDValue Op, DebugLoc dl, unsigned Order) { DAG.getConstant(0x3f800000, MVT::i32)); SDValue Res = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t2); - if (DisableScheduling) { - DAG.AssignOrdering(t1.getNode(), Order); - DAG.AssignOrdering(t2.getNode(), Order); - DAG.AssignOrdering(Res.getNode(), Order); - } - + DAG.AssignOrdering(t1.getNode(), Order); + DAG.AssignOrdering(t2.getNode(), Order); + DAG.AssignOrdering(Res.getNode(), Order); return Res; } @@ -3240,13 +3092,10 @@ GetExponent(SelectionDAG &DAG, SDValue Op, const TargetLowering &TLI, DAG.getConstant(127, MVT::i32)); SDValue Res = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, t2); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), Order); - DAG.AssignOrdering(t1.getNode(), Order); - DAG.AssignOrdering(t2.getNode(), Order); - DAG.AssignOrdering(Res.getNode(), Order); - } - + DAG.AssignOrdering(t0.getNode(), Order); + DAG.AssignOrdering(t1.getNode(), Order); + DAG.AssignOrdering(t2.getNode(), Order); + DAG.AssignOrdering(Res.getNode(), Order); return Res; } @@ -3271,10 +3120,7 @@ SelectionDAGBuilder::implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op) { I.getOperand(1)); setValue(&I, L); DAG.setRoot(L.getValue(1)); - - if (DisableScheduling) - DAG.AssignOrdering(L.getNode(), SDNodeOrder); - + DAG.AssignOrdering(L.getNode(), SDNodeOrder); return 0; } @@ -3288,10 +3134,7 @@ SelectionDAGBuilder::implVisitAluOverflow(CallInst &I, ISD::NodeType Op) { SDValue Result = DAG.getNode(Op, getCurDebugLoc(), VTs, Op1, Op2); setValue(&I, Result); - - if (DisableScheduling) - DAG.AssignOrdering(Result.getNode(), SDNodeOrder); - + DAG.AssignOrdering(Result.getNode(), SDNodeOrder); return 0; } @@ -3319,19 +3162,15 @@ SelectionDAGBuilder::visitExp(CallInst &I) { SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, t1); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(X.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(X.getNode(), SDNodeOrder); // IntegerPartOfX <<= 23; IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, DAG.getConstant(23, TLI.getPointerTy())); - - if (DisableScheduling) - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: @@ -3356,15 +3195,13 @@ SelectionDAGBuilder::visitExp(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t6); - if (DisableScheduling) { - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -3392,17 +3229,15 @@ SelectionDAGBuilder::visitExp(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t8); - if (DisableScheduling) { - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(t7.getNode(), SDNodeOrder); + DAG.AssignOrdering(t8.getNode(), SDNodeOrder); + DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -3443,31 +3278,28 @@ SelectionDAGBuilder::visitExp(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t14); - if (DisableScheduling) { - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(t9.getNode(), SDNodeOrder); - DAG.AssignOrdering(t10.getNode(), SDNodeOrder); - DAG.AssignOrdering(t11.getNode(), SDNodeOrder); - DAG.AssignOrdering(t12.getNode(), SDNodeOrder); - DAG.AssignOrdering(t13.getNode(), SDNodeOrder); - DAG.AssignOrdering(t14.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(t7.getNode(), SDNodeOrder); + DAG.AssignOrdering(t8.getNode(), SDNodeOrder); + DAG.AssignOrdering(t9.getNode(), SDNodeOrder); + DAG.AssignOrdering(t10.getNode(), SDNodeOrder); + DAG.AssignOrdering(t11.getNode(), SDNodeOrder); + DAG.AssignOrdering(t12.getNode(), SDNodeOrder); + DAG.AssignOrdering(t13.getNode(), SDNodeOrder); + DAG.AssignOrdering(t14.getNode(), SDNodeOrder); + DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. result = DAG.getNode(ISD::FEXP, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); - if (DisableScheduling) - DAG.AssignOrdering(result.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -3485,16 +3317,14 @@ SelectionDAGBuilder::visitLog(CallInst &I) { SDValue Op = getValue(I.getOperand(1)); SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); - if (DisableScheduling) - DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); + DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); // Scale the exponent by log(2) [0.69314718f]. SDValue Exp = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder); SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp, getF32Constant(DAG, 0x3f317218)); - if (DisableScheduling) - DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder); + DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder); // Get the significand and build it into a floating-point number with // exponent of 1. @@ -3519,13 +3349,11 @@ SelectionDAGBuilder::visitLog(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, LogOfMantissa); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -3553,17 +3381,15 @@ SelectionDAGBuilder::visitLog(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, LogOfMantissa); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -3599,30 +3425,26 @@ SelectionDAGBuilder::visitLog(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, LogOfMantissa); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(t9.getNode(), SDNodeOrder); - DAG.AssignOrdering(t10.getNode(), SDNodeOrder); - DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(t7.getNode(), SDNodeOrder); + DAG.AssignOrdering(t8.getNode(), SDNodeOrder); + DAG.AssignOrdering(t9.getNode(), SDNodeOrder); + DAG.AssignOrdering(t10.getNode(), SDNodeOrder); + DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. result = DAG.getNode(ISD::FLOG, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); - - if (DisableScheduling) - DAG.AssignOrdering(result.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -3640,14 +3462,12 @@ SelectionDAGBuilder::visitLog2(CallInst &I) { SDValue Op = getValue(I.getOperand(1)); SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); - if (DisableScheduling) - DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); + DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); // Get the exponent. SDValue LogOfExponent = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder); - if (DisableScheduling) - DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder); + DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder); // Get the significand and build it into a floating-point number with // exponent of 1. @@ -3672,13 +3492,11 @@ SelectionDAGBuilder::visitLog2(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log2ofMantissa); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -3706,17 +3524,15 @@ SelectionDAGBuilder::visitLog2(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log2ofMantissa); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -3753,30 +3569,26 @@ SelectionDAGBuilder::visitLog2(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log2ofMantissa); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(t9.getNode(), SDNodeOrder); - DAG.AssignOrdering(t10.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(t7.getNode(), SDNodeOrder); + DAG.AssignOrdering(t8.getNode(), SDNodeOrder); + DAG.AssignOrdering(t9.getNode(), SDNodeOrder); + DAG.AssignOrdering(t10.getNode(), SDNodeOrder); + DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. result = DAG.getNode(ISD::FLOG2, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); - - if (DisableScheduling) - DAG.AssignOrdering(result.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -3794,16 +3606,14 @@ SelectionDAGBuilder::visitLog10(CallInst &I) { SDValue Op = getValue(I.getOperand(1)); SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); - if (DisableScheduling) - DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); + DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); // Scale the exponent by log10(2) [0.30102999f]. SDValue Exp = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder); SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp, getF32Constant(DAG, 0x3e9a209a)); - if (DisableScheduling) - DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder); + DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder); // Get the significand and build it into a floating-point number with // exponent of 1. @@ -3828,13 +3638,11 @@ SelectionDAGBuilder::visitLog10(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log10ofMantissa); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -3858,15 +3666,13 @@ SelectionDAGBuilder::visitLog10(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log10ofMantissa); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -3898,28 +3704,24 @@ SelectionDAGBuilder::visitLog10(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log10ofMantissa); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(t7.getNode(), SDNodeOrder); + DAG.AssignOrdering(t8.getNode(), SDNodeOrder); + DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. result = DAG.getNode(ISD::FLOG10, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); - - if (DisableScheduling) - DAG.AssignOrdering(result.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -3938,8 +3740,7 @@ SelectionDAGBuilder::visitExp2(CallInst &I) { SDValue IntegerPartOfX = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, Op); - if (DisableScheduling) - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); // FractionalPartOfX = x - (float)IntegerPartOfX; SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); @@ -3949,11 +3750,9 @@ SelectionDAGBuilder::visitExp2(CallInst &I) { IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, DAG.getConstant(23, TLI.getPointerTy())); - if (DisableScheduling) { - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(X.getNode(), SDNodeOrder); - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(X.getNode(), SDNodeOrder); + DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: @@ -3977,15 +3776,13 @@ SelectionDAGBuilder::visitExp2(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - if (DisableScheduling) { - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -4012,17 +3809,15 @@ SelectionDAGBuilder::visitExp2(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - if (DisableScheduling) { - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(t7.getNode(), SDNodeOrder); + DAG.AssignOrdering(t8.getNode(), SDNodeOrder); + DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -4060,32 +3855,28 @@ SelectionDAGBuilder::visitExp2(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - if (DisableScheduling) { - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(t9.getNode(), SDNodeOrder); - DAG.AssignOrdering(t10.getNode(), SDNodeOrder); - DAG.AssignOrdering(t11.getNode(), SDNodeOrder); - DAG.AssignOrdering(t12.getNode(), SDNodeOrder); - DAG.AssignOrdering(t13.getNode(), SDNodeOrder); - DAG.AssignOrdering(t14.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(t7.getNode(), SDNodeOrder); + DAG.AssignOrdering(t8.getNode(), SDNodeOrder); + DAG.AssignOrdering(t9.getNode(), SDNodeOrder); + DAG.AssignOrdering(t10.getNode(), SDNodeOrder); + DAG.AssignOrdering(t11.getNode(), SDNodeOrder); + DAG.AssignOrdering(t12.getNode(), SDNodeOrder); + DAG.AssignOrdering(t13.getNode(), SDNodeOrder); + DAG.AssignOrdering(t14.getNode(), SDNodeOrder); + DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. result = DAG.getNode(ISD::FEXP2, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); - - if (DisableScheduling) - DAG.AssignOrdering(result.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -4127,19 +3918,16 @@ SelectionDAGBuilder::visitPow(CallInst &I) { SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, t1); - if (DisableScheduling) { - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(X.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t0.getNode(), SDNodeOrder); + DAG.AssignOrdering(t1.getNode(), SDNodeOrder); + DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(X.getNode(), SDNodeOrder); // IntegerPartOfX <<= 23; IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, DAG.getConstant(23, TLI.getPointerTy())); - if (DisableScheduling) - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: @@ -4163,15 +3951,13 @@ SelectionDAGBuilder::visitPow(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - if (DisableScheduling) { - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -4198,17 +3984,15 @@ SelectionDAGBuilder::visitPow(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - if (DisableScheduling) { - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(t7.getNode(), SDNodeOrder); + DAG.AssignOrdering(t8.getNode(), SDNodeOrder); + DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -4246,23 +4030,21 @@ SelectionDAGBuilder::visitPow(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - if (DisableScheduling) { - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(t9.getNode(), SDNodeOrder); - DAG.AssignOrdering(t10.getNode(), SDNodeOrder); - DAG.AssignOrdering(t11.getNode(), SDNodeOrder); - DAG.AssignOrdering(t12.getNode(), SDNodeOrder); - DAG.AssignOrdering(t13.getNode(), SDNodeOrder); - DAG.AssignOrdering(t14.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(t2.getNode(), SDNodeOrder); + DAG.AssignOrdering(t3.getNode(), SDNodeOrder); + DAG.AssignOrdering(t4.getNode(), SDNodeOrder); + DAG.AssignOrdering(t5.getNode(), SDNodeOrder); + DAG.AssignOrdering(t6.getNode(), SDNodeOrder); + DAG.AssignOrdering(t7.getNode(), SDNodeOrder); + DAG.AssignOrdering(t8.getNode(), SDNodeOrder); + DAG.AssignOrdering(t9.getNode(), SDNodeOrder); + DAG.AssignOrdering(t10.getNode(), SDNodeOrder); + DAG.AssignOrdering(t11.getNode(), SDNodeOrder); + DAG.AssignOrdering(t12.getNode(), SDNodeOrder); + DAG.AssignOrdering(t13.getNode(), SDNodeOrder); + DAG.AssignOrdering(t14.getNode(), SDNodeOrder); + DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. @@ -4270,9 +4052,7 @@ SelectionDAGBuilder::visitPow(CallInst &I) { getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1)), getValue(I.getOperand(2))); - - if (DisableScheduling) - DAG.AssignOrdering(result.getNode(), SDNodeOrder); + DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -4352,15 +4132,13 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Res = DAG.getNode(ISD::RETURNADDR, dl, TLI.getPointerTy(), getValue(I.getOperand(1))); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; case Intrinsic::frameaddress: Res = DAG.getNode(ISD::FRAMEADDR, dl, TLI.getPointerTy(), getValue(I.getOperand(1))); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; case Intrinsic::setjmp: return "_setjmp"+!TLI.usesUnderscoreSetJmp(); @@ -4374,8 +4152,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Res = DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, I.getOperand(1), 0, I.getOperand(2), 0); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::memset: { @@ -4386,8 +4163,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Res = DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align, I.getOperand(1), 0); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::memmove: { @@ -4406,16 +4182,14 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Res = DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, I.getOperand(1), 0, I.getOperand(2), 0); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } Res = DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align, I.getOperand(1), 0, I.getOperand(2), 0); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::dbg_declare: { @@ -4457,8 +4231,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { SDValue Op = DAG.getNode(ISD::EXCEPTIONADDR, dl, VTs, Ops, 1); setValue(&I, Op); DAG.setRoot(Op.getValue(1)); - if (DisableScheduling) - DAG.AssignOrdering(Op.getNode(), SDNodeOrder); + DAG.AssignOrdering(Op.getNode(), SDNodeOrder); return 0; } @@ -4487,10 +4260,8 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Res = DAG.getSExtOrTrunc(Op, dl, MVT::i32); setValue(&I, Res); - if (DisableScheduling) { - DAG.AssignOrdering(Op.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(Op.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } @@ -4508,8 +4279,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { } setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } @@ -4523,8 +4293,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { getValue(I.getOperand(1)), getValue(I.getOperand(2))); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } else { setValue(&I, DAG.getConstant(0, TLI.getPointerTy())); } @@ -4550,12 +4319,10 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Res = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), FA, Offset); setValue(&I, Res); - if (DisableScheduling) { - DAG.AssignOrdering(CfaArg.getNode(), SDNodeOrder); - DAG.AssignOrdering(Offset.getNode(), SDNodeOrder); - DAG.AssignOrdering(FA.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(CfaArg.getNode(), SDNodeOrder); + DAG.AssignOrdering(Offset.getNode(), SDNodeOrder); + DAG.AssignOrdering(FA.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::convertff: @@ -4588,8 +4355,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { getValue(I.getOperand(3)), Code); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::sqrt: @@ -4597,31 +4363,27 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; case Intrinsic::powi: Res = ExpandPowI(dl, getValue(I.getOperand(1)), getValue(I.getOperand(2)), DAG); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; case Intrinsic::sin: Res = DAG.getNode(ISD::FSIN, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; case Intrinsic::cos: Res = DAG.getNode(ISD::FCOS, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; case Intrinsic::log: visitLog(I); @@ -4645,8 +4407,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { SDValue Tmp = getValue(I.getOperand(1)); Res = DAG.getNode(ISD::PCMARKER, dl, MVT::Other, getRoot(), Tmp); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::readcyclecounter: { @@ -4656,8 +4417,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { &Op, 1); setValue(&I, Res); DAG.setRoot(Res.getValue(1)); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::bswap: @@ -4665,16 +4425,14 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; case Intrinsic::cttz: { SDValue Arg = getValue(I.getOperand(1)); EVT Ty = Arg.getValueType(); Res = DAG.getNode(ISD::CTTZ, dl, Ty, Arg); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::ctlz: { @@ -4682,8 +4440,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { EVT Ty = Arg.getValueType(); Res = DAG.getNode(ISD::CTLZ, dl, Ty, Arg); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::ctpop: { @@ -4691,8 +4448,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { EVT Ty = Arg.getValueType(); Res = DAG.getNode(ISD::CTPOP, dl, Ty, Arg); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::stacksave: { @@ -4701,16 +4457,14 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { DAG.getVTList(TLI.getPointerTy(), MVT::Other), &Op, 1); setValue(&I, Res); DAG.setRoot(Res.getValue(1)); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::stackrestore: { Res = getValue(I.getOperand(1)); Res = DAG.getNode(ISD::STACKRESTORE, dl, MVT::Other, getRoot(), Res); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::stackprotector: { @@ -4733,8 +4487,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { 0, true); setValue(&I, Res); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::objectsize: { @@ -4752,8 +4505,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Res = DAG.getConstant(0, Ty); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::var_annotation: @@ -4777,8 +4529,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { setValue(&I, Res); DAG.setRoot(Res.getValue(1)); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::gcroot: @@ -4797,14 +4548,12 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { case Intrinsic::flt_rounds: Res = DAG.getNode(ISD::FLT_ROUNDS_, dl, MVT::i32); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; case Intrinsic::trap: Res = DAG.getNode(ISD::TRAP, dl,MVT::Other, getRoot()); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; case Intrinsic::uadd_with_overflow: return implVisitAluOverflow(I, ISD::UADDO); @@ -4827,8 +4576,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Ops[3] = getValue(I.getOperand(3)); Res = DAG.getNode(ISD::PREFETCH, dl, MVT::Other, &Ops[0], 4); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } @@ -4840,8 +4588,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Res = DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, &Ops[0], 6); DAG.setRoot(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::atomic_cmp_swap: { @@ -4856,8 +4603,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { I.getOperand(1)); setValue(&I, L); DAG.setRoot(L.getValue(1)); - if (DisableScheduling) - DAG.AssignOrdering(L.getNode(), SDNodeOrder); + DAG.AssignOrdering(L.getNode(), SDNodeOrder); return 0; } case Intrinsic::atomic_load_add: @@ -4888,8 +4634,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { // Discard region information. Res = DAG.getUNDEF(TLI.getPointerTy()); setValue(&I, Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; case Intrinsic::invariant_end: case Intrinsic::lifetime_end: @@ -5070,8 +4815,7 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, "Null value expected with tail call!"); if (Result.first.getNode()) { setValue(CS.getInstruction(), Result.first); - if (DisableScheduling) - DAG.AssignOrdering(Result.first.getNode(), SDNodeOrder); + DAG.AssignOrdering(Result.first.getNode(), SDNodeOrder); } else if (!CanLowerReturn && Result.second.getNode()) { // The instruction result is the result of loading from the // hidden sret parameter. @@ -5098,25 +4842,42 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, SDValue Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, &Chains[0], NumValues); PendingLoads.push_back(Chain); + + // Collect the legal value parts into potentially illegal values + // that correspond to the original function's return values. + SmallVector<EVT, 4> RetTys; + RetTy = FTy->getReturnType(); + ComputeValueVTs(TLI, RetTy, RetTys); + ISD::NodeType AssertOp = ISD::DELETED_NODE; + SmallVector<SDValue, 4> ReturnValues; + unsigned CurReg = 0; + for (unsigned I = 0, E = RetTys.size(); I != E; ++I) { + EVT VT = RetTys[I]; + EVT RegisterVT = TLI.getRegisterType(RetTy->getContext(), VT); + unsigned NumRegs = TLI.getNumRegisters(RetTy->getContext(), VT); + + SDValue ReturnValue = + getCopyFromParts(DAG, getCurDebugLoc(), SDNodeOrder, &Values[CurReg], NumRegs, + RegisterVT, VT, AssertOp); + ReturnValues.push_back(ReturnValue); + DAG.AssignOrdering(ReturnValue.getNode(), SDNodeOrder); + CurReg += NumRegs; + } + SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&RetTys[0], RetTys.size()), + &ReturnValues[0], ReturnValues.size()); - SDValue MV = DAG.getNode(ISD::MERGE_VALUES, - getCurDebugLoc(), - DAG.getVTList(&OutVTs[0], NumValues), - &Values[0], NumValues); - setValue(CS.getInstruction(), MV); + setValue(CS.getInstruction(), Res); - if (DisableScheduling) { - DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); - DAG.AssignOrdering(MV.getNode(), SDNodeOrder); - } + DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); + DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } // As a special case, a null chain means that a tail call has been emitted and // the DAG root is already updated. if (Result.second.getNode()) { DAG.setRoot(Result.second); - if (DisableScheduling) - DAG.AssignOrdering(Result.second.getNode(), SDNodeOrder); + DAG.AssignOrdering(Result.second.getNode(), SDNodeOrder); } else { HasTailCall = true; } @@ -5391,9 +5152,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, } Chain = P.getValue(1); - - if (DisableScheduling) - DAG.AssignOrdering(P.getNode(), Order); + DAG.AssignOrdering(P.getNode(), Order); // If the source register was virtual and if we know something about it, // add an assert node. @@ -5432,9 +5191,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, if (FromVT != MVT::Other) { P = DAG.getNode(isSExt ? ISD::AssertSext : ISD::AssertZext, dl, RegisterVT, P, DAG.getValueType(FromVT)); - - if (DisableScheduling) - DAG.AssignOrdering(P.getNode(), Order); + DAG.AssignOrdering(P.getNode(), Order); } } } @@ -5444,8 +5201,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, Values[Value] = getCopyFromParts(DAG, dl, Order, Parts.begin(), NumRegs, RegisterVT, ValueVT); - if (DisableScheduling) - DAG.AssignOrdering(Values[Value].getNode(), Order); + DAG.AssignOrdering(Values[Value].getNode(), Order); Part += NumRegs; Parts.clear(); } @@ -5453,8 +5209,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl, DAG.getVTList(&ValueVTs[0], ValueVTs.size()), &Values[0], ValueVTs.size()); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), Order); + DAG.AssignOrdering(Res.getNode(), Order); return Res; } @@ -5491,9 +5246,7 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, } Chains[i] = Part.getValue(0); - - if (DisableScheduling) - DAG.AssignOrdering(Part.getNode(), Order); + DAG.AssignOrdering(Part.getNode(), Order); } if (NumRegs == 1 || Flag) @@ -5511,8 +5264,7 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, else Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Chains[0], NumRegs); - if (DisableScheduling) - DAG.AssignOrdering(Chain.getNode(), Order); + DAG.AssignOrdering(Chain.getNode(), Order); } /// AddInlineAsmOperands - Add this value to the specified inlineasm node @@ -5529,8 +5281,7 @@ void RegsForValue::AddInlineAsmOperands(unsigned Code, SDValue Res = DAG.getTargetConstant(Flag, MVT::i32); Ops.push_back(Res); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), Order); + DAG.AssignOrdering(Res.getNode(), Order); for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) { unsigned NumRegs = TLI->getNumRegisters(*DAG.getContext(), ValueVTs[Value]); @@ -5539,9 +5290,7 @@ void RegsForValue::AddInlineAsmOperands(unsigned Code, assert(Reg < Regs.size() && "Mismatch in # registers expected"); SDValue Res = DAG.getRegister(Regs[Reg++], RegisterVT); Ops.push_back(Res); - - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), Order); + DAG.AssignOrdering(Res.getNode(), Order); } } } @@ -5761,8 +5510,7 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, OpInfo.ConstraintVT = RegVT; } - if (DisableScheduling) - DAG.AssignOrdering(OpInfo.CallOperand.getNode(), SDNodeOrder); + DAG.AssignOrdering(OpInfo.CallOperand.getNode(), SDNodeOrder); } NumRegs = TLI.getNumRegisters(Context, OpInfo.ConstraintVT); @@ -6483,8 +6231,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, "LowerCall emitted a value with the wrong type!"); }); - if (DisableScheduling) - DAG.AssignOrdering(Chain.getNode(), Order); + DAG.AssignOrdering(Chain.getNode(), Order); // For a tail call, the return value is merely live-out and there aren't // any nodes in the DAG representing it. Return a special value to @@ -6513,8 +6260,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, getCopyFromParts(DAG, dl, Order, &InVals[CurReg], NumRegs, RegisterVT, VT, AssertOp); ReturnValues.push_back(ReturnValue); - if (DisableScheduling) - DAG.AssignOrdering(ReturnValue.getNode(), Order); + DAG.AssignOrdering(ReturnValue.getNode(), Order); CurReg += NumRegs; } @@ -6527,8 +6273,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl, DAG.getVTList(&RetTys[0], RetTys.size()), &ReturnValues[0], ReturnValues.size()); - if (DisableScheduling) - DAG.AssignOrdering(Res.getNode(), Order); + DAG.AssignOrdering(Res.getNode(), Order); return std::make_pair(Res, Chain); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 9ac8f83..2bec964 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -144,7 +144,7 @@ namespace llvm { if (TLI.getSchedulingPreference() == TargetLowering::SchedulingForLatency) return createTDListDAGScheduler(IS, OptLevel); assert(TLI.getSchedulingPreference() == - TargetLowering::SchedulingForRegPressure && "Unknown sched type!"); + TargetLowering::SchedulingForRegPressure && "Unknown sched type!"); return createBURRListDAGScheduler(IS, OptLevel); } } @@ -1426,7 +1426,7 @@ void SelectionDAGISel::CannotYetSelect(SDNode *N) { std::string msg; raw_string_ostream Msg(msg); Msg << "Cannot yet select: "; - N->print(Msg, CurDAG); + N->printrFull(Msg, CurDAG); llvm_report_error(Msg.str()); } diff --git a/lib/CodeGen/SlotIndexes.cpp b/lib/CodeGen/SlotIndexes.cpp index b8f529b..a23efb2 100644 --- a/lib/CodeGen/SlotIndexes.cpp +++ b/lib/CodeGen/SlotIndexes.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Target/TargetInstrInfo.h" using namespace llvm; @@ -107,6 +108,8 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) { for (MachineBasicBlock::iterator miItr = mbb->begin(), miEnd = mbb->end(); miItr != miEnd; ++miItr) { MachineInstr *mi = &*miItr; + if (mi->getOpcode()==TargetInstrInfo::DEBUG_VALUE) + continue; if (miItr == mbb->getFirstTerminator()) { push_back(createEntry(0, index)); diff --git a/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp index f51f74d..d6860bc 100644 --- a/lib/CodeGen/TailDuplication.cpp +++ b/lib/CodeGen/TailDuplication.cpp @@ -108,12 +108,8 @@ bool TailDuplicatePass::runOnMachineFunction(MachineFunction &MF) { MMI = getAnalysisIfAvailable<MachineModuleInfo>(); bool MadeChange = false; - bool MadeChangeThisIteration = true; - while (MadeChangeThisIteration) { - MadeChangeThisIteration = false; - MadeChangeThisIteration |= TailDuplicateBlocks(MF); - MadeChange |= MadeChangeThisIteration; - } + while (TailDuplicateBlocks(MF)) + MadeChange = true; return MadeChange; } @@ -437,28 +433,28 @@ bool TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, SmallVector<MachineBasicBlock*, 8> &TDBBs, SmallVector<MachineInstr*, 16> &Copies) { - // Pre-regalloc tail duplication hurts compile time and doesn't help - // much except for indirect branches. - bool hasIndirectBranch = (!TailBB->empty() && - TailBB->back().getDesc().isIndirectBranch()); - if (PreRegAlloc && !hasIndirectBranch) - return false; - // Set the limit on the number of instructions to duplicate, with a default // of one less than the tail-merge threshold. When optimizing for size, // duplicate only one, because one branch instruction can be eliminated to // compensate for the duplication. unsigned MaxDuplicateCount; - if (hasIndirectBranch) + if (MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize)) + MaxDuplicateCount = 1; + else + MaxDuplicateCount = TailDuplicateSize; + + if (PreRegAlloc) { + // Pre-regalloc tail duplication hurts compile time and doesn't help + // much except for indirect branches. + if (TailBB->empty() || !TailBB->back().getDesc().isIndirectBranch()) + return false; // If the target has hardware branch prediction that can handle indirect // branches, duplicating them can often make them predictable when there // are common paths through the code. The limit needs to be high enough - // to allow undoing the effects of tail merging. + // to allow undoing the effects of tail merging and other optimizations + // that rearrange the predecessors of the indirect branch. MaxDuplicateCount = 20; - else if (MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize)) - MaxDuplicateCount = 1; - else - MaxDuplicateCount = TailDuplicateSize; + } // Don't try to tail-duplicate single-block loops. if (TailBB->isSuccessor(TailBB)) diff --git a/lib/ExecutionEngine/Interpreter/Makefile b/lib/ExecutionEngine/Interpreter/Makefile index 5f937c3..4df38ea 100644 --- a/lib/ExecutionEngine/Interpreter/Makefile +++ b/lib/ExecutionEngine/Interpreter/Makefile @@ -6,7 +6,9 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMInterpreter +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index 0f604ac..4dc119d 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -20,6 +20,7 @@ #include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/DerivedTypes.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/CodeGen/JITCodeEmitter.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineConstantPool.h" @@ -368,12 +369,12 @@ namespace { // the stub is unused. DenseMap<void *, SmallPtrSet<const Function*, 1> > StubFnRefs; - DebugLocTuple PrevDLT; + DILocation PrevDLT; public: JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM) : SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0), - EmittedFunctions(this) { + EmittedFunctions(this), PrevDLT(NULL) { MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); if (jit.getJITInfo().needsGOT()) { MemMgr->AllocateGOT(); @@ -806,10 +807,11 @@ void JITEmitter::AddStubToCurrentFunction(void *StubAddr) { void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) { if (!DL.isUnknown()) { - DebugLocTuple CurDLT = EmissionDetails.MF->getDebugLocTuple(DL); + DILocation CurDLT = EmissionDetails.MF->getDILocation(DL); if (BeforePrintingInsn) { - if (CurDLT.Scope != 0 && PrevDLT != CurDLT) { + if (CurDLT.getScope().getNode() != 0 + && PrevDLT.getNode() != CurDLT.getNode()) { JITEvent_EmittedFunctionDetails::LineStart NextLine; NextLine.Address = getCurrentPCValue(); NextLine.Loc = DL; diff --git a/lib/ExecutionEngine/JIT/Makefile b/lib/ExecutionEngine/JIT/Makefile index e2c9c61..1c93c06 100644 --- a/lib/ExecutionEngine/JIT/Makefile +++ b/lib/ExecutionEngine/JIT/Makefile @@ -6,8 +6,10 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMJIT +CXXFLAGS = -fno-rtti # Get the $(ARCH) setting include $(LEVEL)/Makefile.config diff --git a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp index d01c4b2..2baf979 100644 --- a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp +++ b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp @@ -18,10 +18,12 @@ #define DEBUG_TYPE "oprofile-jit-event-listener" #include "llvm/Function.h" +#include "llvm/Metadata.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Errno.h" #include "llvm/Config/config.h" @@ -70,15 +72,15 @@ OProfileJITEventListener::~OProfileJITEventListener() { class FilenameCache { // Holds the filename of each Scope, so that we can pass a null-terminated - // string into oprofile. - DenseMap<MDNode*, std::string> Filenames; + // string into oprofile. Use an AssertingVH rather than a ValueMap because we + // shouldn't be modifying any MDNodes while this map is alive. + DenseMap<AssertingVH<MDNode>, std::string> Filenames; public: - const char *getFilename(MDNode *Scope) { - std::string &Filename = Filenames[Scope]; + const char *getFilename(DIScope Scope) { + std::string &Filename = Filenames[Scope.getNode()]; if (Filename.empty()) { - DIScope S(Scope); - Filename = S.getFilename(); + Filename = Scope.getFilename(); } return Filename.c_str(); } @@ -89,9 +91,9 @@ static debug_line_info LineStartToOProfileFormat( uintptr_t Address, DebugLoc Loc) { debug_line_info Result; Result.vma = Address; - const DebugLocTuple &tuple = MF.getDebugLocTuple(Loc); - Result.lineno = tuple.Line; - Result.filename = Filenames.getFilename(tuple.Scope); + DILocation DILoc = MF.getDILocation(Loc); + Result.lineno = DILoc.getLineNumber(); + Result.filename = Filenames.getFilename(DILoc.getScope()); DEBUG(dbgs() << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to " << Result.filename << ":" << Result.lineno << "\n"); return Result; diff --git a/lib/ExecutionEngine/Makefile b/lib/ExecutionEngine/Makefile index e0e050e..2387b0e 100644 --- a/lib/ExecutionEngine/Makefile +++ b/lib/ExecutionEngine/Makefile @@ -9,5 +9,6 @@ LEVEL = ../.. LIBRARYNAME = LLVMExecutionEngine PARALLEL_DIRS = Interpreter JIT +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index dcd696c..e2cd47a 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -392,7 +392,7 @@ static Value *RemapOperand(const Value *In, assert(!isa<GlobalValue>(CPV) && "Unmapped global?"); llvm_unreachable("Unknown type of derived type constant value!"); } - } else if (isa<MetadataBase>(In)) { + } else if (isa<MDNode>(In) || isa<MDString>(In)) { Result = const_cast<Value*>(In); } else if (isa<InlineAsm>(In)) { Result = const_cast<Value*>(In); diff --git a/lib/Linker/Makefile b/lib/Linker/Makefile index 19e646b..2179fd2 100644 --- a/lib/Linker/Makefile +++ b/lib/Linker/Makefile @@ -10,6 +10,7 @@ LEVEL = ../.. LIBRARYNAME = LLVMLinker BUILD_ARCHIVE := 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index 8a1a058..9ead33b 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -2,8 +2,6 @@ add_llvm_library(LLVMMC MCAsmInfo.cpp MCAsmInfoCOFF.cpp MCAsmInfoDarwin.cpp - MCAsmLexer.cpp - MCAsmParser.cpp MCAsmStreamer.cpp MCAssembler.cpp MCCodeEmitter.cpp @@ -20,5 +18,4 @@ add_llvm_library(LLVMMC MCStreamer.cpp MCSymbol.cpp MCValue.cpp - TargetAsmParser.cpp ) diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index 3e5c97d..547f904 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -19,8 +19,9 @@ using namespace llvm; MCAsmInfo::MCAsmInfo() { - ZeroFillDirective = 0; - NonexecutableStackDirective = 0; + HasSubsectionsViaSymbols = false; + HasMachoZeroFillDirective = false; + HasStaticCtorDtorReferenceInStaticMode = false; NeedsSet = false; MaxInstLength = 4; PCSymbol = "$"; @@ -36,7 +37,6 @@ MCAsmInfo::MCAsmInfo() { AllowQuotesInName = false; AllowNameToStartWithDigit = false; ZeroDirective = "\t.zero\t"; - ZeroDirectiveSuffix = 0; AsciiDirective = "\t.ascii\t"; AscizDirective = "\t.asciz\t"; Data8bitsDirective = "\t.byte\t"; @@ -52,17 +52,16 @@ MCAsmInfo::MCAsmInfo() { PICJumpTableDirective = 0; GlobalDirective = "\t.globl\t"; SetDirective = 0; - LCOMMDirective = 0; - COMMDirective = "\t.comm\t"; + HasLCOMMDirective = false; COMMDirectiveTakesAlignment = true; HasDotTypeDotSizeDirective = true; HasSingleParameterDotFile = true; - UsedDirective = 0; + HasNoDeadStrip = false; WeakRefDirective = 0; WeakDefDirective = 0; - // FIXME: These are ELFish - move to ELFMAI. - HiddenDirective = "\t.hidden\t"; - ProtectedDirective = "\t.protected\t"; + LinkOnceDirective = 0; + HiddenVisibilityAttr = MCSA_Hidden; + ProtectedVisibilityAttr = MCSA_Protected; AbsoluteDebugSectionOffsets = false; AbsoluteEHSectionOffsets = false; HasLEB128 = false; diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index 23b0dd7..e395acd 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/lib/MC/MCAsmInfoCOFF.cpp @@ -18,14 +18,17 @@ using namespace llvm; MCAsmInfoCOFF::MCAsmInfoCOFF() { GlobalPrefix = "_"; - LCOMMDirective = "\t.lcomm\t"; + HasLCOMMDirective = true; COMMDirectiveTakesAlignment = false; HasDotTypeDotSizeDirective = false; HasSingleParameterDotFile = false; - HiddenDirective = NULL; PrivateGlobalPrefix = "L"; // Prefix for private global symbols WeakRefDirective = "\t.weak\t"; + LinkOnceDirective = "\t.linkonce same_size\n"; SetDirective = "\t.set\t"; + + // Doesn't support visibility: + HiddenVisibilityAttr = ProtectedVisibilityAttr = MCSA_Invalid; // Set up DWARF directives HasLEB128 = true; // Target asm supports leb128 directives (little-endian) diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index d99120d..9902f50 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/lib/MC/MCAsmInfoDarwin.cpp @@ -24,6 +24,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { NeedsSet = true; AllowQuotesInName = true; HasSingleParameterDotFile = false; + HasSubsectionsViaSymbols = true; AlignmentIsInBytes = false; InlineAsmStart = " InlineAsm Start"; @@ -32,14 +33,20 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { // Directives: WeakDefDirective = "\t.weak_definition "; WeakRefDirective = "\t.weak_reference "; - HiddenDirective = "\t.private_extern "; - LCOMMDirective = "\t.lcomm\t"; ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. - ZeroFillDirective = "\t.zerofill\t"; // Uses .zerofill + HasMachoZeroFillDirective = true; // Uses .zerofill + HasStaticCtorDtorReferenceInStaticMode = true; SetDirective = "\t.set"; - ProtectedDirective = "\t.globl\t"; + + HiddenVisibilityAttr = MCSA_PrivateExtern; + // Doesn't support protected visibility. + ProtectedVisibilityAttr = MCSA_Global; + + HasDotTypeDotSizeDirective = false; - UsedDirective = "\t.no_dead_strip\t"; + HasNoDeadStrip = true; + // Note: Even though darwin has the .lcomm directive, it is just a synonym for + // zerofill, so we prefer to use .zerofill. // _foo.eh symbols are currently always exported so that the linker knows // about them. This is not necessary on 10.6 and later, but it diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index b6ebb1a..bf39239 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCStreamer.h" -#include "llvm/ADT/SmallString.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" @@ -17,26 +16,68 @@ #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/FormattedStream.h" using namespace llvm; namespace { class MCAsmStreamer : public MCStreamer { - raw_ostream &OS; + formatted_raw_ostream &OS; const MCAsmInfo &MAI; + bool IsLittleEndian, IsVerboseAsm; MCInstPrinter *InstPrinter; MCCodeEmitter *Emitter; + + SmallString<128> CommentToEmit; + raw_svector_ostream CommentStream; public: - MCAsmStreamer(MCContext &Context, raw_ostream &_OS, const MCAsmInfo &tai, - MCInstPrinter *_Printer, MCCodeEmitter *_Emitter) - : MCStreamer(Context), OS(_OS), MAI(tai), InstPrinter(_Printer), - Emitter(_Emitter) {} + MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, + const MCAsmInfo &mai, + bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *printer, + MCCodeEmitter *emitter) + : MCStreamer(Context), OS(os), MAI(mai), IsLittleEndian(isLittleEndian), + IsVerboseAsm(isVerboseAsm), InstPrinter(printer), Emitter(emitter), + CommentStream(CommentToEmit) {} ~MCAsmStreamer() {} + bool isLittleEndian() const { return IsLittleEndian; } + + + inline void EmitEOL() { + // If we don't have any comments, just emit a \n. + if (!IsVerboseAsm) { + OS << '\n'; + return; + } + EmitCommentsAndEOL(); + } + void EmitCommentsAndEOL(); + + /// AddComment - Add a comment that can be emitted to the generated .s + /// file if applicable as a QoI issue to make the output of the compiler + /// more readable. This only affects the MCAsmStreamer, and only when + /// verbose assembly output is enabled. + virtual void AddComment(const Twine &T); + + /// GetCommentOS - Return a raw_ostream that comments can be written to. + /// Unlike AddComment, you are required to terminate comments with \n if you + /// use this method. + virtual raw_ostream &GetCommentOS() { + if (!IsVerboseAsm) + return nulls(); // Discard comments unless in verbose asm mode. + return CommentStream; + } + + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. + virtual void AddBlankLine() { + EmitEOL(); + } + /// @name MCStreamer Interface /// @{ @@ -44,23 +85,33 @@ public: virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitAssemblerFlag(AssemblerFlag Flag); + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); - virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); + /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, unsigned Size = 0, unsigned ByteAlignment = 0); - virtual void EmitBytes(StringRef Data); + virtual void EmitBytes(StringRef Data, unsigned AddrSpace); - virtual void EmitValue(const MCExpr *Value, unsigned Size); + virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); + virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace); + + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, + unsigned AddrSpace); virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, @@ -78,6 +129,50 @@ public: } // end anonymous namespace. +/// AddComment - Add a comment that can be emitted to the generated .s +/// file if applicable as a QoI issue to make the output of the compiler +/// more readable. This only affects the MCAsmStreamer, and only when +/// verbose assembly output is enabled. +void MCAsmStreamer::AddComment(const Twine &T) { + if (!IsVerboseAsm) return; + + // Make sure that CommentStream is flushed. + CommentStream.flush(); + + T.toVector(CommentToEmit); + // Each comment goes on its own line. + CommentToEmit.push_back('\n'); + + // Tell the comment stream that the vector changed underneath it. + CommentStream.resync(); +} + +void MCAsmStreamer::EmitCommentsAndEOL() { + if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { + OS << '\n'; + return; + } + + CommentStream.flush(); + StringRef Comments = CommentToEmit.str(); + + assert(Comments.back() == '\n' && + "Comment array not newline terminated"); + do { + // Emit a line of comments. + OS.PadToColumn(MAI.getCommentColumn()); + size_t Position = Comments.find('\n'); + OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n'; + + Comments = Comments.substr(Position+1); + } while (!Comments.empty()); + + CommentToEmit.clear(); + // Tell the comment stream that the vector changed underneath it. + CommentStream.resync(); +} + + static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { assert(Bytes && "Invalid size!"); return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); @@ -101,17 +196,17 @@ void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); assert(CurSection && "Cannot emit before setting section!"); - Symbol->print(OS, &MAI); - OS << ":\n"; + OS << *Symbol << ":"; + EmitEOL(); Symbol->setSection(*CurSection); } -void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { +void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { switch (Flag) { default: assert(0 && "Invalid flag!"); - case SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; + case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; } - OS << '\n'; + EmitEOL(); } void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { @@ -119,10 +214,8 @@ void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { assert((Symbol->isUndefined() || Symbol->isAbsolute()) && "Cannot define a symbol twice!"); - Symbol->print(OS, &MAI); - OS << " = "; - Value->print(OS, &MAI); - OS << '\n'; + OS << *Symbol << " = " << *Value; + EmitEOL(); // FIXME: Lift context changes into super class. // FIXME: Set associated section. @@ -130,41 +223,54 @@ void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { } void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, - SymbolAttr Attribute) { + MCSymbolAttr Attribute) { switch (Attribute) { - case Global: OS << ".globl"; break; - case Hidden: OS << ".hidden"; break; - case IndirectSymbol: OS << ".indirect_symbol"; break; - case Internal: OS << ".internal"; break; - case LazyReference: OS << ".lazy_reference"; break; - case NoDeadStrip: OS << ".no_dead_strip"; break; - case PrivateExtern: OS << ".private_extern"; break; - case Protected: OS << ".protected"; break; - case Reference: OS << ".reference"; break; - case Weak: OS << ".weak"; break; - case WeakDefinition: OS << ".weak_definition"; break; - case WeakReference: OS << ".weak_reference"; break; + case MCSA_Invalid: assert(0 && "Invalid symbol attribute"); + case MCSA_Global: OS << MAI.getGlobalDirective(); break; // .globl + case MCSA_Hidden: OS << ".hidden "; break; + case MCSA_IndirectSymbol: OS << ".indirect_symbol "; break; + case MCSA_Internal: OS << ".internal "; break; + case MCSA_LazyReference: OS << ".lazy_reference "; break; + case MCSA_Local: OS << ".local "; break; + case MCSA_NoDeadStrip: OS << ".no_dead_strip "; break; + case MCSA_PrivateExtern: OS << ".private_extern "; break; + case MCSA_Protected: OS << ".protected "; break; + case MCSA_Reference: OS << ".reference "; break; + case MCSA_Weak: OS << ".weak "; break; + case MCSA_WeakDefinition: OS << ".weak_definition "; break; + // .weak_reference + case MCSA_WeakReference: OS << MAI.getWeakRefDirective(); break; } - OS << ' '; - Symbol->print(OS, &MAI); - OS << '\n'; + OS << *Symbol; + EmitEOL(); } void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - OS << ".desc" << ' '; - Symbol->print(OS, &MAI); - OS << ',' << DescValue << '\n'; + OS << ".desc" << ' ' << *Symbol << ',' << DescValue; + EmitEOL(); } -void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, +void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { - OS << ".comm "; - Symbol->print(OS, &MAI); - OS << ',' << Size; - if (ByteAlignment != 0) - OS << ',' << Log2_32(ByteAlignment); - OS << '\n'; + OS << "\t.comm\t" << *Symbol << ',' << Size; + if (ByteAlignment != 0 && MAI.getCOMMDirectiveTakesAlignment()) { + if (MAI.getAlignmentIsInBytes()) + OS << ',' << ByteAlignment; + else + OS << ',' << Log2_32(ByteAlignment); + } + EmitEOL(); +} + +/// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. +/// +/// @param Symbol - The common symbol to emit. +/// @param Size - The size of the common symbol. +void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + assert(MAI.hasLCOMMDirective() && "Doesn't have .lcomm, can't emit it!"); + OS << "\t.lcomm\t" << *Symbol << ',' << Size; + EmitEOL(); } void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, @@ -177,36 +283,130 @@ void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); if (Symbol != NULL) { - OS << ','; - Symbol->print(OS, &MAI); - OS << ',' << Size; + OS << ',' << *Symbol << ',' << Size; if (ByteAlignment != 0) OS << ',' << Log2_32(ByteAlignment); } - OS << '\n'; + EmitEOL(); +} + +static inline char toOctal(int X) { return (X&7)+'0'; } + +void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { + assert(CurSection && "Cannot emit contents before setting section!"); + if (Data.empty()) return; + + if (Data.size() == 1) { + OS << MAI.getData8bitsDirective(AddrSpace); + OS << (unsigned)(unsigned char)Data[0]; + EmitEOL(); + return; + } + + // If the data ends with 0 and the target supports .asciz, use it, otherwise + // use .ascii + if (MAI.getAscizDirective() && Data.back() == 0) { + OS << MAI.getAscizDirective(); + Data = Data.substr(0, Data.size()-1); + } else { + OS << MAI.getAsciiDirective(); + } + + OS << " \""; + for (unsigned i = 0, e = Data.size(); i != e; ++i) { + unsigned char C = Data[i]; + if (C == '"' || C == '\\') { + OS << '\\' << (char)C; + continue; + } + + if (isprint((unsigned char)C)) { + OS << (char)C; + continue; + } + + switch (C) { + case '\b': OS << "\\b"; break; + case '\f': OS << "\\f"; break; + case '\n': OS << "\\n"; break; + case '\r': OS << "\\r"; break; + case '\t': OS << "\\t"; break; + default: + OS << '\\'; + OS << toOctal(C >> 6); + OS << toOctal(C >> 3); + OS << toOctal(C >> 0); + break; + } + } + OS << '"'; + EmitEOL(); } -void MCAsmStreamer::EmitBytes(StringRef Data) { +/// EmitIntValue - Special case of EmitValue that avoids the client having +/// to pass in a MCExpr for constant integers. +void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, + unsigned AddrSpace) { assert(CurSection && "Cannot emit contents before setting section!"); - for (unsigned i = 0, e = Data.size(); i != e; ++i) - OS << ".byte " << (unsigned) (unsigned char) Data[i] << '\n'; + const char *Directive = 0; + switch (Size) { + default: break; + case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break; + case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break; + case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break; + case 8: + Directive = MAI.getData64bitsDirective(AddrSpace); + // If the target doesn't support 64-bit data, emit as two 32-bit halves. + if (Directive) break; + if (isLittleEndian()) { + EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace); + EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace); + } else { + EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace); + EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace); + } + return; + } + + assert(Directive && "Invalid size for machine code value!"); + OS << Directive << truncateToSize(Value, Size); + EmitEOL(); } -void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size) { +void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) { assert(CurSection && "Cannot emit contents before setting section!"); - // Need target hooks to know how to print this. + const char *Directive = 0; switch (Size) { - default: - llvm_unreachable("Invalid size for machine code value!"); - case 1: OS << ".byte"; break; - case 2: OS << ".short"; break; - case 4: OS << ".long"; break; - case 8: OS << ".quad"; break; + default: break; + case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break; + case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break; + case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break; + case 8: Directive = MAI.getData64bitsDirective(AddrSpace); break; } + + assert(Directive && "Invalid size for machine code value!"); + OS << Directive << *truncateToSize(Value, Size); + EmitEOL(); +} + +/// EmitFill - Emit NumBytes bytes worth of the value specified by +/// FillValue. This implements directives such as '.space'. +void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, + unsigned AddrSpace) { + if (NumBytes == 0) return; + + if (AddrSpace == 0) + if (const char *ZeroDirective = MAI.getZeroDirective()) { + OS << ZeroDirective << NumBytes; + if (FillValue != 0) + OS << ',' << (int)FillValue; + EmitEOL(); + return; + } - OS << ' '; - truncateToSize(Value, Size)->print(OS, &MAI); - OS << '\n'; + // Emit a byte at a time. + MCStreamer::EmitFill(NumBytes, FillValue, AddrSpace); } void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, @@ -236,7 +436,7 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, if (MaxBytesToEmit) OS << ", " << MaxBytesToEmit; } - OS << '\n'; + EmitEOL(); return; } @@ -254,15 +454,14 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, OS << ", " << truncateToSize(Value, ValueSize); if (MaxBytesToEmit) OS << ", " << MaxBytesToEmit; - OS << '\n'; + EmitEOL(); } void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset, unsigned char Value) { // FIXME: Verify that Offset is associated with the current section. - OS << ".org "; - Offset->print(OS, &MAI); - OS << ", " << (unsigned) Value << '\n'; + OS << ".org " << *Offset << ", " << (unsigned) Value; + EmitEOL(); } void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { @@ -271,7 +470,7 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { // If we have an AsmPrinter, use that to print. if (InstPrinter) { InstPrinter->printInst(&Inst); - OS << '\n'; + EmitEOL(); // Show the encoding if we have a code emitter. if (Emitter) { @@ -296,15 +495,18 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { // Otherwise fall back to a structural printing for now. Eventually we should // always have access to the target specific printer. Inst.print(OS, &MAI); - OS << '\n'; + EmitEOL(); } void MCAsmStreamer::Finish() { OS.flush(); } -MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS, - const MCAsmInfo &MAI, MCInstPrinter *IP, +MCStreamer *llvm::createAsmStreamer(MCContext &Context, + formatted_raw_ostream &OS, + const MCAsmInfo &MAI, bool isLittleEndian, + bool isVerboseAsm, MCInstPrinter *IP, MCCodeEmitter *CE) { - return new MCAsmStreamer(Context, OS, MAI, IP, CE); + return new MCAsmStreamer(Context, OS, MAI, isLittleEndian, isVerboseAsm, + IP, CE); } diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 1f5b6f1..f0f5a47 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -679,8 +679,6 @@ public: UndefinedSymbolData[i].SymbolData->setIndex(Index++); // The string table is padded to a multiple of 4. - // - // FIXME: Check to see if this varies per arch. while (StringTable.size() % 4) StringTable += '\x00'; } diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index a19ec19..1ee1b1b 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -15,7 +15,7 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; -void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { +void MCExpr::print(raw_ostream &OS) const { switch (getKind()) { case MCExpr::Constant: OS << cast<MCConstantExpr>(*this).getValue(); @@ -26,13 +26,10 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { // Parenthesize names that start with $ so that they don't look like // absolute names. - if (Sym.getName()[0] == '$') { - OS << '('; - Sym.print(OS, MAI); - OS << ')'; - } else { - Sym.print(OS, MAI); - } + if (Sym.getName()[0] == '$') + OS << '(' << Sym << ')'; + else + OS << Sym; return; } @@ -45,7 +42,7 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { case MCUnaryExpr::Not: OS << '~'; break; case MCUnaryExpr::Plus: OS << '+'; break; } - UE.getSubExpr()->print(OS, MAI); + OS << *UE.getSubExpr(); return; } @@ -54,11 +51,9 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { // Only print parens around the LHS if it is non-trivial. if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) { - BE.getLHS()->print(OS, MAI); + OS << *BE.getLHS(); } else { - OS << '('; - BE.getLHS()->print(OS, MAI); - OS << ')'; + OS << '(' << *BE.getLHS() << ')'; } switch (BE.getOpcode()) { @@ -95,11 +90,9 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { // Only print parens around the LHS if it is non-trivial. if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) { - BE.getRHS()->print(OS, MAI); + OS << *BE.getRHS(); } else { - OS << '('; - BE.getRHS()->print(OS, MAI); - OS << ')'; + OS << '(' << *BE.getRHS() << ')'; } return; } @@ -109,7 +102,7 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { } void MCExpr::dump() const { - print(dbgs(), 0); + print(dbgs()); dbgs() << '\n'; } diff --git a/lib/MC/MCInst.cpp b/lib/MC/MCInst.cpp index 7c7a644..0634c9f 100644 --- a/lib/MC/MCInst.cpp +++ b/lib/MC/MCInst.cpp @@ -23,9 +23,7 @@ void MCOperand::print(raw_ostream &OS, const MCAsmInfo *MAI) const { else if (isImm()) OS << "Imm:" << getImm(); else if (isExpr()) { - OS << "Expr:("; - getExpr()->print(OS, MAI); - OS << ")"; + OS << "Expr:(" << *getExpr() << ")"; } else OS << "UNDEFINED"; OS << ">"; diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 828b92a..e559c65 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -117,36 +117,26 @@ public: /// @{ virtual void SwitchSection(const MCSection *Section); - virtual void EmitLabel(MCSymbol *Symbol); - - virtual void EmitAssemblerFlag(AssemblerFlag Flag); - + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - - virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); - + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); - - virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); - + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + assert(0 && "macho doesn't support this directive"); + } virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, unsigned Size = 0, unsigned ByteAlignment = 0); - - virtual void EmitBytes(StringRef Data); - - virtual void EmitValue(const MCExpr *Value, unsigned Size); - + virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, unsigned MaxBytesToEmit = 0); - virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value = 0); - virtual void EmitInstruction(const MCInst &Inst); - virtual void Finish(); /// @} @@ -183,9 +173,9 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { Symbol->setSection(*CurSection); } -void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { +void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { switch (Flag) { - case SubsectionsViaSymbols: + case MCAF_SubsectionsViaSymbols: Assembler.setSubsectionsViaSymbols(true); return; } @@ -204,10 +194,10 @@ void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { } void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, - SymbolAttr Attribute) { + MCSymbolAttr Attribute) { // Indirect symbols are handled differently, to match how 'as' handles // them. This makes writing matching .o files easier. - if (Attribute == MCStreamer::IndirectSymbol) { + if (Attribute == MCSA_IndirectSymbol) { // Note that we intentionally cannot use the symbol data here; this is // important for matching the string table that 'as' generates. IndirectSymbolData ISD; @@ -229,19 +219,21 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, // In the future it might be worth trying to make these operations more well // defined. switch (Attribute) { - case MCStreamer::IndirectSymbol: - case MCStreamer::Hidden: - case MCStreamer::Internal: - case MCStreamer::Protected: - case MCStreamer::Weak: + case MCSA_Invalid: + case MCSA_IndirectSymbol: + case MCSA_Hidden: + case MCSA_Internal: + case MCSA_Protected: + case MCSA_Weak: + case MCSA_Local: assert(0 && "Invalid symbol attribute for Mach-O!"); break; - case MCStreamer::Global: + case MCSA_Global: SD.setExternal(true); break; - case MCStreamer::LazyReference: + case MCSA_LazyReference: // FIXME: This requires -dynamic. SD.setFlags(SD.getFlags() | SF_NoDeadStrip); if (Symbol->isUndefined()) @@ -250,23 +242,23 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, // Since .reference sets the no dead strip bit, it is equivalent to // .no_dead_strip in practice. - case MCStreamer::Reference: - case MCStreamer::NoDeadStrip: + case MCSA_Reference: + case MCSA_NoDeadStrip: SD.setFlags(SD.getFlags() | SF_NoDeadStrip); break; - case MCStreamer::PrivateExtern: + case MCSA_PrivateExtern: SD.setExternal(true); SD.setPrivateExtern(true); break; - case MCStreamer::WeakReference: + case MCSA_WeakReference: // FIXME: This requires -dynamic. if (Symbol->isUndefined()) SD.setFlags(SD.getFlags() | SF_WeakReference); break; - case MCStreamer::WeakDefinition: + case MCSA_WeakDefinition: // FIXME: 'as' enforces that this is defined and global. The manual claims // it has to be in a coalesced section, but this isn't enforced. SD.setFlags(SD.getFlags() | SF_WeakDefinition); @@ -281,7 +273,7 @@ void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { getSymbolData(*Symbol).setFlags(DescValue & SF_DescFlagsMask); } -void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, +void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself. assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); @@ -315,14 +307,15 @@ void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, SectData.setAlignment(ByteAlignment); } -void MCMachOStreamer::EmitBytes(StringRef Data) { +void MCMachOStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); if (!DF) DF = new MCDataFragment(CurSectionData); DF->getContents().append(Data.begin(), Data.end()); } -void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size) { +void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) { new MCFillFragment(*AddValueSymbols(Value), Size, 1, CurSectionData); } @@ -353,11 +346,13 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { if (!Emitter) llvm_unreachable("no code emitter available!"); + // FIXME: Emitting an instruction should cause S_ATTR_SOME_INSTRUCTIONS to + // be set for the current section. // FIXME: Relocations! SmallString<256> Code; raw_svector_ostream VecOS(Code); Emitter->EncodeInstruction(Inst, VecOS); - EmitBytes(VecOS.str()); + EmitBytes(VecOS.str(), 0); } void MCMachOStreamer::Finish() { diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index ddc4e69..7c219b3 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -31,23 +31,25 @@ namespace { virtual void EmitLabel(MCSymbol *Symbol) {} - virtual void EmitAssemblerFlag(AssemblerFlag Flag) {} + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} - virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute) {} + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute){} virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} - virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) {} + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {} virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, unsigned Size = 0, unsigned ByteAlignment = 0) {} - virtual void EmitBytes(StringRef Data) {} + virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {} - virtual void EmitValue(const MCExpr *Value, unsigned Size) {} + virtual void EmitValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) {} virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp new file mode 100644 index 0000000..482eefd --- /dev/null +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -0,0 +1,320 @@ +//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements the lexer for assembly files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/AsmLexer.h" +#include "llvm/Support/SMLoc.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/MC/MCAsmInfo.h" +#include <cerrno> +#include <cstdio> +#include <cstdlib> +using namespace llvm; + +AsmLexer::AsmLexer(const MCAsmInfo &_MAI) : MAI(_MAI) { + CurBuf = NULL; + CurPtr = NULL; + TokStart = 0; +} + +AsmLexer::~AsmLexer() { +} + +void AsmLexer::setBuffer(const MemoryBuffer *buf, const char *ptr) { + CurBuf = buf; + + if (ptr) + CurPtr = ptr; + else + CurPtr = CurBuf->getBufferStart(); + + TokStart = 0; +} + +SMLoc AsmLexer::getLoc() const { + return SMLoc::getFromPointer(TokStart); +} + +/// ReturnError - Set the error to the specified string at the specified +/// location. This is defined to always return AsmToken::Error. +AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) { + SetError(SMLoc::getFromPointer(Loc), Msg); + + return AsmToken(AsmToken::Error, StringRef(Loc, 0)); +} + +int AsmLexer::getNextChar() { + char CurChar = *CurPtr++; + switch (CurChar) { + default: + return (unsigned char)CurChar; + case 0: + // A nul character in the stream is either the end of the current buffer or + // a random nul in the file. Disambiguate that here. + if (CurPtr-1 != CurBuf->getBufferEnd()) + return 0; // Just whitespace. + + // Otherwise, return end of file. + --CurPtr; // Another call to lex will return EOF again. + return EOF; + } +} + +/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* +AsmToken AsmLexer::LexIdentifier() { + while (isalnum(*CurPtr) || *CurPtr == '_' || *CurPtr == '$' || + *CurPtr == '.' || *CurPtr == '@') + ++CurPtr; + return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart)); +} + +/// LexSlash: Slash: / +/// C-Style Comment: /* ... */ +AsmToken AsmLexer::LexSlash() { + switch (*CurPtr) { + case '*': break; // C style comment. + case '/': return ++CurPtr, LexLineComment(); + default: return AsmToken(AsmToken::Slash, StringRef(CurPtr, 1)); + } + + // C Style comment. + ++CurPtr; // skip the star. + while (1) { + int CurChar = getNextChar(); + switch (CurChar) { + case EOF: + return ReturnError(TokStart, "unterminated comment"); + case '*': + // End of the comment? + if (CurPtr[0] != '/') break; + + ++CurPtr; // End the */. + return LexToken(); + } + } +} + +/// LexLineComment: Comment: #[^\n]* +/// : //[^\n]* +AsmToken AsmLexer::LexLineComment() { + // FIXME: This is broken if we happen to a comment at the end of a file, which + // was .included, and which doesn't end with a newline. + int CurChar = getNextChar(); + while (CurChar != '\n' && CurChar != '\n' && CurChar != EOF) + CurChar = getNextChar(); + + if (CurChar == EOF) + return AsmToken(AsmToken::Eof, StringRef(CurPtr, 0)); + return AsmToken(AsmToken::EndOfStatement, StringRef(CurPtr, 0)); +} + + +/// LexDigit: First character is [0-9]. +/// Local Label: [0-9][:] +/// Forward/Backward Label: [0-9][fb] +/// Binary integer: 0b[01]+ +/// Octal integer: 0[0-7]+ +/// Hex integer: 0x[0-9a-fA-F]+ +/// Decimal integer: [1-9][0-9]* +/// TODO: FP literal. +AsmToken AsmLexer::LexDigit() { + if (*CurPtr == ':') + return ReturnError(TokStart, "FIXME: local label not implemented"); + if (*CurPtr == 'f' || *CurPtr == 'b') + return ReturnError(TokStart, "FIXME: directional label not implemented"); + + // Decimal integer: [1-9][0-9]* + if (CurPtr[-1] != '0') { + while (isdigit(*CurPtr)) + ++CurPtr; + + StringRef Result(TokStart, CurPtr - TokStart); + + long long Value; + if (Result.getAsInteger(10, Value)) + return ReturnError(TokStart, "Invalid decimal number"); + return AsmToken(AsmToken::Integer, Result, Value); + } + + if (*CurPtr == 'b') { + ++CurPtr; + const char *NumStart = CurPtr; + while (CurPtr[0] == '0' || CurPtr[0] == '1') + ++CurPtr; + + // Requires at least one binary digit. + if (CurPtr == NumStart) + return ReturnError(TokStart, "Invalid binary number"); + + StringRef Result(TokStart, CurPtr - TokStart); + + long long Value; + if (Result.getAsInteger(2, Value)) + return ReturnError(TokStart, "Invalid binary number"); + + return AsmToken(AsmToken::Integer, Result, Value); + } + + if (*CurPtr == 'x') { + ++CurPtr; + const char *NumStart = CurPtr; + while (isxdigit(CurPtr[0])) + ++CurPtr; + + // Requires at least one hex digit. + if (CurPtr == NumStart) + return ReturnError(CurPtr-2, "Invalid hexadecimal number"); + + unsigned long long Result; + if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result)) + return ReturnError(TokStart, "Invalid hexadecimal number"); + + return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart), + (int64_t)Result); + } + + // Must be an octal number, it starts with 0. + while (*CurPtr >= '0' && *CurPtr <= '7') + ++CurPtr; + + StringRef Result(TokStart, CurPtr - TokStart); + long long Value; + if (Result.getAsInteger(8, Value)) + return ReturnError(TokStart, "Invalid octal number"); + + return AsmToken(AsmToken::Integer, Result, Value); +} + +/// LexQuote: String: "..." +AsmToken AsmLexer::LexQuote() { + int CurChar = getNextChar(); + // TODO: does gas allow multiline string constants? + while (CurChar != '"') { + if (CurChar == '\\') { + // Allow \", etc. + CurChar = getNextChar(); + } + + if (CurChar == EOF) + return ReturnError(TokStart, "unterminated string constant"); + + CurChar = getNextChar(); + } + + return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart)); +} + +StringRef AsmLexer::LexUntilEndOfStatement() { + TokStart = CurPtr; + + while (!isAtStartOfComment(*CurPtr) && // Start of line comment. + *CurPtr != ';' && // End of statement marker. + *CurPtr != '\n' && + *CurPtr != '\r' && + (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) { + ++CurPtr; + } + return StringRef(TokStart, CurPtr-TokStart); +} + +bool AsmLexer::isAtStartOfComment(char Char) { + // FIXME: This won't work for multi-character comment indicators like "//". + return Char == *MAI.getCommentString(); +} + +AsmToken AsmLexer::LexToken() { + TokStart = CurPtr; + // This always consumes at least one character. + int CurChar = getNextChar(); + + if (isAtStartOfComment(CurChar)) + return LexLineComment(); + + switch (CurChar) { + default: + // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* + if (isalpha(CurChar) || CurChar == '_' || CurChar == '.') + return LexIdentifier(); + + // Unknown character, emit an error. + return ReturnError(TokStart, "invalid character in input"); + case EOF: return AsmToken(AsmToken::Eof, StringRef(TokStart, 0)); + case 0: + case ' ': + case '\t': + // Ignore whitespace. + return LexToken(); + case '\n': // FALL THROUGH. + case '\r': // FALL THROUGH. + case ';': return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); + case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1)); + case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1)); + case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1)); + case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1)); + case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1)); + case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1)); + case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1)); + case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1)); + case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1)); + case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1)); + case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1)); + case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1)); + case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1)); + case '=': + if (*CurPtr == '=') + return ++CurPtr, AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2)); + return AsmToken(AsmToken::Equal, StringRef(TokStart, 1)); + case '|': + if (*CurPtr == '|') + return ++CurPtr, AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2)); + return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1)); + case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1)); + case '&': + if (*CurPtr == '&') + return ++CurPtr, AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2)); + return AsmToken(AsmToken::Amp, StringRef(TokStart, 1)); + case '!': + if (*CurPtr == '=') + return ++CurPtr, AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2)); + return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1)); + case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1)); + case '/': return LexSlash(); + case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1)); + case '"': return LexQuote(); + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return LexDigit(); + case '<': + switch (*CurPtr) { + case '<': return ++CurPtr, AsmToken(AsmToken::LessLess, + StringRef(TokStart, 2)); + case '=': return ++CurPtr, AsmToken(AsmToken::LessEqual, + StringRef(TokStart, 2)); + case '>': return ++CurPtr, AsmToken(AsmToken::LessGreater, + StringRef(TokStart, 2)); + default: return AsmToken(AsmToken::Less, StringRef(TokStart, 1)); + } + case '>': + switch (*CurPtr) { + case '>': return ++CurPtr, AsmToken(AsmToken::GreaterGreater, + StringRef(TokStart, 2)); + case '=': return ++CurPtr, AsmToken(AsmToken::GreaterEqual, + StringRef(TokStart, 2)); + default: return AsmToken(AsmToken::Greater, StringRef(TokStart, 1)); + } + + // TODO: Quoted identifiers (objc methods etc) + // local labels: [0-9][:] + // Forward/backward labels: [0-9][fb] + // Integers, fp constants, character constants. + } +} diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp new file mode 100644 index 0000000..dd438b7 --- /dev/null +++ b/lib/MC/MCParser/AsmParser.cpp @@ -0,0 +1,1781 @@ +//===- AsmParser.cpp - Parser for Assembly Files --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements the parser for assembly files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/AsmParser.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmParser.h" +using namespace llvm; + + +enum { DEFAULT_ADDRSPACE = 0 }; + +// Mach-O section uniquing. +// +// FIXME: Figure out where this should live, it should be shared by +// TargetLoweringObjectFile. +typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; + +AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, + const MCAsmInfo &_MAI) + : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), TargetParser(0), + CurBuffer(0), SectionUniquingMap(0) { + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + + // Debugging directives. + AddDirectiveHandler(".file", &AsmParser::ParseDirectiveFile); + AddDirectiveHandler(".line", &AsmParser::ParseDirectiveLine); + AddDirectiveHandler(".loc", &AsmParser::ParseDirectiveLoc); +} + + + +AsmParser::~AsmParser() { + // If we have the MachO uniquing map, free it. + delete (MachOUniqueMapTy*)SectionUniquingMap; +} + +const MCSection *AsmParser::getMachOSection(const StringRef &Segment, + const StringRef &Section, + unsigned TypeAndAttributes, + unsigned Reserved2, + SectionKind Kind) const { + // We unique sections by their segment/section pair. The returned section + // may not have the same flags as the requested section, if so this should be + // diagnosed by the client as an error. + + // Create the map if it doesn't already exist. + if (SectionUniquingMap == 0) + SectionUniquingMap = new MachOUniqueMapTy(); + MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)SectionUniquingMap; + + // Form the name to look up. + SmallString<64> Name; + Name += Segment; + Name.push_back(','); + Name += Section; + + // Do the lookup, if we have a hit, return it. + const MCSectionMachO *&Entry = Map[Name.str()]; + + // FIXME: This should validate the type and attributes. + if (Entry) return Entry; + + // Otherwise, return a new section. + return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes, + Reserved2, Kind, Ctx); +} + +void AsmParser::Warning(SMLoc L, const Twine &Msg) { + PrintMessage(L, Msg.str(), "warning"); +} + +bool AsmParser::Error(SMLoc L, const Twine &Msg) { + PrintMessage(L, Msg.str(), "error"); + return true; +} + +bool AsmParser::TokError(const char *Msg) { + PrintMessage(Lexer.getLoc(), Msg, "error"); + return true; +} + +void AsmParser::PrintMessage(SMLoc Loc, const std::string &Msg, + const char *Type) const { + SrcMgr.PrintMessage(Loc, Msg, Type); +} + +bool AsmParser::EnterIncludeFile(const std::string &Filename) { + int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc()); + if (NewBuf == -1) + return true; + + CurBuffer = NewBuf; + + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + + return false; +} + +const AsmToken &AsmParser::Lex() { + const AsmToken *tok = &Lexer.Lex(); + + if (tok->is(AsmToken::Eof)) { + // If this is the end of an included file, pop the parent file off the + // include stack. + SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); + if (ParentIncludeLoc != SMLoc()) { + CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), + ParentIncludeLoc.getPointer()); + tok = &Lexer.Lex(); + } + } + + if (tok->is(AsmToken::Error)) + PrintMessage(Lexer.getErrLoc(), Lexer.getErr(), "error"); + + return *tok; +} + +bool AsmParser::Run() { + // Create the initial section. + // + // FIXME: Support -n. + // FIXME: Target hook & command line option for initial section. + Out.SwitchSection(getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 0, SectionKind())); + + + // Prime the lexer. + Lex(); + + bool HadError = false; + + AsmCond StartingCondState = TheCondState; + + // While we have input, parse each statement. + while (Lexer.isNot(AsmToken::Eof)) { + // Handle conditional assembly here before calling ParseStatement() + if (Lexer.getKind() == AsmToken::Identifier) { + // If we have an identifier, handle it as the key symbol. + AsmToken ID = getTok(); + SMLoc IDLoc = ID.getLoc(); + StringRef IDVal = ID.getString(); + + if (IDVal == ".if" || + IDVal == ".elseif" || + IDVal == ".else" || + IDVal == ".endif") { + if (!ParseConditionalAssemblyDirectives(IDVal, IDLoc)) + continue; + HadError = true; + EatToEndOfStatement(); + continue; + } + } + if (TheCondState.Ignore) { + EatToEndOfStatement(); + continue; + } + + if (!ParseStatement()) continue; + + // We had an error, remember it and recover by skipping to the next line. + HadError = true; + EatToEndOfStatement(); + } + + if (TheCondState.TheCond != StartingCondState.TheCond || + TheCondState.Ignore != StartingCondState.Ignore) + return TokError("unmatched .ifs or .elses"); + + if (!HadError) + Out.Finish(); + + return HadError; +} + +/// ParseConditionalAssemblyDirectives - parse the conditional assembly +/// directives +bool AsmParser::ParseConditionalAssemblyDirectives(StringRef Directive, + SMLoc DirectiveLoc) { + if (Directive == ".if") + return ParseDirectiveIf(DirectiveLoc); + if (Directive == ".elseif") + return ParseDirectiveElseIf(DirectiveLoc); + if (Directive == ".else") + return ParseDirectiveElse(DirectiveLoc); + if (Directive == ".endif") + return ParseDirectiveEndIf(DirectiveLoc); + return true; +} + +/// EatToEndOfStatement - Throw away the rest of the line for testing purposes. +void AsmParser::EatToEndOfStatement() { + while (Lexer.isNot(AsmToken::EndOfStatement) && + Lexer.isNot(AsmToken::Eof)) + Lex(); + + // Eat EOL. + if (Lexer.is(AsmToken::EndOfStatement)) + Lex(); +} + + +/// ParseParenExpr - Parse a paren expression and return it. +/// NOTE: This assumes the leading '(' has already been consumed. +/// +/// parenexpr ::= expr) +/// +bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { + if (ParseExpression(Res)) return true; + if (Lexer.isNot(AsmToken::RParen)) + return TokError("expected ')' in parentheses expression"); + EndLoc = Lexer.getLoc(); + Lex(); + return false; +} + +MCSymbol *AsmParser::CreateSymbol(StringRef Name) { + if (MCSymbol *S = Ctx.LookupSymbol(Name)) + return S; + + // If the label starts with L it is an assembler temporary label. + if (Name.startswith("L")) + return Ctx.CreateTemporarySymbol(Name); + + return Ctx.CreateSymbol(Name); +} + +/// ParsePrimaryExpr - Parse a primary expression and return it. +/// primaryexpr ::= (parenexpr +/// primaryexpr ::= symbol +/// primaryexpr ::= number +/// primaryexpr ::= ~,+,- primaryexpr +bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { + switch (Lexer.getKind()) { + default: + return TokError("unknown token in expression"); + case AsmToken::Exclaim: + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) + return true; + Res = MCUnaryExpr::CreateLNot(Res, getContext()); + return false; + case AsmToken::String: + case AsmToken::Identifier: { + // This is a symbol reference. + MCSymbol *Sym = CreateSymbol(getTok().getIdentifier()); + EndLoc = Lexer.getLoc(); + Lex(); // Eat identifier. + + // If this is an absolute variable reference, substitute it now to preserve + // semantics in the face of reassignment. + if (Sym->getValue() && isa<MCConstantExpr>(Sym->getValue())) { + Res = Sym->getValue(); + return false; + } + + // Otherwise create a symbol ref. + Res = MCSymbolRefExpr::Create(Sym, getContext()); + return false; + } + case AsmToken::Integer: + Res = MCConstantExpr::Create(getTok().getIntVal(), getContext()); + EndLoc = Lexer.getLoc(); + Lex(); // Eat token. + return false; + case AsmToken::LParen: + Lex(); // Eat the '('. + return ParseParenExpr(Res, EndLoc); + case AsmToken::Minus: + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) + return true; + Res = MCUnaryExpr::CreateMinus(Res, getContext()); + return false; + case AsmToken::Plus: + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) + return true; + Res = MCUnaryExpr::CreatePlus(Res, getContext()); + return false; + case AsmToken::Tilde: + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) + return true; + Res = MCUnaryExpr::CreateNot(Res, getContext()); + return false; + } +} + +bool AsmParser::ParseExpression(const MCExpr *&Res) { + SMLoc EndLoc; + return ParseExpression(Res, EndLoc); +} + +/// ParseExpression - Parse an expression and return it. +/// +/// expr ::= expr +,- expr -> lowest. +/// expr ::= expr |,^,&,! expr -> middle. +/// expr ::= expr *,/,%,<<,>> expr -> highest. +/// expr ::= primaryexpr +/// +bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) { + Res = 0; + return ParsePrimaryExpr(Res, EndLoc) || + ParseBinOpRHS(1, Res, EndLoc); +} + +bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { + if (ParseParenExpr(Res, EndLoc)) + return true; + + return false; +} + +bool AsmParser::ParseAbsoluteExpression(int64_t &Res) { + const MCExpr *Expr; + + SMLoc StartLoc = Lexer.getLoc(); + if (ParseExpression(Expr)) + return true; + + if (!Expr->EvaluateAsAbsolute(Res)) + return Error(StartLoc, "expected absolute expression"); + + return false; +} + +static unsigned getBinOpPrecedence(AsmToken::TokenKind K, + MCBinaryExpr::Opcode &Kind) { + switch (K) { + default: + return 0; // not a binop. + + // Lowest Precedence: &&, || + case AsmToken::AmpAmp: + Kind = MCBinaryExpr::LAnd; + return 1; + case AsmToken::PipePipe: + Kind = MCBinaryExpr::LOr; + return 1; + + // Low Precedence: +, -, ==, !=, <>, <, <=, >, >= + case AsmToken::Plus: + Kind = MCBinaryExpr::Add; + return 2; + case AsmToken::Minus: + Kind = MCBinaryExpr::Sub; + return 2; + case AsmToken::EqualEqual: + Kind = MCBinaryExpr::EQ; + return 2; + case AsmToken::ExclaimEqual: + case AsmToken::LessGreater: + Kind = MCBinaryExpr::NE; + return 2; + case AsmToken::Less: + Kind = MCBinaryExpr::LT; + return 2; + case AsmToken::LessEqual: + Kind = MCBinaryExpr::LTE; + return 2; + case AsmToken::Greater: + Kind = MCBinaryExpr::GT; + return 2; + case AsmToken::GreaterEqual: + Kind = MCBinaryExpr::GTE; + return 2; + + // Intermediate Precedence: |, &, ^ + // + // FIXME: gas seems to support '!' as an infix operator? + case AsmToken::Pipe: + Kind = MCBinaryExpr::Or; + return 3; + case AsmToken::Caret: + Kind = MCBinaryExpr::Xor; + return 3; + case AsmToken::Amp: + Kind = MCBinaryExpr::And; + return 3; + + // Highest Precedence: *, /, %, <<, >> + case AsmToken::Star: + Kind = MCBinaryExpr::Mul; + return 4; + case AsmToken::Slash: + Kind = MCBinaryExpr::Div; + return 4; + case AsmToken::Percent: + Kind = MCBinaryExpr::Mod; + return 4; + case AsmToken::LessLess: + Kind = MCBinaryExpr::Shl; + return 4; + case AsmToken::GreaterGreater: + Kind = MCBinaryExpr::Shr; + return 4; + } +} + + +/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'. +/// Res contains the LHS of the expression on input. +bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, + SMLoc &EndLoc) { + while (1) { + MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; + unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind); + + // If the next token is lower precedence than we are allowed to eat, return + // successfully with what we ate already. + if (TokPrec < Precedence) + return false; + + Lex(); + + // Eat the next primary expression. + const MCExpr *RHS; + if (ParsePrimaryExpr(RHS, EndLoc)) return true; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + MCBinaryExpr::Opcode Dummy; + unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); + if (TokPrec < NextTokPrec) { + if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true; + } + + // Merge LHS and RHS according to operator. + Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext()); + } +} + + + + +/// ParseStatement: +/// ::= EndOfStatement +/// ::= Label* Directive ...Operands... EndOfStatement +/// ::= Label* Identifier OperandList* EndOfStatement +bool AsmParser::ParseStatement() { + if (Lexer.is(AsmToken::EndOfStatement)) { + Lex(); + return false; + } + + // Statements always start with an identifier. + AsmToken ID = getTok(); + SMLoc IDLoc = ID.getLoc(); + StringRef IDVal; + if (ParseIdentifier(IDVal)) + return TokError("unexpected token at start of statement"); + + // FIXME: Recurse on local labels? + + // See what kind of statement we have. + switch (Lexer.getKind()) { + case AsmToken::Colon: { + // identifier ':' -> Label. + Lex(); + + // Diagnose attempt to use a variable as a label. + // + // FIXME: Diagnostics. Note the location of the definition as a label. + // FIXME: This doesn't diagnose assignment to a symbol which has been + // implicitly marked as external. + MCSymbol *Sym = CreateSymbol(IDVal); + if (!Sym->isUndefined()) + return Error(IDLoc, "invalid symbol redefinition"); + + // Emit the label. + Out.EmitLabel(Sym); + + return ParseStatement(); + } + + case AsmToken::Equal: + // identifier '=' ... -> assignment statement + Lex(); + + return ParseAssignment(IDVal); + + default: // Normal instruction or directive. + break; + } + + // Otherwise, we have a normal instruction or directive. + if (IDVal[0] == '.') { + // FIXME: This should be driven based on a hash lookup and callback. + if (IDVal == ".section") + return ParseDirectiveDarwinSection(); + if (IDVal == ".text") + // FIXME: This changes behavior based on the -static flag to the + // assembler. + return ParseDirectiveSectionSwitch("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS); + if (IDVal == ".const") + return ParseDirectiveSectionSwitch("__TEXT", "__const"); + if (IDVal == ".static_const") + return ParseDirectiveSectionSwitch("__TEXT", "__static_const"); + if (IDVal == ".cstring") + return ParseDirectiveSectionSwitch("__TEXT","__cstring", + MCSectionMachO::S_CSTRING_LITERALS); + if (IDVal == ".literal4") + return ParseDirectiveSectionSwitch("__TEXT", "__literal4", + MCSectionMachO::S_4BYTE_LITERALS, + 4); + if (IDVal == ".literal8") + return ParseDirectiveSectionSwitch("__TEXT", "__literal8", + MCSectionMachO::S_8BYTE_LITERALS, + 8); + if (IDVal == ".literal16") + return ParseDirectiveSectionSwitch("__TEXT","__literal16", + MCSectionMachO::S_16BYTE_LITERALS, + 16); + if (IDVal == ".constructor") + return ParseDirectiveSectionSwitch("__TEXT","__constructor"); + if (IDVal == ".destructor") + return ParseDirectiveSectionSwitch("__TEXT","__destructor"); + if (IDVal == ".fvmlib_init0") + return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init0"); + if (IDVal == ".fvmlib_init1") + return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init1"); + + // FIXME: The assembler manual claims that this has the self modify code + // flag, at least on x86-32, but that does not appear to be correct. + if (IDVal == ".symbol_stub") + return ParseDirectiveSectionSwitch("__TEXT","__symbol_stub", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + // FIXME: Different on PPC and ARM. + 0, 16); + // FIXME: PowerPC only? + if (IDVal == ".picsymbol_stub") + return ParseDirectiveSectionSwitch("__TEXT","__picsymbol_stub", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 0, 26); + if (IDVal == ".data") + return ParseDirectiveSectionSwitch("__DATA", "__data"); + if (IDVal == ".static_data") + return ParseDirectiveSectionSwitch("__DATA", "__static_data"); + + // FIXME: The section names of these two are misspelled in the assembler + // manual. + if (IDVal == ".non_lazy_symbol_pointer") + return ParseDirectiveSectionSwitch("__DATA", "__nl_symbol_ptr", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, + 4); + if (IDVal == ".lazy_symbol_pointer") + return ParseDirectiveSectionSwitch("__DATA", "__la_symbol_ptr", + MCSectionMachO::S_LAZY_SYMBOL_POINTERS, + 4); + + if (IDVal == ".dyld") + return ParseDirectiveSectionSwitch("__DATA", "__dyld"); + if (IDVal == ".mod_init_func") + return ParseDirectiveSectionSwitch("__DATA", "__mod_init_func", + MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, + 4); + if (IDVal == ".mod_term_func") + return ParseDirectiveSectionSwitch("__DATA", "__mod_term_func", + MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, + 4); + if (IDVal == ".const_data") + return ParseDirectiveSectionSwitch("__DATA", "__const"); + + + if (IDVal == ".objc_class") + return ParseDirectiveSectionSwitch("__OBJC", "__class", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_meta_class") + return ParseDirectiveSectionSwitch("__OBJC", "__meta_class", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_cat_cls_meth") + return ParseDirectiveSectionSwitch("__OBJC", "__cat_cls_meth", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_cat_inst_meth") + return ParseDirectiveSectionSwitch("__OBJC", "__cat_inst_meth", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_protocol") + return ParseDirectiveSectionSwitch("__OBJC", "__protocol", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_string_object") + return ParseDirectiveSectionSwitch("__OBJC", "__string_object", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_cls_meth") + return ParseDirectiveSectionSwitch("__OBJC", "__cls_meth", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_inst_meth") + return ParseDirectiveSectionSwitch("__OBJC", "__inst_meth", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_cls_refs") + return ParseDirectiveSectionSwitch("__OBJC", "__cls_refs", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP | + MCSectionMachO::S_LITERAL_POINTERS, + 4); + if (IDVal == ".objc_message_refs") + return ParseDirectiveSectionSwitch("__OBJC", "__message_refs", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP | + MCSectionMachO::S_LITERAL_POINTERS, + 4); + if (IDVal == ".objc_symbols") + return ParseDirectiveSectionSwitch("__OBJC", "__symbols", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_category") + return ParseDirectiveSectionSwitch("__OBJC", "__category", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_class_vars") + return ParseDirectiveSectionSwitch("__OBJC", "__class_vars", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_instance_vars") + return ParseDirectiveSectionSwitch("__OBJC", "__instance_vars", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_module_info") + return ParseDirectiveSectionSwitch("__OBJC", "__module_info", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + if (IDVal == ".objc_class_names") + return ParseDirectiveSectionSwitch("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS); + if (IDVal == ".objc_meth_var_types") + return ParseDirectiveSectionSwitch("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS); + if (IDVal == ".objc_meth_var_names") + return ParseDirectiveSectionSwitch("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS); + if (IDVal == ".objc_selector_strs") + return ParseDirectiveSectionSwitch("__OBJC", "__selector_strs", + MCSectionMachO::S_CSTRING_LITERALS); + + // Assembler features + if (IDVal == ".set") + return ParseDirectiveSet(); + + // Data directives + + if (IDVal == ".ascii") + return ParseDirectiveAscii(false); + if (IDVal == ".asciz") + return ParseDirectiveAscii(true); + + if (IDVal == ".byte") + return ParseDirectiveValue(1); + if (IDVal == ".short") + return ParseDirectiveValue(2); + if (IDVal == ".long") + return ParseDirectiveValue(4); + if (IDVal == ".quad") + return ParseDirectiveValue(8); + + // FIXME: Target hooks for IsPow2. + if (IDVal == ".align") + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); + if (IDVal == ".align32") + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); + if (IDVal == ".balign") + return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1); + if (IDVal == ".balignw") + return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2); + if (IDVal == ".balignl") + return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4); + if (IDVal == ".p2align") + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); + if (IDVal == ".p2alignw") + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2); + if (IDVal == ".p2alignl") + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); + + if (IDVal == ".org") + return ParseDirectiveOrg(); + + if (IDVal == ".fill") + return ParseDirectiveFill(); + if (IDVal == ".space") + return ParseDirectiveSpace(); + + // Symbol attribute directives + + if (IDVal == ".globl" || IDVal == ".global") + return ParseDirectiveSymbolAttribute(MCSA_Global); + if (IDVal == ".hidden") + return ParseDirectiveSymbolAttribute(MCSA_Hidden); + if (IDVal == ".indirect_symbol") + return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol); + if (IDVal == ".internal") + return ParseDirectiveSymbolAttribute(MCSA_Internal); + if (IDVal == ".lazy_reference") + return ParseDirectiveSymbolAttribute(MCSA_LazyReference); + if (IDVal == ".no_dead_strip") + return ParseDirectiveSymbolAttribute(MCSA_NoDeadStrip); + if (IDVal == ".private_extern") + return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern); + if (IDVal == ".protected") + return ParseDirectiveSymbolAttribute(MCSA_Protected); + if (IDVal == ".reference") + return ParseDirectiveSymbolAttribute(MCSA_Reference); + if (IDVal == ".weak") + return ParseDirectiveSymbolAttribute(MCSA_Weak); + if (IDVal == ".weak_definition") + return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition); + if (IDVal == ".weak_reference") + return ParseDirectiveSymbolAttribute(MCSA_WeakReference); + + if (IDVal == ".comm") + return ParseDirectiveComm(/*IsLocal=*/false); + if (IDVal == ".lcomm") + return ParseDirectiveComm(/*IsLocal=*/true); + if (IDVal == ".zerofill") + return ParseDirectiveDarwinZerofill(); + if (IDVal == ".desc") + return ParseDirectiveDarwinSymbolDesc(); + if (IDVal == ".lsym") + return ParseDirectiveDarwinLsym(); + + if (IDVal == ".subsections_via_symbols") + return ParseDirectiveDarwinSubsectionsViaSymbols(); + if (IDVal == ".abort") + return ParseDirectiveAbort(); + if (IDVal == ".include") + return ParseDirectiveInclude(); + if (IDVal == ".dump") + return ParseDirectiveDarwinDumpOrLoad(IDLoc, /*IsDump=*/true); + if (IDVal == ".load") + return ParseDirectiveDarwinDumpOrLoad(IDLoc, /*IsLoad=*/false); + + // Look up the handler in the handler table, + bool(AsmParser::*Handler)(StringRef, SMLoc) = DirectiveMap[IDVal]; + if (Handler) + return (this->*Handler)(IDVal, IDLoc); + + // Target hook for parsing target specific directives. + if (!getTargetParser().ParseDirective(ID)) + return false; + + Warning(IDLoc, "ignoring directive for now"); + EatToEndOfStatement(); + return false; + } + + + SmallVector<MCParsedAsmOperand*, 8> ParsedOperands; + if (getTargetParser().ParseInstruction(IDVal, IDLoc, ParsedOperands)) + // FIXME: Leaking ParsedOperands on failure. + return true; + + if (Lexer.isNot(AsmToken::EndOfStatement)) + // FIXME: Leaking ParsedOperands on failure. + return TokError("unexpected token in argument list"); + + // Eat the end of statement marker. + Lex(); + + + MCInst Inst; + + bool MatchFail = getTargetParser().MatchInstruction(ParsedOperands, Inst); + + // Free any parsed operands. + for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i) + delete ParsedOperands[i]; + + if (MatchFail) { + // FIXME: We should give nicer diagnostics about the exact failure. + Error(IDLoc, "unrecognized instruction"); + return true; + } + + // Instruction is good, process it. + Out.EmitInstruction(Inst); + + // Skip to end of line for now. + return false; +} + +bool AsmParser::ParseAssignment(const StringRef &Name) { + // FIXME: Use better location, we should use proper tokens. + SMLoc EqualLoc = Lexer.getLoc(); + + const MCExpr *Value; + SMLoc StartLoc = Lexer.getLoc(); + if (ParseExpression(Value)) + return true; + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in assignment"); + + // Eat the end of statement marker. + Lex(); + + // Validate that the LHS is allowed to be a variable (either it has not been + // used as a symbol, or it is an absolute symbol). + MCSymbol *Sym = getContext().LookupSymbol(Name); + if (Sym) { + // Diagnose assignment to a label. + // + // FIXME: Diagnostics. Note the location of the definition as a label. + // FIXME: Diagnose assignment to protected identifier (e.g., register name). + if (!Sym->isUndefined() && !Sym->isAbsolute()) + return Error(EqualLoc, "redefinition of '" + Name + "'"); + else if (!Sym->isVariable()) + return Error(EqualLoc, "invalid assignment to '" + Name + "'"); + else if (!isa<MCConstantExpr>(Sym->getValue())) + return Error(EqualLoc, "invalid reassignment of non-absolute variable '" + + Name + "'"); + } else + Sym = CreateSymbol(Name); + + // FIXME: Handle '.'. + + // Do the assignment. + Out.EmitAssignment(Sym, Value); + + return false; +} + +/// ParseIdentifier: +/// ::= identifier +/// ::= string +bool AsmParser::ParseIdentifier(StringRef &Res) { + if (Lexer.isNot(AsmToken::Identifier) && + Lexer.isNot(AsmToken::String)) + return true; + + Res = getTok().getIdentifier(); + + Lex(); // Consume the identifier token. + + return false; +} + +/// ParseDirectiveSet: +/// ::= .set identifier ',' expression +bool AsmParser::ParseDirectiveSet() { + StringRef Name; + + if (ParseIdentifier(Name)) + return TokError("expected identifier after '.set' directive"); + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in '.set'"); + Lex(); + + return ParseAssignment(Name); +} + +/// ParseDirectiveSection: +/// ::= .section identifier (',' identifier)* +/// FIXME: This should actually parse out the segment, section, attributes and +/// sizeof_stub fields. +bool AsmParser::ParseDirectiveDarwinSection() { + SMLoc Loc = Lexer.getLoc(); + + StringRef SectionName; + if (ParseIdentifier(SectionName)) + return Error(Loc, "expected identifier after '.section' directive"); + + // Verify there is a following comma. + if (!Lexer.is(AsmToken::Comma)) + return TokError("unexpected token in '.section' directive"); + + std::string SectionSpec = SectionName; + SectionSpec += ","; + + // Add all the tokens until the end of the line, ParseSectionSpecifier will + // handle this. + StringRef EOL = Lexer.LexUntilEndOfStatement(); + SectionSpec.append(EOL.begin(), EOL.end()); + + Lex(); + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.section' directive"); + Lex(); + + + StringRef Segment, Section; + unsigned TAA, StubSize; + std::string ErrorStr = + MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section, + TAA, StubSize); + + if (!ErrorStr.empty()) + return Error(Loc, ErrorStr.c_str()); + + // FIXME: Arch specific. + Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize, + SectionKind())); + return false; +} + +/// ParseDirectiveSectionSwitch - +bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment, + const char *Section, + unsigned TAA, unsigned Align, + unsigned StubSize) { + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in section switching directive"); + Lex(); + + // FIXME: Arch specific. + Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize, + SectionKind())); + + // Set the implicit alignment, if any. + // + // FIXME: This isn't really what 'as' does; I think it just uses the implicit + // alignment on the section (e.g., if one manually inserts bytes into the + // section, then just issueing the section switch directive will not realign + // the section. However, this is arguably more reasonable behavior, and there + // is no good reason for someone to intentionally emit incorrectly sized + // values into the implicitly aligned sections. + if (Align) + Out.EmitValueToAlignment(Align, 0, 1, 0); + + return false; +} + +bool AsmParser::ParseEscapedString(std::string &Data) { + assert(Lexer.is(AsmToken::String) && "Unexpected current token!"); + + Data = ""; + StringRef Str = getTok().getStringContents(); + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + if (Str[i] != '\\') { + Data += Str[i]; + continue; + } + + // Recognize escaped characters. Note that this escape semantics currently + // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes. + ++i; + if (i == e) + return TokError("unexpected backslash at end of string"); + + // Recognize octal sequences. + if ((unsigned) (Str[i] - '0') <= 7) { + // Consume up to three octal characters. + unsigned Value = Str[i] - '0'; + + if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) { + ++i; + Value = Value * 8 + (Str[i] - '0'); + + if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) { + ++i; + Value = Value * 8 + (Str[i] - '0'); + } + } + + if (Value > 255) + return TokError("invalid octal escape sequence (out of range)"); + + Data += (unsigned char) Value; + continue; + } + + // Otherwise recognize individual escapes. + switch (Str[i]) { + default: + // Just reject invalid escape sequences for now. + return TokError("invalid escape sequence (unrecognized character)"); + + case 'b': Data += '\b'; break; + case 'f': Data += '\f'; break; + case 'n': Data += '\n'; break; + case 'r': Data += '\r'; break; + case 't': Data += '\t'; break; + case '"': Data += '"'; break; + case '\\': Data += '\\'; break; + } + } + + return false; +} + +/// ParseDirectiveAscii: +/// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ] +bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) { + if (Lexer.isNot(AsmToken::EndOfStatement)) { + for (;;) { + if (Lexer.isNot(AsmToken::String)) + return TokError("expected string in '.ascii' or '.asciz' directive"); + + std::string Data; + if (ParseEscapedString(Data)) + return true; + + Out.EmitBytes(Data, DEFAULT_ADDRSPACE); + if (ZeroTerminated) + Out.EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE); + + Lex(); + + if (Lexer.is(AsmToken::EndOfStatement)) + break; + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in '.ascii' or '.asciz' directive"); + Lex(); + } + } + + Lex(); + return false; +} + +/// ParseDirectiveValue +/// ::= (.byte | .short | ... ) [ expression (, expression)* ] +bool AsmParser::ParseDirectiveValue(unsigned Size) { + if (Lexer.isNot(AsmToken::EndOfStatement)) { + for (;;) { + const MCExpr *Value; + SMLoc ATTRIBUTE_UNUSED StartLoc = Lexer.getLoc(); + if (ParseExpression(Value)) + return true; + + Out.EmitValue(Value, Size, DEFAULT_ADDRSPACE); + + if (Lexer.is(AsmToken::EndOfStatement)) + break; + + // FIXME: Improve diagnostic. + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + +/// ParseDirectiveSpace +/// ::= .space expression [ , expression ] +bool AsmParser::ParseDirectiveSpace() { + int64_t NumBytes; + if (ParseAbsoluteExpression(NumBytes)) + return true; + + int64_t FillExpr = 0; + bool HasFillExpr = false; + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in '.space' directive"); + Lex(); + + if (ParseAbsoluteExpression(FillExpr)) + return true; + + HasFillExpr = true; + + if (Lexer.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. + Out.EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE); + + return false; +} + +/// ParseDirectiveFill +/// ::= .fill expression , expression , expression +bool AsmParser::ParseDirectiveFill() { + int64_t NumValues; + if (ParseAbsoluteExpression(NumValues)) + return true; + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in '.fill' directive"); + Lex(); + + int64_t FillSize; + if (ParseAbsoluteExpression(FillSize)) + return true; + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in '.fill' directive"); + Lex(); + + int64_t FillExpr; + if (ParseAbsoluteExpression(FillExpr)) + return true; + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.fill' directive"); + + Lex(); + + if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8) + return TokError("invalid '.fill' size, expected 1, 2, 4, or 8"); + + for (uint64_t i = 0, e = NumValues; i != e; ++i) + Out.EmitValue(MCConstantExpr::Create(FillExpr, getContext()), FillSize, + DEFAULT_ADDRSPACE); + + return false; +} + +/// ParseDirectiveOrg +/// ::= .org expression [ , expression ] +bool AsmParser::ParseDirectiveOrg() { + const MCExpr *Offset; + SMLoc StartLoc = Lexer.getLoc(); + if (ParseExpression(Offset)) + return true; + + // Parse optional fill expression. + int64_t FillExpr = 0; + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in '.org' directive"); + Lex(); + + if (ParseAbsoluteExpression(FillExpr)) + return true; + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.org' directive"); + } + + Lex(); + + // FIXME: Only limited forms of relocatable expressions are accepted here, it + // has to be relative to the current section. + Out.EmitValueToOffset(Offset, FillExpr); + + return false; +} + +/// ParseDirectiveAlign +/// ::= {.align, ...} expression [ , expression [ , expression ]] +bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { + SMLoc AlignmentLoc = Lexer.getLoc(); + int64_t Alignment; + if (ParseAbsoluteExpression(Alignment)) + return true; + + SMLoc MaxBytesLoc; + bool HasFillExpr = false; + int64_t FillExpr = 0; + int64_t MaxBytesToFill = 0; + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + // The fill expression can be omitted while specifying a maximum number of + // alignment bytes, e.g: + // .align 3,,4 + if (Lexer.isNot(AsmToken::Comma)) { + HasFillExpr = true; + if (ParseAbsoluteExpression(FillExpr)) + return true; + } + + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + MaxBytesLoc = Lexer.getLoc(); + if (ParseAbsoluteExpression(MaxBytesToFill)) + return true; + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + } + } + + Lex(); + + if (!HasFillExpr) { + // FIXME: Sometimes fill with nop. + FillExpr = 0; + } + + // Compute alignment in bytes. + if (IsPow2) { + // FIXME: Diagnose overflow. + if (Alignment >= 32) { + Error(AlignmentLoc, "invalid alignment value"); + Alignment = 31; + } + + Alignment = 1ULL << Alignment; + } + + // Diagnose non-sensical max bytes to align. + if (MaxBytesLoc.isValid()) { + if (MaxBytesToFill < 1) { + Error(MaxBytesLoc, "alignment directive can never be satisfied in this " + "many bytes, ignoring maximum bytes expression"); + MaxBytesToFill = 0; + } + + if (MaxBytesToFill >= Alignment) { + Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and " + "has no effect"); + MaxBytesToFill = 0; + } + } + + // FIXME: Target specific behavior about how the "extra" bytes are filled. + Out.EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill); + + return false; +} + +/// ParseDirectiveSymbolAttribute +/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] +bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { + if (Lexer.isNot(AsmToken::EndOfStatement)) { + for (;;) { + StringRef Name; + + if (ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + MCSymbol *Sym = CreateSymbol(Name); + + Out.EmitSymbolAttribute(Sym, Attr); + + if (Lexer.is(AsmToken::EndOfStatement)) + break; + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + +/// ParseDirectiveDarwinSymbolDesc +/// ::= .desc identifier , expression +bool AsmParser::ParseDirectiveDarwinSymbolDesc() { + StringRef Name; + if (ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = CreateSymbol(Name); + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in '.desc' directive"); + Lex(); + + SMLoc DescLoc = Lexer.getLoc(); + int64_t DescValue; + if (ParseAbsoluteExpression(DescValue)) + return true; + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.desc' directive"); + + Lex(); + + // Set the n_desc field of this Symbol to this DescValue + Out.EmitSymbolDesc(Sym, DescValue); + + return false; +} + +/// ParseDirectiveComm +/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] +bool AsmParser::ParseDirectiveComm(bool IsLocal) { + SMLoc IDLoc = Lexer.getLoc(); + StringRef Name; + if (ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = CreateSymbol(Name); + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Size; + SMLoc SizeLoc = Lexer.getLoc(); + if (ParseAbsoluteExpression(Size)) + return true; + + int64_t Pow2Alignment = 0; + SMLoc Pow2AlignmentLoc; + if (Lexer.is(AsmToken::Comma)) { + Lex(); + Pow2AlignmentLoc = Lexer.getLoc(); + if (ParseAbsoluteExpression(Pow2Alignment)) + return true; + + // If this target takes alignments in bytes (not log) validate and convert. + if (Lexer.getMAI().getAlignmentIsInBytes()) { + if (!isPowerOf2_64(Pow2Alignment)) + return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); + Pow2Alignment = Log2_64(Pow2Alignment); + } + } + + if (Lexer.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 assember + // 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"); + + // '.lcomm' is equivalent to '.zerofill'. + // Create the Symbol as a common or local common with Size and Pow2Alignment + if (IsLocal) { + Out.EmitZerofill(getMachOSection("__DATA", "__bss", + MCSectionMachO::S_ZEROFILL, 0, + SectionKind()), + Sym, Size, 1 << Pow2Alignment); + return false; + } + + Out.EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment); + return false; +} + +/// ParseDirectiveDarwinZerofill +/// ::= .zerofill segname , sectname [, identifier , size_expression [ +/// , align_expression ]] +bool AsmParser::ParseDirectiveDarwinZerofill() { + // FIXME: Handle quoted names here. + + if (Lexer.isNot(AsmToken::Identifier)) + return TokError("expected segment name after '.zerofill' directive"); + StringRef Segment = getTok().getString(); + Lex(); + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + if (Lexer.isNot(AsmToken::Identifier)) + return TokError("expected section name after comma in '.zerofill' " + "directive"); + StringRef Section = getTok().getString(); + Lex(); + + // If this is the end of the line all that was wanted was to create the + // the section but with no symbol. + if (Lexer.is(AsmToken::EndOfStatement)) { + // Create the zerofill section but no symbol + Out.EmitZerofill(getMachOSection(Segment, Section, + MCSectionMachO::S_ZEROFILL, 0, + SectionKind())); + return false; + } + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + if (Lexer.isNot(AsmToken::Identifier)) + return TokError("expected identifier in directive"); + + // handle the identifier as the key symbol. + SMLoc IDLoc = Lexer.getLoc(); + MCSymbol *Sym = CreateSymbol(getTok().getString()); + Lex(); + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Size; + SMLoc SizeLoc = Lexer.getLoc(); + if (ParseAbsoluteExpression(Size)) + return true; + + int64_t Pow2Alignment = 0; + SMLoc Pow2AlignmentLoc; + if (Lexer.is(AsmToken::Comma)) { + Lex(); + Pow2AlignmentLoc = Lexer.getLoc(); + if (ParseAbsoluteExpression(Pow2Alignment)) + return true; + } + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.zerofill' directive"); + + Lex(); + + if (Size < 0) + return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less " + "than zero"); + + // NOTE: The alignment in the directive is a power of 2 value, the assember + // may internally end up wanting an alignment in bytes. + // FIXME: Diagnose overflow. + if (Pow2Alignment < 0) + return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, " + "can't be less than zero"); + + if (!Sym->isUndefined()) + return Error(IDLoc, "invalid symbol redefinition"); + + // Create the zerofill Symbol with Size and Pow2Alignment + // + // FIXME: Arch specific. + Out.EmitZerofill(getMachOSection(Segment, Section, + MCSectionMachO::S_ZEROFILL, 0, + SectionKind()), + Sym, Size, 1 << Pow2Alignment); + + return false; +} + +/// ParseDirectiveDarwinSubsectionsViaSymbols +/// ::= .subsections_via_symbols +bool AsmParser::ParseDirectiveDarwinSubsectionsViaSymbols() { + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.subsections_via_symbols' directive"); + + Lex(); + + Out.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); + + return false; +} + +/// ParseDirectiveAbort +/// ::= .abort [ "abort_string" ] +bool AsmParser::ParseDirectiveAbort() { + // FIXME: Use loc from directive. + SMLoc Loc = Lexer.getLoc(); + + StringRef Str = ""; + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::String)) + return TokError("expected string in '.abort' directive"); + + Str = getTok().getString(); + + Lex(); + } + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.abort' directive"); + + Lex(); + + // FIXME: Handle here. + if (Str.empty()) + Error(Loc, ".abort detected. Assembly stopping."); + else + Error(Loc, ".abort '" + Str + "' detected. Assembly stopping."); + + return false; +} + +/// ParseDirectiveLsym +/// ::= .lsym identifier , expression +bool AsmParser::ParseDirectiveDarwinLsym() { + StringRef Name; + if (ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = CreateSymbol(Name); + + if (Lexer.isNot(AsmToken::Comma)) + return TokError("unexpected token in '.lsym' directive"); + Lex(); + + const MCExpr *Value; + SMLoc StartLoc = Lexer.getLoc(); + if (ParseExpression(Value)) + return true; + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.lsym' directive"); + + Lex(); + + // We don't currently support this directive. + // + // FIXME: Diagnostic location! + (void) Sym; + return TokError("directive '.lsym' is unsupported"); +} + +/// ParseDirectiveInclude +/// ::= .include "filename" +bool AsmParser::ParseDirectiveInclude() { + if (Lexer.isNot(AsmToken::String)) + return TokError("expected string in '.include' directive"); + + std::string Filename = getTok().getString(); + SMLoc IncludeLoc = Lexer.getLoc(); + Lex(); + + if (Lexer.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)) { + PrintMessage(IncludeLoc, + "Could not find include file '" + Filename + "'", + "error"); + return true; + } + + return false; +} + +/// ParseDirectiveDarwinDumpOrLoad +/// ::= ( .dump | .load ) "filename" +bool AsmParser::ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump) { + if (Lexer.isNot(AsmToken::String)) + return TokError("expected string in '.dump' or '.load' directive"); + + Lex(); + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.dump' or '.load' directive"); + + Lex(); + + // FIXME: If/when .dump and .load are implemented they will be done in the + // the assembly parser and not have any need for an MCStreamer API. + if (IsDump) + Warning(IDLoc, "ignoring directive .dump for now"); + else + Warning(IDLoc, "ignoring directive .load for now"); + + return false; +} + +/// ParseDirectiveIf +/// ::= .if expression +bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { + // Consume the identifier that was the .if directive + Lex(); + + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + if(TheCondState.Ignore) { + EatToEndOfStatement(); + } + else { + int64_t ExprValue; + if (ParseAbsoluteExpression(ExprValue)) + return true; + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.if' directive"); + + Lex(); + + TheCondState.CondMet = ExprValue; + 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; + + // Consume the identifier that was the .elseif directive + Lex(); + + 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 (Lexer.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) { + // Consume the identifier that was the .else directive + Lex(); + + if (Lexer.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) { + // Consume the identifier that was the .endif directive + Lex(); + + if (Lexer.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; +} + +/// ParseDirectiveFile +/// ::= .file [number] string +bool AsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { + // FIXME: I'm not sure what this is. + int64_t FileNumber = -1; + if (Lexer.is(AsmToken::Integer)) { + FileNumber = getTok().getIntVal(); + Lex(); + + if (FileNumber < 1) + return TokError("file number less than one"); + } + + if (Lexer.isNot(AsmToken::String)) + return TokError("unexpected token in '.file' directive"); + + StringRef ATTRIBUTE_UNUSED FileName = getTok().getString(); + Lex(); + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.file' directive"); + + // FIXME: Do something with the .file. + + return false; +} + +/// ParseDirectiveLine +/// ::= .line [number] +bool AsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) { + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::Integer)) + return TokError("unexpected token in '.line' directive"); + + int64_t LineNumber = getTok().getIntVal(); + (void) LineNumber; + Lex(); + + // FIXME: Do something with the .line. + } + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.file' directive"); + + return false; +} + + +/// ParseDirectiveLoc +/// ::= .loc number [number [number]] +bool AsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { + if (Lexer.isNot(AsmToken::Integer)) + return TokError("unexpected token in '.loc' directive"); + + // FIXME: What are these fields? + int64_t FileNumber = getTok().getIntVal(); + (void) FileNumber; + // FIXME: Validate file. + + Lex(); + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::Integer)) + return TokError("unexpected token in '.loc' directive"); + + int64_t Param2 = getTok().getIntVal(); + (void) Param2; + Lex(); + + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::Integer)) + return TokError("unexpected token in '.loc' directive"); + + int64_t Param3 = getTok().getIntVal(); + (void) Param3; + Lex(); + + // FIXME: Do something with the .loc. + } + } + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.file' directive"); + + return false; +} + diff --git a/lib/MC/MCParser/CMakeLists.txt b/lib/MC/MCParser/CMakeLists.txt new file mode 100644 index 0000000..a5c0818 --- /dev/null +++ b/lib/MC/MCParser/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMMCParser + AsmLexer.cpp + AsmParser.cpp + MCAsmLexer.cpp + MCAsmParser.cpp + TargetAsmParser.cpp + ) diff --git a/lib/MC/MCAsmLexer.cpp b/lib/MC/MCParser/MCAsmLexer.cpp index 1e34ed6..e5b2955 100644 --- a/lib/MC/MCAsmLexer.cpp +++ b/lib/MC/MCParser/MCAsmLexer.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/Support/SourceMgr.h" using namespace llvm; diff --git a/lib/MC/MCParser/MCAsmParser.cpp b/lib/MC/MCParser/MCAsmParser.cpp new file mode 100644 index 0000000..b8c2054 --- /dev/null +++ b/lib/MC/MCParser/MCAsmParser.cpp @@ -0,0 +1,35 @@ +//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/Support/SourceMgr.h" +using namespace llvm; + +MCAsmParser::MCAsmParser() { +} + +MCAsmParser::~MCAsmParser() { +} + +const AsmToken &MCAsmParser::getTok() { + return getLexer().getTok(); +} + +bool MCAsmParser::ParseExpression(const MCExpr *&Res) { + SMLoc L; + return ParseExpression(Res, L); +} + +/// getStartLoc - Get the location of the first token of this operand. +SMLoc MCParsedAsmOperand::getStartLoc() const { return SMLoc(); } +SMLoc MCParsedAsmOperand::getEndLoc() const { return SMLoc(); } + + diff --git a/lib/MC/MCParser/Makefile b/lib/MC/MCParser/Makefile new file mode 100644 index 0000000..e4eb483 --- /dev/null +++ b/lib/MC/MCParser/Makefile @@ -0,0 +1,16 @@ +##===- lib/MC/MCParser/Makefile ----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMMCParser +BUILD_ARCHIVE := 1 +CXXFLAGS = -fno-rtti + +include $(LEVEL)/Makefile.common + diff --git a/lib/MC/TargetAsmParser.cpp b/lib/MC/MCParser/TargetAsmParser.cpp index 05760c9..05760c9 100644 --- a/lib/MC/TargetAsmParser.cpp +++ b/lib/MC/MCParser/TargetAsmParser.cpp diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp index 4d520ec..ebfe269 100644 --- a/lib/MC/MCSectionELF.cpp +++ b/lib/MC/MCSectionELF.cpp @@ -22,14 +22,12 @@ Create(StringRef Section, unsigned Type, unsigned Flags, // ShouldOmitSectionDirective - Decides whether a '.section' directive // should be printed before the section name -bool MCSectionELF::ShouldOmitSectionDirective(const char *Name, +bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const { // FIXME: Does .section .bss/.data/.text work everywhere?? - if (strcmp(Name, ".text") == 0 || - strcmp(Name, ".data") == 0 || - (strcmp(Name, ".bss") == 0 && - !MAI.usesELFSectionDirectiveForBSS())) + if (Name == ".text" || Name == ".data" || + (Name == ".bss" && !MAI.usesELFSectionDirectiveForBSS())) return true; return false; @@ -46,7 +44,7 @@ bool MCSectionELF::ShouldPrintSectionType(unsigned Ty) const { void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const { - if (ShouldOmitSectionDirective(SectionName.c_str(), MAI)) { + if (ShouldOmitSectionDirective(SectionName, MAI)) { OS << '\t' << getSectionName() << '\n'; return; } @@ -128,7 +126,7 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, // header index. bool MCSectionELF::HasCommonSymbols() const { - if (strncmp(SectionName.c_str(), ".gnu.linkonce.", 14) == 0) + if (StringRef(SectionName).startswith(".gnu.linkonce.")) return true; return false; diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 8a6dcda..15b3079 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -8,7 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCStreamer.h" - +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context), CurSection(0) { @@ -16,3 +17,25 @@ MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context), CurSection(0) { MCStreamer::~MCStreamer() { } + +raw_ostream &MCStreamer::GetCommentOS() { + // By default, discard comments. + return nulls(); +} + + +/// EmitIntValue - Special case of EmitValue that avoids the client having to +/// pass in a MCExpr for constant integers. +void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size, + unsigned AddrSpace) { + EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace); +} + +/// EmitFill - Emit NumBytes bytes worth of the value specified by +/// FillValue. This implements directives such as '.space'. +void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, + unsigned AddrSpace) { + const MCExpr *E = MCConstantExpr::Create(FillValue, getContext()); + for (uint64_t i = 0, e = NumBytes; i != e; ++i) + EmitValue(E, 1, AddrSpace); +} diff --git a/lib/MC/MCSymbol.cpp b/lib/MC/MCSymbol.cpp index 265d06c..3fb1233 100644 --- a/lib/MC/MCSymbol.cpp +++ b/lib/MC/MCSymbol.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -26,24 +25,11 @@ static bool isAcceptableChar(char C) { return true; } -static char HexDigit(int V) { - return V < 10 ? V+'0' : V+'A'-10; -} - -static void MangleLetter(raw_ostream &OS, unsigned char C) { - OS << '_' << HexDigit(C >> 4) << HexDigit(C & 15) << '_'; -} - -/// NameNeedsEscaping - Return true if the identifier \arg Str needs quotes -/// for this assembler. -static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) { +/// NameNeedsQuoting - Return true if the identifier \arg Str needs quotes to be +/// syntactically correct. +static bool NameNeedsQuoting(StringRef Str) { assert(!Str.empty() && "Cannot create an empty MCSymbol"); - // If the first character is a number and the target does not allow this, we - // need quotes. - if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9') - return true; - // If any of the characters in the string is an unacceptable character, force // quotes. for (unsigned i = 0, e = Str.size(); i != e; ++i) @@ -52,63 +38,18 @@ static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) { return false; } -/// printMangledName - Print the specified string in mangled form if it uses -/// any unusual characters. -void MCSymbol::printMangledName(StringRef Str, raw_ostream &OS, - const MCAsmInfo *MAI) { - // The first character is not allowed to be a number unless the target - // explicitly allows it. - if ((MAI == 0 || !MAI->doesAllowNameToStartWithDigit()) && - Str[0] >= '0' && Str[0] <= '9') { - MangleLetter(OS, Str[0]); - Str = Str.substr(1); - } - - for (unsigned i = 0, e = Str.size(); i != e; ++i) { - if (!isAcceptableChar(Str[i])) - MangleLetter(OS, Str[i]); - else - OS << Str[i]; - } -} - -/// PrintMangledQuotedName - On systems that support quoted symbols, we still -/// have to escape some (obscure) characters like " and \n which would break the -/// assembler's lexing. -static void PrintMangledQuotedName(raw_ostream &OS, StringRef Str) { - OS << '"'; - - for (unsigned i = 0, e = Str.size(); i != e; ++i) { - if (Str[i] == '"') - OS << "_QQ_"; - else if (Str[i] == '\n') - OS << "_NL_"; - else - OS << Str[i]; - } - OS << '"'; -} - - -void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const { - if (MAI == 0 || !NameNeedsEscaping(getName(), *MAI)) { +void MCSymbol::print(raw_ostream &OS) const { + // The name for this MCSymbol is required to be a valid target name. However, + // some targets support quoting names with funny characters. If the name + // contains a funny character, then print it quoted. + if (!NameNeedsQuoting(getName())) { OS << getName(); return; } - - // On systems that do not allow quoted names, print with mangling. - if (!MAI->doesAllowQuotesInName()) - return printMangledName(getName(), OS, MAI); - - // If the string contains a double quote or newline, we still have to mangle - // it. - if (getName().find('"') != std::string::npos || - getName().find('\n') != std::string::npos) - return PrintMangledQuotedName(OS, getName()); OS << '"' << getName() << '"'; } void MCSymbol::dump() const { - print(dbgs(), 0); + print(dbgs()); } diff --git a/lib/MC/MCValue.cpp b/lib/MC/MCValue.cpp index c1222ec..043a49d 100644 --- a/lib/MC/MCValue.cpp +++ b/lib/MC/MCValue.cpp @@ -19,12 +19,10 @@ void MCValue::print(raw_ostream &OS, const MCAsmInfo *MAI) const { return; } - getSymA()->print(OS, MAI); + OS << *getSymA(); - if (getSymB()) { - OS << " - "; - getSymB()->print(OS, MAI); - } + if (getSymB()) + OS << " - " << *getSymB(); if (getConstant()) OS << " + " << getConstant(); diff --git a/lib/MC/Makefile b/lib/MC/Makefile index 314a5b1..371776f 100644 --- a/lib/MC/Makefile +++ b/lib/MC/Makefile @@ -10,6 +10,8 @@ LEVEL = ../.. LIBRARYNAME = LLVMMC BUILD_ARCHIVE := 1 +PARALLEL_DIRS := MCParser +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp index a035771..82b4b8c 100644 --- a/lib/Support/Debug.cpp +++ b/lib/Support/Debug.cpp @@ -115,9 +115,9 @@ raw_ostream &llvm::dbgs() { #else // Avoid "has no symbols" warning. namespace llvm { - /// dbgs - Return dbgs(). + /// dbgs - Return errs(). raw_ostream &dbgs() { - return dbgs(); + return errs(); } } diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp index 7dd42f4..bdc637a 100644 --- a/lib/Support/SourceMgr.cpp +++ b/lib/Support/SourceMgr.cpp @@ -192,18 +192,21 @@ void SMDiagnostic::Print(const char *ProgName, raw_ostream &S) { if (ProgName && ProgName[0]) S << ProgName << ": "; - if (Filename == "-") - S << "<stdin>"; - else - S << Filename; + if (!Filename.empty()) { + if (Filename == "-") + S << "<stdin>"; + else + S << Filename; - if (LineNo != -1) { - S << ':' << LineNo; - if (ColumnNo != -1) - S << ':' << (ColumnNo+1); + if (LineNo != -1) { + S << ':' << LineNo; + if (ColumnNo != -1) + S << ':' << (ColumnNo+1); + } + S << ": "; } - S << ": " << Message << '\n'; + S << Message << '\n'; if (LineNo != -1 && ColumnNo != -1 && ShowLine) { S << LineContents << '\n'; diff --git a/lib/Support/StringExtras.cpp b/lib/Support/StringExtras.cpp index 785e0ec..eb2fa08 100644 --- a/lib/Support/StringExtras.cpp +++ b/lib/Support/StringExtras.cpp @@ -39,13 +39,11 @@ std::pair<StringRef, StringRef> llvm::getToken(StringRef Source, StringRef Delimiters) { // Figure out where the token starts. StringRef::size_type Start = Source.find_first_not_of(Delimiters); - if (Start == StringRef::npos) Start = Source.size(); // Find the next occurrence of the delimiter. StringRef::size_type End = Source.find_first_of(Delimiters, Start); - if (End == StringRef::npos) End = Source.size(); - return std::make_pair(Source.substr(Start, End), Source.substr(End)); + return std::make_pair(Source.slice(Start, End), Source.substr(End)); } /// SplitString - Split up the specified string according to the specified diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index a820210..10d7ec0 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -562,6 +562,17 @@ raw_svector_ostream::~raw_svector_ostream() { flush(); } +/// resync - This is called when the SmallVector we're appending to is changed +/// outside of the raw_svector_ostream's control. It is only safe to do this +/// if the raw_svector_ostream has previously been flushed. +void raw_svector_ostream::resync() { + assert(GetNumBytesInBuffer() == 0 && "Didn't flush before mutating vector"); + + if (OS.capacity() - OS.size() < 64) + OS.reserve(OS.capacity() * 2); + SetBuffer(OS.end(), OS.capacity() - OS.size()); +} + void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { assert(Ptr == OS.end() && OS.size() + Size <= OS.capacity() && "Invalid write_impl() call!"); diff --git a/lib/System/Host.cpp b/lib/System/Host.cpp index 79897e4..e7193db 100644 --- a/lib/System/Host.cpp +++ b/lib/System/Host.cpp @@ -299,3 +299,7 @@ std::string sys::getHostCPUName() { return "generic"; } #endif + +bool sys::getHostCPUFeatures(StringMap<bool> &Features){ + return false; +} diff --git a/lib/System/Unix/TimeValue.inc b/lib/System/Unix/TimeValue.inc index 1ae8c71..d8cc8f5 100644 --- a/lib/System/Unix/TimeValue.inc +++ b/lib/System/Unix/TimeValue.inc @@ -48,7 +48,7 @@ TimeValue TimeValue::now() { } return TimeValue( - static_cast<TimeValue::SecondsType>( the_time.tv_sec ), + static_cast<TimeValue::SecondsType>( the_time.tv_sec + PosixZeroTime.seconds_ ), static_cast<TimeValue::NanoSecondsType>( the_time.tv_usec * NANOSECONDS_PER_MICROSECOND ) ); } diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 969c4a4..fd46a4a 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -715,7 +715,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, RC == ARM::QPR_VFP2RegisterClass) && "Unknown regclass!"); // FIXME: Neon instructions should support predicates if (Align >= 16 - && (getRegisterInfo().needsStackRealignment(MF))) { + && (getRegisterInfo().canRealignStack(MF))) { AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64)) .addFrameIndex(FI).addImm(0).addImm(0).addImm(128) .addMemOperand(MMO) @@ -760,7 +760,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, RC == ARM::QPR_VFP2RegisterClass || RC == ARM::QPR_8RegisterClass) && "Unknown regclass!"); if (Align >= 16 - && (getRegisterInfo().needsStackRealignment(MF))) { + && (getRegisterInfo().canRealignStack(MF))) { AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64), DestReg) .addFrameIndex(FI).addImm(0).addImm(0).addImm(128) .addMemOperand(MMO)); diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index f1b6e1d..ba9e044 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -484,6 +484,14 @@ bool ARMBaseRegisterInfo::hasFP(const MachineFunction &MF) const { MFI->isFrameAddressTaken()); } +bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); + return (RealignStack && + !AFI->isThumb1OnlyFunction() && + !MFI->hasVarSizedObjects()); +} + bool ARMBaseRegisterInfo:: needsStackRealignment(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index 2788d07..f5ca25c 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -96,6 +96,7 @@ public: bool hasFP(const MachineFunction &MF) const; + bool canRealignStack(const MachineFunction &MF) const; bool needsStackRealignment(const MachineFunction &MF) const; bool cannotEliminateFrame(const MachineFunction &MF) const; diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 14a45b3..a260050 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -1296,12 +1296,12 @@ SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, Ops.push_back(Chain); if (!IsLoad) - return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+7); + return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+8); std::vector<EVT> ResTys(NumVecs, RegVT); ResTys.push_back(MVT::Other); SDNode *VLdLn = - CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+7); + CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+8); // For a 64-bit vector load to D registers, nothing more needs to be done. if (is64BitVector) return VLdLn; diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 7b62c00..76c6a27 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -340,7 +340,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) // ARM does not have ROTL. setOperationAction(ISD::ROTL, MVT::i32, Expand); - setOperationAction(ISD::CTTZ, MVT::i32, Expand); + setOperationAction(ISD::CTTZ, MVT::i32, Custom); setOperationAction(ISD::CTPOP, MVT::i32, Expand); if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) setOperationAction(ISD::CTLZ, MVT::i32, Expand); @@ -387,7 +387,8 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) - // Turn f64->i64 into VMOVRRD, i64 -> f64 to VMOVDRR iff target supports vfp2. + // Turn f64->i64 into VMOVRRD, i64 -> f64 to VMOVDRR + // iff target supports vfp2. setOperationAction(ISD::BIT_CONVERT, MVT::i64, Custom); // We want to custom lower some of our intrinsics. @@ -482,6 +483,8 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { case ARMISD::CMOV: return "ARMISD::CMOV"; case ARMISD::CNEG: return "ARMISD::CNEG"; + case ARMISD::RBIT: return "ARMISD::RBIT"; + case ARMISD::FTOSI: return "ARMISD::FTOSI"; case ARMISD::FTOUI: return "ARMISD::FTOUI"; case ARMISD::SITOF: return "ARMISD::SITOF"; @@ -2231,6 +2234,18 @@ SDValue ARMTargetLowering::LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) { return DAG.getMergeValues(Ops, 2, dl); } +static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + if (!ST->hasV6T2Ops()) + return SDValue(); + + SDValue rbit = DAG.getNode(ARMISD::RBIT, dl, VT, N->getOperand(0)); + return DAG.getNode(ISD::CTLZ, dl, VT, rbit); +} + static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST) { EVT VT = N->getValueType(0); @@ -3016,6 +3031,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { case ISD::SHL_PARTS: return LowerShiftLeftParts(Op, DAG); case ISD::SRL_PARTS: case ISD::SRA_PARTS: return LowerShiftRightParts(Op, DAG); + case ISD::CTTZ: return LowerCTTZ(Op.getNode(), DAG, Subtarget); case ISD::VSETCC: return LowerVSETCC(Op, DAG); case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG); case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); @@ -3516,7 +3532,8 @@ static SDValue PerformSUBCombine(SDNode *N, return SDValue(); } -/// PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD. +/// PerformVMOVRRDCombine - Target-specific dag combine xforms for +/// ARMISD::VMOVRRD. static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) { // fmrrd(fmdrr x, y) -> x,y diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index e1b3348..cd9c027 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -53,6 +53,8 @@ namespace llvm { CMOV, // ARM conditional move instructions. CNEG, // ARM conditional negate instructions. + RBIT, // ARM bitreverse instruction + FTOSI, // FP to sint within a FP register. FTOUI, // FP to uint within a FP register. SITOF, // sint to FP within a FP register. diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index f67e74a..af508ee 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -107,6 +107,8 @@ def ARMMemBarrierV6 : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIERV6, def ARMSyncBarrierV6 : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIERV6, [SDNPHasChain]>; +def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>; + //===----------------------------------------------------------------------===// // ARM Instruction Predicate Definitions. // @@ -1455,6 +1457,15 @@ def CLZ : AMiscA1I<0b000010110, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, let Inst{19-16} = 0b1111; } +def RBIT : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "rbit", "\t$dst, $src", + [(set GPR:$dst, (ARMrbit GPR:$src))]>, + Requires<[IsARM, HasV6T2]> { + let Inst{7-4} = 0b0011; + let Inst{11-8} = 0b1111; + let Inst{19-16} = 0b1111; +} + def REV : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, "rev", "\t$dst, $src", [(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]> { @@ -1528,8 +1539,10 @@ def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), defm CMP : AI1_cmp_irs<0b1010, "cmp", BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>; -defm CMN : AI1_cmp_irs<0b1011, "cmn", - BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; +//FIXME: Disable CMN, as CCodes are backwards from compare expectations +// Compare-to-zero still works out, just not the relationals +//defm CMN : AI1_cmp_irs<0b1011, "cmn", +// BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; // Note that TST/TEQ don't set all the same flags that CMP does! defm TST : AI1_cmp_irs<0b1000, "tst", @@ -1542,11 +1555,11 @@ defm CMPz : AI1_cmp_irs<0b1010, "cmp", defm CMNz : AI1_cmp_irs<0b1011, "cmn", BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>; -def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm), - (CMNri GPR:$src, so_imm_neg:$imm)>; +//def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm), +// (CMNri GPR:$src, so_imm_neg:$imm)>; def : ARMPat<(ARMcmpZ GPR:$src, so_imm_neg:$imm), - (CMNri GPR:$src, so_imm_neg:$imm)>; + (CMNzri GPR:$src, so_imm_neg:$imm)>; // Conditional moves diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index 61b7705..cd063bf 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -197,12 +197,12 @@ let mayLoad = 1, hasExtraDefRegAllocReq = 1 in { class VLD2D<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b10,0b1000,op7_4, (outs DPR:$dst1, DPR:$dst2), (ins addrmode6:$addr), IIC_VLD2, - OpcodeStr, Dt, "\\{$dst1,$dst2\\}, $addr", "", []>; + OpcodeStr, Dt, "\\{$dst1, $dst2\\}, $addr", "", []>; class VLD2Q<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b10,0b0011,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4), (ins addrmode6:$addr), IIC_VLD2, - OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr", + OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr", "", []>; def VLD2d8 : VLD2D<0b0000, "vld2", "8">; @@ -210,7 +210,7 @@ def VLD2d16 : VLD2D<0b0100, "vld2", "16">; def VLD2d32 : VLD2D<0b1000, "vld2", "32">; def VLD2d64 : NLdSt<0,0b10,0b1010,0b1100, (outs DPR:$dst1, DPR:$dst2), (ins addrmode6:$addr), IIC_VLD1, - "vld1", "64", "\\{$dst1,$dst2\\}, $addr", "", []>; + "vld1", "64", "\\{$dst1, $dst2\\}, $addr", "", []>; def VLD2q8 : VLD2Q<0b0000, "vld2", "8">; def VLD2q16 : VLD2Q<0b0100, "vld2", "16">; @@ -220,11 +220,11 @@ def VLD2q32 : VLD2Q<0b1000, "vld2", "32">; class VLD3D<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b10,0b0100,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3), (ins addrmode6:$addr), IIC_VLD3, - OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3\\}, $addr", "", []>; + OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3\\}, $addr", "", []>; class VLD3WB<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b10,0b0101,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, GPR:$wb), (ins addrmode6:$addr), IIC_VLD3, - OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3\\}, $addr", + OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3\\}, $addr", "$addr.addr = $wb", []>; def VLD3d8 : VLD3D<0b0000, "vld3", "8">; @@ -233,7 +233,7 @@ def VLD3d32 : VLD3D<0b1000, "vld3", "32">; def VLD3d64 : NLdSt<0,0b10,0b0110,0b1100, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3), (ins addrmode6:$addr), IIC_VLD1, - "vld1", "64", "\\{$dst1,$dst2,$dst3\\}, $addr", "", []>; + "vld1", "64", "\\{$dst1, $dst2, $dst3\\}, $addr", "", []>; // vld3 to double-spaced even registers. def VLD3q8a : VLD3WB<0b0000, "vld3", "8">; @@ -250,13 +250,13 @@ class VLD4D<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b10,0b0000,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4), (ins addrmode6:$addr), IIC_VLD4, - OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr", + OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr", "", []>; class VLD4WB<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b10,0b0001,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb), (ins addrmode6:$addr), IIC_VLD4, - OpcodeStr, Dt, "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr", + OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr", "$addr.addr = $wb", []>; def VLD4d8 : VLD4D<0b0000, "vld4", "8">; @@ -265,7 +265,8 @@ def VLD4d32 : VLD4D<0b1000, "vld4", "32">; def VLD4d64 : NLdSt<0,0b10,0b0010,0b1100, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4), (ins addrmode6:$addr), IIC_VLD1, - "vld1", "64", "\\{$dst1,$dst2,$dst3,$dst4\\}, $addr", "", []>; + "vld1", "64", "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr", + "", []>; // vld4 to double-spaced even registers. def VLD4q8a : VLD4WB<0b0000, "vld4", "8">; @@ -285,7 +286,7 @@ class VLD2LN<bits<4> op11_8, string OpcodeStr, string Dt> : NLdSt<1,0b10,op11_8,{?,?,?,?}, (outs DPR:$dst1, DPR:$dst2), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, nohash_imm:$lane), IIC_VLD2, - OpcodeStr, Dt, "\\{$dst1[$lane],$dst2[$lane]\\}, $addr", + OpcodeStr, Dt, "\\{$dst1[$lane], $dst2[$lane]\\}, $addr", "$src1 = $dst1, $src2 = $dst2", []>; // vld2 to single-spaced registers. @@ -319,7 +320,7 @@ class VLD3LN<bits<4> op11_8, string OpcodeStr, string Dt> (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, nohash_imm:$lane), IIC_VLD3, OpcodeStr, Dt, - "\\{$dst1[$lane],$dst2[$lane],$dst3[$lane]\\}, $addr", + "\\{$dst1[$lane], $dst2[$lane], $dst3[$lane]\\}, $addr", "$src1 = $dst1, $src2 = $dst2, $src3 = $dst3", []>; // vld3 to single-spaced registers. @@ -356,7 +357,7 @@ class VLD4LN<bits<4> op11_8, string OpcodeStr, string Dt> (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, nohash_imm:$lane), IIC_VLD4, OpcodeStr, Dt, - "\\{$dst1[$lane],$dst2[$lane],$dst3[$lane],$dst4[$lane]\\}, $addr", + "\\{$dst1[$lane], $dst2[$lane], $dst3[$lane], $dst4[$lane]\\}, $addr", "$src1 = $dst1, $src2 = $dst2, $src3 = $dst3, $src4 = $dst4", []>; // vld4 to single-spaced registers. @@ -423,12 +424,12 @@ let mayStore = 1, hasExtraSrcRegAllocReq = 1 in { class VST2D<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b00,0b1000,op7_4, (outs), (ins addrmode6:$addr, DPR:$src1, DPR:$src2), IIC_VST, - OpcodeStr, Dt, "\\{$src1,$src2\\}, $addr", "", []>; + OpcodeStr, Dt, "\\{$src1, $src2\\}, $addr", "", []>; class VST2Q<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b00,0b0011,op7_4, (outs), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), IIC_VST, - OpcodeStr, Dt, "\\{$src1,$src2,$src3,$src4\\}, $addr", + OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr", "", []>; def VST2d8 : VST2D<0b0000, "vst2", "8">; @@ -436,7 +437,7 @@ def VST2d16 : VST2D<0b0100, "vst2", "16">; def VST2d32 : VST2D<0b1000, "vst2", "32">; def VST2d64 : NLdSt<0,0b00,0b1010,0b1100, (outs), (ins addrmode6:$addr, DPR:$src1, DPR:$src2), IIC_VST, - "vst1", "64", "\\{$src1,$src2\\}, $addr", "", []>; + "vst1", "64", "\\{$src1, $src2\\}, $addr", "", []>; def VST2q8 : VST2Q<0b0000, "vst2", "8">; def VST2q16 : VST2Q<0b0100, "vst2", "16">; @@ -446,11 +447,11 @@ def VST2q32 : VST2Q<0b1000, "vst2", "32">; class VST3D<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b00,0b0100,op7_4, (outs), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), IIC_VST, - OpcodeStr, Dt, "\\{$src1,$src2,$src3\\}, $addr", "", []>; + OpcodeStr, Dt, "\\{$src1, $src2, $src3\\}, $addr", "", []>; class VST3WB<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b00,0b0101,op7_4, (outs GPR:$wb), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), IIC_VST, - OpcodeStr, Dt, "\\{$src1,$src2,$src3\\}, $addr", + OpcodeStr, Dt, "\\{$src1, $src2, $src3\\}, $addr", "$addr.addr = $wb", []>; def VST3d8 : VST3D<0b0000, "vst3", "8">; @@ -459,7 +460,7 @@ def VST3d32 : VST3D<0b1000, "vst3", "32">; def VST3d64 : NLdSt<0,0b00,0b0110,0b1100, (outs), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), IIC_VST, - "vst1", "64", "\\{$src1,$src2,$src3\\}, $addr", "", []>; + "vst1", "64", "\\{$src1, $src2, $src3\\}, $addr", "", []>; // vst3 to double-spaced even registers. def VST3q8a : VST3WB<0b0000, "vst3", "8">; @@ -476,13 +477,13 @@ class VST4D<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b00,0b0000,op7_4, (outs), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), IIC_VST, - OpcodeStr, Dt, "\\{$src1,$src2,$src3,$src4\\}, $addr", + OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr", "", []>; class VST4WB<bits<4> op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b00,0b0001,op7_4, (outs GPR:$wb), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), IIC_VST, - OpcodeStr, Dt, "\\{$src1,$src2,$src3,$src4\\}, $addr", + OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr", "$addr.addr = $wb", []>; def VST4d8 : VST4D<0b0000, "vst4", "8">; @@ -491,7 +492,8 @@ def VST4d32 : VST4D<0b1000, "vst4", "32">; def VST4d64 : NLdSt<0,0b00,0b0010,0b1100, (outs), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), IIC_VST, - "vst1", "64", "\\{$src1,$src2,$src3,$src4\\}, $addr", "", []>; + "vst1", "64", "\\{$src1, $src2, $src3, $src4\\}, $addr", + "", []>; // vst4 to double-spaced even registers. def VST4q8a : VST4WB<0b0000, "vst4", "8">; @@ -511,7 +513,7 @@ class VST2LN<bits<4> op11_8, string OpcodeStr, string Dt> : NLdSt<1,0b00,op11_8,{?,?,?,?}, (outs), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, nohash_imm:$lane), IIC_VST, - OpcodeStr, Dt, "\\{$src1[$lane],$src2[$lane]\\}, $addr", + OpcodeStr, Dt, "\\{$src1[$lane], $src2[$lane]\\}, $addr", "", []>; // vst2 to single-spaced registers. @@ -545,7 +547,7 @@ class VST3LN<bits<4> op11_8, string OpcodeStr, string Dt> (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, nohash_imm:$lane), IIC_VST, OpcodeStr, Dt, - "\\{$src1[$lane],$src2[$lane],$src3[$lane]\\}, $addr", "", []>; + "\\{$src1[$lane], $src2[$lane], $src3[$lane]\\}, $addr", "", []>; // vst3 to single-spaced registers. def VST3LNd8 : VST3LN<0b0010, "vst3", "8"> { @@ -580,7 +582,7 @@ class VST4LN<bits<4> op11_8, string OpcodeStr, string Dt> (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, nohash_imm:$lane), IIC_VST, OpcodeStr, Dt, - "\\{$src1[$lane],$src2[$lane],$src3[$lane],$src4[$lane]\\}, $addr", + "\\{$src1[$lane], $src2[$lane], $src3[$lane], $src4[$lane]\\}, $addr", "", []>; // vst4 to single-spaced registers. @@ -2116,7 +2118,7 @@ def VACGTq : N3VQInt<1, 0, 0b10, 0b1110, 1, IIC_VBINQ, "vacgt", "f32", v4i32, v4f32, int_arm_neon_vacgtq, 0>; // VTST : Vector Test Bits defm VTST : N3V_QHS<0, 0, 0b1000, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, - IIC_VBINi4Q, "vtst", "i", NEONvtst, 1>; + IIC_VBINi4Q, "vtst", "", NEONvtst, 1>; // Vector Bitwise Operations. @@ -3022,19 +3024,19 @@ let hasExtraSrcRegAllocReq = 1 in { def VTBL2 : N3V<1,1,0b11,0b1001,0,0, (outs DPR:$dst), (ins DPR:$tbl1, DPR:$tbl2, DPR:$src), IIC_VTB2, - "vtbl", "8", "$dst, \\{$tbl1,$tbl2\\}, $src", "", + "vtbl", "8", "$dst, \\{$tbl1, $tbl2\\}, $src", "", [(set DPR:$dst, (v8i8 (int_arm_neon_vtbl2 DPR:$tbl1, DPR:$tbl2, DPR:$src)))]>; def VTBL3 : N3V<1,1,0b11,0b1010,0,0, (outs DPR:$dst), (ins DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$src), IIC_VTB3, - "vtbl", "8", "$dst, \\{$tbl1,$tbl2,$tbl3\\}, $src", "", + "vtbl", "8", "$dst, \\{$tbl1, $tbl2, $tbl3\\}, $src", "", [(set DPR:$dst, (v8i8 (int_arm_neon_vtbl3 DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$src)))]>; def VTBL4 : N3V<1,1,0b11,0b1011,0,0, (outs DPR:$dst), (ins DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src), IIC_VTB4, - "vtbl", "8", "$dst, \\{$tbl1,$tbl2,$tbl3,$tbl4\\}, $src", "", + "vtbl", "8", "$dst, \\{$tbl1, $tbl2, $tbl3, $tbl4\\}, $src", "", [(set DPR:$dst, (v8i8 (int_arm_neon_vtbl4 DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src)))]>; } // hasExtraSrcRegAllocReq = 1 @@ -3050,19 +3052,20 @@ let hasExtraSrcRegAllocReq = 1 in { def VTBX2 : N3V<1,1,0b11,0b1001,1,0, (outs DPR:$dst), (ins DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$src), IIC_VTBX2, - "vtbx", "8", "$dst, \\{$tbl1,$tbl2\\}, $src", "$orig = $dst", + "vtbx", "8", "$dst, \\{$tbl1, $tbl2\\}, $src", "$orig = $dst", [(set DPR:$dst, (v8i8 (int_arm_neon_vtbx2 DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$src)))]>; def VTBX3 : N3V<1,1,0b11,0b1010,1,0, (outs DPR:$dst), (ins DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$src), IIC_VTBX3, - "vtbx", "8", "$dst, \\{$tbl1,$tbl2,$tbl3\\}, $src", "$orig = $dst", + "vtbx", "8", "$dst, \\{$tbl1, $tbl2, $tbl3\\}, $src", "$orig = $dst", [(set DPR:$dst, (v8i8 (int_arm_neon_vtbx3 DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$src)))]>; def VTBX4 : N3V<1,1,0b11,0b1011,1,0, (outs DPR:$dst), (ins DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src), IIC_VTBX4, - "vtbx", "8", "$dst, \\{$tbl1,$tbl2,$tbl3,$tbl4\\}, $src", "$orig = $dst", + "vtbx", "8", "$dst, \\{$tbl1, $tbl2, $tbl3, $tbl4\\}, $src", + "$orig = $dst", [(set DPR:$dst, (v8i8 (int_arm_neon_vtbx4 DPR:$orig, DPR:$tbl1, DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src)))]>; } // hasExtraSrcRegAllocReq = 1 diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 603ccf5..746caff 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -208,7 +208,7 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1 in { let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst", [(brind GPR:$dst)]>, - T1Special<{1,0,1,1}> { + T1Special<{1,0,1,?}> { // <Rd> = Inst{7:2-0} = pc let Inst{2-0} = 0b111; } @@ -534,10 +534,12 @@ def tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, // CMN register let Defs = [CPSR] in { -def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, - "cmn", "\t$lhs, $rhs", - [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>, - T1DataProcessing<0b1011>; +//FIXME: Disable CMN, as CCodes are backwards from compare expectations +// Compare-to-zero still works out, just not the relationals +//def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, +// "cmn", "\t$lhs, $rhs", +// [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>, +// T1DataProcessing<0b1011>; def tCMNz : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, "cmn", "\t$lhs, $rhs", [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>, @@ -630,13 +632,13 @@ def tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, // FIXME: Make these predicable. def tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr, "mov\t$dst, $src", []>, - T1Special<{1,0,0,1}>; + T1Special<{1,0,0,?}>; def tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr, "mov\t$dst, $src", []>, - T1Special<{1,0,1,0}>; + T1Special<{1,0,?,0}>; def tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, "mov\t$dst, $src", []>, - T1Special<{1,0,1,1}>; + T1Special<{1,0,?,?}>; } // neverHasSideEffects // multiply register @@ -771,7 +773,7 @@ let usesCustomInserter = 1 in // Expanded after instruction selection. // 16-bit movcc in IT blocks for Thumb2. def tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr, "mov", "\t$dst, $rhs", []>, - T1Special<{1,0,1,1}>; + T1Special<{1,0,?,?}>; def tMOVCCi : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iCMOVi, "mov", "\t$dst, $rhs", []>, diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 769df7e..c7591d2 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -1540,6 +1540,10 @@ class T2I_misc<bits<2> op1, bits<2> op2, dag oops, dag iops, InstrItinClass itin def t2CLZ : T2I_misc<0b11, 0b00, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, "clz", "\t$dst, $src", [(set GPR:$dst, (ctlz GPR:$src))]>; +def t2RBIT : T2I_misc<0b01, 0b10, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "rbit", "\t$dst, $src", + [(set GPR:$dst, (ARMrbit GPR:$src))]>; + def t2REV : T2I_misc<0b01, 0b00, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, "rev", ".w\t$dst, $src", [(set GPR:$dst, (bswap GPR:$src))]>; @@ -1605,16 +1609,18 @@ defm t2CMP : T2I_cmp_irs<0b1101, "cmp", defm t2CMPz : T2I_cmp_irs<0b1101, "cmp", BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>; -defm t2CMN : T2I_cmp_irs<0b1000, "cmn", - BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; +//FIXME: Disable CMN, as CCodes are backwards from compare expectations +// Compare-to-zero still works out, just not the relationals +//defm t2CMN : T2I_cmp_irs<0b1000, "cmn", +// BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; defm t2CMNz : T2I_cmp_irs<0b1000, "cmn", BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>; -def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm), - (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>; +//def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm), +// (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>; def : T2Pat<(ARMcmpZ GPR:$src, t2_so_imm_neg:$imm), - (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>; + (t2CMNzri GPR:$src, t2_so_imm_neg:$imm)>; defm t2TST : T2I_cmp_irs<0b0000, "tst", BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>; diff --git a/lib/Target/ARM/ARMMCAsmInfo.cpp b/lib/Target/ARM/ARMMCAsmInfo.cpp index 0ff65d2..3dd87c0 100644 --- a/lib/Target/ARM/ARMMCAsmInfo.cpp +++ b/lib/Target/ARM/ARMMCAsmInfo.cpp @@ -64,7 +64,7 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() { PrivateGlobalPrefix = ".L"; WeakRefDirective = "\t.weak\t"; SetDirective = "\t.set\t"; - LCOMMDirective = "\t.lcomm\t"; + HasLCOMMDirective = true; DwarfRequiresFrameSection = false; diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index 1c6fca7..4d20a5c 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -93,10 +93,6 @@ bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM, if (Subtarget.hasNEON()) PM.add(createNEONPreAllocPass()); - // Calculate and set max stack object alignment early, so we can decide - // whether we will need stack realignment (and thus FP). - PM.add(createMaxStackAlignmentCalculatorPass()); - // FIXME: temporarily disabling load / store optimization pass for Thumb1. if (OptLevel != CodeGenOpt::None && !Subtarget.isThumb1Only()) PM.add(createARMLoadStoreOptimizationPass(true)); diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 132738e..89c7769 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -8,18 +8,18 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAsmLexer.h" -#include "llvm/MC/MCAsmParser.h" -#include "llvm/MC/MCParsedAsmOperand.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/SourceMgr.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetAsmParser.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" using namespace llvm; namespace { @@ -222,7 +222,7 @@ struct ARMOperand : public MCParsedAsmOperand { /// TODO this is likely to change to allow different register types and or to /// parse for a specific register type. bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) { - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.getTok(); assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); // FIXME: Validate register for the current architecture; we have to do @@ -232,14 +232,14 @@ bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) { RegNum = MatchRegisterName(Tok.getString()); if (RegNum == -1) return true; - getLexer().Lex(); // Eat identifier token. + Parser.Lex(); // Eat identifier token. bool Writeback = false; if (ParseWriteBack) { - const AsmToken &ExclaimTok = getLexer().getTok(); + const AsmToken &ExclaimTok = Parser.getTok(); if (ExclaimTok.is(AsmToken::Exclaim)) { Writeback = true; - getLexer().Lex(); // Eat exclaim token + Parser.Lex(); // Eat exclaim token } } @@ -251,26 +251,26 @@ bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) { /// Parse a register list, return false if successful else return true or an /// error. The first token must be a '{' when called. bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) { - assert(getLexer().getTok().is(AsmToken::LCurly) && + assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not an Left Curly Brace"); - getLexer().Lex(); // Eat left curly brace token. + Parser.Lex(); // Eat left curly brace token. - const AsmToken &RegTok = getLexer().getTok(); + const AsmToken &RegTok = Parser.getTok(); SMLoc RegLoc = RegTok.getLoc(); if (RegTok.isNot(AsmToken::Identifier)) return Error(RegLoc, "register expected"); int RegNum = MatchRegisterName(RegTok.getString()); if (RegNum == -1) return Error(RegLoc, "register expected"); - getLexer().Lex(); // Eat identifier token. + Parser.Lex(); // Eat identifier token. unsigned RegList = 1 << RegNum; int HighRegNum = RegNum; // TODO ranges like "{Rn-Rm}" - while (getLexer().getTok().is(AsmToken::Comma)) { - getLexer().Lex(); // Eat comma token. + while (Parser.getTok().is(AsmToken::Comma)) { + Parser.Lex(); // Eat comma token. - const AsmToken &RegTok = getLexer().getTok(); + const AsmToken &RegTok = Parser.getTok(); SMLoc RegLoc = RegTok.getLoc(); if (RegTok.isNot(AsmToken::Identifier)) return Error(RegLoc, "register expected"); @@ -285,12 +285,12 @@ bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) { RegList |= 1 << RegNum; HighRegNum = RegNum; - getLexer().Lex(); // Eat identifier token. + Parser.Lex(); // Eat identifier token. } - const AsmToken &RCurlyTok = getLexer().getTok(); + const AsmToken &RCurlyTok = Parser.getTok(); if (RCurlyTok.isNot(AsmToken::RCurly)) return Error(RCurlyTok.getLoc(), "'}' expected"); - getLexer().Lex(); // Eat left curly brace token. + Parser.Lex(); // Eat left curly brace token. return false; } @@ -300,11 +300,11 @@ bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) { /// TODO Only preindexing and postindexing addressing are started, unindexed /// with option, etc are still to do. bool ARMAsmParser::ParseMemory(ARMOperand &Op) { - assert(getLexer().getTok().is(AsmToken::LBrac) && + assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not an Left Bracket"); - getLexer().Lex(); // Eat left bracket token. + Parser.Lex(); // Eat left bracket token. - const AsmToken &BaseRegTok = getLexer().getTok(); + const AsmToken &BaseRegTok = Parser.getTok(); if (BaseRegTok.isNot(AsmToken::Identifier)) return Error(BaseRegTok.getLoc(), "register expected"); if (MaybeParseRegister(Op, false)) @@ -319,10 +319,10 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { // First look for preindexed address forms, that is after the "[Rn" we now // have to see if the next token is a comma. - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.getTok(); if (Tok.is(AsmToken::Comma)) { Preindexed = true; - getLexer().Lex(); // Eat comma token. + Parser.Lex(); // Eat comma token. int OffsetRegNum; bool OffsetRegShifted; enum ShiftType ShiftType; @@ -331,15 +331,15 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, Offset, OffsetIsReg, OffsetRegNum)) return true; - const AsmToken &RBracTok = getLexer().getTok(); + const AsmToken &RBracTok = Parser.getTok(); if (RBracTok.isNot(AsmToken::RBrac)) return Error(RBracTok.getLoc(), "']' expected"); - getLexer().Lex(); // Eat right bracket token. + Parser.Lex(); // Eat right bracket token. - const AsmToken &ExclaimTok = getLexer().getTok(); + const AsmToken &ExclaimTok = Parser.getTok(); if (ExclaimTok.is(AsmToken::Exclaim)) { Writeback = true; - getLexer().Lex(); // Eat exclaim token + Parser.Lex(); // Eat exclaim token } Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, OffsetRegShifted, ShiftType, ShiftAmount, @@ -352,7 +352,7 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { // the "[Rn". Postindexed = true; Writeback = true; - getLexer().Lex(); // Eat right bracket token. + Parser.Lex(); // Eat right bracket token. int OffsetRegNum = 0; bool OffsetRegShifted = false; @@ -360,11 +360,11 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { const MCExpr *ShiftAmount; const MCExpr *Offset; - const AsmToken &NextTok = getLexer().getTok(); + const AsmToken &NextTok = Parser.getTok(); if (NextTok.isNot(AsmToken::EndOfStatement)) { if (NextTok.isNot(AsmToken::Comma)) return Error(NextTok.getLoc(), "',' expected"); - getLexer().Lex(); // Eat comma token. + Parser.Lex(); // Eat comma token. if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, Offset, OffsetIsReg, OffsetRegNum)) return true; @@ -398,15 +398,15 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, OffsetRegShifted = false; OffsetIsReg = false; OffsetRegNum = -1; - const AsmToken &NextTok = getLexer().getTok(); + const AsmToken &NextTok = Parser.getTok(); if (NextTok.is(AsmToken::Plus)) - getLexer().Lex(); // Eat plus token. + Parser.Lex(); // Eat plus token. else if (NextTok.is(AsmToken::Minus)) { Negative = true; - getLexer().Lex(); // Eat minus token + Parser.Lex(); // Eat minus token } // See if there is a register following the "[Rn," or "[Rn]," we have so far. - const AsmToken &OffsetRegTok = getLexer().getTok(); + const AsmToken &OffsetRegTok = Parser.getTok(); if (OffsetRegTok.is(AsmToken::Identifier)) { OffsetIsReg = !MaybeParseRegister(Op, false); if (OffsetIsReg) @@ -415,11 +415,11 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, // If we parsed a register as the offset then their can be a shift after that if (OffsetRegNum != -1) { // Look for a comma then a shift - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.getTok(); if (Tok.is(AsmToken::Comma)) { - getLexer().Lex(); // Eat comma token. + Parser.Lex(); // Eat comma token. - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.getTok(); if (ParseShift(ShiftType, ShiftAmount)) return Error(Tok.getLoc(), "shift expected"); OffsetRegShifted = true; @@ -427,10 +427,10 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, } else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm" // Look for #offset following the "[Rn," or "[Rn]," - const AsmToken &HashTok = getLexer().getTok(); + const AsmToken &HashTok = Parser.getTok(); if (HashTok.isNot(AsmToken::Hash)) return Error(HashTok.getLoc(), "'#' expected"); - getLexer().Lex(); // Eat hash token. + Parser.Lex(); // Eat hash token. if (getParser().ParseExpression(Offset)) return true; @@ -443,7 +443,7 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, /// rrx /// and returns true if it parses a shift otherwise it returns false. bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount) { - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) return true; const StringRef &ShiftName = Tok.getString(); @@ -459,17 +459,17 @@ bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount) { St = Rrx; else return true; - getLexer().Lex(); // Eat shift type token. + Parser.Lex(); // Eat shift type token. // Rrx stands alone. if (St == Rrx) return false; // Otherwise, there must be a '#' and a shift amount. - const AsmToken &HashTok = getLexer().getTok(); + const AsmToken &HashTok = Parser.getTok(); if (HashTok.isNot(AsmToken::Hash)) return Error(HashTok.getLoc(), "'#' expected"); - getLexer().Lex(); // Eat hash token. + Parser.Lex(); // Eat hash token. if (getParser().ParseExpression(ShiftAmount)) return true; @@ -569,14 +569,14 @@ bool ARMAsmParser::ParseOperand(ARMOperand &Op) { case AsmToken::Hash: // #42 -> immediate. // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate - getLexer().Lex(); + Parser.Lex(); const MCExpr *ImmVal; if (getParser().ParseExpression(ImmVal)) return true; Op = ARMOperand::CreateImm(ImmVal); return false; default: - return Error(getLexer().getTok().getLoc(), "unexpected token in operand"); + return Error(Parser.getTok().getLoc(), "unexpected token in operand"); } } @@ -585,7 +585,7 @@ bool ARMAsmParser::ParseInstruction(const StringRef &Name, SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands) { Operands.push_back(new ARMOperand(ARMOperand::CreateToken(Name))); - SMLoc Loc = getLexer().getTok().getLoc(); + SMLoc Loc = Parser.getTok().getLoc(); if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. @@ -594,7 +594,7 @@ bool ARMAsmParser::ParseInstruction(const StringRef &Name, SMLoc NameLoc, Operands.push_back(new ARMOperand(Op)); while (getLexer().is(AsmToken::Comma)) { - getLexer().Lex(); // Eat the comma. + Parser.Lex(); // Eat the comma. // Parse and remember the operand. if (ParseOperand(Op)) return true; @@ -629,7 +629,7 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { if (getParser().ParseExpression(Value)) return true; - getParser().getStreamer().EmitValue(Value, Size); + getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/); if (getLexer().is(AsmToken::EndOfStatement)) break; @@ -637,11 +637,11 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { // FIXME: Improve diagnostic. if (getLexer().isNot(AsmToken::Comma)) return Error(L, "unexpected token in directive"); - getLexer().Lex(); + Parser.Lex(); } } - getLexer().Lex(); + Parser.Lex(); return false; } @@ -650,7 +650,7 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(L, "unexpected token in directive"); - getLexer().Lex(); + Parser.Lex(); // TODO: set thumb mode // TODO: tell the MC streamer the mode @@ -661,15 +661,15 @@ bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { /// ParseDirectiveThumbFunc /// ::= .thumbfunc symbol_name bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) return Error(L, "unexpected token in .syntax directive"); - StringRef ATTRIBUTE_UNUSED SymbolName = getLexer().getTok().getIdentifier(); - getLexer().Lex(); // Consume the identifier token. + StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier(); + Parser.Lex(); // Consume the identifier token. if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(L, "unexpected token in directive"); - getLexer().Lex(); + Parser.Lex(); // TODO: mark symbol as a thumb symbol // getParser().getStreamer().Emit???(); @@ -679,25 +679,25 @@ bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { /// ParseDirectiveSyntax /// ::= .syntax unified | divided bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) { - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) return Error(L, "unexpected token in .syntax directive"); const StringRef &Mode = Tok.getString(); bool unified_syntax; if (Mode == "unified" || Mode == "UNIFIED") { - getLexer().Lex(); + Parser.Lex(); unified_syntax = true; } else if (Mode == "divided" || Mode == "DIVIDED") { - getLexer().Lex(); + Parser.Lex(); unified_syntax = false; } else return Error(L, "unrecognized syntax mode in .syntax directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getTok().getLoc(), "unexpected token in directive"); - getLexer().Lex(); + return Error(Parser.getTok().getLoc(), "unexpected token in directive"); + Parser.Lex(); // TODO tell the MC streamer the mode // getParser().getStreamer().Emit???(); @@ -707,25 +707,25 @@ bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) { /// ParseDirectiveCode /// ::= .code 16 | 32 bool ARMAsmParser::ParseDirectiveCode(SMLoc L) { - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Integer)) return Error(L, "unexpected token in .code directive"); - int64_t Val = getLexer().getTok().getIntVal(); + int64_t Val = Parser.getTok().getIntVal(); bool thumb_mode; if (Val == 16) { - getLexer().Lex(); + Parser.Lex(); thumb_mode = true; } else if (Val == 32) { - getLexer().Lex(); + Parser.Lex(); thumb_mode = false; } else return Error(L, "invalid operand to .code directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getTok().getLoc(), "unexpected token in directive"); - getLexer().Lex(); + return Error(Parser.getTok().getLoc(), "unexpected token in directive"); + Parser.Lex(); // TODO tell the MC streamer the mode // getParser().getStreamer().Emit???(); diff --git a/lib/Target/ARM/AsmParser/Makefile b/lib/Target/ARM/AsmParser/Makefile index 97e5612..4fb8564 100644 --- a/lib/Target/ARM/AsmParser/Makefile +++ b/lib/Target/ARM/AsmParser/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMARMAsmParser +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' ARM target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index 2d13533..e1f386e 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -49,7 +49,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" #include <cctype> using namespace llvm; @@ -160,7 +159,6 @@ namespace { unsigned AsmVariant, const char *ExtraCode); - void PrintGlobalVariable(const GlobalVariable* GVar); void printInstruction(const MachineInstr *MI); // autogenerated. static const char *getRegisterName(unsigned RegNo); @@ -172,7 +170,12 @@ namespace { /// EmitMachineConstantPoolValue - Print a machine constantpool value to /// the .s file. virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { - printDataDirective(MCPV->getType()); + switch (TM.getTargetData()->getTypeAllocSize(MCPV->getType())) { + case 1: O << MAI->getData8bitsDirective(0); break; + case 2: O << MAI->getData16bitsDirective(0); break; + case 4: O << MAI->getData32bitsDirective(0); break; + default: assert(0 && "Unknown CPV size"); + } ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV); SmallString<128> TmpNameStr; @@ -184,32 +187,27 @@ namespace { } else if (ACPV->isBlockAddress()) { O << GetBlockAddressSymbol(ACPV->getBlockAddress())->getName(); } else if (ACPV->isGlobalValue()) { - std::string Name; GlobalValue *GV = ACPV->getGV(); bool isIndirect = Subtarget->isTargetDarwin() && Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel()); if (!isIndirect) - Name = Mang->getMangledName(GV); + O << *GetGlobalValueSymbol(GV); else { // FIXME: Remove this when Darwin transition to @GOT like syntax. - Name = Mang->getMangledName(GV, "$non_lazy_ptr", true); - MCSymbol *Sym = OutContext.GetOrCreateSymbol(StringRef(Name)); + MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + O << *Sym; MachineModuleInfoMachO &MMIMachO = MMI->getObjFileInfo<MachineModuleInfoMachO>(); const MCSymbol *&StubSym = GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) : MMIMachO.getGVStubEntry(Sym); - if (StubSym == 0) { - Mang->getNameWithPrefix(TmpNameStr, GV, false); - StubSym = OutContext.GetOrCreateSymbol(TmpNameStr.str()); - } + if (StubSym == 0) + StubSym = GetGlobalValueSymbol(GV); } - O << Name; } else { assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); - Mang->getNameWithPrefix(TmpNameStr, ACPV->getSymbol()); - OutContext.GetOrCreateSymbol(TmpNameStr.str())->print(O, MAI); + O << *GetExternalSymbolSymbol(ACPV->getSymbol()); } if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; @@ -219,9 +217,9 @@ namespace { << "+" << (unsigned)ACPV->getPCAdjustment(); if (ACPV->mustAddCurrentAddress()) O << "-."; - O << ")"; + O << ')'; } - O << "\n"; + O << '\n'; } void getAnalysisUsage(AnalysisUsage &AU) const { @@ -262,7 +260,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { case Function::InternalLinkage: break; case Function::ExternalLinkage: - O << "\t.globl\t" << CurrentFnName << "\n"; + O << "\t.globl\t" << *CurrentFnSym << "\n"; break; case Function::LinkerPrivateLinkage: case Function::WeakAnyLinkage: @@ -270,15 +268,15 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { case Function::LinkOnceAnyLinkage: case Function::LinkOnceODRLinkage: if (Subtarget->isTargetDarwin()) { - O << "\t.globl\t" << CurrentFnName << "\n"; - O << "\t.weak_definition\t" << CurrentFnName << "\n"; + O << "\t.globl\t" << *CurrentFnSym << "\n"; + O << "\t.weak_definition\t" << *CurrentFnSym << "\n"; } else { - O << MAI->getWeakRefDirective() << CurrentFnName << "\n"; + O << MAI->getWeakRefDirective() << *CurrentFnSym << "\n"; } break; } - printVisibility(CurrentFnName, F->getVisibility()); + printVisibility(CurrentFnSym, F->getVisibility()); unsigned FnAlign = 1 << MF.getAlignment(); // MF alignment is log2. if (AFI->isThumbFunction()) { @@ -286,13 +284,13 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { O << "\t.code\t16\n"; O << "\t.thumb_func"; if (Subtarget->isTargetDarwin()) - O << "\t" << CurrentFnName; + O << "\t" << *CurrentFnSym; O << "\n"; } else { EmitAlignment(FnAlign, F); } - O << CurrentFnName << ":\n"; + O << *CurrentFnSym << ":\n"; // Emit pre-function debug information. DW->BeginFunction(&MF); @@ -320,7 +318,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { } if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; + O << "\t.size " << *CurrentFnSym << ", .-" << *CurrentFnSym << "\n"; // Emit post-function debug information. DW->EndFunction(&MF); @@ -369,7 +367,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, break; } case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_GlobalAddress: { bool isCallOp = Modifier && !strcmp(Modifier, "call"); @@ -381,7 +379,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, else if ((Modifier && strcmp(Modifier, "hi16") == 0) || (TF & ARMII::MO_HI16)) O << ":upper16:"; - O << Mang->getMangledName(GV); + O << *GetGlobalValueSymbol(GV); printOffset(MO.getOffset()); @@ -392,9 +390,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, } case MachineOperand::MO_ExternalSymbol: { bool isCallOp = Modifier && !strcmp(Modifier, "call"); - SmallString<128> NameStr; - Mang->getNameWithPrefix(NameStr, MO.getSymbolName()); - OutContext.GetOrCreateSymbol(NameStr.str())->print(O, MAI); + O << *GetExternalSymbolSymbol(MO.getSymbolName()); if (isCallOp && Subtarget->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_) @@ -402,12 +398,10 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, break; } case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() - << '_' << MO.getIndex(); + O << *GetCPISymbol(MO.getIndex()); break; case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); + O << *GetJTISymbol(MO.getIndex()); break; } } @@ -895,8 +889,7 @@ void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, // data itself. if (!strcmp(Modifier, "label")) { unsigned ID = MI->getOperand(OpNum).getImm(); - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() - << '_' << ID << ":\n"; + O << *GetCPISymbol(ID) << ":\n"; } else { assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); unsigned CPI = MI->getOperand(OpNum).getIndex(); @@ -916,6 +909,7 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) { const MachineOperand &MO1 = MI->getOperand(OpNum); const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id + unsigned JTI = MO1.getIndex(); O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm() << ":\n"; @@ -941,11 +935,11 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) { << '_' << JTI << '_' << MO2.getImm() << "_set_" << MBB->getNumber(); else if (TM.getRelocationModel() == Reloc::PIC_) { - GetMBBSymbol(MBB->getNumber())->print(O, MAI); - O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" + O << *GetMBBSymbol(MBB->getNumber()) + << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm(); } else { - GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MBB->getNumber()); } if (i != e-1) O << '\n'; @@ -976,13 +970,11 @@ void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum) { else if (HalfWordOffset) O << MAI->getData16bitsDirective(); if (ByteOffset || HalfWordOffset) { - O << '('; - GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << '(' << *GetMBBSymbol(MBB->getNumber()); O << "-" << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm() << ")/2"; } else { - O << "\tb.w "; - GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << "\tb.w " << *GetMBBSymbol(MBB->getNumber()); } if (i != e-1) O << '\n'; @@ -1174,146 +1166,6 @@ void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { } } -void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) // External global require no code - return; - - // Check to see if this is a special global used by LLVM, if so, emit it. - - if (EmitSpecialLLVMGlobal(GVar)) { - if (Subtarget->isTargetDarwin() && - TM.getRelocationModel() == Reloc::Static) { - if (GVar->getName() == "llvm.global_ctors") - O << ".reference .constructors_used\n"; - else if (GVar->getName() == "llvm.global_dtors") - O << ".reference .destructors_used\n"; - } - return; - } - - std::string name = Mang->getMangledName(GVar); - Constant *C = GVar->getInitializer(); - const Type *Type = C->getType(); - unsigned Size = TD->getTypeAllocSize(Type); - unsigned Align = TD->getPreferredAlignmentLog(GVar); - bool isDarwin = Subtarget->isTargetDarwin(); - - printVisibility(name, GVar->getVisibility()); - - if (Subtarget->isTargetELF()) - O << "\t.type " << name << ",%object\n"; - - const MCSection *TheSection = - getObjFileLowering().SectionForGlobal(GVar, Mang, TM); - OutStreamer.SwitchSection(TheSection); - - // FIXME: get this stuff from section kind flags. - if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() && - // Don't put things that should go in the cstring section into "comm". - !TheSection->getKind().isMergeableCString()) { - if (GVar->hasExternalLinkage()) { - if (const char *Directive = MAI->getZeroFillDirective()) { - O << "\t.globl\t" << name << "\n"; - O << Directive << "__DATA, __common, " << name << ", " - << Size << ", " << Align << "\n"; - return; - } - } - - if (GVar->hasLocalLinkage() || GVar->isWeakForLinker()) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (isDarwin) { - if (GVar->hasLocalLinkage()) { - O << MAI->getLCOMMDirective() << name << "," << Size - << ',' << Align; - } else if (GVar->hasCommonLinkage()) { - O << MAI->getCOMMDirective() << name << "," << Size - << ',' << Align; - } else { - OutStreamer.SwitchSection(TheSection); - O << "\t.globl " << name << '\n' - << MAI->getWeakDefDirective() << name << '\n'; - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - EmitGlobalConstant(C); - return; - } - } else if (MAI->getLCOMMDirective() != NULL) { - if (GVar->hasLocalLinkage()) { - O << MAI->getLCOMMDirective() << name << "," << Size; - } else { - O << MAI->getCOMMDirective() << name << "," << Size; - if (MAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); - } - } else { - if (GVar->hasLocalLinkage()) - O << "\t.local\t" << name << "\n"; - O << MAI->getCOMMDirective() << name << "," << Size; - if (MAI->getCOMMDirectiveTakesAlignment()) - O << "," << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); - } - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << "\n"; - return; - } - } - - switch (GVar->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::LinkerPrivateLinkage: - if (isDarwin) { - O << "\t.globl " << name << "\n" - << "\t.weak_definition " << name << "\n"; - } else { - O << "\t.weak " << name << "\n"; - } - break; - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - O << "\t.globl " << name << "\n"; - break; - case GlobalValue::PrivateLinkage: - case GlobalValue::InternalLinkage: - break; - default: - llvm_unreachable("Unknown linkage type!"); - } - - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << "\n"; - if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size " << name << ", " << Size << "\n"; - - EmitGlobalConstant(C); - O << '\n'; -} - void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { if (Subtarget->isTargetDarwin()) { @@ -1333,10 +1185,8 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); EmitAlignment(2); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { - Stubs[i].first->print(O, MAI); - O << ":\n\t.indirect_symbol "; - Stubs[i].second->print(O, MAI); - O << "\n\t.long\t0\n"; + O << *Stubs[i].first << ":\n\t.indirect_symbol "; + O << *Stubs[i].second << "\n\t.long\t0\n"; } } @@ -1344,12 +1194,8 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { if (!Stubs.empty()) { OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); EmitAlignment(2); - for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { - Stubs[i].first->print(O, MAI); - O << ":\n\t.long "; - Stubs[i].second->print(O, MAI); - O << "\n"; - } + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) + O << *Stubs[i].first << ":\n\t.long " << *Stubs[i].second << "\n"; } // Funny Darwin hack: This flag tells the linker that no global symbols @@ -1357,7 +1203,7 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { // implementation of multiple entry points). If this doesn't occur, the // linker can safely perform dead code stripping. Since LLVM never // generates code that does this, it is always safe to set. - OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols); + OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); } } @@ -1416,12 +1262,7 @@ void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); EmitAlignment(2); - - const char *Prefix = MAI->getPrivateGlobalPrefix(); - MCSymbol *Label = OutContext.GetOrCreateSymbol(Twine(Prefix)+"CPI"+ - Twine(getFunctionNumber())+ - "_"+ Twine(LabelId)); - OutStreamer.EmitLabel(Label); + OutStreamer.EmitLabel(GetCPISymbol(LabelId)); const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; if (MCPE.isMachineConstantPoolEntry()) diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp index 9fc57e0..6885ecb 100644 --- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp @@ -62,7 +62,7 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, } else { assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); assert(Op.isExpr() && "unknown operand kind in printOperand"); - Op.getExpr()->print(O, &MAI); + O << *Op.getExpr(); } } diff --git a/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp b/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp index c49fee3..f843ee2 100644 --- a/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp @@ -22,7 +22,6 @@ #include "llvm/MC/MCInst.h" //#include "llvm/MC/MCStreamer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Mangler.h" #include "llvm/ADT/SmallString.h" using namespace llvm; @@ -40,33 +39,24 @@ MachineModuleInfoMachO &ARMMCInstLower::getMachOMMI() const { MCSymbol *ARMMCInstLower:: GetGlobalAddressSymbol(const MachineOperand &MO) const { - const GlobalValue *GV = MO.getGlobal(); - - SmallString<128> Name; - Mang.getNameWithPrefix(Name, GV, false); - // FIXME: HANDLE PLT references how?? switch (MO.getTargetFlags()) { default: assert(0 && "Unknown target flag on GV operand"); case 0: break; } - return Ctx.GetOrCreateSymbol(Name.str()); + return Printer.GetGlobalValueSymbol(MO.getGlobal()); } MCSymbol *ARMMCInstLower:: GetExternalSymbolSymbol(const MachineOperand &MO) const { - SmallString<128> Name; - Name += Printer.MAI->getGlobalPrefix(); - Name += MO.getSymbolName(); - // FIXME: HANDLE PLT references how?? switch (MO.getTargetFlags()) { default: assert(0 && "Unknown target flag on GV operand"); case 0: break; } - return Ctx.GetOrCreateSymbol(Name.str()); + return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); } diff --git a/lib/Target/ARM/AsmPrinter/Makefile b/lib/Target/ARM/AsmPrinter/Makefile index 208becc..93b8fc9 100644 --- a/lib/Target/ARM/AsmPrinter/Makefile +++ b/lib/Target/ARM/AsmPrinter/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMARMAsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' arm target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/ARM/Makefile b/lib/Target/ARM/Makefile index a8dd38c..b766a86 100644 --- a/lib/Target/ARM/Makefile +++ b/lib/Target/ARM/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMARMCodeGen TARGET = ARM +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc \ diff --git a/lib/Target/ARM/README.txt b/lib/Target/ARM/README.txt index 11c48ad..a6f26a5 100644 --- a/lib/Target/ARM/README.txt +++ b/lib/Target/ARM/README.txt @@ -596,3 +596,12 @@ Make use of the "rbit" instruction. Take a look at test/CodeGen/Thumb2/machine-licm.ll. ARM should be taught how to licm and cse the unnecessary load from cp#1. + +//===---------------------------------------------------------------------===// + +The CMN instruction sets the flags like an ADD instruction, while CMP sets +them like a subtract. Therefore to be able to use CMN for comparisons other +than the Z bit, we'll need additional logic to reverse the conditionals +associated with the comparison. Perhaps a pseudo-instruction for the comparison, +with a post-codegen pass to clean up and handle the condition codes? +See PR5694 for testcase. diff --git a/lib/Target/ARM/TargetInfo/Makefile b/lib/Target/ARM/TargetInfo/Makefile index 6292ab1..589dbe5 100644 --- a/lib/Target/ARM/TargetInfo/Makefile +++ b/lib/Target/ARM/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMARMInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/ARM/Thumb1InstrInfo.cpp b/lib/Target/ARM/Thumb1InstrInfo.cpp index e875394..7f42c82 100644 --- a/lib/Target/ARM/Thumb1InstrInfo.cpp +++ b/lib/Target/ARM/Thumb1InstrInfo.cpp @@ -105,7 +105,9 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, (TargetRegisterInfo::isPhysicalRegister(SrcReg) && isARMLowRegister(SrcReg))) && "Unknown regclass!"); - if (RC == ARM::tGPRRegisterClass) { + if (RC == ARM::tGPRRegisterClass || + (TargetRegisterInfo::isPhysicalRegister(SrcReg) && + isARMLowRegister(SrcReg))) { MachineFunction &MF = *MBB.getParent(); MachineFrameInfo &MFI = *MF.getFrameInfo(); MachineMemOperand *MMO = @@ -130,7 +132,9 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, (TargetRegisterInfo::isPhysicalRegister(DestReg) && isARMLowRegister(DestReg))) && "Unknown regclass!"); - if (RC == ARM::tGPRRegisterClass) { + if (RC == ARM::tGPRRegisterClass || + (TargetRegisterInfo::isPhysicalRegister(DestReg) && + isARMLowRegister(DestReg))) { MachineFunction &MF = *MBB.getParent(); MachineFrameInfo &MFI = *MF.getFrameInfo(); MachineMemOperand *MMO = diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index 9f3816a..d6630ce 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -479,11 +479,15 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, "Thumb add/sub sp, #imm immediate must be multiple of 4!"); } - if (Offset == 0) { + unsigned PredReg; + if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { // Turn it into a move. MI.setDesc(TII.get(ARM::tMOVgpr2tgpr)); MI.getOperand(i).ChangeToRegister(FrameReg, false); - MI.RemoveOperand(i+1); + // Remove offset and remaining explicit predicate operands. + do MI.RemoveOperand(i+1); + while (MI.getNumOperands() > i+1 && + (!MI.getOperand(i+1).isReg() || !MI.getOperand(i+1).isImm())); return 0; } diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index f4a8c27..387edaf 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -329,12 +329,16 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, Offset += MI.getOperand(FrameRegIdx+1).getImm(); bool isSP = FrameReg == ARM::SP; - if (Offset == 0) { + unsigned PredReg; + if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { // Turn it into a move. MI.setDesc(TII.get(ARM::tMOVgpr2gpr)); MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); - MI.RemoveOperand(FrameRegIdx+1); - Offset = 0; + // Remove offset and remaining explicit predicate operands. + do MI.RemoveOperand(FrameRegIdx+1); + while (MI.getNumOperands() > FrameRegIdx+1 && + (!MI.getOperand(FrameRegIdx+1).isReg() || + !MI.getOperand(FrameRegIdx+1).isImm())); return true; } diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp index 35359aa..95288bf 100644 --- a/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -65,7 +65,8 @@ namespace { { ARM::t2ASRri, ARM::tASRri, 0, 5, 0, 1, 0, 0,0, 0 }, { ARM::t2ASRrr, 0, ARM::tASRrr, 0, 0, 0, 1, 0,0, 0 }, { ARM::t2BICrr, 0, ARM::tBIC, 0, 0, 0, 1, 0,0, 0 }, - { ARM::t2CMNrr, ARM::tCMN, 0, 0, 0, 1, 0, 2,0, 0 }, + //FIXME: Disable CMN, as CCodes are backwards from compare expectations + //{ ARM::t2CMNrr, ARM::tCMN, 0, 0, 0, 1, 0, 2,0, 0 }, { ARM::t2CMPri, ARM::tCMPi8, 0, 8, 0, 1, 0, 2,0, 0 }, { ARM::t2CMPrr, ARM::tCMPhir, 0, 0, 0, 0, 0, 2,0, 0 }, { ARM::t2CMPzri,ARM::tCMPzi8, 0, 8, 0, 1, 0, 2,0, 0 }, diff --git a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp index 338057b..b13f544 100644 --- a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp +++ b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp @@ -28,7 +28,6 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/FormattedStream.h" #include "llvm/ADT/Statistic.h" using namespace llvm; @@ -53,7 +52,6 @@ namespace { void printOp(const MachineOperand &MO, bool IsCallOp = false); void printOperand(const MachineInstr *MI, int opNum); void printBaseOffsetPair(const MachineInstr *MI, int i, bool brackets=true); - void PrintGlobalVariable(const GlobalVariable *GVar); bool runOnMachineFunction(MachineFunction &F); void EmitStartOfAsmFile(Module &M); @@ -95,7 +93,7 @@ void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) { return; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_ConstantPoolIndex: @@ -108,7 +106,7 @@ void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) { return; case MachineOperand::MO_GlobalAddress: - O << Mang->getMangledName(MO.getGlobal()); + O << *GetGlobalValueSymbol(MO.getGlobal()); return; case MachineOperand::MO_JumpTableIndex: @@ -148,29 +146,29 @@ bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) { case Function::PrivateLinkage: case Function::LinkerPrivateLinkage: break; - case Function::ExternalLinkage: - O << "\t.globl " << CurrentFnName << "\n"; - break; + case Function::ExternalLinkage: + O << "\t.globl " << *CurrentFnSym << '\n'; + break; case Function::WeakAnyLinkage: case Function::WeakODRLinkage: case Function::LinkOnceAnyLinkage: case Function::LinkOnceODRLinkage: - O << MAI->getWeakRefDirective() << CurrentFnName << "\n"; + O << MAI->getWeakRefDirective() << *CurrentFnSym << '\n'; break; } - printVisibility(CurrentFnName, F->getVisibility()); + printVisibility(CurrentFnSym, F->getVisibility()); - O << "\t.ent " << CurrentFnName << "\n"; + O << "\t.ent " << *CurrentFnSym << "\n"; - O << CurrentFnName << ":\n"; + O << *CurrentFnSym << ":\n"; // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { - if (I != MF.begin()) { + if (I != MF.begin()) EmitBasicBlockStart(I); - } + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { // Print the assembly for the instruction. @@ -185,7 +183,7 @@ bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) { } } - O << "\t.end " << CurrentFnName << "\n"; + O << "\t.end " << *CurrentFnSym << "\n"; // We didn't modify anything. return false; @@ -199,62 +197,6 @@ void AlphaAsmPrinter::EmitStartOfAsmFile(Module &M) { O << "\t.set noat\n"; } -void AlphaAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) - return; - - std::string name = Mang->getMangledName(GVar); - Constant *C = GVar->getInitializer(); - unsigned Size = TD->getTypeAllocSize(C->getType()); - unsigned Align = TD->getPreferredAlignmentLog(GVar); - - // 0: Switch to section - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang, - TM)); - - // 1: Check visibility - printVisibility(name, GVar->getVisibility()); - - // 2: Kind - switch (GVar->getLinkage()) { - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::CommonLinkage: - O << MAI->getWeakRefDirective() << name << '\n'; - break; - case GlobalValue::AppendingLinkage: - case GlobalValue::ExternalLinkage: - O << MAI->getGlobalDirective() << name << "\n"; - break; - case GlobalValue::InternalLinkage: - case GlobalValue::PrivateLinkage: - case GlobalValue::LinkerPrivateLinkage: - break; - default: - llvm_unreachable("Unknown linkage type!"); - } - - // 3: Type, Size, Align - if (MAI->hasDotTypeDotSizeDirective()) { - O << "\t.type\t" << name << ", @object\n"; - O << "\t.size\t" << name << ", " << Size << "\n"; - } - - EmitAlignment(Align, GVar); - - O << name << ":\n"; - - EmitGlobalConstant(C); - O << '\n'; -} - /// PrintAsmOperand - Print out an operand for an inline asm expression. /// bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, diff --git a/lib/Target/Alpha/AsmPrinter/Makefile b/lib/Target/Alpha/AsmPrinter/Makefile index 3c64a3c..3f64aac 100644 --- a/lib/Target/Alpha/AsmPrinter/Makefile +++ b/lib/Target/Alpha/AsmPrinter/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMAlphaAsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' alpha target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/Alpha/Makefile b/lib/Target/Alpha/Makefile index d2d7109..14cbc6c 100644 --- a/lib/Target/Alpha/Makefile +++ b/lib/Target/Alpha/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMAlphaCodeGen TARGET = Alpha +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = AlphaGenRegisterInfo.h.inc AlphaGenRegisterNames.inc \ diff --git a/lib/Target/Alpha/TargetInfo/Makefile b/lib/Target/Alpha/TargetInfo/Makefile index de01d7f..6f7b898 100644 --- a/lib/Target/Alpha/TargetInfo/Makefile +++ b/lib/Target/Alpha/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMAlphaInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp index 0bd94d4..749f735 100644 --- a/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp +++ b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp @@ -30,7 +30,6 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegistry.h" -#include "llvm/Support/Mangler.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" @@ -55,13 +54,12 @@ namespace { void printInstruction(const MachineInstr *MI); // autogenerated. static const char *getRegisterName(unsigned RegNo); - void emitLinkage(const std::string &n, GlobalValue::LinkageTypes l); + void emitLinkage(const MCSymbol *GVSym, GlobalValue::LinkageTypes l); bool runOnMachineFunction(MachineFunction &F); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode); bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode); - void PrintGlobalVariable(const GlobalVariable* GVar); }; } // end of anonymous namespace @@ -71,48 +69,27 @@ extern "C" void LLVMInitializeBlackfinAsmPrinter() { RegisterAsmPrinter<BlackfinAsmPrinter> X(TheBlackfinTarget); } -void BlackfinAsmPrinter::emitLinkage(const std::string &name, - GlobalValue::LinkageTypes l) { - switch (l) { +void BlackfinAsmPrinter::emitLinkage(const MCSymbol *GVSym, + GlobalValue::LinkageTypes L) { + switch (L) { default: llvm_unreachable("Unknown linkage type!"); case GlobalValue::InternalLinkage: // Symbols default to internal. case GlobalValue::PrivateLinkage: case GlobalValue::LinkerPrivateLinkage: break; case GlobalValue::ExternalLinkage: - O << MAI->getGlobalDirective() << name << "\n"; + O << MAI->getGlobalDirective() << *GVSym << "\n"; break; case GlobalValue::LinkOnceAnyLinkage: case GlobalValue::LinkOnceODRLinkage: case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakODRLinkage: - O << MAI->getGlobalDirective() << name << "\n"; - O << MAI->getWeakDefDirective() << name << "\n"; + O << MAI->getGlobalDirective() << *GVSym << "\n"; + O << MAI->getWeakDefDirective() << *GVSym << "\n"; break; } } -void BlackfinAsmPrinter::PrintGlobalVariable(const GlobalVariable* GV) { - const TargetData *TD = TM.getTargetData(); - - if (!GV->hasInitializer() || EmitSpecialLLVMGlobal(GV)) - return; - - std::string name = Mang->getMangledName(GV); - Constant *C = GV->getInitializer(); - - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang, - TM)); - emitLinkage(name, GV->getLinkage()); - EmitAlignment(TD->getPreferredAlignmentLog(GV), GV); - printVisibility(name, GV->getVisibility()); - - O << "\t.type " << name << ", STT_OBJECT\n"; - O << "\t.size " << name << ',' << TD->getTypeAllocSize(C->getType()) << '\n'; - O << name << ":\n"; - EmitGlobalConstant(C); -} - /// runOnMachineFunction - This uses the printInstruction() /// method to print assembly for each instruction. /// @@ -124,11 +101,11 @@ bool BlackfinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { const Function *F = MF.getFunction(); OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); EmitAlignment(2, F); - emitLinkage(CurrentFnName, F->getLinkage()); - printVisibility(CurrentFnName, F->getVisibility()); + emitLinkage(CurrentFnSym, F->getLinkage()); + printVisibility(CurrentFnSym, F->getVisibility()); - O << "\t.type\t" << CurrentFnName << ", STT_FUNC\n" - << CurrentFnName << ":\n"; + O << "\t.type\t" << *CurrentFnSym << ", STT_FUNC\n"; + O << *CurrentFnSym << ":\n"; if (DW) DW->BeginFunction(&MF); @@ -154,7 +131,7 @@ bool BlackfinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { } } - O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; + O << "\t.size " << *CurrentFnSym << ", .-" << *CurrentFnSym << "\n"; if (DW) DW->EndFunction(&MF); @@ -175,18 +152,15 @@ void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { O << MO.getImm(); break; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_GlobalAddress: - O << Mang->getMangledName(MO.getGlobal()); + O << *GetGlobalValueSymbol(MO.getGlobal()); printOffset(MO.getOffset()); break; - case MachineOperand::MO_ExternalSymbol: { - SmallString<60> NameStr; - Mang->getNameWithPrefix(NameStr, MO.getSymbolName()); - OutContext.GetOrCreateSymbol(NameStr.str())->print(O, MAI); + case MachineOperand::MO_ExternalSymbol: + O << *GetExternalSymbolSymbol(MO.getSymbolName()); break; - } case MachineOperand::MO_ConstantPoolIndex: O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" << MO.getIndex(); diff --git a/lib/Target/Blackfin/AsmPrinter/Makefile b/lib/Target/Blackfin/AsmPrinter/Makefile index 091d4df..30e8285 100644 --- a/lib/Target/Blackfin/AsmPrinter/Makefile +++ b/lib/Target/Blackfin/AsmPrinter/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMBlackfinAsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' Blackfin target directory to grab private # headers diff --git a/lib/Target/Blackfin/Makefile b/lib/Target/Blackfin/Makefile index c68760b..4fdaf27 100644 --- a/lib/Target/Blackfin/Makefile +++ b/lib/Target/Blackfin/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMBlackfinCodeGen TARGET = Blackfin +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = BlackfinGenRegisterInfo.h.inc BlackfinGenRegisterNames.inc \ diff --git a/lib/Target/Blackfin/TargetInfo/Makefile b/lib/Target/Blackfin/TargetInfo/Makefile index c49cfbe..5c770cf 100644 --- a/lib/Target/Blackfin/TargetInfo/Makefile +++ b/lib/Target/Blackfin/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMBlackfinInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 0fd975c..e765655 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -33,6 +33,7 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/Target/Mangler.h" #include "llvm/Transforms/Scalar.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSymbol.h" @@ -44,7 +45,6 @@ #include "llvm/Support/FormattedStream.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/InstVisitor.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" #include "llvm/System/Host.h" #include "llvm/Config/config.h" @@ -58,6 +58,13 @@ extern "C" void LLVMInitializeCBackendTarget() { } namespace { + class CBEMCAsmInfo : public MCAsmInfo { + public: + CBEMCAsmInfo() { + GlobalPrefix = ""; + PrivateGlobalPrefix = ""; + } + }; /// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for /// any unnamed structure types that are used by the program, and merges /// external functions with the same name. @@ -344,11 +351,19 @@ namespace { char CWriter::ID = 0; -static std::string Mangle(const std::string &S) { +static std::string CBEMangle(const std::string &S) { std::string Result; - raw_string_ostream OS(Result); - MCSymbol::printMangledName(S, OS, 0); - return OS.str(); + + for (unsigned i = 0, e = S.size(); i != e; ++i) + if (isalnum(S[i]) || S[i] == '_') { + Result += S[i]; + } else { + Result += '_'; + Result += 'A'+(S[i]&15); + Result += 'A'+((S[i]>>4)&15); + Result += '_'; + } + return Result; } @@ -1445,7 +1460,7 @@ std::string CWriter::GetValueName(const Value *Operand) { if (const GlobalValue *GV = dyn_cast<GlobalValue>(Operand)) { SmallString<128> Str; Mang->getNameWithPrefix(Str, GV, false); - return Mangle(Str.str().str()); + return CBEMangle(Str.str().str()); } std::string Name = Operand->getName(); @@ -1869,8 +1884,17 @@ bool CWriter::doInitialization(Module &M) { IL = new IntrinsicLowering(*TD); IL->AddPrototypes(M); - // Ensure that all structure types have names... - Mang = new Mangler(M); +#if 0 + std::string Triple = TheModule->getTargetTriple(); + if (Triple.empty()) + Triple = llvm::sys::getHostTriple(); + + std::string E; + if (const Target *Match = TargetRegistry::lookupTarget(Triple, E)) + TAsm = Match->createAsmInfo(Triple); +#endif + TAsm = new CBEMCAsmInfo(); + Mang = new Mangler(*TAsm); // Keep track of which functions are static ctors/dtors so they can have // an attribute added to their prototypes. @@ -2223,7 +2247,7 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) { // Print out forward declarations for structure types before anything else! Out << "/* Structure forward decls */\n"; for (; I != End; ++I) { - std::string Name = "struct " + Mangle("l_"+I->first); + std::string Name = "struct " + CBEMangle("l_"+I->first); Out << Name << ";\n"; TypeNames.insert(std::make_pair(I->second, Name)); } @@ -2234,7 +2258,7 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) { // for struct or opaque types. Out << "/* Typedefs */\n"; for (I = TST.begin(); I != End; ++I) { - std::string Name = Mangle("l_"+I->first); + std::string Name = CBEMangle("l_"+I->first); Out << "typedef "; printType(Out, I->second, false, Name); Out << ";\n"; @@ -3240,30 +3264,31 @@ bool CWriter::visitBuiltinCall(CallInst &I, Intrinsic::ID ID, // of the per target tables // handle multiple constraint codes std::string CWriter::InterpretASMConstraint(InlineAsm::ConstraintInfo& c) { - assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle"); - const char *const *table = 0; - // Grab the translation table from MCAsmInfo if it exists. - if (!TAsm) { - std::string Triple = TheModule->getTargetTriple(); - if (Triple.empty()) - Triple = llvm::sys::getHostTriple(); - - std::string E; - if (const Target *Match = TargetRegistry::lookupTarget(Triple, E)) - TAsm = Match->createAsmInfo(Triple); - } - if (TAsm) - table = TAsm->getAsmCBE(); + const MCAsmInfo *TargetAsm; + std::string Triple = TheModule->getTargetTriple(); + if (Triple.empty()) + Triple = llvm::sys::getHostTriple(); + + std::string E; + if (const Target *Match = TargetRegistry::lookupTarget(Triple, E)) + TargetAsm = Match->createAsmInfo(Triple); + else + return c.Codes[0]; + + const char *const *table = TargetAsm->getAsmCBE(); // Search the translation table if it exists. for (int i = 0; table && table[i]; i += 2) - if (c.Codes[0] == table[i]) + if (c.Codes[0] == table[i]) { + delete TargetAsm; return table[i+1]; + } // Default is identity. + delete TargetAsm; return c.Codes[0]; } diff --git a/lib/Target/CBackend/Makefile b/lib/Target/CBackend/Makefile index 3b5ef0f..f82d277 100644 --- a/lib/Target/CBackend/Makefile +++ b/lib/Target/CBackend/Makefile @@ -9,6 +9,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMCBackend +CXXFLAGS = -fno-rtti DIRS = TargetInfo diff --git a/lib/Target/CBackend/TargetInfo/Makefile b/lib/Target/CBackend/TargetInfo/Makefile index d4d5e15..6407904 100644 --- a/lib/Target/CBackend/TargetInfo/Makefile +++ b/lib/Target/CBackend/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMCBackendInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/CMakeLists.txt b/lib/Target/CMakeLists.txt index 8769ee2..10478b4 100644 --- a/lib/Target/CMakeLists.txt +++ b/lib/Target/CMakeLists.txt @@ -1,6 +1,8 @@ add_llvm_library(LLVMTarget + Mangler.cpp SubtargetFeature.cpp Target.cpp + TargetAsmLexer.cpp TargetData.cpp TargetELFWriterInfo.cpp TargetFrameInfo.cpp diff --git a/lib/Target/CellSPU/AsmPrinter/Makefile b/lib/Target/CellSPU/AsmPrinter/Makefile index 69639ef..aa0db52 100644 --- a/lib/Target/CellSPU/AsmPrinter/Makefile +++ b/lib/Target/CellSPU/AsmPrinter/Makefile @@ -9,6 +9,7 @@ LEVEL = ../../../.. LIBRARYNAME = LLVMCellSPUAsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' CellSPU target directory to grab # private headers diff --git a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp index dc9f81c4..59d6ddd 100644 --- a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp +++ b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp @@ -39,9 +39,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" -#include <set> using namespace llvm; namespace { @@ -50,7 +48,6 @@ namespace { const std::string bss_section(".bss"); class SPUAsmPrinter : public AsmPrinter { - std::set<std::string> FnStubs, GVStubs; public: explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, const MCAsmInfo *T, bool V) : @@ -302,9 +299,6 @@ namespace { AU.addRequired<DwarfWriter>(); SPUAsmPrinter::getAnalysisUsage(AU); } - - //! Emit a global variable according to its section and type - void PrintGlobalVariable(const GlobalVariable* GVar); }; } // end of anonymous namespace @@ -318,7 +312,7 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO) { return; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_JumpTableIndex: O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() @@ -331,32 +325,25 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO) { case MachineOperand::MO_ExternalSymbol: // Computing the address of an external symbol, not calling it. if (TM.getRelocationModel() != Reloc::Static) { - std::string Name(MAI->getGlobalPrefix()); Name += MO.getSymbolName(); - GVStubs.insert(Name); - O << "L" << Name << "$non_lazy_ptr"; + O << "L" << MAI->getGlobalPrefix() << MO.getSymbolName() + << "$non_lazy_ptr"; return; } - O << MAI->getGlobalPrefix() << MO.getSymbolName(); + O << *GetExternalSymbolSymbol(MO.getSymbolName()); return; - case MachineOperand::MO_GlobalAddress: { - // Computing the address of a global symbol, not calling it. - GlobalValue *GV = MO.getGlobal(); - std::string Name = Mang->getMangledName(GV); - + case MachineOperand::MO_GlobalAddress: // External or weakly linked global variables need non-lazily-resolved // stubs if (TM.getRelocationModel() != Reloc::Static) { + GlobalValue *GV = MO.getGlobal(); if (((GV->isDeclaration() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) { - GVStubs.insert(Name); - O << "L" << Name << "$non_lazy_ptr"; + O << *GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); return; } } - O << Name; + O << *GetGlobalValueSymbol(MO.getGlobal()); return; - } - default: O << "<unknown operand type: " << MO.getType() << ">"; return; @@ -437,18 +424,19 @@ bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { case Function::InternalLinkage: // Symbols default to internal. break; case Function::ExternalLinkage: - O << "\t.global\t" << CurrentFnName << "\n" - << "\t.type\t" << CurrentFnName << ", @function\n"; + O << "\t.global\t" << *CurrentFnSym << "\n" << "\t.type\t"; + O << *CurrentFnSym << ", @function\n"; break; case Function::WeakAnyLinkage: case Function::WeakODRLinkage: case Function::LinkOnceAnyLinkage: case Function::LinkOnceODRLinkage: - O << "\t.global\t" << CurrentFnName << "\n"; - O << "\t.weak_definition\t" << CurrentFnName << "\n"; + O << "\t.global\t" << *CurrentFnSym << "\n"; + O << "\t.weak_definition\t" << *CurrentFnSym << "\n"; break; } - O << CurrentFnName << ":\n"; + + O << *CurrentFnSym << ":\n"; // Emit pre-function debug information. DW->BeginFunction(&MF); @@ -467,7 +455,7 @@ bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { } } - O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n"; + O << "\t.size\t" << *CurrentFnSym << ",.-" << *CurrentFnSym << "\n"; // Print out jump tables referenced by the function. EmitJumpTableInfo(MF.getJumpTableInfo(), MF); @@ -479,93 +467,6 @@ bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { return false; } - -/*! - Emit a global variable according to its section, alignment, etc. - - \note This code was shamelessly copied from the PowerPC's assembly printer, - which sort of screams for some kind of refactorization of common code. - */ -void LinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) - return; - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) - return; - - std::string name = Mang->getMangledName(GVar); - - printVisibility(name, GVar->getVisibility()); - - Constant *C = GVar->getInitializer(); - const Type *Type = C->getType(); - unsigned Size = TD->getTypeAllocSize(Type); - unsigned Align = TD->getPreferredAlignmentLog(GVar); - - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang, - TM)); - - if (C->isNullValue() && /* FIXME: Verify correct */ - !GVar->hasSection() && - (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() || - GVar->isWeakForLinker())) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (GVar->hasExternalLinkage()) { - O << "\t.global " << name << '\n'; - O << "\t.type " << name << ", @object\n"; - O << name << ":\n"; - O << "\t.zero " << Size << '\n'; - } else if (GVar->hasLocalLinkage()) { - O << MAI->getLCOMMDirective() << name << ',' << Size; - } else { - O << ".comm " << name << ',' << Size; - } - O << "\t\t" << MAI->getCommentString() << " '"; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - O << "'\n"; - return; - } - - switch (GVar->getLinkage()) { - // Should never be seen for the CellSPU platform... - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::CommonLinkage: - O << "\t.global " << name << '\n' - << "\t.type " << name << ", @object\n" - << "\t.weak " << name << '\n'; - break; - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << "\t.global " << name << '\n' - << "\t.type " << name << ", @object\n"; - // FALL THROUGH - case GlobalValue::PrivateLinkage: - case GlobalValue::LinkerPrivateLinkage: - case GlobalValue::InternalLinkage: - break; - default: - llvm_report_error("Unknown linkage type!"); - } - - EmitAlignment(Align, GVar); - O << name << ":\t\t\t\t" << MAI->getCommentString() << " '"; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - O << "'\n"; - - EmitGlobalConstant(C); - O << '\n'; -} - // Force static initialization. extern "C" void LLVMInitializeCellSPUAsmPrinter() { RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget); diff --git a/lib/Target/CellSPU/Makefile b/lib/Target/CellSPU/Makefile index 8415168..9f3ff74 100644 --- a/lib/Target/CellSPU/Makefile +++ b/lib/Target/CellSPU/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMCellSPUCodeGen TARGET = SPU +CXXFLAGS = -fno-rtti BUILT_SOURCES = SPUGenInstrNames.inc SPUGenRegisterNames.inc \ SPUGenAsmWriter.inc SPUGenCodeEmitter.inc \ diff --git a/lib/Target/CellSPU/SPUMCAsmInfo.cpp b/lib/Target/CellSPU/SPUMCAsmInfo.cpp index 1c921ab..03cdb29 100644 --- a/lib/Target/CellSPU/SPUMCAsmInfo.cpp +++ b/lib/Target/CellSPU/SPUMCAsmInfo.cpp @@ -19,7 +19,7 @@ SPULinuxMCAsmInfo::SPULinuxMCAsmInfo(const Target &T, const StringRef &TT) { SetDirective = "\t.set"; Data64bitsDirective = "\t.quad\t"; AlignmentIsInBytes = false; - LCOMMDirective = "\t.lcomm\t"; + HasLCOMMDirective = true; PCSymbol = "."; CommentString = "#"; diff --git a/lib/Target/CellSPU/TargetInfo/Makefile b/lib/Target/CellSPU/TargetInfo/Makefile index 9cb6827..30ca5cf 100644 --- a/lib/Target/CellSPU/TargetInfo/Makefile +++ b/lib/Target/CellSPU/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMCellSPUInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index a872fbd..73272bc 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -472,7 +472,6 @@ namespace { HANDLE_ATTR(Nest); HANDLE_ATTR(ReadNone); HANDLE_ATTR(ReadOnly); - HANDLE_ATTR(InlineHint); HANDLE_ATTR(NoInline); HANDLE_ATTR(AlwaysInline); HANDLE_ATTR(OptimizeForSize); diff --git a/lib/Target/CppBackend/Makefile b/lib/Target/CppBackend/Makefile index dc9cf48..52f2aad 100644 --- a/lib/Target/CppBackend/Makefile +++ b/lib/Target/CppBackend/Makefile @@ -9,6 +9,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMCppBackend +CXXFLAGS = -fno-rtti DIRS = TargetInfo diff --git a/lib/Target/CppBackend/TargetInfo/Makefile b/lib/Target/CppBackend/TargetInfo/Makefile index 6e68283..7e44aab 100644 --- a/lib/Target/CppBackend/TargetInfo/Makefile +++ b/lib/Target/CppBackend/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMCppBackendInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/MSIL/MSILWriter.cpp b/lib/Target/MSIL/MSILWriter.cpp index b3b91da..1bc708e 100644 --- a/lib/Target/MSIL/MSILWriter.cpp +++ b/lib/Target/MSIL/MSILWriter.cpp @@ -102,7 +102,6 @@ bool MSILWriter::runOnFunction(Function &F) { bool MSILWriter::doInitialization(Module &M) { ModulePtr = &M; - Mang = new Mangler(M); Out << ".assembly extern mscorlib {}\n"; Out << ".assembly MSIL {}\n\n"; Out << "// External\n"; @@ -118,7 +117,6 @@ bool MSILWriter::doInitialization(Module &M) { bool MSILWriter::doFinalization(Module &M) { - delete Mang; return false; } @@ -232,7 +230,7 @@ bool MSILWriter::isZeroValue(const Value* V) { std::string MSILWriter::getValueName(const Value* V) { std::string Name; if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) - Name = Mang->getMangledName(GV); + Name = GV->getName(); else { unsigned &No = AnonValueNumbers[V]; if (No == 0) No = ++NextAnonValueNumber; @@ -259,7 +257,7 @@ std::string MSILWriter::getLabelName(const std::string& Name) { std::string MSILWriter::getLabelName(const Value* V) { std::string Name; if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) - Name = Mang->getMangledName(GV); + Name = GV->getName(); else { unsigned &No = AnonValueNumbers[V]; if (No == 0) No = ++NextAnonValueNumber; @@ -1616,7 +1614,7 @@ const char* MSILWriter::getLibraryName(const Function* F) { const char* MSILWriter::getLibraryName(const GlobalVariable* GV) { - return getLibraryForSymbol(Mang->getMangledName(GV), false, CallingConv::C); + return getLibraryForSymbol(GV->getName(), false, CallingConv::C); } @@ -1674,7 +1672,7 @@ void MSILWriter::printExternals() { std::string Tmp = getTypeName(I->getType())+getValueName(&*I); printSimpleInstruction("ldsflda",Tmp.c_str()); Out << "\tldstr\t\"" << getLibraryName(&*I) << "\"\n"; - Out << "\tldstr\t\"" << Mang->getMangledName(&*I) << "\"\n"; + Out << "\tldstr\t\"" << I->getName() << "\"\n"; printSimpleInstruction("call","void* $MSIL_Import(string,string)"); printIndirectSave(I->getType()); } diff --git a/lib/Target/MSIL/MSILWriter.h b/lib/Target/MSIL/MSILWriter.h index 2280a3b..a95ae23 100644 --- a/lib/Target/MSIL/MSILWriter.h +++ b/lib/Target/MSIL/MSILWriter.h @@ -27,7 +27,6 @@ #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Support/Mangler.h" namespace llvm { extern Target TheMSILTarget; @@ -78,7 +77,6 @@ namespace llvm { formatted_raw_ostream &Out; Module* ModulePtr; const TargetData* TD; - Mangler* Mang; LoopInfo *LInfo; std::vector<StaticInitializer>* InitListPtr; std::map<const GlobalVariable*,std::vector<StaticInitializer> > diff --git a/lib/Target/MSIL/Makefile b/lib/Target/MSIL/Makefile index 8057cc7..9fecba5 100644 --- a/lib/Target/MSIL/Makefile +++ b/lib/Target/MSIL/Makefile @@ -9,6 +9,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMMSIL +CXXFLAGS = -fno-rtti DIRS = TargetInfo diff --git a/lib/Target/MSIL/TargetInfo/Makefile b/lib/Target/MSIL/TargetInfo/Makefile index 30b0950..710f5a1 100644 --- a/lib/Target/MSIL/TargetInfo/Makefile +++ b/lib/Target/MSIL/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMMSILInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp index 145359f..6033197 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp @@ -38,9 +38,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/ErrorHandling.h" - using namespace llvm; STATISTIC(EmittedInsts, "Number of machine instrs printed"); @@ -80,7 +78,6 @@ namespace { const char *ExtraCode); void printInstructionThroughMCStreamer(const MachineInstr *MI); - void PrintGlobalVariable(const GlobalVariable* GVar); void emitFunctionHeader(const MachineFunction &MF); bool runOnMachineFunction(MachineFunction &F); @@ -91,89 +88,6 @@ namespace { }; } // end of anonymous namespace -void MSP430AsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) - return; - - const TargetData *TD = TM.getTargetData(); - - std::string name = Mang->getMangledName(GVar); - Constant *C = GVar->getInitializer(); - unsigned Size = TD->getTypeAllocSize(C->getType()); - unsigned Align = TD->getPreferredAlignmentLog(GVar); - - printVisibility(name, GVar->getVisibility()); - - O << "\t.type\t" << name << ",@object\n"; - - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang, - TM)); - - if (C->isNullValue() && !GVar->hasSection() && - !GVar->isThreadLocal() && - (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) { - - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (GVar->hasLocalLinkage()) - O << "\t.local\t" << name << '\n'; - - O << MAI->getCOMMDirective() << name << ',' << Size; - if (MAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); - - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - return; - } - - switch (GVar->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - O << "\t.weak\t" << name << '\n'; - break; - case GlobalValue::DLLExportLinkage: - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << "\t.globl " << name << '\n'; - // FALL THROUGH - case GlobalValue::PrivateLinkage: - case GlobalValue::LinkerPrivateLinkage: - case GlobalValue::InternalLinkage: - break; - default: - assert(0 && "Unknown linkage type!"); - } - - // Use 16-bit alignment by default to simplify bunch of stuff - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - - EmitGlobalConstant(C); - - if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << name << ", " << Size << '\n'; -} void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { const Function *F = MF.getFunction(); @@ -190,20 +104,20 @@ void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { case Function::LinkerPrivateLinkage: break; case Function::ExternalLinkage: - O << "\t.globl\t" << CurrentFnName << '\n'; + O << "\t.globl\t" << *CurrentFnSym << '\n'; break; case Function::LinkOnceAnyLinkage: case Function::LinkOnceODRLinkage: case Function::WeakAnyLinkage: case Function::WeakODRLinkage: - O << "\t.weak\t" << CurrentFnName << '\n'; + O << "\t.weak\t" << *CurrentFnSym << '\n'; break; } - printVisibility(CurrentFnName, F->getVisibility()); + printVisibility(CurrentFnSym, F->getVisibility()); - O << "\t.type\t" << CurrentFnName << ",@function\n" - << CurrentFnName << ":\n"; + O << "\t.type\t" << *CurrentFnSym << ",@function\n"; + O << *CurrentFnSym << ":\n"; } bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) { @@ -226,7 +140,7 @@ bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) { } if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; + O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n'; // We didn't modify anything return false; @@ -259,18 +173,18 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, O << MO.getImm(); return; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_GlobalAddress: { bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - std::string Name = Mang->getMangledName(MO.getGlobal()); uint64_t Offset = MO.getOffset(); O << (isMemOp ? '&' : '#'); if (Offset) O << '(' << Offset << '+'; - O << Name; + O << *GetGlobalValueSymbol(MO.getGlobal()); + if (Offset) O << ')'; @@ -278,11 +192,8 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, } case MachineOperand::MO_ExternalSymbol: { bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - std::string Name(MAI->getGlobalPrefix()); - Name += MO.getSymbolName(); - - O << (isMemOp ? '&' : '#') << Name; - + O << (isMemOp ? '&' : '#'); + O << MAI->getGlobalPrefix() << MO.getSymbolName(); return; } default: diff --git a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp index 0a403c4..a480307 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp @@ -39,7 +39,7 @@ void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo) { O << Op.getImm(); else { assert(Op.isExpr() && "unknown pcrel immediate operand"); - Op.getExpr()->print(O, &MAI); + O << *Op.getExpr(); } } @@ -53,8 +53,7 @@ void MSP430InstPrinter::printOperand(const MCInst *MI, unsigned OpNo, O << '#' << Op.getImm(); } else { assert(Op.isExpr() && "unknown operand kind in printOperand"); - O << '#'; - Op.getExpr()->print(O, &MAI); + O << '#' << *Op.getExpr(); } } @@ -65,8 +64,7 @@ void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo, // Print displacement first if (Disp.isExpr()) { - O << '&'; - Disp.getExpr()->print(O, &MAI); + O << '&' << *Disp.getExpr(); } else { assert(Disp.isImm() && "Expected immediate in displacement field"); if (!Base.getReg()) diff --git a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp index 595b7e7..e1f80b7 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp @@ -22,37 +22,27 @@ #include "llvm/MC/MCInst.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Mangler.h" #include "llvm/ADT/SmallString.h" using namespace llvm; MCSymbol *MSP430MCInstLower:: GetGlobalAddressSymbol(const MachineOperand &MO) const { - const GlobalValue *GV = MO.getGlobal(); - - SmallString<128> Name; - Mang.getNameWithPrefix(Name, GV, false); - switch (MO.getTargetFlags()) { default: llvm_unreachable("Unknown target flag on GV operand"); case 0: break; } - return Ctx.GetOrCreateSymbol(Name.str()); + return Printer.GetGlobalValueSymbol(MO.getGlobal()); } MCSymbol *MSP430MCInstLower:: GetExternalSymbolSymbol(const MachineOperand &MO) const { - SmallString<128> Name; - Name += Printer.MAI->getGlobalPrefix(); - Name += MO.getSymbolName(); - switch (MO.getTargetFlags()) { default: assert(0 && "Unknown target flag on GV operand"); case 0: break; } - return Ctx.GetOrCreateSymbol(Name.str()); + return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); } MCSymbol *MSP430MCInstLower:: diff --git a/lib/Target/MSP430/AsmPrinter/Makefile b/lib/Target/MSP430/AsmPrinter/Makefile index 4f340c6..c8a44a1 100644 --- a/lib/Target/MSP430/AsmPrinter/Makefile +++ b/lib/Target/MSP430/AsmPrinter/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMMSP430AsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' MSP430 target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/MSP430/CMakeLists.txt b/lib/Target/MSP430/CMakeLists.txt index 60e0bb1..29abe46 100644 --- a/lib/Target/MSP430/CMakeLists.txt +++ b/lib/Target/MSP430/CMakeLists.txt @@ -11,9 +11,10 @@ tablegen(MSP430GenCallingConv.inc -gen-callingconv) tablegen(MSP430GenSubtarget.inc -gen-subtarget) add_llvm_target(MSP430CodeGen - MSP430InstrInfo.cpp + MSP430BranchSelector.cpp MSP430ISelDAGToDAG.cpp MSP430ISelLowering.cpp + MSP430InstrInfo.cpp MSP430MCAsmInfo.cpp MSP430RegisterInfo.cpp MSP430Subtarget.cpp diff --git a/lib/Target/MSP430/MSP430.h b/lib/Target/MSP430/MSP430.h index 1ff178d..e742118 100644 --- a/lib/Target/MSP430/MSP430.h +++ b/lib/Target/MSP430/MSP430.h @@ -39,6 +39,8 @@ namespace llvm { FunctionPass *createMSP430ISelDag(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel); + FunctionPass *createMSP430BranchSelectionPass(); + extern Target TheMSP430Target; } // end namespace llvm; diff --git a/lib/Target/MSP430/MSP430.td b/lib/Target/MSP430/MSP430.td index 870a3df..fe533d3 100644 --- a/lib/Target/MSP430/MSP430.td +++ b/lib/Target/MSP430/MSP430.td @@ -48,8 +48,14 @@ include "MSP430CallingConv.td" include "MSP430InstrInfo.td" -def MSP430InstrInfo : InstrInfo {} - +def MSP430InstrInfo : InstrInfo { + // Define how we want to layout our TargetSpecific information field... This + // should be kept up-to-date with the fields in the MSP430InstrInfo.h file. + let TSFlagsFields = ["FormBits", + "Size"]; + let TSFlagsShifts = [0, + 2]; +} def MSP430InstPrinter : AsmWriter { string AsmWriterClassName = "InstPrinter"; diff --git a/lib/Target/MSP430/MSP430BranchSelector.cpp b/lib/Target/MSP430/MSP430BranchSelector.cpp new file mode 100644 index 0000000..836e425 --- /dev/null +++ b/lib/Target/MSP430/MSP430BranchSelector.cpp @@ -0,0 +1,179 @@ +//===-- MSP430BranchSelector.cpp - Emit long conditional branches--*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that scans a machine function to determine which +// conditional branches need more than 10 bits of displacement to reach their +// target basic block. It does this in two passes; a calculation of basic block +// positions pass, and a branch psuedo op to machine branch opcode pass. This +// pass should be run last, just before the assembly printer. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "msp430-branch-select" +#include "MSP430.h" +#include "MSP430InstrInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/MathExtras.h" +using namespace llvm; + +STATISTIC(NumExpanded, "Number of branches expanded to long format"); + +namespace { + struct MSP430BSel : public MachineFunctionPass { + static char ID; + MSP430BSel() : MachineFunctionPass(&ID) {} + + /// BlockSizes - The sizes of the basic blocks in the function. + std::vector<unsigned> BlockSizes; + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "MSP430 Branch Selector"; + } + }; + char MSP430BSel::ID = 0; +} + +/// createMSP430BranchSelectionPass - returns an instance of the Branch +/// Selection Pass +/// +FunctionPass *llvm::createMSP430BranchSelectionPass() { + return new MSP430BSel(); +} + +bool MSP430BSel::runOnMachineFunction(MachineFunction &Fn) { + const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo(); + // Give the blocks of the function a dense, in-order, numbering. + Fn.RenumberBlocks(); + BlockSizes.resize(Fn.getNumBlockIDs()); + + // Measure each MBB and compute a size for the entire function. + unsigned FuncSize = 0; + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock *MBB = MFI; + + unsigned BlockSize = 0; + for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end(); + MBBI != EE; ++MBBI) + BlockSize += TII->GetInstSizeInBytes(MBBI); + + BlockSizes[MBB->getNumber()] = BlockSize; + FuncSize += BlockSize; + } + + // If the entire function is smaller than the displacement of a branch field, + // we know we don't need to shrink any branches in this function. This is a + // common case. + if (FuncSize < (1 << 9)) { + BlockSizes.clear(); + return false; + } + + // For each conditional branch, if the offset to its destination is larger + // than the offset field allows, transform it into a long branch sequence + // like this: + // short branch: + // bCC MBB + // long branch: + // b!CC $PC+6 + // b MBB + // + bool MadeChange = true; + bool EverMadeChange = false; + while (MadeChange) { + // Iteratively expand branches until we reach a fixed point. + MadeChange = false; + + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock &MBB = *MFI; + unsigned MBBStartOffset = 0; + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E; ++I) { + if ((I->getOpcode() != MSP430::JCC || I->getOperand(0).isImm()) && + I->getOpcode() != MSP430::JMP) { + MBBStartOffset += TII->GetInstSizeInBytes(I); + continue; + } + + // Determine the offset from the current branch to the destination + // block. + MachineBasicBlock *Dest = I->getOperand(0).getMBB(); + + int BranchSize; + if (Dest->getNumber() <= MBB.getNumber()) { + // If this is a backwards branch, the delta is the offset from the + // start of this block to this branch, plus the sizes of all blocks + // from this block to the dest. + BranchSize = MBBStartOffset; + + for (unsigned i = Dest->getNumber(), e = MBB.getNumber(); i != e; ++i) + BranchSize += BlockSizes[i]; + } else { + // Otherwise, add the size of the blocks between this block and the + // dest to the number of bytes left in this block. + BranchSize = -MBBStartOffset; + + for (unsigned i = MBB.getNumber(), e = Dest->getNumber(); i != e; ++i) + BranchSize += BlockSizes[i]; + } + + // If this branch is in range, ignore it. + if (isInt<10>(BranchSize)) { + MBBStartOffset += 2; + continue; + } + + // Otherwise, we have to expand it to a long branch. + unsigned NewSize; + MachineInstr *OldBranch = I; + DebugLoc dl = OldBranch->getDebugLoc(); + + if (I->getOpcode() == MSP430::JMP) { + NewSize = 4; + } else { + // The BCC operands are: + // 0. MSP430 branch predicate + // 1. Target MBB + SmallVector<MachineOperand, 1> Cond; + Cond.push_back(I->getOperand(1)); + + // Jump over the uncond branch inst (i.e. $+6) on opposite condition. + TII->ReverseBranchCondition(Cond); + BuildMI(MBB, I, dl, TII->get(MSP430::JCC)) + .addImm(4).addOperand(Cond[0]); + + NewSize = 6; + } + // Uncond branch to the real destination. + I = BuildMI(MBB, I, dl, TII->get(MSP430::B)).addMBB(Dest); + + // Remove the old branch from the function. + OldBranch->eraseFromParent(); + + // Remember that this instruction is NewSize bytes, increase the size of the + // block by NewSize-2, remember to iterate. + BlockSizes[MBB.getNumber()] += NewSize-2; + MBBStartOffset += NewSize; + + ++NumExpanded; + MadeChange = true; + } + } + EverMadeChange |= MadeChange; + } + + BlockSizes.clear(); + return true; +} diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index d3dce4b..b794911 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -675,21 +675,53 @@ static SDValue EmitCMP(SDValue &LHS, SDValue &RHS, SDValue &TargetCC, case ISD::SETULE: std::swap(LHS, RHS); // FALLTHROUGH case ISD::SETUGE: + // Turn lhs u>= rhs with lhs constant into rhs u< lhs+1, this allows us to + // fold constant into instruction. + if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { + LHS = RHS; + RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); + TCC = MSP430CC::COND_LO; + break; + } TCC = MSP430CC::COND_HS; // aka COND_C break; case ISD::SETUGT: std::swap(LHS, RHS); // FALLTHROUGH case ISD::SETULT: + // Turn lhs u< rhs with lhs constant into rhs u>= lhs+1, this allows us to + // fold constant into instruction. + if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { + LHS = RHS; + RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); + TCC = MSP430CC::COND_HS; + break; + } TCC = MSP430CC::COND_LO; // aka COND_NC break; case ISD::SETLE: std::swap(LHS, RHS); // FALLTHROUGH case ISD::SETGE: + // Turn lhs >= rhs with lhs constant into rhs < lhs+1, this allows us to + // fold constant into instruction. + if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { + LHS = RHS; + RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); + TCC = MSP430CC::COND_L; + break; + } TCC = MSP430CC::COND_GE; break; case ISD::SETGT: std::swap(LHS, RHS); // FALLTHROUGH case ISD::SETLT: + // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to + // fold constant into instruction. + if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { + LHS = RHS; + RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); + TCC = MSP430CC::COND_GE; + break; + } TCC = MSP430CC::COND_L; break; } @@ -723,6 +755,8 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { // If we are doing an AND and testing against zero, then the CMP // will not be generated. The AND (or BIT) will generate the condition codes, // but they are different from CMP. + // FIXME: since we're doing a post-processing, use a pseudoinstr here, so + // lowering & isel wouldn't diverge. bool andCC = false; if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) { if (RHSC->isNullValue() && LHS.hasOneUse() && @@ -750,11 +784,11 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { case MSP430CC::COND_HS: // Res = SRW & 1, no processing is required break; - case MSP430CC::COND_LO: + case MSP430CC::COND_LO: // Res = ~(SRW & 1) Invert = true; break; - case MSP430CC::COND_NE: + case MSP430CC::COND_NE: if (andCC) { // C = ~Z, thus Res = SRW & 1, no processing is required } else { @@ -762,7 +796,7 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { Shift = true; } break; - case MSP430CC::COND_E: + case MSP430CC::COND_E: if (andCC) { // C = ~Z, thus Res = ~(SRW & 1) } else { @@ -776,7 +810,7 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { SDValue One = DAG.getConstant(1, VT); if (Convert) { SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SRW, - MVT::i16, Flag); + MVT::i16, Flag); if (Shift) // FIXME: somewhere this is turned into a SRL, lower it MSP specific? SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One); @@ -933,6 +967,31 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const { } } +bool MSP430TargetLowering::isTruncateFree(const Type *Ty1, + const Type *Ty2) const { + if (!Ty1->isInteger() || !Ty2->isInteger()) + return false; + + return (Ty1->getPrimitiveSizeInBits() > Ty2->getPrimitiveSizeInBits()); +} + +bool MSP430TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { + if (!VT1.isInteger() || !VT2.isInteger()) + return false; + + return (VT1.getSizeInBits() > VT2.getSizeInBits()); +} + +bool MSP430TargetLowering::isZExtFree(const Type *Ty1, const Type *Ty2) const { + // MSP430 implicitly zero-extends 8-bit results in 16-bit registers. + return 0 && Ty1->isInteger(8) && Ty2->isInteger(16); +} + +bool MSP430TargetLowering::isZExtFree(EVT VT1, EVT VT2) const { + // MSP430 implicitly zero-extends 8-bit results in 16-bit registers. + return 0 && VT1 == MVT::i8 && VT2 == MVT::i16; +} + //===----------------------------------------------------------------------===// // Other Lowering Code //===----------------------------------------------------------------------===// diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h index 4921500..6152a05 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.h +++ b/lib/Target/MSP430/MSP430ISelLowering.h @@ -99,6 +99,23 @@ namespace llvm { std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; + /// isTruncateFree - Return true if it's free to truncate a value of type + /// Ty1 to type Ty2. e.g. On msp430 it's free to truncate a i16 value in + /// register R15W to i8 by referencing its sub-register R15B. + virtual bool isTruncateFree(const Type *Ty1, const Type *Ty2) const; + virtual bool isTruncateFree(EVT VT1, EVT VT2) const; + + /// isZExtFree - Return true if any actual instruction that defines a value + /// of type Ty1 implicit zero-extends the value to Ty2 in the result + /// register. This does not necessarily include registers defined in unknown + /// ways, such as incoming arguments, or copies from unknown virtual + /// registers. Also, if isTruncateFree(Ty2, Ty1) is true, this does not + /// necessarily apply to truncate instructions. e.g. on msp430, all + /// instructions that define 8-bit values implicit zero-extend the result + /// out to 16 bits. + virtual bool isZExtFree(const Type *Ty1, const Type *Ty2) const; + virtual bool isZExtFree(EVT VT1, EVT VT2) const; + MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *BB, DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const; diff --git a/lib/Target/MSP430/MSP430InstrFormats.td b/lib/Target/MSP430/MSP430InstrFormats.td index 61b3399..4ccc7df 100644 --- a/lib/Target/MSP430/MSP430InstrFormats.td +++ b/lib/Target/MSP430/MSP430InstrFormats.td @@ -11,8 +11,48 @@ // Describe MSP430 instructions format here // +// Format specifies the encoding used by the instruction. This is part of the +// ad-hoc solution used to emit machine instruction encodings by our machine +// code emitter. +class Format<bits<2> val> { + bits<2> Value = val; +} + +def PseudoFrm : Format<0>; +def SingleOpFrm : Format<1>; +def DoubleOpFrm : Format<2>; +def CondJumpFrm : Format<3>; + +class SourceMode<bits<2> val> { + bits<2> Value = val; +} + +def SrcReg : SourceMode<0>; +def SrcMem : SourceMode<1>; +def SrcIndReg : SourceMode<2>; +def SrcPostInc : SourceMode<3>; +def SrcImm : SourceMode<3>; + +class DestMode<bit val> { + bit Value = val; +} + +def DstReg : DestMode<0>; +def DstMem : DestMode<1>; + +class SizeVal<bits<3> val> { + bits<3> Value = val; +} + +def SizeUnknown : SizeVal<0>; // Unknown / unset size +def SizeSpecial : SizeVal<1>; // Special instruction, e.g. pseudo +def Size2Bytes : SizeVal<2>; +def Size4Bytes : SizeVal<3>; +def Size6Bytes : SizeVal<4>; + // Generic MSP430 Format -class MSP430Inst<dag outs, dag ins, string asmstr> : Instruction { +class MSP430Inst<dag outs, dag ins, SizeVal sz, Format f, + string asmstr> : Instruction { field bits<16> Inst; let Namespace = "MSP430"; @@ -20,48 +60,150 @@ class MSP430Inst<dag outs, dag ins, string asmstr> : Instruction { dag OutOperandList = outs; dag InOperandList = ins; + Format Form = f; + bits<2> FormBits = Form.Value; + + SizeVal Sz = sz; + bits<3> Size = Sz.Value; + let AsmString = asmstr; } // FIXME: Create different classes for different addressing modes. // MSP430 Double Operand (Format I) Instructions -class IForm<bits<4> opcode, bit ad, bit bw, bits<2> as, +class IForm<bits<4> opcode, DestMode dest, bit bw, SourceMode src, SizeVal sz, dag outs, dag ins, string asmstr, list<dag> pattern> - : MSP430Inst<outs, ins, asmstr> { + : MSP430Inst<outs, ins, sz, DoubleOpFrm, asmstr> { let Pattern = pattern; + + DestMode ad = dest; + SourceMode as = src; let Inst{12-15} = opcode; - let Inst{7} = ad; + let Inst{7} = ad.Value; let Inst{6} = bw; - let Inst{4-5} = as; + let Inst{4-5} = as.Value; } +// 8 bit IForm instructions +class IForm8<bits<4> opcode, DestMode dest, SourceMode src, SizeVal sz, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm<opcode, dest, 1, src, sz, outs, ins, asmstr, pattern>; + +class I8rr<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstReg, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>; + +class I8ri<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstReg, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>; + +class I8rm<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstReg, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>; + +class I8mr<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstMem, SrcReg, Size4Bytes, outs, ins, asmstr, pattern>; + +class I8mi<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstMem, SrcImm, Size6Bytes, outs, ins, asmstr, pattern>; + +class I8mm<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstMem, SrcMem, Size6Bytes, outs, ins, asmstr, pattern>; + +// 16 bit IForm instructions +class IForm16<bits<4> opcode, DestMode dest, SourceMode src, SizeVal sz, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm<opcode, dest, 0, src, sz, outs, ins, asmstr, pattern>; + +class I16rr<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstReg, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>; + +class I16ri<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstReg, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>; + +class I16rm<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstReg, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>; + +class I16mr<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstMem, SrcReg, Size4Bytes, outs, ins, asmstr, pattern>; + +class I16mi<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstMem, SrcImm, Size6Bytes, outs, ins, asmstr, pattern>; + +class I16mm<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstMem, SrcMem, Size6Bytes, outs, ins, asmstr, pattern>; + // MSP430 Single Operand (Format II) Instructions -class IIForm<bits<9> opcode, bit bw, bits<2> ad, +class IIForm<bits<9> opcode, bit bw, SourceMode src, SizeVal sz, dag outs, dag ins, string asmstr, list<dag> pattern> - : MSP430Inst<outs, ins, asmstr> { + : MSP430Inst<outs, ins, sz, SingleOpFrm, asmstr> { let Pattern = pattern; + SourceMode as = src; + let Inst{7-15} = opcode; let Inst{6} = bw; - let Inst{4-5} = ad; + let Inst{4-5} = as.Value; } +// 8 bit IIForm instructions +class IIForm8<bits<9> opcode, SourceMode src, SizeVal sz, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm<opcode, 1, src, sz, outs, ins, asmstr, pattern>; + +class II8r<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm8<opcode, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>; + +class II8m<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm8<opcode, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>; + +class II8i<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm8<opcode, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>; + +// 16 bit IIForm instructions +class IIForm16<bits<9> opcode, SourceMode src, SizeVal sz, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm<opcode, 0, src, sz, outs, ins, asmstr, pattern>; + +class II16r<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm16<opcode, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>; + +class II16m<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm16<opcode, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>; + +class II16i<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm16<opcode, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>; + // MSP430 Conditional Jumps Instructions -class CJForm<bits<3> opcode, bits<3> cond, bit s, +class CJForm<bits<3> opcode, bits<3> cond, dag outs, dag ins, string asmstr, list<dag> pattern> - : MSP430Inst<outs, ins, asmstr> { + : MSP430Inst<outs, ins, Size2Bytes, CondJumpFrm, asmstr> { let Pattern = pattern; let Inst{13-15} = opcode; let Inst{10-12} = cond; - let Inst{9} = s; } // Pseudo instructions class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern> - : MSP430Inst<outs, ins, asmstr> { + : MSP430Inst<outs, ins, SizeSpecial, PseudoFrm, asmstr> { let Pattern = pattern; let Inst{15-0} = 0; } diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp index 2ae6759..9dc69e0 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.cpp +++ b/lib/Target/MSP430/MSP430InstrInfo.cpp @@ -344,3 +344,45 @@ MSP430InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, } return Count; } + +/// GetInstSize - Return the number of bytes of code the specified +/// instruction may be. This returns the maximum number of bytes. +/// +unsigned MSP430InstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { + const TargetInstrDesc &Desc = MI->getDesc(); + + switch (Desc.TSFlags & MSP430II::SizeMask) { + default: + switch (Desc.getOpcode()) { + default: + assert(0 && "Unknown instruction size!"); + case TargetInstrInfo::DBG_LABEL: + case TargetInstrInfo::EH_LABEL: + case TargetInstrInfo::IMPLICIT_DEF: + case TargetInstrInfo::KILL: + return 0; + case TargetInstrInfo::INLINEASM: { + const MachineFunction *MF = MI->getParent()->getParent(); + const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + return TII.getInlineAsmLength(MI->getOperand(0).getSymbolName(), + *MF->getTarget().getMCAsmInfo()); + } + } + case MSP430II::SizeSpecial: + switch (MI->getOpcode()) { + default: + assert(0 && "Unknown instruction size!"); + case MSP430::SAR8r1c: + case MSP430::SAR16r1c: + return 4; + } + case MSP430II::Size2Bytes: + return 2; + case MSP430II::Size4Bytes: + return 4; + case MSP430II::Size6Bytes: + return 6; + } + + return 6; +} diff --git a/lib/Target/MSP430/MSP430InstrInfo.h b/lib/Target/MSP430/MSP430InstrInfo.h index e4ceeb9..6ef4b0a 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.h +++ b/lib/Target/MSP430/MSP430InstrInfo.h @@ -21,6 +21,22 @@ namespace llvm { class MSP430TargetMachine; +/// MSP430II - This namespace holds all of the target specific flags that +/// instruction info tracks. +/// +namespace MSP430II { + enum { + SizeShift = 2, + SizeMask = 7 << SizeShift, + + SizeUnknown = 0 << SizeShift, + SizeSpecial = 1 << SizeShift, + Size2Bytes = 2 << SizeShift, + Size4Bytes = 3 << SizeShift, + Size6Bytes = 4 << SizeShift + }; +} + class MSP430InstrInfo : public TargetInstrInfoImpl { const MSP430RegisterInfo RI; MSP430TargetMachine &TM; @@ -59,6 +75,8 @@ public: MachineBasicBlock::iterator MI, const std::vector<CalleeSavedInfo> &CSI) const; + unsigned GetInstSizeInBytes(const MachineInstr *MI) const; + // Branch folding goodness bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const; bool isUnpredicatedTerminator(const MachineInstr *MI) const; diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td index 022d171..cd502cf 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.td +++ b/lib/Target/MSP430/MSP430InstrInfo.td @@ -157,23 +157,35 @@ def NOP : Pseudo<(outs), (ins), "nop", []>; // FIXME: Provide proper encoding! let isReturn = 1, isTerminator = 1, isBarrier = 1 in { - def RET : Pseudo<(outs), (ins), "ret", [(MSP430retflag)]>; - def RETI : Pseudo<(outs), (ins), "reti", [(MSP430retiflag)]>; + def RET : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs), (ins), "ret", [(MSP430retflag)]>; + def RETI : II16r<0x0, (outs), (ins), "reti", [(MSP430retiflag)]>; } let isBranch = 1, isTerminator = 1 in { +// FIXME: expand opcode & cond field for branches! + // Direct branch -let isBarrier = 1 in - def JMP : Pseudo<(outs), (ins brtarget:$dst), +let isBarrier = 1 in { + // Short branch + def JMP : CJForm<0, 0, + (outs), (ins brtarget:$dst), "jmp\t$dst", [(br bb:$dst)]>; + // Long branch + def B : I16ri<0, + (outs), (ins brtarget:$dst), + "br\t$dst", + []>; +} // Conditional branches let Uses = [SRW] in - def JCC : Pseudo<(outs), (ins brtarget:$dst, cc:$cc), - "j$cc\t$dst", - [(MSP430brcc bb:$dst, imm:$cc)]>; + def JCC : CJForm<0, 0, + (outs), (ins brtarget:$dst, cc:$cc), + "j$cc\t$dst", + [(MSP430brcc bb:$dst, imm:$cc)]>; } // isBranch, isTerminator //===----------------------------------------------------------------------===// @@ -186,12 +198,15 @@ let isCall = 1 in // registers are added manually. let Defs = [R12W, R13W, R14W, R15W, SRW], Uses = [SPW] in { - def CALLi : Pseudo<(outs), (ins i16imm:$dst, variable_ops), - "call\t$dst", [(MSP430call imm:$dst)]>; - def CALLr : Pseudo<(outs), (ins GR16:$dst, variable_ops), - "call\t$dst", [(MSP430call GR16:$dst)]>; - def CALLm : Pseudo<(outs), (ins memsrc:$dst, variable_ops), - "call\t${dst:mem}", [(MSP430call (load addr:$dst))]>; + def CALLi : II16i<0x0, + (outs), (ins i16imm:$dst, variable_ops), + "call\t$dst", [(MSP430call imm:$dst)]>; + def CALLr : II16r<0x0, + (outs), (ins GR16:$dst, variable_ops), + "call\t$dst", [(MSP430call GR16:$dst)]>; + def CALLm : II16m<0x0, + (outs), (ins memsrc:$dst, variable_ops), + "call\t${dst:mem}", [(MSP430call (load addr:$dst))]>; } @@ -200,10 +215,12 @@ let isCall = 1 in // let Defs = [SPW], Uses = [SPW], neverHasSideEffects=1 in { let mayLoad = 1 in -def POP16r : Pseudo<(outs GR16:$reg), (ins), "pop.w\t$reg", []>; +def POP16r : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$reg), (ins), "pop.w\t$reg", []>; let mayStore = 1 in -def PUSH16r : Pseudo<(outs), (ins GR16:$reg), "push.w\t$reg",[]>; +def PUSH16r : II16r<0x0, + (outs), (ins GR16:$reg), "push.w\t$reg",[]>; } //===----------------------------------------------------------------------===// @@ -211,45 +228,55 @@ def PUSH16r : Pseudo<(outs), (ins GR16:$reg), "push.w\t$reg",[]>; // FIXME: Provide proper encoding! let neverHasSideEffects = 1 in { -def MOV8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src), - "mov.b\t{$src, $dst}", - []>; -def MOV16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "mov.w\t{$src, $dst}", - []>; +def MOV8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src), + "mov.b\t{$src, $dst}", + []>; +def MOV16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src), + "mov.w\t{$src, $dst}", + []>; } // FIXME: Provide proper encoding! let isReMaterializable = 1, isAsCheapAsAMove = 1 in { -def MOV8ri : Pseudo<(outs GR8:$dst), (ins i8imm:$src), - "mov.b\t{$src, $dst}", - [(set GR8:$dst, imm:$src)]>; -def MOV16ri : Pseudo<(outs GR16:$dst), (ins i16imm:$src), - "mov.w\t{$src, $dst}", - [(set GR16:$dst, imm:$src)]>; +def MOV8ri : I8ri<0x0, + (outs GR8:$dst), (ins i8imm:$src), + "mov.b\t{$src, $dst}", + [(set GR8:$dst, imm:$src)]>; +def MOV16ri : I16ri<0x0, + (outs GR16:$dst), (ins i16imm:$src), + "mov.w\t{$src, $dst}", + [(set GR16:$dst, imm:$src)]>; } let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { -def MOV8rm : Pseudo<(outs GR8:$dst), (ins memsrc:$src), - "mov.b\t{$src, $dst}", - [(set GR8:$dst, (load addr:$src))]>; -def MOV16rm : Pseudo<(outs GR16:$dst), (ins memsrc:$src), - "mov.w\t{$src, $dst}", - [(set GR16:$dst, (load addr:$src))]>; +def MOV8rm : I8rm<0x0, + (outs GR8:$dst), (ins memsrc:$src), + "mov.b\t{$src, $dst}", + [(set GR8:$dst, (load addr:$src))]>; +def MOV16rm : I16rm<0x0, + (outs GR16:$dst), (ins memsrc:$src), + "mov.w\t{$src, $dst}", + [(set GR16:$dst, (load addr:$src))]>; } -def MOVZX16rr8 : Pseudo<(outs GR16:$dst), (ins GR8:$src), - "mov.b\t{$src, $dst}", - [(set GR16:$dst, (zext GR8:$src))]>; -def MOVZX16rm8 : Pseudo<(outs GR16:$dst), (ins memsrc:$src), - "mov.b\t{$src, $dst}", - [(set GR16:$dst, (zextloadi16i8 addr:$src))]>; +def MOVZX16rr8 : I8rr<0x0, + (outs GR16:$dst), (ins GR8:$src), + "mov.b\t{$src, $dst}", + [(set GR16:$dst, (zext GR8:$src))]>; +def MOVZX16rm8 : I8rm<0x0, + (outs GR16:$dst), (ins memsrc:$src), + "mov.b\t{$src, $dst}", + [(set GR16:$dst, (zextloadi16i8 addr:$src))]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb" in { -def MOV8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR16:$base), - "mov.b\t{@$base+, $dst}", []>; -def MOV16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$base), - "mov.w\t{@$base+, $dst}", []>; +def MOV8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), (ins GR16:$base), + "mov.b\t{@$base+, $dst}", []>; +def MOV16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), (ins GR16:$base), + "mov.w\t{@$base+, $dst}", []>; } // Any instruction that defines a 8-bit result leaves the high half of the @@ -267,27 +294,32 @@ def def8 : PatLeaf<(i8 GR8:$src), [{ def : Pat<(i16 (zext def8:$src)), (SUBREG_TO_REG (i16 0), GR8:$src, subreg_8bit)>; - -def MOV8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "mov.b\t{$src, $dst}", - [(store (i8 imm:$src), addr:$dst)]>; -def MOV16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "mov.w\t{$src, $dst}", - [(store (i16 imm:$src), addr:$dst)]>; - -def MOV8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "mov.b\t{$src, $dst}", - [(store GR8:$src, addr:$dst)]>; -def MOV16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "mov.w\t{$src, $dst}", - [(store GR16:$src, addr:$dst)]>; - -def MOV8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "mov.b\t{$src, $dst}", - [(store (i8 (load addr:$src)), addr:$dst)]>; -def MOV16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "mov.w\t{$src, $dst}", - [(store (i16 (load addr:$src)), addr:$dst)]>; +def MOV8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "mov.b\t{$src, $dst}", + [(store (i8 imm:$src), addr:$dst)]>; +def MOV16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "mov.w\t{$src, $dst}", + [(store (i16 imm:$src), addr:$dst)]>; + +def MOV8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "mov.b\t{$src, $dst}", + [(store GR8:$src, addr:$dst)]>; +def MOV16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "mov.w\t{$src, $dst}", + [(store GR16:$src, addr:$dst)]>; + +def MOV8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "mov.b\t{$src, $dst}", + [(store (i8 (load addr:$src)), addr:$dst)]>; +def MOV16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "mov.w\t{$src, $dst}", + [(store (i16 (load addr:$src)), addr:$dst)]>; //===----------------------------------------------------------------------===// // Arithmetic Instructions @@ -297,496 +329,624 @@ let isTwoAddress = 1 in { let Defs = [SRW] in { let isCommutable = 1 in { // X = ADD Y, Z == X = ADD Z, Y -// FIXME: Provide proper encoding! -def ADD8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "add.b\t{$src2, $dst}", - [(set GR8:$dst, (add GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def ADD16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "add.w\t{$src2, $dst}", - [(set GR16:$dst, (add GR16:$src1, GR16:$src2)), - (implicit SRW)]>; + +def ADD8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "add.b\t{$src2, $dst}", + [(set GR8:$dst, (add GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def ADD16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "add.w\t{$src2, $dst}", + [(set GR16:$dst, (add GR16:$src1, GR16:$src2)), + (implicit SRW)]>; } -def ADD8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "add.b\t{$src2, $dst}", - [(set GR8:$dst, (add GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def ADD16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "add.w\t{$src2, $dst}", - [(set GR16:$dst, (add GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def ADD8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "add.b\t{$src2, $dst}", + [(set GR8:$dst, (add GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def ADD16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "add.w\t{$src2, $dst}", + [(set GR16:$dst, (add GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb, $src1 = $dst" in { -def ADD8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), - "add.b\t{@$base+, $dst}", []>; -def ADD16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), +def ADD8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), + (ins GR8:$src1, GR16:$base), + "add.b\t{@$base+, $dst}", []>; +def ADD16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), + (ins GR16:$src1, GR16:$base), "add.w\t{@$base+, $dst}", []>; } -def ADD8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "add.b\t{$src2, $dst}", - [(set GR8:$dst, (add GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def ADD16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "add.w\t{$src2, $dst}", - [(set GR16:$dst, (add GR16:$src1, imm:$src2)), - (implicit SRW)]>; +def ADD8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "add.b\t{$src2, $dst}", + [(set GR8:$dst, (add GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def ADD16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "add.w\t{$src2, $dst}", + [(set GR16:$dst, (add GR16:$src1, imm:$src2)), + (implicit SRW)]>; let isTwoAddress = 0 in { -def ADD8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "add.b\t{$src, $dst}", - [(store (add (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def ADD16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "add.w\t{$src, $dst}", - [(store (add (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def ADD8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "add.b\t{$src, $dst}", - [(store (add (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def ADD16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "add.w\t{$src, $dst}", - [(store (add (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def ADD8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "add.b\t{$src, $dst}", - [(store (add (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def ADD16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "add.w\t{$src, $dst}", - [(store (add (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def ADD8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "add.b\t{$src, $dst}", + [(store (add (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def ADD16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "add.w\t{$src, $dst}", + [(store (add (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def ADD8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "add.b\t{$src, $dst}", + [(store (add (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def ADD16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "add.w\t{$src, $dst}", + [(store (add (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def ADD8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "add.b\t{$src, $dst}", + [(store (add (load addr:$dst), + (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def ADD16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "add.w\t{$src, $dst}", + [(store (add (load addr:$dst), + (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } let Uses = [SRW] in { let isCommutable = 1 in { // X = ADDC Y, Z == X = ADDC Z, Y -def ADC8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "addc.b\t{$src2, $dst}", - [(set GR8:$dst, (adde GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def ADC16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "addc.w\t{$src2, $dst}", - [(set GR16:$dst, (adde GR16:$src1, GR16:$src2)), - (implicit SRW)]>; +def ADC8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "addc.b\t{$src2, $dst}", + [(set GR8:$dst, (adde GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def ADC16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "addc.w\t{$src2, $dst}", + [(set GR16:$dst, (adde GR16:$src1, GR16:$src2)), + (implicit SRW)]>; } // isCommutable -def ADC8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "addc.b\t{$src2, $dst}", - [(set GR8:$dst, (adde GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def ADC16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "addc.w\t{$src2, $dst}", - [(set GR16:$dst, (adde GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def ADC8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "addc.b\t{$src2, $dst}", - [(set GR8:$dst, (adde GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def ADC16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "addc.w\t{$src2, $dst}", - [(set GR16:$dst, (adde GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def ADC8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "addc.b\t{$src2, $dst}", + [(set GR8:$dst, (adde GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def ADC16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "addc.w\t{$src2, $dst}", + [(set GR16:$dst, (adde GR16:$src1, imm:$src2)), + (implicit SRW)]>; + +def ADC8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "addc.b\t{$src2, $dst}", + [(set GR8:$dst, (adde GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def ADC16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "addc.w\t{$src2, $dst}", + [(set GR16:$dst, (adde GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let isTwoAddress = 0 in { -def ADC8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "addc.b\t{$src, $dst}", - [(store (adde (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def ADC16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "addc.w\t{$src, $dst}", - [(store (adde (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def ADC8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "addc.b\t{$src, $dst}", - [(store (adde (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def ADC16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "addc.w\t{$src, $dst}", - [(store (adde (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def ADC8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "addc.b\t{$src, $dst}", - [(store (adde (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def ADC16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "addc.w\t{$src, $dst}", - [(store (adde (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def ADC8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "addc.b\t{$src, $dst}", + [(store (adde (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def ADC16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "addc.w\t{$src, $dst}", + [(store (adde (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def ADC8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "addc.b\t{$src, $dst}", + [(store (adde (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def ADC16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "addc.w\t{$src, $dst}", + [(store (adde (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def ADC8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "addc.b\t{$src, $dst}", + [(store (adde (load addr:$dst), + (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def ADC16mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "addc.w\t{$src, $dst}", + [(store (adde (load addr:$dst), + (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } } // Uses = [SRW] let isCommutable = 1 in { // X = AND Y, Z == X = AND Z, Y -def AND8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "and.b\t{$src2, $dst}", - [(set GR8:$dst, (and GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def AND16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "and.w\t{$src2, $dst}", - [(set GR16:$dst, (and GR16:$src1, GR16:$src2)), - (implicit SRW)]>; +def AND8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "and.b\t{$src2, $dst}", + [(set GR8:$dst, (and GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def AND16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "and.w\t{$src2, $dst}", + [(set GR16:$dst, (and GR16:$src1, GR16:$src2)), + (implicit SRW)]>; } -def AND8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "and.b\t{$src2, $dst}", - [(set GR8:$dst, (and GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def AND16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "and.w\t{$src2, $dst}", - [(set GR16:$dst, (and GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def AND8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "and.b\t{$src2, $dst}", - [(set GR8:$dst, (and GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def AND16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "and.w\t{$src2, $dst}", - [(set GR16:$dst, (and GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def AND8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "and.b\t{$src2, $dst}", + [(set GR8:$dst, (and GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def AND16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "and.w\t{$src2, $dst}", + [(set GR16:$dst, (and GR16:$src1, imm:$src2)), + (implicit SRW)]>; + +def AND8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "and.b\t{$src2, $dst}", + [(set GR8:$dst, (and GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def AND16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "and.w\t{$src2, $dst}", + [(set GR16:$dst, (and GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb, $src1 = $dst" in { -def AND8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), - "and.b\t{@$base+, $dst}", []>; -def AND16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), - "and.w\t{@$base+, $dst}", []>; +def AND8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), + (ins GR8:$src1, GR16:$base), + "and.b\t{@$base+, $dst}", []>; +def AND16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), + (ins GR16:$src1, GR16:$base), + "and.w\t{@$base+, $dst}", []>; } let isTwoAddress = 0 in { -def AND8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "and.b\t{$src, $dst}", - [(store (and (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def AND16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "and.w\t{$src, $dst}", - [(store (and (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def AND8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "and.b\t{$src, $dst}", - [(store (and (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def AND16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "and.w\t{$src, $dst}", - [(store (and (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def AND8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "and.b\t{$src, $dst}", - [(store (and (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def AND16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "and.w\t{$src, $dst}", - [(store (and (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def AND8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "and.b\t{$src, $dst}", + [(store (and (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def AND16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "and.w\t{$src, $dst}", + [(store (and (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def AND8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "and.b\t{$src, $dst}", + [(store (and (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def AND16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "and.w\t{$src, $dst}", + [(store (and (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def AND8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "and.b\t{$src, $dst}", + [(store (and (load addr:$dst), + (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def AND16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "and.w\t{$src, $dst}", + [(store (and (load addr:$dst), + (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } let isCommutable = 1 in { // X = OR Y, Z == X = OR Z, Y -def OR8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "bis.b\t{$src2, $dst}", - [(set GR8:$dst, (or GR8:$src1, GR8:$src2))]>; -def OR16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "bis.w\t{$src2, $dst}", - [(set GR16:$dst, (or GR16:$src1, GR16:$src2))]>; +def OR8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "bis.b\t{$src2, $dst}", + [(set GR8:$dst, (or GR8:$src1, GR8:$src2))]>; +def OR16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "bis.w\t{$src2, $dst}", + [(set GR16:$dst, (or GR16:$src1, GR16:$src2))]>; } -def OR8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "bis.b\t{$src2, $dst}", - [(set GR8:$dst, (or GR8:$src1, imm:$src2))]>; -def OR16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "bis.w\t{$src2, $dst}", - [(set GR16:$dst, (or GR16:$src1, imm:$src2))]>; - -def OR8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "bis.b\t{$src2, $dst}", - [(set GR8:$dst, (or GR8:$src1, (load addr:$src2)))]>; -def OR16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "bis.w\t{$src2, $dst}", - [(set GR16:$dst, (or GR16:$src1, (load addr:$src2)))]>; +def OR8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "bis.b\t{$src2, $dst}", + [(set GR8:$dst, (or GR8:$src1, imm:$src2))]>; +def OR16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "bis.w\t{$src2, $dst}", + [(set GR16:$dst, (or GR16:$src1, imm:$src2))]>; + +def OR8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "bis.b\t{$src2, $dst}", + [(set GR8:$dst, (or GR8:$src1, (load addr:$src2)))]>; +def OR16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "bis.w\t{$src2, $dst}", + [(set GR16:$dst, (or GR16:$src1, (load addr:$src2)))]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb, $src1 = $dst" in { -def OR8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), +def OR8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), + (ins GR8:$src1, GR16:$base), "bis.b\t{@$base+, $dst}", []>; -def OR16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), - "bis.w\t{@$base+, $dst}", []>; +def OR16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), + (ins GR16:$src1, GR16:$base), + "bis.w\t{@$base+, $dst}", []>; } let isTwoAddress = 0 in { -def OR8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "bis.b\t{$src, $dst}", - [(store (or (load addr:$dst), GR8:$src), addr:$dst)]>; -def OR16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "bis.w\t{$src, $dst}", - [(store (or (load addr:$dst), GR16:$src), addr:$dst)]>; - -def OR8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "bis.b\t{$src, $dst}", - [(store (or (load addr:$dst), (i8 imm:$src)), addr:$dst)]>; -def OR16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "bis.w\t{$src, $dst}", - [(store (or (load addr:$dst), (i16 imm:$src)), addr:$dst)]>; - -def OR8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "bis.b\t{$src, $dst}", - [(store (or (i8 (load addr:$dst)), - (i8 (load addr:$src))), addr:$dst)]>; -def OR16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "bis.w\t{$src, $dst}", - [(store (or (i16 (load addr:$dst)), - (i16 (load addr:$src))), addr:$dst)]>; +def OR8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "bis.b\t{$src, $dst}", + [(store (or (load addr:$dst), GR8:$src), addr:$dst)]>; +def OR16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "bis.w\t{$src, $dst}", + [(store (or (load addr:$dst), GR16:$src), addr:$dst)]>; + +def OR8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "bis.b\t{$src, $dst}", + [(store (or (load addr:$dst), (i8 imm:$src)), addr:$dst)]>; +def OR16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "bis.w\t{$src, $dst}", + [(store (or (load addr:$dst), (i16 imm:$src)), addr:$dst)]>; + +def OR8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "bis.b\t{$src, $dst}", + [(store (or (i8 (load addr:$dst)), + (i8 (load addr:$src))), addr:$dst)]>; +def OR16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "bis.w\t{$src, $dst}", + [(store (or (i16 (load addr:$dst)), + (i16 (load addr:$src))), addr:$dst)]>; } // bic does not modify condition codes -def BIC8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "bic.b\t{$src2, $dst}", - [(set GR8:$dst, (and GR8:$src1, (not GR8:$src2)))]>; -def BIC16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "bic.w\t{$src2, $dst}", - [(set GR16:$dst, (and GR16:$src1, (not GR16:$src2)))]>; - -def BIC8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "bic.b\t{$src2, $dst}", - [(set GR8:$dst, (and GR8:$src1, (not (i8 (load addr:$src2)))))]>; -def BIC16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "bic.w\t{$src2, $dst}", - [(set GR16:$dst, (and GR16:$src1, (not (i16 (load addr:$src2)))))]>; +def BIC8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "bic.b\t{$src2, $dst}", + [(set GR8:$dst, (and GR8:$src1, (not GR8:$src2)))]>; +def BIC16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "bic.w\t{$src2, $dst}", + [(set GR16:$dst, (and GR16:$src1, (not GR16:$src2)))]>; + +def BIC8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "bic.b\t{$src2, $dst}", + [(set GR8:$dst, (and GR8:$src1, (not (i8 (load addr:$src2)))))]>; +def BIC16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "bic.w\t{$src2, $dst}", + [(set GR16:$dst, (and GR16:$src1, (not (i16 (load addr:$src2)))))]>; let isTwoAddress = 0 in { -def BIC8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "bic.b\t{$src, $dst}", - [(store (and (load addr:$dst), (not GR8:$src)), addr:$dst)]>; -def BIC16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "bic.w\t{$src, $dst}", - [(store (and (load addr:$dst), (not GR16:$src)), addr:$dst)]>; - -def BIC8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "bic.b\t{$src, $dst}", - [(store (and (load addr:$dst), (not (i8 (load addr:$src)))), addr:$dst)]>; -def BIC16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "bic.w\t{$src, $dst}", - [(store (and (load addr:$dst), (not (i16 (load addr:$src)))), addr:$dst)]>; +def BIC8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "bic.b\t{$src, $dst}", + [(store (and (load addr:$dst), (not GR8:$src)), addr:$dst)]>; +def BIC16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "bic.w\t{$src, $dst}", + [(store (and (load addr:$dst), (not GR16:$src)), addr:$dst)]>; + +def BIC8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "bic.b\t{$src, $dst}", + [(store (and (load addr:$dst), + (not (i8 (load addr:$src)))), addr:$dst)]>; +def BIC16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "bic.w\t{$src, $dst}", + [(store (and (load addr:$dst), + (not (i16 (load addr:$src)))), addr:$dst)]>; } let isCommutable = 1 in { // X = XOR Y, Z == X = XOR Z, Y -def XOR8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "xor.b\t{$src2, $dst}", - [(set GR8:$dst, (xor GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def XOR16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "xor.w\t{$src2, $dst}", - [(set GR16:$dst, (xor GR16:$src1, GR16:$src2)), - (implicit SRW)]>; +def XOR8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "xor.b\t{$src2, $dst}", + [(set GR8:$dst, (xor GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def XOR16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "xor.w\t{$src2, $dst}", + [(set GR16:$dst, (xor GR16:$src1, GR16:$src2)), + (implicit SRW)]>; } -def XOR8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "xor.b\t{$src2, $dst}", - [(set GR8:$dst, (xor GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def XOR16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "xor.w\t{$src2, $dst}", - [(set GR16:$dst, (xor GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def XOR8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "xor.b\t{$src2, $dst}", - [(set GR8:$dst, (xor GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def XOR16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "xor.w\t{$src2, $dst}", - [(set GR16:$dst, (xor GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def XOR8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "xor.b\t{$src2, $dst}", + [(set GR8:$dst, (xor GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def XOR16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "xor.w\t{$src2, $dst}", + [(set GR16:$dst, (xor GR16:$src1, imm:$src2)), + (implicit SRW)]>; + +def XOR8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "xor.b\t{$src2, $dst}", + [(set GR8:$dst, (xor GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def XOR16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "xor.w\t{$src2, $dst}", + [(set GR16:$dst, (xor GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb, $src1 = $dst" in { -def XOR8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), - "xor.b\t{@$base+, $dst}", []>; -def XOR16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), - "xor.w\t{@$base+, $dst}", []>; +def XOR8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), + (ins GR8:$src1, GR16:$base), + "xor.b\t{@$base+, $dst}", []>; +def XOR16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), + (ins GR16:$src1, GR16:$base), + "xor.w\t{@$base+, $dst}", []>; } let isTwoAddress = 0 in { -def XOR8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "xor.b\t{$src, $dst}", - [(store (xor (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def XOR16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "xor.w\t{$src, $dst}", - [(store (xor (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def XOR8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "xor.b\t{$src, $dst}", - [(store (xor (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def XOR16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "xor.w\t{$src, $dst}", - [(store (xor (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def XOR8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "xor.b\t{$src, $dst}", - [(store (xor (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def XOR16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "xor.w\t{$src, $dst}", - [(store (xor (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def XOR8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "xor.b\t{$src, $dst}", + [(store (xor (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def XOR16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "xor.w\t{$src, $dst}", + [(store (xor (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def XOR8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "xor.b\t{$src, $dst}", + [(store (xor (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def XOR16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "xor.w\t{$src, $dst}", + [(store (xor (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def XOR8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "xor.b\t{$src, $dst}", + [(store (xor (load addr:$dst), (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def XOR16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "xor.w\t{$src, $dst}", + [(store (xor (load addr:$dst), (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } -def SUB8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "sub.b\t{$src2, $dst}", - [(set GR8:$dst, (sub GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def SUB16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "sub.w\t{$src2, $dst}", - [(set GR16:$dst, (sub GR16:$src1, GR16:$src2)), - (implicit SRW)]>; - -def SUB8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "sub.b\t{$src2, $dst}", - [(set GR8:$dst, (sub GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def SUB16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "sub.w\t{$src2, $dst}", - [(set GR16:$dst, (sub GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def SUB8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "sub.b\t{$src2, $dst}", - [(set GR8:$dst, (sub GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def SUB16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "sub.w\t{$src2, $dst}", - [(set GR16:$dst, (sub GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def SUB8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "sub.b\t{$src2, $dst}", + [(set GR8:$dst, (sub GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def SUB16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "sub.w\t{$src2, $dst}", + [(set GR16:$dst, (sub GR16:$src1, GR16:$src2)), + (implicit SRW)]>; + +def SUB8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "sub.b\t{$src2, $dst}", + [(set GR8:$dst, (sub GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def SUB16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "sub.w\t{$src2, $dst}", + [(set GR16:$dst, (sub GR16:$src1, imm:$src2)), + (implicit SRW)]>; + +def SUB8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "sub.b\t{$src2, $dst}", + [(set GR8:$dst, (sub GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def SUB16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "sub.w\t{$src2, $dst}", + [(set GR16:$dst, (sub GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb, $src1 = $dst" in { -def SUB8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), - "sub.b\t{@$base+, $dst}", []>; -def SUB16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), +def SUB8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), + (ins GR8:$src1, GR16:$base), + "sub.b\t{@$base+, $dst}", []>; +def SUB16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), + (ins GR16:$src1, GR16:$base), "sub.w\t{@$base+, $dst}", []>; } let isTwoAddress = 0 in { -def SUB8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "sub.b\t{$src, $dst}", - [(store (sub (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def SUB16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "sub.w\t{$src, $dst}", - [(store (sub (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def SUB8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "sub.b\t{$src, $dst}", - [(store (sub (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def SUB16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "sub.w\t{$src, $dst}", - [(store (sub (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def SUB8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "sub.b\t{$src, $dst}", - [(store (sub (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def SUB16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "sub.w\t{$src, $dst}", - [(store (sub (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def SUB8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "sub.b\t{$src, $dst}", + [(store (sub (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def SUB16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "sub.w\t{$src, $dst}", + [(store (sub (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def SUB8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "sub.b\t{$src, $dst}", + [(store (sub (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def SUB16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "sub.w\t{$src, $dst}", + [(store (sub (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def SUB8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "sub.b\t{$src, $dst}", + [(store (sub (load addr:$dst), + (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def SUB16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "sub.w\t{$src, $dst}", + [(store (sub (load addr:$dst), + (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } let Uses = [SRW] in { -def SBC8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "subc.b\t{$src2, $dst}", - [(set GR8:$dst, (sube GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def SBC16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "subc.w\t{$src2, $dst}", - [(set GR16:$dst, (sube GR16:$src1, GR16:$src2)), - (implicit SRW)]>; - -def SBC8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "subc.b\t{$src2, $dst}", - [(set GR8:$dst, (sube GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def SBC16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "subc.w\t{$src2, $dst}", - [(set GR16:$dst, (sube GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def SBC8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "subc.b\t{$src2, $dst}", - [(set GR8:$dst, (sube GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def SBC16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "subc.w\t{$src2, $dst}", - [(set GR16:$dst, (sube GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def SBC8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "subc.b\t{$src2, $dst}", + [(set GR8:$dst, (sube GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def SBC16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "subc.w\t{$src2, $dst}", + [(set GR16:$dst, (sube GR16:$src1, GR16:$src2)), + (implicit SRW)]>; + +def SBC8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "subc.b\t{$src2, $dst}", + [(set GR8:$dst, (sube GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def SBC16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "subc.w\t{$src2, $dst}", + [(set GR16:$dst, (sube GR16:$src1, imm:$src2)), + (implicit SRW)]>; + +def SBC8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "subc.b\t{$src2, $dst}", + [(set GR8:$dst, (sube GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def SBC16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "subc.w\t{$src2, $dst}", + [(set GR16:$dst, (sube GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let isTwoAddress = 0 in { -def SBC8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "subc.b\t{$src, $dst}", - [(store (sube (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def SBC16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "subc.w\t{$src, $dst}", - [(store (sube (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def SBC8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "subc.b\t{$src, $dst}", - [(store (sube (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def SBC16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "subc.w\t{$src, $dst}", - [(store (sube (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def SBC8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "subc.b\t{$src, $dst}", - [(store (sube (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def SBC16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "subc.w\t{$src, $dst}", - [(store (sube (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def SBC8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "subc.b\t{$src, $dst}", + [(store (sube (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def SBC16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "subc.w\t{$src, $dst}", + [(store (sube (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def SBC8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "subc.b\t{$src, $dst}", + [(store (sube (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def SBC16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "subc.w\t{$src, $dst}", + [(store (sube (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def SBC8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "subc.b\t{$src, $dst}", + [(store (sube (load addr:$dst), + (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def SBC16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "subc.w\t{$src, $dst}", + [(store (sube (load addr:$dst), + (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } } // Uses = [SRW] -// FIXME: Provide proper encoding! -def SAR8r1 : Pseudo<(outs GR8:$dst), (ins GR8:$src), - "rra.b\t$dst", - [(set GR8:$dst, (MSP430rra GR8:$src)), - (implicit SRW)]>; -def SAR16r1 : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "rra.w\t$dst", - [(set GR16:$dst, (MSP430rra GR16:$src)), - (implicit SRW)]>; - -def SHL8r1 : Pseudo<(outs GR8:$dst), (ins GR8:$src), - "rla.b\t$dst", - [(set GR8:$dst, (MSP430rla GR8:$src)), - (implicit SRW)]>; -def SHL16r1 : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "rla.w\t$dst", - [(set GR16:$dst, (MSP430rla GR16:$src)), - (implicit SRW)]>; +// FIXME: memory variant! +def SAR8r1 : II8r<0x0, + (outs GR8:$dst), (ins GR8:$src), + "rra.b\t$dst", + [(set GR8:$dst, (MSP430rra GR8:$src)), + (implicit SRW)]>; +def SAR16r1 : II16r<0x0, + (outs GR16:$dst), (ins GR16:$src), + "rra.w\t$dst", + [(set GR16:$dst, (MSP430rra GR16:$src)), + (implicit SRW)]>; + +def SHL8r1 : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src), + "rla.b\t$dst", + [(set GR8:$dst, (MSP430rla GR8:$src)), + (implicit SRW)]>; +def SHL16r1 : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src), + "rla.w\t$dst", + [(set GR16:$dst, (MSP430rla GR16:$src)), + (implicit SRW)]>; def SAR8r1c : Pseudo<(outs GR8:$dst), (ins GR8:$src), "clrc\n\t" @@ -799,121 +959,154 @@ def SAR16r1c : Pseudo<(outs GR16:$dst), (ins GR16:$src), [(set GR16:$dst, (MSP430rrc GR16:$src)), (implicit SRW)]>; -def SEXT16r : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "sxt\t$dst", - [(set GR16:$dst, (sext_inreg GR16:$src, i8)), - (implicit SRW)]>; +// FIXME: Memory sext's ? +def SEXT16r : II16r<0x0, + (outs GR16:$dst), (ins GR16:$src), + "sxt\t$dst", + [(set GR16:$dst, (sext_inreg GR16:$src, i8)), + (implicit SRW)]>; } // Defs = [SRW] -def ZEXT16r : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "mov.b\t{$src, $dst}", - [(set GR16:$dst, (zext (trunc GR16:$src)))]>; +def ZEXT16r : I8rr<0x0, + (outs GR16:$dst), (ins GR16:$src), + "mov.b\t{$src, $dst}", + [(set GR16:$dst, (zext (trunc GR16:$src)))]>; -def SWPB16r : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "swpb\t$dst", - [(set GR16:$dst, (bswap GR16:$src))]>; +// FIXME: Memory bitswaps? +def SWPB16r : II16r<0x0, + (outs GR16:$dst), (ins GR16:$src), + "swpb\t$dst", + [(set GR16:$dst, (bswap GR16:$src))]>; } // isTwoAddress = 1 // Integer comparisons let Defs = [SRW] in { -def CMP8rr : Pseudo<(outs), (ins GR8:$src1, GR8:$src2), - "cmp.b\t{$src2, $src1}", - [(MSP430cmp GR8:$src1, GR8:$src2), (implicit SRW)]>; -def CMP16rr : Pseudo<(outs), (ins GR16:$src1, GR16:$src2), - "cmp.w\t{$src2, $src1}", - [(MSP430cmp GR16:$src1, GR16:$src2), (implicit SRW)]>; - -def CMP8ri : Pseudo<(outs), (ins GR8:$src1, i8imm:$src2), +def CMP8rr : I8rr<0x0, + (outs), (ins GR8:$src1, GR8:$src2), + "cmp.b\t{$src2, $src1}", + [(MSP430cmp GR8:$src1, GR8:$src2), (implicit SRW)]>; +def CMP16rr : I16rr<0x0, + (outs), (ins GR16:$src1, GR16:$src2), + "cmp.w\t{$src2, $src1}", + [(MSP430cmp GR16:$src1, GR16:$src2), (implicit SRW)]>; + +def CMP8ri : I8ri<0x0, + (outs), (ins GR8:$src1, i8imm:$src2), "cmp.b\t{$src2, $src1}", [(MSP430cmp GR8:$src1, imm:$src2), (implicit SRW)]>; -def CMP16ri : Pseudo<(outs), (ins GR16:$src1, i16imm:$src2), - "cmp.w\t{$src2, $src1}", - [(MSP430cmp GR16:$src1, imm:$src2), (implicit SRW)]>; - -def CMP8mi : Pseudo<(outs), (ins memsrc:$src1, i8imm:$src2), - "cmp.b\t{$src2, $src1}", - [(MSP430cmp (load addr:$src1), - (i8 imm:$src2)), (implicit SRW)]>; -def CMP16mi : Pseudo<(outs), (ins memsrc:$src1, i16imm:$src2), - "cmp.w\t{$src2, $src1}", - [(MSP430cmp (load addr:$src1), - (i16 imm:$src2)), (implicit SRW)]>; - -def CMP8rm : Pseudo<(outs), (ins GR8:$src1, memsrc:$src2), - "cmp.b\t{$src2, $src1}", - [(MSP430cmp GR8:$src1, (load addr:$src2)), (implicit SRW)]>; -def CMP16rm : Pseudo<(outs), (ins GR16:$src1, memsrc:$src2), - "cmp.w\t{$src2, $src1}", - [(MSP430cmp GR16:$src1, (load addr:$src2)), (implicit SRW)]>; - -def CMP8mr : Pseudo<(outs), (ins memsrc:$src1, GR8:$src2), - "cmp.b\t{$src2, $src1}", - [(MSP430cmp (load addr:$src1), GR8:$src2), (implicit SRW)]>; -def CMP16mr : Pseudo<(outs), (ins memsrc:$src1, GR16:$src2), - "cmp.w\t{$src2, $src1}", - [(MSP430cmp (load addr:$src1), GR16:$src2), (implicit SRW)]>; +def CMP16ri : I16ri<0x0, + (outs), (ins GR16:$src1, i16imm:$src2), + "cmp.w\t{$src2, $src1}", + [(MSP430cmp GR16:$src1, imm:$src2), (implicit SRW)]>; + +def CMP8mi : I8mi<0x0, + (outs), (ins memsrc:$src1, i8imm:$src2), + "cmp.b\t{$src2, $src1}", + [(MSP430cmp (load addr:$src1), + (i8 imm:$src2)), (implicit SRW)]>; +def CMP16mi : I16mi<0x0, + (outs), (ins memsrc:$src1, i16imm:$src2), + "cmp.w\t{$src2, $src1}", + [(MSP430cmp (load addr:$src1), + (i16 imm:$src2)), (implicit SRW)]>; + +def CMP8rm : I8rm<0x0, + (outs), (ins GR8:$src1, memsrc:$src2), + "cmp.b\t{$src2, $src1}", + [(MSP430cmp GR8:$src1, (load addr:$src2)), + (implicit SRW)]>; +def CMP16rm : I16rm<0x0, + (outs), (ins GR16:$src1, memsrc:$src2), + "cmp.w\t{$src2, $src1}", + [(MSP430cmp GR16:$src1, (load addr:$src2)), + (implicit SRW)]>; + +def CMP8mr : I8mr<0x0, + (outs), (ins memsrc:$src1, GR8:$src2), + "cmp.b\t{$src2, $src1}", + [(MSP430cmp (load addr:$src1), GR8:$src2), + (implicit SRW)]>; +def CMP16mr : I16mr<0x0, + (outs), (ins memsrc:$src1, GR16:$src2), + "cmp.w\t{$src2, $src1}", + [(MSP430cmp (load addr:$src1), GR16:$src2), + (implicit SRW)]>; // BIT TESTS, just sets condition codes // Note that the C condition is set differently than when using CMP. let isCommutable = 1 in { -def BIT8rr : Pseudo<(outs), (ins GR8:$src1, GR8:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def BIT16rr : Pseudo<(outs), (ins GR16:$src1, GR16:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR16:$src1, GR16:$src2)), - (implicit SRW)]>; +def BIT8rr : I8rr<0x0, + (outs), (ins GR8:$src1, GR8:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su GR8:$src1, GR8:$src2), 0), + (implicit SRW)]>; +def BIT16rr : I16rr<0x0, + (outs), (ins GR16:$src1, GR16:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su GR16:$src1, GR16:$src2), 0), + (implicit SRW)]>; } -def BIT8ri : Pseudo<(outs), (ins GR8:$src1, i8imm:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def BIT16ri : Pseudo<(outs), (ins GR16:$src1, i16imm:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def BIT8rm : Pseudo<(outs), (ins GR8:$src1, memdst:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def BIT16rm : Pseudo<(outs), (ins GR16:$src1, memdst:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; - -def BIT8mr : Pseudo<(outs), (ins memsrc:$src1, GR8:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (load addr:$src1), GR8:$src2)), - (implicit SRW)]>; -def BIT16mr : Pseudo<(outs), (ins memsrc:$src1, GR16:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (load addr:$src1), GR16:$src2)), - (implicit SRW)]>; - -def BIT8mi : Pseudo<(outs), (ins memsrc:$src1, i8imm:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (load addr:$src1), (i8 imm:$src2))), - (implicit SRW)]>; -def BIT16mi : Pseudo<(outs), (ins memsrc:$src1, i16imm:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (load addr:$src1), (i16 imm:$src2))), - (implicit SRW)]>; - -def BIT8mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (i8 (load addr:$src1)), - (load addr:$src2))), - (implicit SRW)]>; -def BIT16mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (i16 (load addr:$src1)), - (load addr:$src2))), +def BIT8ri : I8ri<0x0, + (outs), (ins GR8:$src1, i8imm:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su GR8:$src1, imm:$src2), 0), + (implicit SRW)]>; +def BIT16ri : I16ri<0x0, + (outs), (ins GR16:$src1, i16imm:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su GR16:$src1, imm:$src2), 0), + (implicit SRW)]>; + +def BIT8rm : I8rm<0x0, + (outs), (ins GR8:$src1, memdst:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su GR8:$src1, (load addr:$src2)), 0), + (implicit SRW)]>; +def BIT16rm : I16rm<0x0, + (outs), (ins GR16:$src1, memdst:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su GR16:$src1, (load addr:$src2)), 0), + (implicit SRW)]>; + +def BIT8mr : I8mr<0x0, + (outs), (ins memsrc:$src1, GR8:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su (load addr:$src1), GR8:$src2), 0), + (implicit SRW)]>; +def BIT16mr : I16mr<0x0, + (outs), (ins memsrc:$src1, GR16:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su (load addr:$src1), GR16:$src2), 0), + (implicit SRW)]>; + +def BIT8mi : I8mi<0x0, + (outs), (ins memsrc:$src1, i8imm:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su (load addr:$src1), (i8 imm:$src2)), 0), + (implicit SRW)]>; +def BIT16mi : I16mi<0x0, + (outs), (ins memsrc:$src1, i16imm:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su (load addr:$src1), (i16 imm:$src2)), 0), + (implicit SRW)]>; + +def BIT8mm : I8mm<0x0, + (outs), (ins memsrc:$src1, memsrc:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su (i8 (load addr:$src1)), + (load addr:$src2)), + 0), (implicit SRW)]>; +def BIT16mm : I16mm<0x0, + (outs), (ins memsrc:$src1, memsrc:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su (i16 (load addr:$src1)), + (load addr:$src2)), + 0), + (implicit SRW)]>; } // Defs = [SRW] //===----------------------------------------------------------------------===// @@ -923,7 +1116,8 @@ def BIT16mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2), def : Pat<(extloadi16i8 addr:$src), (MOVZX16rm8 addr:$src)>; // anyext -def : Pat<(anyext addr:$src), (MOVZX16rr8 GR8:$src)>; +def : Pat<(i16 (anyext GR8:$src)), + (SUBREG_TO_REG (i16 0), GR8:$src, subreg_8bit)>; // truncs def : Pat<(i8 (trunc GR16:$src)), @@ -996,6 +1190,6 @@ def : Pat<(store (subc (load addr:$dst), (i8 (load addr:$src))), addr:$dst), // peephole patterns def : Pat<(and GR16:$src, 255), (ZEXT16r GR16:$src)>; -def : Pat<(MSP430cmp 0, (trunc (and_su GR16:$src1, GR16:$src2))), +def : Pat<(MSP430cmp (trunc (and_su GR16:$src1, GR16:$src2)), 0), (BIT8rr (EXTRACT_SUBREG GR16:$src1, subreg_8bit), (EXTRACT_SUBREG GR16:$src2, subreg_8bit))>; diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp index 14db406..a0dbac2 100644 --- a/lib/Target/MSP430/MSP430TargetMachine.cpp +++ b/lib/Target/MSP430/MSP430TargetMachine.cpp @@ -44,3 +44,9 @@ bool MSP430TargetMachine::addInstSelector(PassManagerBase &PM, return false; } +bool MSP430TargetMachine::addPreEmitPass(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + // Must run branch selection immediately preceding the asm printer. + PM.add(createMSP430BranchSelectionPass()); + return false; +} diff --git a/lib/Target/MSP430/MSP430TargetMachine.h b/lib/Target/MSP430/MSP430TargetMachine.h index d386140..d93ac5c 100644 --- a/lib/Target/MSP430/MSP430TargetMachine.h +++ b/lib/Target/MSP430/MSP430TargetMachine.h @@ -55,6 +55,7 @@ public: } virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel); }; // MSP430TargetMachine. } // end namespace llvm diff --git a/lib/Target/MSP430/Makefile b/lib/Target/MSP430/Makefile index 4b18bc9..11195a4 100644 --- a/lib/Target/MSP430/Makefile +++ b/lib/Target/MSP430/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMMSP430CodeGen TARGET = MSP430 +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = MSP430GenRegisterInfo.h.inc MSP430GenRegisterNames.inc \ diff --git a/lib/Target/MSP430/TargetInfo/Makefile b/lib/Target/MSP430/TargetInfo/Makefile index abb08f2..d17fa7b 100644 --- a/lib/Target/MSP430/TargetInfo/Makefile +++ b/lib/Target/MSP430/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMMSP430Info +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/Makefile b/lib/Target/Makefile index 50a360f..281d58b 100644 --- a/lib/Target/Makefile +++ b/lib/Target/Makefile @@ -10,6 +10,7 @@ LEVEL = ../.. LIBRARYNAME = LLVMTarget BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti # We include this early so we can access the value of TARGETS_TO_BUILD as the # value for PARALLEL_DIRS which must be set before Makefile.rules is included diff --git a/lib/Target/Mangler.cpp b/lib/Target/Mangler.cpp new file mode 100644 index 0000000..ef6defc --- /dev/null +++ b/lib/Target/Mangler.cpp @@ -0,0 +1,179 @@ +//===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Unified name mangler for assembly backends. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/Mangler.h" +#include "llvm/GlobalValue.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +using namespace llvm; + +static bool isAcceptableChar(char C) { + if ((C < 'a' || C > 'z') && + (C < 'A' || C > 'Z') && + (C < '0' || C > '9') && + C != '_' && C != '$' && C != '.' && C != '@') + return false; + return true; +} + +static char HexDigit(int V) { + return V < 10 ? V+'0' : V+'A'-10; +} + +static void MangleLetter(SmallVectorImpl<char> &OutName, unsigned char C) { + OutName.push_back('_'); + OutName.push_back(HexDigit(C >> 4)); + OutName.push_back(HexDigit(C & 15)); + OutName.push_back('_'); +} + +/// NameNeedsEscaping - Return true if the identifier \arg Str needs quotes +/// for this assembler. +static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) { + assert(!Str.empty() && "Cannot create an empty MCSymbol"); + + // If the first character is a number and the target does not allow this, we + // need quotes. + if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9') + return true; + + // If any of the characters in the string is an unacceptable character, force + // quotes. + for (unsigned i = 0, e = Str.size(); i != e; ++i) + if (!isAcceptableChar(Str[i])) + return true; + return false; +} + +/// appendMangledName - Add the specified string in mangled form if it uses +/// any unusual characters. +static void appendMangledName(SmallVectorImpl<char> &OutName, StringRef Str, + const MCAsmInfo *MAI) { + // The first character is not allowed to be a number unless the target + // explicitly allows it. + if ((MAI == 0 || !MAI->doesAllowNameToStartWithDigit()) && + Str[0] >= '0' && Str[0] <= '9') { + MangleLetter(OutName, Str[0]); + Str = Str.substr(1); + } + + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + if (!isAcceptableChar(Str[i])) + MangleLetter(OutName, Str[i]); + else + OutName.push_back(Str[i]); + } +} + + +/// appendMangledQuotedName - On systems that support quoted symbols, we still +/// have to escape some (obscure) characters like " and \n which would break the +/// assembler's lexing. +static void appendMangledQuotedName(SmallVectorImpl<char> &OutName, + StringRef Str) { + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + if (Str[i] == '"' || Str[i] == '\n') + MangleLetter(OutName, Str[i]); + else + OutName.push_back(Str[i]); + } +} + + +/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix +/// and the specified name as the global variable name. GVName must not be +/// empty. +void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, + const Twine &GVName, ManglerPrefixTy PrefixTy) { + SmallString<256> TmpData; + StringRef Name = GVName.toStringRef(TmpData); + assert(!Name.empty() && "getNameWithPrefix requires non-empty name"); + + // If the global name is not led with \1, add the appropriate prefixes. + if (Name[0] == '\1') { + Name = Name.substr(1); + } else { + if (PrefixTy == Mangler::Private) { + const char *Prefix = MAI.getPrivateGlobalPrefix(); + OutName.append(Prefix, Prefix+strlen(Prefix)); + } else if (PrefixTy == Mangler::LinkerPrivate) { + const char *Prefix = MAI.getLinkerPrivateGlobalPrefix(); + OutName.append(Prefix, Prefix+strlen(Prefix)); + } + + const char *Prefix = MAI.getGlobalPrefix(); + if (Prefix[0] == 0) + ; // Common noop, no prefix. + else if (Prefix[1] == 0) + OutName.push_back(Prefix[0]); // Common, one character prefix. + else + OutName.append(Prefix, Prefix+strlen(Prefix)); // Arbitrary length prefix. + } + + // If this is a simple string that doesn't need escaping, just append it. + if (!NameNeedsEscaping(Name, MAI) || + // If quotes are supported, they can be used unless the string contains + // a quote or newline. + (MAI.doesAllowQuotesInName() && + Name.find_first_of("\n\"") == StringRef::npos)) { + OutName.append(Name.begin(), Name.end()); + return; + } + + // On systems that do not allow quoted names, we need to mangle most + // strange characters. + if (!MAI.doesAllowQuotesInName()) + return appendMangledName(OutName, Name, &MAI); + + // Okay, the system allows quoted strings. We can quote most anything, the + // only characters that need escaping are " and \n. + assert(Name.find_first_of("\n\"") != StringRef::npos); + return appendMangledQuotedName(OutName, Name); +} + + +/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix +/// and the specified global variable's name. If the global variable doesn't +/// have a name, this fills in a unique name for the global. +void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, + const GlobalValue *GV, + bool isImplicitlyPrivate) { + ManglerPrefixTy PrefixTy = Mangler::Default; + if (GV->hasPrivateLinkage() || isImplicitlyPrivate) + PrefixTy = Mangler::Private; + else if (GV->hasLinkerPrivateLinkage()) + PrefixTy = Mangler::LinkerPrivate; + + // If this global has a name, handle it simply. + if (GV->hasName()) + return getNameWithPrefix(OutName, GV->getName(), PrefixTy); + + // Get the ID for the global, assigning a new one if we haven't got one + // already. + unsigned &ID = AnonGlobalIDs[GV]; + if (ID == 0) ID = NextAnonGlobalID++; + + // Must mangle the global into a unique ID. + getNameWithPrefix(OutName, "__unnamed_" + Twine(ID), PrefixTy); +} + +/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix +/// and the specified global variable's name. If the global variable doesn't +/// have a name, this fills in a unique name for the global. +std::string Mangler::getNameWithPrefix(const GlobalValue *GV, + bool isImplicitlyPrivate) { + SmallString<64> Buf; + getNameWithPrefix(Buf, GV, isImplicitlyPrivate); + return std::string(Buf.begin(), Buf.end()); +} diff --git a/lib/Target/Mips/AsmPrinter/Makefile b/lib/Target/Mips/AsmPrinter/Makefile index a2fecf4..aed801e 100644 --- a/lib/Target/Mips/AsmPrinter/Makefile +++ b/lib/Target/Mips/AsmPrinter/Makefile @@ -9,6 +9,7 @@ LEVEL = ../../../.. LIBRARYNAME = LLVMMipsAsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' Mips target directory to grab # private headers diff --git a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp index efd3fb7..9af9bd8 100644 --- a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp @@ -37,7 +37,6 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Mangler.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" @@ -45,7 +44,6 @@ #include "llvm/Support/FormattedStream.h" #include "llvm/Support/MathExtras.h" #include <cctype> - using namespace llvm; STATISTIC(EmittedInsts, "Number of machine instrs printed"); @@ -72,7 +70,6 @@ namespace { const char *Modifier = 0); void printFCCOperand(const MachineInstr *MI, int opNum, const char *Modifier = 0); - void PrintGlobalVariable(const GlobalVariable *GVar); void printSavedRegsBitmask(MachineFunction &MF); void printHex32(unsigned int Value); @@ -219,15 +216,15 @@ void MipsAsmPrinter::emitFunctionStart(MachineFunction &MF) { // 2 bits aligned EmitAlignment(MF.getAlignment(), F); - O << "\t.globl\t" << CurrentFnName << '\n'; - O << "\t.ent\t" << CurrentFnName << '\n'; + O << "\t.globl\t" << *CurrentFnSym << '\n'; + O << "\t.ent\t" << *CurrentFnSym << '\n'; - printVisibility(CurrentFnName, F->getVisibility()); + printVisibility(CurrentFnSym, F->getVisibility()); if ((MAI->hasDotTypeDotSizeDirective()) && Subtarget->isLinux()) - O << "\t.type\t" << CurrentFnName << ", @function\n"; + O << "\t.type\t" << *CurrentFnSym << ", @function\n"; - O << CurrentFnName << ":\n"; + O << *CurrentFnSym << ":\n"; emitFrameDirective(MF); printSavedRegsBitmask(MF); @@ -243,9 +240,9 @@ void MipsAsmPrinter::emitFunctionEnd(MachineFunction &MF) { O << "\t.set\tmacro\n"; O << "\t.set\treorder\n"; - O << "\t.end\t" << CurrentFnName << '\n'; + O << "\t.end\t" << *CurrentFnSym << '\n'; if (MAI->hasDotTypeDotSizeDirective() && !Subtarget->isLinux()) - O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; + O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n'; } /// runOnMachineFunction - This uses the printMachineInstruction() @@ -346,20 +343,20 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { break; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_GlobalAddress: - O << Mang->getMangledName(MO.getGlobal()); + O << *GetGlobalValueSymbol(MO.getGlobal()); break; case MachineOperand::MO_ExternalSymbol: - O << MO.getSymbolName(); + O << *GetExternalSymbolSymbol(MO.getSymbolName()); break; case MachineOperand::MO_JumpTableIndex: O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); + << '_' << MO.getIndex(); break; case MachineOperand::MO_ConstantPoolIndex: @@ -425,102 +422,6 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { O << "\t.previous" << '\n'; } -void MipsAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) - return; - - O << "\n\n"; - std::string name = Mang->getMangledName(GVar); - Constant *C = GVar->getInitializer(); - const Type *CTy = C->getType(); - unsigned Size = TD->getTypeAllocSize(CTy); - const ConstantArray *CVA = dyn_cast<ConstantArray>(C); - bool printSizeAndType = true; - - // A data structure or array is aligned in memory to the largest - // alignment boundary required by any data type inside it (this matches - // the Preferred Type Alignment). For integral types, the alignment is - // the type size. - unsigned Align; - if (CTy->getTypeID() == Type::IntegerTyID || - CTy->getTypeID() == Type::VoidTyID) { - assert(!(Size & (Size-1)) && "Alignment is not a power of two!"); - Align = Log2_32(Size); - } else - Align = TD->getPreferredTypeAlignmentShift(CTy); - - printVisibility(name, GVar->getVisibility()); - - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang, - TM)); - - if (C->isNullValue() && !GVar->hasSection()) { - if (!GVar->isThreadLocal() && - (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (GVar->hasLocalLinkage()) - O << "\t.local\t" << name << '\n'; - - O << MAI->getCOMMDirective() << name << ',' << Size; - if (MAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (1 << Align); - - O << '\n'; - return; - } - } - switch (GVar->getLinkage()) { - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::CommonLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - // FIXME: Verify correct for weak. - // Nonnull linkonce -> weak - O << "\t.weak " << name << '\n'; - break; - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of their name - // or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << MAI->getGlobalDirective() << name << '\n'; - // Fall Through - case GlobalValue::PrivateLinkage: - case GlobalValue::LinkerPrivateLinkage: - case GlobalValue::InternalLinkage: - if (CVA && CVA->isCString()) - printSizeAndType = false; - break; - case GlobalValue::GhostLinkage: - llvm_unreachable("Should not have any unmaterialized functions!"); - case GlobalValue::DLLImportLinkage: - llvm_unreachable("DLLImport linkage is not supported by this target!"); - case GlobalValue::DLLExportLinkage: - llvm_unreachable("DLLExport linkage is not supported by this target!"); - default: - llvm_unreachable("Unknown linkage type!"); - } - - EmitAlignment(Align, GVar); - - if (MAI->hasDotTypeDotSizeDirective() && printSizeAndType) { - O << "\t.type " << name << ",@object\n"; - O << "\t.size " << name << ',' << Size << '\n'; - } - - O << name << ":\n"; - EmitGlobalConstant(C); -} - - // Force static initialization. extern "C" void LLVMInitializeMipsAsmPrinter() { RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget); diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile index 0780345..4e4d874 100644 --- a/lib/Target/Mips/Makefile +++ b/lib/Target/Mips/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMMipsCodeGen TARGET = Mips +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = MipsGenRegisterInfo.h.inc MipsGenRegisterNames.inc \ diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 01fe92e..c2bfb8f 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -23,11 +23,11 @@ def RetCC_MipsO32 : CallingConv<[ // i32 are returned in registers V0, V1 CCIfType<[i32], CCAssignToReg<[V0, V1]>>, - // f32 are returned in registers F0, F1 - CCIfType<[f32], CCAssignToReg<[F0, F1]>>, + // f32 are returned in registers F0, F2 + CCIfType<[f32], CCAssignToReg<[F0, F2]>>, - // f64 are returned in register D0 - CCIfType<[f64], CCIfSubtarget<"isNotSingleFloat()", CCAssignToReg<[D0]>>> + // f64 are returned in register D0, D1 + CCIfType<[f64], CCIfSubtarget<"isNotSingleFloat()", CCAssignToReg<[D0, D1]>>> ]>; //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index a53e918..e3a45d2 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -396,9 +396,9 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { else Op = (Opcode == ISD::UDIVREM ? Mips::DIVu : Mips::DIV); - SDNode *Node = CurDAG->getMachineNode(Op, dl, MVT::Flag, Op1, Op2); + SDNode *MulDiv = CurDAG->getMachineNode(Op, dl, MVT::Flag, Op1, Op2); - SDValue InFlag = SDValue(Node, 0); + SDValue InFlag = SDValue(MulDiv, 0); SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, MVT::Flag, InFlag); InFlag = SDValue(Lo,1); @@ -461,9 +461,18 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { case ISD::ConstantFP: { ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node); if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { - SDValue Zero = CurDAG->getRegister(Mips::ZERO, MVT::i32); - ReplaceUses(SDValue(Node, 0), Zero); - return Zero.getNode(); + SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + Mips::ZERO, MVT::i32); + SDValue Undef = SDValue( + CurDAG->getMachineNode( + TargetInstrInfo::IMPLICIT_DEF, dl, MVT::f64), 0); + SDNode *MTC = CurDAG->getMachineNode(Mips::MTC1, dl, MVT::f32, Zero); + SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::SUBREG_FPEVEN, dl, + MVT::f64, Undef, SDValue(MTC, 0)); + SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::SUBREG_FPODD, dl, + MVT::f64, I0, SDValue(MTC, 0)); + ReplaceUses(SDValue(Node, 0), I1); + return I1.getNode(); } break; } @@ -486,10 +495,15 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { /// be loaded with 3 instructions. case MipsISD::JmpLink: { if (TM.getRelocationModel() == Reloc::PIC_) { + unsigned LastOpNum = Node->getNumOperands()-1; + SDValue Chain = Node->getOperand(0); SDValue Callee = Node->getOperand(1); - SDValue T9Reg = CurDAG->getRegister(Mips::T9, MVT::i32); - SDValue InFlag(0, 0); + SDValue InFlag; + + // Skip the incomming flag if present + if (Node->getOperand(LastOpNum).getValueType() == MVT::Flag) + LastOpNum--; if ( (isa<GlobalAddressSDNode>(Callee)) || (isa<ExternalSymbolSDNode>(Callee)) ) @@ -504,18 +518,28 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { Chain = Load.getValue(1); // Call target must be on T9 - Chain = CurDAG->getCopyToReg(Chain, dl, T9Reg, Load, InFlag); + Chain = CurDAG->getCopyToReg(Chain, dl, Mips::T9, Load, InFlag); } else /// Indirect call - Chain = CurDAG->getCopyToReg(Chain, dl, T9Reg, Callee, InFlag); + Chain = CurDAG->getCopyToReg(Chain, dl, Mips::T9, Callee, InFlag); + + // Map the JmpLink operands to JALR + SDVTList NodeTys = CurDAG->getVTList(MVT::Other, MVT::Flag); + SmallVector<SDValue, 8> Ops; + Ops.push_back(CurDAG->getRegister(Mips::T9, MVT::i32)); + + for (unsigned i = 2, e = LastOpNum+1; i != e; ++i) + Ops.push_back(Node->getOperand(i)); + Ops.push_back(Chain); + Ops.push_back(Chain.getValue(1)); // Emit Jump and Link Register - SDNode *ResNode = CurDAG->getMachineNode(Mips::JALR, dl, MVT::Other, - MVT::Flag, T9Reg, Chain); - Chain = SDValue(ResNode, 0); - InFlag = SDValue(ResNode, 1); - ReplaceUses(SDValue(Node, 0), Chain); - ReplaceUses(SDValue(Node, 1), InFlag); + SDNode *ResNode = CurDAG->getMachineNode(Mips::JALR, dl, NodeTys, + &Ops[0], Ops.size()); + + // Replace Chain and InFlag + ReplaceUses(SDValue(Node, 0), SDValue(ResNode, 0)); + ReplaceUses(SDValue(Node, 1), SDValue(ResNode, 1)); return ResNode; } } diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 48b9bdf..1a9bffc 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -134,8 +134,6 @@ copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DestRC, const TargetRegisterClass *SrcRC) const { DebugLoc DL = DebugLoc::getUnknownLoc(); - const MachineFunction *MF = MBB.getParent(); - const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); if (I != MBB.end()) DL = I->getDebugLoc(); @@ -156,13 +154,6 @@ copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, else if ((DestRC == Mips::FGR32RegisterClass) && (SrcRC == Mips::CPURegsRegisterClass)) BuildMI(MBB, I, DL, get(Mips::MTC1), DestReg).addReg(SrcReg); - else if ((DestRC == Mips::AFGR64RegisterClass) && - (SrcRC == Mips::CPURegsRegisterClass) && - (SrcReg == Mips::ZERO)) { - const unsigned *AliasSet = TRI->getAliasSet(DestReg); - BuildMI(MBB, I, DL, get(Mips::MTC1), AliasSet[0]).addReg(SrcReg); - BuildMI(MBB, I, DL, get(Mips::MTC1), AliasSet[1]).addReg(SrcReg); - } // Move from/to Hi/Lo registers else if ((DestRC == Mips::HILORegisterClass) && diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 46cf43e..e67bcbf 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -28,8 +28,8 @@ def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; // Call -def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain, - SDNPOutFlag]>; +def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, + [SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>; // Hi and Lo nodes are used to handle global addresses. Used on // MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol @@ -306,7 +306,7 @@ let isCall=1, hasDelaySlot=1, class JumpLink<bits<6> op, string instr_asm>: FJ< op, (outs), - (ins calltarget:$target), + (ins calltarget:$target, variable_ops), !strconcat(instr_asm, "\t$target"), [(MipsJmpLink imm:$target)], IIBranch>; @@ -315,14 +315,14 @@ let isCall=1, hasDelaySlot=1, FR< op, func, (outs), - (ins CPURegs:$rs), + (ins CPURegs:$rs, variable_ops), !strconcat(instr_asm, "\t$rs"), [(MipsJmpLink CPURegs:$rs)], IIBranch>; class BranchLink<string instr_asm>: FI< 0x1, (outs), - (ins CPURegs:$rs, brtarget:$target), + (ins CPURegs:$rs, brtarget:$target, variable_ops), !strconcat(instr_asm, "\t$rs, $target"), [], IIBranch>; } diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index cae4181..80fd917 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -172,7 +172,7 @@ getReservedRegs(const MachineFunction &MF) const // // The stack is allocated decrementing the stack pointer on // the first instruction of a function prologue. Once decremented, -// all stack referencesare are done thought a positive offset +// all stack references are done thought a positive offset // from the stack/frame pointer, so the stack is considering // to grow up! Otherwise terrible hacks would have to be made // to get this stack ABI compliant :) diff --git a/lib/Target/Mips/TargetInfo/Makefile b/lib/Target/Mips/TargetInfo/Makefile index 32f4e16..f27d49e 100644 --- a/lib/Target/Mips/TargetInfo/Makefile +++ b/lib/Target/Mips/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMMipsInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/PIC16/AsmPrinter/Makefile b/lib/Target/PIC16/AsmPrinter/Makefile index f4db57e..27c4045 100644 --- a/lib/Target/PIC16/AsmPrinter/Makefile +++ b/lib/Target/PIC16/AsmPrinter/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMPIC16AsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' pic16 target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp index 87f5aad..0463596 100644 --- a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp +++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp @@ -29,7 +29,6 @@ #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include <cstring> using namespace llvm; @@ -82,7 +81,7 @@ static int getFunctionColor(const Function *F) { // Color the Auto section of the given function. void PIC16AsmPrinter::ColorAutoSection(const Function *F) { - std::string SectionName = PAN::getAutosSectionName(CurrentFnName); + std::string SectionName = PAN::getAutosSectionName(CurrentFnSym->getName()); PIC16Section* Section = PTOF->findPIC16Section(SectionName); if (Section != NULL) { int Color = getFunctionColor(F); @@ -103,11 +102,8 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { // of runOnMachineFunction. SetupMachineFunction(MF); - // Get the mangled name. - const Function *F = MF.getFunction(); - CurrentFnName = Mang->getMangledName(F); - // Put the color information from function to its auto section. + const Function *F = MF.getFunction(); ColorAutoSection(F); // Emit the function frame (args and temps). @@ -117,18 +113,18 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { // Now emit the instructions of function in its code section. const MCSection *fCodeSection - = getObjFileLowering().SectionForCode(CurrentFnName); + = getObjFileLowering().SectionForCode(CurrentFnSym->getName()); // Start the Code Section. O << "\n"; OutStreamer.SwitchSection(fCodeSection); // Emit the frame address of the function at the beginning of code. - O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnName) << ")\n"; - O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnName) << ")\n"; + O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnSym->getName()) << ")\n"; + O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnSym->getName()) << ")\n"; // Emit function start label. - O << CurrentFnName << ":\n"; + O << *CurrentFnSym << ":\n"; DebugLoc CurDL; O << "\n"; @@ -187,24 +183,22 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { return; case MachineOperand::MO_GlobalAddress: { - std::string Sname = Mang->getMangledName(MO.getGlobal()); + MCSymbol *Sym = GetGlobalValueSymbol(MO.getGlobal()); // FIXME: currently we do not have a memcpy def coming in the module // by any chance, as we do not link in those as .bc lib. So these calls // are always external and it is safe to emit an extern. - if (PAN::isMemIntrinsic(Sname)) { - LibcallDecls.push_back(createESName(Sname)); - } + if (PAN::isMemIntrinsic(Sym->getName())) + LibcallDecls.push_back(createESName(Sym->getName())); - O << Sname; + O << *Sym; break; } case MachineOperand::MO_ExternalSymbol: { const char *Sname = MO.getSymbolName(); // If its a libcall name, record it to decls section. - if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) { + if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) LibcallDecls.push_back(Sname); - } // Record a call to intrinsic to print the extern declaration for it. std::string Sym = Sname; @@ -213,11 +207,11 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { LibcallDecls.push_back(createESName(Sym)); } - O << Sym; + O << Sym; break; } case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; default: @@ -319,16 +313,14 @@ void PIC16AsmPrinter::EmitFunctionDecls(Module &M) { // Emit declarations for external functions. O <<"\n"<<MAI->getCommentString() << "Function Declarations - BEGIN." <<"\n"; for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) { - if (I->isIntrinsic()) - continue; - - std::string Name = Mang->getMangledName(I); - if (Name.compare("@abort") == 0) + if (I->isIntrinsic() || I->getName() == "@abort") continue; if (!I->isDeclaration() && !I->hasExternalLinkage()) continue; + MCSymbol *Sym = GetGlobalValueSymbol(I); + // Do not emit memcpy, memset, and memmove here. // Calls to these routines can be generated in two ways, // 1. User calling the standard lib function @@ -337,14 +329,14 @@ void PIC16AsmPrinter::EmitFunctionDecls(Module &M) { // second case the call is via and externalsym and the prototype is missing. // So declarations for these are currently always getting printing by // tracking both kind of references in printInstrunction. - if (I->isDeclaration() && PAN::isMemIntrinsic(Name)) continue; + if (I->isDeclaration() && PAN::isMemIntrinsic(Sym->getName())) continue; const char *directive = I->isDeclaration() ? MAI->getExternDirective() : MAI->getGlobalDirective(); - O << directive << Name << "\n"; - O << directive << PAN::getRetvalLabel(Name) << "\n"; - O << directive << PAN::getArgsLabel(Name) << "\n"; + O << directive << Sym->getName() << "\n"; + O << directive << PAN::getRetvalLabel(Sym->getName()) << "\n"; + O << directive << PAN::getArgsLabel(Sym->getName()) << "\n"; } O << MAI->getCommentString() << "Function Declarations - END." <<"\n"; @@ -356,9 +348,8 @@ void PIC16AsmPrinter::EmitUndefinedVars(Module &M) { if (!Items.size()) return; O << "\n" << MAI->getCommentString() << "Imported Variables - BEGIN" << "\n"; - for (unsigned j = 0; j < Items.size(); j++) { - O << MAI->getExternDirective() << Mang->getMangledName(Items[j]) << "\n"; - } + for (unsigned j = 0; j < Items.size(); j++) + O << MAI->getExternDirective() << *GetGlobalValueSymbol(Items[j]) << "\n"; O << MAI->getCommentString() << "Imported Variables - END" << "\n"; } @@ -368,9 +359,8 @@ void PIC16AsmPrinter::EmitDefinedVars(Module &M) { if (!Items.size()) return; O << "\n" << MAI->getCommentString() << "Exported Variables - BEGIN" << "\n"; - for (unsigned j = 0; j < Items.size(); j++) { - O << MAI->getGlobalDirective() << Mang->getMangledName(Items[j]) << "\n"; - } + for (unsigned j = 0; j < Items.size(); j++) + O << MAI->getGlobalDirective() << *GetGlobalValueSymbol(Items[j]) << "\n"; O << MAI->getCommentString() << "Exported Variables - END" << "\n"; } @@ -394,19 +384,19 @@ bool PIC16AsmPrinter::doFinalization(Module &M) { void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { const Function *F = MF.getFunction(); - std::string FuncName = Mang->getMangledName(F); const TargetData *TD = TM.getTargetData(); // Emit the data section name. O << "\n"; - PIC16Section *fPDataSection = const_cast<PIC16Section *>(getObjFileLowering(). - SectionForFrame(CurrentFnName)); + PIC16Section *fPDataSection = + const_cast<PIC16Section *>(getObjFileLowering(). + SectionForFrame(CurrentFnSym->getName())); fPDataSection->setColor(getFunctionColor(F)); OutStreamer.SwitchSection(fPDataSection); // Emit function frame label - O << PAN::getFrameLabel(CurrentFnName) << ":\n"; + O << PAN::getFrameLabel(CurrentFnSym->getName()) << ":\n"; const Type *RetType = F->getReturnType(); unsigned RetSize = 0; @@ -418,9 +408,10 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { // we will need to avoid printing a global directive for Retval label // in emitExternandGloblas. if(RetSize > 0) - O << PAN::getRetvalLabel(CurrentFnName) << " RES " << RetSize << "\n"; + O << PAN::getRetvalLabel(CurrentFnSym->getName()) + << " RES " << RetSize << "\n"; else - O << PAN::getRetvalLabel(CurrentFnName) << ": \n"; + O << PAN::getRetvalLabel(CurrentFnSym->getName()) << ": \n"; // Emit variable to hold the space for function arguments unsigned ArgSize = 0; @@ -430,12 +421,13 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { ArgSize += TD->getTypeAllocSize(Ty); } - O << PAN::getArgsLabel(CurrentFnName) << " RES " << ArgSize << "\n"; + O << PAN::getArgsLabel(CurrentFnSym->getName()) << " RES " << ArgSize << "\n"; // Emit temporary space int TempSize = PTLI->GetTmpSize(); if (TempSize > 0) - O << PAN::getTempdataLabel(CurrentFnName) << " RES " << TempSize << '\n'; + O << PAN::getTempdataLabel(CurrentFnSym->getName()) << " RES " + << TempSize << '\n'; } @@ -445,10 +437,9 @@ void PIC16AsmPrinter::EmitInitializedDataSection(const PIC16Section *S) { std::vector<const GlobalVariable*> Items = S->Items; for (unsigned j = 0; j < Items.size(); j++) { - std::string Name = Mang->getMangledName(Items[j]); Constant *C = Items[j]->getInitializer(); int AddrSpace = Items[j]->getType()->getAddressSpace(); - O << Name; + O << *GetGlobalValueSymbol(Items[j]); EmitGlobalConstant(C, AddrSpace); } } @@ -464,11 +455,10 @@ EmitUninitializedDataSection(const PIC16Section *S) { OutStreamer.SwitchSection(S); std::vector<const GlobalVariable*> Items = S->Items; for (unsigned j = 0; j < Items.size(); j++) { - std::string Name = Mang->getMangledName(Items[j]); Constant *C = Items[j]->getInitializer(); const Type *Ty = C->getType(); unsigned Size = TD->getTypeAllocSize(Ty); - O << Name << " RES " << Size << "\n"; + O << *GetGlobalValueSymbol(Items[j]) << " RES " << Size << "\n"; } } diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h index 838c970..74ab72c 100644 --- a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h +++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h @@ -69,9 +69,9 @@ namespace llvm { bool doInitialization(Module &M); bool doFinalization(Module &M); - /// PrintGlobalVariable - Emit the specified global variable and its + /// EmitGlobalVariable - Emit the specified global variable and its /// initializer to the output stream. - virtual void PrintGlobalVariable(const GlobalVariable *GV) { + virtual void EmitGlobalVariable(const GlobalVariable *GV) { // PIC16 doesn't use normal hooks for this. } diff --git a/lib/Target/PIC16/Makefile b/lib/Target/PIC16/Makefile index 4382eba7..a1dbde5 100644 --- a/lib/Target/PIC16/Makefile +++ b/lib/Target/PIC16/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMPIC16CodeGen TARGET = PIC16 +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = PIC16GenRegisterInfo.h.inc PIC16GenRegisterNames.inc \ diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp index 6e0e3ce..8368a3c 100644 --- a/lib/Target/PIC16/PIC16DebugInfo.cpp +++ b/lib/Target/PIC16/PIC16DebugInfo.cpp @@ -259,8 +259,9 @@ void PIC16DbgInfo::ChangeDebugLoc(const MachineFunction &MF, if (! EmitDebugDirectives) return; assert (! DL.isUnknown() && "can't change to invalid debug loc"); - MDNode *CU = MF.getDebugLocTuple(DL).Scope; - unsigned line = MF.getDebugLocTuple(DL).Line; + DILocation Loc = MF.getDILocation(DL); + MDNode *CU = Loc.getScope().getNode(); + unsigned line = Loc.getLineNumber(); SwitchToCU(CU); SwitchToLine(line, IsInBeginFunction); diff --git a/lib/Target/PIC16/PIC16Passes/Makefile b/lib/Target/PIC16/PIC16Passes/Makefile index 9684b8d..fb45d71 100644 --- a/lib/Target/PIC16/PIC16Passes/Makefile +++ b/lib/Target/PIC16/PIC16Passes/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../../.. TARGET = PIC16 LIBRARYNAME = LLVMpic16passes BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Target/PIC16/TargetInfo/Makefile b/lib/Target/PIC16/TargetInfo/Makefile index 76609f6..9004be8 100644 --- a/lib/Target/PIC16/TargetInfo/Makefile +++ b/lib/Target/PIC16/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMPIC16Info +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/PowerPC/AsmPrinter/Makefile b/lib/Target/PowerPC/AsmPrinter/Makefile index 269ef92..4378151 100644 --- a/lib/Target/PowerPC/AsmPrinter/Makefile +++ b/lib/Target/PowerPC/AsmPrinter/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMPowerPCAsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' PowerPC target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp index d505d38..b89c2b4 100644 --- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp @@ -27,21 +27,21 @@ #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DwarfWriter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -58,48 +58,7 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed"); namespace { class PPCAsmPrinter : public AsmPrinter { protected: - struct FnStubInfo { - MCSymbol *Stub, *LazyPtr, *AnonSymbol; - - FnStubInfo() { - Stub = LazyPtr = AnonSymbol = 0; - } - - void Init(const GlobalValue *GV, Mangler *Mang, MCContext &Ctx) { - // Already initialized. - if (Stub != 0) return; - - // Get the names. - SmallString<128> TmpStr; - Mang->getNameWithPrefix(TmpStr, GV, true); - MakeSymbols(TmpStr, Ctx); - } - - void Init(StringRef GVName, Mangler *Mang, MCContext &Ctx) { - assert(!GVName.empty() && "external symbol name shouldn't be empty"); - if (Stub != 0) return; // Already initialized. - // Get the names for the external symbol name. - SmallString<128> TmpStr; - Mang->getNameWithPrefix(TmpStr, GVName, Mangler::Private); - MakeSymbols(TmpStr, Ctx); - } - - void MakeSymbols(SmallString<128> &TmpStr, MCContext &Ctx) { - TmpStr += "$stub"; - Stub = Ctx.GetOrCreateSymbol(TmpStr.str()); - TmpStr.erase(TmpStr.end()-5, TmpStr.end()); // Remove $stub - - TmpStr += "$lazy_ptr"; - LazyPtr = Ctx.GetOrCreateSymbol(TmpStr.str()); - TmpStr.erase(TmpStr.end()-9, TmpStr.end()); // Remove $lazy_ptr - - TmpStr += "$stub$tmp"; - AnonSymbol = Ctx.GetOrCreateSymbol(TmpStr.str()); - } - }; - - StringMap<FnStubInfo> FnStubs; - StringMap<std::string> GVStubs, HiddenGVStubs, TOC; + DenseMap<const MCSymbol*, const MCSymbol*> TOC; const PPCSubtarget &Subtarget; uint64_t LabelID; public: @@ -240,18 +199,26 @@ namespace { GlobalValue *GV = MO.getGlobal(); if (GV->isDeclaration() || GV->isWeakForLinker()) { // Dynamically-resolved functions need a stub for the function. - FnStubInfo &FnInfo = FnStubs[Mang->getMangledName(GV)]; - FnInfo.Init(GV, Mang, OutContext); - FnInfo.Stub->print(O, MAI); + MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub"); + const MCSymbol *&StubSym = + MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); + if (StubSym == 0) + StubSym = GetGlobalValueSymbol(GV); + O << *Sym; return; } } if (MO.getType() == MachineOperand::MO_ExternalSymbol) { - SmallString<128> MangledName; - Mang->getNameWithPrefix(MangledName, MO.getSymbolName()); - FnStubInfo &FnInfo = FnStubs[MangledName.str()]; - FnInfo.Init(MO.getSymbolName(), Mang, OutContext); - FnInfo.Stub->print(O, MAI); + SmallString<128> TempNameStr; + TempNameStr += StringRef(MO.getSymbolName()); + TempNameStr += StringRef("$stub"); + + const MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str()); + const MCSymbol *&StubSym = + MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); + if (StubSym == 0) + StubSym = GetExternalSymbolSymbol(MO.getSymbolName()); + O << *Sym; return; } } @@ -338,21 +305,16 @@ namespace { assert(MO.getType() == MachineOperand::MO_GlobalAddress); - GlobalValue *GV = MO.getGlobal(); - - std::string Name = Mang->getMangledName(GV); + const MCSymbol *Sym = GetGlobalValueSymbol(MO.getGlobal()); // Map symbol -> label of TOC entry. - if (TOC.count(Name) == 0) { - std::string Label; - Label += MAI->getPrivateGlobalPrefix(); - Label += "C"; - Label += utostr(LabelID++); + const MCSymbol *&TOCEntry = TOC[Sym]; + if (TOCEntry == 0) + TOCEntry = OutContext. + GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) + "C" + + Twine(LabelID++)); - TOC[Name] = Label; - } - - O << TOC[Name] << "@toc"; + O << *TOCEntry << "@toc"; } void printPredicateOperand(const MachineInstr *MI, unsigned OpNo, @@ -381,8 +343,6 @@ namespace { AU.addRequired<DwarfWriter>(); PPCAsmPrinter::getAnalysisUsage(AU); } - - void PrintGlobalVariable(const GlobalVariable *GVar); }; /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac @@ -402,14 +362,14 @@ namespace { bool doFinalization(Module &M); void EmitStartOfAsmFile(Module &M); + void EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs); + void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired<MachineModuleInfo>(); AU.addRequired<DwarfWriter>(); PPCAsmPrinter::getAnalysisUsage(AU); } - - void PrintGlobalVariable(const GlobalVariable *GVar); }; } // end of anonymous namespace @@ -422,7 +382,7 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) { llvm_unreachable("printOp() does not handle immediate values"); case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_JumpTableIndex: O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() @@ -434,42 +394,57 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) { << '_' << MO.getIndex(); return; case MachineOperand::MO_BlockAddress: - GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI); + O << *GetBlockAddressSymbol(MO.getBlockAddress()); return; case MachineOperand::MO_ExternalSymbol: { // Computing the address of an external symbol, not calling it. - std::string Name(MAI->getGlobalPrefix()); - Name += MO.getSymbolName(); - - if (TM.getRelocationModel() != Reloc::Static) { - GVStubs[Name] = Name+"$non_lazy_ptr"; - Name += "$non_lazy_ptr"; + if (TM.getRelocationModel() == Reloc::Static) { + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + return; } - O << Name; + + const MCSymbol *NLPSym = + OutContext.GetOrCreateSymbol(StringRef(MAI->getGlobalPrefix())+ + MO.getSymbolName()+"$non_lazy_ptr"); + const MCSymbol *&StubSym = + MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(NLPSym); + if (StubSym == 0) + StubSym = GetExternalSymbolSymbol(MO.getSymbolName()); + + O << *NLPSym; return; } case MachineOperand::MO_GlobalAddress: { // Computing the address of a global symbol, not calling it. GlobalValue *GV = MO.getGlobal(); - std::string Name; + MCSymbol *SymToPrint; // External or weakly linked global variables need non-lazily-resolved stubs if (TM.getRelocationModel() != Reloc::Static && (GV->isDeclaration() || GV->isWeakForLinker())) { if (!GV->hasHiddenVisibility()) { - Name = Mang->getMangledName(GV, "$non_lazy_ptr", true); - GVStubs[Mang->getMangledName(GV)] = Name; + SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + const MCSymbol *&StubSym = + MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(SymToPrint); + if (StubSym == 0) + StubSym = GetGlobalValueSymbol(GV); } else if (GV->isDeclaration() || GV->hasCommonLinkage() || GV->hasAvailableExternallyLinkage()) { - Name = Mang->getMangledName(GV, "$non_lazy_ptr", true); - HiddenGVStubs[Mang->getMangledName(GV)] = Name; + SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + + const MCSymbol *&StubSym = + MMI->getObjFileInfo<MachineModuleInfoMachO>(). + getHiddenGVStubEntry(SymToPrint); + if (StubSym == 0) + StubSym = GetGlobalValueSymbol(GV); } else { - Name = Mang->getMangledName(GV); + SymToPrint = GetGlobalValueSymbol(GV); } } else { - Name = Mang->getMangledName(GV); + SymToPrint = GetGlobalValueSymbol(GV); } - O << Name; + + O << *SymToPrint; printOffset(MO.getOffset()); return; @@ -641,34 +616,34 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { case Function::InternalLinkage: // Symbols default to internal. break; case Function::ExternalLinkage: - O << "\t.global\t" << CurrentFnName << '\n' - << "\t.type\t" << CurrentFnName << ", @function\n"; + O << "\t.global\t" << *CurrentFnSym << '\n' << "\t.type\t"; + O << *CurrentFnSym << ", @function\n"; break; case Function::LinkerPrivateLinkage: case Function::WeakAnyLinkage: case Function::WeakODRLinkage: case Function::LinkOnceAnyLinkage: case Function::LinkOnceODRLinkage: - O << "\t.global\t" << CurrentFnName << '\n'; - O << "\t.weak\t" << CurrentFnName << '\n'; + O << "\t.global\t" << *CurrentFnSym << '\n'; + O << "\t.weak\t" << *CurrentFnSym << '\n'; break; } - printVisibility(CurrentFnName, F->getVisibility()); + printVisibility(CurrentFnSym, F->getVisibility()); EmitAlignment(MF.getAlignment(), F); if (Subtarget.isPPC64()) { // Emit an official procedure descriptor. - // FIXME 64-bit SVR4: Use MCSection here? + // FIXME 64-bit SVR4: Use MCSection here! O << "\t.section\t\".opd\",\"aw\"\n"; O << "\t.align 3\n"; - O << CurrentFnName << ":\n"; - O << "\t.quad .L." << CurrentFnName << ",.TOC.@tocbase\n"; + O << *CurrentFnSym << ":\n"; + O << "\t.quad .L." << *CurrentFnSym << ",.TOC.@tocbase\n"; O << "\t.previous\n"; - O << ".L." << CurrentFnName << ":\n"; + O << ".L." << *CurrentFnSym << ":\n"; } else { - O << CurrentFnName << ":\n"; + O << *CurrentFnSym << ":\n"; } // Emit pre-function debug information. @@ -688,7 +663,7 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { } } - O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << '\n'; + O << "\t.size\t" << *CurrentFnSym << ",.-" << *CurrentFnSym << '\n'; OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); @@ -702,92 +677,6 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) { return false; } -void PPCLinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) - return; - - std::string name = Mang->getMangledName(GVar); - - printVisibility(name, GVar->getVisibility()); - - Constant *C = GVar->getInitializer(); - const Type *Type = C->getType(); - unsigned Size = TD->getTypeAllocSize(Type); - unsigned Align = TD->getPreferredAlignmentLog(GVar); - - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang, - TM)); - - if (C->isNullValue() && /* FIXME: Verify correct */ - !GVar->hasSection() && - (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() || - GVar->isWeakForLinker())) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (GVar->hasExternalLinkage()) { - O << "\t.global " << name << '\n'; - O << "\t.type " << name << ", @object\n"; - O << name << ":\n"; - O << "\t.zero " << Size << '\n'; - } else if (GVar->hasLocalLinkage()) { - O << MAI->getLCOMMDirective() << name << ',' << Size; - } else { - O << ".comm " << name << ',' << Size; - } - if (VerboseAsm) { - O << "\t\t" << MAI->getCommentString() << " '"; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - O << "'"; - } - O << '\n'; - return; - } - - switch (GVar->getLinkage()) { - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::CommonLinkage: - case GlobalValue::LinkerPrivateLinkage: - O << "\t.global " << name << '\n' - << "\t.type " << name << ", @object\n" - << "\t.weak " << name << '\n'; - break; - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << "\t.global " << name << '\n' - << "\t.type " << name << ", @object\n"; - // FALL THROUGH - case GlobalValue::InternalLinkage: - case GlobalValue::PrivateLinkage: - break; - default: - llvm_unreachable("Unknown linkage type!"); - } - - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm) { - O << "\t\t\t\t" << MAI->getCommentString() << " '"; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - O << "'"; - } - O << '\n'; - - EmitGlobalConstant(C); - O << '\n'; -} - bool PPCLinuxAsmPrinter::doFinalization(Module &M) { const TargetData *TD = TM.getTargetData(); @@ -797,10 +686,11 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) { // FIXME 64-bit SVR4: Use MCSection here? O << "\t.section\t\".toc\",\"aw\"\n"; - for (StringMap<std::string>::iterator I = TOC.begin(), E = TOC.end(); - I != E; ++I) { - O << I->second << ":\n"; - O << "\t.tc " << I->getKeyData() << "[TC]," << I->getKeyData() << '\n'; + // FIXME: This is nondeterminstic! + for (DenseMap<const MCSymbol*, const MCSymbol*>::iterator I = TOC.begin(), + E = TOC.end(); I != E; ++I) { + O << *I->second << ":\n"; + O << "\t.tc " << *I->first << "[TC]," << *I->first << '\n'; } } @@ -829,22 +719,22 @@ bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { case Function::InternalLinkage: // Symbols default to internal. break; case Function::ExternalLinkage: - O << "\t.globl\t" << CurrentFnName << '\n'; + O << "\t.globl\t" << *CurrentFnSym << '\n'; break; case Function::WeakAnyLinkage: case Function::WeakODRLinkage: case Function::LinkOnceAnyLinkage: case Function::LinkOnceODRLinkage: case Function::LinkerPrivateLinkage: - O << "\t.globl\t" << CurrentFnName << '\n'; - O << "\t.weak_definition\t" << CurrentFnName << '\n'; + O << "\t.globl\t" << *CurrentFnSym << '\n'; + O << "\t.weak_definition\t" << *CurrentFnSym << '\n'; break; } - printVisibility(CurrentFnName, F->getVisibility()); + printVisibility(CurrentFnSym, F->getVisibility()); EmitAlignment(MF.getAlignment(), F); - O << CurrentFnName << ":\n"; + O << *CurrentFnSym << ":\n"; // Emit pre-function debug information. DW->BeginFunction(&MF); @@ -926,203 +816,110 @@ void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); } -void PPCDarwinAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) { - if (TM.getRelocationModel() == Reloc::Static) { - if (GVar->getName() == "llvm.global_ctors") - O << ".reference .constructors_used\n"; - else if (GVar->getName() == "llvm.global_dtors") - O << ".reference .destructors_used\n"; - } - return; - } - - std::string name = Mang->getMangledName(GVar); - printVisibility(name, GVar->getVisibility()); - - Constant *C = GVar->getInitializer(); - const Type *Type = C->getType(); - unsigned Size = TD->getTypeAllocSize(Type); - unsigned Align = TD->getPreferredAlignmentLog(GVar); - - const MCSection *TheSection = - getObjFileLowering().SectionForGlobal(GVar, Mang, TM); - OutStreamer.SwitchSection(TheSection); - - /// FIXME: Drive this off the section! - if (C->isNullValue() && /* FIXME: Verify correct */ - !GVar->hasSection() && - (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() || - GVar->isWeakForLinker()) && - // Don't put things that should go in the cstring section into "comm". - !TheSection->getKind().isMergeableCString()) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (GVar->hasExternalLinkage()) { - O << "\t.globl " << name << '\n'; - O << "\t.zerofill __DATA, __common, " << name << ", " - << Size << ", " << Align; - } else if (GVar->hasLocalLinkage()) { - O << MAI->getLCOMMDirective() << name << ',' << Size << ',' << Align; - } else if (!GVar->hasCommonLinkage()) { - O << "\t.globl " << name << '\n' - << MAI->getWeakDefDirective() << name << '\n'; - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm) { - O << "\t\t\t\t" << MAI->getCommentString() << " "; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - EmitGlobalConstant(C); - return; - } else { - O << ".comm " << name << ',' << Size; - // Darwin 9 and above support aligned common data. - if (Subtarget.isDarwin9()) - O << ',' << Align; - } - if (VerboseAsm) { - O << "\t\t" << MAI->getCommentString() << " '"; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - O << "'"; - } - O << '\n'; - return; - } - - switch (GVar->getLinkage()) { - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::CommonLinkage: - case GlobalValue::LinkerPrivateLinkage: - O << "\t.globl " << name << '\n' - << "\t.weak_definition " << name << '\n'; - break; - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << "\t.globl " << name << '\n'; - // FALL THROUGH - case GlobalValue::InternalLinkage: - case GlobalValue::PrivateLinkage: - break; - default: - llvm_unreachable("Unknown linkage type!"); - } - - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm) { - O << "\t\t\t\t" << MAI->getCommentString() << " '"; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - O << "'"; - } - O << '\n'; - - EmitGlobalConstant(C); - O << '\n'; +static const MCSymbol *GetLazyPtr(const MCSymbol *Sym, MCContext &Ctx) { + // Remove $stub suffix, add $lazy_ptr. + SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()-5); + TmpStr += "$lazy_ptr"; + return Ctx.GetOrCreateSymbol(TmpStr.str()); } -bool PPCDarwinAsmPrinter::doFinalization(Module &M) { - const TargetData *TD = TM.getTargetData(); - - bool isPPC64 = TD->getPointerSizeInBits() == 64; +static const MCSymbol *GetAnonSym(const MCSymbol *Sym, MCContext &Ctx) { + // Add $tmp suffix to $stub, yielding $stub$tmp. + SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()); + TmpStr += "$tmp"; + return Ctx.GetOrCreateSymbol(TmpStr.str()); +} - // Darwin/PPC always uses mach-o. +void PPCDarwinAsmPrinter:: +EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { + bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64; + TargetLoweringObjectFileMachO &TLOFMacho = static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering()); - - const MCSection *LSPSection = 0; - if (!FnStubs.empty()) // .lazy_symbol_pointer - LSPSection = TLOFMacho.getLazySymbolPointerSection(); - + // .lazy_symbol_pointer + const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection(); // Output stubs for dynamically-linked functions - if (TM.getRelocationModel() == Reloc::PIC_ && !FnStubs.empty()) { + if (TM.getRelocationModel() == Reloc::PIC_) { const MCSection *StubSection = - TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub1", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - 32, SectionKind::getText()); - for (StringMap<FnStubInfo>::iterator I = FnStubs.begin(), E = FnStubs.end(); - I != E; ++I) { + TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 32, SectionKind::getText()); + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { OutStreamer.SwitchSection(StubSection); EmitAlignment(4); - const FnStubInfo &Info = I->second; - Info.Stub->print(O, MAI); - O << ":\n"; - O << "\t.indirect_symbol " << I->getKeyData() << '\n'; + + const MCSymbol *Stub = Stubs[i].first; + const MCSymbol *RawSym = Stubs[i].second; + const MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); + const MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext); + + O << *Stub << ":\n"; + O << "\t.indirect_symbol " << *RawSym << '\n'; O << "\tmflr r0\n"; - O << "\tbcl 20,31,"; - Info.AnonSymbol->print(O, MAI); - O << '\n'; - Info.AnonSymbol->print(O, MAI); - O << ":\n"; + O << "\tbcl 20,31," << *AnonSymbol << '\n'; + O << *AnonSymbol << ":\n"; O << "\tmflr r11\n"; - O << "\taddis r11,r11,ha16("; - Info.LazyPtr->print(O, MAI); - O << '-'; - Info.AnonSymbol->print(O, MAI); - O << ")\n"; + O << "\taddis r11,r11,ha16(" << *LazyPtr << '-' << *AnonSymbol + << ")\n"; O << "\tmtlr r0\n"; - O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16("; - Info.LazyPtr->print(O, MAI); - O << '-'; - Info.AnonSymbol->print(O, MAI); - O << ")(r11)\n"; + O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16(" << *LazyPtr + << '-' << *AnonSymbol << ")(r11)\n"; O << "\tmtctr r12\n"; O << "\tbctr\n"; OutStreamer.SwitchSection(LSPSection); - Info.LazyPtr->print(O, MAI); - O << ":\n"; - O << "\t.indirect_symbol " << I->getKeyData() << '\n'; - O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n"; - } - } else if (!FnStubs.empty()) { - const MCSection *StubSection = - TLOFMacho.getMachOSection("__TEXT","__symbol_stub1", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - 16, SectionKind::getText()); - - for (StringMap<FnStubInfo>::iterator I = FnStubs.begin(), E = FnStubs.end(); - I != E; ++I) { - OutStreamer.SwitchSection(StubSection); - EmitAlignment(4); - const FnStubInfo &Info = I->second; - Info.Stub->print(O, MAI); - O << ":\n"; - O << "\t.indirect_symbol " << I->getKeyData() << '\n'; - O << "\tlis r11,ha16("; - Info.LazyPtr->print(O, MAI); - O << ")\n"; - O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16("; - Info.LazyPtr->print(O, MAI); - O << ")(r11)\n"; - O << "\tmtctr r12\n"; - O << "\tbctr\n"; - OutStreamer.SwitchSection(LSPSection); - Info.LazyPtr->print(O, MAI); - O << ":\n"; - O << "\t.indirect_symbol " << I->getKeyData() << '\n'; + O << *LazyPtr << ":\n"; + O << "\t.indirect_symbol " << *RawSym << '\n'; O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n"; } + O << '\n'; + return; } - + + const MCSection *StubSection = + TLOFMacho.getMachOSection("__TEXT","__symbol_stub1", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 16, SectionKind::getText()); + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + const MCSymbol *Stub = Stubs[i].first; + const MCSymbol *RawSym = Stubs[i].second; + const MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); + + OutStreamer.SwitchSection(StubSection); + EmitAlignment(4); + O << *Stub << ":\n"; + O << "\t.indirect_symbol " << *RawSym << '\n'; + O << "\tlis r11,ha16(" << *LazyPtr << ")\n"; + O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16(" << *LazyPtr + << ")(r11)\n"; + O << "\tmtctr r12\n"; + O << "\tbctr\n"; + OutStreamer.SwitchSection(LSPSection); + O << *LazyPtr << ":\n"; + O << "\t.indirect_symbol " << *RawSym << '\n'; + O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n"; + } + O << '\n'; +} + + +bool PPCDarwinAsmPrinter::doFinalization(Module &M) { + bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64; + + // Darwin/PPC always uses mach-o. + TargetLoweringObjectFileMachO &TLOFMacho = + static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering()); + MachineModuleInfoMachO &MMIMacho = + MMI->getObjFileInfo<MachineModuleInfoMachO>(); + + MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList(); + if (!Stubs.empty()) + EmitFunctionStubs(Stubs); if (MAI->doesSupportExceptionHandling() && MMI) { // Add the (possibly multiple) personalities to the set of global values. @@ -1130,33 +927,39 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { const std::vector<Function *> &Personalities = MMI->getPersonalities(); for (std::vector<Function *>::const_iterator I = Personalities.begin(), E = Personalities.end(); I != E; ++I) { - if (*I) - GVStubs[Mang->getMangledName(*I)] = - Mang->getMangledName(*I, "$non_lazy_ptr", true); + if (*I) { + const MCSymbol *NLPSym = + GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr"); + const MCSymbol *&StubSym = MMIMacho.getGVStubEntry(NLPSym); + StubSym = GetGlobalValueSymbol(*I); + } } } + // Output stubs for dynamically-linked functions. + Stubs = MMIMacho.GetGVStubList(); + // Output macho stubs for external and common global variables. - if (!GVStubs.empty()) { + if (!Stubs.empty()) { // Switch with ".non_lazy_symbol_pointer" directive. OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); EmitAlignment(isPPC64 ? 3 : 2); - for (StringMap<std::string>::iterator I = GVStubs.begin(), - E = GVStubs.end(); I != E; ++I) { - O << I->second << ":\n"; - O << "\t.indirect_symbol " << I->getKeyData() << '\n'; + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + O << *Stubs[i].first << ":\n"; + O << "\t.indirect_symbol " << *Stubs[i].second << '\n'; O << (isPPC64 ? "\t.quad\t0\n" : "\t.long\t0\n"); } } - if (!HiddenGVStubs.empty()) { + Stubs = MMIMacho.GetHiddenGVStubList(); + if (!Stubs.empty()) { OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); EmitAlignment(isPPC64 ? 3 : 2); - for (StringMap<std::string>::iterator I = HiddenGVStubs.begin(), - E = HiddenGVStubs.end(); I != E; ++I) { - O << I->second << ":\n"; - O << (isPPC64 ? "\t.quad\t" : "\t.long\t") << I->getKeyData() << '\n'; + + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + O << *Stubs[i].first << ":\n"; + O << (isPPC64 ? "\t.quad\t" : "\t.long\t") << *Stubs[i].second << '\n'; } } @@ -1165,7 +968,7 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { // implementation of multiple entry points). If this doesn't occur, the // linker can safely perform dead code stripping. Since LLVM never generates // code that does this, it is always safe to set. - OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols); + OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); return AsmPrinter::doFinalization(M); } diff --git a/lib/Target/PowerPC/Makefile b/lib/Target/PowerPC/Makefile index 4015d4a..cd30011 100644 --- a/lib/Target/PowerPC/Makefile +++ b/lib/Target/PowerPC/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMPowerPCCodeGen TARGET = PPC +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = PPCGenInstrNames.inc PPCGenRegisterNames.inc \ diff --git a/lib/Target/PowerPC/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/PPCMCAsmInfo.cpp index ee6deb5..d2ff3b7 100644 --- a/lib/Target/PowerPC/PPCMCAsmInfo.cpp +++ b/lib/Target/PowerPC/PPCMCAsmInfo.cpp @@ -29,7 +29,6 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) { CommentString = "#"; GlobalPrefix = ""; PrivateGlobalPrefix = ".L"; - UsedDirective = "\t# .no_dead_strip\t"; WeakRefDirective = "\t.weak\t"; // Uses '.section' before '.bss' directive @@ -53,7 +52,7 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) { SetDirective = "\t.set"; Data64bitsDirective = is64Bit ? "\t.quad\t" : 0; AlignmentIsInBytes = false; - LCOMMDirective = "\t.lcomm\t"; + HasLCOMMDirective = true; AssemblerDialect = 0; // Old-Style mnemonics. } diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index 8079c6e..c7f7882 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -194,4 +194,31 @@ bool PPCTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, return false; } - +/// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are 4-byte, +/// 8-byte, and target default. The CIE is hard-coded to indicate that the LSDA +/// pointer in the FDE section is an "sdata4", and should be encoded as a 4-byte +/// pointer by default. However, some systems may require a different size due +/// to bugs or other conditions. We will default to a 4-byte encoding unless the +/// system tells us otherwise. +/// +/// The issue is when the CIE says their is an LSDA. That mandates that every +/// FDE have an LSDA slot. But if the function does not need an LSDA. There +/// needs to be some way to signify there is none. The LSDA is encoded as +/// pc-rel. But you don't look for some magic value after adding the pc. You +/// have to look for a zero before adding the pc. The problem is that the size +/// of the zero to look for depends on the encoding. The unwinder bug in SL is +/// that it always checks for a pointer-size zero. So on x86_64 it looks for 8 +/// bytes of zero. If you have an LSDA, it works fine since the 8-bytes are +/// non-zero so it goes ahead and then reads the value based on the encoding. +/// But if you use sdata4 and there is no LSDA, then the test for zero gives a +/// false negative and the unwinder thinks there is an LSDA. +/// +/// FIXME: This call-back isn't good! We should be using the correct encoding +/// regardless of the system. However, there are some systems which have bugs +/// that prevent this from occuring. +DwarfLSDAEncoding::Encoding PPCTargetMachine::getLSDAEncoding() const { + if (Subtarget.isDarwin() && Subtarget.getDarwinVers() != 10) + return DwarfLSDAEncoding::Default; + + return DwarfLSDAEncoding::EightByte; +} diff --git a/lib/Target/PowerPC/PPCTargetMachine.h b/lib/Target/PowerPC/PPCTargetMachine.h index 3399ac8..4afcb23 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.h +++ b/lib/Target/PowerPC/PPCTargetMachine.h @@ -62,6 +62,18 @@ public: return &MachOWriterInfo; } + /// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are + /// 4-byte, 8-byte, and target default. The CIE is hard-coded to indicate that + /// the LSDA pointer in the FDE section is an "sdata4", and should be encoded + /// as a 4-byte pointer by default. However, some systems may require a + /// different size due to bugs or other conditions. We will default to a + /// 4-byte encoding unless the system tells us otherwise. + /// + /// FIXME: This call-back isn't good! We should be using the correct encoding + /// regardless of the system. However, there are some systems which have bugs + /// that prevent this from occuring. + virtual DwarfLSDAEncoding::Encoding getLSDAEncoding() const; + // Pass Pipeline Configuration virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel); diff --git a/lib/Target/PowerPC/TargetInfo/Makefile b/lib/Target/PowerPC/TargetInfo/Makefile index a101aa4..16d0167 100644 --- a/lib/Target/PowerPC/TargetInfo/Makefile +++ b/lib/Target/PowerPC/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMPowerPCInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/README.txt b/lib/Target/README.txt index 69da35f..080ea42 100644 --- a/lib/Target/README.txt +++ b/lib/Target/README.txt @@ -1665,3 +1665,54 @@ int foo() { //===---------------------------------------------------------------------===// +Missed instcombine transformation: +define i1 @a(i32 %x) nounwind readnone { +entry: + %cmp = icmp eq i32 %x, 30 + %sub = add i32 %x, -30 + %cmp2 = icmp ugt i32 %sub, 9 + %or = or i1 %cmp, %cmp2 + ret i1 %or +} +This should be optimized to a single compare. Testcase derived from gcc. + +//===---------------------------------------------------------------------===// + +Missed instcombine transformation: +void b(); +void a(int x) { if (((1<<x)&8)==0) b(); } + +The shift should be optimized out. Testcase derived from gcc. + +//===---------------------------------------------------------------------===// + +Missed instcombine or reassociate transformation: +int a(int a, int b) { return (a==12)&(b>47)&(b<58); } + +The sgt and slt should be combined into a single comparison. Testcase derived +from gcc. + +//===---------------------------------------------------------------------===// + +Missed instcombine transformation: +define i32 @a(i32 %x) nounwind readnone { +entry: + %shr = lshr i32 %x, 5 ; <i32> [#uses=1] + %xor = xor i32 %shr, 67108864 ; <i32> [#uses=1] + %sub = add i32 %xor, -67108864 ; <i32> [#uses=1] + ret i32 %sub +} + +This function is equivalent to "ashr i32 %x, 5". Testcase derived from gcc. + +//===---------------------------------------------------------------------===// + +isSafeToLoadUnconditionally should allow a GEP of a global/alloca with constant +indicies within the bounds of the allocated object. Reduced example: + +const int a[] = {3,6}; +int b(int y) { int* x = y ? &a[0] : &a[1]; return *x; } + +All the loads should be eliminated. Testcase derived from gcc. + +//===---------------------------------------------------------------------===// diff --git a/lib/Target/Sparc/AsmPrinter/Makefile b/lib/Target/Sparc/AsmPrinter/Makefile index a856828..404fad1 100644 --- a/lib/Target/Sparc/AsmPrinter/Makefile +++ b/lib/Target/Sparc/AsmPrinter/Makefile @@ -8,6 +8,8 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMSparcAsmPrinter +CXXFLAGS = -fno-rtti + # Hack: we need to include 'main' Sparc target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp index cd85dd4..8fc4e5a 100644 --- a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp +++ b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp @@ -34,7 +34,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" #include <cctype> #include <cstring> @@ -61,7 +60,6 @@ namespace { return "Sparc Assembly Printer"; } - void PrintGlobalVariable(const GlobalVariable *GVar); void printOperand(const MachineInstr *MI, int opNum); void printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier = 0); @@ -138,7 +136,7 @@ bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) { DW->EndFunction(&MF); // We didn't modify anything. - O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; + O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n'; return false; } @@ -156,7 +154,7 @@ void SparcAsmPrinter::emitFunctionHeader(const MachineFunction &MF) { case Function::DLLExportLinkage: case Function::ExternalLinkage: // Function is externally visible - O << "\t.global\t" << CurrentFnName << '\n'; + O << "\t.global\t" << *CurrentFnSym << '\n'; break; case Function::LinkerPrivateLinkage: case Function::LinkOnceAnyLinkage: @@ -164,14 +162,14 @@ void SparcAsmPrinter::emitFunctionHeader(const MachineFunction &MF) { case Function::WeakAnyLinkage: case Function::WeakODRLinkage: // Function is weak - O << "\t.weak\t" << CurrentFnName << '\n' ; + O << "\t.weak\t" << *CurrentFnSym << '\n'; break; } - printVisibility(CurrentFnName, F->getVisibility()); + printVisibility(CurrentFnSym, F->getVisibility()); - O << "\t.type\t" << CurrentFnName << ", #function\n"; - O << CurrentFnName << ":\n"; + O << "\t.type\t" << *CurrentFnSym << ", #function\n"; + O << *CurrentFnSym << ":\n"; } @@ -195,10 +193,10 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { O << (int)MO.getImm(); break; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_GlobalAddress: - O << Mang->getMangledName(MO.getGlobal()); + O << *GetGlobalValueSymbol(MO.getGlobal()); break; case MachineOperand::MO_ExternalSymbol: O << MO.getSymbolName(); @@ -277,85 +275,6 @@ void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) { O << SPARCCondCodeToString((SPCC::CondCodes)CC); } -void SparcAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) - return; - - O << "\n\n"; - std::string name = Mang->getMangledName(GVar); - Constant *C = GVar->getInitializer(); - unsigned Size = TD->getTypeAllocSize(C->getType()); - unsigned Align = TD->getPreferredAlignment(GVar); - - printVisibility(name, GVar->getVisibility()); - - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang, - TM)); - - if (C->isNullValue() && !GVar->hasSection()) { - if (!GVar->isThreadLocal() && - (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (GVar->hasLocalLinkage()) - O << "\t.local " << name << '\n'; - - O << MAI->getCOMMDirective() << name << ',' << Size; - if (MAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (1 << Align); - - O << '\n'; - return; - } - } - - switch (GVar->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: // FIXME: Verify correct for weak. - case GlobalValue::WeakODRLinkage: // FIXME: Verify correct for weak. - // Nonnull linkonce -> weak - O << "\t.weak " << name << '\n'; - break; - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << MAI->getGlobalDirective() << name << '\n'; - // FALL THROUGH - case GlobalValue::PrivateLinkage: - case GlobalValue::LinkerPrivateLinkage: - case GlobalValue::InternalLinkage: - break; - case GlobalValue::GhostLinkage: - llvm_unreachable("Should not have any unmaterialized functions!"); - case GlobalValue::DLLImportLinkage: - llvm_unreachable("DLLImport linkage is not supported by this target!"); - case GlobalValue::DLLExportLinkage: - llvm_unreachable("DLLExport linkage is not supported by this target!"); - default: - llvm_unreachable("Unknown linkage type!"); - } - - EmitAlignment(Align, GVar); - - if (MAI->hasDotTypeDotSizeDirective()) { - O << "\t.type " << name << ",#object\n"; - O << "\t.size " << name << ',' << Size << '\n'; - } - - O << name << ":\n"; - EmitGlobalConstant(C); -} - /// PrintAsmOperand - Print out an operand for an inline asm expression. /// bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile index 6714b4d..d3e2a89 100644 --- a/lib/Target/Sparc/Makefile +++ b/lib/Target/Sparc/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMSparcCodeGen TARGET = Sparc +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = SparcGenRegisterInfo.h.inc SparcGenRegisterNames.inc \ diff --git a/lib/Target/Sparc/TargetInfo/Makefile b/lib/Target/Sparc/TargetInfo/Makefile index 641ed87..0827fdb 100644 --- a/lib/Target/Sparc/TargetInfo/Makefile +++ b/lib/Target/Sparc/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMSparcInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/SystemZ/AsmPrinter/Makefile b/lib/Target/SystemZ/AsmPrinter/Makefile index 9a350df..36cd6f8 100644 --- a/lib/Target/SystemZ/AsmPrinter/Makefile +++ b/lib/Target/SystemZ/AsmPrinter/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMSystemZAsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' SystemZ target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp index e97e7ca..5c3fe37 100644 --- a/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp +++ b/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp @@ -35,8 +35,6 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" - using namespace llvm; STATISTIC(EmittedInsts, "Number of machine instrs printed"); @@ -73,7 +71,6 @@ namespace { void emitFunctionHeader(const MachineFunction &MF); bool runOnMachineFunction(MachineFunction &F); - void PrintGlobalVariable(const GlobalVariable* GVar); void getAnalysisUsage(AnalysisUsage &AU) const { AsmPrinter::getAnalysisUsage(AU); @@ -99,20 +96,20 @@ void SystemZAsmPrinter::emitFunctionHeader(const MachineFunction &MF) { case Function::LinkerPrivateLinkage: break; case Function::ExternalLinkage: - O << "\t.globl\t" << CurrentFnName << '\n'; + O << "\t.globl\t" << *CurrentFnSym << '\n'; break; case Function::LinkOnceAnyLinkage: case Function::LinkOnceODRLinkage: case Function::WeakAnyLinkage: case Function::WeakODRLinkage: - O << "\t.weak\t" << CurrentFnName << '\n'; + O << "\t.weak\t" << *CurrentFnSym << '\n'; break; } - printVisibility(CurrentFnName, F->getVisibility()); + printVisibility(CurrentFnSym, F->getVisibility()); - O << "\t.type\t" << CurrentFnName << ",@function\n" - << CurrentFnName << ":\n"; + O << "\t.type\t" << *CurrentFnSym << ",@function\n"; + O << *CurrentFnSym << ":\n"; } bool SystemZAsmPrinter::runOnMachineFunction(MachineFunction &MF) { @@ -138,7 +135,7 @@ bool SystemZAsmPrinter::runOnMachineFunction(MachineFunction &MF) { } if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; + O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n'; // Print out jump tables referenced by the function. EmitJumpTableInfo(MF.getJumpTableInfo(), MF); @@ -169,13 +166,11 @@ void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum){ O << MO.getImm(); return; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_GlobalAddress: { const GlobalValue *GV = MO.getGlobal(); - std::string Name = Mang->getMangledName(GV); - - O << Name; + O << *GetGlobalValueSymbol(GV); // Assemble calls via PLT for externally visible symbols if PIC. if (TM.getRelocationModel() == Reloc::PIC_ && @@ -226,7 +221,7 @@ void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, O << MO.getImm(); return; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_JumpTableIndex: O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' @@ -239,17 +234,11 @@ void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, printOffset(MO.getOffset()); break; - case MachineOperand::MO_GlobalAddress: { - const GlobalValue *GV = MO.getGlobal(); - std::string Name = Mang->getMangledName(GV); - - O << Name; + case MachineOperand::MO_GlobalAddress: + O << *GetGlobalValueSymbol(MO.getGlobal()); break; - } case MachineOperand::MO_ExternalSymbol: { - std::string Name(MAI->getGlobalPrefix()); - Name += MO.getSymbolName(); - O << Name; + O << *GetExternalSymbolSymbol(MO.getSymbolName()); break; } default: @@ -304,87 +293,6 @@ void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum, assert(!Index.getReg() && "Should allocate base register first!"); } -void SystemZAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { - const TargetData *TD = TM.getTargetData(); - - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) - return; - - std::string name = Mang->getMangledName(GVar); - Constant *C = GVar->getInitializer(); - unsigned Size = TD->getTypeAllocSize(C->getType()); - unsigned Align = std::max(1U, TD->getPreferredAlignmentLog(GVar)); - - printVisibility(name, GVar->getVisibility()); - - O << "\t.type\t" << name << ",@object\n"; - - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang, - TM)); - - if (C->isNullValue() && !GVar->hasSection() && - !GVar->isThreadLocal() && - (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) { - - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (GVar->hasLocalLinkage()) - O << "\t.local\t" << name << '\n'; - - O << MAI->getCOMMDirective() << name << ',' << Size; - if (MAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); - - if (VerboseAsm) { - O << "\t\t" << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - return; - } - - switch (GVar->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - O << "\t.weak\t" << name << '\n'; - break; - case GlobalValue::DLLExportLinkage: - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << "\t.globl " << name << '\n'; - // FALL THROUGH - case GlobalValue::PrivateLinkage: - case GlobalValue::LinkerPrivateLinkage: - case GlobalValue::InternalLinkage: - break; - default: - assert(0 && "Unknown linkage type!"); - } - - // Use 16-bit alignment by default to simplify bunch of stuff - EmitAlignment(Align, GVar, 1); - O << name << ":"; - if (VerboseAsm) { - O << "\t\t\t\t" << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << name << ", " << Size << '\n'; - - EmitGlobalConstant(C); -} - // Force static initialization. extern "C" void LLVMInitializeSystemZAsmPrinter() { RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget); diff --git a/lib/Target/SystemZ/Makefile b/lib/Target/SystemZ/Makefile index f1097eb..6d0cbbd 100644 --- a/lib/Target/SystemZ/Makefile +++ b/lib/Target/SystemZ/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMSystemZCodeGen TARGET = SystemZ +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = SystemZGenRegisterInfo.h.inc SystemZGenRegisterNames.inc \ diff --git a/lib/Target/SystemZ/SystemZMCAsmInfo.cpp b/lib/Target/SystemZ/SystemZMCAsmInfo.cpp index 8ea11c9..ba392bb 100644 --- a/lib/Target/SystemZ/SystemZMCAsmInfo.cpp +++ b/lib/Target/SystemZ/SystemZMCAsmInfo.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "SystemZMCAsmInfo.h" +#include "llvm/MC/MCSectionELF.h" using namespace llvm; SystemZMCAsmInfo::SystemZMCAsmInfo(const Target &T, const StringRef &TT) { @@ -21,6 +22,9 @@ SystemZMCAsmInfo::SystemZMCAsmInfo(const Target &T, const StringRef &TT) { WeakRefDirective = "\t.weak\t"; SetDirective = "\t.set\t"; PCSymbol = "."; +} - NonexecutableStackDirective = "\t.section\t.note.GNU-stack,\"\",@progbits"; +MCSection *SystemZMCAsmInfo::getNonexecutableStackSection(MCContext &Ctx) const{ + return MCSectionELF::Create(".note.GNU-stack", MCSectionELF::SHT_PROGBITS, + 0, SectionKind::getMetadata(), false, Ctx); } diff --git a/lib/Target/SystemZ/SystemZMCAsmInfo.h b/lib/Target/SystemZ/SystemZMCAsmInfo.h index 3bebcb7..00cb99b 100644 --- a/lib/Target/SystemZ/SystemZMCAsmInfo.h +++ b/lib/Target/SystemZ/SystemZMCAsmInfo.h @@ -22,8 +22,9 @@ namespace llvm { struct SystemZMCAsmInfo : public MCAsmInfo { explicit SystemZMCAsmInfo(const Target &T, const StringRef &TT); + virtual MCSection *getNonexecutableStackSection(MCContext &Ctx) const; }; - + } // namespace llvm #endif diff --git a/lib/Target/SystemZ/TargetInfo/Makefile b/lib/Target/SystemZ/TargetInfo/Makefile index 0be80eb..9f36b2c 100644 --- a/lib/Target/SystemZ/TargetInfo/Makefile +++ b/lib/Target/SystemZ/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMSystemZInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/MC/MCAsmParser.cpp b/lib/Target/TargetAsmLexer.cpp index 2287e89..0ae6c14 100644 --- a/lib/MC/MCAsmParser.cpp +++ b/lib/Target/TargetAsmLexer.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===// +//===-- llvm/Target/TargetAsmLexer.cpp - Target Assembly Lexer ------------===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAsmParser.h" - +#include "llvm/Target/TargetAsmLexer.h" using namespace llvm; -MCAsmParser::MCAsmParser() { -} - -MCAsmParser::~MCAsmParser() { -} +TargetAsmLexer::TargetAsmLexer(const Target &T) : TheTarget(T) {} +TargetAsmLexer::~TargetAsmLexer() {} diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp index 70e8008..a231ebc 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -22,11 +22,11 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -141,9 +141,18 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV, return SectionKind::getThreadData(); } + // Variables with common linkage always get classified as common. + if (GVar->hasCommonLinkage()) + return SectionKind::getCommon(); + // Variable can be easily put to BSS section. - if (isSuitableForBSS(GVar)) + if (isSuitableForBSS(GVar)) { + if (GVar->hasLocalLinkage()) + return SectionKind::getBSSLocal(); + else if (GVar->hasExternalLinkage()) + return SectionKind::getBSSExtern(); return SectionKind::getBSS(); + } Constant *C = GVar->getInitializer(); @@ -300,6 +309,7 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, IsIndirect = false; IsPCRel = false; + // FIXME: Use GetGlobalValueSymbol. SmallString<128> Name; Mang->getNameWithPrefix(Name, GV, false); return MCSymbolRefExpr::Create(Name.str(), getContext()); @@ -464,30 +474,30 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, static SectionKind -getELFKindForNamedSection(const char *Name, SectionKind K) { - if (Name[0] != '.') return K; +getELFKindForNamedSection(StringRef Name, SectionKind K) { + if (Name.empty() || Name[0] != '.') return K; // Some lame default implementation based on some magic section names. - if (strcmp(Name, ".bss") == 0 || - strncmp(Name, ".bss.", 5) == 0 || - strncmp(Name, ".gnu.linkonce.b.", 16) == 0 || - strncmp(Name, ".llvm.linkonce.b.", 17) == 0 || - strcmp(Name, ".sbss") == 0 || - strncmp(Name, ".sbss.", 6) == 0 || - strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 || - strncmp(Name, ".llvm.linkonce.sb.", 18) == 0) + if (Name == ".bss" || + Name.startswith(".bss.") || + Name.startswith(".gnu.linkonce.b.") || + Name.startswith(".llvm.linkonce.b.") || + Name == ".sbss" || + Name.startswith(".sbss.") || + Name.startswith(".gnu.linkonce.sb.") || + Name.startswith(".llvm.linkonce.sb.")) return SectionKind::getBSS(); - if (strcmp(Name, ".tdata") == 0 || - strncmp(Name, ".tdata.", 7) == 0 || - strncmp(Name, ".gnu.linkonce.td.", 17) == 0 || - strncmp(Name, ".llvm.linkonce.td.", 18) == 0) + if (Name == ".tdata" || + Name.startswith(".tdata.") || + Name.startswith(".gnu.linkonce.td.") || + Name.startswith(".llvm.linkonce.td.")) return SectionKind::getThreadData(); - if (strcmp(Name, ".tbss") == 0 || - strncmp(Name, ".tbss.", 6) == 0 || - strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 || - strncmp(Name, ".llvm.linkonce.tb.", 18) == 0) + if (Name == ".tbss" || + Name.startswith(".tbss.") || + Name.startswith(".gnu.linkonce.tb.") || + Name.startswith(".llvm.linkonce.tb.")) return SectionKind::getThreadBSS(); return K; @@ -543,7 +553,7 @@ getELFSectionFlags(SectionKind K) { const MCSection *TargetLoweringObjectFileELF:: getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { - const char *SectionName = GV->getSection().c_str(); + StringRef SectionName = GV->getSection(); // Infer section flags from the section name if we can. Kind = getELFKindForNamedSection(SectionName, Kind); @@ -560,7 +570,6 @@ static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) { if (Kind.isThreadData()) return ".gnu.linkonce.td."; if (Kind.isThreadBSS()) return ".gnu.linkonce.tb."; - if (Kind.isBSS()) return ".gnu.linkonce.b."; if (Kind.isDataNoRel()) return ".gnu.linkonce.d."; if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local."; if (Kind.isDataRel()) return ".gnu.linkonce.d.rel."; @@ -576,20 +585,13 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, // If this global is linkonce/weak and the target handles this by emitting it // into a 'uniqued' section name, create and return the section now. - if (GV->isWeakForLinker()) { + if (GV->isWeakForLinker() && !Kind.isCommon() && !Kind.isBSS()) { const char *Prefix = getSectionPrefixForUniqueGlobal(Kind); - SmallString<128> Name, MangledName; + SmallString<128> Name; Name.append(Prefix, Prefix+strlen(Prefix)); Mang->getNameWithPrefix(Name, GV, false); - - raw_svector_ostream OS(MangledName); - MCSymbol::printMangledName(Name, OS, 0); - OS.flush(); - - return getELFSection(MangledName.str(), - getELFSectionType(MangledName.str(), Kind), - getELFSectionFlags(Kind), - Kind); + return getELFSection(Name.str(), getELFSectionType(Name.str(), Kind), + getELFSectionFlags(Kind), Kind); } if (Kind.isText()) return TextSection; @@ -614,7 +616,7 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, std::string Name = SizeSpec + utostr(Align); - return getELFSection(Name.c_str(), MCSectionELF::SHT_PROGBITS, + return getELFSection(Name, MCSectionELF::SHT_PROGBITS, MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE | MCSectionELF::SHF_STRINGS, @@ -636,7 +638,10 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, if (Kind.isThreadData()) return TLSDataSection; if (Kind.isThreadBSS()) return TLSBSSSection; - if (Kind.isBSS()) return BSSSection; + // Note: we claim that common symbols are put in BSSSection, but they are + // really emitted with the magic .comm directive, which creates a symbol table + // entry but not a section. + if (Kind.isBSS() || Kind.isCommon()) return BSSSection; if (Kind.isDataNoRel()) return DataSection; if (Kind.isDataRelLocal()) return DataRelLocalSection; @@ -762,7 +767,13 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, DataCoalSection = getMachOSection("__DATA","__datacoal_nt", MCSectionMachO::S_COALESCED, SectionKind::getDataRel()); - + DataCommonSection + = getMachOSection("__DATA","__common", MCSectionMachO::S_ZEROFILL, + SectionKind::getBSS()); + DataBSSSection + = getMachOSection("__DATA","__bss", MCSectionMachO::S_ZEROFILL, + SectionKind::getBSS()); + LazySymbolPointerSection = getMachOSection("__DATA", "__la_symbol_ptr", @@ -921,6 +932,16 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, if (Kind.isReadOnlyWithRel()) return ConstDataSection; + // Put zero initialized globals with strong external linkage in the + // DATA, __common section with the .zerofill directive. + if (Kind.isBSSExtern()) + return DataCommonSection; + + // Put zero initialized globals with local linkage in __DATA,__bss directive + // with the .zerofill directive (aka .lcomm). + if (Kind.isBSSLocal()) + return DataBSSSection; + // Otherwise, just drop the variable in the normal data section. return DataSection; } @@ -955,7 +976,8 @@ shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const { // FIXME: ObjC metadata is currently emitted as internal symbols that have // \1L and \0l prefixes on them. Fix them to be Private/LinkerPrivate and // this horrible hack can go away. - const std::string &Name = Mang->getMangledName(GV); + SmallString<64> Name; + Mang->getNameWithPrefix(Name, GV, false); if (Name[0] == 'L' || Name[0] == 'l') return false; } @@ -1064,7 +1086,7 @@ void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx, const MCSection *TargetLoweringObjectFileCOFF:: getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { - return getCOFFSection(GV->getSection().c_str(), false, Kind); + return getCOFFSection(GV->getSection(), false, Kind); } static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) { diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index 46bc9a3..fec59b5 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -46,7 +46,6 @@ namespace llvm { bool DisableJumpTables; bool StrongPHIElim; bool AsmVerbosityDefault(false); - bool DisableScheduling; } static cl::opt<bool, true> @@ -198,11 +197,6 @@ EnableStrongPHIElim(cl::Hidden, "strong-phi-elim", cl::desc("Use strong PHI elimination."), cl::location(StrongPHIElim), cl::init(false)); -static cl::opt<bool, true> -DisableInstScheduling("disable-scheduling", - cl::desc("Disable instruction scheduling"), - cl::location(DisableScheduling), - cl::init(false)); //--------------------------------------------------------------------------- // TargetMachine Class diff --git a/lib/Target/X86/AsmParser/CMakeLists.txt b/lib/Target/X86/AsmParser/CMakeLists.txt index 034d5ab..40dbdd7 100644 --- a/lib/Target/X86/AsmParser/CMakeLists.txt +++ b/lib/Target/X86/AsmParser/CMakeLists.txt @@ -1,6 +1,7 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) add_llvm_library(LLVMX86AsmParser + X86AsmLexer.cpp X86AsmParser.cpp ) add_dependencies(LLVMX86AsmParser X86CodeGenTable_gen) diff --git a/lib/Target/X86/AsmParser/Makefile b/lib/Target/X86/AsmParser/Makefile index 25fb0a2..288b985 100644 --- a/lib/Target/X86/AsmParser/Makefile +++ b/lib/Target/X86/AsmParser/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMX86AsmParser +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' x86 target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/X86/AsmParser/X86AsmLexer.cpp b/lib/Target/X86/AsmParser/X86AsmLexer.cpp new file mode 100644 index 0000000..1a62044 --- /dev/null +++ b/lib/Target/X86/AsmParser/X86AsmLexer.cpp @@ -0,0 +1,43 @@ +//===-- X86AsmLexer.cpp - Tokenize X86 assembly to AsmTokens --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetAsmLexer.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "X86.h" + +using namespace llvm; + +namespace { + +class X86AsmLexer : public TargetAsmLexer { + const MCAsmInfo &AsmInfo; +protected: + AsmToken LexToken(); +public: + X86AsmLexer(const Target &T, const MCAsmInfo &MAI) + : TargetAsmLexer(T), AsmInfo(MAI) { + } +}; + +} + +AsmToken X86AsmLexer::LexToken() { + return AsmToken(AsmToken::Error, "", 0); +} + +extern "C" void LLVMInitializeX86AsmLexer() { + RegisterAsmLexer<X86AsmLexer> X(TheX86_32Target); + RegisterAsmLexer<X86AsmLexer> Y(TheX86_64Target); +} + +//#define REGISTERS_ONLY +//#include "../X86GenAsmMatcher.inc" +//#undef REGISTERS_ONLY diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index c4ae5d2..7a9218e 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -11,12 +11,12 @@ #include "X86.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAsmLexer.h" -#include "llvm/MC/MCAsmParser.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/MC/MCParsedAsmOperand.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetAsmParser.h" @@ -37,11 +37,10 @@ private: bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } - bool ParseRegister(X86Operand &Op); + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); - bool ParseOperand(X86Operand &Op); - - bool ParseMemOperand(X86Operand &Op); + X86Operand *ParseOperand(); + X86Operand *ParseMemOperand(); bool ParseDirectiveWord(unsigned Size, SMLoc L); @@ -51,10 +50,6 @@ private: bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst); - /// MatchRegisterName - Match the given string to a register name, or 0 if - /// there is no match. - unsigned MatchRegisterName(const StringRef &Name); - /// } public: @@ -69,19 +64,27 @@ public: } // end anonymous namespace +/// @name Auto-generated Match Functions +/// { + +static unsigned MatchRegisterName(const StringRef &Name); + +/// } namespace { /// X86Operand - Instances of this class represent a parsed X86 machine /// instruction. struct X86Operand : public MCParsedAsmOperand { - enum { + enum KindTy { Token, Register, Immediate, Memory } Kind; + SMLoc StartLoc, EndLoc; + union { struct { const char *Data; @@ -105,6 +108,14 @@ struct X86Operand : public MCParsedAsmOperand { } Mem; }; + X86Operand(KindTy K, SMLoc Start, SMLoc End) + : Kind(K), StartLoc(Start), EndLoc(End) {} + + /// getStartLoc - Get the location of the first token of this operand. + SMLoc getStartLoc() const { return StartLoc; } + /// getEndLoc - Get the location of the last token of this operand. + SMLoc getEndLoc() const { return EndLoc; } + StringRef getToken() const { assert(Kind == Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); @@ -192,44 +203,40 @@ struct X86Operand : public MCParsedAsmOperand { Inst.addOperand(MCOperand::CreateReg(getMemSegReg())); } - static X86Operand CreateToken(StringRef Str) { - X86Operand Res; - Res.Kind = Token; - Res.Tok.Data = Str.data(); - Res.Tok.Length = Str.size(); + static X86Operand *CreateToken(StringRef Str, SMLoc Loc) { + X86Operand *Res = new X86Operand(Token, Loc, Loc); + Res->Tok.Data = Str.data(); + Res->Tok.Length = Str.size(); return Res; } - static X86Operand CreateReg(unsigned RegNo) { - X86Operand Res; - Res.Kind = Register; - Res.Reg.RegNo = RegNo; + static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) { + X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc); + Res->Reg.RegNo = RegNo; return Res; } - static X86Operand CreateImm(const MCExpr *Val) { - X86Operand Res; - Res.Kind = Immediate; - Res.Imm.Val = Val; + static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){ + X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc); + Res->Imm.Val = Val; return Res; } - static X86Operand CreateMem(unsigned SegReg, const MCExpr *Disp, - unsigned BaseReg, unsigned IndexReg, - unsigned Scale) { + static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp, + unsigned BaseReg, unsigned IndexReg, + unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) { // We should never just have a displacement, that would be an immediate. assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!"); // The scale should always be one of {1,2,4,8}. assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) && "Invalid scale!"); - X86Operand Res; - Res.Kind = Memory; - Res.Mem.SegReg = SegReg; - Res.Mem.Disp = Disp; - Res.Mem.BaseReg = BaseReg; - Res.Mem.IndexReg = IndexReg; - Res.Mem.Scale = Scale; + X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc); + Res->Mem.SegReg = SegReg; + Res->Mem.Disp = Disp; + Res->Mem.BaseReg = BaseReg; + Res->Mem.IndexReg = IndexReg; + Res->Mem.Scale = Scale; return Res; } }; @@ -237,52 +244,57 @@ struct X86Operand : public MCParsedAsmOperand { } // end anonymous namespace. -bool X86ATTAsmParser::ParseRegister(X86Operand &Op) { - const AsmToken &TokPercent = getLexer().getTok(); - (void)TokPercent; // Avoid warning when assertions are disabled. +bool X86ATTAsmParser::ParseRegister(unsigned &RegNo, + SMLoc &StartLoc, SMLoc &EndLoc) { + RegNo = 0; + const AsmToken &TokPercent = Parser.getTok(); assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!"); - getLexer().Lex(); // Eat percent token. + StartLoc = TokPercent.getLoc(); + Parser.Lex(); // Eat percent token. - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) return Error(Tok.getLoc(), "invalid register name"); // FIXME: Validate register for the current architecture; we have to do // validation later, so maybe there is no need for this here. - unsigned RegNo; - RegNo = MatchRegisterName(Tok.getString()); if (RegNo == 0) return Error(Tok.getLoc(), "invalid register name"); - Op = X86Operand::CreateReg(RegNo); - getLexer().Lex(); // Eat identifier token. - + EndLoc = Tok.getLoc(); + Parser.Lex(); // Eat identifier token. return false; } -bool X86ATTAsmParser::ParseOperand(X86Operand &Op) { +X86Operand *X86ATTAsmParser::ParseOperand() { switch (getLexer().getKind()) { default: - return ParseMemOperand(Op); - case AsmToken::Percent: + return ParseMemOperand(); + case AsmToken::Percent: { // FIXME: if a segment register, this could either be just the seg reg, or // the start of a memory operand. - return ParseRegister(Op); + unsigned RegNo; + SMLoc Start, End; + if (ParseRegister(RegNo, Start, End)) return 0; + return X86Operand::CreateReg(RegNo, Start, End); + } case AsmToken::Dollar: { // $42 -> immediate. - getLexer().Lex(); + SMLoc Start = Parser.getTok().getLoc(), End; + Parser.Lex(); const MCExpr *Val; - if (getParser().ParseExpression(Val)) - return true; - Op = X86Operand::CreateImm(Val); - return false; + if (getParser().ParseExpression(Val, End)) + return 0; + return X86Operand::CreateImm(Val, Start, End); } } } /// ParseMemOperand: segment: disp(basereg, indexreg, scale) -bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) { +X86Operand *X86ATTAsmParser::ParseMemOperand() { + SMLoc MemStart = Parser.getTok().getLoc(); + // FIXME: If SegReg ':' (e.g. %gs:), eat and remember. unsigned SegReg = 0; @@ -292,47 +304,47 @@ bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) { // it. const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext()); if (getLexer().isNot(AsmToken::LParen)) { - if (getParser().ParseExpression(Disp)) return true; + SMLoc ExprEnd; + if (getParser().ParseExpression(Disp, ExprEnd)) return 0; // After parsing the base expression we could either have a parenthesized // memory address or not. If not, return now. If so, eat the (. if (getLexer().isNot(AsmToken::LParen)) { // Unless we have a segment register, treat this as an immediate. - if (SegReg) - Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 1); - else - Op = X86Operand::CreateImm(Disp); - return false; + if (SegReg == 0) + return X86Operand::CreateImm(Disp, MemStart, ExprEnd); + return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd); } // Eat the '('. - getLexer().Lex(); + Parser.Lex(); } else { // Okay, we have a '('. We don't know if this is an expression or not, but // so we have to eat the ( to see beyond it. - getLexer().Lex(); // Eat the '('. + SMLoc LParenLoc = Parser.getTok().getLoc(); + Parser.Lex(); // Eat the '('. if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) { // Nothing to do here, fall into the code below with the '(' part of the // memory operand consumed. } else { + SMLoc ExprEnd; + // It must be an parenthesized expression, parse it now. - if (getParser().ParseParenExpression(Disp)) - return true; + if (getParser().ParseParenExpression(Disp, ExprEnd)) + return 0; // After parsing the base expression we could either have a parenthesized // memory address or not. If not, return now. If so, eat the (. if (getLexer().isNot(AsmToken::LParen)) { // Unless we have a segment register, treat this as an immediate. - if (SegReg) - Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 1); - else - Op = X86Operand::CreateImm(Disp); - return false; + if (SegReg == 0) + return X86Operand::CreateImm(Disp, LParenLoc, ExprEnd); + return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd); } // Eat the '('. - getLexer().Lex(); + Parser.Lex(); } } @@ -341,13 +353,12 @@ bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) { unsigned BaseReg = 0, IndexReg = 0, Scale = 1; if (getLexer().is(AsmToken::Percent)) { - if (ParseRegister(Op)) - return true; - BaseReg = Op.getReg(); + SMLoc L; + if (ParseRegister(BaseReg, L, L)) return 0; } if (getLexer().is(AsmToken::Comma)) { - getLexer().Lex(); // Eat the comma. + Parser.Lex(); // Eat the comma. // Following the comma we should have either an index register, or a scale // value. We don't support the later form, but we want to parse it @@ -356,82 +367,89 @@ bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) { // Not that even though it would be completely consistent to support syntax // like "1(%eax,,1)", the assembler doesn't. if (getLexer().is(AsmToken::Percent)) { - if (ParseRegister(Op)) - return true; - IndexReg = Op.getReg(); + SMLoc L; + if (ParseRegister(IndexReg, L, L)) return 0; if (getLexer().isNot(AsmToken::RParen)) { // Parse the scale amount: // ::= ',' [scale-expression] - if (getLexer().isNot(AsmToken::Comma)) - return true; - getLexer().Lex(); // Eat the comma. + if (getLexer().isNot(AsmToken::Comma)) { + Error(Parser.getTok().getLoc(), + "expected comma in scale expression"); + return 0; + } + Parser.Lex(); // Eat the comma. if (getLexer().isNot(AsmToken::RParen)) { - SMLoc Loc = getLexer().getTok().getLoc(); + SMLoc Loc = Parser.getTok().getLoc(); int64_t ScaleVal; if (getParser().ParseAbsoluteExpression(ScaleVal)) - return true; + return 0; // Validate the scale amount. - if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8) - return Error(Loc, "scale factor in address must be 1, 2, 4 or 8"); + if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){ + Error(Loc, "scale factor in address must be 1, 2, 4 or 8"); + return 0; + } Scale = (unsigned)ScaleVal; } } } else if (getLexer().isNot(AsmToken::RParen)) { // Otherwise we have the unsupported form of a scale amount without an // index. - SMLoc Loc = getLexer().getTok().getLoc(); + SMLoc Loc = Parser.getTok().getLoc(); int64_t Value; if (getParser().ParseAbsoluteExpression(Value)) - return true; + return 0; - return Error(Loc, "cannot have scale factor without index register"); + Error(Loc, "cannot have scale factor without index register"); + return 0; } } // Ok, we've eaten the memory operand, verify we have a ')' and eat it too. - if (getLexer().isNot(AsmToken::RParen)) - return Error(getLexer().getTok().getLoc(), - "unexpected token in memory operand"); - getLexer().Lex(); // Eat the ')'. + if (getLexer().isNot(AsmToken::RParen)) { + Error(Parser.getTok().getLoc(), "unexpected token in memory operand"); + return 0; + } + SMLoc MemEnd = Parser.getTok().getLoc(); + Parser.Lex(); // Eat the ')'. - Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale); - return false; + return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, + MemStart, MemEnd); } bool X86ATTAsmParser:: ParseInstruction(const StringRef &Name, SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - Operands.push_back(new X86Operand(X86Operand::CreateToken(Name))); + Operands.push_back(X86Operand::CreateToken(Name, NameLoc)); - SMLoc Loc = getLexer().getTok().getLoc(); if (getLexer().isNot(AsmToken::EndOfStatement)) { // Parse '*' modifier. if (getLexer().is(AsmToken::Star)) { - getLexer().Lex(); // Eat the star. - Operands.push_back(new X86Operand(X86Operand::CreateToken("*"))); + SMLoc Loc = Parser.getTok().getLoc(); + Operands.push_back(X86Operand::CreateToken("*", Loc)); + Parser.Lex(); // Eat the star. } // Read the first operand. - X86Operand Op; - if (ParseOperand(Op)) + if (X86Operand *Op = ParseOperand()) + Operands.push_back(Op); + else return true; - - Operands.push_back(new X86Operand(Op)); - + while (getLexer().is(AsmToken::Comma)) { - getLexer().Lex(); // Eat the comma. + Parser.Lex(); // Eat the comma. // Parse and remember the operand. - if (ParseOperand(Op)) + if (X86Operand *Op = ParseOperand()) + Operands.push_back(Op); + else return true; - Operands.push_back(new X86Operand(Op)); } } @@ -454,7 +472,7 @@ bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { if (getParser().ParseExpression(Value)) return true; - getParser().getStreamer().EmitValue(Value, Size); + getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/); if (getLexer().is(AsmToken::EndOfStatement)) break; @@ -462,18 +480,21 @@ bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { // FIXME: Improve diagnostic. if (getLexer().isNot(AsmToken::Comma)) return Error(L, "unexpected token in directive"); - getLexer().Lex(); + Parser.Lex(); } } - getLexer().Lex(); + Parser.Lex(); return false; } +extern "C" void LLVMInitializeX86AsmLexer(); + // Force static initialization. extern "C" void LLVMInitializeX86AsmParser() { RegisterAsmParser<X86ATTAsmParser> X(TheX86_32Target); RegisterAsmParser<X86ATTAsmParser> Y(TheX86_64Target); + LLVMInitializeX86AsmLexer(); } #include "X86GenAsmMatcher.inc" diff --git a/lib/Target/X86/AsmPrinter/Makefile b/lib/Target/X86/AsmPrinter/Makefile index 2368761..326a22f 100644 --- a/lib/Target/X86/AsmPrinter/Makefile +++ b/lib/Target/X86/AsmPrinter/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMX86AsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' x86 target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp index c74b97a..804dbb9 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp @@ -55,7 +55,7 @@ void X86ATTInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) { O << (int)Op.getImm(); else { assert(Op.isExpr() && "unknown pcrel immediate operand"); - Op.getExpr()->print(O, &MAI); + O << *Op.getExpr(); } } @@ -68,8 +68,7 @@ void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo) { O << '$' << Op.getImm(); } else { assert(Op.isExpr() && "unknown operand kind in printOperand"); - O << '$'; - Op.getExpr()->print(O, &MAI); + O << '$' << *Op.getExpr(); } } @@ -84,7 +83,7 @@ void X86ATTInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { O << DispVal; } else { assert(DispSpec.isExpr() && "non-immediate displacement for LEA?"); - DispSpec.getExpr()->print(O, &MAI); + O << *DispSpec.getExpr(); } if (IndexReg.getReg() || BaseReg.getReg()) { diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp index 70c6dd0..2ffa18f 100644 --- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp @@ -36,7 +36,6 @@ #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" @@ -61,7 +60,7 @@ void X86AsmPrinter::printMCInst(const MCInst *MI) { void X86AsmPrinter::PrintPICBaseSymbol() const { // FIXME: Gross const cast hack. X86AsmPrinter *AP = const_cast<X86AsmPrinter*>(this); - X86MCInstLower(OutContext, 0, *AP).GetPICBaseSymbol()->print(O, MAI); + O << *X86MCInstLower(OutContext, 0, *AP).GetPICBaseSymbol(); } void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { @@ -71,7 +70,8 @@ void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { if (Subtarget->isTargetCygMing()) { X86COFFMachineModuleInfo &COFFMMI = MMI->getObjFileInfo<X86COFFMachineModuleInfo>(); - COFFMMI.DecorateCygMingName(CurrentFnName, F, *TM.getTargetData()); + COFFMMI.DecorateCygMingName(CurrentFnSym, OutContext, F, + *TM.getTargetData()); } OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); @@ -84,7 +84,7 @@ void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { break; case Function::DLLExportLinkage: case Function::ExternalLinkage: - O << "\t.globl\t" << CurrentFnName << '\n'; + OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_Global); break; case Function::LinkerPrivateLinkage: case Function::LinkOnceAnyLinkage: @@ -92,30 +92,30 @@ void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { case Function::WeakAnyLinkage: case Function::WeakODRLinkage: if (Subtarget->isTargetDarwin()) { - O << "\t.globl\t" << CurrentFnName << '\n'; - O << MAI->getWeakDefDirective() << CurrentFnName << '\n'; + OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_Global); + O << MAI->getWeakDefDirective() << *CurrentFnSym << '\n'; } else if (Subtarget->isTargetCygMing()) { - O << "\t.globl\t" << CurrentFnName << "\n" - "\t.linkonce discard\n"; + OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_Global); + O << "\t.linkonce discard\n"; } else { - O << "\t.weak\t" << CurrentFnName << '\n'; + O << "\t.weak\t" << *CurrentFnSym << '\n'; } break; } - printVisibility(CurrentFnName, F->getVisibility()); + printVisibility(CurrentFnSym, F->getVisibility()); - if (Subtarget->isTargetELF()) - O << "\t.type\t" << CurrentFnName << ",@function\n"; - else if (Subtarget->isTargetCygMing()) { - O << "\t.def\t " << CurrentFnName - << ";\t.scl\t" << + if (Subtarget->isTargetELF()) { + O << "\t.type\t" << *CurrentFnSym << ",@function\n"; + } else if (Subtarget->isTargetCygMing()) { + O << "\t.def\t " << *CurrentFnSym; + O << ";\t.scl\t" << (F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT) << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) << ";\t.endef\n"; } - O << CurrentFnName << ':'; + O << *CurrentFnSym << ':'; if (VerboseAsm) { O.PadToColumn(MAI->getCommentColumn()); O << MAI->getCommentString() << ' '; @@ -126,7 +126,7 @@ void X86AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { // Add some workaround for linkonce linkage on Cygwin\MinGW if (Subtarget->isTargetCygMing() && (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) - O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n"; + O << "Lllvm$workaround$fake$stub$" << *CurrentFnSym << ":\n"; } /// runOnMachineFunction - This uses the printMachineInstruction() @@ -184,7 +184,7 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { } if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; + O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n'; // Emit post-function debug information. if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) @@ -201,93 +201,78 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { /// jump tables, constant pools, global address and external symbols, all of /// which print to a label with various suffixes for relocation types etc. void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) { - SmallString<128> TempNameStr; switch (MO.getType()) { default: llvm_unreachable("unknown symbol type!"); case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' - << MO.getIndex(); + O << *GetJTISymbol(MO.getIndex()); break; case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' - << MO.getIndex(); + O << *GetCPISymbol(MO.getIndex()); printOffset(MO.getOffset()); break; case MachineOperand::MO_GlobalAddress: { const GlobalValue *GV = MO.getGlobal(); - const char *Suffix = ""; + MCSymbol *GVSym; if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) - Suffix = "$stub"; + GVSym = GetSymbolWithGlobalValueBase(GV, "$stub"); else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) - Suffix = "$non_lazy_ptr"; - - std::string Name = Mang->getMangledName(GV, Suffix, Suffix[0] != '\0'); + GVSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + else + GVSym = GetGlobalValueSymbol(GV); + if (Subtarget->isTargetCygMing()) { X86COFFMachineModuleInfo &COFFMMI = MMI->getObjFileInfo<X86COFFMachineModuleInfo>(); - COFFMMI.DecorateCygMingName(Name, GV, *TM.getTargetData()); + COFFMMI.DecorateCygMingName(GVSym, OutContext, GV, *TM.getTargetData()); } // Handle dllimport linkage. if (MO.getTargetFlags() == X86II::MO_DLLIMPORT) - Name = "__imp_" + Name; + GVSym = OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName()); if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) { - Mang->getNameWithPrefix(TempNameStr, GV, true); - TempNameStr += "$non_lazy_ptr"; - MCSymbol *Sym = OutContext.GetOrCreateSymbol(TempNameStr.str()); + MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); const MCSymbol *&StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym); - if (StubSym == 0) { - TempNameStr.clear(); - Mang->getNameWithPrefix(TempNameStr, GV, false); - StubSym = OutContext.GetOrCreateSymbol(TempNameStr.str()); - } + if (StubSym == 0) + StubSym = GetGlobalValueSymbol(GV); + } else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){ - Mang->getNameWithPrefix(TempNameStr, GV, true); - TempNameStr += "$non_lazy_ptr"; - MCSymbol *Sym = OutContext.GetOrCreateSymbol(TempNameStr.str()); + MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); const MCSymbol *&StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getHiddenGVStubEntry(Sym); - if (StubSym == 0) { - TempNameStr.clear(); - Mang->getNameWithPrefix(TempNameStr, GV, false); - StubSym = OutContext.GetOrCreateSymbol(TempNameStr.str()); - } + if (StubSym == 0) + StubSym = GetGlobalValueSymbol(GV); } else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { - Mang->getNameWithPrefix(TempNameStr, GV, true); - TempNameStr += "$stub"; - MCSymbol *Sym = OutContext.GetOrCreateSymbol(TempNameStr.str()); + MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub"); const MCSymbol *&StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); - if (StubSym == 0) { - TempNameStr.clear(); - Mang->getNameWithPrefix(TempNameStr, GV, false); - StubSym = OutContext.GetOrCreateSymbol(TempNameStr.str()); - } + if (StubSym == 0) + StubSym = GetGlobalValueSymbol(GV); } // If the name begins with a dollar-sign, enclose it in parens. We do this // to avoid having it look like an integer immediate to the assembler. - if (Name[0] == '$') - O << '(' << Name << ')'; + if (GVSym->getName()[0] != '$') + O << *GVSym; else - O << Name; - + O << '(' << *GVSym << ')'; printOffset(MO.getOffset()); break; } case MachineOperand::MO_ExternalSymbol: { const MCSymbol *SymToPrint; if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { - Mang->getNameWithPrefix(TempNameStr, - StringRef(MO.getSymbolName())+"$stub"); - const MCSymbol *Sym = OutContext.GetOrCreateSymbol(TempNameStr.str()); + SmallString<128> TempNameStr; + TempNameStr += StringRef(MO.getSymbolName()); + TempNameStr += StringRef("$stub"); + + const MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str()); const MCSymbol *&StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); if (StubSym == 0) { @@ -296,19 +281,15 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) { } SymToPrint = StubSym; } else { - Mang->getNameWithPrefix(TempNameStr, MO.getSymbolName()); - SymToPrint = OutContext.GetOrCreateSymbol(TempNameStr.str()); + SymToPrint = GetExternalSymbolSymbol(MO.getSymbolName()); } // If the name begins with a dollar-sign, enclose it in parens. We do this // to avoid having it look like an integer immediate to the assembler. if (SymToPrint->getName()[0] != '$') - SymToPrint->print(O, MAI); - else { - O << '('; - SymToPrint->print(O, MAI); - O << '('; - } + O << *SymToPrint; + else + O << '(' << *SymToPrint << '('; break; } } @@ -357,7 +338,7 @@ void X86AsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) { O << MO.getImm(); return; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_ExternalSymbol: @@ -368,7 +349,7 @@ void X86AsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) { void X86AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, - const char *Modifier) { + const char *Modifier) { const MachineOperand &MO = MI->getOperand(OpNo); switch (MO.getType()) { default: llvm_unreachable("unknown operand type!"); @@ -482,11 +463,10 @@ void X86AsmPrinter::printPICJumpTableSetLabel(unsigned uid, O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; - GetMBBSymbol(MBB->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MBB->getNumber()); if (Subtarget->isPICStyleRIPRel()) - O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << uid << '\n'; + O << '-' << *GetJTISymbol(uid) << '\n'; else { O << '-'; PrintPICBaseSymbol(); @@ -513,11 +493,10 @@ void X86AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, if (Subtarget->isPICStyleRIPRel() || Subtarget->isPICStyleStubPIC()) { O << MAI->getPrivateGlobalPrefix() << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber(); - } else if (Subtarget->isPICStyleGOT()) { - GetMBBSymbol(MBB->getNumber())->print(O, MAI); - O << "@GOTOFF"; - } else - GetMBBSymbol(MBB->getNumber())->print(O, MAI); + } else if (Subtarget->isPICStyleGOT()) + O << *GetMBBSymbol(MBB->getNumber()) << "@GOTOFF"; + else + O << *GetMBBSymbol(MBB->getNumber()); } bool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode) { @@ -664,147 +643,6 @@ void X86AsmPrinter::printMachineInstruction(const MachineInstr *MI) { processDebugLoc(MI, false); } -void X86AsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) { - if (Subtarget->isTargetDarwin() && - TM.getRelocationModel() == Reloc::Static) { - if (GVar->getName() == "llvm.global_ctors") - O << ".reference .constructors_used\n"; - else if (GVar->getName() == "llvm.global_dtors") - O << ".reference .destructors_used\n"; - } - return; - } - - const TargetData *TD = TM.getTargetData(); - - std::string name = Mang->getMangledName(GVar); - Constant *C = GVar->getInitializer(); - const Type *Type = C->getType(); - unsigned Size = TD->getTypeAllocSize(Type); - unsigned Align = TD->getPreferredAlignmentLog(GVar); - - printVisibility(name, GVar->getVisibility()); - - if (Subtarget->isTargetELF()) - O << "\t.type\t" << name << ",@object\n"; - - - SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GVar, TM); - const MCSection *TheSection = - getObjFileLowering().SectionForGlobal(GVar, GVKind, Mang, TM); - OutStreamer.SwitchSection(TheSection); - - // FIXME: get this stuff from section kind flags. - if (C->isNullValue() && !GVar->hasSection() && - // Don't put things that should go in the cstring section into "comm". - !TheSection->getKind().isMergeableCString()) { - if (GVar->hasExternalLinkage()) { - if (const char *Directive = MAI->getZeroFillDirective()) { - O << "\t.globl " << name << '\n'; - O << Directive << "__DATA, __common, " << name << ", " - << Size << ", " << Align << '\n'; - return; - } - } - - if (!GVar->isThreadLocal() && - (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (MAI->getLCOMMDirective() != NULL) { - if (GVar->hasLocalLinkage()) { - O << MAI->getLCOMMDirective() << name << ',' << Size; - if (Subtarget->isTargetDarwin()) - O << ',' << Align; - } else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) { - O << "\t.globl " << name << '\n' - << MAI->getWeakDefDirective() << name << '\n'; - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - EmitGlobalConstant(C); - return; - } else { - O << MAI->getCOMMDirective() << name << ',' << Size; - if (MAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); - } - } else { - if (!Subtarget->isTargetCygMing()) { - if (GVar->hasLocalLinkage()) - O << "\t.local\t" << name << '\n'; - } - O << MAI->getCOMMDirective() << name << ',' << Size; - if (MAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); - } - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - return; - } - } - - switch (GVar->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::LinkerPrivateLinkage: - if (Subtarget->isTargetDarwin()) { - O << "\t.globl " << name << '\n' - << MAI->getWeakDefDirective() << name << '\n'; - } else if (Subtarget->isTargetCygMing()) { - O << "\t.globl\t" << name << "\n" - "\t.linkonce same_size\n"; - } else { - O << "\t.weak\t" << name << '\n'; - } - break; - case GlobalValue::DLLExportLinkage: - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << "\t.globl " << name << '\n'; - // FALL THROUGH - case GlobalValue::PrivateLinkage: - case GlobalValue::InternalLinkage: - break; - default: - llvm_unreachable("Unknown linkage type!"); - } - - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm){ - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - - EmitGlobalConstant(C); - - if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << name << ", " << Size << '\n'; -} - void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { if (Subtarget->isTargetDarwin()) { // All darwin targets use mach-o. @@ -828,10 +666,9 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { OutStreamer.SwitchSection(TheSection); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { - Stubs[i].first->print(O, MAI); - O << ":\n" << "\t.indirect_symbol "; + O << *Stubs[i].first << ":\n"; // Get the MCSymbol without the $stub suffix. - Stubs[i].second->print(O, MAI); + O << "\t.indirect_symbol " << *Stubs[i].second; O << "\n\thlt ; hlt ; hlt ; hlt ; hlt\n"; } O << '\n'; @@ -849,9 +686,7 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { OutStreamer.SwitchSection(TheSection); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { - Stubs[i].first->print(O, MAI); - O << ":\n\t.indirect_symbol "; - Stubs[i].second->print(O, MAI); + O << *Stubs[i].first << ":\n\t.indirect_symbol " << *Stubs[i].second; O << "\n\t.long\t0\n"; } Stubs.clear(); @@ -863,10 +698,8 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { EmitAlignment(2); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { - Stubs[i].first->print(O, MAI); - O << ":\n" << MAI->getData32bitsDirective(); - Stubs[i].second->print(O, MAI); - O << '\n'; + O << *Stubs[i].first << ":\n" << MAI->getData32bitsDirective(); + O << *Stubs[i].second << '\n'; } Stubs.clear(); } @@ -876,7 +709,7 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { // implementation of multiple entry points). If this doesn't occur, the // linker can safely perform dead code stripping. Since LLVM never // generates code that does this, it is always safe to set. - OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols); + OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); } if (Subtarget->isTargetCOFF()) { @@ -894,25 +727,22 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { if (Subtarget->isTargetCygMing()) { // Necessary for dllexport support - std::vector<std::string> DLLExportedFns, DLLExportedGlobals; + std::vector<const MCSymbol*> DLLExportedFns, DLLExportedGlobals; TargetLoweringObjectFileCOFF &TLOFCOFF = static_cast<TargetLoweringObjectFileCOFF&>(getObjFileLowering()); for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) if (I->hasDLLExportLinkage()) { - std::string Name = Mang->getMangledName(I); - COFFMMI.DecorateCygMingName(Name, I, *TM.getTargetData()); - DLLExportedFns.push_back(Name); + MCSymbol *Sym = GetGlobalValueSymbol(I); + COFFMMI.DecorateCygMingName(Sym, OutContext, I, *TM.getTargetData()); + DLLExportedFns.push_back(Sym); } for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) - if (I->hasDLLExportLinkage()) { - std::string Name = Mang->getMangledName(I); - COFFMMI.DecorateCygMingName(Name, I, *TM.getTargetData()); - DLLExportedGlobals.push_back(Mang->getMangledName(I)); - } + if (I->hasDLLExportLinkage()) + DLLExportedGlobals.push_back(GetGlobalValueSymbol(I)); // Output linker support code for dllexported globals on windows. if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) { @@ -920,10 +750,10 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { true, SectionKind::getMetadata())); for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i) - O << "\t.ascii \" -export:" << DLLExportedGlobals[i] << ",data\"\n"; + O << "\t.ascii \" -export:" << *DLLExportedGlobals[i] << ",data\"\n"; for (unsigned i = 0, e = DLLExportedFns.size(); i != e; ++i) - O << "\t.ascii \" -export:" << DLLExportedFns[i] << "\"\n"; + O << "\t.ascii \" -export:" << *DLLExportedFns[i] << "\"\n"; } } } diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.h b/lib/Target/X86/AsmPrinter/X86AsmPrinter.h index 0351829..6a9262d 100644 --- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.h +++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.h @@ -135,7 +135,6 @@ class VISIBILITY_HIDDEN X86AsmPrinter : public AsmPrinter { unsigned uid) const; void printPICLabel(const MachineInstr *MI, unsigned Op); - void PrintGlobalVariable(const GlobalVariable* GVar); void PrintPICBaseSymbol() const; diff --git a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp index fde5902..4efb529 100644 --- a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp @@ -52,7 +52,7 @@ void X86IntelInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) { O << Op.getImm(); else { assert(Op.isExpr() && "unknown pcrel immediate operand"); - Op.getExpr()->print(O, &MAI); + O << *Op.getExpr(); } } @@ -72,7 +72,7 @@ void X86IntelInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, O << Op.getImm(); } else { assert(Op.isExpr() && "unknown operand kind in printOperand"); - Op.getExpr()->print(O, &MAI); + O << *Op.getExpr(); } } @@ -102,7 +102,7 @@ void X86IntelInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { if (!DispSpec.isImm()) { if (NeedPlus) O << " + "; assert(DispSpec.isExpr() && "non-immediate displacement for LEA?"); - DispSpec.getExpr()->print(O, &MAI); + O << *DispSpec.getExpr(); } else { int64_t DispVal = DispSpec.getImm(); if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) { diff --git a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp index 9ee118c..b970d46 100644 --- a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp +++ b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp @@ -16,16 +16,15 @@ #include "X86AsmPrinter.h" #include "X86MCAsmInfo.h" #include "X86COFFMachineModuleInfo.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" -#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/Mangler.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/ADT/SmallString.h" -#include "llvm/Analysis/DebugInfo.h" using namespace llvm; @@ -83,33 +82,24 @@ GetGlobalAddressSymbol(const MachineOperand &MO) const { MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); const MCSymbol *&StubSym = getMachOMMI().getGVStubEntry(Sym); - if (StubSym == 0) { - Name.clear(); - Mang->getNameWithPrefix(Name, GV, false); - StubSym = Ctx.GetOrCreateSymbol(Name.str()); - } + if (StubSym == 0) + StubSym = AsmPrinter.GetGlobalValueSymbol(GV); return Sym; } case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: { Name += "$non_lazy_ptr"; MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); const MCSymbol *&StubSym = getMachOMMI().getHiddenGVStubEntry(Sym); - if (StubSym == 0) { - Name.clear(); - Mang->getNameWithPrefix(Name, GV, false); - StubSym = Ctx.GetOrCreateSymbol(Name.str()); - } + if (StubSym == 0) + StubSym = AsmPrinter.GetGlobalValueSymbol(GV); return Sym; } case X86II::MO_DARWIN_STUB: { Name += "$stub"; MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); const MCSymbol *&StubSym = getMachOMMI().getFnStubEntry(Sym); - if (StubSym == 0) { - Name.clear(); - Mang->getNameWithPrefix(Name, GV, false); - StubSym = Ctx.GetOrCreateSymbol(Name.str()); - } + if (StubSym == 0) + StubSym = AsmPrinter.GetGlobalValueSymbol(GV); return Sym; } // FIXME: These probably should be a modifier on the symbol or something?? @@ -173,6 +163,8 @@ GetExternalSymbolSymbol(const MachineOperand &MO) const { MCSymbol *X86MCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const { SmallString<256> Name; + // FIXME: Use AsmPrinter.GetJTISymbol. @TLSGD shouldn't be part of the symbol + // name! raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "JTI" << AsmPrinter.getFunctionNumber() << '_' << MO.getIndex(); @@ -204,6 +196,8 @@ MCSymbol *X86MCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const { MCSymbol *X86MCInstLower:: GetConstantPoolIndexSymbol(const MachineOperand &MO) const { SmallString<256> Name; + // FIXME: USe AsmPrinter.GetCPISymbol. @TLSGD shouldn't be part of the symbol + // name! raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "CPI" << AsmPrinter.getFunctionNumber() << '_' << MO.getIndex(); @@ -422,22 +416,28 @@ void X86AsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { printLabel(MI); return; case TargetInstrInfo::DEBUG_VALUE: { + // FIXME: if this is implemented for another target before it goes + // away completely, the common part should be moved into AsmPrinter. if (!VerboseAsm) return; O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; - // cast away const; DIetc do not take const operands for some reason - DIVariable V((MDNode*)(MI->getOperand(2).getMetadata())); + unsigned NOps = MI->getNumOperands(); + // cast away const; DIetc do not take const operands for some reason. + DIVariable V((MDNode*)(MI->getOperand(NOps-1).getMetadata())); O << V.getName(); O << " <- "; - if (MI->getOperand(0).getType()==MachineOperand::MO_Register) + if (NOps==3) { + // Variable is in register + assert(MI->getOperand(0).getType()==MachineOperand::MO_Register); printOperand(MI, 0); - else { - assert(MI->getOperand(0).getType()==MachineOperand::MO_Immediate); - int64_t imm = MI->getOperand(0).getImm(); - O << '[' << ((imm<0) ? "EBP" : "ESP+") << imm << ']'; + } else { + // Frame address. Currently handles register +- offset only. + assert(MI->getOperand(0).getType()==MachineOperand::MO_Register); + assert(MI->getOperand(3).getType()==MachineOperand::MO_Immediate); + O << '['; printOperand(MI, 0); O << '+'; printOperand(MI, 3); O << ']'; } O << "+"; - printOperand(MI, 1); + printOperand(MI, NOps-2); return; } case TargetInstrInfo::INLINEASM: diff --git a/lib/Target/X86/Disassembler/Makefile b/lib/Target/X86/Disassembler/Makefile index b289647..6c26853 100644 --- a/lib/Target/X86/Disassembler/Makefile +++ b/lib/Target/X86/Disassembler/Makefile @@ -9,6 +9,7 @@ LEVEL = ../../../.. LIBRARYNAME = LLVMX86Disassembler +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' x86 target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index 6098dbf..5e625dc 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMX86CodeGen TARGET = X86 +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = X86GenRegisterInfo.h.inc X86GenRegisterNames.inc \ diff --git a/lib/Target/X86/TargetInfo/Makefile b/lib/Target/X86/TargetInfo/Makefile index 6677d4b..211607f 100644 --- a/lib/Target/X86/TargetInfo/Makefile +++ b/lib/Target/X86/TargetInfo/Makefile @@ -6,8 +6,10 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../../.. LIBRARYNAME = LLVMX86Info +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/X86/X86COFFMachineModuleInfo.cpp b/lib/Target/X86/X86COFFMachineModuleInfo.cpp index 01c4fcf..ea52795 100644 --- a/lib/Target/X86/X86COFFMachineModuleInfo.cpp +++ b/lib/Target/X86/X86COFFMachineModuleInfo.cpp @@ -15,6 +15,8 @@ #include "X86MachineFunctionInfo.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" @@ -23,7 +25,6 @@ using namespace llvm; X86COFFMachineModuleInfo::X86COFFMachineModuleInfo(const MachineModuleInfo &) { } X86COFFMachineModuleInfo::~X86COFFMachineModuleInfo() { - } void X86COFFMachineModuleInfo::AddFunctionInfo(const Function *F, @@ -114,10 +115,12 @@ void X86COFFMachineModuleInfo::DecorateCygMingName(SmallVectorImpl<char> &Name, /// DecorateCygMingName - Query FunctionInfoMap and use this information for /// various name decorations for Cygwin and MingW. -void X86COFFMachineModuleInfo::DecorateCygMingName(std::string &Name, +void X86COFFMachineModuleInfo::DecorateCygMingName(MCSymbol *&Name, + MCContext &Ctx, const GlobalValue *GV, const TargetData &TD) { - SmallString<128> NameStr(Name.begin(), Name.end()); + SmallString<128> NameStr(Name->getName().begin(), Name->getName().end()); DecorateCygMingName(NameStr, GV, TD); - Name.assign(NameStr.begin(), NameStr.end()); + + Name = Ctx.GetOrCreateSymbol(NameStr.str()); } diff --git a/lib/Target/X86/X86COFFMachineModuleInfo.h b/lib/Target/X86/X86COFFMachineModuleInfo.h index 5017af2..0e2009e 100644 --- a/lib/Target/X86/X86COFFMachineModuleInfo.h +++ b/lib/Target/X86/X86COFFMachineModuleInfo.h @@ -46,8 +46,8 @@ public: ~X86COFFMachineModuleInfo(); - void DecorateCygMingName(std::string &Name, const GlobalValue *GV, - const TargetData &TD); + void DecorateCygMingName(MCSymbol* &Name, MCContext &Ctx, + const GlobalValue *GV, const TargetData &TD); void DecorateCygMingName(SmallVectorImpl<char> &Name, const GlobalValue *GV, const TargetData &TD); diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 7e02d59..d5ad61b 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -1153,6 +1153,10 @@ bool X86FastISel::X86VisitIntrinsicCall(IntrinsicInst &I) { // FIXME: Handle more intrinsics. switch (I.getIntrinsicID()) { default: return false; + case Intrinsic::trap: { + BuildMI(MBB, DL, TII.get(X86::TRAP)); + return true; + } case Intrinsic::sadd_with_overflow: case Intrinsic::uadd_with_overflow: { // Replace "add with overflow" intrinsics with an "add" instruction followed diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index e2a53d1..91e0483 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -384,8 +384,11 @@ static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load, /// static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address, SDValue &Load) { - if (N.getOpcode() == ISD::BIT_CONVERT) + if (N.getOpcode() == ISD::BIT_CONVERT) { + if (!N.hasOneUse()) + return false; N = N.getOperand(0); + } LoadSDNode *LD = dyn_cast<LoadSDNode>(N); if (!LD || LD->isVolatile()) @@ -595,6 +598,7 @@ void X86DAGToDAGISel::PreprocessForRMW() { if (RModW) { MoveBelowTokenFactor(CurDAG, Load, SDValue(I, 0), Chain); ++NumLoadMoved; + checkForCycles(I); } } } @@ -940,7 +944,7 @@ bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, // Okay, we know that we have a scale by now. However, if the scaled // value is an add of something and a constant, we can fold the // constant into the disp field here. - if (ShVal.getNode()->getOpcode() == ISD::ADD && ShVal.hasOneUse() && + if (ShVal.getNode()->getOpcode() == ISD::ADD && isa<ConstantSDNode>(ShVal.getNode()->getOperand(1))) { AM.IndexReg = ShVal.getNode()->getOperand(0); ConstantSDNode *AddVal = diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 228ec9f..11e07df 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -3390,17 +3390,10 @@ X86TargetLowering::LowerAsSplatVectorLoad(SDValue SrcOp, EVT VT, DebugLoc dl, MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); if (DAG.InferPtrAlignment(Ptr) < 16) { if (MFI->isFixedObjectIndex(FI)) { - // Can't change the alignment. Reference stack + offset explicitly - // if stack pointer is at least 16-byte aligned. - unsigned StackAlign = Subtarget->getStackAlignment(); - if (StackAlign < 16) - return SDValue(); - Offset = MFI->getObjectOffset(FI) + Offset; - SDValue StackPtr = DAG.getCopyFromReg(Chain, dl, X86StackPtr, - getPointerTy()); - Ptr = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, - DAG.getConstant(Offset & ~15, getPointerTy())); - Offset %= 16; + // Can't change the alignment. FIXME: It's possible to compute + // the exact stack offset and reference FI + adjust offset instead. + // If someone *really* cares about this. That's the way to implement it. + return SDValue(); } else { MFI->setObjectAlignment(FI, 16); } @@ -7579,7 +7572,7 @@ bool X86TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { bool X86TargetLowering::isZExtFree(const Type *Ty1, const Type *Ty2) const { // x86-64 implicitly zero-extends 32-bit results in 64-bit registers. - return Ty1->isInteger(64) && Ty2->isInteger(64) && Subtarget->is64Bit(); + return Ty1->isInteger(32) && Ty2->isInteger(64) && Subtarget->is64Bit(); } bool X86TargetLowering::isZExtFree(EVT VT1, EVT VT2) const { diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 08e1dd1..9037ba6 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -207,7 +207,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { // EH Pseudo Instructions // let isTerminator = 1, isReturn = 1, isBarrier = 1, - hasCtrlDep = 1 in { + hasCtrlDep = 1, isCodeGenOnly = 1 in { def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr), "ret\t#eh_return, addr: $addr", [(X86ehret GR64:$addr)]>; diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 7b39fb3..3ae352c 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -402,7 +402,7 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) { X86::MOVSX64rr32, X86::MOVSX64rm32, 0 }, { X86::MOVSX64rr8, X86::MOVSX64rm8, 0 }, { X86::MOVUPDrr, X86::MOVUPDrm, 16 }, - { X86::MOVUPSrr, X86::MOVUPSrm, 16 }, + { X86::MOVUPSrr, X86::MOVUPSrm, 0 }, { X86::MOVZDI2PDIrr, X86::MOVZDI2PDIrm, 0 }, { X86::MOVZQI2PQIrr, X86::MOVZQI2PQIrm, 0 }, { X86::MOVZPQILo2PQIrr, X86::MOVZPQILo2PQIrm, 16 }, @@ -2077,8 +2077,7 @@ void X86InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, unsigned SrcReg, bool isKill, int FrameIdx, const TargetRegisterClass *RC) const { const MachineFunction &MF = *MBB.getParent(); - bool isAligned = (RI.getStackAlignment() >= 16) || - RI.needsStackRealignment(MF); + bool isAligned = (RI.getStackAlignment() >= 16) || RI.canRealignStack(MF); unsigned Opc = getStoreRegOpcode(SrcReg, RC, isAligned, TM); DebugLoc DL = DebugLoc::getUnknownLoc(); if (MI != MBB.end()) DL = MI->getDebugLoc(); @@ -2172,8 +2171,7 @@ void X86InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, unsigned DestReg, int FrameIdx, const TargetRegisterClass *RC) const{ const MachineFunction &MF = *MBB.getParent(); - bool isAligned = (RI.getStackAlignment() >= 16) || - RI.needsStackRealignment(MF); + bool isAligned = (RI.getStackAlignment() >= 16) || RI.canRealignStack(MF); unsigned Opc = getLoadRegOpcode(DestReg, RC, isAligned, TM); DebugLoc DL = DebugLoc::getUnknownLoc(); if (MI != MBB.end()) DL = MI->getDebugLoc(); @@ -2202,8 +2200,7 @@ bool X86InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, if (CSI.empty()) return false; - DebugLoc DL = DebugLoc::getUnknownLoc(); - if (MI != MBB.end()) DL = MI->getDebugLoc(); + DebugLoc DL = MBB.findDebugLoc(MI); bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit(); bool isWin64 = TM.getSubtarget<X86Subtarget>().isTargetWin64(); @@ -2241,8 +2238,7 @@ bool X86InstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, if (CSI.empty()) return false; - DebugLoc DL = DebugLoc::getUnknownLoc(); - if (MI != MBB.end()) DL = MI->getDebugLoc(); + DebugLoc DL = MBB.findDebugLoc(MI); MachineFunction &MF = *MBB.getParent(); unsigned FPReg = RI.getFrameRegister(MF); @@ -2872,6 +2868,138 @@ unsigned X86InstrInfo::getOpcodeAfterMemoryUnfold(unsigned Opc, return I->second.first; } +bool +X86InstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, + int64_t &Offset1, int64_t &Offset2) const { + if (!Load1->isMachineOpcode() || !Load2->isMachineOpcode()) + return false; + unsigned Opc1 = Load1->getMachineOpcode(); + unsigned Opc2 = Load2->getMachineOpcode(); + switch (Opc1) { + default: return false; + case X86::MOV8rm: + case X86::MOV16rm: + case X86::MOV32rm: + case X86::MOV64rm: + case X86::LD_Fp32m: + case X86::LD_Fp64m: + case X86::LD_Fp80m: + case X86::MOVSSrm: + case X86::MOVSDrm: + case X86::MMX_MOVD64rm: + case X86::MMX_MOVQ64rm: + case X86::FsMOVAPSrm: + case X86::FsMOVAPDrm: + case X86::MOVAPSrm: + case X86::MOVUPSrm: + case X86::MOVUPSrm_Int: + case X86::MOVAPDrm: + case X86::MOVDQArm: + case X86::MOVDQUrm: + case X86::MOVDQUrm_Int: + break; + } + switch (Opc2) { + default: return false; + case X86::MOV8rm: + case X86::MOV16rm: + case X86::MOV32rm: + case X86::MOV64rm: + case X86::LD_Fp32m: + case X86::LD_Fp64m: + case X86::LD_Fp80m: + case X86::MOVSSrm: + case X86::MOVSDrm: + case X86::MMX_MOVD64rm: + case X86::MMX_MOVQ64rm: + case X86::FsMOVAPSrm: + case X86::FsMOVAPDrm: + case X86::MOVAPSrm: + case X86::MOVUPSrm: + case X86::MOVUPSrm_Int: + case X86::MOVAPDrm: + case X86::MOVDQArm: + case X86::MOVDQUrm: + case X86::MOVDQUrm_Int: + break; + } + + // Check if chain operands and base addresses match. + if (Load1->getOperand(0) != Load2->getOperand(0) || + Load1->getOperand(5) != Load2->getOperand(5)) + return false; + // Segment operands should match as well. + if (Load1->getOperand(4) != Load2->getOperand(4)) + return false; + // Scale should be 1, Index should be Reg0. + if (Load1->getOperand(1) == Load2->getOperand(1) && + Load1->getOperand(2) == Load2->getOperand(2)) { + if (cast<ConstantSDNode>(Load1->getOperand(1))->getZExtValue() != 1) + return false; + SDValue Op2 = Load1->getOperand(2); + if (!isa<RegisterSDNode>(Op2) || + cast<RegisterSDNode>(Op2)->getReg() != 0) + return 0; + + // Now let's examine the displacements. + if (isa<ConstantSDNode>(Load1->getOperand(3)) && + isa<ConstantSDNode>(Load2->getOperand(3))) { + Offset1 = cast<ConstantSDNode>(Load1->getOperand(3))->getSExtValue(); + Offset2 = cast<ConstantSDNode>(Load2->getOperand(3))->getSExtValue(); + return true; + } + } + return false; +} + +bool X86InstrInfo::shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, + int64_t Offset1, int64_t Offset2, + unsigned NumLoads) const { + assert(Offset2 > Offset1); + if ((Offset2 - Offset1) / 8 > 64) + return false; + + unsigned Opc1 = Load1->getMachineOpcode(); + unsigned Opc2 = Load2->getMachineOpcode(); + if (Opc1 != Opc2) + return false; // FIXME: overly conservative? + + switch (Opc1) { + default: break; + case X86::LD_Fp32m: + case X86::LD_Fp64m: + case X86::LD_Fp80m: + case X86::MMX_MOVD64rm: + case X86::MMX_MOVQ64rm: + return false; + } + + EVT VT = Load1->getValueType(0); + switch (VT.getSimpleVT().SimpleTy) { + default: { + // XMM registers. In 64-bit mode we can be a bit more aggressive since we + // have 16 of them to play with. + if (TM.getSubtargetImpl()->is64Bit()) { + if (NumLoads >= 3) + return false; + } else if (NumLoads) + return false; + break; + } + case MVT::i8: + case MVT::i16: + case MVT::i32: + case MVT::i64: + case MVT::f32: + case MVT::f64: + if (NumLoads) + return false; + } + + return true; +} + + bool X86InstrInfo:: ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { assert(Cond.size() == 1 && "Invalid X86 branch condition!"); diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index 0ab85f4..4f35d0d 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -610,6 +610,26 @@ public: bool UnfoldLoad, bool UnfoldStore, unsigned *LoadRegIndex = 0) const; + /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler + /// to determine if two loads are loading from the same base address. It + /// should only return true if the base pointers are the same and the + /// only differences between the two addresses are the offset. It also returns + /// the offsets by reference. + virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, + int64_t &Offset1, int64_t &Offset2) const; + + /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to + /// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should + /// be scheduled togther. On some targets if two loads are loading from + /// addresses in the same cache line, it's better if they are scheduled + /// together. This function takes two integers that represent the load offsets + /// from the common base address. It returns true if it decides it's desirable + /// to schedule the two loads together. "NumLoads" is the number of loads that + /// have already been scheduled after Load1. + virtual bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, + int64_t Offset1, int64_t Offset2, + unsigned NumLoads) const; + virtual bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const; diff --git a/lib/Target/X86/X86MCAsmInfo.cpp b/lib/Target/X86/X86MCAsmInfo.cpp index 9d7e66d..1738d49 100644 --- a/lib/Target/X86/X86MCAsmInfo.cpp +++ b/lib/Target/X86/X86MCAsmInfo.cpp @@ -14,6 +14,7 @@ #include "X86MCAsmInfo.h" #include "X86TargetMachine.h" #include "llvm/ADT/Triple.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/Support/CommandLine.h" using namespace llvm; @@ -87,10 +88,11 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &Triple) { // Exceptions handling ExceptionsType = ExceptionHandling::Dwarf; AbsoluteEHSectionOffsets = false; +} - // On Linux we must declare when we can use a non-executable stack. - if (Triple.getOS() == Triple::Linux) - NonexecutableStackDirective = "\t.section\t.note.GNU-stack,\"\",@progbits"; +MCSection *X86ELFMCAsmInfo::getNonexecutableStackSection(MCContext &Ctx) const { + return MCSectionELF::Create(".note.GNU-stack", MCSectionELF::SHT_PROGBITS, + 0, SectionKind::getMetadata(), false, Ctx); } X86MCAsmInfoCOFF::X86MCAsmInfoCOFF(const Triple &Triple) { @@ -109,7 +111,6 @@ X86WinMCAsmInfo::X86WinMCAsmInfo(const Triple &Triple) { PrivateGlobalPrefix = "$"; AlignDirective = "\tALIGN\t"; ZeroDirective = "\tdb\t"; - ZeroDirectiveSuffix = " dup(0)"; AsciiDirective = "\tdb\t"; AscizDirective = 0; Data8bitsDirective = "\tdb\t"; diff --git a/lib/Target/X86/X86MCAsmInfo.h b/lib/Target/X86/X86MCAsmInfo.h index 18e2bdb..ca227b7 100644 --- a/lib/Target/X86/X86MCAsmInfo.h +++ b/lib/Target/X86/X86MCAsmInfo.h @@ -27,6 +27,7 @@ namespace llvm { struct X86ELFMCAsmInfo : public MCAsmInfo { explicit X86ELFMCAsmInfo(const Triple &Triple); + virtual MCSection *getNonexecutableStackSection(MCContext &Ctx) const; }; struct X86MCAsmInfoCOFF : public MCAsmInfoCOFF { diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 9bd96af..f959a2d 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -438,6 +438,12 @@ bool X86RegisterInfo::hasFP(const MachineFunction &MF) const { (MMI && MMI->callsUnwindInit())); } +bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return (RealignStack && + !MFI->hasVarSizedObjects()); +} + bool X86RegisterInfo::needsStackRealignment(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); bool requiresRealignment = @@ -591,15 +597,6 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int FrameIndex = MI.getOperand(i).getIndex(); unsigned BasePtr; - // DEBUG_VALUE has a special representation, and is only robust enough to - // represent SP(or BP) +- offset addressing modes. We rewrite the - // FrameIndex to be a constant; implicitly positive constants are relative - // to ESP and negative ones to EBP. - if (MI.getOpcode()==TargetInstrInfo::DEBUG_VALUE) { - MI.getOperand(i).ChangeToImmediate(getFrameIndexOffset(MF, FrameIndex)); - return 0; - } - if (needsStackRealignment(MF)) BasePtr = (FrameIndex < 0 ? FramePtr : StackPtr); else @@ -685,8 +682,7 @@ void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, (Is64Bit ? X86::ADD64ri8 : X86::ADD32ri8) : (Is64Bit ? X86::ADD64ri32 : X86::ADD32ri)); uint64_t Chunk = (1LL << 31) - 1; - DebugLoc DL = (MBBI != MBB.end() ? MBBI->getDebugLoc() : - DebugLoc::getUnknownLoc()); + DebugLoc DL = MBB.findDebugLoc(MBBI); while (Offset) { uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset; @@ -1035,8 +1031,7 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { } } - if (MBBI != MBB.end()) - DL = MBBI->getDebugLoc(); + DL = MBB.findDebugLoc(MBBI); // Adjust stack pointer: ESP -= numbytes. if (NumBytes >= 4096 && Subtarget->isTargetCygMing()) { diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index f281a3c..dec3fba 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -128,6 +128,8 @@ public: bool hasFP(const MachineFunction &MF) const; + bool canRealignStack(const MachineFunction &MF) const; + bool needsStackRealignment(const MachineFunction &MF) const; bool hasReservedCallFrame(MachineFunction &MF) const; diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 962f0f7..731c3ab 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -157,9 +157,6 @@ bool X86TargetMachine::addInstSelector(PassManagerBase &PM, bool X86TargetMachine::addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { - // Calculate and set max stack object alignment early, so we can decide - // whether we will need stack realignment (and thus FP). - PM.add(createMaxStackAlignmentCalculatorPass()); return false; // -print-machineinstr shouldn't print after this. } @@ -249,3 +246,32 @@ void X86TargetMachine::setCodeModelForJIT() { else setCodeModel(CodeModel::Small); } + +/// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are 4-byte, +/// 8-byte, and target default. The CIE is hard-coded to indicate that the LSDA +/// pointer in the FDE section is an "sdata4", and should be encoded as a 4-byte +/// pointer by default. However, some systems may require a different size due +/// to bugs or other conditions. We will default to a 4-byte encoding unless the +/// system tells us otherwise. +/// +/// The issue is when the CIE says their is an LSDA. That mandates that every +/// FDE have an LSDA slot. But if the function does not need an LSDA. There +/// needs to be some way to signify there is none. The LSDA is encoded as +/// pc-rel. But you don't look for some magic value after adding the pc. You +/// have to look for a zero before adding the pc. The problem is that the size +/// of the zero to look for depends on the encoding. The unwinder bug in SL is +/// that it always checks for a pointer-size zero. So on x86_64 it looks for 8 +/// bytes of zero. If you have an LSDA, it works fine since the 8-bytes are +/// non-zero so it goes ahead and then reads the value based on the encoding. +/// But if you use sdata4 and there is no LSDA, then the test for zero gives a +/// false negative and the unwinder thinks there is an LSDA. +/// +/// FIXME: This call-back isn't good! We should be using the correct encoding +/// regardless of the system. However, there are some systems which have bugs +/// that prevent this from occuring. +DwarfLSDAEncoding::Encoding X86TargetMachine::getLSDAEncoding() const { + if (Subtarget.isTargetDarwin() && Subtarget.getDarwinVers() != 10) + return DwarfLSDAEncoding::Default; + + return DwarfLSDAEncoding::EightByte; +} diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h index 6183e91..d05bebd 100644 --- a/lib/Target/X86/X86TargetMachine.h +++ b/lib/Target/X86/X86TargetMachine.h @@ -62,6 +62,18 @@ public: return Subtarget.isTargetELF() ? &ELFWriterInfo : 0; } + /// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are + /// 4-byte, 8-byte, and target default. The CIE is hard-coded to indicate that + /// the LSDA pointer in the FDE section is an "sdata4", and should be encoded + /// as a 4-byte pointer by default. However, some systems may require a + /// different size due to bugs or other conditions. We will default to a + /// 4-byte encoding unless the system tells us otherwise. + /// + /// FIXME: This call-back isn't good! We should be using the correct encoding + /// regardless of the system. However, there are some systems which have bugs + /// that prevent this from occuring. + virtual DwarfLSDAEncoding::Encoding getLSDAEncoding() const; + // Set up the pass pipeline. virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); virtual bool addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel); diff --git a/lib/Target/X86/X86TargetObjectFile.cpp b/lib/Target/X86/X86TargetObjectFile.cpp index d39b3c4..41ad153 100644 --- a/lib/Target/X86/X86TargetObjectFile.cpp +++ b/lib/Target/X86/X86TargetObjectFile.cpp @@ -8,11 +8,11 @@ //===----------------------------------------------------------------------===// #include "X86TargetObjectFile.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/Mangler.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" -#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/Target/Mangler.h" +#include "llvm/ADT/SmallString.h" using namespace llvm; const MCExpr *X8632_MachoTargetObjectFile:: @@ -27,6 +27,7 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, MachineModuleInfoMachO &MachOMMI = MMI->getObjFileInfo<MachineModuleInfoMachO>(); + // FIXME: Use GetSymbolWithGlobalValueBase. SmallString<128> Name; Mang->getNameWithPrefix(Name, GV, true); Name += "$non_lazy_ptr"; diff --git a/lib/Target/XCore/AsmPrinter/Makefile b/lib/Target/XCore/AsmPrinter/Makefile index 82dc1df..f0e883e 100644 --- a/lib/Target/XCore/AsmPrinter/Makefile +++ b/lib/Target/XCore/AsmPrinter/Makefile @@ -9,6 +9,7 @@ LEVEL = ../../../.. LIBRARYNAME = LLVMXCoreAsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' XCore target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp b/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp index 2a561c6..40d7160 100644 --- a/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp @@ -37,7 +37,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" #include <algorithm> #include <cctype> @@ -69,11 +68,10 @@ namespace { bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode); - void emitGlobalDirective(const std::string &name); - void emitExternDirective(const std::string &name); + void emitGlobalDirective(const MCSymbol *Sym); - void emitArrayBound(const std::string &name, const GlobalVariable *GV); - virtual void PrintGlobalVariable(const GlobalVariable *GV); + void emitArrayBound(const MCSymbol *Sym, const GlobalVariable *GV); + virtual void EmitGlobalVariable(const GlobalVariable *GV); void emitFunctionStart(MachineFunction &MF); void emitFunctionEnd(MachineFunction &MF); @@ -95,55 +93,44 @@ namespace { #include "XCoreGenAsmWriter.inc" -void XCoreAsmPrinter:: -emitGlobalDirective(const std::string &name) -{ - O << MAI->getGlobalDirective() << name; - O << "\n"; -} - -void XCoreAsmPrinter:: -emitExternDirective(const std::string &name) -{ - O << "\t.extern\t" << name; - O << '\n'; +void XCoreAsmPrinter::emitGlobalDirective(const MCSymbol *Sym) { + O << MAI->getGlobalDirective() << *Sym << "\n"; } -void XCoreAsmPrinter:: -emitArrayBound(const std::string &name, const GlobalVariable *GV) -{ +void XCoreAsmPrinter::emitArrayBound(const MCSymbol *Sym, + const GlobalVariable *GV) { assert(((GV->hasExternalLinkage() || GV->hasWeakLinkage()) || GV->hasLinkOnceLinkage()) && "Unexpected linkage"); if (const ArrayType *ATy = dyn_cast<ArrayType>( - cast<PointerType>(GV->getType())->getElementType())) - { - O << MAI->getGlobalDirective() << name << ".globound" << "\n"; - O << MAI->getSetDirective() << name << ".globound" << "," - << ATy->getNumElements() << "\n"; + cast<PointerType>(GV->getType())->getElementType())) { + O << MAI->getGlobalDirective() << *Sym; + O << ".globound" << "\n"; + O << MAI->getSetDirective() << *Sym; + O << ".globound" << "," << ATy->getNumElements() << "\n"; if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { // TODO Use COMDAT groups for LinkOnceLinkage - O << MAI->getWeakDefDirective() << name << ".globound" << "\n"; + O << MAI->getWeakDefDirective() << *Sym << ".globound" << "\n"; } } } -void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) { +void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // Check to see if this is a special global used by LLVM, if so, emit it. if (!GV->hasInitializer() || EmitSpecialLLVMGlobal(GV)) return; const TargetData *TD = TM.getTargetData(); - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM)); + - std::string name = Mang->getMangledName(GV); + MCSymbol *GVSym = GetGlobalValueSymbol(GV); Constant *C = GV->getInitializer(); unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); // Mark the start of the global - O << "\t.cc_top " << name << ".data," << name << "\n"; + O << "\t.cc_top " << *GVSym << ".data," << *GVSym << "\n"; switch (GV->getLinkage()) { case GlobalValue::AppendingLinkage: @@ -153,12 +140,11 @@ void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) { case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakODRLinkage: case GlobalValue::ExternalLinkage: - emitArrayBound(name, GV); - emitGlobalDirective(name); + emitArrayBound(GVSym, GV); + emitGlobalDirective(GVSym); // TODO Use COMDAT groups for LinkOnceLinkage - if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { - O << MAI->getWeakDefDirective() << name << "\n"; - } + if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) + O << MAI->getWeakDefDirective() << *GVSym << "\n"; // FALL THROUGH case GlobalValue::InternalLinkage: case GlobalValue::PrivateLinkage: @@ -181,25 +167,23 @@ void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) { Size *= MaxThreads; } if (MAI->hasDotTypeDotSizeDirective()) { - O << "\t.type " << name << ",@object\n"; - O << "\t.size " << name << "," << Size << "\n"; + O << "\t.type " << *GVSym << ",@object\n"; + O << "\t.size " << *GVSym << "," << Size << "\n"; } - O << name << ":\n"; + O << *GVSym << ":\n"; EmitGlobalConstant(C); if (GV->isThreadLocal()) { - for (unsigned i = 1; i < MaxThreads; ++i) { + for (unsigned i = 1; i < MaxThreads; ++i) EmitGlobalConstant(C); - } - } - if (Size < 4) { - // The ABI requires that unsigned scalar types smaller than 32 bits - // are are padded to 32 bits. - EmitZeros(4 - Size); } + // The ABI requires that unsigned scalar types smaller than 32 bits + // are padded to 32 bits. + if (Size < 4) + OutStreamer.EmitZeros(4 - Size, 0); // Mark the end of the global - O << "\t.cc_bottom " << name << ".data\n"; + O << "\t.cc_bottom " << *GVSym << ".data\n"; } /// Emit the directives on the start of functions @@ -210,7 +194,7 @@ void XCoreAsmPrinter::emitFunctionStart(MachineFunction &MF) { OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); // Mark the start of the function - O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n"; + O << "\t.cc_top " << *CurrentFnSym << ".function," << *CurrentFnSym << "\n"; switch (F->getLinkage()) { default: llvm_unreachable("Unknown linkage type!"); @@ -219,31 +203,29 @@ void XCoreAsmPrinter::emitFunctionStart(MachineFunction &MF) { case Function::LinkerPrivateLinkage: break; case Function::ExternalLinkage: - emitGlobalDirective(CurrentFnName); + emitGlobalDirective(CurrentFnSym); break; case Function::LinkOnceAnyLinkage: case Function::LinkOnceODRLinkage: case Function::WeakAnyLinkage: case Function::WeakODRLinkage: // TODO Use COMDAT groups for LinkOnceLinkage - O << MAI->getGlobalDirective() << CurrentFnName << "\n"; - O << MAI->getWeakDefDirective() << CurrentFnName << "\n"; + O << MAI->getGlobalDirective() << *CurrentFnSym << "\n"; + O << MAI->getWeakDefDirective() << *CurrentFnSym << "\n"; break; } // (1 << 1) byte aligned EmitAlignment(MF.getAlignment(), F, 1); - if (MAI->hasDotTypeDotSizeDirective()) { - O << "\t.type " << CurrentFnName << ",@function\n"; - } - O << CurrentFnName << ":\n"; + if (MAI->hasDotTypeDotSizeDirective()) + O << "\t.type " << *CurrentFnSym << ",@function\n"; + + O << *CurrentFnSym << ":\n"; } /// Emit the directives on the end of functions -void XCoreAsmPrinter:: -emitFunctionEnd(MachineFunction &MF) -{ +void XCoreAsmPrinter::emitFunctionEnd(MachineFunction &MF) { // Mark the end of the function - O << "\t.cc_bottom " << CurrentFnName << ".function\n"; + O << "\t.cc_bottom " << *CurrentFnSym << ".function\n"; } /// runOnMachineFunction - This uses the printMachineInstruction() @@ -318,10 +300,10 @@ void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { O << MO.getImm(); break; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); break; case MachineOperand::MO_GlobalAddress: - O << Mang->getMangledName(MO.getGlobal()); + O << *GetGlobalValueSymbol(MO.getGlobal()); break; case MachineOperand::MO_ExternalSymbol: O << MO.getSymbolName(); @@ -333,8 +315,9 @@ void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { case MachineOperand::MO_JumpTableIndex: O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << MO.getIndex(); + break; case MachineOperand::MO_BlockAddress: - GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI); + O << *GetBlockAddressSymbol(MO.getBlockAddress()); break; default: llvm_unreachable("not implemented"); diff --git a/lib/Target/XCore/Makefile b/lib/Target/XCore/Makefile index bd3b52a..3bb127f 100644 --- a/lib/Target/XCore/Makefile +++ b/lib/Target/XCore/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMXCoreCodeGen TARGET = XCore +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = XCoreGenRegisterInfo.h.inc XCoreGenRegisterNames.inc \ diff --git a/lib/Target/XCore/TargetInfo/Makefile b/lib/Target/XCore/TargetInfo/Makefile index 07473d2..83bba13 100644 --- a/lib/Target/XCore/TargetInfo/Makefile +++ b/lib/Target/XCore/TargetInfo/Makefile @@ -6,8 +6,10 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../../.. LIBRARYNAME = LLVMXCoreInfo +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Transforms/Hello/Makefile b/lib/Transforms/Hello/Makefile index c5e75d4..46f8098 100644 --- a/lib/Transforms/Hello/Makefile +++ b/lib/Transforms/Hello/Makefile @@ -11,6 +11,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMHello LOADABLE_MODULE = 1 USEDLIBS = +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index 5725db1..0990278 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -171,7 +171,16 @@ static bool InlineCallIfPossible(CallSite CS, CallGraph &CG, return true; } - + +unsigned Inliner::getInlineThreshold(Function* Caller) const { + if (Caller && !Caller->isDeclaration() && + Caller->hasFnAttr(Attribute::OptimizeForSize) && + InlineLimit.getNumOccurrences() == 0) + return 50; + else + return InlineThreshold; +} + /// shouldInline - Return true if the inliner should attempt to inline /// at the given CallSite. bool Inliner::shouldInline(CallSite CS) { @@ -190,14 +199,8 @@ bool Inliner::shouldInline(CallSite CS) { } int Cost = IC.getValue(); - int CurrentThreshold = InlineThreshold; Function *Caller = CS.getCaller(); - if (Caller && !Caller->isDeclaration() && - Caller->hasFnAttr(Attribute::OptimizeForSize) && - InlineLimit.getNumOccurrences() == 0 && - InlineThreshold != 50) - CurrentThreshold = 50; - + int CurrentThreshold = getInlineThreshold(Caller); float FudgeFactor = getInlineFudgeFactor(CS); if (Cost >= (int)(CurrentThreshold * FudgeFactor)) { DEBUG(dbgs() << " NOT Inlining: cost=" << Cost @@ -233,13 +236,8 @@ bool Inliner::shouldInline(CallSite CS) { outerCallsFound = true; int Cost2 = IC2.getValue(); - int CurrentThreshold2 = InlineThreshold; Function *Caller2 = CS2.getCaller(); - if (Caller2 && !Caller2->isDeclaration() && - Caller2->hasFnAttr(Attribute::OptimizeForSize) && - InlineThreshold != 50) - CurrentThreshold2 = 50; - + int CurrentThreshold2 = getInlineThreshold(Caller2); float FudgeFactor2 = getInlineFudgeFactor(CS2); if (Cost2 >= (int)(CurrentThreshold2 * FudgeFactor2)) diff --git a/lib/Transforms/IPO/Makefile b/lib/Transforms/IPO/Makefile index 5c42374..fd018c4 100644 --- a/lib/Transforms/IPO/Makefile +++ b/lib/Transforms/IPO/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMipo BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Transforms/IPO/StripSymbols.cpp b/lib/Transforms/IPO/StripSymbols.cpp index ae88d9e..0e0d83a 100644 --- a/lib/Transforms/IPO/StripSymbols.cpp +++ b/lib/Transforms/IPO/StripSymbols.cpp @@ -147,7 +147,7 @@ static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) { // Strip the symbol table of its names. static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) { for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) { - if (PreserveDbgInfo && strncmp(TI->first.c_str(), "llvm.dbg", 8) == 0) + if (PreserveDbgInfo && StringRef(TI->first).startswith("llvm.dbg")) ++TI; else ST.remove(TI++); diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index af300fc..fa7bb12 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1751,6 +1751,11 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { return BinaryOperator::CreateOr(NotX, NotY); return BinaryOperator::CreateAnd(NotX, NotY); } + + } else if (Op0I->getOpcode() == Instruction::AShr) { + // ~(~X >>s Y) --> (X >>s Y) + if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0))) + return BinaryOperator::CreateAShr(Op0NotVal, Op0I->getOperand(1)); } } } diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index e018b35..f25dd35 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -955,6 +955,19 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) { ShAmt); } + // If this input is a trunc from our destination, then turn sext(trunc(x)) + // into shifts. + if (TruncInst *TI = dyn_cast<TruncInst>(Src)) + if (TI->hasOneUse() && TI->getOperand(0)->getType() == DestTy) { + uint32_t SrcBitSize = SrcTy->getScalarSizeInBits(); + uint32_t DestBitSize = DestTy->getScalarSizeInBits(); + + // We need to emit a shl + ashr to do the sign extend. + Value *ShAmt = ConstantInt::get(DestTy, DestBitSize-SrcBitSize); + Value *Res = Builder->CreateShl(TI->getOperand(0), ShAmt, "sext"); + return BinaryOperator::CreateAShr(Res, ShAmt); + } + // If the input is a shl/ashr pair of a same constant, then this is a sign // extension from a smaller value. If we could trust arbitrary bitwidth // integers, we could turn this into a truncate to the smaller bit and then diff --git a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 6c0ecc9..ae728dd 100644 --- a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -366,7 +366,7 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) { // alloca dead. // If the RHS is an alloca with a two uses, the other one being a // llvm.dbg.declare, zapify the store and the declare, making the - // alloca dead. We must do this to prevent declare's from affecting + // alloca dead. We must do this to prevent declares from affecting // codegen. if (!SI.isVolatile()) { if (Ptr->hasOneUse()) { @@ -408,8 +408,6 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) { --BBI; // Don't count debug info directives, lest they affect codegen, // and we skip pointer-to-pointer bitcasts, which are NOPs. - // It is necessary for correctness to skip those that feed into a - // llvm.dbg.declare, as these are not present when debugging is off. if (isa<DbgInfoIntrinsic>(BBI) || (isa<BitCastInst>(BBI) && isa<PointerType>(BBI->getType()))) { ScanInsts++; @@ -475,9 +473,8 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) { // If this store is the last instruction in the basic block (possibly - // excepting debug info instructions and the pointer bitcasts that feed - // into them), and if the block ends with an unconditional branch, try - // to move it to the successor block. + // excepting debug info instructions), and if the block ends with an + // unconditional branch, try to move it to the successor block. BBI = &SI; do { ++BBI; diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 6afc0cd..2e26a75 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -407,7 +407,7 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) { return Common; if (ConstantInt *C = dyn_cast<ConstantInt>(Op1)) { - // X udiv C^2 -> X >> C + // X udiv 2^C -> X >> C // Check to see if this is an unsigned division with an exact power of 2, // if so, convert to a right shift. if (C->getValue().isPowerOf2()) // 0 not included in isPowerOf2 diff --git a/lib/Transforms/InstCombine/InstCombineShifts.cpp b/lib/Transforms/InstCombine/InstCombineShifts.cpp index fe91da1..321c91d 100644 --- a/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -404,12 +404,26 @@ Instruction *InstCombiner::visitAShr(BinaryOperator &I) { if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) { // If the input is a SHL by the same constant (ashr (shl X, C), C), then we - // have a sign-extend idiom. If the input value is known to already be sign - // extended enough, delete the extension. + // have a sign-extend idiom. Value *X; - if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) && - ComputeNumSignBits(X) > Op1C->getZExtValue()) - return ReplaceInstUsesWith(I, X); + if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1)))) { + // If the input value is known to already be sign extended enough, delete + // the extension. + if (ComputeNumSignBits(X) > Op1C->getZExtValue()) + return ReplaceInstUsesWith(I, X); + + // If the input is an extension from the shifted amount value, e.g. + // %x = zext i8 %A to i32 + // %y = shl i32 %x, 24 + // %z = ashr %y, 24 + // then turn this into "z = sext i8 A to i32". + if (ZExtInst *ZI = dyn_cast<ZExtInst>(X)) { + uint32_t SrcBits = ZI->getOperand(0)->getType()->getScalarSizeInBits(); + uint32_t DestBits = ZI->getType()->getScalarSizeInBits(); + if (Op1C->getZExtValue() == DestBits-SrcBits) + return new SExtInst(ZI->getOperand(0), ZI->getType()); + } + } } // See if we can turn a signed shr into an unsigned shr. diff --git a/lib/Transforms/InstCombine/Makefile b/lib/Transforms/InstCombine/Makefile index 0c488e78..f9de42a 100644 --- a/lib/Transforms/InstCombine/Makefile +++ b/lib/Transforms/InstCombine/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMInstCombine BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Transforms/Instrumentation/Makefile b/lib/Transforms/Instrumentation/Makefile index 6cbc7a9..1238896 100644 --- a/lib/Transforms/Instrumentation/Makefile +++ b/lib/Transforms/Instrumentation/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMInstrumentation BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp b/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp index 94b0671..5650150 100644 --- a/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp +++ b/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp @@ -130,7 +130,7 @@ bool OptimalEdgeProfiler::runOnModule(Module &M) { // actual MST is returned but the edges _not_ in the MST. ProfileInfo::EdgeWeights ECs = - getAnalysisID<ProfileInfo>(ProfileEstimatorPassID, *F).getEdgeWeights(F); + getAnalysis<ProfileInfo>(*F).getEdgeWeights(F); std::vector<ProfileInfo::EdgeWeight> EdgeVector(ECs.begin(), ECs.end()); MaximumSpanningTree<BasicBlock> MST (EdgeVector); std::stable_sort(MST.begin(),MST.end()); diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 9c1b440..c3139a5 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -617,7 +617,23 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, TLI->getTargetData()->getIntPtrType(AccessTy->getContext()); Value *Result = 0; - // Start with the scale value. + + // Start with the base register. Do this first so that subsequent address + // matching finds it last, which will prevent it from trying to match it + // as the scaled value in case it happens to be a mul. That would be + // problematic if we've sunk a different mul for the scale, because then + // we'd end up sinking both muls. + if (AddrMode.BaseReg) { + Value *V = AddrMode.BaseReg; + if (isa<PointerType>(V->getType())) + V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt); + if (V->getType() != IntPtrTy) + V = CastInst::CreateIntegerCast(V, IntPtrTy, /*isSigned=*/true, + "sunkaddr", InsertPt); + Result = V; + } + + // Add the scale value. if (AddrMode.Scale) { Value *V = AddrMode.ScaledReg; if (V->getType() == IntPtrTy) { @@ -634,17 +650,6 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, V = BinaryOperator::CreateMul(V, ConstantInt::get(IntPtrTy, AddrMode.Scale), "sunkaddr", InsertPt); - Result = V; - } - - // Add in the base register. - if (AddrMode.BaseReg) { - Value *V = AddrMode.BaseReg; - if (isa<PointerType>(V->getType())) - V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt); - if (V->getType() != IntPtrTy) - V = CastInst::CreateIntegerCast(V, IntPtrTy, /*isSigned=*/true, - "sunkaddr", InsertPt); if (Result) Result = BinaryOperator::CreateAdd(Result, V, "sunkaddr", InsertPt); else diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index ac0d850..b29fe74 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -70,18 +70,44 @@ static cl::opt<bool> EnableLoadPRE("enable-load-pre", cl::init(true)); /// two values. namespace { struct Expression { - enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL, - UDIV, SDIV, FDIV, UREM, SREM, - FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ, - ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE, - ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ, - FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE, - FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE, - FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT, - SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI, - FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT, - PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, CONSTANT, - INSERTVALUE, EXTRACTVALUE, EMPTY, TOMBSTONE }; + enum ExpressionOpcode { + ADD = Instruction::Add, + FADD = Instruction::FAdd, + SUB = Instruction::Sub, + FSUB = Instruction::FSub, + MUL = Instruction::Mul, + FMUL = Instruction::FMul, + UDIV = Instruction::UDiv, + SDIV = Instruction::SDiv, + FDIV = Instruction::FDiv, + UREM = Instruction::URem, + SREM = Instruction::SRem, + FREM = Instruction::FRem, + SHL = Instruction::Shl, + LSHR = Instruction::LShr, + ASHR = Instruction::AShr, + AND = Instruction::And, + OR = Instruction::Or, + XOR = Instruction::Xor, + TRUNC = Instruction::Trunc, + ZEXT = Instruction::ZExt, + SEXT = Instruction::SExt, + FPTOUI = Instruction::FPToUI, + FPTOSI = Instruction::FPToSI, + UITOFP = Instruction::UIToFP, + SITOFP = Instruction::SIToFP, + FPTRUNC = Instruction::FPTrunc, + FPEXT = Instruction::FPExt, + PTRTOINT = Instruction::PtrToInt, + INTTOPTR = Instruction::IntToPtr, + BITCAST = Instruction::BitCast, + ICMPEQ, ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE, + ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ, + FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE, + FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE, + FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT, + SHUFFLE, SELECT, GEP, CALL, CONSTANT, + INSERTVALUE, EXTRACTVALUE, EMPTY, TOMBSTONE }; ExpressionOpcode opcode; const Type* type; @@ -127,9 +153,7 @@ namespace { uint32_t nextValueNumber; - Expression::ExpressionOpcode getOpcode(BinaryOperator* BO); Expression::ExpressionOpcode getOpcode(CmpInst* C); - Expression::ExpressionOpcode getOpcode(CastInst* C); Expression create_expression(BinaryOperator* BO); Expression create_expression(CmpInst* C); Expression create_expression(ShuffleVectorInst* V); @@ -200,30 +224,6 @@ struct isPodLike<Expression> { static const bool value = true; }; //===----------------------------------------------------------------------===// // ValueTable Internal Functions //===----------------------------------------------------------------------===// -Expression::ExpressionOpcode ValueTable::getOpcode(BinaryOperator* BO) { - switch(BO->getOpcode()) { - default: // THIS SHOULD NEVER HAPPEN - llvm_unreachable("Binary operator with unknown opcode?"); - case Instruction::Add: return Expression::ADD; - case Instruction::FAdd: return Expression::FADD; - case Instruction::Sub: return Expression::SUB; - case Instruction::FSub: return Expression::FSUB; - case Instruction::Mul: return Expression::MUL; - case Instruction::FMul: return Expression::FMUL; - case Instruction::UDiv: return Expression::UDIV; - case Instruction::SDiv: return Expression::SDIV; - case Instruction::FDiv: return Expression::FDIV; - case Instruction::URem: return Expression::UREM; - case Instruction::SRem: return Expression::SREM; - case Instruction::FRem: return Expression::FREM; - case Instruction::Shl: return Expression::SHL; - case Instruction::LShr: return Expression::LSHR; - case Instruction::AShr: return Expression::ASHR; - case Instruction::And: return Expression::AND; - case Instruction::Or: return Expression::OR; - case Instruction::Xor: return Expression::XOR; - } -} Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) { if (isa<ICmpInst>(C)) { @@ -263,25 +263,6 @@ Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) { } } -Expression::ExpressionOpcode ValueTable::getOpcode(CastInst* C) { - switch(C->getOpcode()) { - default: // THIS SHOULD NEVER HAPPEN - llvm_unreachable("Cast operator with unknown opcode?"); - case Instruction::Trunc: return Expression::TRUNC; - case Instruction::ZExt: return Expression::ZEXT; - case Instruction::SExt: return Expression::SEXT; - case Instruction::FPToUI: return Expression::FPTOUI; - case Instruction::FPToSI: return Expression::FPTOSI; - case Instruction::UIToFP: return Expression::UITOFP; - case Instruction::SIToFP: return Expression::SITOFP; - case Instruction::FPTrunc: return Expression::FPTRUNC; - case Instruction::FPExt: return Expression::FPEXT; - case Instruction::PtrToInt: return Expression::PTRTOINT; - case Instruction::IntToPtr: return Expression::INTTOPTR; - case Instruction::BitCast: return Expression::BITCAST; - } -} - Expression ValueTable::create_expression(CallInst* C) { Expression e; @@ -302,7 +283,7 @@ Expression ValueTable::create_expression(BinaryOperator* BO) { e.varargs.push_back(lookup_or_add(BO->getOperand(1))); e.function = 0; e.type = BO->getType(); - e.opcode = getOpcode(BO); + e.opcode = static_cast<Expression::ExpressionOpcode>(BO->getOpcode()); return e; } @@ -325,7 +306,7 @@ Expression ValueTable::create_expression(CastInst* C) { e.varargs.push_back(lookup_or_add(C->getOperand(0))); e.function = 0; e.type = C->getType(); - e.opcode = getOpcode(C); + e.opcode = static_cast<Expression::ExpressionOpcode>(C->getOpcode()); return e; } diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index ce1307c..17f7d98 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -471,6 +471,13 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType, // Compute the final addrec to expand into code. const SCEV *AR = IU->getReplacementExpr(*UI); + // Evaluate the expression out of the loop, if possible. + if (!L->contains(UI->getUser())) { + const SCEV *ExitVal = SE->getSCEVAtScope(AR, L->getParentLoop()); + if (ExitVal->isLoopInvariant(L)) + AR = ExitVal; + } + // FIXME: It is an extremely bad idea to indvar substitute anything more // complex than affine induction variables. Doing so will put expensive // polynomial evaluations inside of the loop, and the str reduction pass @@ -522,11 +529,10 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType, Rewriter.clear(); // Now that we're done iterating through lists, clean up any instructions // which are now dead. - while (!DeadInsts.empty()) { - Instruction *Inst = dyn_cast_or_null<Instruction>(DeadInsts.pop_back_val()); - if (Inst) + while (!DeadInsts.empty()) + if (Instruction *Inst = + dyn_cast_or_null<Instruction>(DeadInsts.pop_back_val())) RecursivelyDeleteTriviallyDeadInstructions(Inst); - } } /// If there's a single exit block, sink any loop-invariant values that diff --git a/lib/Transforms/Scalar/Makefile b/lib/Transforms/Scalar/Makefile index cc42fd0..e18f30f 100644 --- a/lib/Transforms/Scalar/Makefile +++ b/lib/Transforms/Scalar/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMScalarOpts BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index 9e1e79a..f473480 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -85,10 +85,6 @@ namespace { /// isUnsafe - This is set to true if the alloca cannot be SROA'd. bool isUnsafe : 1; - /// needsCleanup - This is set to true if there is some use of the alloca - /// that requires cleanup. - bool needsCleanup : 1; - /// isMemCpySrc - This is true if this aggregate is memcpy'd from. bool isMemCpySrc : 1; @@ -96,15 +92,14 @@ namespace { bool isMemCpyDst : 1; AllocaInfo() - : isUnsafe(false), needsCleanup(false), - isMemCpySrc(false), isMemCpyDst(false) {} + : isUnsafe(false), isMemCpySrc(false), isMemCpyDst(false) {} }; unsigned SRThreshold; void MarkUnsafe(AllocaInfo &I) { I.isUnsafe = true; } - int isSafeAllocaToScalarRepl(AllocaInst *AI); + bool isSafeAllocaToScalarRepl(AllocaInst *AI); void isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, AllocaInfo &Info); @@ -119,7 +114,6 @@ namespace { void DoScalarReplacement(AllocaInst *AI, std::vector<AllocaInst*> &WorkList); void DeleteDeadInstructions(); - void CleanupAllocaUsers(Value *V); AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocaInst *Base); void RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, @@ -281,14 +275,7 @@ bool SROA::performScalarRepl(Function &F) { getNumSAElements(AI->getAllocatedType()) <= SRThreshold/4) { // Check that all of the users of the allocation are capable of being // transformed. - switch (isSafeAllocaToScalarRepl(AI)) { - default: llvm_unreachable("Unexpected value!"); - case 0: // Not safe to scalar replace. - break; - case 1: // Safe, but requires cleanup/canonicalizations first - CleanupAllocaUsers(AI); - // FALL THROUGH. - case 3: // Safe to scalar replace. + if (isSafeAllocaToScalarRepl(AI)) { DoScalarReplacement(AI, WorkList); Changed = true; continue; @@ -437,14 +424,6 @@ void SROA::isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, SIType, true, Info); } else MarkUnsafe(Info); - } else if (isa<DbgInfoIntrinsic>(UI)) { - // If one user is DbgInfoIntrinsic then check if all users are - // DbgInfoIntrinsics. - if (OnlyUsedByDbgInfoIntrinsics(I)) { - Info.needsCleanup = true; - return; - } - MarkUnsafe(Info); } else { DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); MarkUnsafe(Info); @@ -752,9 +731,16 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, } break; } - // If OtherPtr has already been rewritten, this intrinsic will be dead. - if (OtherPtr == NewElts[0]) + // Copying the alloca to itself is a no-op: just delete it. + if (OtherPtr == AI || OtherPtr == NewElts[0]) { + // This code will run twice for a no-op memcpy -- once for each operand. + // Put only one reference to MI on the DeadInsts list. + for (SmallVector<Value*, 32>::const_iterator I = DeadInsts.begin(), + E = DeadInsts.end(); I != E; ++I) + if (*I == MI) return; + DeadInsts.push_back(MI); return; + } if (ConstantExpr *BCE = dyn_cast<ConstantExpr>(OtherPtr)) if (BCE->getOpcode() == Instruction::BitCast) @@ -779,10 +765,7 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, Value *OtherElt = 0; unsigned OtherEltAlign = MemAlignment; - if (OtherPtr == AI) { - OtherElt = NewElts[i]; - OtherEltAlign = 0; - } else if (OtherPtr) { + if (OtherPtr) { Value *Idx[2] = { Zero, ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) }; OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx, Idx + 2, @@ -1146,7 +1129,7 @@ static bool HasPadding(const Type *Ty, const TargetData &TD) { /// isSafeStructAllocaToScalarRepl - Check to see if the specified allocation of /// an aggregate can be broken down into elements. Return 0 if not, 3 if safe, /// or 1 if safe after canonicalization has been performed. -int SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) { +bool SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) { // Loop over the use list of the alloca. We can only transform it if all of // the users are safe to transform. AllocaInfo Info; @@ -1154,7 +1137,7 @@ int SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) { isSafeForScalarRepl(AI, AI, 0, Info); if (Info.isUnsafe) { DEBUG(dbgs() << "Cannot transform: " << *AI << '\n'); - return 0; + return false; } // Okay, we know all the users are promotable. If the aggregate is a memcpy @@ -1164,29 +1147,9 @@ int SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) { // struct. if (Info.isMemCpySrc && Info.isMemCpyDst && HasPadding(AI->getAllocatedType(), *TD)) - return 0; - - // If we require cleanup, return 1, otherwise return 3. - return Info.needsCleanup ? 1 : 3; -} + return false; -/// CleanupAllocaUsers - If SROA reported that it can promote the specified -/// allocation, but only if cleaned up, perform the cleanups required. -void SROA::CleanupAllocaUsers(Value *V) { - for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); - UI != E; ) { - User *U = *UI++; - Instruction *I = cast<Instruction>(U); - SmallVector<DbgInfoIntrinsic *, 2> DbgInUses; - if (!isa<StoreInst>(I) && OnlyUsedByDbgInfoIntrinsics(I, &DbgInUses)) { - // Safe to remove debug info uses. - while (!DbgInUses.empty()) { - DbgInfoIntrinsic *DI = DbgInUses.pop_back_val(); - DI->eraseFromParent(); - } - I->eraseFromParent(); - } - } + return true; } /// MergeInType - Add the 'In' type to the accumulated type (Accum) so far at @@ -1321,10 +1284,6 @@ bool SROA::CanConvertToScalar(Value *V, bool &IsNotTrivial, const Type *&VecTy, } } - // Ignore dbg intrinsic. - if (isa<DbgInfoIntrinsic>(User)) - continue; - // Otherwise, we cannot handle this! return false; } @@ -1449,18 +1408,11 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset) { } else { // Noop transfer. Src == Dst } - MTI->eraseFromParent(); continue; } - // If user is a dbg info intrinsic then it is safe to remove it. - if (isa<DbgInfoIntrinsic>(User)) { - User->eraseFromParent(); - continue; - } - llvm_unreachable("Unsupported operation!"); } } diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 9183f3a..a49da9c 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -81,6 +81,10 @@ public: /// and the return value has 'i8*' type. Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B); + /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the + /// specified pointer arguments. + Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B); + /// EmitMemCpy - Emit a call to the memcpy function to the builder. This /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, @@ -176,6 +180,22 @@ Value *LibCallOptimization::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B) { return CI; } +/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the +/// specified pointer arguments. +Value *LibCallOptimization::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI[2]; + AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + const Type *I8Ptr = Type::getInt8PtrTy(*Context); + Value *StrCpy = M->getOrInsertFunction("strcpy", AttrListPtr::get(AWI, 2), + I8Ptr, I8Ptr, I8Ptr, NULL); + CallInst *CI = B.CreateCall2(StrCpy, CastToCStr(Dst, B), CastToCStr(Src, B), + "strcpy"); + if (const Function *F = dyn_cast<Function>(StrCpy->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + return CI; +} /// EmitMemCpy - Emit a call to the memcpy function to the builder. This always /// expects that the size has type 'intptr_t' and Dst/Src are pointers. @@ -1181,6 +1201,31 @@ struct MemMoveChkOpt : public LibCallOptimization { } }; +struct StrCpyChkOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || + !isa<PointerType>(FT->getParamType(0)) || + !isa<PointerType>(FT->getParamType(1)) || + !isa<IntegerType>(FT->getParamType(2))) + return 0; + + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeCI) + return 0; + + // We don't have any length information, just lower to a plain strcpy. + if (SizeCI->isAllOnesValue()) + return EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B); + + return 0; + } +}; + + //===----------------------------------------------------------------------===// // Math Library Optimizations //===----------------------------------------------------------------------===// @@ -1725,6 +1770,7 @@ namespace { // Object Size Checking MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk; + StrCpyChkOpt StrCpyChk; bool Modified; // This is only used by doInitialization. public: @@ -1836,6 +1882,7 @@ void SimplifyLibCalls::InitOptimizations() { Optimizations["__memcpy_chk"] = &MemCpyChk; Optimizations["__memset_chk"] = &MemSetChk; Optimizations["__memmove_chk"] = &MemMoveChk; + Optimizations["__strcpy_chk"] = &StrCpyChk; } diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp index e902688..7bc4fcd 100644 --- a/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -615,11 +615,6 @@ Value *llvm::FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, Instruction *Inst = --ScanFrom; if (isa<DbgInfoIntrinsic>(Inst)) continue; - // We skip pointer-to-pointer bitcasts, which are NOPs. - // It is necessary for correctness to skip those that feed into a - // llvm.dbg.declare, as these are not present when debugging is off. - if (isa<BitCastInst>(Inst) && isa<PointerType>(Inst->getType())) - continue; // Restore ScanFrom to expected value in case next test succeeds ScanFrom++; diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 90e929e..92bdf2d 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -609,30 +609,6 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) { return true; } - - -/// OnlyUsedByDbgIntrinsics - Return true if the instruction I is only used -/// by DbgIntrinsics. If DbgInUses is specified then the vector is filled -/// with the DbgInfoIntrinsic that use the instruction I. -bool llvm::OnlyUsedByDbgInfoIntrinsics(Instruction *I, - SmallVectorImpl<DbgInfoIntrinsic *> *DbgInUses) { - if (DbgInUses) - DbgInUses->clear(); - - for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE; - ++UI) { - if (DbgInfoIntrinsic *DI = dyn_cast<DbgInfoIntrinsic>(*UI)) { - if (DbgInUses) - DbgInUses->push_back(DI); - } else { - if (DbgInUses) - DbgInUses->clear(); - return false; - } - } - return true; -} - /// EliminateDuplicatePHINodes - Check for and eliminate duplicate PHI /// nodes in this block. This doesn't try to be clever about PHI nodes /// which differ only in the order of the incoming values, but instcombine diff --git a/lib/Transforms/Utils/LoopSimplify.cpp b/lib/Transforms/Utils/LoopSimplify.cpp index 7fcc5f7..e81b779 100644 --- a/lib/Transforms/Utils/LoopSimplify.cpp +++ b/lib/Transforms/Utils/LoopSimplify.cpp @@ -232,7 +232,7 @@ ReprocessLoop: PN->eraseFromParent(); } - // If this loop has muliple exits and the exits all go to the same + // If this loop has multiple exits and the exits all go to the same // block, attempt to merge the exits. This helps several passes, such // as LoopRotation, which do not support loops with multiple exits. // SimplifyCFG also does this (and this code uses the same utility diff --git a/lib/Transforms/Utils/Makefile b/lib/Transforms/Utils/Makefile index d1e9336..b9761df 100644 --- a/lib/Transforms/Utils/Makefile +++ b/lib/Transforms/Utils/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMTransformUtils BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index baaa130..d9261ac 100644 --- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -23,6 +23,7 @@ #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/ADT/DenseMap.h" @@ -76,16 +77,6 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) { return false; // Don't allow a store OF the AI, only INTO the AI. if (SI->isVolatile()) return false; - } else if (const BitCastInst *BC = dyn_cast<BitCastInst>(*UI)) { - // A bitcast that does not feed into debug info inhibits promotion. - if (!BC->hasOneUse() || !isa<DbgInfoIntrinsic>(*BC->use_begin())) - return false; - // If the only use is by debug info, this alloca will not exist in - // non-debug code, so don't try to promote; this ensures the same - // codegen with debug info. Otherwise, debug info should not - // inhibit promotion (but we must examine other uses). - if (AI->hasOneUse()) - return false; } else { return false; } @@ -173,6 +164,7 @@ namespace { std::vector<AllocaInst*> Allocas; DominatorTree &DT; DominanceFrontier &DF; + DIFactory *DIF; /// AST - An AliasSetTracker object to update. If null, don't update it. /// @@ -209,7 +201,7 @@ namespace { public: PromoteMem2Reg(const std::vector<AllocaInst*> &A, DominatorTree &dt, DominanceFrontier &df, AliasSetTracker *ast) - : Allocas(A), DT(dt), DF(df), AST(ast) {} + : Allocas(A), DT(dt), DF(df), DIF(0), AST(ast) {} void run(); @@ -251,8 +243,9 @@ namespace { LargeBlockInfo &LBI); void PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, LargeBlockInfo &LBI); - - + void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, StoreInst* SI, + uint64_t Offset); + void RenamePass(BasicBlock *BB, BasicBlock *Pred, RenamePassData::ValVector &IncVals, std::vector<RenamePassData> &Worklist); @@ -290,15 +283,7 @@ namespace { for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E;) { Instruction *User = cast<Instruction>(*UI++); - if (BitCastInst *BC = dyn_cast<BitCastInst>(User)) { - // Remove any uses of this alloca in DbgInfoInstrinsics. - assert(BC->hasOneUse() && "Unexpected alloca uses!"); - DbgInfoIntrinsic *DI = cast<DbgInfoIntrinsic>(*BC->use_begin()); - DI->eraseFromParent(); - BC->eraseFromParent(); - continue; - } - + if (StoreInst *SI = dyn_cast<StoreInst>(User)) { // Remember the basic blocks which define new values for the alloca DefiningBlocks.push_back(SI->getParent()); @@ -324,6 +309,19 @@ namespace { } // end of anonymous namespace +/// Finds the llvm.dbg.declare intrinsic corresponding to an alloca if any. +static DbgDeclareInst *findDbgDeclare(AllocaInst *AI) { + Function *F = AI->getParent()->getParent(); + for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end(); + BI != BE; ++BI) + if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) + if (DDI->getAddress() == AI) + return DDI; + + return 0; +} + void PromoteMem2Reg::run() { Function &F = *DF.getRoot()->getParent(); @@ -362,6 +360,8 @@ void PromoteMem2Reg::run() { // Finally, after the scan, check to see if the store is all that is left. if (Info.UsingBlocks.empty()) { + // Record debuginfo for the store before removing it. + ConvertDebugDeclareToDebugValue(findDbgDeclare(AI), Info.OnlyStore, 0); // Remove the (now dead) store and alloca. Info.OnlyStore->eraseFromParent(); LBI.deleteValue(Info.OnlyStore); @@ -388,8 +388,11 @@ void PromoteMem2Reg::run() { if (Info.UsingBlocks.empty()) { // Remove the (now dead) stores and alloca. + DbgDeclareInst *DDI = findDbgDeclare(AI); while (!AI->use_empty()) { StoreInst *SI = cast<StoreInst>(AI->use_back()); + // Record debuginfo for the store before removing it. + ConvertDebugDeclareToDebugValue(DDI, SI, 0); SI->eraseFromParent(); LBI.deleteValue(SI); } @@ -851,6 +854,18 @@ void PromoteMem2Reg::PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, } } +// Inserts a llvm.dbg.value instrinsic before the stores to an alloca'd value +// that has an associated llvm.dbg.decl intrinsic. +void PromoteMem2Reg::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, + StoreInst* SI, + uint64_t Offset) { + if (!DDI) return; + + if (!DIF) + DIF = new DIFactory(*SI->getParent()->getParent()->getParent()); + DIF->InsertDbgValueIntrinsic(SI->getOperand(0), Offset, + DIVariable(DDI->getVariable()), SI); +} // QueuePhiNode - queues a phi-node to be added to a basic-block for a specific // Alloca returns true if there wasn't already a phi-node for that variable @@ -964,6 +979,8 @@ NextIteration: // what value were we writing? IncomingVals[ai->second] = SI->getOperand(0); + // Record debuginfo for the store before removing it. + ConvertDebugDeclareToDebugValue(findDbgDeclare(Dest), SI, 0); BB->getInstList().erase(SI); } } diff --git a/lib/Transforms/Utils/ValueMapper.cpp b/lib/Transforms/Utils/ValueMapper.cpp index 39331d7..a6e6701 100644 --- a/lib/Transforms/Utils/ValueMapper.cpp +++ b/lib/Transforms/Utils/ValueMapper.cpp @@ -13,12 +13,11 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/ValueMapper.h" -#include "llvm/DerivedTypes.h" // For getNullValue(Type::Int32Ty) +#include "llvm/Type.h" #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Metadata.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/ErrorHandling.h" using namespace llvm; Value *llvm::MapValue(const Value *V, ValueMapTy &VM) { @@ -28,11 +27,19 @@ Value *llvm::MapValue(const Value *V, ValueMapTy &VM) { // NOTE: VMSlot can be invalidated by any reference to VM, which can grow the // DenseMap. This includes any recursive calls to MapValue. - // Global values and metadata do not need to be seeded into the ValueMap if - // they are using the identity mapping. - if (isa<GlobalValue>(V) || isa<InlineAsm>(V) || isa<MetadataBase>(V)) + // Global values and non-function-local metadata do not need to be seeded into + // the ValueMap if they are using the identity mapping. + if (isa<GlobalValue>(V) || isa<InlineAsm>(V) || isa<MDString>(V) || + (isa<MDNode>(V) && !cast<MDNode>(V)->isFunctionLocal())) return VMSlot = const_cast<Value*>(V); + if (const MDNode *MD = dyn_cast<MDNode>(V)) { + SmallVector<Value*, 4> Elts; + for (unsigned i = 0; i != MD->getNumOperands(); i++) + Elts.push_back(MD->getOperand(i) ? MapValue(MD->getOperand(i), VM) : 0); + return VM[V] = MDNode::get(V->getContext(), Elts.data(), Elts.size()); + } + Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V)); if (C == 0) return 0; @@ -111,14 +118,10 @@ Value *llvm::MapValue(const Value *V, ValueMapTy &VM) { return VM[V] = C; } - if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) { - Function *F = cast<Function>(MapValue(BA->getFunction(), VM)); - BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(),VM)); - return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock()); - } - - llvm_unreachable("Unknown type of constant!"); - return 0; + BlockAddress *BA = cast<BlockAddress>(C); + Function *F = cast<Function>(MapValue(BA->getFunction(), VM)); + BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(),VM)); + return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock()); } /// RemapInstruction - Convert the instruction operands from referencing the @@ -131,3 +134,4 @@ void llvm::RemapInstruction(Instruction *I, ValueMapTy &ValueMap) { *op = V; } } + diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index eff2c77..c9f3849 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -2062,9 +2062,9 @@ void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const { else W.printAlias(cast<GlobalAlias>(GV)); } else if (const MDNode *N = dyn_cast<MDNode>(this)) { - Function *F = N->getFunction(); + const Function *F = N->getFunction(); SlotTracker SlotTable(F); - AssemblyWriter W(OS, SlotTable, getModuleFromVal(F), AAW); + AssemblyWriter W(OS, SlotTable, F ? getModuleFromVal(F) : 0, AAW); W.printMDNodeBody(N); } else if (const NamedMDNode *N = dyn_cast<NamedMDNode>(this)) { SlotTracker SlotTable(N->getParent()); diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp index a371c6f..65155f1 100644 --- a/lib/VMCore/Attributes.cpp +++ b/lib/VMCore/Attributes.cpp @@ -56,8 +56,6 @@ std::string Attribute::getAsString(Attributes Attrs) { Result += "optsize "; if (Attrs & Attribute::NoInline) Result += "noinline "; - if (Attrs & Attribute::InlineHint) - Result += "inlinehint "; if (Attrs & Attribute::AlwaysInline) Result += "alwaysinline "; if (Attrs & Attribute::StackProtect) diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index 2161841..5e4c9fb 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -521,7 +521,7 @@ void llvm::CheckDebugInfoIntrinsics(Module *M) { if (Function *Declare = M->getFunction("llvm.dbg.declare")) { if (!Declare->use_empty()) { DbgDeclareInst *DDI = cast<DbgDeclareInst>(Declare->use_back()); - if (!isa<MDNode>(DDI->getOperand(2))) { + if (!isa<MDNode>(DDI->getOperand(1)) ||!isa<MDNode>(DDI->getOperand(2))) { while (!Declare->use_empty()) { CallInst *CI = cast<CallInst>(Declare->use_back()); CI->eraseFromParent(); diff --git a/lib/VMCore/CMakeLists.txt b/lib/VMCore/CMakeLists.txt index 61d01ee..5ecedf1 100644 --- a/lib/VMCore/CMakeLists.txt +++ b/lib/VMCore/CMakeLists.txt @@ -16,7 +16,6 @@ add_llvm_library(LLVMCore IRBuilder.cpp LLVMContext.cpp LeakDetector.cpp - Mangler.cpp Metadata.cpp Module.cpp ModuleProvider.cpp diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 3a24389..ddd5587 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -1673,14 +1673,15 @@ Constant *llvm::ConstantFoldCompareInstruction(LLVMContext &Context, SmallVector<Constant*, 16> C1Elts, C2Elts; C1->getVectorElements(Context, C1Elts); C2->getVectorElements(Context, C2Elts); + if (C1Elts.empty() || C2Elts.empty()) + return 0; // If we can constant fold the comparison of each element, constant fold // the whole vector comparison. SmallVector<Constant*, 4> ResElts; for (unsigned i = 0, e = C1Elts.size(); i != e; ++i) { // Compare the elements, producing an i1 result or constant expr. - ResElts.push_back( - ConstantExpr::getCompare(pred, C1Elts[i], C2Elts[i])); + ResElts.push_back(ConstantExpr::getCompare(pred, C1Elts[i], C2Elts[i])); } return ConstantVector::get(&ResElts[0], ResElts.size()); } diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index cc8961f..916aac6 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1630,7 +1630,7 @@ Constant *ConstantExpr::getInBoundsGetElementPtr(Constant *C, } Constant * -ConstantExpr::getICmp(unsigned short pred, Constant* LHS, Constant* RHS) { +ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) { assert(LHS->getType() == RHS->getType()); assert(pred >= ICmpInst::FIRST_ICMP_PREDICATE && pred <= ICmpInst::LAST_ICMP_PREDICATE && "Invalid ICmp Predicate"); @@ -1646,13 +1646,16 @@ ConstantExpr::getICmp(unsigned short pred, Constant* LHS, Constant* RHS) { // Get the key type with both the opcode and predicate const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred); + const Type *ResultTy = Type::getInt1Ty(LHS->getContext()); + if (const VectorType *VT = dyn_cast<VectorType>(LHS->getType())) + ResultTy = VectorType::get(ResultTy, VT->getNumElements()); + LLVMContextImpl *pImpl = LHS->getType()->getContext().pImpl; - return - pImpl->ExprConstants.getOrCreate(Type::getInt1Ty(LHS->getContext()), Key); + return pImpl->ExprConstants.getOrCreate(ResultTy, Key); } Constant * -ConstantExpr::getFCmp(unsigned short pred, Constant* LHS, Constant* RHS) { +ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) { assert(LHS->getType() == RHS->getType()); assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && "Invalid FCmp Predicate"); @@ -1666,10 +1669,13 @@ ConstantExpr::getFCmp(unsigned short pred, Constant* LHS, Constant* RHS) { ArgVec.push_back(RHS); // Get the key type with both the opcode and predicate const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred); - + + const Type *ResultTy = Type::getInt1Ty(LHS->getContext()); + if (const VectorType *VT = dyn_cast<VectorType>(LHS->getType())) + ResultTy = VectorType::get(ResultTy, VT->getNumElements()); + LLVMContextImpl *pImpl = LHS->getType()->getContext().pImpl; - return - pImpl->ExprConstants.getOrCreate(Type::getInt1Ty(LHS->getContext()), Key); + return pImpl->ExprConstants.getOrCreate(ResultTy, Key); } Constant *ConstantExpr::getExtractElementTy(const Type *ReqTy, Constant *Val, diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 2619047..e2b920e 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -2079,25 +2079,26 @@ unsigned CastInst::isEliminableCastPair( return secondOp; case 3: // no-op cast in second op implies firstOp as long as the DestTy - // is integer - if (DstTy->isInteger()) + // is integer and we are not converting between a vector and a + // non vector type. + if (!isa<VectorType>(SrcTy) && DstTy->isInteger()) return firstOp; return 0; case 4: // no-op cast in second op implies firstOp as long as the DestTy - // is floating point + // is floating point. if (DstTy->isFloatingPoint()) return firstOp; return 0; case 5: // no-op cast in first op implies secondOp as long as the SrcTy - // is an integer + // is an integer. if (SrcTy->isInteger()) return secondOp; return 0; case 6: // no-op cast in first op implies secondOp as long as the SrcTy - // is a floating point + // is a floating point. if (SrcTy->isFloatingPoint()) return secondOp; return 0; @@ -2714,6 +2715,8 @@ BitCastInst::BitCastInst( // CmpInst Classes //===----------------------------------------------------------------------===// +void CmpInst::Anchor() const {} + CmpInst::CmpInst(const Type *ty, OtherOps op, unsigned short predicate, Value *LHS, Value *RHS, const Twine &Name, Instruction *InsertBefore) diff --git a/lib/VMCore/IntrinsicInst.cpp b/lib/VMCore/IntrinsicInst.cpp index cb9252e..d8f015a 100644 --- a/lib/VMCore/IntrinsicInst.cpp +++ b/lib/VMCore/IntrinsicInst.cpp @@ -51,6 +51,17 @@ Value *DbgInfoIntrinsic::StripCast(Value *C) { } //===----------------------------------------------------------------------===// +/// DbgDeclareInst - This represents the llvm.dbg.declare instruction. +/// + +Value *DbgDeclareInst::getAddress() const { + if (MDNode* MD = cast_or_null<MDNode>(getOperand(1))) + return MD->getOperand(0); + else + return NULL; +} + +//===----------------------------------------------------------------------===// /// DbgValueInst - This represents the llvm.dbg.value instruction. /// diff --git a/lib/VMCore/Makefile b/lib/VMCore/Makefile index e9d3dc8..ecadaee 100644 --- a/lib/VMCore/Makefile +++ b/lib/VMCore/Makefile @@ -9,6 +9,7 @@ LEVEL = ../.. LIBRARYNAME = LLVMCore BUILD_ARCHIVE = 1 +#CXXFLAGS = -fno-rtti BUILT_SOURCES = $(PROJ_OBJ_ROOT)/include/llvm/Intrinsics.gen diff --git a/lib/VMCore/Mangler.cpp b/lib/VMCore/Mangler.cpp deleted file mode 100644 index 7d9f330..0000000 --- a/lib/VMCore/Mangler.cpp +++ /dev/null @@ -1,273 +0,0 @@ -//===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Unified name mangler for CWriter and assembly backends. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/Mangler.h" -#include "llvm/Function.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -static char HexDigit(int V) { - return V < 10 ? V+'0' : V+'A'-10; -} - -static void MangleLetter(SmallVectorImpl<char> &OutName, unsigned char C) { - OutName.push_back('_'); - OutName.push_back(HexDigit(C >> 4)); - OutName.push_back(HexDigit(C & 15)); - OutName.push_back('_'); -} - -/// makeNameProper - We don't want identifier names non-C-identifier characters -/// in them, so mangle them as appropriate. -/// -/// FIXME: This is deprecated, new code should use getNameWithPrefix and use -/// MCSymbol printing to handle quotes or not etc. -/// -void Mangler::makeNameProper(SmallVectorImpl<char> &OutName, - const Twine &TheName, - ManglerPrefixTy PrefixTy) { - SmallString<256> TmpData; - StringRef X = TheName.toStringRef(TmpData); - assert(!X.empty() && "Cannot mangle empty strings"); - - if (!UseQuotes) { - // If X does not start with (char)1, add the prefix. - StringRef::iterator I = X.begin(); - if (*I == 1) { - ++I; // Skip over the no-prefix marker. - } else { - if (PrefixTy == Mangler::Private) - OutName.append(PrivatePrefix, PrivatePrefix+strlen(PrivatePrefix)); - else if (PrefixTy == Mangler::LinkerPrivate) - OutName.append(LinkerPrivatePrefix, - LinkerPrivatePrefix+strlen(LinkerPrivatePrefix)); - OutName.append(Prefix, Prefix+strlen(Prefix)); - } - - // Mangle the first letter specially, don't allow numbers unless the target - // explicitly allows them. - if (!SymbolsCanStartWithDigit && *I >= '0' && *I <= '9') - MangleLetter(OutName, *I++); - - for (StringRef::iterator E = X.end(); I != E; ++I) { - if (!isCharAcceptable(*I)) - MangleLetter(OutName, *I); - else - OutName.push_back(*I); - } - return; - } - - bool NeedPrefix = true; - bool NeedQuotes = false; - StringRef::iterator I = X.begin(); - if (*I == 1) { - NeedPrefix = false; - ++I; // Skip over the marker. - } - - // If the first character is a number, we need quotes. - if (*I >= '0' && *I <= '9') - NeedQuotes = true; - - // Do an initial scan of the string, checking to see if we need quotes or - // to escape a '"' or not. - if (!NeedQuotes) - for (StringRef::iterator E = X.end(); I != E; ++I) - if (!isCharAcceptable(*I)) { - NeedQuotes = true; - break; - } - - // In the common case, we don't need quotes. Handle this quickly. - if (!NeedQuotes) { - if (!NeedPrefix) { - OutName.append(X.begin()+1, X.end()); // Strip off the \001. - return; - } - - if (PrefixTy == Mangler::Private) - OutName.append(PrivatePrefix, PrivatePrefix+strlen(PrivatePrefix)); - else if (PrefixTy == Mangler::LinkerPrivate) - OutName.append(LinkerPrivatePrefix, - LinkerPrivatePrefix+strlen(LinkerPrivatePrefix)); - - if (Prefix[0] == 0) - ; // Common noop, no prefix. - else if (Prefix[1] == 0) - OutName.push_back(Prefix[0]); // Common, one character prefix. - else - OutName.append(Prefix, Prefix+strlen(Prefix)); // Arbitrary prefix. - OutName.append(X.begin(), X.end()); - return; - } - - // Add leading quote. - OutName.push_back('"'); - - // Add prefixes unless disabled. - if (NeedPrefix) { - if (PrefixTy == Mangler::Private) - OutName.append(PrivatePrefix, PrivatePrefix+strlen(PrivatePrefix)); - else if (PrefixTy == Mangler::LinkerPrivate) - OutName.append(LinkerPrivatePrefix, - LinkerPrivatePrefix+strlen(LinkerPrivatePrefix)); - OutName.append(Prefix, Prefix+strlen(Prefix)); - } - - // Add the piece that we already scanned through. - OutName.append(X.begin()+!NeedPrefix, I); - - // Otherwise, construct the string the expensive way. - for (StringRef::iterator E = X.end(); I != E; ++I) { - if (*I == '"') { - const char *Quote = "_QQ_"; - OutName.append(Quote, Quote+4); - } else if (*I == '\n') { - const char *Newline = "_NL_"; - OutName.append(Newline, Newline+4); - } else - OutName.push_back(*I); - } - - // Add trailing quote. - OutName.push_back('"'); -} - -/// getMangledName - Returns the mangled name of V, an LLVM Value, -/// in the current module. If 'Suffix' is specified, the name ends with the -/// specified suffix. If 'ForcePrivate' is specified, the label is specified -/// to have a private label prefix. -/// -/// FIXME: This is deprecated, new code should use getNameWithPrefix and use -/// MCSymbol printing to handle quotes or not etc. -/// -std::string Mangler::getMangledName(const GlobalValue *GV, const char *Suffix, - bool ForcePrivate) { - assert((!isa<Function>(GV) || !cast<Function>(GV)->isIntrinsic()) && - "Intrinsic functions cannot be mangled by Mangler"); - - ManglerPrefixTy PrefixTy = - (GV->hasPrivateLinkage() || ForcePrivate) ? Mangler::Private : - GV->hasLinkerPrivateLinkage() ? Mangler::LinkerPrivate : Mangler::Default; - - SmallString<128> Result; - if (GV->hasName()) { - makeNameProper(Result, GV->getNameStr() + Suffix, PrefixTy); - return Result.str().str(); - } - - // Get the ID for the global, assigning a new one if we haven't got one - // already. - unsigned &ID = AnonGlobalIDs[GV]; - if (ID == 0) ID = NextAnonGlobalID++; - - // Must mangle the global into a unique ID. - makeNameProper(Result, "__unnamed_" + utostr(ID) + Suffix, PrefixTy); - return Result.str().str(); -} - -/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix -/// and the specified name as the global variable name. GVName must not be -/// empty. -void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, - const Twine &GVName, ManglerPrefixTy PrefixTy) { - SmallString<256> TmpData; - StringRef Name = GVName.toStringRef(TmpData); - assert(!Name.empty() && "getNameWithPrefix requires non-empty name"); - - // If the global name is not led with \1, add the appropriate prefixes. - if (Name[0] != '\1') { - if (PrefixTy == Mangler::Private) - OutName.append(PrivatePrefix, PrivatePrefix+strlen(PrivatePrefix)); - else if (PrefixTy == Mangler::LinkerPrivate) - OutName.append(LinkerPrivatePrefix, - LinkerPrivatePrefix+strlen(LinkerPrivatePrefix)); - - if (Prefix[0] == 0) - ; // Common noop, no prefix. - else if (Prefix[1] == 0) - OutName.push_back(Prefix[0]); // Common, one character prefix. - else - OutName.append(Prefix, Prefix+strlen(Prefix)); // Arbitrary prefix. - } else { - Name = Name.substr(1); - } - - OutName.append(Name.begin(), Name.end()); -} - - -/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix -/// and the specified global variable's name. If the global variable doesn't -/// have a name, this fills in a unique name for the global. -void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, - const GlobalValue *GV, - bool isImplicitlyPrivate) { - // If this global has a name, handle it simply. - if (GV->hasName()) { - ManglerPrefixTy PrefixTy = Mangler::Default; - if (GV->hasPrivateLinkage() || isImplicitlyPrivate) - PrefixTy = Mangler::Private; - else if (GV->hasLinkerPrivateLinkage()) - PrefixTy = Mangler::LinkerPrivate; - - return getNameWithPrefix(OutName, GV->getName(), PrefixTy); - } - - // If the global variable doesn't have a name, return a unique name for the - // global based on a numbering. - - // Anonymous names always get prefixes. - if (GV->hasPrivateLinkage() || isImplicitlyPrivate) - OutName.append(PrivatePrefix, PrivatePrefix+strlen(PrivatePrefix)); - else if (GV->hasLinkerPrivateLinkage()) - OutName.append(LinkerPrivatePrefix, - LinkerPrivatePrefix+strlen(LinkerPrivatePrefix));; - OutName.append(Prefix, Prefix+strlen(Prefix)); - - // Get the ID for the global, assigning a new one if we haven't got one - // already. - unsigned &ID = AnonGlobalIDs[GV]; - if (ID == 0) ID = NextAnonGlobalID++; - - // Must mangle the global into a unique ID. - raw_svector_ostream(OutName) << "__unnamed_" << ID; -} - - -Mangler::Mangler(Module &M, const char *prefix, const char *privatePrefix, - const char *linkerPrivatePrefix) - : Prefix(prefix), PrivatePrefix(privatePrefix), - LinkerPrivatePrefix(linkerPrivatePrefix), UseQuotes(false), - SymbolsCanStartWithDigit(false), NextAnonGlobalID(1) { - std::fill(AcceptableChars, array_endof(AcceptableChars), 0); - - // Letters and numbers are acceptable. - for (unsigned char X = 'a'; X <= 'z'; ++X) - markCharAcceptable(X); - for (unsigned char X = 'A'; X <= 'Z'; ++X) - markCharAcceptable(X); - for (unsigned char X = '0'; X <= '9'; ++X) - markCharAcceptable(X); - - // These chars are acceptable. - markCharAcceptable('_'); - markCharAcceptable('$'); - markCharAcceptable('.'); - markCharAcceptable('@'); -} diff --git a/lib/VMCore/Metadata.cpp b/lib/VMCore/Metadata.cpp index 7988b44..ee8e713 100644 --- a/lib/VMCore/Metadata.cpp +++ b/lib/VMCore/Metadata.cpp @@ -28,7 +28,7 @@ using namespace llvm; // MDString::MDString(LLVMContext &C, StringRef S) - : MetadataBase(Type::getMetadataTy(C), Value::MDStringVal), Str(S) {} + : Value(Type::getMetadataTy(C), Value::MDStringVal), Str(S) {} MDString *MDString::get(LLVMContext &Context, StringRef Str) { LLVMContextImpl *pImpl = Context.pImpl; @@ -93,7 +93,7 @@ static MDNodeOperand *getOperandPtr(MDNode *N, unsigned Op) { MDNode::MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, bool isFunctionLocal) -: MetadataBase(Type::getMetadataTy(C), Value::MDNodeVal) { +: Value(Type::getMetadataTy(C), Value::MDNodeVal) { NumOperands = NumVals; if (isFunctionLocal) @@ -121,67 +121,60 @@ MDNode::~MDNode() { Op->~MDNodeOperand(); } -#ifndef NDEBUG -static Function *assertLocalFunction(const MDNode *N, - SmallPtrSet<const MDNode *, 32> &Visited) { - Function *F = NULL; - // Only visit each MDNode once. - if (!Visited.insert(N)) return F; - - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { - Value *V = N->getOperand(i); - Function *NewF = NULL; - if (!V) continue; - if (Instruction *I = dyn_cast<Instruction>(V)) - NewF = I->getParent()->getParent(); - else if (BasicBlock *BB = dyn_cast<BasicBlock>(V)) - NewF = BB->getParent(); - else if (Argument *A = dyn_cast<Argument>(V)) - NewF = A->getParent(); - else if (MDNode *MD = dyn_cast<MDNode>(V)) - if (MD->isFunctionLocal()) - NewF = assertLocalFunction(MD, Visited); - if (F && NewF) assert(F == NewF && "inconsistent function-local metadata"); - if (!F) F = NewF; - } - return F; +static const Function *getFunctionForValue(Value *V) { + assert(!isa<MDNode>(V) && "does not iterate over metadata operands"); + if (!V) return NULL; + if (Instruction *I = dyn_cast<Instruction>(V)) + return I->getParent()->getParent(); + if (BasicBlock *BB = dyn_cast<BasicBlock>(V)) + return BB->getParent(); + if (Argument *A = dyn_cast<Argument>(V)) + return A->getParent(); + return NULL; } -#endif -static Function *getFunctionHelper(const MDNode *N, - SmallPtrSet<const MDNode *, 32> &Visited) { - assert(N->isFunctionLocal() && "Should only be called on function-local MD"); #ifndef NDEBUG - return assertLocalFunction(N, Visited); -#endif - Function *F = NULL; - // Only visit each MDNode once. - if (!Visited.insert(N)) return F; - +static const Function *assertLocalFunction(const MDNode *N) { + if (!N->isFunctionLocal()) return 0; + + const Function *F = 0, *NewF = 0; for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { - Value *V = N->getOperand(i); - if (!V) continue; - if (Instruction *I = dyn_cast<Instruction>(V)) - F = I->getParent()->getParent(); - else if (BasicBlock *BB = dyn_cast<BasicBlock>(V)) - F = BB->getParent(); - else if (Argument *A = dyn_cast<Argument>(V)) - F = A->getParent(); - else if (MDNode *MD = dyn_cast<MDNode>(V)) - if (MD->isFunctionLocal()) - F = getFunctionHelper(MD, Visited); - if (F) break; + if (Value *V = N->getOperand(i)) { + if (MDNode *MD = dyn_cast<MDNode>(V)) + NewF = assertLocalFunction(MD); + else + NewF = getFunctionForValue(V); + } + if (F == 0) + F = NewF; + else + assert((NewF == 0 || F == NewF) &&"inconsistent function-local metadata"); } return F; } +#endif // getFunction - If this metadata is function-local and recursively has a // function-local operand, return the first such operand's parent function. -// Otherwise, return null. -Function *MDNode::getFunction() const { +// Otherwise, return null. getFunction() should not be used for performance- +// critical code because it recursively visits all the MDNode's operands. +const Function *MDNode::getFunction() const { +#ifndef NDEBUG + return assertLocalFunction(this); +#endif if (!isFunctionLocal()) return NULL; - SmallPtrSet<const MDNode *, 32> Visited; - return getFunctionHelper(this, Visited); + + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + if (Value *V = getOperand(i)) { + if (MDNode *MD = dyn_cast<MDNode>(V)) { + if (const Function *F = MD->getFunction()) + return F; + } else { + return getFunctionForValue(V); + } + } + } + return NULL; } // destroy - Delete this node. Only when there are no uses. diff --git a/lib/VMCore/Pass.cpp b/lib/VMCore/Pass.cpp index 39da8fb..45000f2 100644 --- a/lib/VMCore/Pass.cpp +++ b/lib/VMCore/Pass.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PassNameParser.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Atomic.h" #include "llvm/System/Mutex.h" @@ -394,6 +395,8 @@ void PassRegistrationListener::enumeratePasses() { getPassRegistrar()->EnumerateWith(this); } +PassNameParser::~PassNameParser() {} + //===----------------------------------------------------------------------===// // AnalysisUsage Class Implementation // diff --git a/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp index b37b2ae..0c0d64e 100644 --- a/lib/VMCore/PassManager.cpp +++ b/lib/VMCore/PassManager.cpp @@ -127,6 +127,9 @@ public: bool doFinalization(Module &M); bool doFinalization(Function &F); + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + virtual const char *getPassName() const { return "BasicBlock Pass Manager"; } @@ -169,7 +172,7 @@ private: public: static char ID; explicit FunctionPassManagerImpl(int Depth) : - Pass(&ID), PMDataManager(Depth), + Pass(PT_PassManager, &ID), PMDataManager(Depth), PMTopLevelManager(TLM_Function), wasRun(false) { } /// add - Add a pass to the queue of passes to run. This passes ownership of @@ -196,15 +199,17 @@ public: /// bool doFinalization(Module &M); + + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + /// Pass Manager itself does not invalidate any analysis info. void getAnalysisUsage(AnalysisUsage &Info) const { Info.setPreservesAll(); } inline void addTopLevelPass(Pass *P) { - - if (ImmutablePass *IP = dynamic_cast<ImmutablePass *> (P)) { - + if (ImmutablePass *IP = P->getAsImmutablePass()) { // P is a immutable pass and it will be managed by this // top level manager. Set up analysis resolver to connect them. AnalysisResolver *AR = new AnalysisResolver(*this); @@ -236,7 +241,7 @@ class MPPassManager : public Pass, public PMDataManager { public: static char ID; explicit MPPassManager(int Depth) : - Pass(&ID), PMDataManager(Depth) { } + Pass(PT_PassManager, &ID), PMDataManager(Depth) { } // Delete on the fly managers. virtual ~MPPassManager() { @@ -271,6 +276,9 @@ public: return "Module Pass Manager"; } + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + // Print passes managed by this manager void dumpPassStructure(unsigned Offset) { llvm::dbgs() << std::string(Offset*2, ' ') << "ModulePass Manager\n"; @@ -313,7 +321,8 @@ class PassManagerImpl : public Pass, public: static char ID; explicit PassManagerImpl(int Depth) : - Pass(&ID), PMDataManager(Depth), PMTopLevelManager(TLM_Pass) { } + Pass(PT_PassManager, &ID), PMDataManager(Depth), + PMTopLevelManager(TLM_Pass) { } /// add - Add a pass to the queue of passes to run. This passes ownership of /// the Pass to the PassManager. When the PassManager is destroyed, the pass @@ -333,8 +342,7 @@ public: } inline void addTopLevelPass(Pass *P) { - if (ImmutablePass *IP = dynamic_cast<ImmutablePass *> (P)) { - + if (ImmutablePass *IP = P->getAsImmutablePass()) { // P is a immutable pass and it will be managed by this // top level manager. Set up analysis resolver to connect them. AnalysisResolver *AR = new AnalysisResolver(*this); @@ -347,6 +355,9 @@ public: } } + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + MPPassManager *getContainedManager(unsigned N) { assert(N < PassManagers.size() && "Pass number out of range!"); MPPassManager *MP = static_cast<MPPassManager *>(PassManagers[N]); @@ -390,7 +401,7 @@ public: /// passStarted - This method creates a timer for the given pass if it doesn't /// already have one, and starts the timer. Timer *passStarted(Pass *P) { - if (dynamic_cast<PMDataManager *>(P)) + if (P->getAsPMDataManager()) return 0; sys::SmartScopedLock<true> Lock(*TimingInfoMutex); @@ -584,11 +595,11 @@ void PMTopLevelManager::dumpPasses() const { // Every class that derives from PMDataManager also derives from Pass // (sometimes indirectly), but there's no inheritance relationship - // between PMDataManager and Pass, so we have to dynamic_cast to get + // between PMDataManager and Pass, so we have to getAsPass to get // from a PMDataManager* to a Pass*. for (SmallVector<PMDataManager *, 8>::const_iterator I = PassManagers.begin(), E = PassManagers.end(); I != E; ++I) - dynamic_cast<Pass *>(*I)->dumpPassStructure(1); + (*I)->getAsPass()->dumpPassStructure(1); } void PMTopLevelManager::dumpArguments() const { @@ -670,7 +681,7 @@ bool PMDataManager::preserveHigherLevelAnalysis(Pass *P) { for (SmallVector<Pass *, 8>::iterator I = HigherLevelAnalysis.begin(), E = HigherLevelAnalysis.end(); I != E; ++I) { Pass *P1 = *I; - if (!dynamic_cast<ImmutablePass*>(P1) && + if (P1->getAsImmutablePass() == 0 && std::find(PreservedSet.begin(), PreservedSet.end(), P1->getPassInfo()) == PreservedSet.end()) @@ -713,8 +724,8 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) { for (std::map<AnalysisID, Pass*>::iterator I = AvailableAnalysis.begin(), E = AvailableAnalysis.end(); I != E; ) { std::map<AnalysisID, Pass*>::iterator Info = I++; - if (!dynamic_cast<ImmutablePass*>(Info->second) - && std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) == + if (Info->second->getAsImmutablePass() == 0 && + std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) == PreservedSet.end()) { // Remove this analysis if (PassDebugging >= Details) { @@ -737,7 +748,7 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) { I = InheritedAnalysis[Index]->begin(), E = InheritedAnalysis[Index]->end(); I != E; ) { std::map<AnalysisID, Pass *>::iterator Info = I++; - if (!dynamic_cast<ImmutablePass*>(Info->second) && + if (Info->second->getAsImmutablePass() == 0 && std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) == PreservedSet.end()) { // Remove this analysis @@ -854,12 +865,12 @@ void PMDataManager::add(Pass *P, bool ProcessAnalysis) { // Set P as P's last user until someone starts using P. // However, if P is a Pass Manager then it does not need // to record its last user. - if (!dynamic_cast<PMDataManager *>(P)) + if (P->getAsPMDataManager() == 0) LastUses.push_back(P); TPM->setLastUser(LastUses, P); if (!TransferLastUses.empty()) { - Pass *My_PM = dynamic_cast<Pass *>(this); + Pass *My_PM = getAsPass(); TPM->setLastUser(TransferLastUses, My_PM); TransferLastUses.clear(); } @@ -968,7 +979,7 @@ void PMDataManager::dumpLastUses(Pass *P, unsigned Offset) const{ void PMDataManager::dumpPassArguments() const { for (SmallVector<Pass *, 8>::const_iterator I = PassVector.begin(), E = PassVector.end(); I != E; ++I) { - if (PMDataManager *PMD = dynamic_cast<PMDataManager *>(*I)) + if (PMDataManager *PMD = (*I)->getAsPMDataManager()) PMD->dumpPassArguments(); else if (const PassInfo *PI = (*I)->getPassInfo()) @@ -1469,7 +1480,7 @@ Pass* MPPassManager::getOnTheFlyPass(Pass *MP, const PassInfo *PI, Function &F){ FPP->releaseMemoryOnTheFly(); FPP->run(F); - return (dynamic_cast<PMTopLevelManager *>(FPP))->findAnalysisPass(PI); + return ((PMTopLevelManager*)FPP)->findAnalysisPass(PI); } @@ -1586,7 +1597,7 @@ void PMStack::push(PMDataManager *PM) { void PMStack::dump() { for (std::deque<PMDataManager *>::iterator I = S.begin(), E = S.end(); I != E; ++I) - printf("%s ", dynamic_cast<Pass *>(*I)->getPassName()); + printf("%s ", (*I)->getAsPass()->getPassName()); if (!S.empty()) printf("\n"); @@ -1616,16 +1627,18 @@ void FunctionPass::assignPassManager(PMStack &PMS, PassManagerType PreferredType) { // Find Module Pass Manager - while(!PMS.empty()) { + while (!PMS.empty()) { if (PMS.top()->getPassManagerType() > PMT_FunctionPassManager) PMS.pop(); else break; } - FPPassManager *FPP = dynamic_cast<FPPassManager *>(PMS.top()); - // Create new Function Pass Manager - if (!FPP) { + // Create new Function Pass Manager if needed. + FPPassManager *FPP; + if (PMS.top()->getPassManagerType() == PMT_FunctionPassManager) { + FPP = (FPPassManager *)PMS.top(); + } else { assert(!PMS.empty() && "Unable to create Function Pass Manager"); PMDataManager *PMD = PMS.top(); @@ -1653,17 +1666,16 @@ void FunctionPass::assignPassManager(PMStack &PMS, /// in the PM Stack and add self into that manager. void BasicBlockPass::assignPassManager(PMStack &PMS, PassManagerType PreferredType) { - BBPassManager *BBP = NULL; + BBPassManager *BBP; // Basic Pass Manager is a leaf pass manager. It does not handle // any other pass manager. - if (!PMS.empty()) - BBP = dynamic_cast<BBPassManager *>(PMS.top()); - - // If leaf manager is not Basic Block Pass manager then create new - // basic Block Pass manager. - - if (!BBP) { + if (!PMS.empty() && + PMS.top()->getPassManagerType() == PMT_BasicBlockPassManager) { + BBP = (BBPassManager *)PMS.top(); + } else { + // If leaf manager is not Basic Block Pass manager then create new + // basic Block Pass manager. assert(!PMS.empty() && "Unable to create BasicBlock Pass Manager"); PMDataManager *PMD = PMS.top(); diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index ec475e4..76d9d43 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -1301,6 +1301,8 @@ void Verifier::visitAllocaInst(AllocaInst &AI) { &AI); Assert1(PTy->getElementType()->isSized(), "Cannot allocate unsized type", &AI); + Assert1(AI.getArraySize()->getType()->isInteger(32), + "Alloca array size must be i32", &AI); visitInstruction(AI); } @@ -1579,7 +1581,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { // If the intrinsic takes MDNode arguments, verify that they are either global // or are local to *this* function. - for (unsigned i = 0, e = CI.getNumOperands(); i != e; ++i) + for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i) if (MDNode *MD = dyn_cast<MDNode>(CI.getOperand(i))) { if (!MD->isFunctionLocal()) continue; SmallPtrSet<MDNode *, 32> Visited; @@ -1589,12 +1591,17 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { switch (ID) { default: break; - case Intrinsic::dbg_declare: // llvm.dbg.declare - if (MDNode *MD = dyn_cast<MDNode>(CI.getOperand(1))) + case Intrinsic::dbg_declare: { // llvm.dbg.declare + Assert1(CI.getOperand(1) && isa<MDNode>(CI.getOperand(1)), + "invalid llvm.dbg.declare intrinsic call 1", &CI); + MDNode *MD = cast<MDNode>(CI.getOperand(1)); + Assert1(MD->getNumOperands() == 1, + "invalid llvm.dbg.declare intrinsic call 2", &CI); + if (MD->getOperand(0)) if (Constant *C = dyn_cast<Constant>(MD->getOperand(0))) Assert1(C && !isa<ConstantPointerNull>(C), - "invalid llvm.dbg.declare intrinsic call", &CI); - break; + "invalid llvm.dbg.declare intrinsic call 3", &CI); + } break; case Intrinsic::memcpy: case Intrinsic::memmove: case Intrinsic::memset: diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt index 78e12fd..1a286db 100644 --- a/projects/CMakeLists.txt +++ b/projects/CMakeLists.txt @@ -4,6 +4,8 @@ file(GLOB entries *) foreach(entry ${entries}) if(IS_DIRECTORY ${entry} AND EXISTS ${entry}/CMakeLists.txt) - add_subdirectory(${entry}) + if(NOT (${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/compiler-rt)) + add_subdirectory(${entry}) + endif() endif() endforeach(entry) diff --git a/projects/Makefile b/projects/Makefile index b966fc7..491d596 100644 --- a/projects/Makefile +++ b/projects/Makefile @@ -14,6 +14,9 @@ include $(LEVEL)/Makefile.config # Before 2008.06.24 it lived in llvm-test, so exclude that as well for now. DIRS:= $(filter-out llvm-test test-suite,$(patsubst $(PROJ_SRC_DIR)/%/Makefile,%,$(wildcard $(PROJ_SRC_DIR)/*/Makefile))) +# Don't build compiler-rt either, it isn't designed to be built directly. +DIRS := $(filter-out compiler-rt,$(DIRS)) + # Sparc cannot link shared libraries (libtool problem?) ifeq ($(ARCH), Sparc) DIRS := $(filter-out sample, $(DIRS)) diff --git a/test/Analysis/PostDominators/pr6047_a.ll b/test/Analysis/PostDominators/pr6047_a.ll new file mode 100644 index 0000000..ec1455b --- /dev/null +++ b/test/Analysis/PostDominators/pr6047_a.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -postdomtree -analyze | FileCheck %s +define internal void @f() { +entry: + br i1 undef, label %bb35, label %bb3.i + +bb3.i: + br label %bb3.i + +bb35.loopexit3: + br label %bb35 + +bb35: + ret void +} +; CHECK: [3] %entry diff --git a/test/Analysis/PostDominators/pr6047_b.ll b/test/Analysis/PostDominators/pr6047_b.ll new file mode 100644 index 0000000..7bd2c86 --- /dev/null +++ b/test/Analysis/PostDominators/pr6047_b.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -postdomtree -analyze | FileCheck %s +define internal void @f() { +entry: + br i1 undef, label %a, label %bb3.i + +a: + br i1 undef, label %bb35, label %bb3.i + +bb3.i: + br label %bb3.i + + +bb35.loopexit3: + br label %bb35 + +bb35: + ret void +} +; CHECK: [4] %entry diff --git a/test/Analysis/PostDominators/pr6047_c.ll b/test/Analysis/PostDominators/pr6047_c.ll new file mode 100644 index 0000000..08c9551 --- /dev/null +++ b/test/Analysis/PostDominators/pr6047_c.ll @@ -0,0 +1,147 @@ +; RUN: opt < %s -postdomtree -analyze | FileCheck %s +define internal void @f() { +entry: + br i1 undef, label %bb35, label %bb3.i + +bb3.i: + br label %bb3.i + +bb: + br label %bb35 + +bb.i: + br label %bb35 + +_float32_unpack.exit: + br label %bb35 + +bb.i5: + br label %bb35 + +_float32_unpack.exit8: + br label %bb35 + +bb32.preheader: + br label %bb35 + +bb3: + br label %bb35 + +bb3.split.us: + br label %bb35 + +bb.i4.us: + br label %bb35 + +bb7.i.us: + br label %bb35 + +bb.i4.us.backedge: + br label %bb35 + +bb1.i.us: + br label %bb35 + +bb6.i.us: + br label %bb35 + +bb4.i.us: + br label %bb35 + +bb8.i.us: + br label %bb35 + +bb3.i.loopexit.us: + br label %bb35 + +bb.nph21: + br label %bb35 + +bb4: + br label %bb35 + +bb5: + br label %bb35 + +bb14.preheader: + br label %bb35 + +bb.nph18: + br label %bb35 + +bb8.us.preheader: + br label %bb35 + +bb8.preheader: + br label %bb35 + +bb8.us: + br label %bb35 + +bb8: + br label %bb35 + +bb15.loopexit: + br label %bb35 + +bb15.loopexit2: + br label %bb35 + +bb15: + br label %bb35 + +bb16: + br label %bb35 + +bb17.loopexit.split: + br label %bb35 + +bb.nph14: + br label %bb35 + +bb19: + br label %bb35 + +bb20: + br label %bb35 + +bb29.preheader: + br label %bb35 + +bb.nph: + br label %bb35 + +bb23.us.preheader: + br label %bb35 + +bb23.preheader: + br label %bb35 + +bb23.us: + br label %bb35 + +bb23: + br label %bb35 + +bb30.loopexit: + br label %bb35 + +bb30.loopexit1: + br label %bb35 + +bb30: + br label %bb35 + +bb31: + br label %bb35 + +bb35.loopexit: + br label %bb35 + +bb35.loopexit3: + br label %bb35 + +bb35: + ret void +} +; CHECK: [3] %entry diff --git a/test/Analysis/PostDominators/pr6047_d.ll b/test/Analysis/PostDominators/pr6047_d.ll new file mode 100644 index 0000000..4cfa880 --- /dev/null +++ b/test/Analysis/PostDominators/pr6047_d.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -postdomtree -analyze | FileCheck %s +define internal void @f() { +entry: + br i1 1, label %a, label %b + +a: +br label %c + +b: +br label %c + +c: + br i1 undef, label %bb35, label %bb3.i + +bb3.i: + br label %bb3.i + +bb35.loopexit3: + br label %bb35 + +bb35: + ret void +} +; CHECK: [4] %entry diff --git a/test/Assembler/functionlocal-metadata.ll b/test/Assembler/functionlocal-metadata.ll index 8265aa1..16bc9d0 100644 --- a/test/Assembler/functionlocal-metadata.ll +++ b/test/Assembler/functionlocal-metadata.ll @@ -9,17 +9,24 @@ entry: call void @llvm.dbg.declare(metadata !{i32* %1}, metadata !{i32* %1}) ; CHECK: metadata !{i32* %1}, metadata !{i32* %1} call void @llvm.dbg.declare(metadata !{i32 %two}, metadata !{i32 %0}) +; CHECK: metadata !{i32 %two}, metadata !{i32 %0} call void @llvm.dbg.declare(metadata !{i32 %0}, metadata !{i32* %1, i32 %0}) +; CHECK: metadata !{i32 %0}, metadata !{i32* %1, i32 %0} call void @llvm.dbg.declare(metadata !{i32* %1}, metadata !{i32 %b, i32 %0}) +; CHECK: metadata !{i32* %1}, metadata !{i32 %b, i32 %0} call void @llvm.dbg.declare(metadata !{i32 %a}, metadata !{i32 %a, metadata !"foo"}) -; CHECK: metadata !{i32 %a, metadata !"foo"} +; CHECK: metadata !{i32 %a}, metadata !{i32 %a, metadata !"foo"} call void @llvm.dbg.declare(metadata !{i32 %b}, metadata !{metadata !0, i32 %two}) +; CHECK: metadata !{i32 %b}, metadata !{metadata !0, i32 %two} call void @llvm.dbg.value(metadata !{ i32 %a }, i64 0, metadata !1) +; CHECK: metadata !{i32 %a}, i64 0, metadata !1 call void @llvm.dbg.value(metadata !{ i32 %0 }, i64 25, metadata !0) +; CHECK: metadata !{i32 %0}, i64 25, metadata !0 call void @llvm.dbg.value(metadata !{ i32* %1 }, i64 16, metadata !"foo") ; CHECK: call void @llvm.dbg.value(metadata !{i32* %1}, i64 16, metadata !"foo") call void @llvm.dbg.value(metadata !"foo", i64 12, metadata !"bar") +; CHECK: metadata !"foo", i64 12, metadata !"bar" ret void, !foo !0, !bar !1 ; CHECK: ret void, !foo !0, !bar !1 diff --git a/test/CodeGen/ARM/ctz.ll b/test/CodeGen/ARM/ctz.ll new file mode 100644 index 0000000..1d2ced3 --- /dev/null +++ b/test/CodeGen/ARM/ctz.ll @@ -0,0 +1,11 @@ +; RUN: llc < %s -march=arm -mattr=+v6t2 | FileCheck %s + +declare i32 @llvm.cttz.i32(i32) + +define i32 @f1(i32 %a) { +; CHECK: f1: +; CHECK: rbit +; CHECK: clz + %tmp = call i32 @llvm.cttz.i32( i32 %a ) + ret i32 %tmp +} diff --git a/test/CodeGen/ARM/indirectbr.ll b/test/CodeGen/ARM/indirectbr.ll index cd16084..5135d03 100644 --- a/test/CodeGen/ARM/indirectbr.ll +++ b/test/CodeGen/ARM/indirectbr.ll @@ -12,6 +12,10 @@ define internal arm_apcscc i32 @foo(i32 %i) nounwind { entry: %0 = load i8** @nextaddr, align 4 ; <i8*> [#uses=2] %1 = icmp eq i8* %0, null ; <i1> [#uses=1] +; indirect branch gets duplicated here +; ARM: bx +; THUMB: mov pc, r1 +; THUMB2: mov pc, r1 br i1 %1, label %bb3, label %bb2 bb2: ; preds = %entry, %bb3 diff --git a/test/CodeGen/ARM/vbits.ll b/test/CodeGen/ARM/vbits.ll index e1d23a1..293d229 100644 --- a/test/CodeGen/ARM/vbits.ll +++ b/test/CodeGen/ARM/vbits.ll @@ -442,7 +442,7 @@ define <2 x i64> @v_ornQi64(<2 x i64>* %A, <2 x i64>* %B) nounwind { define <8 x i8> @vtsti8(<8 x i8>* %A, <8 x i8>* %B) nounwind { ;CHECK: vtsti8: -;CHECK: vtst.i8 +;CHECK: vtst.8 %tmp1 = load <8 x i8>* %A %tmp2 = load <8 x i8>* %B %tmp3 = and <8 x i8> %tmp1, %tmp2 @@ -453,7 +453,7 @@ define <8 x i8> @vtsti8(<8 x i8>* %A, <8 x i8>* %B) nounwind { define <4 x i16> @vtsti16(<4 x i16>* %A, <4 x i16>* %B) nounwind { ;CHECK: vtsti16: -;CHECK: vtst.i16 +;CHECK: vtst.16 %tmp1 = load <4 x i16>* %A %tmp2 = load <4 x i16>* %B %tmp3 = and <4 x i16> %tmp1, %tmp2 @@ -464,7 +464,7 @@ define <4 x i16> @vtsti16(<4 x i16>* %A, <4 x i16>* %B) nounwind { define <2 x i32> @vtsti32(<2 x i32>* %A, <2 x i32>* %B) nounwind { ;CHECK: vtsti32: -;CHECK: vtst.i32 +;CHECK: vtst.32 %tmp1 = load <2 x i32>* %A %tmp2 = load <2 x i32>* %B %tmp3 = and <2 x i32> %tmp1, %tmp2 @@ -475,7 +475,7 @@ define <2 x i32> @vtsti32(<2 x i32>* %A, <2 x i32>* %B) nounwind { define <16 x i8> @vtstQi8(<16 x i8>* %A, <16 x i8>* %B) nounwind { ;CHECK: vtstQi8: -;CHECK: vtst.i8 +;CHECK: vtst.8 %tmp1 = load <16 x i8>* %A %tmp2 = load <16 x i8>* %B %tmp3 = and <16 x i8> %tmp1, %tmp2 @@ -486,7 +486,7 @@ define <16 x i8> @vtstQi8(<16 x i8>* %A, <16 x i8>* %B) nounwind { define <8 x i16> @vtstQi16(<8 x i16>* %A, <8 x i16>* %B) nounwind { ;CHECK: vtstQi16: -;CHECK: vtst.i16 +;CHECK: vtst.16 %tmp1 = load <8 x i16>* %A %tmp2 = load <8 x i16>* %B %tmp3 = and <8 x i16> %tmp1, %tmp2 @@ -497,7 +497,7 @@ define <8 x i16> @vtstQi16(<8 x i16>* %A, <8 x i16>* %B) nounwind { define <4 x i32> @vtstQi32(<4 x i32>* %A, <4 x i32>* %B) nounwind { ;CHECK: vtstQi32: -;CHECK: vtst.i32 +;CHECK: vtst.32 %tmp1 = load <4 x i32>* %A %tmp2 = load <4 x i32>* %B %tmp3 = and <4 x i32> %tmp1, %tmp2 diff --git a/test/CodeGen/CellSPU/call_indirect.ll b/test/CodeGen/CellSPU/call_indirect.ll index f25d6b5..08dad74 100644 --- a/test/CodeGen/CellSPU/call_indirect.ll +++ b/test/CodeGen/CellSPU/call_indirect.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -march=cellspu > %t1.s -; RUN: llc < %s -march=cellspu -mattr=large_mem > %t2.s +; RUN: llc < %s -march=cellspu -asm-verbose=0 > %t1.s +; RUN: llc < %s -march=cellspu -mattr=large_mem -asm-verbose=0 > %t2.s ; RUN: grep bisl %t1.s | count 7 ; RUN: grep ila %t1.s | count 1 ; RUN: grep rotqby %t1.s | count 5 diff --git a/test/CodeGen/Generic/GC/frame_size.ll b/test/CodeGen/Generic/GC/frame_size.ll deleted file mode 100644 index 31783cd..0000000 --- a/test/CodeGen/Generic/GC/frame_size.ll +++ /dev/null @@ -1,14 +0,0 @@ -; RUN: llc < %s -asm-verbose | grep {frame size} | grep -v 0x0 - -declare void @llvm.gcroot(i8** %value, i8* %tag) -declare void @g() gc "ocaml" - -define void @f(i8* %arg.0, void()* %arg.1) gc "ocaml" { -entry: - %gcroot.0 = alloca i8* - call void @llvm.gcroot(i8** %gcroot.0, i8* null) - store i8* %arg.0, i8** %gcroot.0 - call void @g() - call void %arg.1() - ret void -} diff --git a/test/CodeGen/MSP430/bit.ll b/test/CodeGen/MSP430/bit.ll index 0dc2158..cd664a1 100644 --- a/test/CodeGen/MSP430/bit.ll +++ b/test/CodeGen/MSP430/bit.ll @@ -1,5 +1,4 @@ ; RUN: llvm-as < %s | llc -march=msp430 | FileCheck %s -; XFAIL: * target datalayout = "e-p:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:16:32" target triple = "msp430-generic-generic" diff --git a/test/CodeGen/MSP430/setcc.ll b/test/CodeGen/MSP430/setcc.ll index ecf0661..9db51cc 100644 --- a/test/CodeGen/MSP430/setcc.ll +++ b/test/CodeGen/MSP430/setcc.ll @@ -1,5 +1,4 @@ ; RUN: llc -march=msp430 < %s | FileCheck %s -; XFAIL: * target datalayout = "e-p:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:16:32" target triple = "msp430-generic-generic" @@ -32,7 +31,7 @@ define i16 @sccwne(i16 %a, i16 %b) nounwind { ret i16 %t2 } ; CHECK:sccwne: -; CHECK: cmp.w r15, r14 +; CHECK: cmp.w r14, r15 ; CHECK-NEXT: mov.w r2, r15 ; CHECK-NEXT: rra.w r15 ; CHECK-NEXT: and.w #1, r15 @@ -43,7 +42,7 @@ define i16 @sccweq(i16 %a, i16 %b) nounwind { ret i16 %t2 } ; CHECK:sccweq: -; CHECK: cmp.w r15, r14 +; CHECK: cmp.w r14, r15 ; CHECK-NEXT: mov.w r2, r15 ; CHECK-NEXT: rra.w r15 ; CHECK-NEXT: and.w #1, r15 @@ -55,7 +54,7 @@ define i16 @sccwugt(i16 %a, i16 %b) nounwind { ret i16 %t2 } ; CHECK:sccwugt: -; CHECK: cmp.w r14, r15 +; CHECK: cmp.w r15, r14 ; CHECK-NEXT: mov.w r2, r15 ; CHECK-NEXT: and.w #1, r15 ; CHECK-NEXT: xor.w #1, r15 @@ -66,7 +65,7 @@ define i16 @sccwuge(i16 %a, i16 %b) nounwind { ret i16 %t2 } ; CHECK:sccwuge: -; CHECK: cmp.w r15, r14 +; CHECK: cmp.w r14, r15 ; CHECK-NEXT: mov.w r2, r15 ; CHECK-NEXT: and.w #1, r15 @@ -76,7 +75,7 @@ define i16 @sccwult(i16 %a, i16 %b) nounwind { ret i16 %t2 } ; CHECK:sccwult: -; CHECK: cmp.w r15, r14 +; CHECK: cmp.w r14, r15 ; CHECK-NEXT: mov.w r2, r15 ; CHECK-NEXT: and.w #1, r15 ; CHECK-NEXT: xor.w #1, r15 @@ -87,7 +86,7 @@ define i16 @sccwule(i16 %a, i16 %b) nounwind { ret i16 %t2 } ; CHECK:sccwule: -; CHECK: cmp.w r14, r15 +; CHECK: cmp.w r15, r14 ; CHECK-NEXT: mov.w r2, r15 ; CHECK-NEXT: and.w #1, r15 diff --git a/test/CodeGen/PIC16/globals.ll b/test/CodeGen/PIC16/globals.ll index b8c9116..432c291 100644 --- a/test/CodeGen/PIC16/globals.ll +++ b/test/CodeGen/PIC16/globals.ll @@ -2,7 +2,8 @@ @G1 = global i32 4712, section "Address=412" ; CHECK: @G1.412..user_section.# IDATA 412 -; CHECK: @G1 dl 4712 +; CHECK: @G1 +; CHECK: dl 4712 @G2 = global i32 0, section "Address=412" ; CHECK: @G2.412..user_section.# UDATA 412 @@ -10,6 +11,7 @@ @G3 = addrspace(1) constant i32 4712, section "Address=412" ; CHECK: @G3.412..user_section.# ROMDATA 412 -; CHECK: @G3 rom_dl 4712 +; CHECK: @G3 +; CHECK: rom_dl 4712 diff --git a/test/CodeGen/PowerPC/2008-12-12-EH.ll b/test/CodeGen/PowerPC/2008-12-12-EH.ll index b56c22a..2315e36 100644 --- a/test/CodeGen/PowerPC/2008-12-12-EH.ll +++ b/test/CodeGen/PowerPC/2008-12-12-EH.ll @@ -1,4 +1,3 @@ -; RUN: llc < %s -march=ppc32 -mtriple=powerpc-unknown-linux-gnu | grep ^.L_Z1fv.eh ; RUN: llc < %s -march=ppc32 -mtriple=powerpc-apple-darwin9 | grep ^__Z1fv.eh define void @_Z1fv() { diff --git a/test/CodeGen/PowerPC/sections.ll b/test/CodeGen/PowerPC/sections.ll index 1af3709..0ff4a89 100644 --- a/test/CodeGen/PowerPC/sections.ll +++ b/test/CodeGen/PowerPC/sections.ll @@ -4,5 +4,5 @@ @A = global i32 0 ; CHECK: .section .bss,"aw",@nobits -; CHECK: .global A +; CHECK: .globl A diff --git a/test/CodeGen/PowerPC/stubs.ll b/test/CodeGen/PowerPC/stubs.ll new file mode 100644 index 0000000..4889263 --- /dev/null +++ b/test/CodeGen/PowerPC/stubs.ll @@ -0,0 +1,22 @@ +; RUN: llc %s -o - -mtriple=powerpc-apple-darwin8 | FileCheck %s +define ppc_fp128 @test1(i64 %X) nounwind readnone { +entry: + %0 = sitofp i64 %X to ppc_fp128 + ret ppc_fp128 %0 +} + +; CHECK: _test1: +; CHECK: bl ___floatditf$stub +; CHECK: .section __TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16 +; CHECK: ___floatditf$stub: +; CHECK: .indirect_symbol ___floatditf +; CHECK: lis r11,ha16(___floatditf$lazy_ptr) +; CHECK: lwzu r12,lo16(___floatditf$lazy_ptr)(r11) +; CHECK: mtctr r12 +; CHECK: bctr +; CHECK: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers +; CHECK: ___floatditf$lazy_ptr: +; CHECK: .indirect_symbol ___floatditf +; CHECK: .long dyld_stub_binding_helper + + diff --git a/test/CodeGen/Thumb/2009-12-17-pre-regalloc-taildup.ll b/test/CodeGen/Thumb/2009-12-17-pre-regalloc-taildup.ll index 3401915..2a5d9d6 100644 --- a/test/CodeGen/Thumb/2009-12-17-pre-regalloc-taildup.ll +++ b/test/CodeGen/Thumb/2009-12-17-pre-regalloc-taildup.ll @@ -1,4 +1,4 @@ -; RUN: llc -O3 -pre-regalloc-taildup < %s | FileCheck %s +; RUN: llc -O3 < %s | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" target triple = "thumbv7-apple-darwin10" diff --git a/test/CodeGen/Thumb/2010-01-15-local-alloc-spill-physical.ll b/test/CodeGen/Thumb/2010-01-15-local-alloc-spill-physical.ll new file mode 100644 index 0000000..d676369 --- /dev/null +++ b/test/CodeGen/Thumb/2010-01-15-local-alloc-spill-physical.ll @@ -0,0 +1,20 @@ +; RUN: llc < %s -regalloc=local -relocation-model=pic | FileCheck %s + +target triple = "thumbv6-apple-darwin10" + +@fred = internal global i32 0 ; <i32*> [#uses=1] + +define arm_apcscc void @foo() nounwind { +entry: +; CHECK: str r0, [sp] + %0 = call arm_apcscc i32 (...)* @bar() nounwind ; <i32> [#uses=1] +; CHECK: blx _bar +; CHECK: ldr r1, [sp] + store i32 %0, i32* @fred, align 4 + br label %return + +return: ; preds = %entry + ret void +} + +declare arm_apcscc i32 @bar(...) diff --git a/test/CodeGen/Thumb2/2010-01-06-TailDuplicateLabels.ll b/test/CodeGen/Thumb2/2010-01-06-TailDuplicateLabels.ll index 6a05df1..07a3527 100644 --- a/test/CodeGen/Thumb2/2010-01-06-TailDuplicateLabels.ll +++ b/test/CodeGen/Thumb2/2010-01-06-TailDuplicateLabels.ll @@ -1,4 +1,4 @@ -; RUN: llc -relocation-model=pic -pre-regalloc-taildup < %s | grep {:$} | sort | uniq -d | count 0 +; RUN: llc -relocation-model=pic < %s | grep {:$} | sort | uniq -d | count 0 target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" target triple = "thumbv7-apple-darwin10" diff --git a/test/CodeGen/Thumb2/2010-01-19-RemovePredicates.ll b/test/CodeGen/Thumb2/2010-01-19-RemovePredicates.ll new file mode 100644 index 0000000..41682c1 --- /dev/null +++ b/test/CodeGen/Thumb2/2010-01-19-RemovePredicates.ll @@ -0,0 +1,53 @@ +; RUN: llc -O3 -relocation-model=pic -mcpu=cortex-a8 -mattr=+thumb2 < %s +; +; This test creates a predicated t2ADDri instruction that is then turned into a t2MOVgpr2gpr instr. +; Test that that the predicate operands are removed properly. +; +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" +target triple = "thumbv7-apple-darwin10" + +declare arm_apcscc void @etoe53(i16* nocapture, i16* nocapture) nounwind + +define arm_apcscc void @earith(double* nocapture %value, i32 %icode, double* nocapture %r1, double* nocapture %r2) nounwind { +entry: + %v = alloca [6 x i16], align 4 ; <[6 x i16]*> [#uses=1] + br i1 undef, label %bb2.i, label %bb5 + +bb2.i: ; preds = %entry + %0 = bitcast double* %value to i16* ; <i16*> [#uses=1] + call arm_apcscc void @etoe53(i16* null, i16* %0) nounwind + ret void + +bb5: ; preds = %entry + switch i32 %icode, label %bb10 [ + i32 57, label %bb14 + i32 58, label %bb18 + i32 67, label %bb22 + i32 76, label %bb26 + i32 77, label %bb35 + ] + +bb10: ; preds = %bb5 + br label %bb46 + +bb14: ; preds = %bb5 + unreachable + +bb18: ; preds = %bb5 + unreachable + +bb22: ; preds = %bb5 + unreachable + +bb26: ; preds = %bb5 + br label %bb46 + +bb35: ; preds = %bb5 + unreachable + +bb46: ; preds = %bb26, %bb10 + %1 = bitcast double* %value to i16* ; <i16*> [#uses=1] + %v47 = getelementptr inbounds [6 x i16]* %v, i32 0, i32 0 ; <i16*> [#uses=1] + call arm_apcscc void @etoe53(i16* %v47, i16* %1) nounwind + ret void +} diff --git a/test/CodeGen/X86/2007-08-13-SpillerReuse.ll b/test/CodeGen/X86/2007-08-13-SpillerReuse.ll deleted file mode 100644 index d6ea510..0000000 --- a/test/CodeGen/X86/2007-08-13-SpillerReuse.ll +++ /dev/null @@ -1,102 +0,0 @@ -; RUN: llc < %s -mtriple=i686-apple-darwin | grep "48(%esp)" | count 5 - - %struct..0anon = type { i32 } - %struct.rtvec_def = type { i32, [1 x %struct..0anon] } - %struct.rtx_def = type { i16, i8, i8, [1 x %struct..0anon] } -@rtx_format = external global [116 x i8*] ; <[116 x i8*]*> [#uses=1] -@rtx_length = external global [117 x i32] ; <[117 x i32]*> [#uses=1] - -declare %struct.rtx_def* @fixup_memory_subreg(%struct.rtx_def*, %struct.rtx_def*, i32) - -define %struct.rtx_def* @walk_fixup_memory_subreg(%struct.rtx_def* %x, %struct.rtx_def* %insn) { -entry: - %tmp2 = icmp eq %struct.rtx_def* %x, null ; <i1> [#uses=1] - br i1 %tmp2, label %UnifiedReturnBlock, label %cond_next - -cond_next: ; preds = %entry - %tmp6 = getelementptr %struct.rtx_def* %x, i32 0, i32 0 ; <i16*> [#uses=1] - %tmp7 = load i16* %tmp6 ; <i16> [#uses=2] - %tmp78 = zext i16 %tmp7 to i32 ; <i32> [#uses=2] - %tmp10 = icmp eq i16 %tmp7, 54 ; <i1> [#uses=1] - br i1 %tmp10, label %cond_true13, label %cond_next32 - -cond_true13: ; preds = %cond_next - %tmp15 = getelementptr %struct.rtx_def* %x, i32 0, i32 3 ; <[1 x %struct..0anon]*> [#uses=1] - %tmp1718 = bitcast [1 x %struct..0anon]* %tmp15 to %struct.rtx_def** ; <%struct.rtx_def**> [#uses=1] - %tmp19 = load %struct.rtx_def** %tmp1718 ; <%struct.rtx_def*> [#uses=1] - %tmp20 = getelementptr %struct.rtx_def* %tmp19, i32 0, i32 0 ; <i16*> [#uses=1] - %tmp21 = load i16* %tmp20 ; <i16> [#uses=1] - %tmp22 = icmp eq i16 %tmp21, 57 ; <i1> [#uses=1] - br i1 %tmp22, label %cond_true25, label %cond_next32 - -cond_true25: ; preds = %cond_true13 - %tmp29 = tail call %struct.rtx_def* @fixup_memory_subreg( %struct.rtx_def* %x, %struct.rtx_def* %insn, i32 1 ) ; <%struct.rtx_def*> [#uses=1] - ret %struct.rtx_def* %tmp29 - -cond_next32: ; preds = %cond_true13, %cond_next - %tmp34 = getelementptr [116 x i8*]* @rtx_format, i32 0, i32 %tmp78 ; <i8**> [#uses=1] - %tmp35 = load i8** %tmp34, align 4 ; <i8*> [#uses=1] - %tmp37 = getelementptr [117 x i32]* @rtx_length, i32 0, i32 %tmp78 ; <i32*> [#uses=1] - %tmp38 = load i32* %tmp37, align 4 ; <i32> [#uses=1] - %i.011 = add i32 %tmp38, -1 ; <i32> [#uses=2] - %tmp12513 = icmp sgt i32 %i.011, -1 ; <i1> [#uses=1] - br i1 %tmp12513, label %bb, label %UnifiedReturnBlock - -bb: ; preds = %bb123, %cond_next32 - %indvar = phi i32 [ %indvar.next26, %bb123 ], [ 0, %cond_next32 ] ; <i32> [#uses=2] - %i.01.0 = sub i32 %i.011, %indvar ; <i32> [#uses=5] - %tmp42 = getelementptr i8* %tmp35, i32 %i.01.0 ; <i8*> [#uses=2] - %tmp43 = load i8* %tmp42 ; <i8> [#uses=1] - switch i8 %tmp43, label %bb123 [ - i8 101, label %cond_true47 - i8 69, label %bb105.preheader - ] - -cond_true47: ; preds = %bb - %tmp52 = getelementptr %struct.rtx_def* %x, i32 0, i32 3, i32 %i.01.0 ; <%struct..0anon*> [#uses=1] - %tmp5354 = bitcast %struct..0anon* %tmp52 to %struct.rtx_def** ; <%struct.rtx_def**> [#uses=1] - %tmp55 = load %struct.rtx_def** %tmp5354 ; <%struct.rtx_def*> [#uses=1] - %tmp58 = tail call %struct.rtx_def* @walk_fixup_memory_subreg( %struct.rtx_def* %tmp55, %struct.rtx_def* %insn ) ; <%struct.rtx_def*> [#uses=1] - %tmp62 = getelementptr %struct.rtx_def* %x, i32 0, i32 3, i32 %i.01.0, i32 0 ; <i32*> [#uses=1] - %tmp58.c = ptrtoint %struct.rtx_def* %tmp58 to i32 ; <i32> [#uses=1] - store i32 %tmp58.c, i32* %tmp62 - %tmp6816 = load i8* %tmp42 ; <i8> [#uses=1] - %tmp6917 = icmp eq i8 %tmp6816, 69 ; <i1> [#uses=1] - br i1 %tmp6917, label %bb105.preheader, label %bb123 - -bb105.preheader: ; preds = %cond_true47, %bb - %tmp11020 = getelementptr %struct.rtx_def* %x, i32 0, i32 3, i32 %i.01.0 ; <%struct..0anon*> [#uses=1] - %tmp11111221 = bitcast %struct..0anon* %tmp11020 to %struct.rtvec_def** ; <%struct.rtvec_def**> [#uses=3] - %tmp11322 = load %struct.rtvec_def** %tmp11111221 ; <%struct.rtvec_def*> [#uses=1] - %tmp11423 = getelementptr %struct.rtvec_def* %tmp11322, i32 0, i32 0 ; <i32*> [#uses=1] - %tmp11524 = load i32* %tmp11423 ; <i32> [#uses=1] - %tmp11625 = icmp eq i32 %tmp11524, 0 ; <i1> [#uses=1] - br i1 %tmp11625, label %bb123, label %bb73 - -bb73: ; preds = %bb73, %bb105.preheader - %j.019 = phi i32 [ %tmp104, %bb73 ], [ 0, %bb105.preheader ] ; <i32> [#uses=3] - %tmp81 = load %struct.rtvec_def** %tmp11111221 ; <%struct.rtvec_def*> [#uses=2] - %tmp92 = getelementptr %struct.rtvec_def* %tmp81, i32 0, i32 1, i32 %j.019 ; <%struct..0anon*> [#uses=1] - %tmp9394 = bitcast %struct..0anon* %tmp92 to %struct.rtx_def** ; <%struct.rtx_def**> [#uses=1] - %tmp95 = load %struct.rtx_def** %tmp9394 ; <%struct.rtx_def*> [#uses=1] - %tmp98 = tail call %struct.rtx_def* @walk_fixup_memory_subreg( %struct.rtx_def* %tmp95, %struct.rtx_def* %insn ) ; <%struct.rtx_def*> [#uses=1] - %tmp101 = getelementptr %struct.rtvec_def* %tmp81, i32 0, i32 1, i32 %j.019, i32 0 ; <i32*> [#uses=1] - %tmp98.c = ptrtoint %struct.rtx_def* %tmp98 to i32 ; <i32> [#uses=1] - store i32 %tmp98.c, i32* %tmp101 - %tmp104 = add i32 %j.019, 1 ; <i32> [#uses=2] - %tmp113 = load %struct.rtvec_def** %tmp11111221 ; <%struct.rtvec_def*> [#uses=1] - %tmp114 = getelementptr %struct.rtvec_def* %tmp113, i32 0, i32 0 ; <i32*> [#uses=1] - %tmp115 = load i32* %tmp114 ; <i32> [#uses=1] - %tmp116 = icmp ult i32 %tmp104, %tmp115 ; <i1> [#uses=1] - br i1 %tmp116, label %bb73, label %bb123 - -bb123: ; preds = %bb73, %bb105.preheader, %cond_true47, %bb - %i.0 = add i32 %i.01.0, -1 ; <i32> [#uses=1] - %tmp125 = icmp sgt i32 %i.0, -1 ; <i1> [#uses=1] - %indvar.next26 = add i32 %indvar, 1 ; <i32> [#uses=1] - br i1 %tmp125, label %bb, label %UnifiedReturnBlock - -UnifiedReturnBlock: ; preds = %bb123, %cond_next32, %entry - %UnifiedRetVal = phi %struct.rtx_def* [ null, %entry ], [ %x, %cond_next32 ], [ %x, %bb123 ] ; <%struct.rtx_def*> [#uses=1] - ret %struct.rtx_def* %UnifiedRetVal -} diff --git a/test/CodeGen/X86/2008-04-02-unnamedEH.ll b/test/CodeGen/X86/2008-04-02-unnamedEH.ll index a9f368b..27bbbaa 100644 --- a/test/CodeGen/X86/2008-04-02-unnamedEH.ll +++ b/test/CodeGen/X86/2008-04-02-unnamedEH.ll @@ -1,26 +1,16 @@ -; RUN: llc < %s | grep unnamed_1.eh +; RUN: llc < %s | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin8" define void @_Z3bazv() { - call i32 @0( ) ; <i32>:1 [#uses=0] - br label %2 -; <label>:2 ; preds = %0 + call void @0( ) ; <i32>:1 [#uses=0] ret void } -define internal i32 @""() { - alloca i32 ; <i32*>:1 [#uses=2] - alloca i32 ; <i32*>:2 [#uses=2] - bitcast i32 0 to i32 ; <i32>:3 [#uses=0] +define internal void @""() { call i32 @_Z3barv( ) ; <i32>:4 [#uses=1] - store i32 %4, i32* %2, align 4 - load i32* %2, align 4 ; <i32>:5 [#uses=1] - store i32 %5, i32* %1, align 4 - br label %6 -; <label>:6 ; preds = %0 - load i32* %1 ; <i32>:7 [#uses=1] - ret i32 %7 + ret void } +; CHECK: unnamed_1.eh declare i32 @_Z3barv() diff --git a/test/CodeGen/X86/2008-09-18-inline-asm-2.ll b/test/CodeGen/X86/2008-09-18-inline-asm-2.ll index f5bd307..e3b6fdf 100644 --- a/test/CodeGen/X86/2008-09-18-inline-asm-2.ll +++ b/test/CodeGen/X86/2008-09-18-inline-asm-2.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -march=x86 | grep "#%ebp %edi %esi 8(%edx) %eax (%ebx)" -; RUN: llc < %s -march=x86 -regalloc=local | grep "#%edi %edx %ebp 8(%ebx) %eax (%esi)" +; RUN: llc < %s -march=x86 | grep "#%ebp %esi %edi 8(%edx) %eax (%ebx)" +; RUN: llc < %s -march=x86 -regalloc=local | grep "#%edi %ebp %edx 8(%ebx) %eax (%esi)" ; The 1st, 2nd, 3rd and 5th registers above must all be different. The registers ; referenced in the 4th and 6th operands must not be the same as the 1st or 5th ; operand. There are many combinations that work; this is what llc puts out now. diff --git a/test/CodeGen/X86/2008-12-19-EarlyClobberBug.ll b/test/CodeGen/X86/2008-12-19-EarlyClobberBug.ll index 13a9080..a6cabc4 100644 --- a/test/CodeGen/X86/2008-12-19-EarlyClobberBug.ll +++ b/test/CodeGen/X86/2008-12-19-EarlyClobberBug.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mtriple=i386-apple-darwin | FileCheck %s +; RUN: llc < %s -mtriple=i386-apple-darwin -asm-verbose=0 | FileCheck %s ; PR3149 ; Make sure the copy after inline asm is not coalesced away. diff --git a/test/CodeGen/X86/2009-02-04-sext-i64-gep.ll b/test/CodeGen/X86/2009-02-04-sext-i64-gep.ll index 6ba046a..4880f62 100644 --- a/test/CodeGen/X86/2009-02-04-sext-i64-gep.ll +++ b/test/CodeGen/X86/2009-02-04-sext-i64-gep.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s | grep { - 92} +; RUN: llc < %s | grep p-92 ; PR3481 ; The offset should print as -92, not +17179869092 diff --git a/test/CodeGen/X86/2009-09-10-SpillComments.ll b/test/CodeGen/X86/2009-09-10-SpillComments.ll index 1dd9990..f9ca861 100644 --- a/test/CodeGen/X86/2009-09-10-SpillComments.ll +++ b/test/CodeGen/X86/2009-09-10-SpillComments.ll @@ -1,5 +1,11 @@ ; RUN: llc < %s -mtriple=x86_64-unknown-linux | FileCheck %s +; This test shouldn't require spills. + +; CHECK: subq $8, %rsp +; CHECK-NOT: $rsp +; CHECK: addq $8, %rsp + %struct..0anon = type { i32 } %struct.rtvec_def = type { i32, [1 x %struct..0anon] } %struct.rtx_def = type { i16, i8, i8, [1 x %struct..0anon] } @@ -10,9 +16,6 @@ declare %struct.rtx_def* @fixup_memory_subreg(%struct.rtx_def*, %struct.rtx_def* define %struct.rtx_def* @walk_fixup_memory_subreg(%struct.rtx_def* %x, %struct.rtx_def* %insn) { entry: -; CHECK: Spill -; CHECK: Folded Spill -; CHECK: Reload %tmp2 = icmp eq %struct.rtx_def* %x, null ; <i1> [#uses=1] br i1 %tmp2, label %UnifiedReturnBlock, label %cond_next diff --git a/test/CodeGen/X86/2010-01-15-SelectionDAGCycle.ll b/test/CodeGen/X86/2010-01-15-SelectionDAGCycle.ll new file mode 100644 index 0000000..5d96e4a --- /dev/null +++ b/test/CodeGen/X86/2010-01-15-SelectionDAGCycle.ll @@ -0,0 +1,28 @@ +; RUN: llc < %s -march=x86-64 +; ModuleID = 'bugpoint-reduced-simplified.bc' +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" +target triple = "x86_64-unknown-linux-gnu" + +define void @numvec_(i32* noalias %ncelet, i32* noalias %ncel, i32* noalias %nfac, i32* noalias %nfabor, i32* noalias %lregis, i32* noalias %irveci, i32* noalias %irvecb, [0 x [2 x i32]]* noalias %ifacel, [0 x i32]* noalias %ifabor, [0 x i32]* noalias %inumfi, [0 x i32]* noalias %inumfb, [1 x i32]* noalias %iworkf, [0 x i32]* noalias %ismbs) { +"file bug754399.f90, line 1, bb1": + %r1037 = bitcast <2 x double> zeroinitializer to <4 x i32> ; <<4 x i32>> [#uses=1] + br label %"file bug754399.f90, line 184, in inner vector loop at depth 0, bb164" + +"file bug754399.f90, line 184, in inner vector loop at depth 0, bb164": ; preds = %"file bug754399.f90, line 184, in inner vector loop at depth 0, bb164", %"file bug754399.f90, line 1, bb1" + %tmp641 = add i64 0, 48 ; <i64> [#uses=1] + %tmp641642 = inttoptr i64 %tmp641 to <4 x i32>* ; <<4 x i32>*> [#uses=1] + %r1258 = load <4 x i32>* %tmp641642, align 4 ; <<4 x i32>> [#uses=2] + %r1295 = extractelement <4 x i32> %r1258, i32 3 ; <i32> [#uses=1] + %r1296 = sext i32 %r1295 to i64 ; <i64> [#uses=1] + %r1297 = add i64 %r1296, -1 ; <i64> [#uses=1] + %r1298183 = getelementptr [0 x i32]* %ismbs, i64 0, i64 %r1297 ; <i32*> [#uses=1] + %r1298184 = load i32* %r1298183, align 4 ; <i32> [#uses=1] + %r1301 = extractelement <4 x i32> %r1037, i32 3 ; <i32> [#uses=1] + %r1302 = mul i32 %r1298184, %r1301 ; <i32> [#uses=1] + %r1306 = insertelement <4 x i32> zeroinitializer, i32 %r1302, i32 3 ; <<4 x i32>> [#uses=1] + %r1321 = add <4 x i32> %r1306, %r1258 ; <<4 x i32>> [#uses=1] + %tmp643 = add i64 0, 48 ; <i64> [#uses=1] + %tmp643644 = inttoptr i64 %tmp643 to <4 x i32>* ; <<4 x i32>*> [#uses=1] + store <4 x i32> %r1321, <4 x i32>* %tmp643644, align 4 + br label %"file bug754399.f90, line 184, in inner vector loop at depth 0, bb164" +} diff --git a/test/CodeGen/X86/2010-01-19-OptExtBug.ll b/test/CodeGen/X86/2010-01-19-OptExtBug.ll new file mode 100644 index 0000000..cd8960b --- /dev/null +++ b/test/CodeGen/X86/2010-01-19-OptExtBug.ll @@ -0,0 +1,57 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin11 -relocation-model=pic -disable-fp-elim -stats |& not grep ext-opt + +define fastcc i8* @S_scan_str(i8* %start, i32 %keep_quoted, i32 %keep_delims) nounwind ssp { +entry: + switch i8 undef, label %bb6 [ + i8 9, label %bb5 + i8 32, label %bb5 + i8 10, label %bb5 + i8 13, label %bb5 + i8 12, label %bb5 + ] + +bb5: ; preds = %entry, %entry, %entry, %entry, %entry + br label %bb6 + +bb6: ; preds = %bb5, %entry + br i1 undef, label %bb7, label %bb9 + +bb7: ; preds = %bb6 + unreachable + +bb9: ; preds = %bb6 + %0 = load i8* undef, align 1 ; <i8> [#uses=3] + br i1 undef, label %bb12, label %bb10 + +bb10: ; preds = %bb9 + br i1 undef, label %bb12, label %bb11 + +bb11: ; preds = %bb10 + unreachable + +bb12: ; preds = %bb10, %bb9 + br i1 undef, label %bb13, label %bb14 + +bb13: ; preds = %bb12 + store i8 %0, i8* undef, align 1 + %1 = zext i8 %0 to i32 ; <i32> [#uses=1] + br label %bb18 + +bb14: ; preds = %bb12 + br label %bb18 + +bb18: ; preds = %bb14, %bb13 + %termcode.0 = phi i32 [ %1, %bb13 ], [ undef, %bb14 ] ; <i32> [#uses=2] + %2 = icmp eq i8 %0, 0 ; <i1> [#uses=1] + br i1 %2, label %bb21, label %bb19 + +bb19: ; preds = %bb18 + br i1 undef, label %bb21, label %bb20 + +bb20: ; preds = %bb19 + br label %bb21 + +bb21: ; preds = %bb20, %bb19, %bb18 + %termcode.1 = phi i32 [ %termcode.0, %bb18 ], [ %termcode.0, %bb19 ], [ undef, %bb20 ] ; <i32> [#uses=0] + unreachable +} diff --git a/test/CodeGen/X86/bigstructret2.ll b/test/CodeGen/X86/bigstructret2.ll new file mode 100644 index 0000000..46e0fd2 --- /dev/null +++ b/test/CodeGen/X86/bigstructret2.ll @@ -0,0 +1,12 @@ +; RUN: llc < %s -march=x86 -o %t + +%0 = type { i64, i64 } + +declare fastcc %0 @ReturnBigStruct() nounwind readnone + +define void @test(%0* %p) { + %1 = call fastcc %0 @ReturnBigStruct() + store %0 %1, %0* %p + ret void +} + diff --git a/test/CodeGen/X86/bss_pagealigned.ll b/test/CodeGen/X86/bss_pagealigned.ll index 27c5361..da95aca 100644 --- a/test/CodeGen/X86/bss_pagealigned.ll +++ b/test/CodeGen/X86/bss_pagealigned.ll @@ -1,4 +1,4 @@ -; RUN: llc --code-model=kernel -march=x86-64 <%s | FileCheck %s +; RUN: llc --code-model=kernel -march=x86-64 <%s -asm-verbose=0 | FileCheck %s ; PR4933 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" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/CodeGen/X86/full-lsr.ll b/test/CodeGen/X86/full-lsr.ll index 68575bc..3bd58b6 100644 --- a/test/CodeGen/X86/full-lsr.ll +++ b/test/CodeGen/X86/full-lsr.ll @@ -1,6 +1,12 @@ -; RUN: llc < %s -march=x86 -enable-full-lsr >%t -; RUN: grep {addl \\\$4,} %t | count 3 -; RUN: not grep {,%} %t +; RUN: llc < %s -march=x86 >%t + +; TODO: Enhance full lsr mode to get this: +; RUNX: grep {addl \\\$4,} %t | count 3 +; RUNX: not grep {,%} %t + +; For now, it should find this, which is still pretty good: +; RUN: not grep {addl \\\$4,} %t +; RUN: grep {,%} %t | count 6 define void @foo(float* nocapture %A, float* nocapture %B, float* nocapture %C, i32 %N) nounwind { entry: diff --git a/test/CodeGen/X86/global-sections.ll b/test/CodeGen/X86/global-sections.ll index 38948a7..1a7b577 100644 --- a/test/CodeGen/X86/global-sections.ll +++ b/test/CodeGen/X86/global-sections.ll @@ -6,7 +6,6 @@ @G1 = common global i32 0 ; LINUX: .type G1,@object -; LINUX: .section .gnu.linkonce.b.G1,"aw",@nobits ; LINUX: .comm G1,4,4 ; DARWIN: .comm _G1,4,2 @@ -76,14 +75,14 @@ ; LINUX: .section .gnu.linkonce.r.G6,"a",@progbits ; LINUX: .weak G6 ; LINUX: G6: -; LINUX: .ascii "\001" +; LINUX: .byte 1 ; LINUX: .size G6, 1 ; DARWIN: .section __TEXT,__const_coal,coalesced ; DARWIN: .globl _G6 ; DARWIN: .weak_definition _G6 ; DARWIN:_G6: -; DARWIN: .ascii "\001" +; DARWIN: .byte 1 @G7 = constant [10 x i8] c"abcdefghi\00" @@ -120,4 +119,19 @@ ; LINUX:G9 +@G10 = weak global [100 x i32] zeroinitializer, align 32 ; <[100 x i32]*> [#uses=0] + + +; DARWIN: .section __DATA,__datacoal_nt,coalesced +; DARWIN: .globl _G10 +; DARWIN: .weak_definition _G10 +; DARWIN: .align 5 +; DARWIN: _G10: +; DARWIN: .space 400 + +; LINUX: .bss +; LINUX: .weak G10 +; LINUX: .align 32 +; LINUX: G10: +; LINUX: .zero 400 diff --git a/test/CodeGen/X86/i128-and-beyond.ll b/test/CodeGen/X86/i128-and-beyond.ll index 907a6b8..b741681 100644 --- a/test/CodeGen/X86/i128-and-beyond.ll +++ b/test/CodeGen/X86/i128-and-beyond.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=x86 -mtriple=i686-pc-linux-gnu | grep 18446744073709551615 | count 14 +; RUN: llc < %s -march=x86 -mtriple=i686-pc-linux-gnu | grep -- -1 | count 14 ; These static initializers are too big to hand off to assemblers ; as monolithic blobs. diff --git a/test/CodeGen/X86/illegal-asm.ll b/test/CodeGen/X86/illegal-asm.ll deleted file mode 100644 index 43128dc..0000000 --- a/test/CodeGen/X86/illegal-asm.ll +++ /dev/null @@ -1,34 +0,0 @@ -; RUN: llc < %s -mtriple=i386-apple-darwin -disable-fp-elim -; RUN: llc < %s -mtriple=i386-linux -disable-fp-elim -; XFAIL: * -; Expected to run out of registers during allocation. -; PR3864 -; rdar://6251720 - - %struct.CABACContext = type { i32, i32, i8* } - %struct.H264Context = type { %struct.CABACContext, [460 x i8] } -@coeff_abs_level_m1_offset = common global [6 x i32] zeroinitializer ; <[6 x i32]*> [#uses=1] -@coeff_abs_level1_ctx = common global [8 x i8] zeroinitializer ; <[8 x i8]*> [#uses=1] - -define i32 @decode_cabac_residual(%struct.H264Context* %h, i32 %cat) nounwind { -entry: - %0 = getelementptr [6 x i32]* @coeff_abs_level_m1_offset, i32 0, i32 %cat ; <i32*> [#uses=1] - %1 = load i32* %0, align 4 ; <i32> [#uses=1] - %2 = load i8* getelementptr ([8 x i8]* @coeff_abs_level1_ctx, i32 0, i32 0), align 1 ; <i8> [#uses=1] - %3 = zext i8 %2 to i32 ; <i32> [#uses=1] - %.sum = add i32 %3, %1 ; <i32> [#uses=1] - %4 = getelementptr %struct.H264Context* %h, i32 0, i32 1, i32 %.sum ; <i8*> [#uses=2] - %5 = getelementptr %struct.H264Context* %h, i32 0, i32 0, i32 0 ; <i32*> [#uses=2] - %6 = getelementptr %struct.H264Context* %h, i32 0, i32 0, i32 1 ; <i32*> [#uses=2] - %7 = getelementptr %struct.H264Context* %h, i32 0, i32 0, i32 2 ; <i8**> [#uses=2] - %8 = load i32* %5, align 4 ; <i32> [#uses=1] - %9 = load i32* %6, align 4 ; <i32> [#uses=1] - %10 = load i8* %4, align 4 ; <i8> [#uses=1] - %asmtmp = tail call { i32, i32, i32, i32 } asm sideeffect "#$0 $1 $2 $3 $4 $5", "=&{di},=r,=r,=*m,=&q,=*imr,1,2,*m,5,~{dirflag},~{fpsr},~{flags},~{cx}"(i8** %7, i8* %4, i32 %8, i32 %9, i8** %7, i8 %10) nounwind ; <{ i32, i32, i32, i32 }> [#uses=3] - %asmresult = extractvalue { i32, i32, i32, i32 } %asmtmp, 0 ; <i32> [#uses=1] - %asmresult1 = extractvalue { i32, i32, i32, i32 } %asmtmp, 1 ; <i32> [#uses=1] - store i32 %asmresult1, i32* %5 - %asmresult2 = extractvalue { i32, i32, i32, i32 } %asmtmp, 2 ; <i32> [#uses=1] - store i32 %asmresult2, i32* %6 - ret i32 %asmresult -} diff --git a/test/CodeGen/X86/loop-hoist.ll b/test/CodeGen/X86/loop-hoist.ll index b52066d..b9008e5 100644 --- a/test/CodeGen/X86/loop-hoist.ll +++ b/test/CodeGen/X86/loop-hoist.ll @@ -4,7 +4,7 @@ ; CHECK: _foo: ; CHECK: L_Arr$non_lazy_ptr -; CHECK: LBB1_1: ## %cond_true +; CHECK: LBB1_1: @Arr = external global [0 x i32] ; <[0 x i32]*> [#uses=1] diff --git a/test/CodeGen/X86/loop-strength-reduce4.ll b/test/CodeGen/X86/loop-strength-reduce4.ll index 87b606f..07e46ec 100644 --- a/test/CodeGen/X86/loop-strength-reduce4.ll +++ b/test/CodeGen/X86/loop-strength-reduce4.ll @@ -4,7 +4,7 @@ @state = external global [0 x i32] ; <[0 x i32]*> [#uses=4] @S = external global [0 x i32] ; <[0 x i32]*> [#uses=4] -define i32 @foo() { +define i32 @foo() nounwind { entry: br label %bb diff --git a/test/CodeGen/X86/neg-shl-add.ll b/test/CodeGen/X86/neg-shl-add.ll new file mode 100644 index 0000000..7aebc38 --- /dev/null +++ b/test/CodeGen/X86/neg-shl-add.ll @@ -0,0 +1,17 @@ +; RUN: llc -march=x86-64 < %s | not grep negq + +; These sequences don't need neg instructions; they can be done with +; a single shift and sub each. + +define i64 @foo(i64 %x, i64 %y, i64 %n) nounwind { + %a = sub i64 0, %y + %b = shl i64 %a, %n + %c = add i64 %b, %x + ret i64 %c +} +define i64 @boo(i64 %x, i64 %y, i64 %n) nounwind { + %a = sub i64 0, %y + %b = shl i64 %a, %n + %c = add i64 %x, %b + ret i64 %c +} diff --git a/test/CodeGen/X86/pr3495-2.ll b/test/CodeGen/X86/pr3495-2.ll index 1372a15..71aa5a0 100644 --- a/test/CodeGen/X86/pr3495-2.ll +++ b/test/CodeGen/X86/pr3495-2.ll @@ -1,5 +1,6 @@ ; RUN: llc < %s -march=x86 -relocation-model=pic -disable-fp-elim -stats |& grep {Number of reloads omited} +target datalayout = "e-p:32:32:32" target triple = "i386-apple-darwin9.6" %struct.constraintVCGType = type { i32, i32, i32, i32 } %struct.nodeVCGType = type { %struct.constraintVCGType*, i32, i32, i32, %struct.constraintVCGType*, i32, i32, i32 } diff --git a/test/CodeGen/X86/pr3495.ll b/test/CodeGen/X86/pr3495.ll index 4b62bf4..1795970 100644 --- a/test/CodeGen/X86/pr3495.ll +++ b/test/CodeGen/X86/pr3495.ll @@ -1,6 +1,6 @@ -; RUN: llc < %s -march=x86 -stats |& grep {Number of reloads omited} | grep 1 -; RUN: llc < %s -march=x86 -stats |& grep {Number of available reloads turned into copies} | grep 1 -; RUN: llc < %s -march=x86 -stats |& grep {Number of machine instrs printed} | grep 40 +; RUN: llc < %s -march=x86 -stats |& grep {Number of loads added} | grep 2 +; RUN: llc < %s -march=x86 -stats |& grep {Number of register spills} | grep 1 +; RUN: llc < %s -march=x86 -stats |& grep {Number of machine instrs printed} | grep 38 ; PR3495 ; The loop reversal kicks in once here, resulting in one fewer instruction. diff --git a/test/CodeGen/X86/ptrtoint-constexpr.ll b/test/CodeGen/X86/ptrtoint-constexpr.ll index 72a428e..7e33e79 100644 --- a/test/CodeGen/X86/ptrtoint-constexpr.ll +++ b/test/CodeGen/X86/ptrtoint-constexpr.ll @@ -3,6 +3,6 @@ ; CHECK: .globl r ; CHECK: r: -; CHECK: .quad ((r) & 4294967295) +; CHECK: .quad r&4294967295 @r = global %union.x { i64 ptrtoint (%union.x* @r to i64) }, align 4 diff --git a/test/CodeGen/X86/remat-mov-0.ll b/test/CodeGen/X86/remat-mov-0.ll index c4f768c..5fb445c 100644 --- a/test/CodeGen/X86/remat-mov-0.ll +++ b/test/CodeGen/X86/remat-mov-0.ll @@ -1,13 +1,33 @@ -; RUN: llc < %s -march=x86-64 | grep {xorl %edi, %edi} | count 4 +; RUN: llc < %s -march=x86-64 | FileCheck %s ; CodeGen should remat the zero instead of spilling it. declare void @foo(i64 %p) +; CHECK: bar: +; CHECK: xorl %edi, %edi +; CHECK: xorl %edi, %edi define void @bar() nounwind { call void @foo(i64 0) call void @foo(i64 0) - call void @foo(i64 0) - call void @foo(i64 0) ret void } + +; CHECK: bat: +; CHECK: movq $-1, %rdi +; CHECK: movq $-1, %rdi +define void @bat() nounwind { + call void @foo(i64 -1) + call void @foo(i64 -1) + ret void +} + +; CHECK: bau: +; CHECK: movl $1, %edi +; CHECK: movl $1, %edi +define void @bau() nounwind { + call void @foo(i64 1) + call void @foo(i64 1) + ret void +} + diff --git a/test/CodeGen/X86/remat-mov-1.ll b/test/CodeGen/X86/remat-mov-1.ll deleted file mode 100644 index d71b7a5..0000000 --- a/test/CodeGen/X86/remat-mov-1.ll +++ /dev/null @@ -1,40 +0,0 @@ -; RUN: llc < %s -march=x86 | grep -- -1 | grep mov | count 2 - - %struct.FILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 } - %struct.ImgT = type { i8, i8*, i8*, %struct.FILE*, i32, i32, i32, i32, i8*, double*, float*, float*, float*, i32*, double, double, i32*, double*, i32*, i32* } - %struct._CompT = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, float, float, i8, %struct._PixT*, %struct._CompT*, i8, %struct._CompT* } - %struct._PixT = type { i32, i32, %struct._PixT* } - %struct.__sFILEX = type opaque - %struct.__sbuf = type { i8*, i32 } - -declare fastcc void @MergeComponents(%struct._CompT*, %struct._CompT*, %struct._CompT*, %struct._CompT**, %struct.ImgT*) nounwind - -define fastcc void @MergeToLeft(%struct._CompT* %comp, %struct._CompT** %head, %struct.ImgT* %img) nounwind { -entry: - br label %bb208 - -bb105: ; preds = %bb200 - br i1 false, label %bb197, label %bb149 - -bb149: ; preds = %bb105 - %tmp151 = getelementptr %struct._CompT* %comp, i32 0, i32 0 ; <i32*> [#uses=1] - br label %bb193 - -bb193: ; preds = %bb184, %bb149 - %tmp196 = load i32* %tmp151, align 4 ; <i32> [#uses=1] - br label %bb197 - -bb197: ; preds = %bb193, %bb105 - %last_comp.0 = phi i32 [ %tmp196, %bb193 ], [ 0, %bb105 ] ; <i32> [#uses=0] - %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1] - br label %bb200 - -bb200: ; preds = %bb208, %bb197 - %indvar = phi i32 [ 0, %bb208 ], [ %indvar.next, %bb197 ] ; <i32> [#uses=2] - %xm.0 = sub i32 %indvar, 0 ; <i32> [#uses=1] - %tmp202 = icmp slt i32 %xm.0, 1 ; <i1> [#uses=1] - br i1 %tmp202, label %bb105, label %bb208 - -bb208: ; preds = %bb200, %entry - br label %bb200 -} diff --git a/test/CodeGen/X86/remat-scalar-zero.ll b/test/CodeGen/X86/remat-scalar-zero.ll index 790ae83..2da96ab 100644 --- a/test/CodeGen/X86/remat-scalar-zero.ll +++ b/test/CodeGen/X86/remat-scalar-zero.ll @@ -1,7 +1,7 @@ ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu > %t ; RUN: not grep xor %t ; RUN: not grep movap %t -; RUN: grep {\\.zero} %t +; RUN: grep {\\.quad.*0} %t ; Remat should be able to fold the zero constant into the div instructions ; as a constant-pool load. diff --git a/test/CodeGen/X86/splat-scalar-load.ll b/test/CodeGen/X86/splat-scalar-load.ll index 32d3ab6..2b13029 100644 --- a/test/CodeGen/X86/splat-scalar-load.ll +++ b/test/CodeGen/X86/splat-scalar-load.ll @@ -1,21 +1,6 @@ ; RUN: llc < %s -mtriple=i386-apple-darwin -mattr=+sse2 | FileCheck %s ; rdar://7434544 -define <2 x i64> @t1() nounwind ssp { -entry: -; CHECK: t1: -; CHECK: pshufd $0, (%esp), %xmm0 - %array = alloca [8 x float], align 16 - %arrayidx = getelementptr inbounds [8 x float]* %array, i32 0, i32 0 - %tmp2 = load float* %arrayidx - %vecinit = insertelement <4 x float> undef, float %tmp2, i32 0 - %vecinit5 = insertelement <4 x float> %vecinit, float %tmp2, i32 1 - %vecinit7 = insertelement <4 x float> %vecinit5, float %tmp2, i32 2 - %vecinit9 = insertelement <4 x float> %vecinit7, float %tmp2, i32 3 - %0 = bitcast <4 x float> %vecinit9 to <2 x i64> - ret <2 x i64> %0 -} - define <2 x i64> @t2() nounwind ssp { entry: ; CHECK: t2: @@ -30,14 +15,3 @@ entry: %0 = bitcast <4 x float> %vecinit9 to <2 x i64> ret <2 x i64> %0 } - -define <4 x float> @t3(float %tmp1, float %tmp2, float %tmp3) nounwind readnone ssp { -entry: -; CHECK: t3: -; CHECK: pshufd $-86, (%esp), %xmm0 - %0 = insertelement <4 x float> undef, float %tmp3, i32 0 - %1 = insertelement <4 x float> %0, float %tmp3, i32 1 - %2 = insertelement <4 x float> %1, float %tmp3, i32 2 - %3 = insertelement <4 x float> %2, float %tmp3, i32 3 - ret <4 x float> %3 -} diff --git a/test/CodeGen/X86/stride-reuse.ll b/test/CodeGen/X86/stride-reuse.ll index a99a9c9..5cbd895 100644 --- a/test/CodeGen/X86/stride-reuse.ll +++ b/test/CodeGen/X86/stride-reuse.ll @@ -5,7 +5,7 @@ @A = external global [1000 x float], align 32 @P = external global [1000 x i32], align 32 -define void @foo(i32 %m) { +define void @foo(i32 %m) nounwind { entry: %tmp1 = icmp sgt i32 %m, 0 br i1 %tmp1, label %bb, label %return diff --git a/test/CodeGen/X86/subreg-to-reg-5.ll b/test/CodeGen/X86/subreg-to-reg-5.ll deleted file mode 100644 index ba4c307..0000000 --- a/test/CodeGen/X86/subreg-to-reg-5.ll +++ /dev/null @@ -1,35 +0,0 @@ -; RUN: llc < %s -march=x86-64 > %t -; RUN: grep addl %t -; RUN: not egrep {movl|movq} %t - -define float @foo(float* %B) nounwind { -entry: - br label %bb2 - -bb2: ; preds = %bb3, %entry - %B_addr.0.rec = phi i64 [ %indvar.next154, %bb3 ], [ 0, %entry ] ; <i64> [#uses=2] - %z = icmp slt i64 %B_addr.0.rec, 20000 - br i1 %z, label %bb3, label %bb4 - -bb3: ; preds = %bb2 - %indvar.next154 = add i64 %B_addr.0.rec, 1 ; <i64> [#uses=1] - br label %bb2 - -bb4: ; preds = %bb2 - %B_addr.0 = getelementptr float* %B, i64 %B_addr.0.rec ; <float*> [#uses=1] - %t1 = ptrtoint float* %B_addr.0 to i64 ; <i64> [#uses=1] - %t2 = and i64 %t1, 4294967295 ; <i64> [#uses=1] - %t3 = icmp eq i64 %t2, 0 ; <i1> [#uses=1] - br i1 %t3, label %bb5, label %bb10.preheader - -bb10.preheader: ; preds = %bb4 - br label %bb9 - -bb5: ; preds = %bb4 - ret float 7.0 - -bb9: ; preds = %bb10.preheader - %t5 = getelementptr float* %B, i64 0 ; <float*> [#uses=1] - %t7 = load float* %t5 ; <float> [#uses=1] - ret float %t7 -} diff --git a/test/CodeGen/X86/tail-opts.ll b/test/CodeGen/X86/tail-opts.ll index c5dbb04..7b21e1b 100644 --- a/test/CodeGen/X86/tail-opts.ll +++ b/test/CodeGen/X86/tail-opts.ll @@ -109,15 +109,15 @@ altret: ; CHECK: dont_merge_oddly: ; CHECK-NOT: ret -; CHECK: ucomiss %xmm0, %xmm1 +; CHECK: ucomiss %xmm1, %xmm2 ; CHECK-NEXT: jbe .LBB3_3 -; CHECK-NEXT: ucomiss %xmm2, %xmm0 +; CHECK-NEXT: ucomiss %xmm0, %xmm1 ; CHECK-NEXT: ja .LBB3_4 ; CHECK-NEXT: .LBB3_2: ; CHECK-NEXT: movb $1, %al ; CHECK-NEXT: ret ; CHECK-NEXT: .LBB3_3: -; CHECK-NEXT: ucomiss %xmm2, %xmm1 +; CHECK-NEXT: ucomiss %xmm0, %xmm2 ; CHECK-NEXT: jbe .LBB3_2 ; CHECK-NEXT: .LBB3_4: ; CHECK-NEXT: xorb %al, %al diff --git a/test/CodeGen/X86/unaligned-load.ll b/test/CodeGen/X86/unaligned-load.ll index 7778983..b61803d 100644 --- a/test/CodeGen/X86/unaligned-load.ll +++ b/test/CodeGen/X86/unaligned-load.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin10.0 -relocation-model=dynamic-no-pic | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-apple-darwin10.0 -relocation-model=dynamic-no-pic --asm-verbose=0 | FileCheck %s @.str1 = internal constant [31 x i8] c"DHRYSTONE PROGRAM, SOME STRING\00", align 8 @.str3 = internal constant [31 x i8] c"DHRYSTONE PROGRAM, 2'ND STRING\00", align 8 @@ -23,5 +23,5 @@ declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind ; CHECK: .align 3 ; CHECK-NEXT: _.str1: ; CHECK-NEXT: .asciz "DHRYSTONE PROGRAM, SOME STRING" -; CHECK-NEXT: .align 3 +; CHECK: .align 3 ; CHECK-NEXT: _.str3: diff --git a/test/CodeGen/X86/xor.ll b/test/CodeGen/X86/xor.ll index 7bd06bb..9bfff8a 100644 --- a/test/CodeGen/X86/xor.ll +++ b/test/CodeGen/X86/xor.ll @@ -131,3 +131,14 @@ bb12: ; X32: andl {{.*}}[[REG]] } +define i32 @test8(i32 %a) nounwind { +; rdar://7553032 +entry: + %t1 = sub i32 0, %a + %t2 = add i32 %t1, -1 + ret i32 %t2 +; X64: test8: +; X64: notl %eax +; X32: test8: +; X32: notl %eax +} diff --git a/test/DebugInfo/2010-01-19-DbgScope.ll b/test/DebugInfo/2010-01-19-DbgScope.ll new file mode 100644 index 0000000..7afb5a5 --- /dev/null +++ b/test/DebugInfo/2010-01-19-DbgScope.ll @@ -0,0 +1,28 @@ +; RUN: llc -O0 < %s -o /dev/null +; Ignore unreachable scopes. +declare void @foo(i32) noreturn + +define i32 @bar() nounwind ssp { +entry: + br i1 undef, label %bb, label %bb11, !dbg !0 + +bb: ; preds = %entry + call void @foo(i32 0) noreturn nounwind, !dbg !7 + unreachable, !dbg !7 + +bb11: ; preds = %entry + ret i32 1, !dbg !11 +} + +!0 = metadata !{i32 8647, i32 0, metadata !1, null} +!1 = metadata !{i32 458763, metadata !2} ; [ DW_TAG_lexical_block ] +!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"bar", metadata !"bar", metadata !"bar", metadata !3, i32 8639, metadata !4, i1 true, i1 true, i32 0, i32 0, null} ; [ DW_TAG_subprogram ] +!3 = metadata !{i32 458769, i32 0, i32 1, metadata !"c-parser.c", metadata !"llvmgcc", metadata !"LLVM build 00", i1 true, i1 false, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] +!4 = metadata !{i32 458773, metadata !3, metadata !"", metadata !3, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !5, i32 0} ; [ DW_TAG_subroutine_type ] +!5 = metadata !{metadata !6} +!6 = metadata !{i32 458788, metadata !3, metadata !"char", metadata !3, i32 0, i64 8, i64 8, i64 0, i32 0, i32 6} ; [ DW_TAG_base_type ] +!7 = metadata !{i32 8648, i32 0, metadata !8, null} +!8 = metadata !{i32 458763, metadata !9} ; [ DW_TAG_lexical_block ] +!9 = metadata !{i32 458763, metadata !10} ; [ DW_TAG_lexical_block ] +!10 = metadata !{i32 458798, i32 0, metadata !3, metadata !"bar2", metadata !"bar2", metadata !"bar2", metadata !3, i32 8639, metadata !4, i1 true, i1 true, i32 0, i32 0, null} ; [ DW_TAG_subprogram ] +!11 = metadata !{i32 8652, i32 0, metadata !1, null} diff --git a/test/FrontendC/2010-01-18-Inlined-Debug.c b/test/FrontendC/2010-01-18-Inlined-Debug.c new file mode 100644 index 0000000..4aec7b2 --- /dev/null +++ b/test/FrontendC/2010-01-18-Inlined-Debug.c @@ -0,0 +1,12 @@ +// PR: 6058 +// RUN: %llvmgcc -g -S %s -o - | llc -O0 -o /dev/null + +static inline int foo(double) __attribute__ ((always_inline)); +static inline int foo(double __x) { return __x; } + +void bar(double x) { + foo(x); +} + + + diff --git a/test/FrontendC/pr5406.c b/test/FrontendC/pr5406.c new file mode 100644 index 0000000..c873e51 --- /dev/null +++ b/test/FrontendC/pr5406.c @@ -0,0 +1,20 @@ +// RUN: %llvmgcc %s -S -emit-llvm -O0 -o - | FileCheck %s +// PR 5406 + +// XFAIL: * +// XTARGET: arm + +typedef struct { char x[3]; } A0; +void foo (int i, ...); + + +// CHECK: call arm_aapcscc void (i32, ...)* @foo(i32 1, i32 {{.*}}) nounwind +int main (void) +{ + A0 a3; + a3.x[0] = 0; + a3.x[0] = 0; + a3.x[2] = 26; + foo (1, a3 ); + return 0; +} diff --git a/test/MC/AsmParser/X86/x86_instructions.s b/test/MC/AsmParser/X86/x86_instructions.s index 4c5b698..ed806ee 100644 --- a/test/MC/AsmParser/X86/x86_instructions.s +++ b/test/MC/AsmParser/X86/x86_instructions.s @@ -16,7 +16,9 @@ movl %eax, 10(%ebp, %ebx, 4) // CHECK: movl %eax, 10(,%ebx,4) movl %eax, 10(, %ebx, 4) - +// CHECK: ret + ret + // FIXME: Check that this matches SUB32ri8 // CHECK: subl $1, %eax subl $1, %eax diff --git a/test/MC/AsmParser/directive_ascii.s b/test/MC/AsmParser/directive_ascii.s index cc6d23b..5bfc1e9 100644 --- a/test/MC/AsmParser/directive_ascii.s +++ b/test/MC/AsmParser/directive_ascii.s @@ -23,27 +23,12 @@ TEST3: .asciz "B", "C" # CHECK: TEST4: -# CHECK: .byte 1 -# CHECK: .byte 1 -# CHECK: .byte 7 -# CHECK: .byte 0 -# CHECK: .byte 56 -# CHECK: .byte 1 -# CHECK: .byte 0 -# CHECK: .byte 49 -# CHECK: .byte 128 -# CHECK: .byte 0 +# CHECK: .asciz "\001\001\007\0008\001\0001\200" TEST4: .ascii "\1\01\07\08\001\0001\200\0" # CHECK: TEST5: -# CHECK: .byte 8 -# CHECK: .byte 12 -# CHECK: .byte 10 -# CHECK: .byte 13 -# CHECK: .byte 9 -# CHECK: .byte 92 -# CHECK: .byte 34 +# CHECK: .ascii "\b\f\n\r\t\\\"" TEST5: .ascii "\b\f\n\r\t\\\"" diff --git a/test/MC/AsmParser/directive_lcomm.s b/test/MC/AsmParser/directive_lcomm.s index d38805f..0a0add5 100644 --- a/test/MC/AsmParser/directive_lcomm.s +++ b/test/MC/AsmParser/directive_lcomm.s @@ -1,4 +1,4 @@ -# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s +# RUN: llvm-mc -triple i386-apple-darwin10 %s | FileCheck %s # CHECK: TEST0: # CHECK: .zerofill __DATA,__bss,a,7,4 diff --git a/test/MC/AsmParser/directive_space.s b/test/MC/AsmParser/directive_space.s index a897654..e6353a4 100644 --- a/test/MC/AsmParser/directive_space.s +++ b/test/MC/AsmParser/directive_space.s @@ -1,12 +1,11 @@ -# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s +# RUN: llvm-mc -triple i386-apple-darwin %s | FileCheck %s # CHECK: TEST0: -# CHECK: .byte 0 +# CHECK: .space 1 TEST0: .space 1 # CHECK: TEST1: -# CHECK: .byte 3 -# CHECK: .byte 3 +# CHECK: .space 2,3 TEST1: .space 2, 3 diff --git a/test/Transforms/ConstProp/constant-expr.ll b/test/Transforms/ConstProp/constant-expr.ll index eece37f..9963032 100644 --- a/test/Transforms/ConstProp/constant-expr.ll +++ b/test/Transforms/ConstProp/constant-expr.ll @@ -57,4 +57,11 @@ @T4 = global i1* inttoptr (i64 trunc (i256 lshr (i256 or (i256 and (i256 and (i256 shl (i256 zext (i64 ptrtoint (i1* @B to i64) to i256), i256 64), i256 -6277101735386680763495507056286727952638980837032266301441), i256 6277101735386680763835789423207666416102355444464034512895), i256 shl (i256 zext (i64 ptrtoint (i1* @A to i64) to i256), i256 192)), i256 64) to i64) to i1*) ; CHECK: @T5 = global i1* @A -@T5 = global i1* inttoptr (i64 add (i64 trunc (i256 lshr (i256 or (i256 and (i256 and (i256 shl (i256 zext (i64 ptrtoint (i1* @B to i64) to i256), i256 64), i256 -6277101735386680763495507056286727952638980837032266301441), i256 6277101735386680763835789423207666416102355444464034512895), i256 shl (i256 zext (i64 ptrtoint (i1* @A to i64) to i256), i256 192)), i256 192) to i64), i64 trunc (i256 lshr (i256 or (i256 and (i256 and (i256 shl (i256 zext (i64 ptrtoint (i1* @B to i64) to i256), i256 64), i256 -6277101735386680763495507056286727952638980837032266301441), i256 6277101735386680763835789423207666416102355444464034512895), i256 shl (i256 zext (i64 ptrtoint (i1* @A to i64) to i256), i256 192)), i256 128) to i64)) to i1*)
\ No newline at end of file +@T5 = global i1* inttoptr (i64 add (i64 trunc (i256 lshr (i256 or (i256 and (i256 and (i256 shl (i256 zext (i64 ptrtoint (i1* @B to i64) to i256), i256 64), i256 -6277101735386680763495507056286727952638980837032266301441), i256 6277101735386680763835789423207666416102355444464034512895), i256 shl (i256 zext (i64 ptrtoint (i1* @A to i64) to i256), i256 192)), i256 192) to i64), i64 trunc (i256 lshr (i256 or (i256 and (i256 and (i256 shl (i256 zext (i64 ptrtoint (i1* @B to i64) to i256), i256 64), i256 -6277101735386680763495507056286727952638980837032266301441), i256 6277101735386680763835789423207666416102355444464034512895), i256 shl (i256 zext (i64 ptrtoint (i1* @A to i64) to i256), i256 192)), i256 128) to i64)) to i1*) + + + +; PR6096 + +; No check line. This used to crash llvm-as. +@T6 = global <2 x i1> fcmp ole (<2 x float> fdiv (<2 x float> undef, <2 x float> <float 1.000000e+00, float 1.000000e+00>), <2 x float> zeroinitializer) diff --git a/test/Transforms/IndVarSimplify/gep-with-mul-base.ll b/test/Transforms/IndVarSimplify/gep-with-mul-base.ll index 7809594..19d54ff 100644 --- a/test/Transforms/IndVarSimplify/gep-with-mul-base.ll +++ b/test/Transforms/IndVarSimplify/gep-with-mul-base.ll @@ -1,6 +1,7 @@ ; RUN: opt < %s -indvars -S > %t -; RUN: grep add %t | count 8 -; RUN: grep mul %t | count 7 +; RUN: grep add %t | count 6 +; RUN: grep sub %t | count 2 +; RUN: grep mul %t | count 6 define void @foo(i64 %n, i64 %m, i64 %o, double* nocapture %p) nounwind { entry: diff --git a/test/Transforms/InstCombine/apint-elim-logicalops.ll b/test/Transforms/InstCombine/apint-elim-logicalops.ll deleted file mode 100644 index ec60e45..0000000 --- a/test/Transforms/InstCombine/apint-elim-logicalops.ll +++ /dev/null @@ -1,39 +0,0 @@ -; Test that elimination of logical operators works with -; arbitrary precision integers. -; RUN: opt < %s -instcombine -S | \ -; RUN: not grep {(and\|xor\|add\|shl\|shr)} -; END. - -define i33 @test1(i33 %x) { - %tmp.1 = and i33 %x, 65535 ; <i33> [#uses=1] - %tmp.2 = xor i33 %tmp.1, -32768 ; <i33> [#uses=1] - %tmp.3 = add i33 %tmp.2, 32768 ; <i33> [#uses=1] - ret i33 %tmp.3 -} - -define i33 @test2(i33 %x) { - %tmp.1 = and i33 %x, 65535 ; <i33> [#uses=1] - %tmp.2 = xor i33 %tmp.1, 32768 ; <i33> [#uses=1] - %tmp.3 = add i33 %tmp.2, -32768 ; <i33> [#uses=1] - ret i33 %tmp.3 -} - -define i33 @test3(i16 %P) { - %tmp.1 = zext i16 %P to i33 ; <i33> [#uses=1] - %tmp.4 = xor i33 %tmp.1, 32768 ; <i33> [#uses=1] - %tmp.5 = add i33 %tmp.4, -32768 ; <i33> [#uses=1] - ret i33 %tmp.5 -} - -define i33 @test5(i33 %x) { - %tmp.1 = and i33 %x, 254 - %tmp.2 = xor i33 %tmp.1, 128 - %tmp.3 = add i33 %tmp.2, -128 - ret i33 %tmp.3 -} - -define i33 @test6(i33 %x) { - %tmp.2 = shl i33 %x, 16 ; <i33> [#uses=1] - %tmp.4 = lshr i33 %tmp.2, 16 ; <i33> [#uses=1] - ret i33 %tmp.4 -} diff --git a/test/Transforms/InstCombine/bitcast-sext-vector.ll b/test/Transforms/InstCombine/bitcast-sext-vector.ll new file mode 100644 index 0000000..d70bdba --- /dev/null +++ b/test/Transforms/InstCombine/bitcast-sext-vector.ll @@ -0,0 +1,11 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; CHECK: sext +; Don't fold zero/sign extensions with a bitcast between a vector and scalar. + +define i32 @t(<4 x i8> %src1, <4 x i8> %src2) nounwind readonly { +entry: + %cmp = icmp eq <4 x i8> %src1, %src2; <<4 x i1>> [#uses=1] + %sext = sext <4 x i1> %cmp to <4 x i8> + %val = bitcast <4 x i8> %sext to i32 + ret i32 %val +} diff --git a/test/Transforms/InstCombine/canonicalize_branch.ll b/test/Transforms/InstCombine/canonicalize_branch.ll index 52aff3d..24090ab 100644 --- a/test/Transforms/InstCombine/canonicalize_branch.ll +++ b/test/Transforms/InstCombine/canonicalize_branch.ll @@ -1,36 +1,44 @@ -; RUN: opt < %s -instcombine -S | \ -; RUN: not grep {icmp ne\|icmp ule\|icmp uge} +; RUN: opt < %s -instcombine -S | FileCheck %s define i32 @test1(i32 %X, i32 %Y) { - %C = icmp ne i32 %X, %Y ; <i1> [#uses=1] + %C = icmp ne i32 %X, %Y br i1 %C, label %T, label %F -T: ; preds = %0 - ret i32 12 +; CHECK: @test1 +; CHECK: %C = icmp eq i32 %X, %Y +; CHECK: br i1 %C, label %F, label %T -F: ; preds = %0 +T: + ret i32 12 +F: ret i32 123 } define i32 @test2(i32 %X, i32 %Y) { - %C = icmp ule i32 %X, %Y ; <i1> [#uses=1] + %C = icmp ule i32 %X, %Y br i1 %C, label %T, label %F -T: ; preds = %0 - ret i32 12 +; CHECK: @test2 +; CHECK: %C = icmp ugt i32 %X, %Y +; CHECK: br i1 %C, label %F, label %T -F: ; preds = %0 +T: + ret i32 12 +F: ret i32 123 } define i32 @test3(i32 %X, i32 %Y) { - %C = icmp uge i32 %X, %Y ; <i1> [#uses=1] + %C = icmp uge i32 %X, %Y br i1 %C, label %T, label %F -T: ; preds = %0 - ret i32 12 +; CHECK: @test3 +; CHECK: %C = icmp ult i32 %X, %Y +; CHECK: br i1 %C, label %F, label %T -F: ; preds = %0 +T: + ret i32 12 +F: ret i32 123 } diff --git a/test/Transforms/InstCombine/fsub-fadd.ll b/test/Transforms/InstCombine/fsub-fadd.ll deleted file mode 100644 index f4cff88..0000000 --- a/test/Transforms/InstCombine/fsub-fadd.ll +++ /dev/null @@ -1,39 +0,0 @@ -; RUN: opt < %s -instcombine -S | FileCheck %s -; <rdar://problem/7530098> - -define void @func(double* %rhi, double* %rlo, double %xh, double %xl, double %yh, double %yl) nounwind ssp { -entry: - %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] - %tmp = fmul double %xh, 0x41A0000002000000 ; <double> [#uses=2] - %tmp1 = fsub double %xh, %tmp ; <double> [#uses=1] - %tmp2 = fadd double %tmp1, %tmp ; <double> [#uses=3] - %tmp3 = fsub double %xh, %tmp2 ; <double> [#uses=2] - %tmp4 = fmul double %yh, 0x41A0000002000000 ; <double> [#uses=2] - %tmp5 = fsub double %yh, %tmp4 ; <double> [#uses=1] - %tmp6 = fadd double %tmp5, %tmp4 ; <double> [#uses=3] - %tmp7 = fsub double %yh, %tmp6 ; <double> [#uses=2] - %tmp8 = fmul double %xh, %yh ; <double> [#uses=3] - %tmp9 = fmul double %tmp2, %tmp6 ; <double> [#uses=1] - %tmp10 = fsub double %tmp9, %tmp8 ; <double> [#uses=1] - %tmp11 = fmul double %tmp2, %tmp7 ; <double> [#uses=1] - %tmp12 = fadd double %tmp10, %tmp11 ; <double> [#uses=1] - %tmp13 = fmul double %tmp3, %tmp6 ; <double> [#uses=1] - %tmp14 = fadd double %tmp12, %tmp13 ; <double> [#uses=1] - %tmp15 = fmul double %tmp3, %tmp7 ; <double> [#uses=1] - %tmp16 = fadd double %tmp14, %tmp15 ; <double> [#uses=1] - %tmp17 = fmul double %xh, %yl ; <double> [#uses=1] - %tmp18 = fmul double %xl, %yh ; <double> [#uses=1] - %tmp19 = fadd double %tmp17, %tmp18 ; <double> [#uses=1] - %tmp20 = fadd double %tmp19, %tmp16 ; <double> [#uses=2] - %tmp21 = fadd double %tmp8, %tmp20 ; <double> [#uses=1] - store double %tmp21, double* %rhi, align 8 - %tmp22 = load double* %rhi, align 8 ; <double> [#uses=1] - %tmp23 = fsub double %tmp8, %tmp22 ; <double> [#uses=1] - %tmp24 = fadd double %tmp23, %tmp20 ; <double> [#uses=1] - -; CHECK: %tmp23 = fsub double %tmp8, %tmp21 -; CHECK: %tmp24 = fadd double %tmp23, %tmp20 - - store double %tmp24, double* %rlo, align 8 - ret void -} diff --git a/test/Transforms/InstCombine/fsub-fsub.ll b/test/Transforms/InstCombine/fsub-fsub.ll deleted file mode 100644 index 94ebf09..0000000 --- a/test/Transforms/InstCombine/fsub-fsub.ll +++ /dev/null @@ -1,8 +0,0 @@ -; RUN: opt < %s -instcombine -S | grep fsub | count 2 -; PR4374 - -define float @func(float %a, float %b) nounwind { - %tmp3 = fsub float %a, %b - %tmp4 = fsub float -0.000000e+00, %tmp3 - ret float %tmp4 -} diff --git a/test/Transforms/InstCombine/fsub.ll b/test/Transforms/InstCombine/fsub.ll new file mode 100644 index 0000000..af2fadd --- /dev/null +++ b/test/Transforms/InstCombine/fsub.ll @@ -0,0 +1,23 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; PR4374 +define float @test1(float %a, float %b) nounwind { + %t1 = fsub float %a, %b + %t2 = fsub float -0.000000e+00, %t1 + +; CHECK: %t1 = fsub float %a, %b +; CHECK-NEXT: %t2 = fsub float -0.000000e+00, %t1 + + ret float %t2 +} + +; <rdar://problem/7530098> +define double @test2(double %x, double %y) nounwind { + %t1 = fadd double %x, %y + %t2 = fsub double %x, %t1 + +; CHECK: %t1 = fadd double %x, %y +; CHECK-NEXT: %t2 = fsub double %x, %t1 + + ret double %t2 +} diff --git a/test/Transforms/InstCombine/idioms.ll b/test/Transforms/InstCombine/idioms.ll new file mode 100644 index 0000000..6b3567f --- /dev/null +++ b/test/Transforms/InstCombine/idioms.ll @@ -0,0 +1,32 @@ +; RUN: opt -instcombine %s -S | FileCheck %s + +; Check that code corresponding to the following C function is +; simplified into a single ASR operation: +; +; int test_asr(int a, int b) { +; return a < 0 ? -(-a - 1 >> b) - 1 : a >> b; +; } +; +define i32 @test_asr(i32 %a, i32 %b) { +entry: + %c = icmp slt i32 %a, 0 + br i1 %c, label %bb2, label %bb3 + +bb2: + %t1 = sub i32 0, %a + %not = sub i32 %t1, 1 + %d = ashr i32 %not, %b + %t2 = sub i32 0, %d + %not2 = sub i32 %t2, 1 + br label %bb4 +bb3: + %e = ashr i32 %a, %b + br label %bb4 +bb4: + %f = phi i32 [ %not2, %bb2 ], [ %e, %bb3 ] + ret i32 %f +; CHECK: @test_asr +; CHECK: bb4: +; CHECK: %f = ashr i32 %a, %b +; CHECK: ret i32 %f +} diff --git a/test/Transforms/InstCombine/signext.ll b/test/Transforms/InstCombine/signext.ll index 008662e..1c52b62 100644 --- a/test/Transforms/InstCombine/signext.ll +++ b/test/Transforms/InstCombine/signext.ll @@ -1,12 +1,16 @@ -; RUN: opt < %s -instcombine -S | \ -; RUN: not grep {(and\|xor\|add\|shl\|shr)} -; END. +; RUN: opt < %s -instcombine -S | FileCheck %s + +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" define i32 @test1(i32 %x) { %tmp.1 = and i32 %x, 65535 ; <i32> [#uses=1] %tmp.2 = xor i32 %tmp.1, -32768 ; <i32> [#uses=1] %tmp.3 = add i32 %tmp.2, 32768 ; <i32> [#uses=1] ret i32 %tmp.3 +; CHECK: @test1 +; CHECK: %sext1 = shl i32 %x, 16 +; CHECK: %tmp.3 = ashr i32 %sext1, 16 +; CHECK: ret i32 %tmp.3 } define i32 @test2(i32 %x) { @@ -14,6 +18,10 @@ define i32 @test2(i32 %x) { %tmp.2 = xor i32 %tmp.1, 32768 ; <i32> [#uses=1] %tmp.3 = add i32 %tmp.2, -32768 ; <i32> [#uses=1] ret i32 %tmp.3 +; CHECK: @test2 +; CHECK: %sext1 = shl i32 %x, 16 +; CHECK: %tmp.3 = ashr i32 %sext1, 16 +; CHECK: ret i32 %tmp.3 } define i32 @test3(i16 %P) { @@ -21,6 +29,9 @@ define i32 @test3(i16 %P) { %tmp.4 = xor i32 %tmp.1, 32768 ; <i32> [#uses=1] %tmp.5 = add i32 %tmp.4, -32768 ; <i32> [#uses=1] ret i32 %tmp.5 +; CHECK: @test3 +; CHECK: %tmp.5 = sext i16 %P to i32 +; CHECK: ret i32 %tmp.5 } define i32 @test4(i16 %P) { @@ -28,18 +39,38 @@ define i32 @test4(i16 %P) { %tmp.4 = xor i32 %tmp.1, 32768 ; <i32> [#uses=1] %tmp.5 = add i32 %tmp.4, -32768 ; <i32> [#uses=1] ret i32 %tmp.5 +; CHECK: @test4 +; CHECK: %tmp.5 = sext i16 %P to i32 +; CHECK: ret i32 %tmp.5 } define i32 @test5(i32 %x) { - %tmp.1 = and i32 %x, 254 ; <i32> [#uses=1] + %tmp.1 = and i32 %x, 255 ; <i32> [#uses=1] %tmp.2 = xor i32 %tmp.1, 128 ; <i32> [#uses=1] %tmp.3 = add i32 %tmp.2, -128 ; <i32> [#uses=1] ret i32 %tmp.3 +; CHECK: @test5 +; CHECK: %sext1 = shl i32 %x, 24 +; CHECK: %tmp.3 = ashr i32 %sext1, 24 +; CHECK: ret i32 %tmp.3 } define i32 @test6(i32 %x) { %tmp.2 = shl i32 %x, 16 ; <i32> [#uses=1] %tmp.4 = ashr i32 %tmp.2, 16 ; <i32> [#uses=1] ret i32 %tmp.4 +; CHECK: @test6 +; CHECK: %tmp.2 = shl i32 %x, 16 +; CHECK: %tmp.4 = ashr i32 %tmp.2, 16 +; CHECK: ret i32 %tmp.4 } +define i32 @test7(i16 %P) { + %tmp.1 = zext i16 %P to i32 ; <i32> [#uses=1] + %sext1 = shl i32 %tmp.1, 16 ; <i32> [#uses=1] + %tmp.5 = ashr i32 %sext1, 16 ; <i32> [#uses=1] + ret i32 %tmp.5 +; CHECK: @test7 +; CHECK: %tmp.5 = sext i16 %P to i32 +; CHECK: ret i32 %tmp.5 +} diff --git a/test/Transforms/InstCombine/xor2.ll b/test/Transforms/InstCombine/xor2.ll index 23a9915..de3d65d 100644 --- a/test/Transforms/InstCombine/xor2.ll +++ b/test/Transforms/InstCombine/xor2.ll @@ -41,3 +41,13 @@ define i32 @test3(i32 %tmp1) { %ov110 = xor i32 %ov31, 153 ret i32 %ov110 } + +define i32 @test4(i32 %A, i32 %B) { + %1 = xor i32 %A, -1 + %2 = ashr i32 %1, %B + %3 = xor i32 %2, -1 + ret i32 %3 +; CHECK: @test4 +; CHECK: %1 = ashr i32 %A, %B +; CHECK: ret i32 %1 +} diff --git a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll index 56a89f6..36941ad 100644 --- a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll +++ b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll @@ -6,7 +6,7 @@ target triple = "x86_64-apple-darwin9" ; happens before the relevant use, so the comparison stride can't be ; easily changed. -define void @foo() { +define void @foo() nounwind { entry: br label %loop diff --git a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll index 8a3978b..ea8a259 100644 --- a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll +++ b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll @@ -1,10 +1,10 @@ -; RUN: llc %s -o - --x86-asm-syntax=att | grep {cmpq \$8} +; RUN: llc %s -o - --x86-asm-syntax=att | grep {cmp. \$8} 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" target triple = "x86_64-apple-darwin9" -; This is like change-compare-stride-trickiness-0.ll except the comparison -; happens after the relevant use, so the comparison stride can be -; easily changed. +; The comparison happens after the relevant use, so the stride can easily +; be changed. The comparison can be done in a narrower mode than the +; induction variable. define void @foo() nounwind { entry: diff --git a/test/Transforms/LoopStrengthReduce/icmp_use_postinc.ll b/test/Transforms/LoopStrengthReduce/icmp_use_postinc.ll deleted file mode 100644 index 4ad5d14..0000000 --- a/test/Transforms/LoopStrengthReduce/icmp_use_postinc.ll +++ /dev/null @@ -1,27 +0,0 @@ -; RUN: opt < %s -loop-reduce -S | FileCheck %s - -define i32 @main(i32 %argc, i8** nocapture %argv) nounwind ssp { -entry: - br i1 undef, label %bb4.preheader, label %bb.nph8 - -bb4.preheader: ; preds = %entry - br label %bb4 - -bb1: ; preds = %bb4 - br i1 undef, label %bb.nph8, label %bb3 - -bb3: ; preds = %bb1 - %phitmp = add i32 %indvar, 1 ; <i32> [#uses=1] - br label %bb4 - -bb4: ; preds = %bb3, %bb4.preheader -; CHECK: %lsr.iv = phi -; CHECK: %lsr.iv.next = add i32 %lsr.iv, 1 -; CHECK: %0 = icmp slt i32 %lsr.iv.next, %argc - %indvar = phi i32 [ 1, %bb4.preheader ], [ %phitmp, %bb3 ] ; <i32> [#uses=2] - %0 = icmp slt i32 %indvar, %argc ; <i1> [#uses=1] - br i1 %0, label %bb1, label %bb.nph8 - -bb.nph8: ; preds = %bb4, %bb1, %entry - unreachable -} diff --git a/test/Transforms/LoopStrengthReduce/related_indvars.ll b/test/Transforms/LoopStrengthReduce/related_indvars.ll index 2494378..12942bf 100644 --- a/test/Transforms/LoopStrengthReduce/related_indvars.ll +++ b/test/Transforms/LoopStrengthReduce/related_indvars.ll @@ -7,7 +7,7 @@ ; *D++ = F; ; } -define void @foo(double* %D, double* %E, double %F) { +define void @foo(double* %D, double* %E, double %F) nounwind { entry: %tmp.24 = icmp eq double* %D, %E ; <i1> [#uses=1] br i1 %tmp.24, label %return, label %no_exit diff --git a/test/Transforms/Mem2Reg/ConvertDebugInfo.ll b/test/Transforms/Mem2Reg/ConvertDebugInfo.ll new file mode 100644 index 0000000..8e309c0 --- /dev/null +++ b/test/Transforms/Mem2Reg/ConvertDebugInfo.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -mem2reg -S | FileCheck %s + +target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" + +define double @testfunc(i32 %i, double %j) { + %I = alloca i32 ; <i32*> [#uses=4] + call void @llvm.dbg.declare(metadata !{i32* %I}, metadata !0) + %J = alloca double ; <double*> [#uses=2] + call void @llvm.dbg.declare(metadata !{double* %J}, metadata !1) +; CHECK: call void @llvm.dbg.value(metadata !{i32 %i}, i64 0, metadata !0) + store i32 %i, i32* %I +; CHECK: call void @llvm.dbg.value(metadata !{double %j}, i64 0, metadata !1) + store double %j, double* %J + %t1 = load i32* %I ; <i32> [#uses=1] + %t2 = add i32 %t1, 1 ; <i32> [#uses=1] + store i32 %t2, i32* %I + %t3 = load i32* %I ; <i32> [#uses=1] + %t4 = sitofp i32 %t3 to double ; <double> [#uses=1] + %t5 = load double* %J ; <double> [#uses=1] + %t6 = fmul double %t4, %t5 ; <double> [#uses=1] + ret double %t6 +} + +declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone + +!bar = !{!0} +!foo = !{!2} + +!0 = metadata !{i32 459008, metadata !1, metadata !"foo", metadata !2, i32 5, metadata !"foo"} ; [ DW_TAG_auto_variable ] +!1 = metadata !{i32 459008, metadata !1, metadata !"foo", metadata !0, i32 5, metadata !1} ; [ DW_TAG_auto_variable ] +!2 = metadata !{i32 458804, i32 0, metadata !2, metadata !"foo", metadata !"bar", metadata !"bar", metadata !2, i32 3, metadata !0, i1 false, i1 true} ; [ DW_TAG_variable ] diff --git a/test/Transforms/Reassociate/inverses.ll b/test/Transforms/Reassociate/inverses.ll index fa1a4bd..34abdc7 100644 --- a/test/Transforms/Reassociate/inverses.ll +++ b/test/Transforms/Reassociate/inverses.ll @@ -1,28 +1,34 @@ -; RUN: opt < %s -reassociate -dce -S | \ -; RUN: not grep {\\(and\\|sub\\)} +; RUN: opt < %s -reassociate -die -S | FileCheck %s define i32 @test1(i32 %a, i32 %b) { - %tmp.2 = and i32 %b, %a ; <i32> [#uses=1] - %tmp.4 = xor i32 %a, -1 ; <i32> [#uses=1] + %tmp.2 = and i32 %b, %a + %tmp.4 = xor i32 %a, -1 ; (A&B)&~A == 0 - %tmp.5 = and i32 %tmp.2, %tmp.4 ; <i32> [#uses=1] + %tmp.5 = and i32 %tmp.2, %tmp.4 ret i32 %tmp.5 +; CHECK: @test1 +; CHECK: ret i32 0 } define i32 @test2(i32 %a, i32 %b) { - %tmp.1 = and i32 %a, 1234 ; <i32> [#uses=1] - %tmp.2 = and i32 %b, %tmp.1 ; <i32> [#uses=1] - %tmp.4 = xor i32 %a, -1 ; <i32> [#uses=1] + %tmp.1 = and i32 %a, 1234 + %tmp.2 = and i32 %b, %tmp.1 + %tmp.4 = xor i32 %a, -1 ; A&~A == 0 - %tmp.5 = and i32 %tmp.2, %tmp.4 ; <i32> [#uses=1] + %tmp.5 = and i32 %tmp.2, %tmp.4 ret i32 %tmp.5 +; CHECK: @test2 +; CHECK: ret i32 0 } define i32 @test3(i32 %b, i32 %a) { - %tmp.1 = add i32 %a, 1234 ; <i32> [#uses=1] - %tmp.2 = add i32 %b, %tmp.1 ; <i32> [#uses=1] - %tmp.4 = sub i32 0, %a ; <i32> [#uses=1] + %tmp.1 = add i32 %a, 1234 + %tmp.2 = add i32 %b, %tmp.1 + %tmp.4 = sub i32 0, %a ; (b+(a+1234))+-a -> b+1234 - %tmp.5 = add i32 %tmp.2, %tmp.4 ; <i32> [#uses=1] + %tmp.5 = add i32 %tmp.2, %tmp.4 ret i32 %tmp.5 +; CHECK: @test3 +; CHECK: %tmp.5 = add i32 %b, 1234 +; CHECK: ret i32 %tmp.5 } diff --git a/test/Transforms/ScalarRepl/2010-01-18-SelfCopy.ll b/test/Transforms/ScalarRepl/2010-01-18-SelfCopy.ll new file mode 100644 index 0000000..74cf251 --- /dev/null +++ b/test/Transforms/ScalarRepl/2010-01-18-SelfCopy.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -scalarrepl -S | FileCheck %s +; Radar 7552893 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" + +%struct.test = type { [3 x double ] } + +define arm_apcscc void @test_memcpy_self() nounwind { +; CHECK: @test_memcpy_self +; CHECK-NOT: alloca +; CHECK: ret void + %1 = alloca %struct.test + %2 = bitcast %struct.test* %1 to i8* + call void @llvm.memcpy.i32(i8* %2, i8* %2, i32 24, i32 4) + ret void +} + +declare void @llvm.memcpy.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind diff --git a/test/lit.cfg b/test/lit.cfg index 246f270..8e85168 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -133,7 +133,7 @@ def llvm_gcc_supports(name): bindings = set(site_exp['llvm_bindings'].split(',')) def llvm_supports_binding(name): - return name in langs + return name in bindings # Provide on_clone hook for reading 'dg.exp'. import os diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index a591417..c2b002f 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -22,7 +22,6 @@ #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/Analysis/Verifier.h" -#include "llvm/Support/Mangler.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" @@ -235,30 +234,16 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*>&Funcs){ return TestFn(BD, ToOptimize, ToNotOptimize); } -/// DisambiguateGlobalSymbols - Mangle symbols to guarantee uniqueness by -/// modifying predominantly internal symbols rather than external ones. +/// DisambiguateGlobalSymbols - Give anonymous global values names. /// static void DisambiguateGlobalSymbols(Module *M) { - // Try not to cause collisions by minimizing chances of renaming an - // already-external symbol, so take in external globals and functions as-is. - // The code should work correctly without disambiguation (assuming the same - // mangler is used by the two code generators), but having symbols with the - // same name causes warnings to be emitted by the code generator. - Mangler Mang(*M); - // Agree with the CBE on symbol naming - Mang.markCharUnacceptable('.'); for (Module::global_iterator I = M->global_begin(), E = M->global_end(); - I != E; ++I) { - // Don't mangle asm names. - if (!I->hasName() || I->getName()[0] != 1) - I->setName(Mang.getMangledName(I)); - } - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { - // Don't mangle asm names or intrinsics. - if ((!I->hasName() || I->getName()[0] != 1) && - I->getIntrinsicID() == 0) - I->setName(Mang.getMangledName(I)); - } + I != E; ++I) + if (!I->hasName()) + I->setName("anon_global"); + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + if (!I->hasName()) + I->setName("anon_fn"); } /// ExtractLoops - Given a reduced list of functions that still exposed the bug, @@ -548,10 +533,6 @@ DebugAMiscompilation(BugDriver &BD, ExtractLoops(BD, TestFn, MiscompiledFunctions)) { // Okay, we extracted some loops and the problem still appears. See if we // can eliminate some of the created functions from being candidates. - - // Loop extraction can introduce functions with the same name (foo_code). - // Make sure to disambiguate the symbols so that when the program is split - // apart that we can link it back together again. DisambiguateGlobalSymbols(BD.getProgram()); // Do the reduction... @@ -569,10 +550,6 @@ DebugAMiscompilation(BugDriver &BD, ExtractBlocks(BD, TestFn, MiscompiledFunctions)) { // Okay, we extracted some blocks and the problem still appears. See if we // can eliminate some of the created functions from being candidates. - - // Block extraction can introduce functions with the same name (foo_code). - // Make sure to disambiguate the symbols so that when the program is split - // apart that we can link it back together again. DisambiguateGlobalSymbols(BD.getProgram()); // Do the reduction... diff --git a/tools/gold/Makefile b/tools/gold/Makefile index 7bac4ec..3f77229 100644 --- a/tools/gold/Makefile +++ b/tools/gold/Makefile @@ -19,6 +19,7 @@ LINK_LIBS_IN_SHARED=1 SHARED_LIBRARY = 1 BUILD_ARCHIVE = 0 LOADABLE_MODULE = 1 +CXXFLAGS = -fno-rtti LINK_COMPONENTS := support system LIBS += -llto diff --git a/tools/llc/Makefile b/tools/llc/Makefile index 7319aad..6b5b125 100644 --- a/tools/llc/Makefile +++ b/tools/llc/Makefile @@ -9,6 +9,7 @@ LEVEL = ../.. TOOLNAME = llc +CXXFLAGS = -fno-rtti # Include this here so we can get the configuration of the targets # that have been configured for construction. We have to do this diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 930de26..4f93a43 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -366,9 +366,7 @@ int main(int argc, char **argv) { sys::Path(OutputFilename).eraseFromDisk(); return 1; case FileModel::AsmFile: - break; case FileModel::MachOFile: - OCE = AddMachOWriter(Passes, *Out, Target); break; case FileModel::ElfFile: OCE = AddELFWriter(Passes, *Out, Target); diff --git a/tools/lli/Makefile b/tools/lli/Makefile index 8f6eeed..2341bed 100644 --- a/tools/lli/Makefile +++ b/tools/lli/Makefile @@ -9,6 +9,7 @@ LEVEL := ../.. TOOLNAME := lli +CXXFLAGS = -fno-rtti LINK_COMPONENTS := jit interpreter nativecodegen bitreader selectiondag # Enable JIT support diff --git a/tools/llvm-ar/Makefile b/tools/llvm-ar/Makefile index e4fe4e8..3db7964 100644 --- a/tools/llvm-ar/Makefile +++ b/tools/llvm-ar/Makefile @@ -11,6 +11,7 @@ LEVEL = ../.. TOOLNAME = llvm-ar LINK_COMPONENTS = archive REQUIRES_EH := 1 +#CXXFLAGS = -fno-rtti # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/tools/llvm-as/Makefile b/tools/llvm-as/Makefile index ae449c4..d6fbd71 100644 --- a/tools/llvm-as/Makefile +++ b/tools/llvm-as/Makefile @@ -10,7 +10,7 @@ LEVEL = ../.. TOOLNAME = llvm-as LINK_COMPONENTS := asmparser bitwriter -REQUIRES_EH := 1 +CXXFLAGS = -fno-rtti # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/tools/llvm-bcanalyzer/Makefile b/tools/llvm-bcanalyzer/Makefile index 251f758..488387d 100644 --- a/tools/llvm-bcanalyzer/Makefile +++ b/tools/llvm-bcanalyzer/Makefile @@ -10,7 +10,6 @@ LEVEL = ../.. TOOLNAME = llvm-bcanalyzer LINK_COMPONENTS := bitreader -REQUIRES_EH := 1 # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/tools/llvm-config/Makefile b/tools/llvm-config/Makefile index 6eedca0..e5bdc04 100644 --- a/tools/llvm-config/Makefile +++ b/tools/llvm-config/Makefile @@ -10,7 +10,6 @@ LEVEL = ../.. EXTRA_DIST = LibDeps.txt FinalLibDeps.txt llvm-config.in.in find-cycles.pl -REQUIRES_EH := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-config/llvm-config.in.in b/tools/llvm-config/llvm-config.in.in index d0edda0..d435d57 100644 --- a/tools/llvm-config/llvm-config.in.in +++ b/tools/llvm-config/llvm-config.in.in @@ -18,6 +18,7 @@ use 5.006; use strict; use warnings; +use Cwd 'abs_path'; #---- begin autoconf values ---- my $PACKAGE_NAME = q{@PACKAGE_NAME@}; @@ -53,20 +54,14 @@ my $LLVM_BUILDMODE = q{@LLVM_BUILDMODE@}; # Convert the current executable name into its directory (e.g. "."). my ($RUN_DIR) = ($0 =~ /^(.*)\/.*$/); -# Find the unix pwd program: we don't want to use the bash builtin, as it does -# not look through symlinks etc. -my $PWD = `which pwd`; -chomp($PWD); -$PWD = "pwd" if (!-e $PWD); - # Turn the directory into an absolute directory on the file system, also pop up # from "bin" into the build or prefix dir. -my $ABS_RUN_DIR = `cd $RUN_DIR/..; $PWD`; +my $ABS_RUN_DIR = abs_path("$RUN_DIR/.."); chomp($ABS_RUN_DIR); # Compute the absolute object directory build, e.g. "foo/llvm/Debug". my $ABS_OBJ_ROOT = "$LLVM_OBJ_ROOT/$LLVM_BUILDMODE"; -$ABS_OBJ_ROOT = `cd $ABS_OBJ_ROOT; $PWD` if (-d $ABS_OBJ_ROOT); +$ABS_OBJ_ROOT = abs_path("$ABS_OBJ_ROOT") if (-d $ABS_OBJ_ROOT); chomp($ABS_OBJ_ROOT); my $INCLUDEDIR = "$ABS_RUN_DIR/include"; @@ -134,9 +129,9 @@ foreach my $arg (@ARGV) { } elsif ($arg eq "--build-mode") { $has_opt = 1; print "$LLVM_BUILDMODE\n"; } elsif ($arg eq "--obj-root") { - $has_opt = 1; print `cd $LLVM_OBJ_ROOT/; $PWD`; + $has_opt = 1; print abs_path("$LLVM_OBJ_ROOT/"); } elsif ($arg eq "--src-root") { - $has_opt = 1; print `cd $LLVM_SRC_ROOT/; $PWD`; + $has_opt = 1; print abs_path("$LLVM_SRC_ROOT/"); } else { usage(); } diff --git a/tools/llvm-dis/Makefile b/tools/llvm-dis/Makefile index dfd5e34..96f3cbb 100644 --- a/tools/llvm-dis/Makefile +++ b/tools/llvm-dis/Makefile @@ -10,7 +10,7 @@ LEVEL = ../.. TOOLNAME = llvm-dis LINK_COMPONENTS := bitreader -REQUIRES_EH := 1 +CXXFLAGS = -fno-rtti # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/tools/llvm-extract/Makefile b/tools/llvm-extract/Makefile index 5672aa3..dee0572 100644 --- a/tools/llvm-extract/Makefile +++ b/tools/llvm-extract/Makefile @@ -11,6 +11,7 @@ LEVEL = ../.. TOOLNAME = llvm-extract LINK_COMPONENTS := ipo bitreader bitwriter asmparser +CXXFLAGS = -fno-rtti # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/tools/llvm-ld/Makefile b/tools/llvm-ld/Makefile index 1ef9bf1..1da1966 100644 --- a/tools/llvm-ld/Makefile +++ b/tools/llvm-ld/Makefile @@ -11,5 +11,6 @@ LEVEL = ../.. TOOLNAME = llvm-ld LINK_COMPONENTS = ipo scalaropts linker archive bitwriter +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/tools/llvm-link/Makefile b/tools/llvm-link/Makefile index 2637018..de592aa 100644 --- a/tools/llvm-link/Makefile +++ b/tools/llvm-link/Makefile @@ -10,6 +10,7 @@ LEVEL = ../.. TOOLNAME = llvm-link LINK_COMPONENTS = linker bitreader bitwriter asmparser +CXXFLAGS = -fno-rtti # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/tools/llvm-mc/AsmLexer.cpp b/tools/llvm-mc/AsmLexer.cpp index ba0d247..234b8f3 100644 --- a/tools/llvm-mc/AsmLexer.cpp +++ b/tools/llvm-mc/AsmLexer.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "AsmLexer.h" -#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/SMLoc.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Config/config.h" // for strtoull. #include "llvm/MC/MCAsmInfo.h" @@ -21,78 +21,53 @@ #include <cstdlib> using namespace llvm; -AsmLexer::AsmLexer(SourceMgr &SM, const MCAsmInfo &_MAI) : SrcMgr(SM), - MAI(_MAI) { - CurBuffer = 0; - CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); - CurPtr = CurBuf->getBufferStart(); +AsmLexer::AsmLexer(const MCAsmInfo &_MAI) : MAI(_MAI) { + CurBuf = NULL; + CurPtr = NULL; TokStart = 0; } AsmLexer::~AsmLexer() { } -SMLoc AsmLexer::getLoc() const { - return SMLoc::getFromPointer(TokStart); +void AsmLexer::setBuffer(const MemoryBuffer *buf, const char *ptr) { + CurBuf = buf; + + if (ptr) + CurPtr = ptr; + else + CurPtr = CurBuf->getBufferStart(); + + TokStart = 0; } -void AsmLexer::PrintMessage(SMLoc Loc, const std::string &Msg, - const char *Type) const { - SrcMgr.PrintMessage(Loc, Msg, Type); +SMLoc AsmLexer::getLoc() const { + return SMLoc::getFromPointer(TokStart); } /// ReturnError - Set the error to the specified string at the specified /// location. This is defined to always return AsmToken::Error. AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) { - PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error"); - return AsmToken(AsmToken::Error, StringRef(Loc, 0)); -} - -/// EnterIncludeFile - Enter the specified file. This prints an error and -/// returns true on failure. -bool AsmLexer::EnterIncludeFile(const std::string &Filename) { - int NewBuf = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr)); - if (NewBuf == -1) - return true; + SetError(SMLoc::getFromPointer(Loc), Msg); - // Save the line number and lex buffer of the includer. - CurBuffer = NewBuf; - CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); - CurPtr = CurBuf->getBufferStart(); - return false; + return AsmToken(AsmToken::Error, StringRef(Loc, 0)); } - int AsmLexer::getNextChar() { char CurChar = *CurPtr++; switch (CurChar) { default: return (unsigned char)CurChar; - case 0: { + case 0: // A nul character in the stream is either the end of the current buffer or // a random nul in the file. Disambiguate that here. if (CurPtr-1 != CurBuf->getBufferEnd()) return 0; // Just whitespace. - // If this is the end of an included file, pop the parent file off the - // include stack. - SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); - if (ParentIncludeLoc != SMLoc()) { - CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc); - CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); - CurPtr = ParentIncludeLoc.getPointer(); - - // Reset the token start pointer to the start of the new file. - TokStart = CurPtr; - - return getNextChar(); - } - // Otherwise, return end of file. --CurPtr; // Another call to lex will return EOF again. return EOF; } - } } /// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* diff --git a/tools/llvm-mc/AsmLexer.h b/tools/llvm-mc/AsmLexer.h index ce292f6..1d49e4b 100644 --- a/tools/llvm-mc/AsmLexer.h +++ b/tools/llvm-mc/AsmLexer.h @@ -23,23 +23,17 @@ namespace llvm { class MemoryBuffer; -class SourceMgr; class SMLoc; class MCAsmInfo; /// AsmLexer - Lexer class for assembly files. class AsmLexer : public MCAsmLexer { - SourceMgr &SrcMgr; const MCAsmInfo &MAI; const char *CurPtr; const MemoryBuffer *CurBuf; const char *TokStart; - - /// This is the current buffer index we're lexing from as managed by the - /// SourceMgr object. - int CurBuffer; void operator=(const AsmLexer&); // DO NOT IMPLEMENT AsmLexer(const AsmLexer&); // DO NOT IMPLEMENT @@ -49,20 +43,19 @@ protected: virtual AsmToken LexToken(); public: - AsmLexer(SourceMgr &SrcMgr, const MCAsmInfo &MAI); + AsmLexer(const MCAsmInfo &MAI); ~AsmLexer(); + void setBuffer(const MemoryBuffer *buf, const char *ptr = NULL); + SMLoc getLoc() const; StringRef LexUntilEndOfStatement(); bool isAtStartOfComment(char Char); - - /// EnterIncludeFile - Enter the specified file. This returns true on failure. - bool EnterIncludeFile(const std::string &Filename); - - void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type) const; + const MCAsmInfo &getMAI() const { return MAI; } + private: int getNextChar(); AsmToken ReturnError(const char *Loc, const std::string &Msg); diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp index 2eb75a7..068e506 100644 --- a/tools/llvm-mc/AsmParser.cpp +++ b/tools/llvm-mc/AsmParser.cpp @@ -29,10 +29,8 @@ #include "llvm/Target/TargetAsmParser.h" using namespace llvm; -/// getStartLoc - Get the location of the first token of this operand. -SMLoc MCParsedAsmOperand::getStartLoc() const { return SMLoc(); } -SMLoc MCParsedAsmOperand::getEndLoc() const { return SMLoc(); } +enum { DEFAULT_ADDRSPACE = 0 }; // Mach-O section uniquing. // @@ -42,8 +40,10 @@ typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) - : Lexer(_SM, _MAI), Ctx(_Ctx), Out(_Out), TargetParser(0), - SectionUniquingMap(0) { + : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), TargetParser(0), + CurBuffer(0), SectionUniquingMap(0) { + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + // Debugging directives. AddDirectiveHandler(".file", &AsmParser::ParseDirectiveFile); AddDirectiveHandler(".line", &AsmParser::ParseDirectiveLine); @@ -89,19 +89,57 @@ const MCSection *AsmParser::getMachOSection(const StringRef &Segment, } void AsmParser::Warning(SMLoc L, const Twine &Msg) { - Lexer.PrintMessage(L, Msg.str(), "warning"); + PrintMessage(L, Msg.str(), "warning"); } bool AsmParser::Error(SMLoc L, const Twine &Msg) { - Lexer.PrintMessage(L, Msg.str(), "error"); + PrintMessage(L, Msg.str(), "error"); return true; } bool AsmParser::TokError(const char *Msg) { - Lexer.PrintMessage(Lexer.getLoc(), Msg, "error"); + PrintMessage(Lexer.getLoc(), Msg, "error"); return true; } +void AsmParser::PrintMessage(SMLoc Loc, const std::string &Msg, + const char *Type) const { + SrcMgr.PrintMessage(Loc, Msg, Type); +} + +bool AsmParser::EnterIncludeFile(const std::string &Filename) { + int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc()); + if (NewBuf == -1) + return true; + + CurBuffer = NewBuf; + + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + + return false; +} + +const AsmToken &AsmParser::Lex() { + const AsmToken *tok = &Lexer.Lex(); + + if (tok->is(AsmToken::Eof)) { + // If this is the end of an included file, pop the parent file off the + // include stack. + SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); + if (ParentIncludeLoc != SMLoc()) { + CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), + ParentIncludeLoc.getPointer()); + tok = &Lexer.Lex(); + } + } + + if (tok->is(AsmToken::Error)) + PrintMessage(Lexer.getErrLoc(), Lexer.getErr(), "error"); + + return *tok; +} + bool AsmParser::Run() { // Create the initial section. // @@ -113,7 +151,7 @@ bool AsmParser::Run() { // Prime the lexer. - Lexer.Lex(); + Lex(); bool HadError = false; @@ -124,7 +162,7 @@ bool AsmParser::Run() { // Handle conditional assembly here before calling ParseStatement() if (Lexer.getKind() == AsmToken::Identifier) { // If we have an identifier, handle it as the key symbol. - AsmToken ID = Lexer.getTok(); + AsmToken ID = getTok(); SMLoc IDLoc = ID.getLoc(); StringRef IDVal = ID.getString(); @@ -180,11 +218,11 @@ bool AsmParser::ParseConditionalAssemblyDirectives(StringRef Directive, void AsmParser::EatToEndOfStatement() { while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) - Lexer.Lex(); + Lex(); // Eat EOL. if (Lexer.is(AsmToken::EndOfStatement)) - Lexer.Lex(); + Lex(); } @@ -193,11 +231,12 @@ void AsmParser::EatToEndOfStatement() { /// /// parenexpr ::= expr) /// -bool AsmParser::ParseParenExpr(const MCExpr *&Res) { +bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { if (ParseExpression(Res)) return true; if (Lexer.isNot(AsmToken::RParen)) return TokError("expected ')' in parentheses expression"); - Lexer.Lex(); + EndLoc = Lexer.getLoc(); + Lex(); return false; } @@ -217,21 +256,22 @@ MCSymbol *AsmParser::CreateSymbol(StringRef Name) { /// primaryexpr ::= symbol /// primaryexpr ::= number /// primaryexpr ::= ~,+,- primaryexpr -bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res) { +bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { switch (Lexer.getKind()) { default: return TokError("unknown token in expression"); case AsmToken::Exclaim: - Lexer.Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res)) + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) return true; Res = MCUnaryExpr::CreateLNot(Res, getContext()); return false; case AsmToken::String: case AsmToken::Identifier: { // This is a symbol reference. - MCSymbol *Sym = CreateSymbol(Lexer.getTok().getIdentifier()); - Lexer.Lex(); // Eat identifier. + MCSymbol *Sym = CreateSymbol(getTok().getIdentifier()); + EndLoc = Lexer.getLoc(); + Lex(); // Eat identifier. // If this is an absolute variable reference, substitute it now to preserve // semantics in the face of reassignment. @@ -245,33 +285,39 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res) { return false; } case AsmToken::Integer: - Res = MCConstantExpr::Create(Lexer.getTok().getIntVal(), getContext()); - Lexer.Lex(); // Eat token. + Res = MCConstantExpr::Create(getTok().getIntVal(), getContext()); + EndLoc = Lexer.getLoc(); + Lex(); // Eat token. return false; case AsmToken::LParen: - Lexer.Lex(); // Eat the '('. - return ParseParenExpr(Res); + Lex(); // Eat the '('. + return ParseParenExpr(Res, EndLoc); case AsmToken::Minus: - Lexer.Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res)) + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) return true; Res = MCUnaryExpr::CreateMinus(Res, getContext()); return false; case AsmToken::Plus: - Lexer.Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res)) + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) return true; Res = MCUnaryExpr::CreatePlus(Res, getContext()); return false; case AsmToken::Tilde: - Lexer.Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res)) + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) return true; Res = MCUnaryExpr::CreateNot(Res, getContext()); return false; } } +bool AsmParser::ParseExpression(const MCExpr *&Res) { + SMLoc EndLoc; + return ParseExpression(Res, EndLoc); +} + /// ParseExpression - Parse an expression and return it. /// /// expr ::= expr +,- expr -> lowest. @@ -279,14 +325,14 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res) { /// expr ::= expr *,/,%,<<,>> expr -> highest. /// expr ::= primaryexpr /// -bool AsmParser::ParseExpression(const MCExpr *&Res) { +bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) { Res = 0; - return ParsePrimaryExpr(Res) || - ParseBinOpRHS(1, Res); + return ParsePrimaryExpr(Res, EndLoc) || + ParseBinOpRHS(1, Res, EndLoc); } -bool AsmParser::ParseParenExpression(const MCExpr *&Res) { - if (ParseParenExpr(Res)) +bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { + if (ParseParenExpr(Res, EndLoc)) return true; return false; @@ -381,7 +427,8 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, /// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'. /// Res contains the LHS of the expression on input. -bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res) { +bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, + SMLoc &EndLoc) { while (1) { MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind); @@ -391,18 +438,18 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res) { if (TokPrec < Precedence) return false; - Lexer.Lex(); + Lex(); // Eat the next primary expression. const MCExpr *RHS; - if (ParsePrimaryExpr(RHS)) return true; + if (ParsePrimaryExpr(RHS, EndLoc)) return true; // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. MCBinaryExpr::Opcode Dummy; unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); if (TokPrec < NextTokPrec) { - if (ParseBinOpRHS(Precedence+1, RHS)) return true; + if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true; } // Merge LHS and RHS according to operator. @@ -419,12 +466,12 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res) { /// ::= Label* Identifier OperandList* EndOfStatement bool AsmParser::ParseStatement() { if (Lexer.is(AsmToken::EndOfStatement)) { - Lexer.Lex(); + Lex(); return false; } // Statements always start with an identifier. - AsmToken ID = Lexer.getTok(); + AsmToken ID = getTok(); SMLoc IDLoc = ID.getLoc(); StringRef IDVal; if (ParseIdentifier(IDVal)) @@ -436,7 +483,7 @@ bool AsmParser::ParseStatement() { switch (Lexer.getKind()) { case AsmToken::Colon: { // identifier ':' -> Label. - Lexer.Lex(); + Lex(); // Diagnose attempt to use a variable as a label. // @@ -455,7 +502,7 @@ bool AsmParser::ParseStatement() { case AsmToken::Equal: // identifier '=' ... -> assignment statement - Lexer.Lex(); + Lex(); return ParseAssignment(IDVal); @@ -727,7 +774,7 @@ bool AsmParser::ParseStatement() { return TokError("unexpected token in argument list"); // Eat the end of statement marker. - Lexer.Lex(); + Lex(); MCInst Inst; @@ -764,7 +811,7 @@ bool AsmParser::ParseAssignment(const StringRef &Name) { return TokError("unexpected token in assignment"); // Eat the end of statement marker. - Lexer.Lex(); + Lex(); // Validate that the LHS is allowed to be a variable (either it has not been // used as a symbol, or it is an absolute symbol). @@ -800,9 +847,9 @@ bool AsmParser::ParseIdentifier(StringRef &Res) { Lexer.isNot(AsmToken::String)) return true; - Res = Lexer.getTok().getIdentifier(); + Res = getTok().getIdentifier(); - Lexer.Lex(); // Consume the identifier token. + Lex(); // Consume the identifier token. return false; } @@ -817,7 +864,7 @@ bool AsmParser::ParseDirectiveSet() { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in '.set'"); - Lexer.Lex(); + Lex(); return ParseAssignment(Name); } @@ -845,10 +892,10 @@ bool AsmParser::ParseDirectiveDarwinSection() { StringRef EOL = Lexer.LexUntilEndOfStatement(); SectionSpec.append(EOL.begin(), EOL.end()); - Lexer.Lex(); + Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.section' directive"); - Lexer.Lex(); + Lex(); StringRef Segment, Section; @@ -873,7 +920,7 @@ bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment, unsigned StubSize) { if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in section switching directive"); - Lexer.Lex(); + Lex(); // FIXME: Arch specific. Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize, @@ -897,7 +944,7 @@ bool AsmParser::ParseEscapedString(std::string &Data) { assert(Lexer.is(AsmToken::String) && "Unexpected current token!"); Data = ""; - StringRef Str = Lexer.getTok().getStringContents(); + StringRef Str = getTok().getStringContents(); for (unsigned i = 0, e = Str.size(); i != e; ++i) { if (Str[i] != '\\') { Data += Str[i]; @@ -963,22 +1010,22 @@ bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) { if (ParseEscapedString(Data)) return true; - Out.EmitBytes(Data); + Out.EmitBytes(Data, DEFAULT_ADDRSPACE); if (ZeroTerminated) - Out.EmitBytes(StringRef("\0", 1)); + Out.EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE); - Lexer.Lex(); + Lex(); if (Lexer.is(AsmToken::EndOfStatement)) break; if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in '.ascii' or '.asciz' directive"); - Lexer.Lex(); + Lex(); } } - Lexer.Lex(); + Lex(); return false; } @@ -992,7 +1039,7 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) { if (ParseExpression(Value)) return true; - Out.EmitValue(Value, Size); + Out.EmitValue(Value, Size, DEFAULT_ADDRSPACE); if (Lexer.is(AsmToken::EndOfStatement)) break; @@ -1000,11 +1047,11 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) { // FIXME: Improve diagnostic. if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); - Lexer.Lex(); + Lex(); } } - Lexer.Lex(); + Lex(); return false; } @@ -1020,7 +1067,7 @@ bool AsmParser::ParseDirectiveSpace() { if (Lexer.isNot(AsmToken::EndOfStatement)) { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in '.space' directive"); - Lexer.Lex(); + Lex(); if (ParseAbsoluteExpression(FillExpr)) return true; @@ -1031,14 +1078,13 @@ bool AsmParser::ParseDirectiveSpace() { return TokError("unexpected token in '.space' directive"); } - Lexer.Lex(); + 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. - for (uint64_t i = 0, e = NumBytes; i != e; ++i) - Out.EmitValue(MCConstantExpr::Create(FillExpr, getContext()), 1); + Out.EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE); return false; } @@ -1052,7 +1098,7 @@ bool AsmParser::ParseDirectiveFill() { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in '.fill' directive"); - Lexer.Lex(); + Lex(); int64_t FillSize; if (ParseAbsoluteExpression(FillSize)) @@ -1060,7 +1106,7 @@ bool AsmParser::ParseDirectiveFill() { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in '.fill' directive"); - Lexer.Lex(); + Lex(); int64_t FillExpr; if (ParseAbsoluteExpression(FillExpr)) @@ -1069,13 +1115,14 @@ bool AsmParser::ParseDirectiveFill() { if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.fill' directive"); - Lexer.Lex(); + Lex(); if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8) return TokError("invalid '.fill' size, expected 1, 2, 4, or 8"); for (uint64_t i = 0, e = NumValues; i != e; ++i) - Out.EmitValue(MCConstantExpr::Create(FillExpr, getContext()), FillSize); + Out.EmitValue(MCConstantExpr::Create(FillExpr, getContext()), FillSize, + DEFAULT_ADDRSPACE); return false; } @@ -1093,7 +1140,7 @@ bool AsmParser::ParseDirectiveOrg() { if (Lexer.isNot(AsmToken::EndOfStatement)) { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in '.org' directive"); - Lexer.Lex(); + Lex(); if (ParseAbsoluteExpression(FillExpr)) return true; @@ -1102,7 +1149,7 @@ bool AsmParser::ParseDirectiveOrg() { return TokError("unexpected token in '.org' directive"); } - Lexer.Lex(); + Lex(); // FIXME: Only limited forms of relocatable expressions are accepted here, it // has to be relative to the current section. @@ -1126,7 +1173,7 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { if (Lexer.isNot(AsmToken::EndOfStatement)) { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); - Lexer.Lex(); + Lex(); // The fill expression can be omitted while specifying a maximum number of // alignment bytes, e.g: @@ -1140,7 +1187,7 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { if (Lexer.isNot(AsmToken::EndOfStatement)) { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); - Lexer.Lex(); + Lex(); MaxBytesLoc = Lexer.getLoc(); if (ParseAbsoluteExpression(MaxBytesToFill)) @@ -1151,7 +1198,7 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { } } - Lexer.Lex(); + Lex(); if (!HasFillExpr) { // FIXME: Sometimes fill with nop. @@ -1209,11 +1256,11 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr) { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); - Lexer.Lex(); + Lex(); } } - Lexer.Lex(); + Lex(); return false; } @@ -1229,7 +1276,7 @@ bool AsmParser::ParseDirectiveDarwinSymbolDesc() { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in '.desc' directive"); - Lexer.Lex(); + Lex(); SMLoc DescLoc = Lexer.getLoc(); int64_t DescValue; @@ -1239,7 +1286,7 @@ bool AsmParser::ParseDirectiveDarwinSymbolDesc() { if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.desc' directive"); - Lexer.Lex(); + Lex(); // Set the n_desc field of this Symbol to this DescValue Out.EmitSymbolDesc(Sym, DescValue); @@ -1260,7 +1307,7 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); - Lexer.Lex(); + Lex(); int64_t Size; SMLoc SizeLoc = Lexer.getLoc(); @@ -1270,16 +1317,23 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { int64_t Pow2Alignment = 0; SMLoc Pow2AlignmentLoc; if (Lexer.is(AsmToken::Comma)) { - Lexer.Lex(); + Lex(); Pow2AlignmentLoc = Lexer.getLoc(); if (ParseAbsoluteExpression(Pow2Alignment)) return true; + + // If this target takes alignments in bytes (not log) validate and convert. + if (Lexer.getMAI().getAlignmentIsInBytes()) { + if (!isPowerOf2_64(Pow2Alignment)) + return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); + Pow2Alignment = Log2_64(Pow2Alignment); + } } if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.comm' or '.lcomm' directive"); - Lexer.Lex(); + 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. @@ -1319,18 +1373,18 @@ bool AsmParser::ParseDirectiveDarwinZerofill() { if (Lexer.isNot(AsmToken::Identifier)) return TokError("expected segment name after '.zerofill' directive"); - StringRef Segment = Lexer.getTok().getString(); - Lexer.Lex(); + StringRef Segment = getTok().getString(); + Lex(); if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); - Lexer.Lex(); + Lex(); if (Lexer.isNot(AsmToken::Identifier)) return TokError("expected section name after comma in '.zerofill' " "directive"); - StringRef Section = Lexer.getTok().getString(); - Lexer.Lex(); + StringRef Section = getTok().getString(); + Lex(); // If this is the end of the line all that was wanted was to create the // the section but with no symbol. @@ -1344,19 +1398,19 @@ bool AsmParser::ParseDirectiveDarwinZerofill() { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); - Lexer.Lex(); + Lex(); if (Lexer.isNot(AsmToken::Identifier)) return TokError("expected identifier in directive"); // handle the identifier as the key symbol. SMLoc IDLoc = Lexer.getLoc(); - MCSymbol *Sym = CreateSymbol(Lexer.getTok().getString()); - Lexer.Lex(); + MCSymbol *Sym = CreateSymbol(getTok().getString()); + Lex(); if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); - Lexer.Lex(); + Lex(); int64_t Size; SMLoc SizeLoc = Lexer.getLoc(); @@ -1366,7 +1420,7 @@ bool AsmParser::ParseDirectiveDarwinZerofill() { int64_t Pow2Alignment = 0; SMLoc Pow2AlignmentLoc; if (Lexer.is(AsmToken::Comma)) { - Lexer.Lex(); + Lex(); Pow2AlignmentLoc = Lexer.getLoc(); if (ParseAbsoluteExpression(Pow2Alignment)) return true; @@ -1375,7 +1429,7 @@ bool AsmParser::ParseDirectiveDarwinZerofill() { if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.zerofill' directive"); - Lexer.Lex(); + Lex(); if (Size < 0) return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less " @@ -1408,7 +1462,7 @@ bool AsmParser::ParseDirectiveDarwinSubsectionsViaSymbols() { if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.subsections_via_symbols' directive"); - Lexer.Lex(); + Lex(); Out.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols); @@ -1426,15 +1480,15 @@ bool AsmParser::ParseDirectiveAbort() { if (Lexer.isNot(AsmToken::String)) return TokError("expected string in '.abort' directive"); - Str = Lexer.getTok().getString(); + Str = getTok().getString(); - Lexer.Lex(); + Lex(); } if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.abort' directive"); - Lexer.Lex(); + Lex(); // FIXME: Handle here. if (Str.empty()) @@ -1457,7 +1511,7 @@ bool AsmParser::ParseDirectiveDarwinLsym() { if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in '.lsym' directive"); - Lexer.Lex(); + Lex(); const MCExpr *Value; SMLoc StartLoc = Lexer.getLoc(); @@ -1467,7 +1521,7 @@ bool AsmParser::ParseDirectiveDarwinLsym() { if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.lsym' directive"); - Lexer.Lex(); + Lex(); // We don't currently support this directive. // @@ -1482,9 +1536,9 @@ bool AsmParser::ParseDirectiveInclude() { if (Lexer.isNot(AsmToken::String)) return TokError("expected string in '.include' directive"); - std::string Filename = Lexer.getTok().getString(); + std::string Filename = getTok().getString(); SMLoc IncludeLoc = Lexer.getLoc(); - Lexer.Lex(); + Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.include' directive"); @@ -1494,10 +1548,10 @@ bool AsmParser::ParseDirectiveInclude() { // Attempt to switch the lexer to the included file before consuming the end // of statement to avoid losing it when we switch. - if (Lexer.EnterIncludeFile(Filename)) { - Lexer.PrintMessage(IncludeLoc, - "Could not find include file '" + Filename + "'", - "error"); + if (EnterIncludeFile(Filename)) { + PrintMessage(IncludeLoc, + "Could not find include file '" + Filename + "'", + "error"); return true; } @@ -1510,12 +1564,12 @@ bool AsmParser::ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump) { if (Lexer.isNot(AsmToken::String)) return TokError("expected string in '.dump' or '.load' directive"); - Lexer.Lex(); + Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.dump' or '.load' directive"); - Lexer.Lex(); + Lex(); // FIXME: If/when .dump and .load are implemented they will be done in the // the assembly parser and not have any need for an MCStreamer API. @@ -1531,7 +1585,7 @@ bool AsmParser::ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump) { /// ::= .if expression bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { // Consume the identifier that was the .if directive - Lexer.Lex(); + Lex(); TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; @@ -1546,7 +1600,7 @@ bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.if' directive"); - Lexer.Lex(); + Lex(); TheCondState.CondMet = ExprValue; TheCondState.Ignore = !TheCondState.CondMet; @@ -1565,7 +1619,7 @@ bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { TheCondState.TheCond = AsmCond::ElseIfCond; // Consume the identifier that was the .elseif directive - Lexer.Lex(); + Lex(); bool LastIgnoreState = false; if (!TheCondStack.empty()) @@ -1582,7 +1636,7 @@ bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.elseif' directive"); - Lexer.Lex(); + Lex(); TheCondState.CondMet = ExprValue; TheCondState.Ignore = !TheCondState.CondMet; } @@ -1594,12 +1648,12 @@ bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { /// ::= .else bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { // Consume the identifier that was the .else directive - Lexer.Lex(); + Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.else' directive"); - Lexer.Lex(); + Lex(); if (TheCondState.TheCond != AsmCond::IfCond && TheCondState.TheCond != AsmCond::ElseIfCond) @@ -1621,12 +1675,12 @@ bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { /// ::= .endif bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) { // Consume the identifier that was the .endif directive - Lexer.Lex(); + Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.endif' directive"); - Lexer.Lex(); + Lex(); if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty()) @@ -1646,8 +1700,8 @@ bool AsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { // FIXME: I'm not sure what this is. int64_t FileNumber = -1; if (Lexer.is(AsmToken::Integer)) { - FileNumber = Lexer.getTok().getIntVal(); - Lexer.Lex(); + FileNumber = getTok().getIntVal(); + Lex(); if (FileNumber < 1) return TokError("file number less than one"); @@ -1656,8 +1710,8 @@ bool AsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { if (Lexer.isNot(AsmToken::String)) return TokError("unexpected token in '.file' directive"); - StringRef ATTRIBUTE_UNUSED FileName = Lexer.getTok().getString(); - Lexer.Lex(); + StringRef ATTRIBUTE_UNUSED FileName = getTok().getString(); + Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.file' directive"); @@ -1674,9 +1728,9 @@ bool AsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) { if (Lexer.isNot(AsmToken::Integer)) return TokError("unexpected token in '.line' directive"); - int64_t LineNumber = Lexer.getTok().getIntVal(); + int64_t LineNumber = getTok().getIntVal(); (void) LineNumber; - Lexer.Lex(); + Lex(); // FIXME: Do something with the .line. } @@ -1695,26 +1749,26 @@ bool AsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { return TokError("unexpected token in '.loc' directive"); // FIXME: What are these fields? - int64_t FileNumber = Lexer.getTok().getIntVal(); + int64_t FileNumber = getTok().getIntVal(); (void) FileNumber; // FIXME: Validate file. - Lexer.Lex(); + Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) { if (Lexer.isNot(AsmToken::Integer)) return TokError("unexpected token in '.loc' directive"); - int64_t Param2 = Lexer.getTok().getIntVal(); + int64_t Param2 = getTok().getIntVal(); (void) Param2; - Lexer.Lex(); + Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) { if (Lexer.isNot(AsmToken::Integer)) return TokError("unexpected token in '.loc' directive"); - int64_t Param3 = Lexer.getTok().getIntVal(); + int64_t Param3 = getTok().getIntVal(); (void) Param3; - Lexer.Lex(); + Lex(); // FIXME: Do something with the .loc. } diff --git a/tools/llvm-mc/AsmParser.h b/tools/llvm-mc/AsmParser.h index 171dfcd..9336d35 100644 --- a/tools/llvm-mc/AsmParser.h +++ b/tools/llvm-mc/AsmParser.h @@ -25,21 +25,28 @@ namespace llvm { class AsmCond; +class AsmToken; class MCContext; class MCExpr; class MCInst; class MCStreamer; class MCAsmInfo; class MCValue; +class SourceMgr; class TargetAsmParser; class Twine; class AsmParser : public MCAsmParser { -private: +private: AsmLexer Lexer; MCContext &Ctx; MCStreamer &Out; + SourceMgr &SrcMgr; TargetAsmParser *TargetParser; + + /// This is the current buffer index we're lexing from as managed by the + /// SourceMgr object. + int CurBuffer; AsmCond TheCondState; std::vector<AsmCond> TheCondStack; @@ -79,8 +86,11 @@ public: virtual void Warning(SMLoc L, const Twine &Meg); virtual bool Error(SMLoc L, const Twine &Msg); - virtual bool ParseExpression(const MCExpr *&Res); - virtual bool ParseParenExpression(const MCExpr *&Res); + const AsmToken &Lex(); + + bool ParseExpression(const MCExpr *&Res); + virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc); + virtual bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc); virtual bool ParseAbsoluteExpression(int64_t &Res); /// } @@ -99,15 +109,20 @@ private: bool TokError(const char *Msg); + void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type) const; + + /// EnterIncludeFile - Enter the specified file. This returns true on failure. + bool EnterIncludeFile(const std::string &Filename); + bool ParseConditionalAssemblyDirectives(StringRef Directive, SMLoc DirectiveLoc); void EatToEndOfStatement(); bool ParseAssignment(const StringRef &Name); - bool ParsePrimaryExpr(const MCExpr *&Res); - bool ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res); - bool ParseParenExpr(const MCExpr *&Res); + bool ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc); + bool ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc); + bool ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc); /// ParseIdentifier - Parse an identifier or string (as a quoted identifier) /// and set \arg Res to the identifier contents. diff --git a/tools/llvm-mc/CMakeLists.txt b/tools/llvm-mc/CMakeLists.txt index 46c5c6b..49c2932 100644 --- a/tools/llvm-mc/CMakeLists.txt +++ b/tools/llvm-mc/CMakeLists.txt @@ -1,8 +1,6 @@ -set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC) +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC MCParser) add_llvm_tool(llvm-mc llvm-mc.cpp - AsmLexer.cpp - AsmParser.cpp Disassembler.cpp ) diff --git a/tools/llvm-mc/Makefile b/tools/llvm-mc/Makefile index 9bfb773..5ce1a8f 100644 --- a/tools/llvm-mc/Makefile +++ b/tools/llvm-mc/Makefile @@ -13,12 +13,13 @@ TOOLNAME = llvm-mc # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 NO_INSTALL = 1 +CXXFLAGS = -fno-rtti # Include this here so we can get the configuration of the targets # that have been configured for construction. We have to do this # early so we can set up LINK_COMPONENTS before including Makefile.rules include $(LEVEL)/Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) MC support +LINK_COMPONENTS := $(TARGETS_TO_BUILD) MCParser MC support include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 30cdfba..342ae99 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCInstPrinter.h" @@ -28,10 +28,11 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/System/Signals.h" #include "llvm/Target/TargetAsmParser.h" +#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetMachine.h" // FIXME. #include "llvm/Target/TargetSelect.h" -#include "AsmParser.h" +#include "llvm/MC/MCParser/AsmParser.h" #include "Disassembler.h" using namespace llvm; @@ -133,14 +134,14 @@ static int AsLexInput(const char *ProgName) { const MCAsmInfo *MAI = TheTarget->createAsmInfo(TripleName); assert(MAI && "Unable to create target asm info!"); - AsmLexer Lexer(SrcMgr, *MAI); + AsmLexer Lexer(*MAI); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { switch (Lexer.getKind()) { default: - Lexer.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); + SrcMgr.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); Error = true; break; case AsmToken::Error: @@ -263,7 +264,9 @@ static int AssembleInput(const char *ProgName) { IP.reset(TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *Out)); if (ShowEncoding) CE.reset(TheTarget->createCodeEmitter(*TM)); - Str.reset(createAsmStreamer(Ctx, *Out, *MAI, IP.get(), CE.get())); + Str.reset(createAsmStreamer(Ctx, *Out, *MAI, + TM->getTargetData()->isLittleEndian(), + /*asmverbose*/true, IP.get(), CE.get())); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); CE.reset(TheTarget->createCodeEmitter(*TM)); diff --git a/tools/llvm-nm/Makefile b/tools/llvm-nm/Makefile index ecf5f8c..bdefaa6 100644 --- a/tools/llvm-nm/Makefile +++ b/tools/llvm-nm/Makefile @@ -13,5 +13,6 @@ LINK_COMPONENTS = archive bitreader # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/tools/llvm-prof/Makefile b/tools/llvm-prof/Makefile index 86eb54d..b1fd330 100644 --- a/tools/llvm-prof/Makefile +++ b/tools/llvm-prof/Makefile @@ -13,5 +13,6 @@ LINK_COMPONENTS = bitreader analysis # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 93eb0a5..46e967a 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -32,13 +32,13 @@ #include "llvm/CodeGen/FileWriters.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/StandardPasses.h" #include "llvm/Support/SystemUtils.h" #include "llvm/System/Host.h" #include "llvm/System/Program.h" #include "llvm/System/Signals.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetOptions.h" #include "llvm/MC/MCAsmInfo.h" @@ -323,19 +323,18 @@ void LTOCodeGenerator::applyScopeRestrictions() // mark which symbols can not be internalized if ( !_mustPreserveSymbols.empty() ) { - Mangler mangler(*mergedModule, - _target->getMCAsmInfo()->getGlobalPrefix()); + Mangler mangler(*_target->getMCAsmInfo()); std::vector<const char*> mustPreserveList; for (Module::iterator f = mergedModule->begin(), e = mergedModule->end(); f != e; ++f) { if ( !f->isDeclaration() - && _mustPreserveSymbols.count(mangler.getMangledName(f)) ) + && _mustPreserveSymbols.count(mangler.getNameWithPrefix(f)) ) mustPreserveList.push_back(::strdup(f->getNameStr().c_str())); } for (Module::global_iterator v = mergedModule->global_begin(), e = mergedModule->global_end(); v != e; ++v) { if ( !v->isDeclaration() - && _mustPreserveSymbols.count(mangler.getMangledName(v)) ) + && _mustPreserveSymbols.count(mangler.getNameWithPrefix(v)) ) mustPreserveList.push_back(::strdup(v->getNameStr().c_str())); } passes.add(createInternalizePass(mustPreserveList)); @@ -403,14 +402,12 @@ bool LTOCodeGenerator::generateAssemblyCode(formatted_raw_ostream& out, switch (_target->addPassesToEmitFile(*codeGenPasses, out, TargetMachine::AssemblyFile, CodeGenOpt::Aggressive)) { - case FileModel::MachOFile: - oce = AddMachOWriter(*codeGenPasses, out, *_target); - break; case FileModel::ElfFile: oce = AddELFWriter(*codeGenPasses, out, *_target); break; case FileModel::AsmFile: break; + case FileModel::MachOFile: case FileModel::Error: case FileModel::None: errMsg = "target file type not supported"; diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index bce4162..64de668 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -22,12 +22,12 @@ #include "llvm/ADT/Triple.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/SystemUtils.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MathExtras.h" #include "llvm/System/Host.h" #include "llvm/System/Path.h" #include "llvm/System/Process.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/SubtargetFeature.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetMachine.h" @@ -320,7 +320,7 @@ void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler, return; // string is owned by _defines - const char* symbolName = ::strdup(mangler.getMangledName(def).c_str()); + const char* symbolName = ::strdup(mangler.getNameWithPrefix(def).c_str()); // set alignment part log2() can have rounding errors uint32_t align = def->getAlignment(); @@ -393,7 +393,7 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler) if (isa<GlobalAlias>(decl)) return; - std::string name = mangler.getMangledName(decl); + std::string name = mangler.getNameWithPrefix(decl); // we already have the symbol if (_undefines.find(name) != _undefines.end()) @@ -439,15 +439,7 @@ void LTOModule::lazyParseSymbols() _symbolsParsed = true; // Use mangler to add GlobalPrefix to names to match linker names. - Mangler mangler(*_module, _target->getMCAsmInfo()->getGlobalPrefix()); - // add chars used in ObjC method names so method names aren't mangled - mangler.markCharAcceptable('['); - mangler.markCharAcceptable(']'); - mangler.markCharAcceptable('('); - mangler.markCharAcceptable(')'); - mangler.markCharAcceptable('-'); - mangler.markCharAcceptable('+'); - mangler.markCharAcceptable(' '); + Mangler mangler(*_target->getMCAsmInfo()); // add functions for (Module::iterator f = _module->begin(); f != _module->end(); ++f) { diff --git a/tools/lto/Makefile b/tools/lto/Makefile index 3120aa5..f0bc67c 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -17,6 +17,7 @@ include $(LEVEL)/Makefile.config LINK_LIBS_IN_SHARED = 1 SHARED_LIBRARY = 1 +CXXFLAGS = -fno-rtti LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader bitwriter diff --git a/tools/opt/Makefile b/tools/opt/Makefile index 726cad8..2f184a6 100644 --- a/tools/opt/Makefile +++ b/tools/opt/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../.. TOOLNAME = opt +CXXFLAGS = -fno-rtti LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index a636bd9..6ed8c9d 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -288,7 +288,17 @@ void AddOptimizationPasses(PassManager &MPM, FunctionPassManager &FPM, unsigned OptLevel) { createStandardFunctionPasses(&FPM, OptLevel); - llvm::Pass *InliningPass = OptLevel > 1 ? createFunctionInliningPass() : 0; + llvm::Pass *InliningPass = 0; + if (DisableInline) { + // No inlining pass + } else if (OptLevel) { + unsigned Threshold = 200; + if (OptLevel > 2) + Threshold = 250; + InliningPass = createFunctionInliningPass(Threshold); + } else { + InliningPass = createAlwaysInlinerPass(); + } createStandardModulePasses(&MPM, OptLevel, /*OptimizeSize=*/ false, UnitAtATime, @@ -373,24 +383,29 @@ int main(int argc, char **argv) { // FIXME: outs() is not binary! raw_ostream *Out = &outs(); // Default to printing to stdout... if (OutputFilename != "-") { - // Make sure that the Output file gets unlinked from the disk if we get a - // SIGINT - sys::RemoveFileOnSignal(sys::Path(OutputFilename)); - - std::string ErrorInfo; - Out = new raw_fd_ostream(OutputFilename.c_str(), ErrorInfo, - raw_fd_ostream::F_Binary); - if (!ErrorInfo.empty()) { - errs() << ErrorInfo << '\n'; - delete Out; - return 1; + if (NoOutput || AnalyzeOnly) { + errs() << "WARNING: The -o (output filename) option is ignored when\n" + "the --disable-output or --analyze options are used.\n"; + } else { + // Make sure that the Output file gets unlinked from the disk if we get a + // SIGINT + sys::RemoveFileOnSignal(sys::Path(OutputFilename)); + + std::string ErrorInfo; + Out = new raw_fd_ostream(OutputFilename.c_str(), ErrorInfo, + raw_fd_ostream::F_Binary); + if (!ErrorInfo.empty()) { + errs() << ErrorInfo << '\n'; + delete Out; + return 1; + } } } // If the output is set to be emitted to standard out, and standard out is a // console, print out a warning message and refuse to do it. We don't // impress anyone by spewing tons of binary goo to a terminal. - if (!Force && !NoOutput && !OutputAssembly) + if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly) if (CheckBitcodeOutputToConsole(*Out, !Quiet)) NoOutput = true; @@ -461,24 +476,26 @@ int main(int argc, char **argv) { errs() << argv[0] << ": cannot create pass: " << PassInf->getPassName() << "\n"; if (P) { - bool isBBPass = dynamic_cast<BasicBlockPass*>(P) != 0; - bool isLPass = !isBBPass && dynamic_cast<LoopPass*>(P) != 0; - bool isFPass = !isLPass && dynamic_cast<FunctionPass*>(P) != 0; - bool isCGSCCPass = !isFPass && dynamic_cast<CallGraphSCCPass*>(P) != 0; - addPass(Passes, P); if (AnalyzeOnly) { - if (isBBPass) + switch (P->getPassKind()) { + case PT_BasicBlock: Passes.add(new BasicBlockPassPrinter(PassInf)); - else if (isLPass) + break; + case PT_Loop: Passes.add(new LoopPassPrinter(PassInf)); - else if (isFPass) + break; + case PT_Function: Passes.add(new FunctionPassPrinter(PassInf)); - else if (isCGSCCPass) + break; + case PT_CallGraphSCC: Passes.add(new CallGraphSCCPassPrinter(PassInf)); - else + break; + default: Passes.add(new ModulePassPrinter(PassInf)); + break; + } } } @@ -517,7 +534,7 @@ int main(int argc, char **argv) { if (!NoVerify && !VerifyEach) Passes.add(createVerifierPass()); - // Write bitcode or assembly out to disk or outs() as the last step... + // Write bitcode or assembly out to disk or outs() as the last step... if (!NoOutput && !AnalyzeOnly) { if (OutputAssembly) Passes.add(createPrintModulePass(Out)); diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp index dda86fb..a58a087 100644 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp @@ -23,6 +23,9 @@ using namespace llvm; +int dummy; + +#if 0 namespace { struct FunctionEmittedEvent { @@ -235,3 +238,4 @@ testing::Environment* const jit_env = testing::AddGlobalTestEnvironment(new JITEnvironment); } // anonymous namespace +#endif diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp index 7f75afa..bed2d22 100644 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITTest.cpp @@ -58,6 +58,7 @@ std::string DumpFunction(const Function *F) { return Result; } +#if 0 class RecordingJITMemoryManager : public JITMemoryManager { const OwningPtr<JITMemoryManager> Base; public: @@ -178,6 +179,7 @@ public: return Base->endExceptionTable(F, TableStart, TableEnd, FrameRegister); } }; +#endif bool LoadAssemblyInto(Module *M, const char *assembly) { SMDiagnostic Error; @@ -195,11 +197,15 @@ class JITTest : public testing::Test { virtual void SetUp() { M = new Module("<main>", Context); MP = new ExistingModuleProvider(M); +#if 0 RJMM = new RecordingJITMemoryManager; RJMM->setPoisonMemory(true); +#endif std::string Error; TheJIT.reset(EngineBuilder(MP).setEngineKind(EngineKind::JIT) +#if 0 .setJITMemoryManager(RJMM) +#endif .setErrorStr(&Error).create()); ASSERT_TRUE(TheJIT.get() != NULL) << Error; } @@ -211,7 +217,9 @@ class JITTest : public testing::Test { LLVMContext Context; Module *M; // Owned by MP. ModuleProvider *MP; // Owned by ExecutionEngine. +#if 0 RecordingJITMemoryManager *RJMM; +#endif OwningPtr<ExecutionEngine> TheJIT; }; @@ -430,6 +438,7 @@ TEST_F(JITTest, ModuleDeletion) { TheJIT->getPointerToFunction(func); TheJIT->deleteModuleProvider(MP); +#if 0 SmallPtrSet<const void*, 2> FunctionsDeallocated; for (unsigned i = 0, e = RJMM->deallocateFunctionBodyCalls.size(); i != e; ++i) { @@ -463,6 +472,7 @@ TEST_F(JITTest, ModuleDeletion) { } EXPECT_EQ(RJMM->startExceptionTableCalls.size(), NumTablesDeallocated); +#endif } // ARM and PPC still emit stubs for calls since the target may be too far away @@ -497,14 +507,18 @@ TEST_F(JITTest, NoStubs) { // We should now allocate no more stubs, we have the code to foo // and the existing stub for bar. +#if 0 int stubsBefore = RJMM->stubsAllocated; +#endif Function *func = M->getFunction("main"); TheJIT->getPointerToFunction(func); Function *bar = M->getFunction("bar"); TheJIT->getPointerToFunction(bar); +#if 0 ASSERT_EQ(stubsBefore, RJMM->stubsAllocated); +#endif } #endif // !ARM && !PPC diff --git a/unittests/Support/System.cpp b/unittests/Support/System.cpp new file mode 100644 index 0000000..b3dd17d --- /dev/null +++ b/unittests/Support/System.cpp @@ -0,0 +1,16 @@ +//===- llvm/unittest/Support/System.cpp - System tests --===// +#include "gtest/gtest.h" +#include "llvm/System/TimeValue.h" +#include <time.h> + +using namespace llvm; +namespace { +class SystemTest : public ::testing::Test { +}; + +TEST_F(SystemTest, TimeValue) { + sys::TimeValue now = sys::TimeValue::now(); + time_t now_t = time(NULL); + EXPECT_TRUE(abs(now_t - now.toEpochTime()) < 2); +} +} diff --git a/unittests/VMCore/PassManagerTest.cpp b/unittests/VMCore/PassManagerTest.cpp index cb8f9eb..092ce3d 100644 --- a/unittests/VMCore/PassManagerTest.cpp +++ b/unittests/VMCore/PassManagerTest.cpp @@ -32,6 +32,10 @@ #include "llvm/Assembly/PrintModulePass.h" #include "gtest/gtest.h" +int dummy; + +#if 0 + namespace llvm { namespace { // ND = no deps @@ -525,3 +529,4 @@ namespace llvm { } } +#endif diff --git a/utils/GetSourceVersion b/utils/GetSourceVersion new file mode 100755 index 0000000..b25f2f9 --- /dev/null +++ b/utils/GetSourceVersion @@ -0,0 +1,27 @@ +#!/bin/sh + +usage() { + echo "usage: $0 <source root>" + echo " Prints the source control revision of the given source directory," + echo " the exact format of the revision string depends on the source " + echo " control system. If the source control system isn't known, the output" + echo " is empty and the exit code is 1." + exit 1 +} + +if [ $# != 1 ] || [ ! -d $1 ]; then + usage; +fi + +cd $1 +if [ -d .svn ]; then + svnversion +elif [ -d .git/svn ]; then + git svn info | grep 'Revision:' | cut -d: -f2- +elif [ -d .git ]; then + git log -1 --pretty=format:%H +else + exit 1; +fi + +exit 0 diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 019908b..ce1521d 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -465,6 +465,10 @@ struct InstructionInfo { if (Operands.size() != RHS.Operands.size()) return false; + // Otherwise, make sure the ordering of the two instructions is unambiguous + // by checking that either (a) a token or operand kind discriminates them, + // or (b) the ordering among equivalent kinds is consistent. + // Tokens and operand kinds are unambiguous (assuming a correct target // specific parser). for (unsigned i = 0, e = Operands.size(); i != e; ++i) @@ -1386,9 +1390,7 @@ static void EmitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, "return " + utostr(i + 1) + ";")); } - OS << "unsigned " << Target.getName() - << AsmParser->getValueAsString("AsmParserClassName") - << "::MatchRegisterName(const StringRef &Name) {\n"; + OS << "static unsigned MatchRegisterName(const StringRef &Name) {\n"; EmitStringMatcher("Name", Matches, OS); @@ -1447,6 +1449,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Emit the function to match a register name to number. EmitMatchRegisterName(Target, AsmParser, OS); + + OS << "#ifndef REGISTERS_ONLY\n\n"; // Generate the unified function to convert operands into an MCInst. EmitConvertToMCInst(Target, Info.Instructions, OS); @@ -1546,4 +1550,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " return true;\n"; OS << "}\n\n"; + + OS << "#endif // REGISTERS_ONLY\n"; } diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm index 25f6554..1fa3fdf 100755 --- a/utils/buildit/build_llvm +++ b/utils/buildit/build_llvm @@ -57,25 +57,20 @@ DARWIN_VERS=`uname -r | sed 's/\..*//'` echo DARWIN_VERS = $DARWIN_VERS if [ "x$RC_ProjectName" = "xllvmCore_Embedded" ]; then - DT_HOME=$DEST_DIR/Developer/Platforms/iPhoneOS.platform/Developer/usr - DEST_ROOT="/Developer/Platforms/iPhoneOS.platform/Developer$DEST_ROOT" -elif [ "x$RC_ProjectName" = "xllvmCore_EmbeddedHosted" ]; then - DT_HOME=$DEST_DIR/usr - DEST_ROOT="/Developer$DEST_ROOT" + DEST_DIR="$DEST_DIR/Developer/Platforms/iPhoneOS.platform" + mkdir -p "$DEST_DIR" +fi + +DEVELOPER_DIR="${DEVELOPER_DIR-Developer}" +if [ "x$RC_ProjectName" = "xllvmCore_EmbeddedHosted" ]; then + DT_HOME="$DEST_DIR/usr" HOST_SDKROOT=$SDKROOT else - DT_HOME=$DEST_DIR/Developer/usr - DEST_ROOT="/Developer$DEST_ROOT" -fi -if [ "x$DEVELOPER_BIN" != "x" ]; then - if [ "x$RC_ProjectName" = "xllvmCore_Embedded" ]; then - DT_HOME=$DEST_DIR/Developer/Platforms/iPhoneOS.platform/$DEVELOPER_DIR/usr - else - DT_HOME=$DEST_DIR/$DEVELOPER_DIR/usr - fi - DEST_ROOT="/$DEVELOPER_DIR$DEST_ROOT" + DT_HOME="$DEST_DIR/$DEVELOPER_DIR/usr" fi +DEST_ROOT="/$DEVELOPER_DIR$DEST_ROOT" + ################################################################################ # Run the build. @@ -350,7 +345,7 @@ find $DEST_DIR -name html.tar.gz -exec rm {} \; cd $DEST_DIR mkdir -p ./usr/lib/ cd usr/lib -ln -s ../../Developer/usr/lib/libLTO.dylib ./libLTO.dylib +ln -s ../../$DEVELOPER_DIR/usr/lib/libLTO.dylib ./libLTO.dylib ################################################################################ # w00t! Done! diff --git a/utils/lit/lit/Test.py b/utils/lit/lit/Test.py index 1f6556b..db2e032 100644 --- a/utils/lit/lit/Test.py +++ b/utils/lit/lit/Test.py @@ -70,7 +70,7 @@ class Test: self.elapsed = elapsed def getFullName(self): - return self.suite.config.name + '::' + '/'.join(self.path_in_suite) + return self.suite.config.name + ' :: ' + '/'.join(self.path_in_suite) def getSourcePath(self): return self.suite.getSourcePath(self.path_in_suite) diff --git a/utils/llvm.grm b/utils/llvm.grm index 86a707a..4499d4b 100644 --- a/utils/llvm.grm +++ b/utils/llvm.grm @@ -161,7 +161,6 @@ FuncAttr ::= noreturn | signext | readnone | readonly - | inlinehint | noinline | alwaysinline | optsize diff --git a/utils/mkpatch b/utils/mkpatch index d256d98..278a241 100755 --- a/utils/mkpatch +++ b/utils/mkpatch @@ -23,8 +23,8 @@ echo "mkpatch: Generating differences on all directories" svn diff -x -u >> "$NAME".patch.raw 2>&1 \ autoconf docs utils include lib/System lib/Support lib/VMCore lib/AsmParser \ lib/Bitcode lib/Analysis lib/Transforms lib/CodeGen lib/Target \ - lib/ExecutionEngine lib/Debugger lib/Linker \ - tools test unittests runtime projects examples win32 Xcode + lib/ExecutionEngine lib/Linker \ + tools test unittests runtime projects examples Xcode echo "mkpatch: Removing cruft from the patch file" sed -e '/^[?] .*/d' -e '/^cvs diff: Diffing/d' "$NAME".patch.raw | awk '\ diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim index 6e4a207..48a4c68 100644 --- a/utils/vim/llvm.vim +++ b/utils/vim/llvm.vim @@ -51,7 +51,7 @@ syn keyword llvmKeyword volatile fastcc coldcc cc ccc syn keyword llvmKeyword x86_stdcallcc x86_fastcallcc syn keyword llvmKeyword signext zeroext inreg sret nounwind noreturn syn keyword llvmKeyword nocapture byval nest readnone readonly noalias -syn keyword llvmKeyword inlinehint noinline alwaysinline optsize ssp sspreq +syn keyword llvmKeyword noinline alwaysinline optsize ssp sspreq syn keyword llvmKeyword noredzone noimplicitfloat naked syn keyword llvmKeyword module asm align tail to syn keyword llvmKeyword addrspace section alias sideeffect c gc |