mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Update LLVM to r98164.
This commit is contained in:
parent
f5a3459adf
commit
ea5b2dd11c
206 changed files with 3945 additions and 2392 deletions
|
|
@ -66,35 +66,64 @@ Archive.CMA := $(strip $(OCAMLC) -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \
|
|||
Compile.CMX := $(strip $(OCAMLOPT) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o)
|
||||
Archive.CMXA := $(strip $(OCAMLOPT) -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) -o)
|
||||
|
||||
ifdef OCAMLOPT
|
||||
Archive.EXE := $(strip $(OCAMLOPT) -cc $(CXX) $(OCAMLCFLAGS) $(UsedOcamLibs:%=%.cmxa) $(OCAMLDEBUGFLAG) -o)
|
||||
else
|
||||
Archive.EXE := $(strip $(OCAMLC) -cc $(CXX) $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG:%=%.cma) -o)
|
||||
endif
|
||||
|
||||
# Source files
|
||||
OcamlSources1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.ml))
|
||||
OcamlHeaders1 := $(OcamlSources1:.ml=.mli)
|
||||
OcamlHeaders1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.mli))
|
||||
|
||||
OcamlSources := $(OcamlSources1:$(PROJ_SRC_DIR)/%=$(ObjDir)/%)
|
||||
OcamlHeaders := $(OcamlHeaders1:$(PROJ_SRC_DIR)/%=$(ObjDir)/%)
|
||||
OcamlSources2 := $(filter-out $(ExcludeSources),$(OcamlSources1))
|
||||
OcamlHeaders2 := $(filter-out $(ExcludeHeaders),$(OcamlHeaders1))
|
||||
|
||||
OcamlSources := $(OcamlSources2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%)
|
||||
OcamlHeaders := $(OcamlHeaders2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%)
|
||||
|
||||
# Intermediate files
|
||||
LibraryCMA := $(ObjDir)/$(LIBRARYNAME).cma
|
||||
LibraryCMXA := $(ObjDir)/$(LIBRARYNAME).cmxa
|
||||
ObjectsCMI := $(OcamlSources:%.ml=%.cmi)
|
||||
ObjectsCMO := $(OcamlSources:%.ml=%.cmo)
|
||||
ObjectsCMX := $(OcamlSources:%.ml=%.cmx)
|
||||
|
||||
ifdef LIBRARYNAME
|
||||
LibraryCMA := $(ObjDir)/$(LIBRARYNAME).cma
|
||||
LibraryCMXA := $(ObjDir)/$(LIBRARYNAME).cmxa
|
||||
endif
|
||||
|
||||
ifdef TOOLNAME
|
||||
ToolEXE := $(ObjDir)/$(TOOLNAME)$(EXEEXT)
|
||||
endif
|
||||
|
||||
# Output files
|
||||
# The .cmo files are the only intermediates; all others are to be installed.
|
||||
LibraryA := $(OcamlDir)/lib$(LIBRARYNAME).a
|
||||
OutputCMA := $(LibraryCMA:$(ObjDir)/%.cma=$(OcamlDir)/%.cma)
|
||||
OutputCMXA := $(LibraryCMXA:$(ObjDir)/%.cmxa=$(OcamlDir)/%.cmxa)
|
||||
OutputsCMI := $(ObjectsCMI:$(ObjDir)/%.cmi=$(OcamlDir)/%.cmi)
|
||||
OutputsCMX := $(ObjectsCMX:$(ObjDir)/%.cmx=$(OcamlDir)/%.cmx)
|
||||
OutputLibs := $(UsedLibNames:%=$(OcamlDir)/%)
|
||||
|
||||
ifdef LIBRARYNAME
|
||||
LibraryA := $(OcamlDir)/lib$(LIBRARYNAME).a
|
||||
OutputCMA := $(LibraryCMA:$(ObjDir)/%.cma=$(OcamlDir)/%.cma)
|
||||
OutputCMXA := $(LibraryCMXA:$(ObjDir)/%.cmxa=$(OcamlDir)/%.cmxa)
|
||||
endif
|
||||
|
||||
ifdef TOOLNAME
|
||||
ifdef EXAMPLE_TOOL
|
||||
OutputEXE := $(ExmplDir)/$(strip $(TOOLNAME))$(EXEEXT)
|
||||
else
|
||||
OutputEXE := $(ToolDir)/$(strip $(TOOLNAME))$(EXEEXT)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Installation targets
|
||||
DestLibs := $(UsedLibNames:%=$(PROJ_libocamldir)/%)
|
||||
|
||||
ifdef LIBRARYNAME
|
||||
DestA := $(PROJ_libocamldir)/lib$(LIBRARYNAME).a
|
||||
DestCMA := $(PROJ_libocamldir)/$(LIBRARYNAME).cma
|
||||
DestCMXA := $(PROJ_libocamldir)/$(LIBRARYNAME).cmxa
|
||||
DestLibs := $(UsedLibNames:%=$(PROJ_libocamldir)/%)
|
||||
|
||||
endif
|
||||
|
||||
##===- Dependencies -------------------------------------------------------===##
|
||||
# Copy the sources into the intermediate directory because older ocamlc doesn't
|
||||
|
|
@ -106,18 +135,27 @@ $(ObjDir)/%.mli: $(PROJ_SRC_DIR)/%.mli $(ObjDir)/.dir
|
|||
$(ObjDir)/%.ml: $(PROJ_SRC_DIR)/%.ml $(ObjDir)/.dir
|
||||
$(Verb) $(CP) -f $< $@
|
||||
|
||||
$(ObjectsCMI): $(UsedOcamlInterfaces:%=$(OcamlDir)/%.cmi)
|
||||
|
||||
ifdef LIBRARYNAME
|
||||
$(ObjDir)/$(LIBRARYNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \
|
||||
$(OcamlDir)/.dir $(ObjDir)/.dir
|
||||
$(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@
|
||||
|
||||
$(ObjectsCMI): $(UsedOcamlInterfaces:%=$(OcamlDir)/%.cmi)
|
||||
|
||||
-include $(ObjDir)/$(LIBRARYNAME).ocamldep
|
||||
endif
|
||||
|
||||
ifdef TOOLNAME
|
||||
$(ObjDir)/$(TOOLNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \
|
||||
$(OcamlDir)/.dir $(ObjDir)/.dir
|
||||
$(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@
|
||||
|
||||
-include $(ObjDir)/$(TOOLNAME).ocamldep
|
||||
endif
|
||||
|
||||
##===- Build static library from C sources --------------------------------===##
|
||||
|
||||
ifneq ($(ObjectsO),)
|
||||
ifdef LibraryA
|
||||
all-local:: $(LibraryA)
|
||||
clean-local:: clean-a
|
||||
install-local:: install-a
|
||||
|
|
@ -160,7 +198,7 @@ $(OcamlDir)/%.o: $(LibDir)/%.o
|
|||
$(Verb) ln -sf $< $@
|
||||
|
||||
clean-deplibs:
|
||||
$(Verb) rm -f $(OutputLibs)
|
||||
$(Verb) $(RM) -f $(OutputLibs)
|
||||
|
||||
install-deplibs:
|
||||
$(Verb) $(MKDIR) $(PROJ_libocamldir)
|
||||
|
|
@ -169,11 +207,12 @@ install-deplibs:
|
|||
done
|
||||
|
||||
uninstall-deplibs:
|
||||
$(Verb) rm -f $(DestLibs)
|
||||
$(Verb) $(RM) -f $(DestLibs)
|
||||
|
||||
|
||||
##===- Build ocaml interfaces (.mli's -> .cmi's) --------------------------===##
|
||||
|
||||
ifneq ($(OcamlHeaders),)
|
||||
all-local:: build-cmis
|
||||
clean-local:: clean-cmis
|
||||
install-local:: install-cmis
|
||||
|
|
@ -212,10 +251,16 @@ uninstall-cmis::
|
|||
$(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \
|
||||
$(RM) -f "$(PROJ_libocamldir)/$$i"; \
|
||||
done
|
||||
endif
|
||||
|
||||
|
||||
##===- Build ocaml bytecode archive (.ml's -> .cmo's -> .cma) -------------===##
|
||||
|
||||
$(ObjDir)/%.cmo: $(ObjDir)/%.ml
|
||||
$(Echo) "Compiling $(notdir $<) for $(BuildMode) build"
|
||||
$(Verb) $(Compile.CMO) $@ $<
|
||||
|
||||
ifdef LIBRARYNAME
|
||||
all-local:: $(OutputCMA)
|
||||
clean-local:: clean-cma
|
||||
install-local:: install-cma
|
||||
|
|
@ -228,10 +273,6 @@ $(LibraryCMA): $(ObjectsCMO) $(OcamlDir)/.dir
|
|||
$(Echo) "Archiving $(notdir $@) for $(BuildMode) build"
|
||||
$(Verb) $(Archive.CMA) $@ $(ObjectsCMO)
|
||||
|
||||
$(ObjDir)/%.cmo: $(ObjDir)/%.ml
|
||||
$(Echo) "Compiling $(notdir $<) for $(BuildMode) build"
|
||||
$(Verb) $(Compile.CMO) $@ $<
|
||||
|
||||
clean-cma::
|
||||
$(Verb) $(RM) -f $(OutputCMA) $(UsedLibNames:%=$(OcamlDir)/%)
|
||||
|
||||
|
|
@ -243,7 +284,7 @@ install-cma:: $(OutputCMA)
|
|||
uninstall-cma::
|
||||
$(Echo) "Uninstalling $(DestCMA)"
|
||||
-$(Verb) $(RM) -f $(DestCMA)
|
||||
|
||||
endif
|
||||
|
||||
##===- Build optimized ocaml archive (.ml's -> .cmx's -> .cmxa, .a) -------===##
|
||||
|
||||
|
|
@ -251,6 +292,14 @@ uninstall-cma::
|
|||
# If unavailable, 'configure' will not define OCAMLOPT in Makefile.config.
|
||||
ifdef OCAMLOPT
|
||||
|
||||
$(OcamlDir)/%.cmx: $(ObjDir)/%.cmx
|
||||
$(Verb) $(CP) -f $< $@
|
||||
|
||||
$(ObjDir)/%.cmx: $(ObjDir)/%.ml
|
||||
$(Echo) "Compiling optimized $(notdir $<) for $(BuildMode) build"
|
||||
$(Verb) $(Compile.CMX) $@ $<
|
||||
|
||||
ifdef LIBRARYNAME
|
||||
all-local:: $(OutputCMXA) $(OutputsCMX)
|
||||
clean-local:: clean-cmxa
|
||||
install-local:: install-cmxa
|
||||
|
|
@ -260,18 +309,11 @@ $(OutputCMXA): $(LibraryCMXA)
|
|||
$(Verb) $(CP) -f $< $@
|
||||
$(Verb) $(CP) -f $(<:.cmxa=.a) $(@:.cmxa=.a)
|
||||
|
||||
$(OcamlDir)/%.cmx: $(ObjDir)/%.cmx
|
||||
$(Verb) $(CP) -f $< $@
|
||||
|
||||
$(LibraryCMXA): $(ObjectsCMX)
|
||||
$(Echo) "Archiving $(notdir $@) for $(BuildMode) build"
|
||||
$(Verb) $(Archive.CMXA) $@ $(ObjectsCMX)
|
||||
$(Verb) $(RM) -f $(@:.cmxa=.o)
|
||||
|
||||
$(ObjDir)/%.cmx: $(ObjDir)/%.ml
|
||||
$(Echo) "Compiling optimized $(notdir $<) for $(BuildMode) build"
|
||||
$(Verb) $(Compile.CMX) $@ $<
|
||||
|
||||
clean-cmxa::
|
||||
$(Verb) $(RM) -f $(OutputCMXA) $(OutputCMXA:.cmxa=.a) $(OutputsCMX)
|
||||
|
||||
|
|
@ -295,7 +337,27 @@ uninstall-cmxa::
|
|||
$(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \
|
||||
$(RM) -f $(PROJ_libocamldir)/$$i; \
|
||||
done
|
||||
endif
|
||||
endif
|
||||
|
||||
##===- Build executables --------------------------------------------------===##
|
||||
|
||||
ifdef TOOLNAME
|
||||
all-local:: $(OutputEXE)
|
||||
clean-local:: clean-exe
|
||||
|
||||
$(OutputEXE): $(ToolEXE) $(OcamlDir)/.dir
|
||||
$(Verb) $(CP) -f $< $@
|
||||
|
||||
ifndef OCAMLOPT
|
||||
$(ToolEXE): $(ObjectsCMO) $(OcamlDir)/.dir
|
||||
$(Echo) "Archiving $(notdir $@) for $(BuildMode) build"
|
||||
$(Verb) $(Archive.EXE) $@ $<
|
||||
else
|
||||
$(ToolEXE): $(ObjectsCMX) $(OcamlDir)/.dir
|
||||
$(Echo) "Archiving $(notdir $@) for $(BuildMode) build"
|
||||
$(Verb) $(Archive.EXE) $@ $<
|
||||
endif
|
||||
endif
|
||||
|
||||
##===- Generate documentation ---------------------------------------------===##
|
||||
|
|
@ -325,7 +387,10 @@ printcamlvars::
|
|||
$(Echo) "LibraryCMA : " '$(LibraryCMA)'
|
||||
$(Echo) "LibraryCMXA : " '$(LibraryCMXA)'
|
||||
$(Echo) "OcamlSources1: " '$(OcamlSources1)'
|
||||
$(Echo) "OcamlSources2: " '$(OcamlSources2)'
|
||||
$(Echo) "OcamlSources : " '$(OcamlSources)'
|
||||
$(Echo) "OcamlHeaders1: " '$(OcamlHeaders1)'
|
||||
$(Echo) "OcamlHeaders2: " '$(OcamlHeaders2)'
|
||||
$(Echo) "OcamlHeaders : " '$(OcamlHeaders)'
|
||||
$(Echo) "ObjectsCMI : " '$(ObjectsCMI)'
|
||||
$(Echo) "ObjectsCMO : " '$(ObjectsCMO)'
|
||||
|
|
@ -340,4 +405,6 @@ printcamlvars::
|
|||
.PHONY: printcamlvars build-cmis \
|
||||
clean-a clean-cmis clean-cma clean-cmxa \
|
||||
install-a install-cmis install-cma install-cmxa \
|
||||
uninstall-a uninstall-cmis uninstall-cma uninstall-cmxa
|
||||
install-exe \
|
||||
uninstall-a uninstall-cmis uninstall-cma uninstall-cmxa \
|
||||
uninstall-exe
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@
|
|||
<li><a href="#targetimpls">Target-specific Implementation Notes</a>
|
||||
<ul>
|
||||
<li><a href="#tailcallopt">Tail call optimization</a></li>
|
||||
<li><a href="#sibcallopt">Sibling call optimization</a></li>
|
||||
<li><a href="#x86">The X86 backend</a></li>
|
||||
<li><a href="#ppc">The PowerPC backend</a>
|
||||
<ul>
|
||||
|
|
@ -1731,6 +1732,50 @@ define fastcc i32 @tailcaller(i32 %in1, i32 %in2) {
|
|||
(because one or more of above constraints are not met) to be followed by a
|
||||
readjustment of the stack. So performance might be worse in such cases.</p>
|
||||
|
||||
</div>
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="sibcallopt">Sibling call optimization</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>Sibling call optimization is a restricted form of tail call optimization.
|
||||
Unlike tail call optimization described in the previous section, it can be
|
||||
performed automatically on any tail calls when <tt>-tailcallopt</tt> option
|
||||
is not specified.</p>
|
||||
|
||||
<p>Sibling call optimization is currently performed on x86/x86-64 when the
|
||||
following constraints are met:</p>
|
||||
|
||||
<ul>
|
||||
<li>Caller and callee have the same calling convention. It can be either
|
||||
<tt>c</tt> or <tt>fastcc</tt>.
|
||||
|
||||
<li>The call is a tail call - in tail position (ret immediately follows call
|
||||
and ret uses value of call or is void).</li>
|
||||
|
||||
<li>Caller and callee have matching return type or the callee result is not
|
||||
used.
|
||||
|
||||
<li>If any of the callee arguments are being passed in stack, they must be
|
||||
available in caller's own incoming argument stack and the frame offsets
|
||||
must be the same.
|
||||
</ul>
|
||||
|
||||
<p>Example:</p>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
declare i32 @bar(i32, i32)
|
||||
|
||||
define i32 @foo(i32 %a, i32 %b, i32 %c) {
|
||||
entry:
|
||||
%0 = tail call i32 @bar(i32 %a, i32 %b)
|
||||
ret i32 %0
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
|
|
@ -2116,7 +2161,7 @@ MOVSX32rm16 -> movsx, 32-bit register, 16-bit memory
|
|||
|
||||
<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-03-02 02:11:08 +0100 (Tue, 02 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-08 22:05:02 +0100 (Mon, 08 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -5149,8 +5149,11 @@ Loop: ; Infinite loop that counts from 0 on up...
|
|||
a <a href="#i_ret"><tt>ret</tt></a> instruction. If the "tail" marker is
|
||||
present, the function call is eligible for tail call optimization,
|
||||
but <a href="CodeGenerator.html#tailcallopt">might not in fact be
|
||||
optimized into a jump</a>. As of this writing, the extra requirements for
|
||||
a call to actually be optimized are:
|
||||
optimized into a jump</a>. The code generator may optimize calls marked
|
||||
"tail" with either 1) automatic <a href="CodeGenerator.html#sibcallopt">
|
||||
sibling call optimization</a> when the caller and callee have
|
||||
matching signatures, or 2) forced tail call optimization when the
|
||||
following extra requirements are met:
|
||||
<ul>
|
||||
<li>Caller and callee both have the calling
|
||||
convention <tt>fastcc</tt>.</li>
|
||||
|
|
@ -7470,7 +7473,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-03-05 00:44:48 +0100 (Fri, 05 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-08 22:05:02 +0100 (Mon, 08 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
<li><a href="#debug_info_descriptors">Debug information descriptors</a>
|
||||
<ul>
|
||||
<li><a href="#format_compile_units">Compile unit descriptors</a></li>
|
||||
<li><a href="#format_files">File descriptors</a></li>
|
||||
<li><a href="#format_global_variables">Global variable descriptors</a></li>
|
||||
<li><a href="#format_subprograms">Subprogram descriptors</a></li>
|
||||
<li><a href="#format_blocks">Block descriptors</a></li>
|
||||
|
|
@ -255,7 +256,7 @@ height="369">
|
|||
<p>To provide basic functionality, the LLVM debugger does have to make some
|
||||
assumptions about the source-level language being debugged, though it keeps
|
||||
these to a minimum. The only common features that the LLVM debugger assumes
|
||||
exist are <a href="#format_compile_units">source files</a>,
|
||||
exist are <a href="#format_files">source files</a>,
|
||||
and <a href="#format_global_variables">program objects</a>. These abstract
|
||||
objects are used by a debugger to form stack traces, show information about
|
||||
local variables, etc.</p>
|
||||
|
|
@ -307,8 +308,8 @@ height="369">
|
|||
of tags are loosely bound to the tag values of DWARF information entries.
|
||||
However, that does not restrict the use of the information supplied to DWARF
|
||||
targets. To facilitate versioning of debug information, the tag is augmented
|
||||
with the current debug version (LLVMDebugVersion = 7 << 16 or 0x70000 or
|
||||
458752.)</a></p>
|
||||
with the current debug version (LLVMDebugVersion = 8 << 16 or 0x80000 or
|
||||
524288.)</a></p>
|
||||
|
||||
<p>The details of the various descriptors follow.</p>
|
||||
|
||||
|
|
@ -346,18 +347,36 @@ height="369">
|
|||
that produced it.</p>
|
||||
|
||||
<p>Compile unit descriptors provide the root context for objects declared in a
|
||||
specific source file. Global variables and top level functions would be
|
||||
defined using this context. Compile unit descriptors also provide context
|
||||
for source line correspondence.</p>
|
||||
specific compilation unit. File descriptors are defined using this context.</p>
|
||||
|
||||
<p>Each input file is encoded as a separate compile unit in LLVM debugging
|
||||
information output. However, many target specific tool chains prefer to
|
||||
encode only one compile unit in an object file. In this situation, the LLVM
|
||||
code generator will include debugging information entities in the compile
|
||||
unit that is marked as main compile unit. The code generator accepts maximum
|
||||
one main compile unit per module. If a module does not contain any main
|
||||
compile unit then the code generator will emit multiple compile units in the
|
||||
output object file.</p>
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="format_files">File descriptors</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
!0 = metadata !{
|
||||
i32, ;; Tag = 41 + <a href="#LLVMDebugVersion">LLVMDebugVersion</a>
|
||||
;; (DW_TAG_file_type)
|
||||
metadata, ;; Source file name
|
||||
metadata, ;; Source file directory (includes trailing slash)
|
||||
metadata ;; Reference to compile unit where defined
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>These descriptors contain informations for a file. Global variables and top
|
||||
level functions would be defined using this context.k File descriptors also
|
||||
provide context for source line correspondence. </p>
|
||||
|
||||
<p>Each input file is encoded as a separate file descriptor in LLVM debugging
|
||||
information output. Each file descriptor would be defined using a
|
||||
compile unit. </p>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -378,7 +397,7 @@ height="369">
|
|||
metadata, ;; Name
|
||||
metadata, ;; Display name (fully qualified C++ name)
|
||||
metadata, ;; MIPS linkage name (for C++)
|
||||
metadata, ;; Reference to compile unit where defined
|
||||
metadata, ;; Reference to file where defined
|
||||
i32, ;; Line number where defined
|
||||
metadata, ;; Reference to type descriptor
|
||||
i1, ;; True if the global is local to compile unit (static)
|
||||
|
|
@ -410,7 +429,7 @@ provide details such as name, type and where the variable is defined.</p>
|
|||
metadata, ;; Name
|
||||
metadata, ;; Display name (fully qualified C++ name)
|
||||
metadata, ;; MIPS linkage name (for C++)
|
||||
metadata, ;; Reference to compile unit where defined
|
||||
metadata, ;; Reference to file where defined
|
||||
i32, ;; Line number where defined
|
||||
metadata, ;; Reference to type descriptor
|
||||
i1, ;; True if the global is local to compile unit (static)
|
||||
|
|
@ -461,7 +480,7 @@ provide details such as name, type and where the variable is defined.</p>
|
|||
;; (DW_TAG_base_type)
|
||||
metadata, ;; Reference to context (typically a compile unit)
|
||||
metadata, ;; Name (may be "" for anonymous types)
|
||||
metadata, ;; Reference to compile unit where defined (may be NULL)
|
||||
metadata, ;; Reference to file where defined (may be NULL)
|
||||
i32, ;; Line number where defined (may be 0)
|
||||
i64, ;; Size in bits
|
||||
i64, ;; Alignment in bits
|
||||
|
|
@ -512,7 +531,7 @@ DW_ATE_unsigned_char = 8
|
|||
i32, ;; Tag (see below)
|
||||
metadata, ;; Reference to context
|
||||
metadata, ;; Name (may be "" for anonymous types)
|
||||
metadata, ;; Reference to compile unit where defined (may be NULL)
|
||||
metadata, ;; Reference to file where defined (may be NULL)
|
||||
i32, ;; Line number where defined (may be 0)
|
||||
i32, ;; Size in bits
|
||||
i32, ;; Alignment in bits
|
||||
|
|
@ -580,7 +599,7 @@ DW_TAG_restrict_type = 55
|
|||
i32, ;; Tag (see below)
|
||||
metadata, ;; Reference to context
|
||||
metadata, ;; Name (may be "" for anonymous types)
|
||||
metadata, ;; Reference to compile unit where defined (may be NULL)
|
||||
metadata, ;; Reference to file where defined (may be NULL)
|
||||
i32, ;; Line number where defined (may be 0)
|
||||
i64, ;; Size in bits
|
||||
i64, ;; Alignment in bits
|
||||
|
|
@ -715,7 +734,7 @@ DW_TAG_inheritance = 28
|
|||
i32, ;; Tag (see below)
|
||||
metadata, ;; Context
|
||||
metadata, ;; Name
|
||||
metadata, ;; Reference to compile unit where defined
|
||||
metadata, ;; Reference to file where defined
|
||||
i32, ;; Line number where defined
|
||||
metadata ;; Type descriptor
|
||||
}
|
||||
|
|
@ -1012,10 +1031,10 @@ int main(int argc, char *argv[]) {
|
|||
<pre>
|
||||
...
|
||||
;;
|
||||
;; Define the compile unit for the source file "/Users/mine/sources/MySource.cpp".
|
||||
;; Define the compile unit for the main source file "/Users/mine/sources/MySource.cpp".
|
||||
;;
|
||||
!3 = metadata !{
|
||||
i32 458769, ;; Tag
|
||||
!2 = metadata !{
|
||||
i32 524305, ;; Tag
|
||||
i32 0, ;; Unused
|
||||
i32 4, ;; Language Id
|
||||
metadata !"MySource.cpp",
|
||||
|
|
@ -1027,19 +1046,24 @@ int main(int argc, char *argv[]) {
|
|||
i32 0} ;; Runtime version
|
||||
|
||||
;;
|
||||
;; Define the compile unit for the header file "/Users/mine/sources/MyHeader.h".
|
||||
;; Define the file for the file "/Users/mine/sources/MySource.cpp".
|
||||
;;
|
||||
!1 = metadata !{
|
||||
i32 458769, ;; Tag
|
||||
i32 0, ;; Unused
|
||||
i32 4, ;; Language Id
|
||||
metadata !"MyHeader.h",
|
||||
i32 524329, ;; Tag
|
||||
metadata !"MySource.cpp",
|
||||
metadata !"/Users/mine/sources",
|
||||
metadata !"4.2.1 (Based on Apple Inc. build 5649) (LLVM build 00)",
|
||||
i1 false, ;; Main Compile Unit
|
||||
i1 false, ;; Optimized compile unit
|
||||
metadata !"", ;; Compiler flags
|
||||
i32 0} ;; Runtime version
|
||||
metadata !3 ;; Compile unit
|
||||
}
|
||||
|
||||
;;
|
||||
;; Define the file for the file "/Users/mine/sources/Myheader.h"
|
||||
;;
|
||||
!3 = metadata !{
|
||||
i32 524329, ;; Tag
|
||||
metadata !"Myheader.h"
|
||||
metadata !"/Users/mine/sources",
|
||||
metadata !3 ;; Compile unit
|
||||
}
|
||||
|
||||
...
|
||||
</pre>
|
||||
|
|
@ -1081,15 +1105,15 @@ int MyGlobal = 100;
|
|||
;; variable anchor and the global variable itself.
|
||||
;;
|
||||
!0 = metadata !{
|
||||
i32 458804, ;; Tag
|
||||
i32 524340, ;; Tag
|
||||
i32 0, ;; Unused
|
||||
metadata !1, ;; Context
|
||||
metadata !"MyGlobal", ;; Name
|
||||
metadata !"MyGlobal", ;; Display Name
|
||||
metadata !"MyGlobal", ;; Linkage Name
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !3, ;; Compile Unit
|
||||
i32 1, ;; Line Number
|
||||
metadata !2, ;; Type
|
||||
metadata !4, ;; Type
|
||||
i1 false, ;; Is a local variable
|
||||
i1 true, ;; Is this a definition
|
||||
i32* @MyGlobal ;; The global variable
|
||||
|
|
@ -1099,11 +1123,11 @@ int MyGlobal = 100;
|
|||
;; Define the basic type of 32 bit signed integer. Note that since int is an
|
||||
;; intrinsic type the source file is NULL and line 0.
|
||||
;;
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
!4 = metadata !{
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"int", ;; Name
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 32, ;; Size in Bits
|
||||
i64 32, ;; Align in Bits
|
||||
|
|
@ -1143,16 +1167,16 @@ int main(int argc, char *argv[]) {
|
|||
;; anchor is 46, which is the same as the tag for subprograms
|
||||
;; (46 = DW_TAG_subprogram.)
|
||||
;;
|
||||
!0 = metadata !{
|
||||
i32 458798, ;; Tag
|
||||
!6 = metadata !{
|
||||
i32 524334, ;; Tag
|
||||
i32 0, ;; Unused
|
||||
metadata !1, ;; Context
|
||||
metadata !"main", ;; Name
|
||||
metadata !"main", ;; Display name
|
||||
metadata !"main", ;; Linkage name
|
||||
metadata !1, ;; Compile unit
|
||||
metadata !1, ;; File
|
||||
i32 1, ;; Line number
|
||||
metadata !2, ;; Type
|
||||
metadata !4, ;; Type
|
||||
i1 false, ;; Is local
|
||||
i1 true ;; Is definition
|
||||
}
|
||||
|
|
@ -1188,10 +1212,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"bool", ;; Name
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 8, ;; Size in Bits
|
||||
i64 8, ;; Align in Bits
|
||||
|
|
@ -1214,10 +1238,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"char", ;; Name
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 8, ;; Size in Bits
|
||||
i64 8, ;; Align in Bits
|
||||
|
|
@ -1240,10 +1264,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"unsigned char",
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 8, ;; Size in Bits
|
||||
i64 8, ;; Align in Bits
|
||||
|
|
@ -1266,10 +1290,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"short int",
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 16, ;; Size in Bits
|
||||
i64 16, ;; Align in Bits
|
||||
|
|
@ -1292,10 +1316,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"short unsigned int",
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 16, ;; Size in Bits
|
||||
i64 16, ;; Align in Bits
|
||||
|
|
@ -1318,10 +1342,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"int", ;; Name
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 32, ;; Size in Bits
|
||||
i64 32, ;; Align in Bits
|
||||
|
|
@ -1343,10 +1367,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"unsigned int",
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 32, ;; Size in Bits
|
||||
i64 32, ;; Align in Bits
|
||||
|
|
@ -1369,10 +1393,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"long long int",
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 64, ;; Size in Bits
|
||||
i64 64, ;; Align in Bits
|
||||
|
|
@ -1395,10 +1419,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"long long unsigned int",
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 64, ;; Size in Bits
|
||||
i64 64, ;; Align in Bits
|
||||
|
|
@ -1421,10 +1445,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"float",
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 32, ;; Size in Bits
|
||||
i64 32, ;; Align in Bits
|
||||
|
|
@ -1447,10 +1471,10 @@ define i32 @main(i32 %argc, i8** %argv) {
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
!2 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"double",;; Name
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 64, ;; Size in Bits
|
||||
i64 64, ;; Align in Bits
|
||||
|
|
@ -1486,10 +1510,10 @@ typedef const int *IntPtr;
|
|||
;; Define the typedef "IntPtr".
|
||||
;;
|
||||
!2 = metadata !{
|
||||
i32 458774, ;; Tag
|
||||
i32 524310, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"IntPtr", ;; Name
|
||||
metadata !3, ;; Compile unit
|
||||
metadata !3, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 0, ;; Size in bits
|
||||
i64 0, ;; Align in bits
|
||||
|
|
@ -1502,10 +1526,10 @@ typedef const int *IntPtr;
|
|||
;; Define the pointer type.
|
||||
;;
|
||||
!4 = metadata !{
|
||||
i32 458767, ;; Tag
|
||||
i32 524303, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"", ;; Name
|
||||
metadata !1, ;; Compile unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 64, ;; Size in bits
|
||||
i64 64, ;; Align in bits
|
||||
|
|
@ -1517,10 +1541,10 @@ typedef const int *IntPtr;
|
|||
;; Define the const type.
|
||||
;;
|
||||
!5 = metadata !{
|
||||
i32 458790, ;; Tag
|
||||
i32 524326, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"", ;; Name
|
||||
metadata !1, ;; Compile unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 32, ;; Size in bits
|
||||
i64 32, ;; Align in bits
|
||||
|
|
@ -1532,10 +1556,10 @@ typedef const int *IntPtr;
|
|||
;; Define the int type.
|
||||
;;
|
||||
!6 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"int", ;; Name
|
||||
metadata !1, ;; Compile unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 32, ;; Size in bits
|
||||
i64 32, ;; Align in bits
|
||||
|
|
@ -1575,10 +1599,10 @@ struct Color {
|
|||
;; Define basic type for unsigned int.
|
||||
;;
|
||||
!5 = metadata !{
|
||||
i32 458788, ;; Tag
|
||||
i32 524324, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"unsigned int",
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 0, ;; Line number
|
||||
i64 32, ;; Size in Bits
|
||||
i64 32, ;; Align in Bits
|
||||
|
|
@ -1590,7 +1614,7 @@ struct Color {
|
|||
;; Define composite type for struct Color.
|
||||
;;
|
||||
!2 = metadata !{
|
||||
i32 458771, ;; Tag
|
||||
i32 524307, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"Color", ;; Name
|
||||
metadata !1, ;; Compile unit
|
||||
|
|
@ -1608,10 +1632,10 @@ struct Color {
|
|||
;; Define the Red field.
|
||||
;;
|
||||
!4 = metadata !{
|
||||
i32 458765, ;; Tag
|
||||
i32 524301, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"Red", ;; Name
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 2, ;; Line number
|
||||
i64 32, ;; Size in bits
|
||||
i64 32, ;; Align in bits
|
||||
|
|
@ -1624,10 +1648,10 @@ struct Color {
|
|||
;; Define the Green field.
|
||||
;;
|
||||
!6 = metadata !{
|
||||
i32 458765, ;; Tag
|
||||
i32 524301, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"Green", ;; Name
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 3, ;; Line number
|
||||
i64 32, ;; Size in bits
|
||||
i64 32, ;; Align in bits
|
||||
|
|
@ -1640,10 +1664,10 @@ struct Color {
|
|||
;; Define the Blue field.
|
||||
;;
|
||||
!7 = metadata !{
|
||||
i32 458765, ;; Tag
|
||||
i32 524301, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"Blue", ;; Name
|
||||
metadata !1, ;; Compile Unit
|
||||
metadata !1, ;; File
|
||||
i32 4, ;; Line number
|
||||
i64 32, ;; Size in bits
|
||||
i64 32, ;; Align in bits
|
||||
|
|
@ -1688,10 +1712,10 @@ enum Trees {
|
|||
;; Define composite type for enum Trees
|
||||
;;
|
||||
!2 = metadata !{
|
||||
i32 458756, ;; Tag
|
||||
i32 524292, ;; Tag
|
||||
metadata !1, ;; Context
|
||||
metadata !"Trees", ;; Name
|
||||
metadata !1, ;; Compile unit
|
||||
metadata !1, ;; File
|
||||
i32 1, ;; Line number
|
||||
i64 32, ;; Size in bits
|
||||
i64 32, ;; Align in bits
|
||||
|
|
@ -1710,17 +1734,17 @@ enum Trees {
|
|||
;;
|
||||
;; Define Spruce enumerator.
|
||||
;;
|
||||
!4 = metadata !{i32 458792, metadata !"Spruce", i64 100}
|
||||
!4 = metadata !{i32 524328, metadata !"Spruce", i64 100}
|
||||
|
||||
;;
|
||||
;; Define Oak enumerator.
|
||||
;;
|
||||
!5 = metadata !{i32 458792, metadata !"Oak", i64 200}
|
||||
!5 = metadata !{i32 524328, metadata !"Oak", i64 200}
|
||||
|
||||
;;
|
||||
;; Define Maple enumerator.
|
||||
;;
|
||||
!6 = metadata !{i32 458792, metadata !"Maple", i64 300}
|
||||
!6 = metadata !{i32 524328, metadata !"Maple", i64 300}
|
||||
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -1738,7 +1762,7 @@ enum Trees {
|
|||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-01-11 23:53:48 +0100 (Mon, 11 Jan 2010) $
|
||||
Last modified: $Date: 2010-03-09 01:44:10 +0100 (Tue, 09 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -909,16 +909,22 @@ finalization.</p>
|
|||
|
||||
<p>A <tt>MachineFunctionPass</tt> is a part of the LLVM code generator that
|
||||
executes on the machine-dependent representation of each LLVM function in the
|
||||
program. A <tt>MachineFunctionPass</tt> is also a <tt>FunctionPass</tt>, so all
|
||||
program.</p>
|
||||
|
||||
<p>Code generator passes are registered and initialized specially by
|
||||
<tt>TargetMachine::addPassesToEmitFile</tt> and similar routines, so they
|
||||
cannot generally be run from the <tt>opt</tt> or <tt>bugpoint</tt>
|
||||
commands.</p>
|
||||
|
||||
<p>A <tt>MachineFunctionPass</tt> is also a <tt>FunctionPass</tt>, so all
|
||||
the restrictions that apply to a <tt>FunctionPass</tt> also apply to it.
|
||||
<tt>MachineFunctionPass</tt>es also have additional restrictions. In particular,
|
||||
<tt>MachineFunctionPass</tt>es are not allowed to do any of the following:</p>
|
||||
|
||||
<ol>
|
||||
<li>Modify any LLVM Instructions, BasicBlocks or Functions.</li>
|
||||
<li>Modify or create any LLVM IR Instructions, BasicBlocks, Arguments,
|
||||
Functions, GlobalVariables, GlobalAliases, or Modules.</li>
|
||||
<li>Modify a MachineFunction other than the one currently being processed.</li>
|
||||
<li>Add or remove MachineFunctions from the current Module.</li>
|
||||
<li>Add or remove global variables from the current Module.</li>
|
||||
<li>Maintain state across invocations of <a
|
||||
href="#runOnMachineFunction"><tt>runOnMachineFunction</tt></a> (including global
|
||||
data)</li>
|
||||
|
|
@ -1829,7 +1835,7 @@ Despite that, we have kept the LLVM passes SMP ready, and you should too.</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-02-18 15:37:52 +0100 (Thu, 18 Feb 2010) $
|
||||
Last modified: $Date: 2010-03-10 02:29:39 +0100 (Wed, 10 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ exception Error of string
|
|||
let the_module = create_module (global_context ()) "my cool jit"
|
||||
let builder = builder (global_context ())
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
|
@ -389,7 +390,7 @@ that there is an LLVM Function object that is ready to go for us.</p>
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block "entry" the_function in
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
|
|
@ -903,6 +904,7 @@ let context = global_context ()
|
|||
let the_module = create_module context "my cool jit"
|
||||
let builder = builder context
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
|
||||
let rec codegen_expr = function
|
||||
| Ast.Number n -> const_float double_type n
|
||||
|
|
@ -974,7 +976,7 @@ let codegen_func = function
|
|||
let the_function = codegen_proto proto in
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block "entry" the_function in
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
|
|
@ -1085,7 +1087,7 @@ main ()
|
|||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-03-02 02:11:08 +0100 (Tue, 02 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -186,9 +186,8 @@ add a set of optimizations to run. The code looks like this:</p>
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
(* Create the JIT. *)
|
||||
let the_module_provider = ModuleProvider.create Codegen.the_module in
|
||||
let the_execution_engine = ExecutionEngine.create the_module_provider in
|
||||
let the_fpm = PassManager.create_function the_module_provider in
|
||||
let the_execution_engine = ExecutionEngine.create Codegen.the_module in
|
||||
let the_fpm = PassManager.create_function Codegen.the_module in
|
||||
|
||||
(* Set up the optimizer pipeline. Start with registering info about how the
|
||||
* target lays out data structures. *)
|
||||
|
|
@ -213,18 +212,11 @@ add a set of optimizations to run. The code looks like this:</p>
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<p>This code defines two values, an <tt>Llvm.llmoduleprovider</tt> and a
|
||||
<tt>Llvm.PassManager.t</tt>. The former is basically a wrapper around our
|
||||
<tt>Llvm.llmodule</tt> that the <tt>Llvm.PassManager.t</tt> requires. It
|
||||
provides certain flexibility that we're not going to take advantage of here,
|
||||
so I won't dive into any details about it.</p>
|
||||
|
||||
<p>The meat of the matter here, is the definition of "<tt>the_fpm</tt>". It
|
||||
requires a pointer to the <tt>the_module</tt> (through the
|
||||
<tt>the_module_provider</tt>) to construct itself. Once it is set up, we use a
|
||||
series of "add" calls to add a bunch of LLVM passes. The first pass is
|
||||
basically boilerplate, it adds a pass so that later optimizations know how the
|
||||
data structures in the program are laid out. The
|
||||
requires a pointer to the <tt>the_module</tt> to construct itself. Once it is
|
||||
set up, we use a series of "add" calls to add a bunch of LLVM passes. The
|
||||
first pass is basically boilerplate, it adds a pass so that later optimizations
|
||||
know how the data structures in the program are laid out. The
|
||||
"<tt>the_execution_engine</tt>" variable is related to the JIT, which we will
|
||||
get to in the next section.</p>
|
||||
|
||||
|
|
@ -320,8 +312,7 @@ by adding a global variable and a call in <tt>main</tt>:</p>
|
|||
let main () =
|
||||
...
|
||||
<b>(* Create the JIT. *)
|
||||
let the_module_provider = ModuleProvider.create Codegen.the_module in
|
||||
let the_execution_engine = ExecutionEngine.create the_module_provider in</b>
|
||||
let the_execution_engine = ExecutionEngine.create Codegen.the_module in</b>
|
||||
...
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -351,7 +342,7 @@ can change the code that parses a top-level expression to look like this:</p>
|
|||
the_execution_engine in
|
||||
|
||||
print_string "Evaluated to ";
|
||||
print_float (GenericValue.as_float double_type result);
|
||||
print_float (GenericValue.as_float Codegen.double_type result);
|
||||
print_newline ();
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -796,6 +787,7 @@ let context = global_context ()
|
|||
let the_module = create_module context "my cool jit"
|
||||
let builder = builder context
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
|
||||
let rec codegen_expr = function
|
||||
| Ast.Number n -> const_float double_type n
|
||||
|
|
@ -867,7 +859,7 @@ let codegen_func the_fpm = function
|
|||
let the_function = codegen_proto proto in
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block "entry" the_function in
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
|
|
@ -932,7 +924,7 @@ let rec main_loop the_fpm the_execution_engine stream =
|
|||
the_execution_engine in
|
||||
|
||||
print_string "Evaluated to ";
|
||||
print_float (GenericValue.as_float double_type result);
|
||||
print_float (GenericValue.as_float Codegen.double_type result);
|
||||
print_newline ();
|
||||
with Stream.Error s | Codegen.Error s ->
|
||||
(* Skip token for error recovery. *)
|
||||
|
|
@ -971,16 +963,15 @@ let main () =
|
|||
let stream = Lexer.lex (Stream.of_channel stdin) in
|
||||
|
||||
(* Create the JIT. *)
|
||||
let the_module_provider = ModuleProvider.create Codegen.the_module in
|
||||
let the_execution_engine = ExecutionEngine.create the_module_provider in
|
||||
let the_fpm = PassManager.create_function the_module_provider in
|
||||
let the_execution_engine = ExecutionEngine.create Codegen.the_module in
|
||||
let the_fpm = PassManager.create_function Codegen.the_module in
|
||||
|
||||
(* Set up the optimizer pipeline. Start with registering info about how the
|
||||
* target lays out data structures. *)
|
||||
TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
|
||||
|
||||
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
|
||||
add_instruction_combining the_fpm;
|
||||
add_instruction_combination the_fpm;
|
||||
|
||||
(* reassociate expressions. *)
|
||||
add_reassociation the_fpm;
|
||||
|
|
@ -1032,7 +1023,7 @@ extern double putchard(double X) {
|
|||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-03-02 02:11:08 +0100 (Tue, 02 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ value as a 1-bit (bool) value.</p>
|
|||
let start_bb = insertion_block builder in
|
||||
let the_function = block_parent start_bb in
|
||||
|
||||
let then_bb = append_block "then" the_function in
|
||||
let then_bb = append_block context "then" the_function in
|
||||
position_at_end then_bb builder;
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -417,7 +417,7 @@ up-to-date value for code that will set up the Phi node.</p>
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
(* Emit 'else' value. *)
|
||||
let else_bb = append_block "else" the_function in
|
||||
let else_bb = append_block context "else" the_function in
|
||||
position_at_end else_bb builder;
|
||||
let else_val = codegen_expr else_ in
|
||||
|
||||
|
|
@ -433,7 +433,7 @@ the 'then' block.</p>
|
|||
<div class="doc_code">
|
||||
<pre>
|
||||
(* Emit merge block. *)
|
||||
let merge_bb = append_block "ifcont" the_function in
|
||||
let merge_bb = append_block context "ifcont" the_function in
|
||||
position_at_end merge_bb builder;
|
||||
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
|
||||
let phi = build_phi incoming "iftmp" builder in
|
||||
|
|
@ -704,7 +704,7 @@ block, but remember that the body code itself could consist of multiple blocks
|
|||
* block. *)
|
||||
let preheader_bb = insertion_block builder in
|
||||
let the_function = block_parent preheader_bb in
|
||||
let loop_bb = append_block "loop" the_function in
|
||||
let loop_bb = append_block context "loop" the_function in
|
||||
|
||||
(* Insert an explicit fall through from the current block to the
|
||||
* loop_bb. *)
|
||||
|
|
@ -804,7 +804,7 @@ statement.</p>
|
|||
<pre>
|
||||
(* Create the "after loop" block and insert it. *)
|
||||
let loop_end_bb = insertion_block builder in
|
||||
let after_bb = append_block "afterloop" the_function in
|
||||
let after_bb = append_block context "afterloop" the_function in
|
||||
|
||||
(* Insert the conditional branch into the end of loop_end_bb. *)
|
||||
ignore (build_cond_br end_cond loop_bb after_bb builder);
|
||||
|
|
@ -1204,6 +1204,7 @@ let context = global_context ()
|
|||
let the_module = create_module context "my cool jit"
|
||||
let builder = builder context
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
|
||||
let rec codegen_expr = function
|
||||
| Ast.Number n -> const_float double_type n
|
||||
|
|
@ -1250,7 +1251,7 @@ let rec codegen_expr = function
|
|||
let start_bb = insertion_block builder in
|
||||
let the_function = block_parent start_bb in
|
||||
|
||||
let then_bb = append_block "then" the_function in
|
||||
let then_bb = append_block context "then" the_function in
|
||||
|
||||
(* Emit 'then' value. *)
|
||||
position_at_end then_bb builder;
|
||||
|
|
@ -1262,7 +1263,7 @@ let rec codegen_expr = function
|
|||
let new_then_bb = insertion_block builder in
|
||||
|
||||
(* Emit 'else' value. *)
|
||||
let else_bb = append_block "else" the_function in
|
||||
let else_bb = append_block context "else" the_function in
|
||||
position_at_end else_bb builder;
|
||||
let else_val = codegen_expr else_ in
|
||||
|
||||
|
|
@ -1271,7 +1272,7 @@ let rec codegen_expr = function
|
|||
let new_else_bb = insertion_block builder in
|
||||
|
||||
(* Emit merge block. *)
|
||||
let merge_bb = append_block "ifcont" the_function in
|
||||
let merge_bb = append_block context "ifcont" the_function in
|
||||
position_at_end merge_bb builder;
|
||||
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
|
||||
let phi = build_phi incoming "iftmp" builder in
|
||||
|
|
@ -1297,7 +1298,7 @@ let rec codegen_expr = function
|
|||
* block. *)
|
||||
let preheader_bb = insertion_block builder in
|
||||
let the_function = block_parent preheader_bb in
|
||||
let loop_bb = append_block "loop" the_function in
|
||||
let loop_bb = append_block context "loop" the_function in
|
||||
|
||||
(* Insert an explicit fall through from the current block to the
|
||||
* loop_bb. *)
|
||||
|
|
@ -1341,7 +1342,7 @@ let rec codegen_expr = function
|
|||
|
||||
(* Create the "after loop" block and insert it. *)
|
||||
let loop_end_bb = insertion_block builder in
|
||||
let after_bb = append_block "afterloop" the_function in
|
||||
let after_bb = append_block context "afterloop" the_function in
|
||||
|
||||
(* Insert the conditional branch into the end of loop_end_bb. *)
|
||||
ignore (build_cond_br end_cond loop_bb after_bb builder);
|
||||
|
|
@ -1397,7 +1398,7 @@ let codegen_func the_fpm = function
|
|||
let the_function = codegen_proto proto in
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block "entry" the_function in
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
|
|
@ -1462,7 +1463,7 @@ let rec main_loop the_fpm the_execution_engine stream =
|
|||
the_execution_engine in
|
||||
|
||||
print_string "Evaluated to ";
|
||||
print_float (GenericValue.as_float double_type result);
|
||||
print_float (GenericValue.as_float Codegen.double_type result);
|
||||
print_newline ();
|
||||
with Stream.Error s | Codegen.Error s ->
|
||||
(* Skip token for error recovery. *)
|
||||
|
|
@ -1501,16 +1502,15 @@ let main () =
|
|||
let stream = Lexer.lex (Stream.of_channel stdin) in
|
||||
|
||||
(* Create the JIT. *)
|
||||
let the_module_provider = ModuleProvider.create Codegen.the_module in
|
||||
let the_execution_engine = ExecutionEngine.create the_module_provider in
|
||||
let the_fpm = PassManager.create_function the_module_provider in
|
||||
let the_execution_engine = ExecutionEngine.create Codegen.the_module in
|
||||
let the_fpm = PassManager.create_function Codegen.the_module in
|
||||
|
||||
(* Set up the optimizer pipeline. Start with registering info about how the
|
||||
* target lays out data structures. *)
|
||||
TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
|
||||
|
||||
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
|
||||
add_instruction_combining the_fpm;
|
||||
add_instruction_combination the_fpm;
|
||||
|
||||
(* reassociate expressions. *)
|
||||
add_reassociation the_fpm;
|
||||
|
|
@ -1563,7 +1563,7 @@ operators</a>
|
|||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-03-02 02:11:08 +0100 (Tue, 02 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ let codegen_func the_fpm = function
|
|||
end;</b>
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block "entry" the_function in
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
...
|
||||
</pre>
|
||||
|
|
@ -1177,6 +1177,7 @@ let context = global_context ()
|
|||
let the_module = create_module context "my cool jit"
|
||||
let builder = builder context
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
|
||||
let rec codegen_expr = function
|
||||
| Ast.Number n -> const_float double_type n
|
||||
|
|
@ -1241,7 +1242,7 @@ let rec codegen_expr = function
|
|||
let start_bb = insertion_block builder in
|
||||
let the_function = block_parent start_bb in
|
||||
|
||||
let then_bb = append_block "then" the_function in
|
||||
let then_bb = append_block context "then" the_function in
|
||||
|
||||
(* Emit 'then' value. *)
|
||||
position_at_end then_bb builder;
|
||||
|
|
@ -1253,7 +1254,7 @@ let rec codegen_expr = function
|
|||
let new_then_bb = insertion_block builder in
|
||||
|
||||
(* Emit 'else' value. *)
|
||||
let else_bb = append_block "else" the_function in
|
||||
let else_bb = append_block context "else" the_function in
|
||||
position_at_end else_bb builder;
|
||||
let else_val = codegen_expr else_ in
|
||||
|
||||
|
|
@ -1262,7 +1263,7 @@ let rec codegen_expr = function
|
|||
let new_else_bb = insertion_block builder in
|
||||
|
||||
(* Emit merge block. *)
|
||||
let merge_bb = append_block "ifcont" the_function in
|
||||
let merge_bb = append_block context "ifcont" the_function in
|
||||
position_at_end merge_bb builder;
|
||||
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
|
||||
let phi = build_phi incoming "iftmp" builder in
|
||||
|
|
@ -1288,7 +1289,7 @@ let rec codegen_expr = function
|
|||
* block. *)
|
||||
let preheader_bb = insertion_block builder in
|
||||
let the_function = block_parent preheader_bb in
|
||||
let loop_bb = append_block "loop" the_function in
|
||||
let loop_bb = append_block context "loop" the_function in
|
||||
|
||||
(* Insert an explicit fall through from the current block to the
|
||||
* loop_bb. *)
|
||||
|
|
@ -1332,7 +1333,7 @@ let rec codegen_expr = function
|
|||
|
||||
(* Create the "after loop" block and insert it. *)
|
||||
let loop_end_bb = insertion_block builder in
|
||||
let after_bb = append_block "afterloop" the_function in
|
||||
let after_bb = append_block context "afterloop" the_function in
|
||||
|
||||
(* Insert the conditional branch into the end of loop_end_bb. *)
|
||||
ignore (build_cond_br end_cond loop_bb after_bb builder);
|
||||
|
|
@ -1396,7 +1397,7 @@ let codegen_func the_fpm = function
|
|||
end;
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block "entry" the_function in
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
|
|
@ -1461,7 +1462,7 @@ let rec main_loop the_fpm the_execution_engine stream =
|
|||
the_execution_engine in
|
||||
|
||||
print_string "Evaluated to ";
|
||||
print_float (GenericValue.as_float double_type result);
|
||||
print_float (GenericValue.as_float Codegen.double_type result);
|
||||
print_newline ();
|
||||
with Stream.Error s | Codegen.Error s ->
|
||||
(* Skip token for error recovery. *)
|
||||
|
|
@ -1500,16 +1501,15 @@ let main () =
|
|||
let stream = Lexer.lex (Stream.of_channel stdin) in
|
||||
|
||||
(* Create the JIT. *)
|
||||
let the_module_provider = ModuleProvider.create Codegen.the_module in
|
||||
let the_execution_engine = ExecutionEngine.create the_module_provider in
|
||||
let the_fpm = PassManager.create_function the_module_provider in
|
||||
let the_execution_engine = ExecutionEngine.create Codegen.the_module in
|
||||
let the_fpm = PassManager.create_function Codegen.the_module in
|
||||
|
||||
(* Set up the optimizer pipeline. Start with registering info about how the
|
||||
* target lays out data structures. *)
|
||||
TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
|
||||
|
||||
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
|
||||
add_instruction_combining the_fpm;
|
||||
add_instruction_combination the_fpm;
|
||||
|
||||
(* reassociate expressions. *)
|
||||
add_reassociation the_fpm;
|
||||
|
|
@ -1568,7 +1568,7 @@ SSA construction</a>
|
|||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-02-03 18:27:31 +0100 (Wed, 03 Feb 2010) $
|
||||
Last modified: $Date: 2010-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -543,7 +543,7 @@ good codegen once again:</p>
|
|||
<pre>
|
||||
let main () =
|
||||
...
|
||||
let the_fpm = PassManager.create_function the_module_provider in
|
||||
let the_fpm = PassManager.create_function Codegen.the_module in
|
||||
|
||||
(* Set up the optimizer pipeline. Start with registering info about how the
|
||||
* target lays out data structures. *)
|
||||
|
|
@ -1388,6 +1388,7 @@ let context = global_context ()
|
|||
let the_module = create_module context "my cool jit"
|
||||
let builder = builder context
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
|
||||
(* Create an alloca instruction in the entry block of the function. This
|
||||
* is used for mutable variables etc. *)
|
||||
|
|
@ -1482,7 +1483,7 @@ let rec codegen_expr = function
|
|||
let start_bb = insertion_block builder in
|
||||
let the_function = block_parent start_bb in
|
||||
|
||||
let then_bb = append_block "then" the_function in
|
||||
let then_bb = append_block context "then" the_function in
|
||||
|
||||
(* Emit 'then' value. *)
|
||||
position_at_end then_bb builder;
|
||||
|
|
@ -1494,7 +1495,7 @@ let rec codegen_expr = function
|
|||
let new_then_bb = insertion_block builder in
|
||||
|
||||
(* Emit 'else' value. *)
|
||||
let else_bb = append_block "else" the_function in
|
||||
let else_bb = append_block context "else" the_function in
|
||||
position_at_end else_bb builder;
|
||||
let else_val = codegen_expr else_ in
|
||||
|
||||
|
|
@ -1503,7 +1504,7 @@ let rec codegen_expr = function
|
|||
let new_else_bb = insertion_block builder in
|
||||
|
||||
(* Emit merge block. *)
|
||||
let merge_bb = append_block "ifcont" the_function in
|
||||
let merge_bb = append_block context "ifcont" the_function in
|
||||
position_at_end merge_bb builder;
|
||||
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
|
||||
let phi = build_phi incoming "iftmp" builder in
|
||||
|
|
@ -1555,7 +1556,7 @@ let rec codegen_expr = function
|
|||
|
||||
(* Make the new basic block for the loop header, inserting after current
|
||||
* block. *)
|
||||
let loop_bb = append_block "loop" the_function in
|
||||
let loop_bb = append_block context "loop" the_function in
|
||||
|
||||
(* Insert an explicit fall through from the current block to the
|
||||
* loop_bb. *)
|
||||
|
|
@ -1599,7 +1600,7 @@ let rec codegen_expr = function
|
|||
let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
|
||||
|
||||
(* Create the "after loop" block and insert it. *)
|
||||
let after_bb = append_block "afterloop" the_function in
|
||||
let after_bb = append_block context "afterloop" the_function in
|
||||
|
||||
(* Insert the conditional branch into the end of loop_end_bb. *)
|
||||
ignore (build_cond_br end_cond loop_bb after_bb builder);
|
||||
|
|
@ -1723,7 +1724,7 @@ let codegen_func the_fpm = function
|
|||
end;
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block "entry" the_function in
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
|
|
@ -1791,7 +1792,7 @@ let rec main_loop the_fpm the_execution_engine stream =
|
|||
the_execution_engine in
|
||||
|
||||
print_string "Evaluated to ";
|
||||
print_float (GenericValue.as_float double_type result);
|
||||
print_float (GenericValue.as_float Codegen.double_type result);
|
||||
print_newline ();
|
||||
with Stream.Error s | Codegen.Error s ->
|
||||
(* Skip token for error recovery. *)
|
||||
|
|
@ -1831,9 +1832,8 @@ let main () =
|
|||
let stream = Lexer.lex (Stream.of_channel stdin) in
|
||||
|
||||
(* Create the JIT. *)
|
||||
let the_module_provider = ModuleProvider.create Codegen.the_module in
|
||||
let the_execution_engine = ExecutionEngine.create the_module_provider in
|
||||
let the_fpm = PassManager.create_function the_module_provider in
|
||||
let the_execution_engine = ExecutionEngine.create Codegen.the_module in
|
||||
let the_fpm = PassManager.create_function Codegen.the_module in
|
||||
|
||||
(* Set up the optimizer pipeline. Start with registering info about how the
|
||||
* target lays out data structures. *)
|
||||
|
|
@ -1843,7 +1843,7 @@ let main () =
|
|||
add_memory_to_register_promotion the_fpm;
|
||||
|
||||
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
|
||||
add_instruction_combining the_fpm;
|
||||
add_instruction_combination the_fpm;
|
||||
|
||||
(* reassociate expressions. *)
|
||||
add_reassociation the_fpm;
|
||||
|
|
@ -1901,7 +1901,7 @@ extern double printd(double X) {
|
|||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
|
||||
Last modified: $Date: 2010-03-02 02:11:08 +0100 (Tue, 02 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -25,4 +25,8 @@ ifeq ($(LLVM_ON_UNIX),1)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(filter $(BINDINGS_TO_BUILD),ocaml),ocaml)
|
||||
PARALLEL_DIRS += OCaml-Kaleidoscope
|
||||
endif
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ namespace llvm {
|
|||
/// 1.01E-2 4 1 1.01E-2
|
||||
void toString(SmallVectorImpl<char> &Str,
|
||||
unsigned FormatPrecision = 0,
|
||||
unsigned FormatMaxPadding = 3);
|
||||
unsigned FormatMaxPadding = 3) const;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -192,6 +192,13 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void swap(DenseMap& RHS) {
|
||||
std::swap(NumBuckets, RHS.NumBuckets);
|
||||
std::swap(Buckets, RHS.Buckets);
|
||||
std::swap(NumEntries, RHS.NumEntries);
|
||||
std::swap(NumTombstones, RHS.NumTombstones);
|
||||
}
|
||||
|
||||
value_type& FindAndConstruct(const KeyT &Key) {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(Key, TheBucket))
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ public:
|
|||
return TheMap.erase(V);
|
||||
}
|
||||
|
||||
void swap(DenseSet& RHS) {
|
||||
TheMap.swap(RHS.TheMap);
|
||||
}
|
||||
|
||||
DenseSet &operator=(const DenseSet &RHS) {
|
||||
TheMap = RHS.TheMap;
|
||||
return *this;
|
||||
|
|
@ -55,6 +59,12 @@ public:
|
|||
class Iterator {
|
||||
typename MapTy::iterator I;
|
||||
public:
|
||||
typedef typename MapTy::iterator::difference_type difference_type;
|
||||
typedef ValueT value_type;
|
||||
typedef value_type *pointer;
|
||||
typedef value_type &reference;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
Iterator(const typename MapTy::iterator &i) : I(i) {}
|
||||
|
||||
ValueT& operator*() { return I->first; }
|
||||
|
|
@ -68,6 +78,12 @@ public:
|
|||
class ConstIterator {
|
||||
typename MapTy::const_iterator I;
|
||||
public:
|
||||
typedef typename MapTy::const_iterator::difference_type difference_type;
|
||||
typedef ValueT value_type;
|
||||
typedef value_type *pointer;
|
||||
typedef value_type &reference;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
|
||||
|
||||
const ValueT& operator*() { return I->first; }
|
||||
|
|
|
|||
|
|
@ -44,11 +44,6 @@ namespace llvm {
|
|||
protected:
|
||||
MDNode *DbgNode;
|
||||
|
||||
/// DIDescriptor constructor. If the specified node is non-null, check
|
||||
/// to make sure that the tag in the descriptor matches 'RequiredTag'. If
|
||||
/// not, the debug info is corrupt and we ignore it.
|
||||
DIDescriptor(MDNode *N, unsigned RequiredTag);
|
||||
|
||||
StringRef getStringField(unsigned Elt) const;
|
||||
unsigned getUnsignedField(unsigned Elt) const {
|
||||
return (unsigned)getUInt64Field(Elt);
|
||||
|
|
@ -67,7 +62,7 @@ namespace llvm {
|
|||
explicit DIDescriptor() : DbgNode(0) {}
|
||||
explicit DIDescriptor(MDNode *N) : DbgNode(N) {}
|
||||
|
||||
bool isNull() const { return DbgNode == 0; }
|
||||
bool Verify() const { return DbgNode != 0; }
|
||||
|
||||
MDNode *getNode() const { return DbgNode; }
|
||||
|
||||
|
|
@ -92,6 +87,7 @@ namespace llvm {
|
|||
bool isSubprogram() const;
|
||||
bool isGlobalVariable() const;
|
||||
bool isScope() const;
|
||||
bool isFile() const;
|
||||
bool isCompileUnit() const;
|
||||
bool isNameSpace() const;
|
||||
bool isLexicalBlock() const;
|
||||
|
|
@ -104,8 +100,7 @@ namespace llvm {
|
|||
/// DISubrange - This is used to represent ranges, for array bounds.
|
||||
class DISubrange : public DIDescriptor {
|
||||
public:
|
||||
explicit DISubrange(MDNode *N = 0)
|
||||
: DIDescriptor(N, dwarf::DW_TAG_subrange_type) {}
|
||||
explicit DISubrange(MDNode *N = 0) : DIDescriptor(N) {}
|
||||
|
||||
int64_t getLo() const { return (int64_t)getUInt64Field(1); }
|
||||
int64_t getHi() const { return (int64_t)getUInt64Field(2); }
|
||||
|
|
@ -126,10 +121,7 @@ namespace llvm {
|
|||
/// DIScope - A base class for various scopes.
|
||||
class DIScope : public DIDescriptor {
|
||||
public:
|
||||
explicit DIScope(MDNode *N = 0) : DIDescriptor (N) {
|
||||
if (DbgNode && !isScope())
|
||||
DbgNode = 0;
|
||||
}
|
||||
explicit DIScope(MDNode *N = 0) : DIDescriptor (N) {}
|
||||
virtual ~DIScope() {}
|
||||
|
||||
StringRef getFilename() const;
|
||||
|
|
@ -139,10 +131,7 @@ namespace llvm {
|
|||
/// DICompileUnit - A wrapper for a compile unit.
|
||||
class DICompileUnit : public DIScope {
|
||||
public:
|
||||
explicit DICompileUnit(MDNode *N = 0) : DIScope(N) {
|
||||
if (DbgNode && !isCompileUnit())
|
||||
DbgNode = 0;
|
||||
}
|
||||
explicit DICompileUnit(MDNode *N = 0) : DIScope(N) {}
|
||||
|
||||
unsigned getLanguage() const { return getUnsignedField(2); }
|
||||
StringRef getFilename() const { return getStringField(3); }
|
||||
|
|
@ -170,13 +159,24 @@ namespace llvm {
|
|||
void dump() const;
|
||||
};
|
||||
|
||||
/// DIFile - This is a wrapper for a file.
|
||||
class DIFile : public DIScope {
|
||||
public:
|
||||
explicit DIFile(MDNode *N = 0) : DIScope(N) {
|
||||
if (DbgNode && !isFile())
|
||||
DbgNode = 0;
|
||||
}
|
||||
StringRef getFilename() const { return getStringField(1); }
|
||||
StringRef getDirectory() const { return getStringField(2); }
|
||||
DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); }
|
||||
};
|
||||
|
||||
/// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}').
|
||||
/// FIXME: it seems strange that this doesn't have either a reference to the
|
||||
/// type/precision or a file/line pair for location info.
|
||||
class DIEnumerator : public DIDescriptor {
|
||||
public:
|
||||
explicit DIEnumerator(MDNode *N = 0)
|
||||
: DIDescriptor(N, dwarf::DW_TAG_enumerator) {}
|
||||
explicit DIEnumerator(MDNode *N = 0) : DIDescriptor(N) {}
|
||||
|
||||
StringRef getName() const { return getStringField(1); }
|
||||
uint64_t getEnumValue() const { return getUInt64Field(2); }
|
||||
|
|
@ -185,7 +185,7 @@ namespace llvm {
|
|||
/// DIType - This is a wrapper for a type.
|
||||
/// FIXME: Types should be factored much better so that CV qualifiers and
|
||||
/// others do not require a huge and empty descriptor full of zeros.
|
||||
class DIType : public DIDescriptor {
|
||||
class DIType : public DIScope {
|
||||
public:
|
||||
enum {
|
||||
FlagPrivate = 1 << 0,
|
||||
|
|
@ -199,11 +199,9 @@ namespace llvm {
|
|||
};
|
||||
|
||||
protected:
|
||||
DIType(MDNode *N, unsigned Tag)
|
||||
: DIDescriptor(N, Tag) {}
|
||||
// This ctor is used when the Tag has already been validated by a derived
|
||||
// ctor.
|
||||
DIType(MDNode *N, bool, bool) : DIDescriptor(N) {}
|
||||
DIType(MDNode *N, bool, bool) : DIScope(N) {}
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -214,9 +212,15 @@ namespace llvm {
|
|||
explicit DIType() {}
|
||||
virtual ~DIType() {}
|
||||
|
||||
DIDescriptor getContext() const { return getDescriptorField(1); }
|
||||
DIScope getContext() const { return getFieldAs<DIScope>(1); }
|
||||
StringRef getName() const { return getStringField(2); }
|
||||
DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); }
|
||||
DICompileUnit getCompileUnit() const{
|
||||
if (getVersion() == llvm::LLVMDebugVersion7)
|
||||
return getFieldAs<DICompileUnit>(3);
|
||||
|
||||
DIFile F = getFieldAs<DIFile>(3);
|
||||
return F.getCompileUnit();
|
||||
}
|
||||
unsigned getLineNumber() const { return getUnsignedField(4); }
|
||||
uint64_t getSizeInBits() const { return getUInt64Field(5); }
|
||||
uint64_t getAlignInBits() const { return getUInt64Field(6); }
|
||||
|
|
@ -246,7 +250,11 @@ namespace llvm {
|
|||
bool isArtificial() const {
|
||||
return (getFlags() & FlagArtificial) != 0;
|
||||
}
|
||||
|
||||
bool isValid() const {
|
||||
return DbgNode && (isBasicType() || isDerivedType() || isCompositeType());
|
||||
}
|
||||
StringRef getFilename() const { return getCompileUnit().getFilename();}
|
||||
StringRef getDirectory() const { return getCompileUnit().getDirectory();}
|
||||
/// dump - print type.
|
||||
void dump() const;
|
||||
};
|
||||
|
|
@ -254,8 +262,7 @@ namespace llvm {
|
|||
/// DIBasicType - A basic type, like 'int' or 'float'.
|
||||
class DIBasicType : public DIType {
|
||||
public:
|
||||
explicit DIBasicType(MDNode *N = 0)
|
||||
: DIType(N, dwarf::DW_TAG_base_type) {}
|
||||
explicit DIBasicType(MDNode *N = 0) : DIType(N) {}
|
||||
|
||||
unsigned getEncoding() const { return getUnsignedField(9); }
|
||||
|
||||
|
|
@ -271,10 +278,7 @@ namespace llvm {
|
|||
: DIType(N, true, true) {}
|
||||
public:
|
||||
explicit DIDerivedType(MDNode *N = 0)
|
||||
: DIType(N, true, true) {
|
||||
if (DbgNode && !isDerivedType())
|
||||
DbgNode = 0;
|
||||
}
|
||||
: DIType(N, true, true) {}
|
||||
|
||||
DIType getTypeDerivedFrom() const { return getFieldAs<DIType>(9); }
|
||||
|
||||
|
|
@ -317,17 +321,23 @@ namespace llvm {
|
|||
/// DIGlobal - This is a common class for global variables and subprograms.
|
||||
class DIGlobal : public DIDescriptor {
|
||||
protected:
|
||||
explicit DIGlobal(MDNode *N, unsigned RequiredTag)
|
||||
: DIDescriptor(N, RequiredTag) {}
|
||||
explicit DIGlobal(MDNode *N) : DIDescriptor(N) {}
|
||||
|
||||
public:
|
||||
virtual ~DIGlobal() {}
|
||||
|
||||
DIDescriptor getContext() const { return getDescriptorField(2); }
|
||||
DIScope getContext() const { return getFieldAs<DIScope>(2); }
|
||||
StringRef getName() const { return getStringField(3); }
|
||||
StringRef getDisplayName() const { return getStringField(4); }
|
||||
StringRef getLinkageName() const { return getStringField(5); }
|
||||
DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(6); }
|
||||
DICompileUnit getCompileUnit() const{
|
||||
if (getVersion() == llvm::LLVMDebugVersion7)
|
||||
return getFieldAs<DICompileUnit>(6);
|
||||
|
||||
DIFile F = getFieldAs<DIFile>(6);
|
||||
return F.getCompileUnit();
|
||||
}
|
||||
|
||||
unsigned getLineNumber() const { return getUnsignedField(7); }
|
||||
DIType getType() const { return getFieldAs<DIType>(8); }
|
||||
|
||||
|
|
@ -343,16 +353,19 @@ namespace llvm {
|
|||
/// DISubprogram - This is a wrapper for a subprogram (e.g. a function).
|
||||
class DISubprogram : public DIScope {
|
||||
public:
|
||||
explicit DISubprogram(MDNode *N = 0) : DIScope(N) {
|
||||
if (DbgNode && !isSubprogram())
|
||||
DbgNode = 0;
|
||||
}
|
||||
explicit DISubprogram(MDNode *N = 0) : DIScope(N) {}
|
||||
|
||||
DIDescriptor getContext() const { return getDescriptorField(2); }
|
||||
DIScope getContext() const { return getFieldAs<DIScope>(2); }
|
||||
StringRef getName() const { return getStringField(3); }
|
||||
StringRef getDisplayName() const { return getStringField(4); }
|
||||
StringRef getLinkageName() const { return getStringField(5); }
|
||||
DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(6); }
|
||||
DICompileUnit getCompileUnit() const{
|
||||
if (getVersion() == llvm::LLVMDebugVersion7)
|
||||
return getFieldAs<DICompileUnit>(6);
|
||||
|
||||
DIFile F = getFieldAs<DIFile>(6);
|
||||
return F.getCompileUnit();
|
||||
}
|
||||
unsigned getLineNumber() const { return getUnsignedField(7); }
|
||||
DICompositeType getType() const { return getFieldAs<DICompositeType>(8); }
|
||||
|
||||
|
|
@ -360,7 +373,7 @@ namespace llvm {
|
|||
/// DIType or as DICompositeType.
|
||||
StringRef getReturnTypeName() const {
|
||||
DICompositeType DCT(getFieldAs<DICompositeType>(8));
|
||||
if (!DCT.isNull()) {
|
||||
if (DCT.Verify()) {
|
||||
DIArray A = DCT.getTypeArray();
|
||||
DIType T(A.getElement(0).getNode());
|
||||
return T.getName();
|
||||
|
|
@ -399,8 +412,7 @@ namespace llvm {
|
|||
/// DIGlobalVariable - This is a wrapper for a global variable.
|
||||
class DIGlobalVariable : public DIGlobal {
|
||||
public:
|
||||
explicit DIGlobalVariable(MDNode *N = 0)
|
||||
: DIGlobal(N, dwarf::DW_TAG_variable) {}
|
||||
explicit DIGlobalVariable(MDNode *N = 0) : DIGlobal(N) {}
|
||||
|
||||
GlobalVariable *getGlobal() const { return getGlobalVariableField(11); }
|
||||
|
||||
|
|
@ -416,14 +428,17 @@ namespace llvm {
|
|||
class DIVariable : public DIDescriptor {
|
||||
public:
|
||||
explicit DIVariable(MDNode *N = 0)
|
||||
: DIDescriptor(N) {
|
||||
if (DbgNode && !isVariable())
|
||||
DbgNode = 0;
|
||||
}
|
||||
: DIDescriptor(N) {}
|
||||
|
||||
DIDescriptor getContext() const { return getDescriptorField(1); }
|
||||
StringRef getName() const { return getStringField(2); }
|
||||
DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); }
|
||||
DIScope getContext() const { return getFieldAs<DIScope>(1); }
|
||||
StringRef getName() const { return getStringField(2); }
|
||||
DICompileUnit getCompileUnit() const{
|
||||
if (getVersion() == llvm::LLVMDebugVersion7)
|
||||
return getFieldAs<DICompileUnit>(3);
|
||||
|
||||
DIFile F = getFieldAs<DIFile>(3);
|
||||
return F.getCompileUnit();
|
||||
}
|
||||
unsigned getLineNumber() const { return getUnsignedField(4); }
|
||||
DIType getType() const { return getFieldAs<DIType>(5); }
|
||||
|
||||
|
|
@ -455,10 +470,7 @@ namespace llvm {
|
|||
/// DILexicalBlock - This is a wrapper for a lexical block.
|
||||
class DILexicalBlock : public DIScope {
|
||||
public:
|
||||
explicit DILexicalBlock(MDNode *N = 0) : DIScope(N) {
|
||||
if (DbgNode && !isLexicalBlock())
|
||||
DbgNode = 0;
|
||||
}
|
||||
explicit DILexicalBlock(MDNode *N = 0) : DIScope(N) {}
|
||||
DIScope getContext() const { return getFieldAs<DIScope>(1); }
|
||||
StringRef getDirectory() const { return getContext().getDirectory(); }
|
||||
StringRef getFilename() const { return getContext().getFilename(); }
|
||||
|
|
@ -469,16 +481,18 @@ namespace llvm {
|
|||
/// DINameSpace - A wrapper for a C++ style name space.
|
||||
class DINameSpace : public DIScope {
|
||||
public:
|
||||
explicit DINameSpace(MDNode *N = 0) : DIScope(N) {
|
||||
if (DbgNode && !isNameSpace())
|
||||
DbgNode = 0;
|
||||
}
|
||||
|
||||
explicit DINameSpace(MDNode *N = 0) : DIScope(N) {}
|
||||
DIScope getContext() const { return getFieldAs<DIScope>(1); }
|
||||
StringRef getName() const { return getStringField(2); }
|
||||
StringRef getDirectory() const { return getContext().getDirectory(); }
|
||||
StringRef getFilename() const { return getContext().getFilename(); }
|
||||
DICompileUnit getCompileUnit() const { return getFieldAs<DICompileUnit>(3);}
|
||||
DICompileUnit getCompileUnit() const{
|
||||
if (getVersion() == llvm::LLVMDebugVersion7)
|
||||
return getFieldAs<DICompileUnit>(3);
|
||||
|
||||
DIFile F = getFieldAs<DIFile>(3);
|
||||
return F.getCompileUnit();
|
||||
}
|
||||
unsigned getLineNumber() const { return getUnsignedField(4); }
|
||||
};
|
||||
|
||||
|
|
@ -494,6 +508,7 @@ namespace llvm {
|
|||
DILocation getOrigLocation() const { return getFieldAs<DILocation>(3); }
|
||||
StringRef getFilename() const { return getScope().getFilename(); }
|
||||
StringRef getDirectory() const { return getScope().getDirectory(); }
|
||||
bool Verify() const;
|
||||
};
|
||||
|
||||
/// DIFactory - This object assists with the construction of the various
|
||||
|
|
@ -531,19 +546,22 @@ namespace llvm {
|
|||
StringRef Flags = "",
|
||||
unsigned RunTimeVer = 0);
|
||||
|
||||
/// CreateFile - Create a new descriptor for the specified file.
|
||||
DIFile CreateFile(StringRef Filename, StringRef Directory, DICompileUnit CU);
|
||||
|
||||
/// CreateEnumerator - Create a single enumerator value.
|
||||
DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val);
|
||||
|
||||
/// CreateBasicType - Create a basic type like int, float, etc.
|
||||
DIBasicType CreateBasicType(DIDescriptor Context, StringRef Name,
|
||||
DICompileUnit CompileUnit, unsigned LineNumber,
|
||||
DIFile F, unsigned LineNumber,
|
||||
uint64_t SizeInBits, uint64_t AlignInBits,
|
||||
uint64_t OffsetInBits, unsigned Flags,
|
||||
unsigned Encoding);
|
||||
|
||||
/// CreateBasicType - Create a basic type like int, float, etc.
|
||||
DIBasicType CreateBasicTypeEx(DIDescriptor Context, StringRef Name,
|
||||
DICompileUnit CompileUnit, unsigned LineNumber,
|
||||
DIFile F, unsigned LineNumber,
|
||||
Constant *SizeInBits, Constant *AlignInBits,
|
||||
Constant *OffsetInBits, unsigned Flags,
|
||||
unsigned Encoding);
|
||||
|
|
@ -552,7 +570,7 @@ namespace llvm {
|
|||
/// pointer, typedef, etc.
|
||||
DIDerivedType CreateDerivedType(unsigned Tag, DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNumber,
|
||||
uint64_t SizeInBits, uint64_t AlignInBits,
|
||||
uint64_t OffsetInBits, unsigned Flags,
|
||||
|
|
@ -561,17 +579,18 @@ namespace llvm {
|
|||
/// CreateDerivedType - Create a derived type like const qualified type,
|
||||
/// pointer, typedef, etc.
|
||||
DIDerivedType CreateDerivedTypeEx(unsigned Tag, DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
unsigned LineNumber,
|
||||
Constant *SizeInBits, Constant *AlignInBits,
|
||||
Constant *OffsetInBits, unsigned Flags,
|
||||
DIType DerivedFrom);
|
||||
StringRef Name,
|
||||
DIFile F,
|
||||
unsigned LineNumber,
|
||||
Constant *SizeInBits,
|
||||
Constant *AlignInBits,
|
||||
Constant *OffsetInBits, unsigned Flags,
|
||||
DIType DerivedFrom);
|
||||
|
||||
/// CreateCompositeType - Create a composite type like array, struct, etc.
|
||||
DICompositeType CreateCompositeType(unsigned Tag, DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNumber,
|
||||
uint64_t SizeInBits,
|
||||
uint64_t AlignInBits,
|
||||
|
|
@ -586,22 +605,23 @@ namespace llvm {
|
|||
|
||||
/// CreateCompositeType - Create a composite type like array, struct, etc.
|
||||
DICompositeType CreateCompositeTypeEx(unsigned Tag, DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
unsigned LineNumber,
|
||||
Constant *SizeInBits,
|
||||
Constant *AlignInBits,
|
||||
Constant *OffsetInBits, unsigned Flags,
|
||||
DIType DerivedFrom,
|
||||
DIArray Elements,
|
||||
unsigned RunTimeLang = 0);
|
||||
StringRef Name,
|
||||
DIFile F,
|
||||
unsigned LineNumber,
|
||||
Constant *SizeInBits,
|
||||
Constant *AlignInBits,
|
||||
Constant *OffsetInBits,
|
||||
unsigned Flags,
|
||||
DIType DerivedFrom,
|
||||
DIArray Elements,
|
||||
unsigned RunTimeLang = 0);
|
||||
|
||||
/// CreateSubprogram - Create a new descriptor for the specified subprogram.
|
||||
/// See comments in DISubprogram for descriptions of these fields.
|
||||
DISubprogram CreateSubprogram(DIDescriptor Context, StringRef Name,
|
||||
StringRef DisplayName,
|
||||
StringRef LinkageName,
|
||||
DICompileUnit CompileUnit, unsigned LineNo,
|
||||
DIFile F, unsigned LineNo,
|
||||
DIType Ty, bool isLocalToUnit,
|
||||
bool isDefinition,
|
||||
unsigned VK = 0,
|
||||
|
|
@ -618,21 +638,21 @@ namespace llvm {
|
|||
CreateGlobalVariable(DIDescriptor Context, StringRef Name,
|
||||
StringRef DisplayName,
|
||||
StringRef LinkageName,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
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,
|
||||
DIFile F, unsigned LineNo,
|
||||
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,
|
||||
DIFile F, unsigned LineNo,
|
||||
DIType Ty,
|
||||
SmallVector<Value *, 9> &addr);
|
||||
|
||||
|
|
@ -644,7 +664,7 @@ namespace llvm {
|
|||
/// CreateNameSpace - This creates new descriptor for a namespace
|
||||
/// with the specified parent context.
|
||||
DINameSpace CreateNameSpace(DIDescriptor Context, StringRef Name,
|
||||
DICompileUnit CU, unsigned LineNo);
|
||||
DIFile F, unsigned LineNo);
|
||||
|
||||
/// CreateLocation - Creates a debug info location.
|
||||
DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo,
|
||||
|
|
|
|||
|
|
@ -179,6 +179,11 @@ namespace llvm {
|
|||
void resetCachedCostInfo(Function* Caller) {
|
||||
CachedFunctionInfo[Caller] = FunctionInfo();
|
||||
}
|
||||
|
||||
/// growCachedCostInfo - update the cached cost info for Caller after Callee
|
||||
/// has been inlined. If Callee is NULL it means a dead call has been
|
||||
/// eliminated.
|
||||
void growCachedCostInfo(Function* Caller, Function* Callee);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ struct PostDominatorTree : public FunctionPass {
|
|||
return DT->properlyDominates(A, B);
|
||||
}
|
||||
|
||||
inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) {
|
||||
return DT->findNearestCommonDominator(A, B);
|
||||
}
|
||||
|
||||
virtual void releaseMemory() {
|
||||
DT->releaseMemory();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ namespace llvm {
|
|||
mutable const MachineInstr *LastMI;
|
||||
mutable const Function *LastFn;
|
||||
mutable unsigned Counter;
|
||||
mutable unsigned SetCounter;
|
||||
|
||||
// Private state for processDebugLoc()
|
||||
mutable const MDNode *PrevDLT;
|
||||
|
|
@ -275,6 +276,13 @@ namespace llvm {
|
|||
/// EmitInt64 - Emit a long long directive and value.
|
||||
///
|
||||
void EmitInt64(uint64_t Value) const;
|
||||
|
||||
|
||||
/// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size
|
||||
/// in bytes of the directive is specified by Size and Hi/Lo specify the
|
||||
/// labels. This implicitly uses .set if it is available.
|
||||
void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
|
||||
unsigned Size) const;
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class Value;
|
|||
class Module;
|
||||
class MDNode;
|
||||
class MCAsmInfo;
|
||||
class MCSymbol;
|
||||
class raw_ostream;
|
||||
class Instruction;
|
||||
class DICompileUnit;
|
||||
|
|
@ -82,10 +83,10 @@ public:
|
|||
///
|
||||
void EndFunction(const MachineFunction *MF);
|
||||
|
||||
/// RecordSourceLine - Register a source line with debug info. Returns a
|
||||
/// unique label ID used to generate a label and provide correspondence to
|
||||
/// RecordSourceLine - Register a source line with debug info. Returns the
|
||||
/// unique label that was emitted and which provides correspondence to
|
||||
/// the source line list.
|
||||
unsigned RecordSourceLine(unsigned Line, unsigned Col, MDNode *Scope);
|
||||
MCSymbol *RecordSourceLine(unsigned Line, unsigned Col, MDNode *Scope);
|
||||
|
||||
/// getRecordSourceLineCount - Count source lines.
|
||||
unsigned getRecordSourceLineCount();
|
||||
|
|
@ -94,7 +95,7 @@ public:
|
|||
/// be emitted.
|
||||
bool ShouldEmitDwarfDebug() const;
|
||||
|
||||
void BeginScope(const MachineInstr *MI, unsigned Label);
|
||||
void BeginScope(const MachineInstr *MI, MCSymbol *Label);
|
||||
void EndScope(const MachineInstr *MI);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -217,26 +217,19 @@ public:
|
|||
/// MachineModuleInfo, for example because the code was deleted.
|
||||
void InvalidateLabel(unsigned LabelID) {
|
||||
// Remap to zero to indicate deletion.
|
||||
RemapLabel(LabelID, 0);
|
||||
}
|
||||
|
||||
/// RemapLabel - Indicate that a label has been merged into another.
|
||||
///
|
||||
void RemapLabel(unsigned OldLabelID, unsigned NewLabelID) {
|
||||
assert(0 < OldLabelID && OldLabelID <= LabelIDList.size() &&
|
||||
"Old label ID out of range.");
|
||||
assert(NewLabelID <= LabelIDList.size() &&
|
||||
"New label ID out of range.");
|
||||
LabelIDList[OldLabelID - 1] = NewLabelID;
|
||||
assert(0 < LabelID && LabelID <= LabelIDList.size() &&
|
||||
"Old label ID out of range.");
|
||||
LabelIDList[LabelID - 1] = 0;
|
||||
}
|
||||
|
||||
/// MappedLabel - Find out the label's final ID. Zero indicates deletion.
|
||||
/// ID != Mapped ID indicates that the label was folded into another label.
|
||||
unsigned MappedLabel(unsigned LabelID) const {
|
||||
/// isLabelDeleted - Return true if the label was deleted.
|
||||
/// FIXME: This should eventually be eliminated and use the 'is emitted' bit
|
||||
/// on MCSymbol.
|
||||
bool isLabelDeleted(unsigned LabelID) const {
|
||||
assert(LabelID <= LabelIDList.size() && "Debug label ID out of range.");
|
||||
return LabelID ? LabelIDList[LabelID - 1] : 0;
|
||||
return LabelID == 0 || LabelIDList[LabelID - 1] == 0;
|
||||
}
|
||||
|
||||
|
||||
/// getFrameMoves - Returns a reference to a list of moves done in the current
|
||||
/// function's prologue. Used to construct frame maps for debug and exception
|
||||
/// handling comsumers.
|
||||
|
|
|
|||
|
|
@ -247,18 +247,6 @@ namespace llvm {
|
|||
/// encode inline subroutine information.
|
||||
bool DwarfUsesInlineInfoSection; // Defaults to false.
|
||||
|
||||
/// Is_EHSymbolPrivate - If set, the "_foo.eh" is made private so that it
|
||||
/// doesn't show up in the symbol table of the object file.
|
||||
bool Is_EHSymbolPrivate; // Defaults to true.
|
||||
|
||||
/// GlobalEHDirective - This is the directive used to make exception frame
|
||||
/// tables globally visible.
|
||||
const char *GlobalEHDirective; // Defaults to NULL.
|
||||
|
||||
/// SupportsWeakEmptyEHFrame - True if target assembler and linker will
|
||||
/// handle a weak_definition of constant 0 for an omitted EH frame.
|
||||
bool SupportsWeakOmittedEHFrame; // Defaults to true.
|
||||
|
||||
/// DwarfSectionOffsetDirective - Special section offset directive.
|
||||
const char* DwarfSectionOffsetDirective; // Defaults to NULL
|
||||
|
||||
|
|
@ -419,15 +407,6 @@ namespace llvm {
|
|||
bool doesDwarfUsesInlineInfoSection() const {
|
||||
return DwarfUsesInlineInfoSection;
|
||||
}
|
||||
bool is_EHSymbolPrivate() const {
|
||||
return Is_EHSymbolPrivate;
|
||||
}
|
||||
const char *getGlobalEHDirective() const {
|
||||
return GlobalEHDirective;
|
||||
}
|
||||
bool getSupportsWeakOmittedEHFrame() const {
|
||||
return SupportsWeakOmittedEHFrame;
|
||||
}
|
||||
const char *getDwarfSectionOffsetDirective() const {
|
||||
return DwarfSectionOffsetDirective;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,11 +46,6 @@ namespace llvm {
|
|||
/// @name Symbol Managment
|
||||
/// @{
|
||||
|
||||
/// CreateSymbol - Create a new symbol with the specified @p Name.
|
||||
///
|
||||
/// @param Name - The symbol name, which must be unique across all symbols.
|
||||
MCSymbol *CreateSymbol(StringRef Name);
|
||||
|
||||
/// GetOrCreateSymbol - Lookup the symbol inside with the specified
|
||||
/// @p Name. If it exists, return it. If not, create a forward
|
||||
/// reference and return it.
|
||||
|
|
@ -59,13 +54,15 @@ namespace llvm {
|
|||
MCSymbol *GetOrCreateSymbol(StringRef Name);
|
||||
MCSymbol *GetOrCreateSymbol(const Twine &Name);
|
||||
|
||||
/// CreateTemporarySymbol - Create a new temporary symbol with the specified
|
||||
/// @p Name.
|
||||
/// GetOrCreateTemporarySymbol - Create a new assembler temporary symbol
|
||||
/// with the specified @p Name if it doesn't exist or return the existing
|
||||
/// one if it does.
|
||||
///
|
||||
/// @param Name - The symbol name, for debugging purposes only, temporary
|
||||
/// symbols do not surive assembly. If non-empty the name must be unique
|
||||
/// across all symbols.
|
||||
MCSymbol *CreateTemporarySymbol(StringRef Name = "");
|
||||
MCSymbol *GetOrCreateTemporarySymbol(StringRef Name = "");
|
||||
MCSymbol *GetOrCreateTemporarySymbol(const Twine &Name);
|
||||
|
||||
/// LookupSymbol - Get the symbol for \p Name, or null.
|
||||
MCSymbol *LookupSymbol(StringRef Name) const;
|
||||
|
|
|
|||
|
|
@ -127,6 +127,10 @@ public:
|
|||
|
||||
static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, MCContext &Ctx);
|
||||
static const MCSymbolRefExpr *Create(StringRef Name, MCContext &Ctx);
|
||||
|
||||
/// CreateTemp - Create a reference to an assembler temporary label with the
|
||||
/// specified name.
|
||||
static const MCSymbolRefExpr *CreateTemp(StringRef Name, MCContext &Ctx);
|
||||
|
||||
/// @}
|
||||
/// @name Accessors
|
||||
|
|
|
|||
|
|
@ -191,6 +191,11 @@ namespace llvm {
|
|||
/// 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);
|
||||
|
||||
/// EmitSymbolValue - Special case of EmitValue that avoids the client
|
||||
/// having to pass in a MCExpr for MCSymbols.
|
||||
virtual void EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
|
||||
unsigned AddrSpace);
|
||||
|
||||
/// EmitGPRel32Value - Emit the expression @p Value into the output as a
|
||||
/// gprel32 (32-bit GP relative) value.
|
||||
|
|
|
|||
|
|
@ -43,8 +43,10 @@ protected:
|
|||
|
||||
public:
|
||||
static MDString *get(LLVMContext &Context, StringRef Str);
|
||||
static MDString *get(LLVMContext &Context, const char *Str);
|
||||
|
||||
static MDString *get(LLVMContext &Context, const char *Str) {
|
||||
return get(Context, Str ? StringRef(Str) : StringRef());
|
||||
}
|
||||
|
||||
StringRef getString() const { return Str; }
|
||||
|
||||
unsigned getLength() const { return (unsigned)Str.size(); }
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ namespace llvm {
|
|||
// Debug info constants.
|
||||
|
||||
enum {
|
||||
LLVMDebugVersion = (7 << 16), // Current version of debug information.
|
||||
LLVMDebugVersion = (8 << 16), // Current version of debug information.
|
||||
LLVMDebugVersion7 = (7 << 16), // Constant for version 7.
|
||||
LLVMDebugVersion6 = (6 << 16), // Constant for version 6.
|
||||
LLVMDebugVersion5 = (5 << 16), // Constant for version 5.
|
||||
LLVMDebugVersion4 = (4 << 16), // Constant for version 4.
|
||||
|
|
|
|||
|
|
@ -664,12 +664,12 @@ public:
|
|||
|
||||
/// getOptimalMemOpType - Returns the target specific optimal type for load
|
||||
/// and store operations as a result of memset, memcpy, and memmove lowering.
|
||||
/// It returns EVT::iAny if SelectionDAG should be responsible for
|
||||
/// It returns EVT::Other if SelectionDAG should be responsible for
|
||||
/// determining it.
|
||||
virtual EVT getOptimalMemOpType(uint64_t Size, unsigned Align,
|
||||
bool isSrcConst, bool isSrcStr,
|
||||
SelectionDAG &DAG) const {
|
||||
return MVT::iAny;
|
||||
return MVT::Other;
|
||||
}
|
||||
|
||||
/// usesUnderscoreSetJmp - Determine if we should use _setjmp or setjmp
|
||||
|
|
|
|||
|
|
@ -87,11 +87,23 @@ protected:
|
|||
const MCSection *DwarfRangesSection;
|
||||
const MCSection *DwarfMacroInfoSection;
|
||||
|
||||
/// SupportsWeakEmptyEHFrame - True if target object file supports a
|
||||
/// weak_definition of constant 0 for an omitted EH frame.
|
||||
bool SupportsWeakOmittedEHFrame;
|
||||
|
||||
/// IsFunctionEHSymbolGlobal - This flag is set to true if the ".eh" symbol
|
||||
/// for a function should be marked .globl.
|
||||
bool IsFunctionEHSymbolGlobal;
|
||||
|
||||
/// IsFunctionEHFrameSymbolPrivate - This flag is set to true if the
|
||||
/// "EH_frame" symbol for EH information should be an assembler temporary (aka
|
||||
/// private linkage, aka an L or .L label) or false if it should be a normal
|
||||
/// non-.globl label. This defaults to true.
|
||||
bool IsFunctionEHFrameSymbolPrivate;
|
||||
public:
|
||||
|
||||
MCContext &getContext() const { return *Ctx; }
|
||||
|
||||
|
||||
virtual ~TargetLoweringObjectFile();
|
||||
|
||||
/// Initialize - this method must be called before any actual lowering is
|
||||
|
|
@ -101,6 +113,15 @@ public:
|
|||
Ctx = &ctx;
|
||||
}
|
||||
|
||||
bool isFunctionEHSymbolGlobal() const {
|
||||
return IsFunctionEHSymbolGlobal;
|
||||
}
|
||||
bool isFunctionEHFrameSymbolPrivate() const {
|
||||
return IsFunctionEHFrameSymbolPrivate;
|
||||
}
|
||||
bool getSupportsWeakOmittedEHFrame() const {
|
||||
return SupportsWeakOmittedEHFrame;
|
||||
}
|
||||
|
||||
const MCSection *getTextSection() const { return TextSection; }
|
||||
const MCSection *getDataSection() const { return DataSection; }
|
||||
|
|
|
|||
|
|
@ -682,8 +682,9 @@ public:
|
|||
/// When -enable-frame-index-scavenging is enabled, the virtual register
|
||||
/// allocated for this frame index is returned and its value is stored in
|
||||
/// *Value.
|
||||
typedef std::pair<unsigned, int> FrameIndexValue;
|
||||
virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
||||
int SPAdj, int *Value = NULL,
|
||||
int SPAdj, FrameIndexValue *Value = NULL,
|
||||
RegScavenger *RS=NULL) const = 0;
|
||||
|
||||
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||
|
|
|
|||
|
|
@ -75,6 +75,10 @@ struct Inliner : public CallGraphSCCPass {
|
|||
///
|
||||
virtual void resetCachedCostInfo(Function* Caller) = 0;
|
||||
|
||||
/// growCachedCostInfo - update the cached cost info for Caller after Callee
|
||||
/// has been inlined.
|
||||
virtual void growCachedCostInfo(Function* Caller, Function* Callee) = 0;
|
||||
|
||||
/// removeDeadFunctions - Remove dead functions that are not included in
|
||||
/// DNR (Do Not Remove) list.
|
||||
bool removeDeadFunctions(CallGraph &CG,
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ bool DIDescriptor::ValidDebugInfo(MDNode *N, unsigned OptLevel) {
|
|||
|
||||
DIDescriptor DI(N);
|
||||
|
||||
// Check current version. Allow Version6 for now.
|
||||
// Check current version. Allow Version7 for now.
|
||||
unsigned Version = DI.getVersion();
|
||||
if (Version != LLVMDebugVersion && Version != LLVMDebugVersion6)
|
||||
if (Version != LLVMDebugVersion && Version != LLVMDebugVersion7)
|
||||
return false;
|
||||
|
||||
switch (DI.getTag()) {
|
||||
|
|
@ -69,15 +69,6 @@ bool DIDescriptor::ValidDebugInfo(MDNode *N, unsigned OptLevel) {
|
|||
return true;
|
||||
}
|
||||
|
||||
DIDescriptor::DIDescriptor(MDNode *N, unsigned RequiredTag) {
|
||||
DbgNode = N;
|
||||
|
||||
// If this is non-null, check to see if the Tag matches. If not, set to null.
|
||||
if (N && getTag() != RequiredTag) {
|
||||
DbgNode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
StringRef
|
||||
DIDescriptor::getStringField(unsigned Elt) const {
|
||||
if (DbgNode == 0)
|
||||
|
|
@ -132,13 +123,12 @@ unsigned DIVariable::getNumAddrElements() const {
|
|||
/// isBasicType - Return true if the specified tag is legal for
|
||||
/// DIBasicType.
|
||||
bool DIDescriptor::isBasicType() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
return getTag() == dwarf::DW_TAG_base_type;
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_base_type;
|
||||
}
|
||||
|
||||
/// isDerivedType - Return true if the specified tag is legal for DIDerivedType.
|
||||
bool DIDescriptor::isDerivedType() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
if (!DbgNode) return false;
|
||||
switch (getTag()) {
|
||||
case dwarf::DW_TAG_typedef:
|
||||
case dwarf::DW_TAG_pointer_type:
|
||||
|
|
@ -158,7 +148,7 @@ bool DIDescriptor::isDerivedType() const {
|
|||
/// isCompositeType - Return true if the specified tag is legal for
|
||||
/// DICompositeType.
|
||||
bool DIDescriptor::isCompositeType() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
if (!DbgNode) return false;
|
||||
switch (getTag()) {
|
||||
case dwarf::DW_TAG_array_type:
|
||||
case dwarf::DW_TAG_structure_type:
|
||||
|
|
@ -175,7 +165,7 @@ bool DIDescriptor::isCompositeType() const {
|
|||
|
||||
/// isVariable - Return true if the specified tag is legal for DIVariable.
|
||||
bool DIDescriptor::isVariable() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
if (!DbgNode) return false;
|
||||
switch (getTag()) {
|
||||
case dwarf::DW_TAG_auto_variable:
|
||||
case dwarf::DW_TAG_arg_variable:
|
||||
|
|
@ -194,15 +184,13 @@ bool DIDescriptor::isType() const {
|
|||
/// isSubprogram - Return true if the specified tag is legal for
|
||||
/// DISubprogram.
|
||||
bool DIDescriptor::isSubprogram() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
return getTag() == dwarf::DW_TAG_subprogram;
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_subprogram;
|
||||
}
|
||||
|
||||
/// isGlobalVariable - Return true if the specified tag is legal for
|
||||
/// DIGlobalVariable.
|
||||
bool DIDescriptor::isGlobalVariable() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
return getTag() == dwarf::DW_TAG_variable;
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_variable;
|
||||
}
|
||||
|
||||
/// isGlobal - Return true if the specified tag is legal for DIGlobal.
|
||||
|
|
@ -213,7 +201,7 @@ bool DIDescriptor::isGlobal() const {
|
|||
/// isScope - Return true if the specified tag is one of the scope
|
||||
/// related tag.
|
||||
bool DIDescriptor::isScope() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
if (!DbgNode) return false;
|
||||
switch (getTag()) {
|
||||
case dwarf::DW_TAG_compile_unit:
|
||||
case dwarf::DW_TAG_lexical_block:
|
||||
|
|
@ -228,39 +216,39 @@ bool DIDescriptor::isScope() const {
|
|||
|
||||
/// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit.
|
||||
bool DIDescriptor::isCompileUnit() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
return getTag() == dwarf::DW_TAG_compile_unit;
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_compile_unit;
|
||||
}
|
||||
|
||||
/// isFile - Return true if the specified tag is DW_TAG_file_type.
|
||||
bool DIDescriptor::isFile() const {
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_file_type;
|
||||
}
|
||||
|
||||
/// isNameSpace - Return true if the specified tag is DW_TAG_namespace.
|
||||
bool DIDescriptor::isNameSpace() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
return getTag() == dwarf::DW_TAG_namespace;
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_namespace;
|
||||
}
|
||||
|
||||
/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block.
|
||||
bool DIDescriptor::isLexicalBlock() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
return getTag() == dwarf::DW_TAG_lexical_block;
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_lexical_block;
|
||||
}
|
||||
|
||||
/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type.
|
||||
bool DIDescriptor::isSubrange() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
return getTag() == dwarf::DW_TAG_subrange_type;
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_subrange_type;
|
||||
}
|
||||
|
||||
/// isEnumerator - Return true if the specified tag is DW_TAG_enumerator.
|
||||
bool DIDescriptor::isEnumerator() const {
|
||||
assert(!isNull() && "Invalid descriptor!");
|
||||
return getTag() == dwarf::DW_TAG_enumerator;
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_enumerator;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Simple Descriptor Constructors and other Methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
DIType::DIType(MDNode *N) : DIDescriptor(N) {
|
||||
DIType::DIType(MDNode *N) : DIScope(N) {
|
||||
if (!N) return;
|
||||
if (!isBasicType() && !isDerivedType() && !isCompositeType()) {
|
||||
DbgNode = 0;
|
||||
|
|
@ -268,7 +256,8 @@ DIType::DIType(MDNode *N) : DIDescriptor(N) {
|
|||
}
|
||||
|
||||
unsigned DIArray::getNumElements() const {
|
||||
assert(DbgNode && "Invalid DIArray");
|
||||
if (!DbgNode)
|
||||
return 0;
|
||||
return DbgNode->getNumOperands();
|
||||
}
|
||||
|
||||
|
|
@ -276,11 +265,9 @@ unsigned DIArray::getNumElements() const {
|
|||
/// this descriptor. After this completes, the current debug info value
|
||||
/// is erased.
|
||||
void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) {
|
||||
if (isNull())
|
||||
if (!DbgNode)
|
||||
return;
|
||||
|
||||
assert(!D.isNull() && "Can not replace with null");
|
||||
|
||||
// Since we use a TrackingVH for the node, its easy for clients to manufacture
|
||||
// legitimate situations where they want to replaceAllUsesWith() on something
|
||||
// which, due to uniquing, has merged with the source. We shield clients from
|
||||
|
|
@ -295,7 +282,7 @@ void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) {
|
|||
|
||||
/// Verify - Verify that a compile unit is well formed.
|
||||
bool DICompileUnit::Verify() const {
|
||||
if (isNull())
|
||||
if (!DbgNode)
|
||||
return false;
|
||||
StringRef N = getFilename();
|
||||
if (N.empty())
|
||||
|
|
@ -306,36 +293,36 @@ bool DICompileUnit::Verify() const {
|
|||
|
||||
/// Verify - Verify that a type descriptor is well formed.
|
||||
bool DIType::Verify() const {
|
||||
if (isNull())
|
||||
if (!DbgNode)
|
||||
return false;
|
||||
if (getContext().isNull())
|
||||
if (!getContext().Verify())
|
||||
return false;
|
||||
|
||||
DICompileUnit CU = getCompileUnit();
|
||||
if (!CU.isNull() && !CU.Verify())
|
||||
if (!CU.Verify())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Verify - Verify that a composite type descriptor is well formed.
|
||||
bool DICompositeType::Verify() const {
|
||||
if (isNull())
|
||||
if (!DbgNode)
|
||||
return false;
|
||||
if (getContext().isNull())
|
||||
if (!getContext().Verify())
|
||||
return false;
|
||||
|
||||
DICompileUnit CU = getCompileUnit();
|
||||
if (!CU.isNull() && !CU.Verify())
|
||||
if (!CU.Verify())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Verify - Verify that a subprogram descriptor is well formed.
|
||||
bool DISubprogram::Verify() const {
|
||||
if (isNull())
|
||||
if (!DbgNode)
|
||||
return false;
|
||||
|
||||
if (getContext().isNull())
|
||||
if (!getContext().Verify())
|
||||
return false;
|
||||
|
||||
DICompileUnit CU = getCompileUnit();
|
||||
|
|
@ -343,24 +330,24 @@ bool DISubprogram::Verify() const {
|
|||
return false;
|
||||
|
||||
DICompositeType Ty = getType();
|
||||
if (!Ty.isNull() && !Ty.Verify())
|
||||
if (!Ty.Verify())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Verify - Verify that a global variable descriptor is well formed.
|
||||
bool DIGlobalVariable::Verify() const {
|
||||
if (isNull())
|
||||
if (!DbgNode)
|
||||
return false;
|
||||
|
||||
if (getDisplayName().empty())
|
||||
return false;
|
||||
|
||||
if (getContext().isNull())
|
||||
if (!getContext().Verify())
|
||||
return false;
|
||||
|
||||
DICompileUnit CU = getCompileUnit();
|
||||
if (!CU.isNull() && !CU.Verify())
|
||||
if (!CU.Verify())
|
||||
return false;
|
||||
|
||||
DIType Ty = getType();
|
||||
|
|
@ -375,10 +362,10 @@ bool DIGlobalVariable::Verify() const {
|
|||
|
||||
/// Verify - Verify that a variable descriptor is well formed.
|
||||
bool DIVariable::Verify() const {
|
||||
if (isNull())
|
||||
if (!DbgNode)
|
||||
return false;
|
||||
|
||||
if (getContext().isNull())
|
||||
if (!getContext().Verify())
|
||||
return false;
|
||||
|
||||
DIType Ty = getType();
|
||||
|
|
@ -388,6 +375,14 @@ bool DIVariable::Verify() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Verify - Verify that a location descriptor is well formed.
|
||||
bool DILocation::Verify() const {
|
||||
if (!DbgNode)
|
||||
return false;
|
||||
|
||||
return DbgNode->getNumOperands() == 4;
|
||||
}
|
||||
|
||||
/// getOriginalTypeSize - If this type is derived from a base type then
|
||||
/// return base type size.
|
||||
uint64_t DIDerivedType::getOriginalTypeSize() const {
|
||||
|
|
@ -398,7 +393,7 @@ uint64_t DIDerivedType::getOriginalTypeSize() const {
|
|||
DIType BaseType = getTypeDerivedFrom();
|
||||
// If this type is not derived from any type then take conservative
|
||||
// approach.
|
||||
if (BaseType.isNull())
|
||||
if (!BaseType.isValid())
|
||||
return getSizeInBits();
|
||||
if (BaseType.isDerivedType())
|
||||
return DIDerivedType(BaseType.getNode()).getOriginalTypeSize();
|
||||
|
|
@ -422,6 +417,8 @@ bool DISubprogram::describes(const Function *F) {
|
|||
}
|
||||
|
||||
StringRef DIScope::getFilename() const {
|
||||
if (!DbgNode)
|
||||
return StringRef();
|
||||
if (isLexicalBlock())
|
||||
return DILexicalBlock(DbgNode).getFilename();
|
||||
if (isSubprogram())
|
||||
|
|
@ -430,11 +427,17 @@ StringRef DIScope::getFilename() const {
|
|||
return DICompileUnit(DbgNode).getFilename();
|
||||
if (isNameSpace())
|
||||
return DINameSpace(DbgNode).getFilename();
|
||||
if (isType())
|
||||
return DIType(DbgNode).getFilename();
|
||||
if (isFile())
|
||||
return DIFile(DbgNode).getFilename();
|
||||
assert(0 && "Invalid DIScope!");
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef DIScope::getDirectory() const {
|
||||
if (!DbgNode)
|
||||
return StringRef();
|
||||
if (isLexicalBlock())
|
||||
return DILexicalBlock(DbgNode).getDirectory();
|
||||
if (isSubprogram())
|
||||
|
|
@ -443,6 +446,10 @@ StringRef DIScope::getDirectory() const {
|
|||
return DICompileUnit(DbgNode).getDirectory();
|
||||
if (isNameSpace())
|
||||
return DINameSpace(DbgNode).getDirectory();
|
||||
if (isType())
|
||||
return DIType(DbgNode).getDirectory();
|
||||
if (isFile())
|
||||
return DIFile(DbgNode).getDirectory();
|
||||
assert(0 && "Invalid DIScope!");
|
||||
return StringRef();
|
||||
}
|
||||
|
|
@ -468,7 +475,7 @@ void DICompileUnit::dump() const {
|
|||
|
||||
/// dump - Print type.
|
||||
void DIType::dump() const {
|
||||
if (isNull()) return;
|
||||
if (!DbgNode) return;
|
||||
|
||||
StringRef Res = getName();
|
||||
if (!Res.empty())
|
||||
|
|
@ -521,8 +528,6 @@ void DIDerivedType::dump() const {
|
|||
/// dump - Print composite type.
|
||||
void DICompositeType::dump() const {
|
||||
DIArray A = getTypeArray();
|
||||
if (A.isNull())
|
||||
return;
|
||||
dbgs() << " [" << A.getNumElements() << " elements]";
|
||||
}
|
||||
|
||||
|
|
@ -665,6 +670,20 @@ DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID,
|
|||
return DICompileUnit(MDNode::get(VMContext, &Elts[0], 10));
|
||||
}
|
||||
|
||||
/// CreateFile - Create a new descriptor for the specified file.
|
||||
DIFile DIFactory::CreateFile(StringRef Filename,
|
||||
StringRef Directory,
|
||||
DICompileUnit CU) {
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(dwarf::DW_TAG_file_type),
|
||||
MDString::get(VMContext, Filename),
|
||||
MDString::get(VMContext, Directory),
|
||||
CU.getNode()
|
||||
};
|
||||
|
||||
return DIFile(MDNode::get(VMContext, &Elts[0], 4));
|
||||
}
|
||||
|
||||
/// CreateEnumerator - Create a single enumerator value.
|
||||
DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){
|
||||
Value *Elts[] = {
|
||||
|
|
@ -679,7 +698,7 @@ DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){
|
|||
/// CreateBasicType - Create a basic type like int, float, etc.
|
||||
DIBasicType DIFactory::CreateBasicType(DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNumber,
|
||||
uint64_t SizeInBits,
|
||||
uint64_t AlignInBits,
|
||||
|
|
@ -689,7 +708,7 @@ DIBasicType DIFactory::CreateBasicType(DIDescriptor Context,
|
|||
GetTagConstant(dwarf::DW_TAG_base_type),
|
||||
Context.getNode(),
|
||||
MDString::get(VMContext, Name),
|
||||
CompileUnit.getNode(),
|
||||
F.getNode(),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
|
||||
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
|
||||
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
|
||||
|
|
@ -704,7 +723,7 @@ DIBasicType DIFactory::CreateBasicType(DIDescriptor Context,
|
|||
/// CreateBasicType - Create a basic type like int, float, etc.
|
||||
DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNumber,
|
||||
Constant *SizeInBits,
|
||||
Constant *AlignInBits,
|
||||
|
|
@ -714,7 +733,7 @@ DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context,
|
|||
GetTagConstant(dwarf::DW_TAG_base_type),
|
||||
Context.getNode(),
|
||||
MDString::get(VMContext, Name),
|
||||
CompileUnit.getNode(),
|
||||
F.getNode(),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
|
||||
SizeInBits,
|
||||
AlignInBits,
|
||||
|
|
@ -754,7 +773,7 @@ DIType DIFactory::CreateArtificialType(DIType Ty) {
|
|||
DIDerivedType DIFactory::CreateDerivedType(unsigned Tag,
|
||||
DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNumber,
|
||||
uint64_t SizeInBits,
|
||||
uint64_t AlignInBits,
|
||||
|
|
@ -765,7 +784,7 @@ DIDerivedType DIFactory::CreateDerivedType(unsigned Tag,
|
|||
GetTagConstant(Tag),
|
||||
Context.getNode(),
|
||||
MDString::get(VMContext, Name),
|
||||
CompileUnit.getNode(),
|
||||
F.getNode(),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
|
||||
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
|
||||
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
|
||||
|
|
@ -782,7 +801,7 @@ DIDerivedType DIFactory::CreateDerivedType(unsigned Tag,
|
|||
DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag,
|
||||
DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNumber,
|
||||
Constant *SizeInBits,
|
||||
Constant *AlignInBits,
|
||||
|
|
@ -793,7 +812,7 @@ DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag,
|
|||
GetTagConstant(Tag),
|
||||
Context.getNode(),
|
||||
MDString::get(VMContext, Name),
|
||||
CompileUnit.getNode(),
|
||||
F.getNode(),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
|
||||
SizeInBits,
|
||||
AlignInBits,
|
||||
|
|
@ -809,7 +828,7 @@ DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag,
|
|||
DICompositeType DIFactory::CreateCompositeType(unsigned Tag,
|
||||
DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNumber,
|
||||
uint64_t SizeInBits,
|
||||
uint64_t AlignInBits,
|
||||
|
|
@ -824,7 +843,7 @@ DICompositeType DIFactory::CreateCompositeType(unsigned Tag,
|
|||
GetTagConstant(Tag),
|
||||
Context.getNode(),
|
||||
MDString::get(VMContext, Name),
|
||||
CompileUnit.getNode(),
|
||||
F.getNode(),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
|
||||
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
|
||||
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
|
||||
|
|
@ -843,7 +862,7 @@ DICompositeType DIFactory::CreateCompositeType(unsigned Tag,
|
|||
DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag,
|
||||
DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNumber,
|
||||
Constant *SizeInBits,
|
||||
Constant *AlignInBits,
|
||||
|
|
@ -857,7 +876,7 @@ DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag,
|
|||
GetTagConstant(Tag),
|
||||
Context.getNode(),
|
||||
MDString::get(VMContext, Name),
|
||||
CompileUnit.getNode(),
|
||||
F.getNode(),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
|
||||
SizeInBits,
|
||||
AlignInBits,
|
||||
|
|
@ -878,7 +897,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
|
|||
StringRef Name,
|
||||
StringRef DisplayName,
|
||||
StringRef LinkageName,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNo, DIType Ty,
|
||||
bool isLocalToUnit,
|
||||
bool isDefinition,
|
||||
|
|
@ -893,7 +912,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
|
|||
MDString::get(VMContext, Name),
|
||||
MDString::get(VMContext, DisplayName),
|
||||
MDString::get(VMContext, LinkageName),
|
||||
CompileUnit.getNode(),
|
||||
F.getNode(),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
|
||||
Ty.getNode(),
|
||||
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
|
||||
|
|
@ -938,7 +957,7 @@ DIGlobalVariable
|
|||
DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
|
||||
StringRef DisplayName,
|
||||
StringRef LinkageName,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNo, DIType Ty,bool isLocalToUnit,
|
||||
bool isDefinition, llvm::GlobalVariable *Val) {
|
||||
Value *Elts[] = {
|
||||
|
|
@ -948,7 +967,7 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
|
|||
MDString::get(VMContext, Name),
|
||||
MDString::get(VMContext, DisplayName),
|
||||
MDString::get(VMContext, LinkageName),
|
||||
CompileUnit.getNode(),
|
||||
F.getNode(),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
|
||||
Ty.getNode(),
|
||||
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
|
||||
|
|
@ -970,13 +989,14 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
|
|||
/// CreateVariable - Create a new descriptor for the specified variable.
|
||||
DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context,
|
||||
StringRef Name,
|
||||
DICompileUnit CompileUnit, unsigned LineNo,
|
||||
DIFile F,
|
||||
unsigned LineNo,
|
||||
DIType Ty) {
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(Tag),
|
||||
Context.getNode(),
|
||||
MDString::get(VMContext, Name),
|
||||
CompileUnit.getNode(),
|
||||
F.getNode(),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
|
||||
Ty.getNode(),
|
||||
};
|
||||
|
|
@ -988,7 +1008,7 @@ DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context,
|
|||
/// which has a complex address expression for its address.
|
||||
DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context,
|
||||
const std::string &Name,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNo,
|
||||
DIType Ty,
|
||||
SmallVector<Value *, 9> &addr) {
|
||||
|
|
@ -996,7 +1016,7 @@ DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context,
|
|||
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(F.getNode());
|
||||
Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo));
|
||||
Elts.push_back(Ty.getNode());
|
||||
Elts.insert(Elts.end(), addr.begin(), addr.end());
|
||||
|
|
@ -1021,13 +1041,13 @@ DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context,
|
|||
/// CreateNameSpace - This creates new descriptor for a namespace
|
||||
/// with the specified parent context.
|
||||
DINameSpace DIFactory::CreateNameSpace(DIDescriptor Context, StringRef Name,
|
||||
DICompileUnit CompileUnit,
|
||||
DIFile F,
|
||||
unsigned LineNo) {
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(dwarf::DW_TAG_namespace),
|
||||
Context.getNode(),
|
||||
MDString::get(VMContext, Name),
|
||||
CompileUnit.getNode(),
|
||||
F.getNode(),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)
|
||||
};
|
||||
return DINameSpace(MDNode::get(VMContext, &Elts[0], 5));
|
||||
|
|
@ -1155,9 +1175,8 @@ void DebugInfoFinder::processModule(Module &M) {
|
|||
|
||||
/// processLocation - Process DILocation.
|
||||
void DebugInfoFinder::processLocation(DILocation Loc) {
|
||||
if (Loc.isNull()) return;
|
||||
DIScope S(Loc.getScope().getNode());
|
||||
if (S.isNull()) return;
|
||||
if (!Loc.Verify()) return;
|
||||
DIDescriptor S(Loc.getScope().getNode());
|
||||
if (S.isCompileUnit())
|
||||
addCompileUnit(DICompileUnit(S.getNode()));
|
||||
else if (S.isSubprogram())
|
||||
|
|
@ -1177,26 +1196,21 @@ void DebugInfoFinder::processType(DIType DT) {
|
|||
DICompositeType DCT(DT.getNode());
|
||||
processType(DCT.getTypeDerivedFrom());
|
||||
DIArray DA = DCT.getTypeArray();
|
||||
if (!DA.isNull())
|
||||
for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) {
|
||||
DIDescriptor D = DA.getElement(i);
|
||||
DIType TyE = DIType(D.getNode());
|
||||
if (!TyE.isNull())
|
||||
processType(TyE);
|
||||
else
|
||||
processSubprogram(DISubprogram(D.getNode()));
|
||||
}
|
||||
for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) {
|
||||
DIDescriptor D = DA.getElement(i);
|
||||
if (D.isType())
|
||||
processType(DIType(D.getNode()));
|
||||
else if (D.isSubprogram())
|
||||
processSubprogram(DISubprogram(D.getNode()));
|
||||
}
|
||||
} else if (DT.isDerivedType()) {
|
||||
DIDerivedType DDT(DT.getNode());
|
||||
if (!DDT.isNull())
|
||||
processType(DDT.getTypeDerivedFrom());
|
||||
processType(DDT.getTypeDerivedFrom());
|
||||
}
|
||||
}
|
||||
|
||||
/// processLexicalBlock
|
||||
void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) {
|
||||
if (LB.isNull())
|
||||
return;
|
||||
DIScope Context = LB.getContext();
|
||||
if (Context.isLexicalBlock())
|
||||
return processLexicalBlock(DILexicalBlock(Context.getNode()));
|
||||
|
|
@ -1206,8 +1220,6 @@ void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) {
|
|||
|
||||
/// processSubprogram - Process DISubprogram.
|
||||
void DebugInfoFinder::processSubprogram(DISubprogram SP) {
|
||||
if (SP.isNull())
|
||||
return;
|
||||
if (!addSubprogram(SP))
|
||||
return;
|
||||
addCompileUnit(SP.getCompileUnit());
|
||||
|
|
@ -1216,20 +1228,23 @@ void DebugInfoFinder::processSubprogram(DISubprogram SP) {
|
|||
|
||||
/// processDeclare - Process DbgDeclareInst.
|
||||
void DebugInfoFinder::processDeclare(DbgDeclareInst *DDI) {
|
||||
DIVariable DV(cast<MDNode>(DDI->getVariable()));
|
||||
if (DV.isNull())
|
||||
MDNode *N = dyn_cast<MDNode>(DDI->getVariable());
|
||||
if (!N) return;
|
||||
|
||||
DIDescriptor DV(N);
|
||||
if (!DV.isVariable())
|
||||
return;
|
||||
|
||||
if (!NodesSeen.insert(DV.getNode()))
|
||||
return;
|
||||
|
||||
addCompileUnit(DV.getCompileUnit());
|
||||
processType(DV.getType());
|
||||
addCompileUnit(DIVariable(N).getCompileUnit());
|
||||
processType(DIVariable(N).getType());
|
||||
}
|
||||
|
||||
/// addType - Add type into Tys.
|
||||
bool DebugInfoFinder::addType(DIType DT) {
|
||||
if (DT.isNull())
|
||||
if (!DT.isValid())
|
||||
return false;
|
||||
|
||||
if (!NodesSeen.insert(DT.getNode()))
|
||||
|
|
@ -1241,7 +1256,7 @@ bool DebugInfoFinder::addType(DIType DT) {
|
|||
|
||||
/// addCompileUnit - Add compile unit into CUs.
|
||||
bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) {
|
||||
if (CU.isNull())
|
||||
if (!CU.Verify())
|
||||
return false;
|
||||
|
||||
if (!NodesSeen.insert(CU.getNode()))
|
||||
|
|
@ -1253,7 +1268,7 @@ bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) {
|
|||
|
||||
/// addGlobalVariable - Add global variable into GVs.
|
||||
bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) {
|
||||
if (DIG.isNull())
|
||||
if (!DIDescriptor(DIG.getNode()).isGlobalVariable())
|
||||
return false;
|
||||
|
||||
if (!NodesSeen.insert(DIG.getNode()))
|
||||
|
|
@ -1265,7 +1280,7 @@ bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) {
|
|||
|
||||
// addSubprogram - Add subprgoram into SPs.
|
||||
bool DebugInfoFinder::addSubprogram(DISubprogram SP) {
|
||||
if (SP.isNull())
|
||||
if (!DIDescriptor(SP.getNode()).isSubprogram())
|
||||
return false;
|
||||
|
||||
if (!NodesSeen.insert(SP.getNode()))
|
||||
|
|
@ -1283,10 +1298,10 @@ static Value *findDbgGlobalDeclare(GlobalVariable *V) {
|
|||
return 0;
|
||||
|
||||
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
|
||||
DIGlobalVariable DIG(cast_or_null<MDNode>(NMD->getOperand(i)));
|
||||
if (DIG.isNull())
|
||||
DIDescriptor DIG(cast_or_null<MDNode>(NMD->getOperand(i)));
|
||||
if (!DIG.isGlobalVariable())
|
||||
continue;
|
||||
if (DIG.getGlobal() == V)
|
||||
if (DIGlobalVariable(DIG.getNode()).getGlobal() == V)
|
||||
return DIG.getNode();
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -1378,12 +1393,6 @@ DebugLoc llvm::ExtractDebugLocation(DILocation &Loc,
|
|||
/// getDISubprogram - Find subprogram that is enclosing this scope.
|
||||
DISubprogram llvm::getDISubprogram(MDNode *Scope) {
|
||||
DIDescriptor D(Scope);
|
||||
if (D.isNull())
|
||||
return DISubprogram();
|
||||
|
||||
if (D.isCompileUnit())
|
||||
return DISubprogram();
|
||||
|
||||
if (D.isSubprogram())
|
||||
return DISubprogram(Scope);
|
||||
|
||||
|
|
@ -1395,9 +1404,6 @@ DISubprogram llvm::getDISubprogram(MDNode *Scope) {
|
|||
|
||||
/// getDICompositeType - Find underlying composite type.
|
||||
DICompositeType llvm::getDICompositeType(DIType T) {
|
||||
if (T.isNull())
|
||||
return DICompositeType();
|
||||
|
||||
if (T.isCompositeType())
|
||||
return DICompositeType(T.getNode());
|
||||
|
||||
|
|
|
|||
|
|
@ -352,11 +352,6 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
|
|||
// Calls usually take a long time, so they make the inlining gain smaller.
|
||||
InlineCost += CalleeFI.Metrics.NumCalls * InlineConstants::CallPenalty;
|
||||
|
||||
// Don't inline into something too big, which would make it bigger.
|
||||
// "size" here is the number of basic blocks, not instructions.
|
||||
//
|
||||
InlineCost += Caller->size()/15;
|
||||
|
||||
// Look at the size of the callee. Each instruction counts as 5.
|
||||
InlineCost += CalleeFI.Metrics.NumInsts*InlineConstants::InstrCost;
|
||||
|
||||
|
|
@ -388,3 +383,45 @@ float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) {
|
|||
Factor += 1.5f;
|
||||
return Factor;
|
||||
}
|
||||
|
||||
/// growCachedCostInfo - update the cached cost info for Caller after Callee has
|
||||
/// been inlined.
|
||||
void
|
||||
InlineCostAnalyzer::growCachedCostInfo(Function* Caller, Function* Callee) {
|
||||
FunctionInfo &CallerFI = CachedFunctionInfo[Caller];
|
||||
|
||||
// For small functions we prefer to recalculate the cost for better accuracy.
|
||||
if (CallerFI.Metrics.NumBlocks < 10 || CallerFI.Metrics.NumInsts < 1000) {
|
||||
resetCachedCostInfo(Caller);
|
||||
return;
|
||||
}
|
||||
|
||||
// For large functions, we can save a lot of computation time by skipping
|
||||
// recalculations.
|
||||
if (CallerFI.Metrics.NumCalls > 0)
|
||||
--CallerFI.Metrics.NumCalls;
|
||||
|
||||
if (Callee) {
|
||||
FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];
|
||||
if (!CalleeFI.Metrics.NumBlocks) {
|
||||
resetCachedCostInfo(Caller);
|
||||
return;
|
||||
}
|
||||
CallerFI.Metrics.NeverInline |= CalleeFI.Metrics.NeverInline;
|
||||
CallerFI.Metrics.usesDynamicAlloca |= CalleeFI.Metrics.usesDynamicAlloca;
|
||||
|
||||
CallerFI.Metrics.NumInsts += CalleeFI.Metrics.NumInsts;
|
||||
CallerFI.Metrics.NumBlocks += CalleeFI.Metrics.NumBlocks;
|
||||
CallerFI.Metrics.NumCalls += CalleeFI.Metrics.NumCalls;
|
||||
CallerFI.Metrics.NumVectorInsts += CalleeFI.Metrics.NumVectorInsts;
|
||||
CallerFI.Metrics.NumRets += CalleeFI.Metrics.NumRets;
|
||||
|
||||
// analyzeBasicBlock counts each function argument as an inst.
|
||||
if (CallerFI.Metrics.NumInsts >= Callee->arg_size())
|
||||
CallerFI.Metrics.NumInsts -= Callee->arg_size();
|
||||
else
|
||||
CallerFI.Metrics.NumInsts = 0;
|
||||
}
|
||||
// We are not updating the argumentweights. We have already determined that
|
||||
// Caller is a fairly large function, so we accept the loss of precision.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -264,6 +264,13 @@ unsigned Loop::getSmallConstantTripMultiple() const {
|
|||
|
||||
/// isLCSSAForm - Return true if the Loop is in LCSSA form
|
||||
bool Loop::isLCSSAForm() const {
|
||||
// Collect all the reachable blocks in the function, for fast lookups.
|
||||
SmallPtrSet<BasicBlock *, 32> ReachableBBs;
|
||||
BasicBlock *EntryBB = getHeader()->getParent()->begin();
|
||||
for (df_iterator<BasicBlock *> NI = df_begin(EntryBB),
|
||||
NE = df_end(EntryBB); NI != NE; ++NI)
|
||||
ReachableBBs.insert(*NI);
|
||||
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallPtrSet<BasicBlock *, 16> LoopBBs(block_begin(), block_end());
|
||||
|
|
@ -277,9 +284,13 @@ bool Loop::isLCSSAForm() const {
|
|||
if (PHINode *P = dyn_cast<PHINode>(*UI))
|
||||
UserBB = P->getIncomingBlock(UI);
|
||||
|
||||
// Check the current block, as a fast-path. Most values are used in
|
||||
// the same block they are defined in.
|
||||
if (UserBB != BB && !LoopBBs.count(UserBB))
|
||||
// Check the current block, as a fast-path, before checking whether
|
||||
// the use is anywhere in the loop. Most values are used in the same
|
||||
// block they are defined in. Also, blocks not reachable from the
|
||||
// entry are special; uses in them don't need to go through PHIs.
|
||||
if (UserBB != BB &&
|
||||
!LoopBBs.count(UserBB) &&
|
||||
ReachableBBs.count(UserBB))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3101,9 +3101,16 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
|
|||
return getUnknown(V);
|
||||
|
||||
unsigned Opcode = Instruction::UserOp1;
|
||||
if (Instruction *I = dyn_cast<Instruction>(V))
|
||||
if (Instruction *I = dyn_cast<Instruction>(V)) {
|
||||
Opcode = I->getOpcode();
|
||||
else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
||||
|
||||
// Don't attempt to analyze instructions in blocks that aren't
|
||||
// reachable. Such instructions don't matter, and they aren't required
|
||||
// to obey basic rules for definitions dominating uses which this
|
||||
// analysis depends on.
|
||||
if (!DT->isReachableFromEntry(I->getParent()))
|
||||
return getUnknown(V);
|
||||
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
||||
Opcode = CE->getOpcode();
|
||||
else if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
|
||||
return getConstant(CI);
|
||||
|
|
|
|||
|
|
@ -1286,6 +1286,8 @@ Value *SCEVExpander::expand(const SCEV *S) {
|
|||
// there) so that it is guaranteed to dominate any user inside the loop.
|
||||
if (L && S->hasComputableLoopEvolution(L) && L != PostIncLoop)
|
||||
InsertPt = L->getHeader()->getFirstNonPHI();
|
||||
while (isa<DbgInfoIntrinsic>(InsertPt))
|
||||
InsertPt = llvm::next(BasicBlock::iterator(InsertPt));
|
||||
while (isInsertedInstruction(InsertPt))
|
||||
InsertPt = llvm::next(BasicBlock::iterator(InsertPt));
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm,
|
|||
: MachineFunctionPass(&ID), O(o),
|
||||
TM(tm), MAI(T), TRI(tm.getRegisterInfo()),
|
||||
OutContext(Ctx), OutStreamer(Streamer),
|
||||
LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) {
|
||||
LastMI(0), LastFn(0), Counter(~0U), SetCounter(0), PrevDLT(NULL) {
|
||||
DW = 0; MMI = 0;
|
||||
VerboseAsm = Streamer.isVerboseAsm();
|
||||
}
|
||||
|
|
@ -335,7 +335,7 @@ static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) {
|
|||
// Print source line info.
|
||||
DIScope Scope = DLT.getScope();
|
||||
// Omit the directory, because it's likely to be long and uninteresting.
|
||||
if (!Scope.isNull())
|
||||
if (Scope.Verify())
|
||||
CommentOS << Scope.getFilename();
|
||||
else
|
||||
CommentOS << "<unknown>";
|
||||
|
|
@ -893,6 +893,31 @@ void AsmPrinter::EmitInt64(uint64_t Value) const {
|
|||
OutStreamer.EmitIntValue(Value, 8, 0/*addrspace*/);
|
||||
}
|
||||
|
||||
/// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size
|
||||
/// in bytes of the directive is specified by Size and Hi/Lo specify the
|
||||
/// labels. This implicitly uses .set if it is available.
|
||||
void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
|
||||
unsigned Size) const {
|
||||
// Get the Hi-Lo expression.
|
||||
const MCExpr *Diff =
|
||||
MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(Hi, OutContext),
|
||||
MCSymbolRefExpr::Create(Lo, OutContext),
|
||||
OutContext);
|
||||
|
||||
if (!MAI->hasSetDirective()) {
|
||||
OutStreamer.EmitValue(Diff, Size, 0/*AddrSpace*/);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, emit with .set (aka assignment).
|
||||
MCSymbol *SetLabel =
|
||||
OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) +
|
||||
"set" + Twine(SetCounter++));
|
||||
OutStreamer.EmitAssignment(SetLabel, Diff);
|
||||
OutStreamer.EmitSymbolValue(SetLabel, Size, 0/*AddrSpace*/);
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// EmitAlignment - Emit an alignment directive to the specified power of
|
||||
|
|
@ -1287,18 +1312,16 @@ void AsmPrinter::processDebugLoc(const MachineInstr *MI,
|
|||
if (DL.isUnknown())
|
||||
return;
|
||||
DILocation CurDLT = MF->getDILocation(DL);
|
||||
if (CurDLT.getScope().isNull())
|
||||
if (!CurDLT.getScope().Verify())
|
||||
return;
|
||||
|
||||
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';
|
||||
MCSymbol *L = DW->RecordSourceLine(CurDLT.getLineNumber(),
|
||||
CurDLT.getColumnNumber(),
|
||||
CurDLT.getScope().getNode());
|
||||
DW->BeginScope(MI, L);
|
||||
PrevDLT = CurDLT.getNode();
|
||||
}
|
||||
|
|
@ -1529,12 +1552,17 @@ void AsmPrinter::printKill(const MachineInstr *MI) const {
|
|||
/// printLabel - This method prints a local label used by debug and
|
||||
/// exception handling tables.
|
||||
void AsmPrinter::printLabelInst(const MachineInstr *MI) const {
|
||||
printLabel(MI->getOperand(0).getImm());
|
||||
OutStreamer.AddBlankLine();
|
||||
MCSymbol *Sym =
|
||||
OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) +
|
||||
"label" + Twine(MI->getOperand(0).getImm()));
|
||||
OutStreamer.EmitLabel(Sym);
|
||||
}
|
||||
|
||||
void AsmPrinter::printLabel(unsigned Id) const {
|
||||
O << MAI->getPrivateGlobalPrefix() << "label" << Id << ':';
|
||||
MCSymbol *Sym =
|
||||
OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) +
|
||||
"label" + Twine(Id));
|
||||
OutStreamer.EmitLabel(Sym);
|
||||
}
|
||||
|
||||
/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
|
||||
|
|
@ -1575,15 +1603,14 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F,
|
|||
"_" + FnName.str() + "_" + BB->getName(),
|
||||
Mangler::Private);
|
||||
|
||||
return OutContext.GetOrCreateSymbol(NameResult.str());
|
||||
return OutContext.GetOrCreateTemporarySymbol(NameResult.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());
|
||||
return OutContext.GetOrCreateTemporarySymbol
|
||||
(Twine(MAI->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber())
|
||||
+ "_" + Twine(CPID));
|
||||
}
|
||||
|
||||
/// GetJTISymbol - Return the symbol for the specified jump table entry.
|
||||
|
|
@ -1594,10 +1621,9 @@ MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const {
|
|||
/// GetJTSetSymbol - Return the symbol for the specified jump table .set
|
||||
/// FIXME: privatize to AsmPrinter.
|
||||
MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const {
|
||||
SmallString<60> Name;
|
||||
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
|
||||
<< getFunctionNumber() << '_' << UID << "_set_" << MBBID;
|
||||
return OutContext.GetOrCreateSymbol(Name.str());
|
||||
return OutContext.GetOrCreateTemporarySymbol
|
||||
(Twine(MAI->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" +
|
||||
Twine(UID) + "_set_" + Twine(MBBID));
|
||||
}
|
||||
|
||||
/// GetGlobalValueSymbol - Return the MCSymbol for the specified global
|
||||
|
|
@ -1605,7 +1631,10 @@ MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const {
|
|||
MCSymbol *AsmPrinter::GetGlobalValueSymbol(const GlobalValue *GV) const {
|
||||
SmallString<60> NameStr;
|
||||
Mang->getNameWithPrefix(NameStr, GV, false);
|
||||
return OutContext.GetOrCreateSymbol(NameStr.str());
|
||||
|
||||
if (!GV->hasPrivateLinkage())
|
||||
return OutContext.GetOrCreateSymbol(NameStr.str());
|
||||
return OutContext.GetOrCreateTemporarySymbol(NameStr.str());
|
||||
}
|
||||
|
||||
/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with
|
||||
|
|
@ -1617,7 +1646,9 @@ MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV,
|
|||
SmallString<60> NameStr;
|
||||
Mang->getNameWithPrefix(NameStr, GV, ForcePrivate);
|
||||
NameStr.append(Suffix.begin(), Suffix.end());
|
||||
return OutContext.GetOrCreateSymbol(NameStr.str());
|
||||
if (!GV->hasPrivateLinkage() && !ForcePrivate)
|
||||
return OutContext.GetOrCreateSymbol(NameStr.str());
|
||||
return OutContext.GetOrCreateTemporarySymbol(NameStr.str());
|
||||
}
|
||||
|
||||
/// GetExternalSymbolSymbol - Return the MCSymbol for the specified
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ add_llvm_library(LLVMAsmPrinter
|
|||
DIE.cpp
|
||||
DwarfDebug.cpp
|
||||
DwarfException.cpp
|
||||
DwarfLabel.cpp
|
||||
DwarfPrinter.cpp
|
||||
DwarfWriter.cpp
|
||||
OcamlGCPrinter.cpp
|
||||
|
|
|
|||
|
|
@ -131,17 +131,15 @@ void DIE::print(raw_ostream &O, unsigned IncIndent) {
|
|||
<< "Die: "
|
||||
<< format("0x%lx", (long)(intptr_t)this)
|
||||
<< ", Offset: " << Offset
|
||||
<< ", Size: " << Size
|
||||
<< "\n";
|
||||
<< ", Size: " << Size << "\n";
|
||||
|
||||
O << Indent
|
||||
<< dwarf::TagString(Abbrev.getTag())
|
||||
<< " "
|
||||
<< dwarf::ChildrenString(Abbrev.getChildrenFlag());
|
||||
<< dwarf::ChildrenString(Abbrev.getChildrenFlag()) << "\n";
|
||||
} else {
|
||||
O << "Size: " << Size;
|
||||
O << "Size: " << Size << "\n";
|
||||
}
|
||||
O << "\n";
|
||||
|
||||
const SmallVector<DIEAbbrevData, 8> &Data = Abbrev.getData();
|
||||
|
||||
|
|
@ -254,51 +252,27 @@ void DIEString::print(raw_ostream &O) {
|
|||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEDwarfLabel Implementation
|
||||
// DIELabel Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitValue - Emit label value.
|
||||
///
|
||||
void DIEDwarfLabel::EmitValue(DwarfPrinter *D, unsigned Form) const {
|
||||
void DIELabel::EmitValue(DwarfPrinter *D, unsigned Form) const {
|
||||
bool IsSmall = Form == dwarf::DW_FORM_data4;
|
||||
D->EmitReference(Label, false, IsSmall);
|
||||
unsigned Size = IsSmall ? 4 : D->getTargetData()->getPointerSize();
|
||||
D->getAsm()->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/);
|
||||
}
|
||||
|
||||
/// SizeOf - Determine size of label value in bytes.
|
||||
///
|
||||
unsigned DIEDwarfLabel::SizeOf(const TargetData *TD, unsigned Form) const {
|
||||
unsigned DIELabel::SizeOf(const TargetData *TD, unsigned Form) const {
|
||||
if (Form == dwarf::DW_FORM_data4) return 4;
|
||||
return TD->getPointerSize();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEDwarfLabel::print(raw_ostream &O) {
|
||||
O << "Lbl: ";
|
||||
Label.print(O);
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEObjectLabel Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitValue - Emit label value.
|
||||
///
|
||||
void DIEObjectLabel::EmitValue(DwarfPrinter *D, unsigned Form) const {
|
||||
bool IsSmall = Form == dwarf::DW_FORM_data4;
|
||||
D->EmitReference(Sym, false, IsSmall);
|
||||
}
|
||||
|
||||
/// SizeOf - Determine size of label value in bytes.
|
||||
///
|
||||
unsigned DIEObjectLabel::SizeOf(const TargetData *TD, unsigned Form) const {
|
||||
if (Form == dwarf::DW_FORM_data4) return 4;
|
||||
return TD->getPointerSize();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIEObjectLabel::print(raw_ostream &O) {
|
||||
O << "Obj: " << Sym->getName();
|
||||
void DIELabel::print(raw_ostream &O) {
|
||||
O << "Lbl: " << Label->getName();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -310,10 +284,7 @@ void DIEObjectLabel::print(raw_ostream &O) {
|
|||
///
|
||||
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(),
|
||||
IsSmall, IsEH, UseSet);
|
||||
D->getAsm()->O << '\n'; // FIXME: Necesssary?
|
||||
D->EmitSectionOffset(Label, Section, IsSmall, IsEH);
|
||||
}
|
||||
|
||||
/// SizeOf - Determine size of delta value in bytes.
|
||||
|
|
@ -325,11 +296,8 @@ unsigned DIESectionOffset::SizeOf(const TargetData *TD, unsigned Form) const {
|
|||
|
||||
#ifndef NDEBUG
|
||||
void DIESectionOffset::print(raw_ostream &O) {
|
||||
O << "Off: ";
|
||||
Label.print(O);
|
||||
O << "-";
|
||||
Section.print(O);
|
||||
O << "-" << IsEH << "-" << UseSet;
|
||||
O << "Off: " << Label->getName() << "-" << Section->getName()
|
||||
<< "-" << IsEH;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -353,10 +321,7 @@ unsigned DIEDelta::SizeOf(const TargetData *TD, unsigned Form) const {
|
|||
|
||||
#ifndef NDEBUG
|
||||
void DIEDelta::print(raw_ostream &O) {
|
||||
O << "Del: ";
|
||||
LabelHi.print(O);
|
||||
O << "-";
|
||||
LabelLo.print(O);
|
||||
O << "Del: " << LabelHi->getName() << "-" << LabelLo->getName();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -400,15 +365,13 @@ void DIEBlock::EmitValue(DwarfPrinter *D, unsigned Form) const {
|
|||
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: D->EmitULEB128(Size); break;
|
||||
default: llvm_unreachable("Improper form for block"); 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->O << '\n';
|
||||
for (unsigned i = 0, N = Values.size(); i < N; ++i)
|
||||
Values[i]->EmitValue(D, AbbrevData[i].getForm());
|
||||
}
|
||||
}
|
||||
|
||||
/// SizeOf - Determine size of block data in bytes.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#ifndef CODEGEN_ASMPRINTER_DIE_H__
|
||||
#define CODEGEN_ASMPRINTER_DIE_H__
|
||||
|
||||
#include "DwarfLabel.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
|
@ -26,6 +25,7 @@ namespace llvm {
|
|||
class DwarfPrinter;
|
||||
class TargetData;
|
||||
class MCSymbol;
|
||||
class raw_ostream;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a
|
||||
|
|
@ -203,7 +203,6 @@ namespace llvm {
|
|||
isInteger,
|
||||
isString,
|
||||
isLabel,
|
||||
isAsIsLabel,
|
||||
isSectionOffset,
|
||||
isDelta,
|
||||
isEntry,
|
||||
|
|
@ -306,12 +305,12 @@ namespace llvm {
|
|||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEDwarfLabel - A Dwarf internal label expression DIE.
|
||||
/// DIELabel - A label expression DIE.
|
||||
//
|
||||
class DIEDwarfLabel : public DIEValue {
|
||||
const DWLabel Label;
|
||||
class DIELabel : public DIEValue {
|
||||
const MCSymbol *Label;
|
||||
public:
|
||||
explicit DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
|
||||
explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {}
|
||||
|
||||
/// EmitValue - Emit label value.
|
||||
///
|
||||
|
|
@ -322,37 +321,9 @@ namespace llvm {
|
|||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEDwarfLabel *) { return true; }
|
||||
static bool classof(const DIELabel *) { return true; }
|
||||
static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(raw_ostream &O);
|
||||
#endif
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEObjectLabel - A label to an object in code or data.
|
||||
//
|
||||
class DIEObjectLabel : public DIEValue {
|
||||
const MCSymbol *Sym;
|
||||
public:
|
||||
explicit DIEObjectLabel(const MCSymbol *S)
|
||||
: DIEValue(isAsIsLabel), Sym(S) {}
|
||||
|
||||
/// EmitValue - Emit label value.
|
||||
///
|
||||
virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of label value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIEObjectLabel *) { return true; }
|
||||
static bool classof(const DIEValue *L) {
|
||||
return L->getType() == isAsIsLabel;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(raw_ostream &O);
|
||||
#endif
|
||||
|
|
@ -362,15 +333,14 @@ namespace llvm {
|
|||
/// DIESectionOffset - A section offset DIE.
|
||||
///
|
||||
class DIESectionOffset : public DIEValue {
|
||||
const DWLabel Label;
|
||||
const DWLabel Section;
|
||||
const MCSymbol *Label;
|
||||
const MCSymbol *Section;
|
||||
bool IsEH : 1;
|
||||
bool UseSet : 1;
|
||||
public:
|
||||
DIESectionOffset(const DWLabel &Lab, const DWLabel &Sec,
|
||||
bool isEH = false, bool useSet = true)
|
||||
DIESectionOffset(const MCSymbol *Lab, const MCSymbol *Sec,
|
||||
bool isEH = false)
|
||||
: DIEValue(isSectionOffset), Label(Lab), Section(Sec),
|
||||
IsEH(isEH), UseSet(useSet) {}
|
||||
IsEH(isEH) {}
|
||||
|
||||
/// EmitValue - Emit section offset.
|
||||
///
|
||||
|
|
@ -395,10 +365,10 @@ namespace llvm {
|
|||
/// DIEDelta - A simple label difference DIE.
|
||||
///
|
||||
class DIEDelta : public DIEValue {
|
||||
const DWLabel LabelHi;
|
||||
const DWLabel LabelLo;
|
||||
const MCSymbol *LabelHi;
|
||||
const MCSymbol *LabelLo;
|
||||
public:
|
||||
DIEDelta(const DWLabel &Hi, const DWLabel &Lo)
|
||||
DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo)
|
||||
: DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
|
||||
|
||||
/// EmitValue - Emit delta value.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -62,14 +62,6 @@ class DwarfDebug : public DwarfPrinter {
|
|||
// Attributes used to construct specific Dwarf sections.
|
||||
//
|
||||
|
||||
/// CompileUnitMap - A map of global variables representing compile units to
|
||||
/// compile units.
|
||||
DenseMap<Value *, CompileUnit *> CompileUnitMap;
|
||||
|
||||
/// CompileUnits - All the compile units in this module.
|
||||
///
|
||||
SmallVector<CompileUnit *, 8> CompileUnits;
|
||||
|
||||
/// ModuleCU - All DIEs are inserted in ModuleCU.
|
||||
CompileUnit *ModuleCU;
|
||||
|
||||
|
|
@ -175,8 +167,8 @@ class DwarfDebug : public DwarfPrinter {
|
|||
|
||||
/// InlineInfo - Keep track of inlined functions and their location. This
|
||||
/// information is used to populate debug_inlined section.
|
||||
typedef std::pair<unsigned, DIE *> InlineInfoLabels;
|
||||
DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo;
|
||||
typedef std::pair<MCSymbol*, DIE *> InlineInfoLabels;
|
||||
DenseMap<MDNode*, SmallVector<InlineInfoLabels, 4> > InlineInfo;
|
||||
SmallVector<MDNode *, 4> InlinedSPNodes;
|
||||
|
||||
/// CompileUnitOffsets - A vector of the offsets of the compile units. This is
|
||||
|
|
@ -251,23 +243,18 @@ class DwarfDebug : public DwarfPrinter {
|
|||
/// addLabel - Add a Dwarf label attribute data and value.
|
||||
///
|
||||
void addLabel(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
const DWLabel &Label);
|
||||
|
||||
/// addObjectLabel - Add an non-Dwarf label attribute data and value.
|
||||
///
|
||||
void addObjectLabel(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
const MCSymbol *Sym);
|
||||
const MCSymbol *Label);
|
||||
|
||||
/// addSectionOffset - Add a section offset label attribute data and value.
|
||||
///
|
||||
void addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
const DWLabel &Label, const DWLabel &Section,
|
||||
bool isEH = false, bool useSet = true);
|
||||
const MCSymbol *Label, const MCSymbol *Section,
|
||||
bool isEH = false);
|
||||
|
||||
/// addDelta - Add a label delta attribute data and value.
|
||||
///
|
||||
void addDelta(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
const DWLabel &Hi, const DWLabel &Lo);
|
||||
const MCSymbol *Hi, const MCSymbol *Lo);
|
||||
|
||||
/// addDIEEntry - Add a DIE attribute data and value.
|
||||
///
|
||||
|
|
@ -346,7 +333,7 @@ class DwarfDebug : public DwarfPrinter {
|
|||
DICompositeType *CTy);
|
||||
|
||||
/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
|
||||
DIE *constructEnumTypeDIE(DIEnumerator *ETy);
|
||||
DIE *constructEnumTypeDIE(DIEnumerator ETy);
|
||||
|
||||
/// createGlobalVariableDIE - Create new DIE using GV.
|
||||
DIE *createGlobalVariableDIE(const DIGlobalVariable &GV);
|
||||
|
|
@ -357,10 +344,6 @@ class DwarfDebug : public DwarfPrinter {
|
|||
/// createSubprogramDIE - Create new DIE using SP.
|
||||
DIE *createSubprogramDIE(const DISubprogram &SP, bool MakeDecl = false);
|
||||
|
||||
/// findCompileUnit - Get the compile unit for the given descriptor.
|
||||
///
|
||||
CompileUnit *findCompileUnit(DICompileUnit Unit);
|
||||
|
||||
/// getUpdatedDbgScope - Find or create DbgScope assicated with
|
||||
/// the instruction. Initialize scope and update scope hierarchy.
|
||||
DbgScope *getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, MDNode *InlinedAt);
|
||||
|
|
@ -529,10 +512,10 @@ public:
|
|||
///
|
||||
void endFunction(const MachineFunction *MF);
|
||||
|
||||
/// recordSourceLine - Records location information and associates it with a
|
||||
/// label. Returns a unique label ID used to generate a label and provide
|
||||
/// correspondence to the source line list.
|
||||
unsigned recordSourceLine(unsigned Line, unsigned Col, MDNode *Scope);
|
||||
/// recordSourceLine - Register a source line with debug info. Returns the
|
||||
/// unique label that was emitted and which provides correspondence to
|
||||
/// the source line list.
|
||||
MCSymbol *recordSourceLine(unsigned Line, unsigned Col, MDNode *Scope);
|
||||
|
||||
/// getSourceLineCount - Return the number of source lines in the debug
|
||||
/// info.
|
||||
|
|
@ -556,7 +539,7 @@ public:
|
|||
void collectVariableInfo();
|
||||
|
||||
/// beginScope - Process beginning of a scope starting at Label.
|
||||
void beginScope(const MachineInstr *MI, unsigned Label);
|
||||
void beginScope(const MachineInstr *MI, MCSymbol *Label);
|
||||
|
||||
/// endScope - Prcess end of a scope.
|
||||
void endScope(const MachineInstr *MI);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ using namespace llvm;
|
|||
|
||||
DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A,
|
||||
const MCAsmInfo *T)
|
||||
: DwarfPrinter(OS, A, T, "eh"), shouldEmitTable(false),shouldEmitMoves(false),
|
||||
: DwarfPrinter(OS, A, T), shouldEmitTable(false),shouldEmitMoves(false),
|
||||
shouldEmitTableModule(false), shouldEmitMovesModule(false),
|
||||
ExceptionTimer(0) {
|
||||
if (TimePassesIsEnabled)
|
||||
|
|
@ -60,7 +60,7 @@ const MCExpr *DwarfException::CreateLabelDiff(const MCExpr *ExprRef,
|
|||
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
|
||||
<< LabelName << Asm->getFunctionNumber()
|
||||
<< "_" << Index;
|
||||
MCSymbol *DotSym = Asm->OutContext.GetOrCreateSymbol(Name.str());
|
||||
MCSymbol *DotSym = Asm->OutContext.GetOrCreateTemporarySymbol(Name.str());
|
||||
Asm->OutStreamer.EmitLabel(DotSym);
|
||||
|
||||
return MCBinaryExpr::CreateSub(ExprRef,
|
||||
|
|
@ -84,25 +84,29 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
|
|||
// Begin eh frame section.
|
||||
Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection());
|
||||
|
||||
if (MAI->is_EHSymbolPrivate())
|
||||
O << MAI->getPrivateGlobalPrefix();
|
||||
O << "EH_frame" << Index << ":\n";
|
||||
MCSymbol *EHFrameSym;
|
||||
if (TLOF.isFunctionEHFrameSymbolPrivate())
|
||||
EHFrameSym = getDWLabel("EH_frame", Index);
|
||||
else
|
||||
EHFrameSym = Asm->OutContext.GetOrCreateSymbol(Twine("EH_frame") +
|
||||
Twine(Index));
|
||||
Asm->OutStreamer.EmitLabel(EHFrameSym);
|
||||
|
||||
EmitLabel("section_eh_frame", Index);
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("section_eh_frame", Index));
|
||||
|
||||
// Define base labels.
|
||||
EmitLabel("eh_frame_common", Index);
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common", Index));
|
||||
|
||||
// Define the eh frame length.
|
||||
EmitDifference("eh_frame_common_end", Index,
|
||||
"eh_frame_common_begin", Index, true);
|
||||
EOL("Length of Common Information Entry");
|
||||
Asm->OutStreamer.AddComment("Length of Common Information Entry");
|
||||
EmitDifference(getDWLabel("eh_frame_common_end", Index),
|
||||
getDWLabel("eh_frame_common_begin", Index), true);
|
||||
|
||||
// EH frame header.
|
||||
EmitLabel("eh_frame_common_begin", Index);
|
||||
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("CIE Identifier Tag");
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_begin", Index));
|
||||
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.AddComment("DW_CIE_VERSION");
|
||||
Asm->OutStreamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1/*size*/, 0/*addr*/);
|
||||
|
||||
// The personality presence indicates that language specific information will
|
||||
|
|
@ -138,14 +142,14 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
|
|||
if (APtr != Augmentation + 1)
|
||||
Augmentation[0] = 'z';
|
||||
|
||||
Asm->OutStreamer.AddComment("CIE Augmentation");
|
||||
Asm->OutStreamer.EmitBytes(StringRef(Augmentation, strlen(Augmentation)+1),0);
|
||||
EOL("CIE Augmentation");
|
||||
|
||||
// Round out reader.
|
||||
EmitULEB128(1, "CIE Code Alignment Factor");
|
||||
EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
|
||||
Asm->OutStreamer.AddComment("CIE Return Address Column");
|
||||
Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true));
|
||||
EOL("CIE Return Address Column");
|
||||
|
||||
if (Augmentation[0]) {
|
||||
EmitULEB128(AugmentationSize, "Augmentation Size");
|
||||
|
|
@ -153,8 +157,8 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
|
|||
// If there is a personality, we need to indicate the function's location.
|
||||
if (PersonalityFn) {
|
||||
EmitEncodingByte(PerEncoding, "Personality");
|
||||
Asm->OutStreamer.AddComment("Personality");
|
||||
EmitReference(PersonalityFn, PerEncoding);
|
||||
EOL("Personality");
|
||||
}
|
||||
if (UsesLSDA[Index])
|
||||
EmitEncodingByte(LSDAEncoding, "LSDA");
|
||||
|
|
@ -171,8 +175,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
|
|||
// be 8-byte on 64-bit targets to match what gcc does. Otherwise you get
|
||||
// holes which confuse readers of eh_frame.
|
||||
Asm->EmitAlignment(TD->getPointerSize() == 4 ? 2 : 3, 0, 0, false);
|
||||
EmitLabel("eh_frame_common_end", Index);
|
||||
Asm->O << '\n';
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_end", Index));
|
||||
}
|
||||
|
||||
/// EmitFDE - Emit the Frame Description Entry (FDE) for the function.
|
||||
|
|
@ -190,13 +193,13 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
|
|||
|
||||
// Externally visible entry into the functions eh frame info. If the
|
||||
// corresponding function is static, this should not be externally visible.
|
||||
if (!TheFunc->hasLocalLinkage())
|
||||
if (const char *GlobalEHDirective = MAI->getGlobalEHDirective())
|
||||
O << GlobalEHDirective << *EHFrameInfo.FunctionEHSym << '\n';
|
||||
if (!TheFunc->hasLocalLinkage() && TLOF.isFunctionEHSymbolGlobal())
|
||||
Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,MCSA_Global);
|
||||
|
||||
// If corresponding function is weak definition, this should be too.
|
||||
if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective())
|
||||
O << MAI->getWeakDefDirective() << *EHFrameInfo.FunctionEHSym << '\n';
|
||||
Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,
|
||||
MCSA_WeakDefinition);
|
||||
|
||||
// If corresponding function is hidden, this should be too.
|
||||
if (TheFunc->hasHiddenVisibility())
|
||||
|
|
@ -211,8 +214,9 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
|
|||
if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory &&
|
||||
(!TheFunc->isWeakForLinker() ||
|
||||
!MAI->getWeakDefDirective() ||
|
||||
MAI->getSupportsWeakOmittedEHFrame())) {
|
||||
O << *EHFrameInfo.FunctionEHSym << " = 0\n";
|
||||
TLOF.getSupportsWeakOmittedEHFrame())) {
|
||||
Asm->OutStreamer.EmitAssignment(EHFrameInfo.FunctionEHSym,
|
||||
MCConstantExpr::Create(0, Asm->OutContext));
|
||||
// This name has no connection to the function, so it might get
|
||||
// dead-stripped when the function is not, erroneously. Prohibit
|
||||
// dead-stripping unconditionally.
|
||||
|
|
@ -220,28 +224,29 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
|
|||
Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,
|
||||
MCSA_NoDeadStrip);
|
||||
} else {
|
||||
O << *EHFrameInfo.FunctionEHSym << ":\n";
|
||||
Asm->OutStreamer.EmitLabel(EHFrameInfo.FunctionEHSym);
|
||||
|
||||
// EH frame header.
|
||||
EmitDifference("eh_frame_end", EHFrameInfo.Number,
|
||||
"eh_frame_begin", EHFrameInfo.Number,
|
||||
Asm->OutStreamer.AddComment("Length of Frame Information Entry");
|
||||
EmitDifference(getDWLabel("eh_frame_end", EHFrameInfo.Number),
|
||||
getDWLabel("eh_frame_begin", EHFrameInfo.Number),
|
||||
true);
|
||||
EOL("Length of Frame Information Entry");
|
||||
|
||||
EmitLabel("eh_frame_begin", EHFrameInfo.Number);
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_begin",EHFrameInfo.Number));
|
||||
|
||||
EmitSectionOffset("eh_frame_begin", "eh_frame_common",
|
||||
EHFrameInfo.Number, EHFrameInfo.PersonalityIndex,
|
||||
true, true, false);
|
||||
Asm->OutStreamer.AddComment("FDE CIE offset");
|
||||
EmitSectionOffset(getDWLabel("eh_frame_begin", EHFrameInfo.Number),
|
||||
getDWLabel("eh_frame_common",
|
||||
EHFrameInfo.PersonalityIndex),
|
||||
true, true);
|
||||
|
||||
EOL("FDE CIE offset");
|
||||
|
||||
EmitReference("eh_func_begin", EHFrameInfo.Number, FDEEncoding);
|
||||
EOL("FDE initial location");
|
||||
EmitDifference("eh_func_end", EHFrameInfo.Number,
|
||||
"eh_func_begin", EHFrameInfo.Number,
|
||||
Asm->OutStreamer.AddComment("FDE initial location");
|
||||
EmitReference(getDWLabel("eh_func_begin", EHFrameInfo.Number), FDEEncoding);
|
||||
Asm->OutStreamer.AddComment("FDE address range");
|
||||
EmitDifference(getDWLabel("eh_func_end", EHFrameInfo.Number),
|
||||
getDWLabel("eh_func_begin", EHFrameInfo.Number),
|
||||
SizeOfEncodedValue(FDEEncoding) == 4);
|
||||
EOL("FDE address range");
|
||||
|
||||
// If there is a personality and landing pads then point to the language
|
||||
// specific data area in the exception table.
|
||||
|
|
@ -249,12 +254,12 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
|
|||
unsigned Size = SizeOfEncodedValue(LSDAEncoding);
|
||||
|
||||
EmitULEB128(Size, "Augmentation size");
|
||||
Asm->OutStreamer.AddComment("Language Specific Data Area");
|
||||
if (EHFrameInfo.hasLandingPads)
|
||||
EmitReference("exception", EHFrameInfo.Number, LSDAEncoding);
|
||||
EmitReference(getDWLabel("exception", EHFrameInfo.Number),LSDAEncoding);
|
||||
else
|
||||
Asm->OutStreamer.EmitIntValue(0, Size/*size*/, 0/*addrspace*/);
|
||||
|
||||
EOL("Language Specific Data Area");
|
||||
} else {
|
||||
EmitULEB128(0, "Augmentation size");
|
||||
}
|
||||
|
|
@ -268,7 +273,7 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
|
|||
// get holes which confuse readers of eh_frame.
|
||||
Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3,
|
||||
0, 0, false);
|
||||
EmitLabel("eh_frame_end", EHFrameInfo.Number);
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_end", EHFrameInfo.Number));
|
||||
|
||||
// If the function is marked used, this table should be also. We cannot
|
||||
// make the mark unconditional in this case, since retaining the table also
|
||||
|
|
@ -280,7 +285,7 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
|
|||
Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,
|
||||
MCSA_NoDeadStrip);
|
||||
}
|
||||
Asm->O << '\n';
|
||||
Asm->OutStreamer.AddBlankLine();
|
||||
}
|
||||
|
||||
/// SharedTypeIds - How many leading type ids two landing pads have in common.
|
||||
|
|
@ -699,15 +704,14 @@ void DwarfException::EmitExceptionTable() {
|
|||
Asm->EmitAlignment(2, 0, 0, false);
|
||||
|
||||
// Emit the LSDA.
|
||||
O << "GCC_except_table" << SubprogramCount << ":\n";
|
||||
EmitLabel("exception", SubprogramCount);
|
||||
MCSymbol *GCCETSym =
|
||||
Asm->OutContext.GetOrCreateSymbol(Twine("GCC_except_table")+
|
||||
Twine(SubprogramCount));
|
||||
Asm->OutStreamer.EmitLabel(GCCETSym);
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("exception", SubprogramCount));
|
||||
|
||||
if (IsSJLJ) {
|
||||
SmallString<16> LSDAName;
|
||||
raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() <<
|
||||
"_LSDA_" << Asm->getFunctionNumber();
|
||||
O << LSDAName.str() << ":\n";
|
||||
}
|
||||
if (IsSJLJ)
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("_LSDA_", Asm->getFunctionNumber()));
|
||||
|
||||
// Emit the LSDA header.
|
||||
EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
|
||||
|
|
@ -819,27 +823,30 @@ void DwarfException::EmitExceptionTable() {
|
|||
// Offset of the call site relative to the previous call site, counted in
|
||||
// number of 16-byte bundles. The first call site is counted relative to
|
||||
// the start of the procedure fragment.
|
||||
EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount,
|
||||
Asm->OutStreamer.AddComment("Region start");
|
||||
EmitSectionOffset(getDWLabel(BeginTag, BeginNumber),
|
||||
getDWLabel("eh_func_begin", SubprogramCount),
|
||||
true, true);
|
||||
EOL("Region start");
|
||||
|
||||
Asm->OutStreamer.AddComment("Region length");
|
||||
if (!S.EndLabel)
|
||||
EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber,
|
||||
EmitDifference(getDWLabel("eh_func_end", SubprogramCount),
|
||||
getDWLabel(BeginTag, BeginNumber),
|
||||
true);
|
||||
else
|
||||
EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true);
|
||||
EmitDifference(getDWLabel("label", S.EndLabel),
|
||||
getDWLabel(BeginTag, BeginNumber), true);
|
||||
|
||||
EOL("Region length");
|
||||
|
||||
// Offset of the landing pad, counted in 16-byte bundles relative to the
|
||||
// @LPStart address.
|
||||
Asm->OutStreamer.AddComment("Landing pad");
|
||||
if (!S.PadLabel) {
|
||||
Asm->OutStreamer.AddComment("Landing pad");
|
||||
Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
|
||||
} else {
|
||||
EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount,
|
||||
EmitSectionOffset(getDWLabel("label", S.PadLabel),
|
||||
getDWLabel("eh_func_begin", SubprogramCount),
|
||||
true, true);
|
||||
EOL("Landing pad");
|
||||
}
|
||||
|
||||
// Offset of the first associated action record, relative to the start of
|
||||
|
|
@ -850,11 +857,16 @@ void DwarfException::EmitExceptionTable() {
|
|||
}
|
||||
|
||||
// Emit the Action Table.
|
||||
if (Actions.size() != 0) EOL("-- Action Record Table --");
|
||||
if (Actions.size() != 0) {
|
||||
Asm->OutStreamer.AddComment("-- Action Record Table --");
|
||||
Asm->OutStreamer.AddBlankLine();
|
||||
}
|
||||
|
||||
for (SmallVectorImpl<ActionEntry>::const_iterator
|
||||
I = Actions.begin(), E = Actions.end(); I != E; ++I) {
|
||||
const ActionEntry &Action = *I;
|
||||
EOL("Action Record:");
|
||||
Asm->OutStreamer.AddComment("Action Record");
|
||||
Asm->OutStreamer.AddBlankLine();
|
||||
|
||||
// Type Filter
|
||||
//
|
||||
|
|
@ -870,23 +882,26 @@ void DwarfException::EmitExceptionTable() {
|
|||
}
|
||||
|
||||
// Emit the Catch TypeInfos.
|
||||
if (!TypeInfos.empty()) EOL("-- Catch TypeInfos --");
|
||||
if (!TypeInfos.empty()) {
|
||||
Asm->OutStreamer.AddComment("-- Catch TypeInfos --");
|
||||
Asm->OutStreamer.AddBlankLine();
|
||||
}
|
||||
for (std::vector<GlobalVariable *>::const_reverse_iterator
|
||||
I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) {
|
||||
const GlobalVariable *GV = *I;
|
||||
|
||||
if (GV) {
|
||||
Asm->OutStreamer.AddComment("TypeInfo");
|
||||
if (GV)
|
||||
EmitReference(GV, TTypeEncoding);
|
||||
EOL("TypeInfo");
|
||||
} else {
|
||||
PrintRelDirective(TTypeEncoding);
|
||||
O << "0x0";
|
||||
EOL("");
|
||||
}
|
||||
else
|
||||
Asm->OutStreamer.EmitIntValue(0, SizeOfEncodedValue(TTypeEncoding), 0);
|
||||
}
|
||||
|
||||
// Emit the Exception Specifications.
|
||||
if (!FilterIds.empty()) EOL("-- Filter IDs --");
|
||||
if (!FilterIds.empty()) {
|
||||
Asm->OutStreamer.AddComment("-- Filter IDs --");
|
||||
Asm->OutStreamer.AddBlankLine();
|
||||
}
|
||||
for (std::vector<unsigned>::const_iterator
|
||||
I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
|
||||
unsigned TypeID = *I;
|
||||
|
|
@ -945,7 +960,7 @@ void DwarfException::BeginFunction(const MachineFunction *MF) {
|
|||
|
||||
if (shouldEmitMoves || shouldEmitTable)
|
||||
// Assumes in correct section after the entry point.
|
||||
EmitLabel("eh_func_begin", ++SubprogramCount);
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_begin", ++SubprogramCount));
|
||||
|
||||
shouldEmitTableModule |= shouldEmitTable;
|
||||
shouldEmitMovesModule |= shouldEmitMoves;
|
||||
|
|
@ -962,12 +977,13 @@ void DwarfException::EndFunction() {
|
|||
if (TimePassesIsEnabled)
|
||||
ExceptionTimer->startTimer();
|
||||
|
||||
EmitLabel("eh_func_end", SubprogramCount);
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_end", SubprogramCount));
|
||||
EmitExceptionTable();
|
||||
|
||||
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
|
||||
MCSymbol *FunctionEHSym =
|
||||
Asm->GetSymbolWithGlobalValueBase(MF->getFunction(), ".eh",
|
||||
Asm->MAI->is_EHSymbolPrivate());
|
||||
TLOF.isFunctionEHFrameSymbolPrivate());
|
||||
|
||||
// Save EH frame information
|
||||
EHFrames.push_back(FunctionEHFrameInfo(FunctionEHSym, SubprogramCount,
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
//===--- lib/CodeGen/DwarfLabel.cpp - Dwarf Label -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DWARF Labels
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DwarfLabel.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
/// Profile - Used to gather unique data for the folding set.
|
||||
///
|
||||
void DWLabel::Profile(FoldingSetNodeID &ID) const {
|
||||
ID.AddString(Tag);
|
||||
ID.AddInteger(Number);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DWLabel::print(raw_ostream &O) const {
|
||||
O << "." << Tag;
|
||||
if (Number) O << Number;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
//===--- lib/CodeGen/DwarfLabel.h - Dwarf Label -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DWARF Labels.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CODEGEN_ASMPRINTER_DWARFLABEL_H__
|
||||
#define CODEGEN_ASMPRINTER_DWARFLABEL_H__
|
||||
|
||||
namespace llvm {
|
||||
class FoldingSetNodeID;
|
||||
class raw_ostream;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DWLabel - Labels are used to track locations in the assembler file.
|
||||
/// Labels appear in the form @verbatim <prefix><Tag><Number> @endverbatim,
|
||||
/// where the tag is a category of label (Ex. location) and number is a value
|
||||
/// unique in that category.
|
||||
class DWLabel {
|
||||
/// Tag - Label category tag. Should always be a statically declared C
|
||||
/// string.
|
||||
///
|
||||
const char *Tag;
|
||||
|
||||
/// Number - Value to make label unique.
|
||||
///
|
||||
unsigned Number;
|
||||
public:
|
||||
DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {}
|
||||
|
||||
// Accessors.
|
||||
const char *getTag() const { return Tag; }
|
||||
unsigned getNumber() const { return Number; }
|
||||
|
||||
/// Profile - Used to gather unique data for the folding set.
|
||||
///
|
||||
void Profile(FoldingSetNodeID &ID) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void print(raw_ostream &O) const;
|
||||
#endif
|
||||
};
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
||||
|
|
@ -31,11 +31,31 @@
|
|||
#include "llvm/ADT/SmallString.h"
|
||||
using namespace llvm;
|
||||
|
||||
DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
|
||||
const char *flavor)
|
||||
DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T)
|
||||
: 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) {}
|
||||
SubprogramCount(0) {}
|
||||
|
||||
|
||||
/// getDWLabel - Return the MCSymbol corresponding to the assembler temporary
|
||||
/// label with the specified stem and unique ID.
|
||||
MCSymbol *DwarfPrinter::getDWLabel(const char *Name, unsigned ID) const {
|
||||
// FIXME: REMOVE this. However, there is stuff in EH that passes counters in
|
||||
// here that can be zero.
|
||||
|
||||
//assert(ID && "Should use getTempLabel if no ID");
|
||||
if (ID == 0) return getTempLabel(Name);
|
||||
return Asm->OutContext.GetOrCreateTemporarySymbol
|
||||
(Twine(MAI->getPrivateGlobalPrefix()) + Twine(Name) + Twine(ID));
|
||||
}
|
||||
|
||||
/// getTempLabel - Return the MCSymbol corresponding to the assembler temporary
|
||||
/// label with the specified name.
|
||||
MCSymbol *DwarfPrinter::getTempLabel(const char *Name) const {
|
||||
return Asm->OutContext.GetOrCreateTemporarySymbol
|
||||
(Twine(MAI->getPrivateGlobalPrefix()) + Name);
|
||||
}
|
||||
|
||||
|
||||
/// SizeOfEncodedValue - Return the size of the encoding in bytes.
|
||||
unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const {
|
||||
|
|
@ -57,33 +77,6 @@ unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const {
|
||||
if (isInSection && MAI->getDwarfSectionOffsetDirective())
|
||||
O << MAI->getDwarfSectionOffsetDirective();
|
||||
else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t))
|
||||
O << MAI->getData32bitsDirective();
|
||||
else
|
||||
O << MAI->getData64bitsDirective();
|
||||
}
|
||||
|
||||
void DwarfPrinter::PrintRelDirective(unsigned Encoding) const {
|
||||
unsigned Size = SizeOfEncodedValue(Encoding);
|
||||
assert((Size == 4 || Size == 8) && "Do not support other types or rels!");
|
||||
|
||||
O << (Size == 4 ?
|
||||
MAI->getData32bitsDirective() : 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";
|
||||
|
|
@ -145,6 +138,7 @@ void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const {
|
|||
Asm->OutStreamer.AddComment(Desc);
|
||||
|
||||
if (MAI->hasLEB128()) {
|
||||
// FIXME: MCize.
|
||||
O << "\t.sleb128\t" << Value;
|
||||
Asm->OutStreamer.AddBlankLine();
|
||||
return;
|
||||
|
|
@ -170,6 +164,7 @@ void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc,
|
|||
Asm->OutStreamer.AddComment(Desc);
|
||||
|
||||
if (MAI->hasLEB128() && PadTo == 0) {
|
||||
// FIXME: MCize.
|
||||
O << "\t.uleb128\t" << Value;
|
||||
Asm->OutStreamer.AddBlankLine();
|
||||
return;
|
||||
|
|
@ -191,134 +186,48 @@ void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc,
|
|||
}
|
||||
|
||||
|
||||
/// PrintLabelName - Print label name in form used by Dwarf writer.
|
||||
///
|
||||
void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const {
|
||||
O << MAI->getPrivateGlobalPrefix() << Tag;
|
||||
if (Number) O << Number;
|
||||
}
|
||||
void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number,
|
||||
const char *Suffix) const {
|
||||
O << MAI->getPrivateGlobalPrefix() << Tag;
|
||||
if (Number) O << Number;
|
||||
O << Suffix;
|
||||
}
|
||||
|
||||
/// EmitLabel - Emit location label for internal use by Dwarf.
|
||||
///
|
||||
void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const {
|
||||
PrintLabelName(Tag, Number);
|
||||
O << ":\n";
|
||||
}
|
||||
|
||||
/// EmitReference - Emit a reference to a label.
|
||||
///
|
||||
void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
|
||||
bool IsPCRelative, bool Force32Bit) const {
|
||||
PrintRelDirective(Force32Bit);
|
||||
PrintLabelName(Tag, Number);
|
||||
if (IsPCRelative) O << "-" << MAI->getPCSymbol();
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
|
||||
unsigned Encoding) const {
|
||||
SmallString<64> Name;
|
||||
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
|
||||
<< Tag << Number;
|
||||
|
||||
MCSymbol *Sym = Asm->OutContext.GetOrCreateSymbol(Name.str());
|
||||
EmitReference(Sym, Encoding);
|
||||
}
|
||||
|
||||
void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const {
|
||||
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
|
||||
|
||||
PrintRelDirective(Encoding);
|
||||
O << *TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding);;
|
||||
const MCExpr *Exp = TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding);
|
||||
Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0);
|
||||
}
|
||||
|
||||
void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const {
|
||||
void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{
|
||||
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
|
||||
|
||||
PrintRelDirective(Encoding);
|
||||
O << *TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang,
|
||||
Asm->MMI, Encoding);;
|
||||
const MCExpr *Exp =
|
||||
TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang, Asm->MMI, Encoding);
|
||||
Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0);
|
||||
}
|
||||
|
||||
/// EmitDifference - Emit the difference between two labels. If this assembler
|
||||
/// supports .set, we emit a .set of a temporary and then use it in the .word.
|
||||
void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi,
|
||||
const char *TagLo, unsigned NumberLo,
|
||||
void DwarfPrinter::EmitDifference(const MCSymbol *TagHi, const MCSymbol *TagLo,
|
||||
bool IsSmall) {
|
||||
if (MAI->hasSetDirective()) {
|
||||
// FIXME: switch to OutStreamer.EmitAssignment.
|
||||
O << "\t.set\t";
|
||||
PrintLabelName("set", SetCounter, Flavor);
|
||||
O << ",";
|
||||
PrintLabelName(TagHi, NumberHi);
|
||||
O << "-";
|
||||
PrintLabelName(TagLo, NumberLo);
|
||||
O << "\n";
|
||||
|
||||
PrintRelDirective(IsSmall);
|
||||
PrintLabelName("set", SetCounter, Flavor);
|
||||
++SetCounter;
|
||||
} else {
|
||||
PrintRelDirective(IsSmall);
|
||||
PrintLabelName(TagHi, NumberHi);
|
||||
O << "-";
|
||||
PrintLabelName(TagLo, NumberLo);
|
||||
}
|
||||
unsigned Size = IsSmall ? 4 : TD->getPointerSize();
|
||||
Asm->EmitLabelDifference(TagHi, TagLo, Size);
|
||||
}
|
||||
|
||||
void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section,
|
||||
unsigned LabelNumber,
|
||||
unsigned SectionNumber,
|
||||
bool IsSmall, bool isEH,
|
||||
bool useSet) {
|
||||
bool printAbsolute = false;
|
||||
void DwarfPrinter::EmitSectionOffset(const MCSymbol *Label,
|
||||
const MCSymbol *Section,
|
||||
bool IsSmall, bool isEH) {
|
||||
bool isAbsolute;
|
||||
if (isEH)
|
||||
printAbsolute = MAI->isAbsoluteEHSectionOffsets();
|
||||
isAbsolute = MAI->isAbsoluteEHSectionOffsets();
|
||||
else
|
||||
printAbsolute = MAI->isAbsoluteDebugSectionOffsets();
|
||||
isAbsolute = MAI->isAbsoluteDebugSectionOffsets();
|
||||
|
||||
if (MAI->hasSetDirective() && useSet) {
|
||||
// FIXME: switch to OutStreamer.EmitAssignment.
|
||||
O << "\t.set\t";
|
||||
PrintLabelName("set", SetCounter, Flavor);
|
||||
O << ",";
|
||||
PrintLabelName(Label, LabelNumber);
|
||||
|
||||
if (!printAbsolute) {
|
||||
O << "-";
|
||||
PrintLabelName(Section, SectionNumber);
|
||||
}
|
||||
|
||||
O << "\n";
|
||||
PrintRelDirective(IsSmall);
|
||||
PrintLabelName("set", SetCounter, Flavor);
|
||||
++SetCounter;
|
||||
} else {
|
||||
PrintRelDirective(IsSmall, true);
|
||||
PrintLabelName(Label, LabelNumber);
|
||||
|
||||
if (!printAbsolute) {
|
||||
O << "-";
|
||||
PrintLabelName(Section, SectionNumber);
|
||||
}
|
||||
if (!isAbsolute)
|
||||
return EmitDifference(Label, Section, IsSmall);
|
||||
|
||||
// On COFF targets, we have to emit the weird .secrel32 directive.
|
||||
if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective())
|
||||
// FIXME: MCize.
|
||||
Asm->O << SecOffDir << Label->getName();
|
||||
else {
|
||||
unsigned Size = IsSmall ? 4 : TD->getPointerSize();
|
||||
Asm->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -337,12 +246,9 @@ void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
|
|||
const MachineMove &Move = Moves[i];
|
||||
unsigned LabelID = Move.getLabelID();
|
||||
|
||||
if (LabelID) {
|
||||
LabelID = MMI->MappedLabel(LabelID);
|
||||
|
||||
// Throw out move if the label is invalid.
|
||||
if (!LabelID) continue;
|
||||
}
|
||||
// Throw out move if the label is invalid.
|
||||
if (LabelID && MMI->isLabelDeleted(LabelID))
|
||||
continue;
|
||||
|
||||
const MachineLocation &Dst = Move.getDestination();
|
||||
const MachineLocation &Src = Move.getSource();
|
||||
|
|
@ -350,9 +256,8 @@ void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
|
|||
// Advance row if new location.
|
||||
if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) {
|
||||
EmitCFAByte(dwarf::DW_CFA_advance_loc4);
|
||||
EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true);
|
||||
Asm->O << '\n';
|
||||
|
||||
EmitDifference(getDWLabel("label", LabelID),
|
||||
getDWLabel(BaseLabel, BaseLabelID), true);
|
||||
BaseLabelID = LabelID;
|
||||
BaseLabel = "label";
|
||||
IsLocal = true;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#ifndef CODEGEN_ASMPRINTER_DWARFPRINTER_H__
|
||||
#define CODEGEN_ASMPRINTER_DWARFPRINTER_H__
|
||||
|
||||
#include "DwarfLabel.h"
|
||||
#include "llvm/CodeGen/MachineLocation.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
|
|
@ -67,15 +66,7 @@ protected:
|
|||
/// 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);
|
||||
DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T);
|
||||
public:
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
|
|
@ -86,17 +77,17 @@ public:
|
|||
const MCAsmInfo *getMCAsmInfo() const { return MAI; }
|
||||
const TargetData *getTargetData() const { return TD; }
|
||||
|
||||
/// getDWLabel - Return the MCSymbol corresponding to the assembler temporary
|
||||
/// label with the specified stem and unique ID.
|
||||
MCSymbol *getDWLabel(const char *Name, unsigned ID) const;
|
||||
|
||||
/// getTempLabel - Return an assembler temporary label with the specified
|
||||
/// name.
|
||||
MCSymbol *getTempLabel(const char *Name) const;
|
||||
|
||||
/// SizeOfEncodedValue - Return the size of the encoding in bytes.
|
||||
unsigned SizeOfEncodedValue(unsigned Encoding) const;
|
||||
|
||||
void PrintRelDirective(unsigned Encoding) const;
|
||||
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
|
||||
|
|
@ -115,57 +106,20 @@ public:
|
|||
unsigned PadTo = 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;
|
||||
|
||||
void EmitReference(const char *Tag, unsigned Number, unsigned Encoding) const;
|
||||
void EmitReference(const MCSymbol *Sym, unsigned Encoding) const;
|
||||
void EmitReference(const GlobalValue *GV, unsigned Encoding) const;
|
||||
|
||||
/// EmitDifference - Emit the difference between two labels.
|
||||
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,
|
||||
void EmitDifference(const MCSymbol *LabelHi, const MCSymbol *LabelLo,
|
||||
bool IsSmall = false);
|
||||
|
||||
void EmitSectionOffset(const char* Label, const char* Section,
|
||||
unsigned LabelNumber, unsigned SectionNumber,
|
||||
bool IsSmall = false, bool isEH = false,
|
||||
bool useSet = true);
|
||||
|
||||
/// EmitSectionOffset - Emit Label-Section or use a special purpose directive
|
||||
/// to emit a section offset if the target has one.
|
||||
void EmitSectionOffset(const MCSymbol *Label, const MCSymbol *Section,
|
||||
bool IsSmall = false, bool isEH = false);
|
||||
|
||||
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
|
||||
/// frame.
|
||||
void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
|
||||
|
|
|
|||
|
|
@ -73,11 +73,11 @@ void DwarfWriter::EndFunction(const MachineFunction *MF) {
|
|||
MMI->EndFunction();
|
||||
}
|
||||
|
||||
/// RecordSourceLine - Records location information and associates it with a
|
||||
/// label. Returns a unique label ID used to generate a label and provide
|
||||
/// correspondence to the source line list.
|
||||
unsigned DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col,
|
||||
MDNode *Scope) {
|
||||
/// RecordSourceLine - Register a source line with debug info. Returns the
|
||||
/// unique label that was emitted and which provides correspondence to
|
||||
/// the source line list.
|
||||
MCSymbol *DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col,
|
||||
MDNode *Scope) {
|
||||
return DD->recordSourceLine(Line, Col, Scope);
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ bool DwarfWriter::ShouldEmitDwarfDebug() const {
|
|||
return DD && DD->ShouldEmitDwarfDebug();
|
||||
}
|
||||
|
||||
void DwarfWriter::BeginScope(const MachineInstr *MI, unsigned L) {
|
||||
void DwarfWriter::BeginScope(const MachineInstr *MI, MCSymbol *L) {
|
||||
DD->beginScope(MI, L);
|
||||
}
|
||||
void DwarfWriter::EndScope(const MachineInstr *MI) {
|
||||
|
|
|
|||
|
|
@ -310,12 +310,23 @@ static unsigned HashEndOfMBB(const MachineBasicBlock *MBB,
|
|||
return 0; // Empty MBB.
|
||||
|
||||
--I;
|
||||
// Skip debug info so it will not affect codegen.
|
||||
while (I->isDebugValue()) {
|
||||
if (I==MBB->begin())
|
||||
return 0; // MBB empty except for debug info.
|
||||
--I;
|
||||
}
|
||||
unsigned Hash = HashMachineInstr(I);
|
||||
|
||||
if (I == MBB->begin() || minCommonTailLength == 1)
|
||||
return Hash; // Single instr MBB.
|
||||
|
||||
--I;
|
||||
while (I->isDebugValue()) {
|
||||
if (I==MBB->begin())
|
||||
return Hash; // MBB with single non-debug instr.
|
||||
--I;
|
||||
}
|
||||
// Hash in the second-to-last instruction.
|
||||
Hash ^= HashMachineInstr(I) << 2;
|
||||
return Hash;
|
||||
|
|
@ -334,9 +345,32 @@ static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1,
|
|||
unsigned TailLen = 0;
|
||||
while (I1 != MBB1->begin() && I2 != MBB2->begin()) {
|
||||
--I1; --I2;
|
||||
// Don't merge debugging pseudos.
|
||||
if (I1->isDebugValue() || I2->isDebugValue() ||
|
||||
!I1->isIdenticalTo(I2) ||
|
||||
// Skip debugging pseudos; necessary to avoid changing the code.
|
||||
while (I1->isDebugValue()) {
|
||||
if (I1==MBB1->begin()) {
|
||||
while (I2->isDebugValue()) {
|
||||
if (I2==MBB2->begin())
|
||||
// I1==DBG at begin; I2==DBG at begin
|
||||
return TailLen;
|
||||
--I2;
|
||||
}
|
||||
++I2;
|
||||
// I1==DBG at begin; I2==non-DBG, or first of DBGs not at begin
|
||||
return TailLen;
|
||||
}
|
||||
--I1;
|
||||
}
|
||||
// I1==first (untested) non-DBG preceding known match
|
||||
while (I2->isDebugValue()) {
|
||||
if (I2==MBB2->begin()) {
|
||||
++I1;
|
||||
// I1==non-DBG, or first of DBGs not at begin; I2==DBG at begin
|
||||
return TailLen;
|
||||
}
|
||||
--I2;
|
||||
}
|
||||
// I1, I2==first (untested) non-DBGs preceding known match
|
||||
if (!I1->isIdenticalTo(I2) ||
|
||||
// FIXME: This check is dubious. It's used to get around a problem where
|
||||
// people incorrectly expect inline asm directives to remain in the same
|
||||
// relative order. This is untenable because normal compiler
|
||||
|
|
@ -348,6 +382,29 @@ static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1,
|
|||
}
|
||||
++TailLen;
|
||||
}
|
||||
// Back past possible debugging pseudos at beginning of block. This matters
|
||||
// when one block differs from the other only by whether debugging pseudos
|
||||
// are present at the beginning. (This way, the various checks later for
|
||||
// I1==MBB1->begin() work as expected.)
|
||||
if (I1 == MBB1->begin() && I2 != MBB2->begin()) {
|
||||
--I2;
|
||||
while (I2->isDebugValue()) {
|
||||
if (I2 == MBB2->begin()) {
|
||||
return TailLen;
|
||||
}
|
||||
--I2;
|
||||
}
|
||||
++I2;
|
||||
}
|
||||
if (I2 == MBB2->begin() && I1 != MBB1->begin()) {
|
||||
--I1;
|
||||
while (I1->isDebugValue()) {
|
||||
if (I1 == MBB1->begin())
|
||||
return TailLen;
|
||||
--I1;
|
||||
}
|
||||
++I1;
|
||||
}
|
||||
return TailLen;
|
||||
}
|
||||
|
||||
|
|
@ -643,6 +700,8 @@ unsigned BranchFolder::CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB,
|
|||
SameTails[commonTailIndex].getTailStartPos();
|
||||
MachineBasicBlock *MBB = SameTails[commonTailIndex].getBlock();
|
||||
|
||||
// If the common tail includes any debug info we will take it pretty
|
||||
// randomly from one of the inputs. Might be better to remove it?
|
||||
DEBUG(dbgs() << "\nSplitting BB#" << MBB->getNumber() << ", size "
|
||||
<< maxCommonTailLength);
|
||||
|
||||
|
|
@ -912,6 +971,18 @@ bool BranchFolder::OptimizeBranches(MachineFunction &MF) {
|
|||
return MadeChange;
|
||||
}
|
||||
|
||||
// Blocks should be considered empty if they contain only debug info;
|
||||
// else the debug info would affect codegen.
|
||||
static bool IsEmptyBlock(MachineBasicBlock *MBB) {
|
||||
if (MBB->empty())
|
||||
return true;
|
||||
for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end();
|
||||
MBBI!=MBBE; ++MBBI) {
|
||||
if (!MBBI->isDebugValue())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// IsBetterFallthrough - Return true if it would be clearly better to
|
||||
/// fall-through to MBB1 than to fall through into MBB2. This has to return
|
||||
|
|
@ -949,7 +1020,7 @@ ReoptimizeBlock:
|
|||
// explicitly. Landing pads should not do this since the landing-pad table
|
||||
// points to this block. Blocks with their addresses taken shouldn't be
|
||||
// optimized away.
|
||||
if (MBB->empty() && !MBB->isLandingPad() && !MBB->hasAddressTaken()) {
|
||||
if (IsEmptyBlock(MBB) && !MBB->isLandingPad() && !MBB->hasAddressTaken()) {
|
||||
// Dead block? Leave for cleanup later.
|
||||
if (MBB->pred_empty()) return MadeChange;
|
||||
|
||||
|
|
@ -1141,7 +1212,23 @@ ReoptimizeBlock:
|
|||
// be 'non-branch terminators' in the block, try removing the branch and
|
||||
// then seeing if the block is empty.
|
||||
TII->RemoveBranch(*MBB);
|
||||
|
||||
// If the only things remaining in the block are debug info, remove these
|
||||
// as well, so this will behave the same as an empty block in non-debug
|
||||
// mode.
|
||||
if (!MBB->empty()) {
|
||||
bool NonDebugInfoFound = false;
|
||||
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
|
||||
I != E; ++I) {
|
||||
if (!I->isDebugValue()) {
|
||||
NonDebugInfoFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!NonDebugInfoFound)
|
||||
// Make the block empty, losing the debug info (we could probably
|
||||
// improve this in some cases.)
|
||||
MBB->erase(MBB->begin(), MBB->end());
|
||||
}
|
||||
// If this block is just an unconditional branch to CurTBB, we can
|
||||
// usually completely eliminate the block. The only case we cannot
|
||||
// completely eliminate the block is when the block before this one
|
||||
|
|
|
|||
|
|
@ -67,9 +67,6 @@ static cl::opt<bool> VerifyMachineCode("verify-machineinstrs", cl::Hidden,
|
|||
cl::desc("Verify generated machine code"),
|
||||
cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL));
|
||||
|
||||
static cl::opt<bool> EnableMachineCSE("enable-machine-cse", cl::Hidden,
|
||||
cl::desc("Enable Machine CSE"));
|
||||
|
||||
static cl::opt<cl::boolOrDefault>
|
||||
AsmVerbose("asm-verbose", cl::desc("Add comments to directives."),
|
||||
cl::init(cl::BOU_UNSET));
|
||||
|
|
@ -328,11 +325,10 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM,
|
|||
PM.add(createOptimizeExtsPass());
|
||||
if (!DisableMachineLICM)
|
||||
PM.add(createMachineLICMPass());
|
||||
if (EnableMachineCSE)
|
||||
PM.add(createMachineCSEPass());
|
||||
PM.add(createMachineCSEPass());
|
||||
if (!DisableMachineSink)
|
||||
PM.add(createMachineSinkingPass());
|
||||
printAndVerify(PM, "After MachineLICM and MachineSinking",
|
||||
printAndVerify(PM, "After Machine LICM, CSE and Sinking passes",
|
||||
/* allowDoubleDefs= */ true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -593,13 +593,10 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
|
|||
|
||||
MachineBasicBlock::iterator E = MBB->end();
|
||||
while (mi != E) {
|
||||
if (mi->isDebugValue()) {
|
||||
while (mi != E && mi->isDebugValue())
|
||||
++mi;
|
||||
if (mi != E && !mi->isDebugValue()) {
|
||||
baseIndex = indexes_->getNextNonNullIndex(baseIndex);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (mi == E)
|
||||
break;
|
||||
if (mi->killsRegister(interval.reg, tri_)) {
|
||||
DEBUG(dbgs() << " killed");
|
||||
end = baseIndex.getDefIndex();
|
||||
|
|
|
|||
|
|
@ -42,12 +42,11 @@ MachineBasicBlock::~MachineBasicBlock() {
|
|||
/// getSymbol - Return the MCSymbol for this basic block.
|
||||
///
|
||||
MCSymbol *MachineBasicBlock::getSymbol(MCContext &Ctx) const {
|
||||
SmallString<60> Name;
|
||||
const MachineFunction *MF = getParent();
|
||||
raw_svector_ostream(Name)
|
||||
<< MF->getTarget().getMCAsmInfo()->getPrivateGlobalPrefix() << "BB"
|
||||
<< MF->getFunctionNumber() << '_' << getNumber();
|
||||
return Ctx.GetOrCreateSymbol(Name.str());
|
||||
const char *Prefix = MF->getTarget().getMCAsmInfo()->getPrivateGlobalPrefix();
|
||||
return Ctx.GetOrCreateTemporarySymbol(Twine(Prefix) + "BB" +
|
||||
Twine(MF->getFunctionNumber()) + "_" +
|
||||
Twine(getNumber()));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ namespace {
|
|||
class MachineCSE : public MachineFunctionPass {
|
||||
const TargetInstrInfo *TII;
|
||||
const TargetRegisterInfo *TRI;
|
||||
MachineRegisterInfo *MRI;
|
||||
MachineDominatorTree *DT;
|
||||
AliasAnalysis *AA;
|
||||
MachineDominatorTree *DT;
|
||||
MachineRegisterInfo *MRI;
|
||||
public:
|
||||
static char ID; // Pass identification
|
||||
MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {}
|
||||
|
|
@ -61,6 +61,8 @@ namespace {
|
|||
MachineBasicBlock::const_iterator E);
|
||||
bool hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB);
|
||||
bool isCSECandidate(MachineInstr *MI);
|
||||
bool isProfitableToCSE(unsigned CSReg, unsigned Reg,
|
||||
MachineInstr *CSMI, MachineInstr *MI);
|
||||
bool ProcessBlock(MachineDomTreeNode *Node);
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
|
@ -92,7 +94,16 @@ bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI,
|
|||
if (TII->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) &&
|
||||
TargetRegisterInfo::isVirtualRegister(SrcReg) &&
|
||||
!SrcSubIdx && !DstSubIdx) {
|
||||
const TargetRegisterClass *SRC = MRI->getRegClass(SrcReg);
|
||||
const TargetRegisterClass *RC = MRI->getRegClass(Reg);
|
||||
const TargetRegisterClass *NewRC = getCommonSubClass(RC, SRC);
|
||||
if (!NewRC)
|
||||
continue;
|
||||
DEBUG(dbgs() << "Coalescing: " << *DefMI);
|
||||
DEBUG(dbgs() << "*** to: " << *MI);
|
||||
MO.setReg(SrcReg);
|
||||
if (NewRC != SRC)
|
||||
MRI->setRegClass(SrcReg, NewRC);
|
||||
DefMI->eraseFromParent();
|
||||
++NumCoalesces;
|
||||
Changed = true;
|
||||
|
|
@ -133,6 +144,8 @@ bool MachineCSE::isPhysDefTriviallyDead(unsigned Reg,
|
|||
return false;
|
||||
}
|
||||
|
||||
/// hasLivePhysRegDefUse - Return true if the specified instruction read / write
|
||||
/// physical registers (except for dead defs of physical registers).
|
||||
bool MachineCSE::hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB){
|
||||
unsigned PhysDef = 0;
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
|
|
@ -167,12 +180,19 @@ bool MachineCSE::hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB){
|
|||
return false;
|
||||
}
|
||||
|
||||
bool MachineCSE::isCSECandidate(MachineInstr *MI) {
|
||||
// Ignore copies or instructions that read / write physical registers
|
||||
// (except for dead defs of physical registers).
|
||||
static bool isCopy(const MachineInstr *MI, const TargetInstrInfo *TII) {
|
||||
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
|
||||
if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) ||
|
||||
MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg())
|
||||
return TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) ||
|
||||
MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg();
|
||||
}
|
||||
|
||||
bool MachineCSE::isCSECandidate(MachineInstr *MI) {
|
||||
if (MI->isLabel() || MI->isPHI() || MI->isImplicitDef() ||
|
||||
MI->isKill() || MI->isInlineAsm())
|
||||
return false;
|
||||
|
||||
// Ignore copies.
|
||||
if (isCopy(MI, TII))
|
||||
return false;
|
||||
|
||||
// Ignore stuff that we obviously can't move.
|
||||
|
|
@ -194,9 +214,69 @@ bool MachineCSE::isCSECandidate(MachineInstr *MI) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// isProfitableToCSE - Return true if it's profitable to eliminate MI with a
|
||||
/// common expression that defines Reg.
|
||||
bool MachineCSE::isProfitableToCSE(unsigned CSReg, unsigned Reg,
|
||||
MachineInstr *CSMI, MachineInstr *MI) {
|
||||
// FIXME: Heuristics that works around the lack the live range splitting.
|
||||
|
||||
// Heuristics #1: Don't cse "cheap" computating if the def is not local or in an
|
||||
// immediate predecessor. We don't want to increase register pressure and end up
|
||||
// causing other computation to be spilled.
|
||||
if (MI->getDesc().isAsCheapAsAMove()) {
|
||||
MachineBasicBlock *CSBB = CSMI->getParent();
|
||||
MachineBasicBlock *BB = MI->getParent();
|
||||
if (CSBB != BB &&
|
||||
find(CSBB->succ_begin(), CSBB->succ_end(), BB) == CSBB->succ_end())
|
||||
return false;
|
||||
}
|
||||
|
||||
// Heuristics #2: If the expression doesn't not use a vr and the only use
|
||||
// of the redundant computation are copies, do not cse.
|
||||
bool HasVRegUse = false;
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
const MachineOperand &MO = MI->getOperand(i);
|
||||
if (MO.isReg() && MO.isUse() && MO.getReg() &&
|
||||
TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
|
||||
HasVRegUse = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!HasVRegUse) {
|
||||
bool HasNonCopyUse = false;
|
||||
for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(Reg),
|
||||
E = MRI->use_nodbg_end(); I != E; ++I) {
|
||||
MachineInstr *Use = &*I;
|
||||
// Ignore copies.
|
||||
if (!isCopy(Use, TII)) {
|
||||
HasNonCopyUse = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!HasNonCopyUse)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Heuristics #3: If the common subexpression is used by PHIs, do not reuse
|
||||
// it unless the defined value is already used in the BB of the new use.
|
||||
bool HasPHI = false;
|
||||
SmallPtrSet<MachineBasicBlock*, 4> CSBBs;
|
||||
for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(CSReg),
|
||||
E = MRI->use_nodbg_end(); I != E; ++I) {
|
||||
MachineInstr *Use = &*I;
|
||||
HasPHI |= Use->isPHI();
|
||||
CSBBs.insert(Use->getParent());
|
||||
}
|
||||
|
||||
if (!HasPHI)
|
||||
return true;
|
||||
return CSBBs.count(MI->getParent());
|
||||
}
|
||||
|
||||
bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
|
||||
bool Changed = false;
|
||||
|
||||
SmallVector<std::pair<unsigned, unsigned>, 8> CSEPairs;
|
||||
ScopedHashTableScope<MachineInstr*, unsigned,
|
||||
MachineInstrExpressionTrait> VNTS(VNT);
|
||||
MachineBasicBlock *MBB = Node->getBlock();
|
||||
|
|
@ -231,6 +311,9 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
|
|||
MachineInstr *CSMI = Exps[CSVN];
|
||||
DEBUG(dbgs() << "Examining: " << *MI);
|
||||
DEBUG(dbgs() << "*** Found a common subexpression: " << *CSMI);
|
||||
|
||||
// Check if it's profitable to perform this CSE.
|
||||
bool DoCSE = true;
|
||||
unsigned NumDefs = MI->getDesc().getNumDefs();
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); NumDefs && i != e; ++i) {
|
||||
MachineOperand &MO = MI->getOperand(i);
|
||||
|
|
@ -243,11 +326,26 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
|
|||
assert(TargetRegisterInfo::isVirtualRegister(OldReg) &&
|
||||
TargetRegisterInfo::isVirtualRegister(NewReg) &&
|
||||
"Do not CSE physical register defs!");
|
||||
MRI->replaceRegWith(OldReg, NewReg);
|
||||
if (!isProfitableToCSE(NewReg, OldReg, CSMI, MI)) {
|
||||
DoCSE = false;
|
||||
break;
|
||||
}
|
||||
CSEPairs.push_back(std::make_pair(OldReg, NewReg));
|
||||
--NumDefs;
|
||||
}
|
||||
MI->eraseFromParent();
|
||||
++NumCSEs;
|
||||
|
||||
// Actually perform the elimination.
|
||||
if (DoCSE) {
|
||||
for (unsigned i = 0, e = CSEPairs.size(); i != e; ++i)
|
||||
MRI->replaceRegWith(CSEPairs[i].first, CSEPairs[i].second);
|
||||
MI->eraseFromParent();
|
||||
++NumCSEs;
|
||||
} else {
|
||||
DEBUG(dbgs() << "*** Not profitable, avoid CSE!\n");
|
||||
VNT.insert(MI, CurrVN++);
|
||||
Exps.push_back(MI);
|
||||
}
|
||||
CSEPairs.clear();
|
||||
}
|
||||
|
||||
// Recursively call ProcessBlock with childred.
|
||||
|
|
@ -262,7 +360,7 @@ bool MachineCSE::runOnMachineFunction(MachineFunction &MF) {
|
|||
TII = MF.getTarget().getInstrInfo();
|
||||
TRI = MF.getTarget().getRegisterInfo();
|
||||
MRI = &MF.getRegInfo();
|
||||
DT = &getAnalysis<MachineDominatorTree>();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
DT = &getAnalysis<MachineDominatorTree>();
|
||||
return ProcessBlock(DT->getRootNode());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -464,7 +464,9 @@ MCSymbol *MachineFunction::getJTISymbol(unsigned JTI, MCContext &Ctx,
|
|||
SmallString<60> Name;
|
||||
raw_svector_ostream(Name)
|
||||
<< Prefix << "JTI" << getFunctionNumber() << '_' << JTI;
|
||||
return Ctx.GetOrCreateSymbol(Name.str());
|
||||
if (isLinkerPrivate)
|
||||
return Ctx.GetOrCreateSymbol(Name.str());
|
||||
return Ctx.GetOrCreateTemporarySymbol(Name.str());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1219,7 +1219,7 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const {
|
|||
DIScope Scope = DLT.getScope();
|
||||
OS << " dbg:";
|
||||
// Omit the directory, since it's usually long and uninteresting.
|
||||
if (!Scope.isNull())
|
||||
if (Scope.Verify())
|
||||
OS << Scope.getFilename();
|
||||
else
|
||||
OS << "<unknown>";
|
||||
|
|
|
|||
|
|
@ -185,7 +185,8 @@ void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) {
|
|||
void MachineModuleInfo::TidyLandingPads() {
|
||||
for (unsigned i = 0; i != LandingPads.size(); ) {
|
||||
LandingPadInfo &LandingPad = LandingPads[i];
|
||||
LandingPad.LandingPadLabel = MappedLabel(LandingPad.LandingPadLabel);
|
||||
if (isLabelDeleted(LandingPad.LandingPadLabel))
|
||||
LandingPad.LandingPadLabel = 0;
|
||||
|
||||
// Special case: we *should* emit LPs with null LP MBB. This indicates
|
||||
// "nounwind" case.
|
||||
|
|
@ -195,17 +196,14 @@ void MachineModuleInfo::TidyLandingPads() {
|
|||
}
|
||||
|
||||
for (unsigned j=0; j != LandingPads[i].BeginLabels.size(); ) {
|
||||
unsigned BeginLabel = MappedLabel(LandingPad.BeginLabels[j]);
|
||||
unsigned EndLabel = MappedLabel(LandingPad.EndLabels[j]);
|
||||
|
||||
if (!BeginLabel || !EndLabel) {
|
||||
unsigned BeginLabel = LandingPad.BeginLabels[j];
|
||||
unsigned EndLabel = LandingPad.EndLabels[j];
|
||||
if (isLabelDeleted(BeginLabel) || isLabelDeleted(EndLabel)) {
|
||||
LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j);
|
||||
LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j);
|
||||
continue;
|
||||
}
|
||||
|
||||
LandingPad.BeginLabels[j] = BeginLabel;
|
||||
LandingPad.EndLabels[j] = EndLabel;
|
||||
++j;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) {
|
|||
const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo();
|
||||
RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : NULL;
|
||||
FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn);
|
||||
FrameConstantRegMap.clear();
|
||||
|
||||
// Get MachineModuleInfo so that we can track the construction of the
|
||||
// frame.
|
||||
|
|
@ -685,7 +686,7 @@ void PEI::replaceFrameIndices(MachineFunction &Fn) {
|
|||
// If this instruction has a FrameIndex operand, we need to
|
||||
// use that target machine register info object to eliminate
|
||||
// it.
|
||||
int Value;
|
||||
TargetRegisterInfo::FrameIndexValue Value;
|
||||
unsigned VReg =
|
||||
TRI.eliminateFrameIndex(MI, SPAdj, &Value,
|
||||
FrameIndexVirtualScavenging ? NULL : RS);
|
||||
|
|
@ -764,12 +765,12 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) {
|
|||
unsigned CurrentVirtReg = 0;
|
||||
unsigned CurrentScratchReg = 0;
|
||||
bool havePrevValue = false;
|
||||
int PrevValue = 0;
|
||||
TargetRegisterInfo::FrameIndexValue PrevValue(0,0);
|
||||
TargetRegisterInfo::FrameIndexValue Value(0,0);
|
||||
MachineInstr *PrevLastUseMI = NULL;
|
||||
unsigned PrevLastUseOp = 0;
|
||||
bool trackingCurrentValue = false;
|
||||
int SPAdj = 0;
|
||||
int Value = 0;
|
||||
|
||||
// The instruction stream may change in the loop, so check BB->end()
|
||||
// directly.
|
||||
|
|
@ -826,8 +827,11 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) {
|
|||
if (trackingCurrentValue) {
|
||||
SPAdj = (*Entry).second.second;
|
||||
Value = (*Entry).second.first;
|
||||
} else
|
||||
SPAdj = Value = 0;
|
||||
} else {
|
||||
SPAdj = 0;
|
||||
Value.first = 0;
|
||||
Value.second = 0;
|
||||
}
|
||||
|
||||
// If the scratch register from the last allocation is still
|
||||
// available, see if the value matches. If it does, just re-use it.
|
||||
|
|
|
|||
|
|
@ -102,7 +102,8 @@ namespace llvm {
|
|||
// When using the scavenger post-pass to resolve frame reference
|
||||
// materialization registers, maintain a map of the registers to
|
||||
// the constant value and SP adjustment associated with it.
|
||||
typedef std::pair<int, int> FrameConstantEntry;
|
||||
typedef std::pair<TargetRegisterInfo::FrameIndexValue, int>
|
||||
FrameConstantEntry;
|
||||
DenseMap<unsigned, FrameConstantEntry> FrameConstantRegMap;
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
|
|||
|
|
@ -34,14 +34,16 @@ class SDDbgValue {
|
|||
MDNode *mdPtr;
|
||||
uint64_t Offset;
|
||||
DebugLoc DL;
|
||||
unsigned Order;
|
||||
public:
|
||||
// Constructor for non-constants.
|
||||
SDDbgValue(MDNode *mdP, SDNode *N, unsigned R, uint64_t off, DebugLoc dl) :
|
||||
Node(N), ResNo(R), Const(0), mdPtr(mdP), Offset(off), DL(dl) {}
|
||||
SDDbgValue(MDNode *mdP, SDNode *N, unsigned R, uint64_t off, DebugLoc dl,
|
||||
unsigned O) :
|
||||
Node(N), ResNo(R), Const(0), mdPtr(mdP), Offset(off), DL(dl), Order(O) {}
|
||||
|
||||
// Constructor for constants.
|
||||
SDDbgValue(MDNode *mdP, Value *C, uint64_t off, DebugLoc dl) : Node(0),
|
||||
ResNo(0), Const(C), mdPtr(mdP), Offset(off), DL(dl) {}
|
||||
SDDbgValue(MDNode *mdP, Value *C, uint64_t off, DebugLoc dl, unsigned O) :
|
||||
Node(0), ResNo(0), Const(C), mdPtr(mdP), Offset(off), DL(dl), Order(O) {}
|
||||
|
||||
// Returns the MDNode pointer.
|
||||
MDNode *getMDPtr() { return mdPtr; }
|
||||
|
|
@ -60,6 +62,10 @@ public:
|
|||
|
||||
// Returns the DebugLoc.
|
||||
DebugLoc getDebugLoc() { return DL; }
|
||||
|
||||
// Returns the SDNodeOrder. This is the order of the preceding node in the
|
||||
// input.
|
||||
unsigned getOrder() { return Order; }
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
|
|
|||
|
|
@ -3208,7 +3208,7 @@ bool MeetsMaxMemopRequirement(std::vector<EVT> &MemOps,
|
|||
bool isSrcConst = isa<ConstantSDNode>(Src);
|
||||
EVT VT = TLI.getOptimalMemOpType(Size, Align, isSrcConst, isSrcStr, DAG);
|
||||
bool AllowUnalign = TLI.allowsUnalignedMemoryAccesses(VT);
|
||||
if (VT != MVT::iAny) {
|
||||
if (VT != MVT::Other) {
|
||||
const Type *Ty = VT.getTypeForEVT(*DAG.getContext());
|
||||
unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty);
|
||||
// If source is a string constant, this will require an unaligned load.
|
||||
|
|
@ -3216,14 +3216,14 @@ bool MeetsMaxMemopRequirement(std::vector<EVT> &MemOps,
|
|||
if (Dst.getOpcode() != ISD::FrameIndex) {
|
||||
// Can't change destination alignment. It requires a unaligned store.
|
||||
if (AllowUnalign)
|
||||
VT = MVT::iAny;
|
||||
VT = MVT::Other;
|
||||
} else {
|
||||
int FI = cast<FrameIndexSDNode>(Dst)->getIndex();
|
||||
MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
|
||||
if (MFI->isFixedObjectIndex(FI)) {
|
||||
// Can't change destination alignment. It requires a unaligned store.
|
||||
if (AllowUnalign)
|
||||
VT = MVT::iAny;
|
||||
VT = MVT::Other;
|
||||
} else {
|
||||
// Give the stack frame object a larger alignment if needed.
|
||||
if (MFI->getObjectAlignment(FI) < NewAlign)
|
||||
|
|
@ -3234,7 +3234,7 @@ bool MeetsMaxMemopRequirement(std::vector<EVT> &MemOps,
|
|||
}
|
||||
}
|
||||
|
||||
if (VT == MVT::iAny) {
|
||||
if (VT == MVT::Other) {
|
||||
if (TLI.allowsUnalignedMemoryAccesses(MVT::i64)) {
|
||||
VT = MVT::i64;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2141,6 +2141,9 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
|
|||
|
||||
while (1) {
|
||||
assert(MatcherIndex < TableSize && "Invalid index");
|
||||
#ifndef NDEBUG
|
||||
unsigned CurrentOpcodeIndex = MatcherIndex;
|
||||
#endif
|
||||
BuiltinOpcodes Opcode = (BuiltinOpcodes)MatcherTable[MatcherIndex++];
|
||||
switch (Opcode) {
|
||||
case OPC_Scope: {
|
||||
|
|
@ -2666,6 +2669,7 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
|
|||
// If the code reached this point, then the match failed. See if there is
|
||||
// another child to try in the current 'Scope', otherwise pop it until we
|
||||
// find a case to check.
|
||||
DEBUG(errs() << " Match failed at index " << CurrentOpcodeIndex << "\n");
|
||||
while (1) {
|
||||
if (MatchScopes.empty()) {
|
||||
CannotYetSelect(NodeToMatch);
|
||||
|
|
@ -2680,13 +2684,12 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
|
|||
NodeStack.append(LastScope.NodeStack.begin(), LastScope.NodeStack.end());
|
||||
N = NodeStack.back();
|
||||
|
||||
DEBUG(errs() << " Match failed at index " << MatcherIndex
|
||||
<< " continuing at " << LastScope.FailIndex << "\n");
|
||||
|
||||
if (LastScope.NumMatchedMemRefs != MatchedMemRefs.size())
|
||||
MatchedMemRefs.resize(LastScope.NumMatchedMemRefs);
|
||||
MatcherIndex = LastScope.FailIndex;
|
||||
|
||||
DEBUG(errs() << " Continuing at " << MatcherIndex << "\n");
|
||||
|
||||
InputChain = LastScope.InputChain;
|
||||
InputFlag = LastScope.InputFlag;
|
||||
if (!LastScope.HasChainNodesMatched)
|
||||
|
|
|
|||
|
|
@ -1671,8 +1671,20 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
|
|||
// density, do not join them, instead mark the physical register as its
|
||||
// allocation preference.
|
||||
LiveInterval &JoinVInt = SrcIsPhys ? DstInt : SrcInt;
|
||||
LiveInterval &JoinPInt = SrcIsPhys ? SrcInt : DstInt;
|
||||
unsigned JoinVReg = SrcIsPhys ? DstReg : SrcReg;
|
||||
unsigned JoinPReg = SrcIsPhys ? SrcReg : DstReg;
|
||||
|
||||
// Don't join with physregs that have a ridiculous number of live
|
||||
// ranges. The data structure performance is really bad when that
|
||||
// happens.
|
||||
if (JoinPInt.ranges.size() > 1000) {
|
||||
mri_->setRegAllocationHint(JoinVInt.reg, 0, JoinPReg);
|
||||
++numAborts;
|
||||
DEBUG(dbgs() << "\tPhysical register too complicated, abort!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const TargetRegisterClass *RC = mri_->getRegClass(JoinVReg);
|
||||
unsigned Threshold = allocatableRCRegs_[RC].count() * 2;
|
||||
unsigned Length = li_->getApproximateInstructionCount(JoinVInt);
|
||||
|
|
|
|||
|
|
@ -403,12 +403,15 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
|
|||
|
||||
// Add information about the stub reference to ELFMMI so that the stub
|
||||
// gets emitted by the asmprinter.
|
||||
MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str());
|
||||
MCSymbol *Sym = getContext().GetOrCreateTemporarySymbol(Name.str());
|
||||
MCSymbol *&StubSym = ELFMMI.getGVStubEntry(Sym);
|
||||
if (StubSym == 0) {
|
||||
Name.clear();
|
||||
Mang->getNameWithPrefix(Name, GV, false);
|
||||
StubSym = getContext().GetOrCreateSymbol(Name.str());
|
||||
if (GV->hasPrivateLinkage())
|
||||
StubSym = getContext().GetOrCreateTemporarySymbol(Name.str());
|
||||
else
|
||||
StubSym = getContext().GetOrCreateSymbol(Name.str());
|
||||
}
|
||||
|
||||
return TargetLoweringObjectFile::
|
||||
|
|
@ -463,6 +466,14 @@ getMachOSection(StringRef Segment, StringRef Section,
|
|||
|
||||
void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx,
|
||||
const TargetMachine &TM) {
|
||||
// _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
|
||||
// doesn't hurt anything.
|
||||
// FIXME: I need to get this from Triple.
|
||||
IsFunctionEHSymbolGlobal = true;
|
||||
IsFunctionEHFrameSymbolPrivate = false;
|
||||
SupportsWeakOmittedEHFrame = false;
|
||||
|
||||
if (UniquingMap != 0)
|
||||
((MachOUniqueMapTy*)UniquingMap)->clear();
|
||||
TargetLoweringObjectFile::Initialize(Ctx, TM);
|
||||
|
|
@ -651,16 +662,16 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
|
|||
}
|
||||
|
||||
// FIXME: Alignment check should be handled by section classifier.
|
||||
if (Kind.isMergeable1ByteCString() ||
|
||||
(Kind.isMergeable2ByteCString() && !GV->hasExternalLinkage())) {
|
||||
if (TM.getTargetData()->getPreferredAlignment(
|
||||
cast<GlobalVariable>(GV)) < 32) {
|
||||
if (Kind.isMergeable1ByteCString())
|
||||
return CStringSection;
|
||||
assert(Kind.isMergeable2ByteCString());
|
||||
return UStringSection;
|
||||
}
|
||||
}
|
||||
if (Kind.isMergeable1ByteCString() &&
|
||||
TM.getTargetData()->getPreferredAlignment(cast<GlobalVariable>(GV)) < 32)
|
||||
return CStringSection;
|
||||
|
||||
// Do not put 16-bit arrays in the UString section if they have an
|
||||
// externally visible label, this runs into issues with certain linker
|
||||
// versions.
|
||||
if (Kind.isMergeable2ByteCString() && !GV->hasExternalLinkage() &&
|
||||
TM.getTargetData()->getPreferredAlignment(cast<GlobalVariable>(GV)) < 32)
|
||||
return UStringSection;
|
||||
|
||||
if (Kind.isMergeableConst()) {
|
||||
if (Kind.isMergeableConst4())
|
||||
|
|
@ -749,12 +760,15 @@ getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
|
|||
|
||||
// Add information about the stub reference to MachOMMI so that the stub
|
||||
// gets emitted by the asmprinter.
|
||||
MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str());
|
||||
MCSymbol *Sym = getContext().GetOrCreateTemporarySymbol(Name.str());
|
||||
MCSymbol *&StubSym = MachOMMI.getGVStubEntry(Sym);
|
||||
if (StubSym == 0) {
|
||||
Name.clear();
|
||||
Mang->getNameWithPrefix(Name, GV, false);
|
||||
StubSym = getContext().GetOrCreateSymbol(Name.str());
|
||||
if (GV->hasPrivateLinkage())
|
||||
StubSym = getContext().GetOrCreateTemporarySymbol(Name.str());
|
||||
else
|
||||
StubSym = getContext().GetOrCreateSymbol(Name.str());
|
||||
}
|
||||
|
||||
return TargetLoweringObjectFile::
|
||||
|
|
|
|||
|
|
@ -75,10 +75,9 @@ JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr,
|
|||
unsigned LabelID = Move.getLabelID();
|
||||
|
||||
if (LabelID) {
|
||||
LabelID = MMI->MappedLabel(LabelID);
|
||||
|
||||
// Throw out move if the label is invalid.
|
||||
if (!LabelID) continue;
|
||||
if (MMI->isLabelDeleted(LabelID))
|
||||
continue;
|
||||
}
|
||||
|
||||
intptr_t LabelPtr = 0;
|
||||
|
|
@ -722,10 +721,9 @@ JITDwarfEmitter::GetFrameMovesSizeInBytes(intptr_t BaseLabelPtr,
|
|||
unsigned LabelID = Move.getLabelID();
|
||||
|
||||
if (LabelID) {
|
||||
LabelID = MMI->MappedLabel(LabelID);
|
||||
|
||||
// Throw out move if the label is invalid.
|
||||
if (!LabelID) continue;
|
||||
if (MMI->isLabelDeleted(LabelID))
|
||||
continue;
|
||||
}
|
||||
|
||||
intptr_t LabelPtr = 0;
|
||||
|
|
|
|||
|
|
@ -68,9 +68,6 @@ MCAsmInfo::MCAsmInfo() {
|
|||
ExceptionsType = ExceptionHandling::None;
|
||||
DwarfRequiresFrameSection = true;
|
||||
DwarfUsesInlineInfoSection = false;
|
||||
Is_EHSymbolPrivate = true;
|
||||
GlobalEHDirective = 0;
|
||||
SupportsWeakOmittedEHFrame = true;
|
||||
DwarfSectionOffsetDirective = 0;
|
||||
|
||||
AsmTransCBE = 0;
|
||||
|
|
|
|||
|
|
@ -40,19 +40,8 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
|
|||
HiddenVisibilityAttr = MCSA_PrivateExtern;
|
||||
// Doesn't support protected visibility.
|
||||
ProtectedVisibilityAttr = MCSA_Global;
|
||||
|
||||
|
||||
HasDotTypeDotSizeDirective = false;
|
||||
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
|
||||
// doesn't hurt anything.
|
||||
// FIXME: I need to get this from Triple.
|
||||
Is_EHSymbolPrivate = false;
|
||||
GlobalEHDirective = "\t.globl\t";
|
||||
SupportsWeakOmittedEHFrame = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -440,29 +440,49 @@ public:
|
|||
DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
|
||||
std::vector<MachRelocationEntry> &Relocs) {
|
||||
uint32_t Address = Fragment.getOffset() + Fixup.Offset;
|
||||
unsigned IsPCRel = 0;
|
||||
unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind);
|
||||
unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
|
||||
unsigned Type = RIT_Vanilla;
|
||||
|
||||
// See <reloc.h>.
|
||||
const MCSymbol *A = Target.getSymA();
|
||||
MCSymbolData *SD = SymbolMap.lookup(A);
|
||||
uint32_t Value = SD->getFragment()->getAddress() + SD->getOffset();
|
||||
MCSymbolData *A_SD = SymbolMap.lookup(A);
|
||||
|
||||
if (!A_SD->getFragment())
|
||||
llvm_report_error("symbol '" + A->getName() +
|
||||
"' can not be undefined in a subtraction expression");
|
||||
|
||||
uint32_t Value = A_SD->getFragment()->getAddress() + A_SD->getOffset();
|
||||
uint32_t Value2 = 0;
|
||||
|
||||
if (const MCSymbol *B = Target.getSymB()) {
|
||||
Type = RIT_LocalDifference;
|
||||
MCSymbolData *B_SD = SymbolMap.lookup(B);
|
||||
|
||||
MCSymbolData *SD = SymbolMap.lookup(B);
|
||||
Value2 = SD->getFragment()->getAddress() + SD->getOffset();
|
||||
if (!B_SD->getFragment())
|
||||
llvm_report_error("symbol '" + B->getName() +
|
||||
"' can not be undefined in a subtraction expression");
|
||||
|
||||
// Select the appropriate difference relocation type.
|
||||
//
|
||||
// Note that there is no longer any semantic difference between these two
|
||||
// relocation types from the linkers point of view, this is done solely
|
||||
// for pedantic compatibility with 'as'.
|
||||
Type = A_SD->isExternal() ? RIT_Difference : RIT_LocalDifference;
|
||||
Value2 = B_SD->getFragment()->getAddress() + B_SD->getOffset();
|
||||
}
|
||||
|
||||
// The value which goes in the fixup is current value of the expression.
|
||||
Fixup.FixedValue = Value - Value2 + Target.getConstant();
|
||||
if (isFixupKindPCRel(Fixup.Kind)) {
|
||||
if (IsPCRel)
|
||||
Fixup.FixedValue -= Address;
|
||||
IsPCRel = 1;
|
||||
}
|
||||
|
||||
// If this fixup is a vanilla PC relative relocation for a local label, we
|
||||
// don't need a relocation.
|
||||
//
|
||||
// FIXME: Implement proper atom support.
|
||||
if (IsPCRel && Target.getSymA() && Target.getSymA()->isTemporary() &&
|
||||
!Target.getSymB())
|
||||
return;
|
||||
|
||||
MachRelocationEntry MRE;
|
||||
MRE.Word0 = ((Address << 0) |
|
||||
|
|
@ -473,14 +493,12 @@ public:
|
|||
MRE.Word1 = Value;
|
||||
Relocs.push_back(MRE);
|
||||
|
||||
if (Type == RIT_LocalDifference) {
|
||||
Type = RIT_Pair;
|
||||
|
||||
if (Type == RIT_Difference || Type == RIT_LocalDifference) {
|
||||
MachRelocationEntry MRE;
|
||||
MRE.Word0 = ((0 << 0) |
|
||||
(Type << 24) |
|
||||
(RIT_Pair << 24) |
|
||||
(Log2Size << 28) |
|
||||
(0 << 30) |
|
||||
(IsPCRel << 30) |
|
||||
RF_Scattered);
|
||||
MRE.Word1 = Value2;
|
||||
Relocs.push_back(MRE);
|
||||
|
|
@ -491,15 +509,21 @@ public:
|
|||
MCAsmFixup &Fixup,
|
||||
DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
|
||||
std::vector<MachRelocationEntry> &Relocs) {
|
||||
unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind);
|
||||
unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
|
||||
|
||||
MCValue Target;
|
||||
if (!Fixup.Value->EvaluateAsRelocatable(Target))
|
||||
llvm_report_error("expected relocatable expression");
|
||||
|
||||
// If this is a difference or a local symbol plus an offset, then we need a
|
||||
// scattered relocation entry.
|
||||
// If this is a difference or a defined symbol plus an offset, then we need
|
||||
// a scattered relocation entry.
|
||||
uint32_t Offset = Target.getConstant();
|
||||
if (IsPCRel)
|
||||
Offset += 1 << Log2Size;
|
||||
if (Target.getSymB() ||
|
||||
(Target.getSymA() && !Target.getSymA()->isUndefined() &&
|
||||
Target.getConstant()))
|
||||
Offset))
|
||||
return ComputeScatteredRelocationInfo(Asm, Fragment, Fixup, Target,
|
||||
SymbolMap, Relocs);
|
||||
|
||||
|
|
@ -507,8 +531,6 @@ public:
|
|||
uint32_t Address = Fragment.getOffset() + Fixup.Offset;
|
||||
uint32_t Value = 0;
|
||||
unsigned Index = 0;
|
||||
unsigned IsPCRel = 0;
|
||||
unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
|
||||
unsigned IsExtern = 0;
|
||||
unsigned Type = 0;
|
||||
|
||||
|
|
@ -545,11 +567,15 @@ public:
|
|||
|
||||
// The value which goes in the fixup is current value of the expression.
|
||||
Fixup.FixedValue = Value + Target.getConstant();
|
||||
|
||||
if (isFixupKindPCRel(Fixup.Kind)) {
|
||||
if (IsPCRel)
|
||||
Fixup.FixedValue -= Address;
|
||||
IsPCRel = 1;
|
||||
}
|
||||
|
||||
// If this fixup is a vanilla PC relative relocation for a local label, we
|
||||
// don't need a relocation.
|
||||
//
|
||||
// FIXME: Implement proper atom support.
|
||||
if (IsPCRel && Target.getSymA() && Target.getSymA()->isTemporary())
|
||||
return;
|
||||
|
||||
// struct relocation_info (8 bytes)
|
||||
MachRelocationEntry MRE;
|
||||
|
|
@ -1040,8 +1066,8 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
|
|||
|
||||
// Align the fragment offset; it is safe to adjust the offset freely since
|
||||
// this is only in virtual sections.
|
||||
uint64_t Aligned = RoundUpToAlignment(Address, ZFF.getAlignment());
|
||||
F.setOffset(Aligned - SD.getAddress());
|
||||
Address = RoundUpToAlignment(Address, ZFF.getAlignment());
|
||||
F.setOffset(Address - SD.getAddress());
|
||||
|
||||
// FIXME: This is misnamed.
|
||||
F.setFileSize(ZFF.getSize());
|
||||
|
|
@ -1270,9 +1296,15 @@ void MCAssembler::Finish() {
|
|||
if (!isVirtualSection(SD.getSection()))
|
||||
continue;
|
||||
|
||||
// Align this section if necessary by adding padding bytes to the previous
|
||||
// section.
|
||||
if (uint64_t Pad = OffsetToAlignment(Address, it->getAlignment()))
|
||||
Address += Pad;
|
||||
|
||||
SD.setAddress(Address);
|
||||
LayoutSection(SD);
|
||||
Address += SD.getSize();
|
||||
|
||||
}
|
||||
|
||||
DEBUG_WITH_TYPE("mc-dump", {
|
||||
|
|
@ -1336,7 +1368,7 @@ void MCDataFragment::dump() {
|
|||
OS << ",\n ";
|
||||
OS << " Fixups:[";
|
||||
for (fixup_iterator it = fixup_begin(), ie = fixup_end(); it != ie; ++it) {
|
||||
if (it != fixup_begin()) OS << ",\n ";
|
||||
if (it != fixup_begin()) OS << ",\n ";
|
||||
OS << *it;
|
||||
}
|
||||
OS << "]";
|
||||
|
|
@ -1379,7 +1411,7 @@ void MCSectionData::dump() {
|
|||
OS << "<MCSectionData";
|
||||
OS << " Alignment:" << getAlignment() << " Address:" << Address
|
||||
<< " Size:" << Size << " FileSize:" << FileSize
|
||||
<< " Fragments:[";
|
||||
<< " Fragments:[\n ";
|
||||
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
||||
if (it != begin()) OS << ",\n ";
|
||||
it->dump();
|
||||
|
|
@ -1407,7 +1439,7 @@ void MCAssembler::dump() {
|
|||
raw_ostream &OS = llvm::errs();
|
||||
|
||||
OS << "<MCAssembler\n";
|
||||
OS << " Sections:[";
|
||||
OS << " Sections:[\n ";
|
||||
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
||||
if (it != begin()) OS << ",\n ";
|
||||
it->dump();
|
||||
|
|
@ -1416,7 +1448,7 @@ void MCAssembler::dump() {
|
|||
OS << " Symbols:[";
|
||||
|
||||
for (symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) {
|
||||
if (it != symbol_begin()) OS << ",\n ";
|
||||
if (it != symbol_begin()) OS << ",\n ";
|
||||
it->dump();
|
||||
}
|
||||
OS << "]>\n";
|
||||
|
|
|
|||
|
|
@ -23,16 +23,8 @@ MCContext::~MCContext() {
|
|||
// we don't need to free them here.
|
||||
}
|
||||
|
||||
MCSymbol *MCContext::CreateSymbol(StringRef Name) {
|
||||
assert(Name[0] != '\0' && "Normal symbols cannot be unnamed!");
|
||||
|
||||
// Create and bind the symbol, and ensure that names are unique.
|
||||
MCSymbol *&Entry = Symbols[Name];
|
||||
assert(!Entry && "Duplicate symbol definition!");
|
||||
return Entry = new (*this) MCSymbol(Name, false);
|
||||
}
|
||||
|
||||
MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) {
|
||||
assert(!Name.empty() && "Normal symbols cannot be unnamed!");
|
||||
MCSymbol *&Entry = Symbols[Name];
|
||||
if (Entry) return Entry;
|
||||
|
||||
|
|
@ -46,17 +38,24 @@ MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) {
|
|||
}
|
||||
|
||||
|
||||
MCSymbol *MCContext::CreateTemporarySymbol(StringRef Name) {
|
||||
MCSymbol *MCContext::GetOrCreateTemporarySymbol(StringRef Name) {
|
||||
// If unnamed, just create a symbol.
|
||||
if (Name.empty())
|
||||
new (*this) MCSymbol("", true);
|
||||
|
||||
// Otherwise create as usual.
|
||||
MCSymbol *&Entry = Symbols[Name];
|
||||
assert(!Entry && "Duplicate symbol definition!");
|
||||
if (Entry) return Entry;
|
||||
return Entry = new (*this) MCSymbol(Name, true);
|
||||
}
|
||||
|
||||
MCSymbol *MCContext::GetOrCreateTemporarySymbol(const Twine &Name) {
|
||||
SmallString<128> NameSV;
|
||||
Name.toVector(NameSV);
|
||||
return GetOrCreateTemporarySymbol(NameSV.str());
|
||||
}
|
||||
|
||||
|
||||
MCSymbol *MCContext::LookupSymbol(StringRef Name) const {
|
||||
return Symbols.lookup(Name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,6 +133,11 @@ const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, MCContext &Ctx) {
|
|||
return Create(Ctx.GetOrCreateSymbol(Name), Ctx);
|
||||
}
|
||||
|
||||
const MCSymbolRefExpr *MCSymbolRefExpr::CreateTemp(StringRef Name,
|
||||
MCContext &Ctx) {
|
||||
return Create(Ctx.GetOrCreateTemporarySymbol(Name), Ctx);
|
||||
}
|
||||
|
||||
void MCTargetExpr::Anchor() {}
|
||||
|
||||
/* *** */
|
||||
|
|
|
|||
|
|
@ -29,7 +29,11 @@ namespace {
|
|||
CurSection = Section;
|
||||
}
|
||||
|
||||
virtual void EmitLabel(MCSymbol *Symbol) {}
|
||||
virtual void EmitLabel(MCSymbol *Symbol) {
|
||||
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
|
||||
assert(CurSection && "Cannot emit before setting section!");
|
||||
Symbol->setSection(*CurSection);
|
||||
}
|
||||
|
||||
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -240,14 +240,10 @@ bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
|
|||
}
|
||||
|
||||
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);
|
||||
return Ctx.GetOrCreateTemporarySymbol(Name);
|
||||
return Ctx.GetOrCreateSymbol(Name);
|
||||
}
|
||||
|
||||
/// ParsePrimaryExpr - Parse a primary expression and return it.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size,
|
|||
EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace);
|
||||
}
|
||||
|
||||
void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
|
||||
unsigned AddrSpace) {
|
||||
EmitValue(MCSymbolRefExpr::Create(Sym, 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,
|
||||
|
|
|
|||
|
|
@ -3366,7 +3366,7 @@ namespace {
|
|||
|
||||
void APFloat::toString(SmallVectorImpl<char> &Str,
|
||||
unsigned FormatPrecision,
|
||||
unsigned FormatMaxPadding) {
|
||||
unsigned FormatMaxPadding) const {
|
||||
switch (category) {
|
||||
case fcInfinity:
|
||||
if (isNegative())
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ bool isJumpTableBranchOpcode(int Opc) {
|
|||
|
||||
static inline
|
||||
bool isIndirectBranchOpcode(int Opc) {
|
||||
return Opc == ARM::BRIND || Opc == ARM::tBRIND;
|
||||
return Opc == ARM::BRIND || Opc == ARM::MOVPCRX || Opc == ARM::tBRIND;
|
||||
}
|
||||
|
||||
/// getInstrPredicate - If instruction is predicated, returns its predicate
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#include "llvm/Support/CommandLine.h"
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool>
|
||||
cl::opt<bool>
|
||||
ReuseFrameIndexVals("arm-reuse-frame-index-vals", cl::Hidden, cl::init(true),
|
||||
cl::desc("Reuse repeated frame index values"));
|
||||
|
||||
|
|
@ -1153,7 +1153,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
|||
|
||||
unsigned
|
||||
ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, int *Value,
|
||||
int SPAdj, FrameIndexValue *Value,
|
||||
RegScavenger *RS) const {
|
||||
unsigned i = 0;
|
||||
MachineInstr &MI = *II;
|
||||
|
|
@ -1205,7 +1205,10 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||
MI.getOperand(i).ChangeToRegister(FrameReg, false, false, false);
|
||||
else {
|
||||
ScratchReg = MF.getRegInfo().createVirtualRegister(ARM::GPRRegisterClass);
|
||||
if (Value) *Value = Offset;
|
||||
if (Value) {
|
||||
Value->first = FrameReg; // use the frame register as a kind indicator
|
||||
Value->second = Offset;
|
||||
}
|
||||
if (!AFI->isThumbFunction())
|
||||
emitARMRegPlusImmediate(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg,
|
||||
Offset, Pred, PredReg, TII);
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ public:
|
|||
MachineBasicBlock::iterator I) const;
|
||||
|
||||
virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, int *Value = NULL,
|
||||
int SPAdj, FrameIndexValue *Value = NULL,
|
||||
RegScavenger *RS = NULL) const;
|
||||
|
||||
virtual void emitPrologue(MachineFunction &MF) const;
|
||||
|
|
|
|||
|
|
@ -1138,7 +1138,7 @@ void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) {
|
|||
// Set the conditional execution predicate
|
||||
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
|
||||
|
||||
if (TID.Opcode == ARM::BX_RET)
|
||||
if (TID.Opcode == ARM::BX_RET || TID.Opcode == ARM::MOVPCLR)
|
||||
// The return register is LR.
|
||||
Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@
|
|||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/PseudoSourceValue.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/ADT/VectorExtras.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
|
@ -130,7 +130,8 @@ void ARMTargetLowering::addQRTypeForNEON(EVT VT) {
|
|||
|
||||
static TargetLoweringObjectFile *createTLOF(TargetMachine &TM) {
|
||||
if (TM.getSubtarget<ARMSubtarget>().isTargetDarwin())
|
||||
return new TargetLoweringObjectFileMachO();
|
||||
return new ARMMachOTargetObjectFile();
|
||||
|
||||
return new ARMElfTargetObjectFile();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ def SDT_ARMCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>, SDTCisVT<1, i32> ]>;
|
|||
|
||||
def SDT_ARMSaveCallPC : SDTypeProfile<0, 1, []>;
|
||||
|
||||
def SDT_ARMcall : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
|
||||
def SDT_ARMcall : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
|
||||
|
||||
def SDT_ARMCMov : SDTypeProfile<1, 3,
|
||||
[SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
|
||||
|
|
@ -113,6 +113,8 @@ def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>;
|
|||
//===----------------------------------------------------------------------===//
|
||||
// ARM Instruction Predicate Definitions.
|
||||
//
|
||||
def HasV4T : Predicate<"Subtarget->hasV4TOps()">;
|
||||
def NoV4T : Predicate<"!Subtarget->hasV4TOps()">;
|
||||
def HasV5T : Predicate<"Subtarget->hasV5TOps()">;
|
||||
def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">;
|
||||
def HasV6 : Predicate<"Subtarget->hasV6Ops()">;
|
||||
|
|
@ -851,24 +853,50 @@ def LEApcrelJT : AXI1<0x0, (outs GPR:$dst),
|
|||
// Control Flow Instructions.
|
||||
//
|
||||
|
||||
let isReturn = 1, isTerminator = 1, isBarrier = 1 in
|
||||
let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
|
||||
// ARMV4T and above
|
||||
def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br,
|
||||
"bx", "\tlr", [(ARMretflag)]> {
|
||||
let Inst{3-0} = 0b1110;
|
||||
let Inst{7-4} = 0b0001;
|
||||
let Inst{19-8} = 0b111111111111;
|
||||
let Inst{27-20} = 0b00010010;
|
||||
"bx", "\tlr", [(ARMretflag)]>,
|
||||
Requires<[IsARM, HasV4T]> {
|
||||
let Inst{3-0} = 0b1110;
|
||||
let Inst{7-4} = 0b0001;
|
||||
let Inst{19-8} = 0b111111111111;
|
||||
let Inst{27-20} = 0b00010010;
|
||||
}
|
||||
|
||||
// ARMV4 only
|
||||
def MOVPCLR : AI<(outs), (ins), BrMiscFrm, IIC_Br,
|
||||
"mov", "\tpc, lr", [(ARMretflag)]>,
|
||||
Requires<[IsARM, NoV4T]> {
|
||||
let Inst{11-0} = 0b000000001110;
|
||||
let Inst{15-12} = 0b1111;
|
||||
let Inst{19-16} = 0b0000;
|
||||
let Inst{27-20} = 0b00011010;
|
||||
}
|
||||
}
|
||||
|
||||
// Indirect branches
|
||||
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
|
||||
// ARMV4T and above
|
||||
def BRIND : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "bx\t$dst",
|
||||
[(brind GPR:$dst)]> {
|
||||
[(brind GPR:$dst)]>,
|
||||
Requires<[IsARM, HasV4T]> {
|
||||
let Inst{7-4} = 0b0001;
|
||||
let Inst{19-8} = 0b111111111111;
|
||||
let Inst{27-20} = 0b00010010;
|
||||
let Inst{31-28} = 0b1110;
|
||||
}
|
||||
|
||||
// ARMV4 only
|
||||
def MOVPCRX : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "mov\tpc, $dst",
|
||||
[(brind GPR:$dst)]>,
|
||||
Requires<[IsARM, NoV4T]> {
|
||||
let Inst{11-4} = 0b00000000;
|
||||
let Inst{15-12} = 0b1111;
|
||||
let Inst{19-16} = 0b0000;
|
||||
let Inst{27-20} = 0b00011010;
|
||||
let Inst{31-28} = 0b1110;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: remove when we have a way to marking a MI with these properties.
|
||||
|
|
@ -913,11 +941,22 @@ let isCall = 1,
|
|||
def BX : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
|
||||
IIC_Br, "mov\tlr, pc\n\tbx\t$func",
|
||||
[(ARMcall_nolink tGPR:$func)]>,
|
||||
Requires<[IsARM, IsNotDarwin]> {
|
||||
Requires<[IsARM, HasV4T, IsNotDarwin]> {
|
||||
let Inst{7-4} = 0b0001;
|
||||
let Inst{19-8} = 0b111111111111;
|
||||
let Inst{27-20} = 0b00010010;
|
||||
}
|
||||
|
||||
// ARMv4
|
||||
def BMOVPCRX : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
|
||||
IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func",
|
||||
[(ARMcall_nolink tGPR:$func)]>,
|
||||
Requires<[IsARM, NoV4T, IsNotDarwin]> {
|
||||
let Inst{11-4} = 0b00000000;
|
||||
let Inst{15-12} = 0b1111;
|
||||
let Inst{19-16} = 0b0000;
|
||||
let Inst{27-20} = 0b00011010;
|
||||
}
|
||||
}
|
||||
|
||||
// On Darwin R9 is call-clobbered.
|
||||
|
|
@ -950,11 +989,23 @@ let isCall = 1,
|
|||
// Note: Restrict $func to the tGPR regclass to prevent it being in LR.
|
||||
def BXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
|
||||
IIC_Br, "mov\tlr, pc\n\tbx\t$func",
|
||||
[(ARMcall_nolink tGPR:$func)]>, Requires<[IsARM, IsDarwin]> {
|
||||
[(ARMcall_nolink tGPR:$func)]>,
|
||||
Requires<[IsARM, HasV4T, IsDarwin]> {
|
||||
let Inst{7-4} = 0b0001;
|
||||
let Inst{19-8} = 0b111111111111;
|
||||
let Inst{27-20} = 0b00010010;
|
||||
}
|
||||
|
||||
// ARMv4
|
||||
def BMOVPCRXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
|
||||
IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func",
|
||||
[(ARMcall_nolink tGPR:$func)]>,
|
||||
Requires<[IsARM, NoV4T, IsDarwin]> {
|
||||
let Inst{11-4} = 0b00000000;
|
||||
let Inst{15-12} = 0b1111;
|
||||
let Inst{19-16} = 0b0000;
|
||||
let Inst{27-20} = 0b00011010;
|
||||
}
|
||||
}
|
||||
|
||||
let isBranch = 1, isTerminator = 1 in {
|
||||
|
|
@ -2793,29 +2844,29 @@ def MRSsys : ABI<0b0001,(outs GPR:$dst),(ins), NoItinerary,"mrs","\t$dst, spsr",
|
|||
let Inst{7-4} = 0b0000;
|
||||
}
|
||||
|
||||
// FIXME: mask is ignored for the time being.
|
||||
def MSR : ABI<0b0001,(outs),(ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src",
|
||||
def MSR : ABI<0b0001, (outs), (ins GPR:$src, i32imm:$mask), NoItinerary, "msr",
|
||||
"\tcpsr${mask:msr}, $src",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{23-20} = 0b0010;
|
||||
let Inst{7-4} = 0b0000;
|
||||
}
|
||||
|
||||
// FIXME: mask is ignored for the time being.
|
||||
def MSRi : ABI<0b0011,(outs),(ins so_imm:$a), NoItinerary, "msr", "\tcpsr, $a",
|
||||
def MSRi : ABI<0b0011, (outs), (ins so_imm:$a, i32imm:$mask), NoItinerary,"msr",
|
||||
"\tcpsr${mask:msr}, $a",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{23-20} = 0b0010;
|
||||
let Inst{7-4} = 0b0000;
|
||||
}
|
||||
|
||||
// FIXME: mask is ignored for the time being.
|
||||
def MSRsys : ABI<0b0001,(outs),(ins GPR:$src),NoItinerary,"msr","\tspsr, $src",
|
||||
def MSRsys : ABI<0b0001, (outs), (ins GPR:$src, i32imm:$mask),NoItinerary,"msr",
|
||||
"\tspsr${mask:msr}, $src",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{23-20} = 0b0110;
|
||||
let Inst{7-4} = 0b0000;
|
||||
}
|
||||
|
||||
// FIXME: mask is ignored for the time being.
|
||||
def MSRsysi : ABI<0b0011,(outs),(ins so_imm:$a),NoItinerary,"msr","\tspsr, $a",
|
||||
def MSRsysi : ABI<0b0011,(outs),(ins so_imm:$a, i32imm:$mask),NoItinerary,"msr",
|
||||
"\tspsr${mask:msr}, $a",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{23-20} = 0b0110;
|
||||
let Inst{7-4} = 0b0000;
|
||||
|
|
|
|||
|
|
@ -2707,21 +2707,21 @@ def VSETLNi32 : NVSetLane<{1,1,1,0,0,0,?,0}, 0b1011, 0b00, (outs DPR:$dst),
|
|||
}
|
||||
def : Pat<(vector_insert (v16i8 QPR:$src1), GPR:$src2, imm:$lane),
|
||||
(v16i8 (INSERT_SUBREG QPR:$src1,
|
||||
(VSETLNi8 (v8i8 (EXTRACT_SUBREG QPR:$src1,
|
||||
(v8i8 (VSETLNi8 (v8i8 (EXTRACT_SUBREG QPR:$src1,
|
||||
(DSubReg_i8_reg imm:$lane))),
|
||||
GPR:$src2, (SubReg_i8_lane imm:$lane)),
|
||||
GPR:$src2, (SubReg_i8_lane imm:$lane))),
|
||||
(DSubReg_i8_reg imm:$lane)))>;
|
||||
def : Pat<(vector_insert (v8i16 QPR:$src1), GPR:$src2, imm:$lane),
|
||||
(v8i16 (INSERT_SUBREG QPR:$src1,
|
||||
(VSETLNi16 (v4i16 (EXTRACT_SUBREG QPR:$src1,
|
||||
(v4i16 (VSETLNi16 (v4i16 (EXTRACT_SUBREG QPR:$src1,
|
||||
(DSubReg_i16_reg imm:$lane))),
|
||||
GPR:$src2, (SubReg_i16_lane imm:$lane)),
|
||||
GPR:$src2, (SubReg_i16_lane imm:$lane))),
|
||||
(DSubReg_i16_reg imm:$lane)))>;
|
||||
def : Pat<(insertelt (v4i32 QPR:$src1), GPR:$src2, imm:$lane),
|
||||
(v4i32 (INSERT_SUBREG QPR:$src1,
|
||||
(VSETLNi32 (v2i32 (EXTRACT_SUBREG QPR:$src1,
|
||||
(v2i32 (VSETLNi32 (v2i32 (EXTRACT_SUBREG QPR:$src1,
|
||||
(DSubReg_i32_reg imm:$lane))),
|
||||
GPR:$src2, (SubReg_i32_lane imm:$lane)),
|
||||
GPR:$src2, (SubReg_i32_lane imm:$lane))),
|
||||
(DSubReg_i32_reg imm:$lane)))>;
|
||||
|
||||
def : Pat<(v2f32 (insertelt DPR:$src1, SPR:$src2, imm:$src3)),
|
||||
|
|
@ -3093,16 +3093,17 @@ def VTBX4
|
|||
|
||||
class N2VSPat<SDNode OpNode, ValueType ResTy, ValueType OpTy, NeonI Inst>
|
||||
: NEONFPPat<(ResTy (OpNode SPR:$a)),
|
||||
(EXTRACT_SUBREG (Inst (INSERT_SUBREG (OpTy (IMPLICIT_DEF)),
|
||||
SPR:$a, arm_ssubreg_0)),
|
||||
(EXTRACT_SUBREG (OpTy (Inst (INSERT_SUBREG (OpTy (IMPLICIT_DEF)),
|
||||
SPR:$a, arm_ssubreg_0))),
|
||||
arm_ssubreg_0)>;
|
||||
|
||||
class N3VSPat<SDNode OpNode, NeonI Inst>
|
||||
: NEONFPPat<(f32 (OpNode SPR:$a, SPR:$b)),
|
||||
(EXTRACT_SUBREG (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)),
|
||||
SPR:$a, arm_ssubreg_0),
|
||||
(INSERT_SUBREG (v2f32 (IMPLICIT_DEF)),
|
||||
SPR:$b, arm_ssubreg_0)),
|
||||
(EXTRACT_SUBREG (v2f32
|
||||
(Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)),
|
||||
SPR:$a, arm_ssubreg_0),
|
||||
(INSERT_SUBREG (v2f32 (IMPLICIT_DEF)),
|
||||
SPR:$b, arm_ssubreg_0))),
|
||||
arm_ssubreg_0)>;
|
||||
|
||||
class N3VSMulOpPat<SDNode MulNode, SDNode OpNode, NeonI Inst>
|
||||
|
|
|
|||
|
|
@ -331,9 +331,9 @@ multiclass T2I_bin_ii12rs<bits<3> op23_21, string opc, PatFrag opnode,
|
|||
let Inst{15} = 0;
|
||||
}
|
||||
// 12-bit imm
|
||||
def ri12 : T2sI<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi,
|
||||
!strconcat(opc, "w"), "\t$dst, $lhs, $rhs",
|
||||
[(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]> {
|
||||
def ri12 : T2I<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi,
|
||||
!strconcat(opc, "w"), "\t$dst, $lhs, $rhs",
|
||||
[(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]> {
|
||||
let Inst{31-27} = 0b11110;
|
||||
let Inst{25} = 1;
|
||||
let Inst{24} = 0;
|
||||
|
|
@ -2637,9 +2637,9 @@ def t2MRSsys : T2I<(outs GPR:$dst), (ins), NoItinerary, "mrs", "\t$dst, spsr",
|
|||
let Inst{12} = 0;
|
||||
}
|
||||
|
||||
// FIXME: mask is ignored for the time being.
|
||||
// Rn = Inst{19-16}
|
||||
def t2MSR : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src",
|
||||
def t2MSR : T2I<(outs), (ins GPR:$src, i32imm:$mask), NoItinerary, "msr",
|
||||
"\tcpsr${mask:msr}, $src",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{31-27} = 0b11110;
|
||||
let Inst{26} = 0;
|
||||
|
|
@ -2649,9 +2649,9 @@ def t2MSR : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src",
|
|||
let Inst{12} = 0;
|
||||
}
|
||||
|
||||
// FIXME: mask is ignored for the time being.
|
||||
// Rn = Inst{19-16}
|
||||
def t2MSRsys : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tspsr, $src",
|
||||
def t2MSRsys : T2I<(outs), (ins GPR:$src, i32imm:$mask), NoItinerary, "msr",
|
||||
"\tspsr${mask:msr}, $src",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
let Inst{31-27} = 0b11110;
|
||||
let Inst{26} = 0;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ def vfp_f64imm : Operand<f64>,
|
|||
let canFoldAsLoad = 1, isReMaterializable = 1 in {
|
||||
def VLDRD : ADI5<0b1101, 0b01, (outs DPR:$dst), (ins addrmode5:$addr),
|
||||
IIC_fpLoad64, "vldr", ".64\t$dst, $addr",
|
||||
[(set DPR:$dst, (load addrmode5:$addr))]>;
|
||||
[(set DPR:$dst, (f64 (load addrmode5:$addr)))]>;
|
||||
|
||||
def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr),
|
||||
IIC_fpLoad32, "vldr", ".32\t$dst, $addr",
|
||||
|
|
@ -66,7 +66,7 @@ def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr),
|
|||
|
||||
def VSTRD : ADI5<0b1101, 0b00, (outs), (ins DPR:$src, addrmode5:$addr),
|
||||
IIC_fpStore64, "vstr", ".64\t$src, $addr",
|
||||
[(store DPR:$src, addrmode5:$addr)]>;
|
||||
[(store (f64 DPR:$src), addrmode5:$addr)]>;
|
||||
|
||||
def VSTRS : ASI5<0b1101, 0b00, (outs), (ins SPR:$src, addrmode5:$addr),
|
||||
IIC_fpStore32, "vstr", ".32\t$src, $addr",
|
||||
|
|
@ -116,7 +116,7 @@ def VSTMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$wb,
|
|||
|
||||
def VADDD : ADbI<0b11100, 0b11, 0, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b),
|
||||
IIC_fpALU64, "vadd", ".f64\t$dst, $a, $b",
|
||||
[(set DPR:$dst, (fadd DPR:$a, DPR:$b))]>;
|
||||
[(set DPR:$dst, (fadd DPR:$a, (f64 DPR:$b)))]>;
|
||||
|
||||
def VADDS : ASbIn<0b11100, 0b11, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
|
||||
IIC_fpALU32, "vadd", ".f32\t$dst, $a, $b",
|
||||
|
|
@ -126,7 +126,7 @@ def VADDS : ASbIn<0b11100, 0b11, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
|
|||
let Defs = [FPSCR] in {
|
||||
def VCMPED : ADuI<0b11101, 0b11, 0b0100, 0b11, 0, (outs), (ins DPR:$a, DPR:$b),
|
||||
IIC_fpCMP64, "vcmpe", ".f64\t$a, $b",
|
||||
[(arm_cmpfp DPR:$a, DPR:$b)]>;
|
||||
[(arm_cmpfp DPR:$a, (f64 DPR:$b))]>;
|
||||
|
||||
def VCMPD : ADuI<0b11101, 0b11, 0b0100, 0b01, 0, (outs), (ins DPR:$a, DPR:$b),
|
||||
IIC_fpCMP64, "vcmp", ".f64\t$a, $b",
|
||||
|
|
@ -143,7 +143,7 @@ def VCMPS : ASuI<0b11101, 0b11, 0b0100, 0b01, 0, (outs), (ins SPR:$a, SPR:$b),
|
|||
|
||||
def VDIVD : ADbI<0b11101, 0b00, 0, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b),
|
||||
IIC_fpDIV64, "vdiv", ".f64\t$dst, $a, $b",
|
||||
[(set DPR:$dst, (fdiv DPR:$a, DPR:$b))]>;
|
||||
[(set DPR:$dst, (fdiv DPR:$a, (f64 DPR:$b)))]>;
|
||||
|
||||
def VDIVS : ASbI<0b11101, 0b00, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
|
||||
IIC_fpDIV32, "vdiv", ".f32\t$dst, $a, $b",
|
||||
|
|
@ -151,7 +151,7 @@ def VDIVS : ASbI<0b11101, 0b00, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
|
|||
|
||||
def VMULD : ADbI<0b11100, 0b10, 0, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b),
|
||||
IIC_fpMUL64, "vmul", ".f64\t$dst, $a, $b",
|
||||
[(set DPR:$dst, (fmul DPR:$a, DPR:$b))]>;
|
||||
[(set DPR:$dst, (fmul DPR:$a, (f64 DPR:$b)))]>;
|
||||
|
||||
def VMULS : ASbIn<0b11100, 0b10, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
|
||||
IIC_fpMUL32, "vmul", ".f32\t$dst, $a, $b",
|
||||
|
|
@ -159,14 +159,14 @@ def VMULS : ASbIn<0b11100, 0b10, 0, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
|
|||
|
||||
def VNMULD : ADbI<0b11100, 0b10, 1, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b),
|
||||
IIC_fpMUL64, "vnmul", ".f64\t$dst, $a, $b",
|
||||
[(set DPR:$dst, (fneg (fmul DPR:$a, DPR:$b)))]>;
|
||||
[(set DPR:$dst, (fneg (fmul DPR:$a, (f64 DPR:$b))))]>;
|
||||
|
||||
def VNMULS : ASbI<0b11100, 0b10, 1, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
|
||||
IIC_fpMUL32, "vnmul", ".f32\t$dst, $a, $b",
|
||||
[(set SPR:$dst, (fneg (fmul SPR:$a, SPR:$b)))]>;
|
||||
|
||||
// Match reassociated forms only if not sign dependent rounding.
|
||||
def : Pat<(fmul (fneg DPR:$a), DPR:$b),
|
||||
def : Pat<(fmul (fneg DPR:$a), (f64 DPR:$b)),
|
||||
(VNMULD DPR:$a, DPR:$b)>, Requires<[NoHonorSignDependentRounding]>;
|
||||
def : Pat<(fmul (fneg SPR:$a), SPR:$b),
|
||||
(VNMULS SPR:$a, SPR:$b)>, Requires<[NoHonorSignDependentRounding]>;
|
||||
|
|
@ -174,7 +174,7 @@ def : Pat<(fmul (fneg SPR:$a), SPR:$b),
|
|||
|
||||
def VSUBD : ADbI<0b11100, 0b11, 1, 0, (outs DPR:$dst), (ins DPR:$a, DPR:$b),
|
||||
IIC_fpALU64, "vsub", ".f64\t$dst, $a, $b",
|
||||
[(set DPR:$dst, (fsub DPR:$a, DPR:$b))]>;
|
||||
[(set DPR:$dst, (fsub DPR:$a, (f64 DPR:$b)))]>;
|
||||
|
||||
def VSUBS : ASbIn<0b11100, 0b11, 1, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
|
||||
IIC_fpALU32, "vsub", ".f32\t$dst, $a, $b",
|
||||
|
|
@ -186,7 +186,7 @@ def VSUBS : ASbIn<0b11100, 0b11, 1, 0, (outs SPR:$dst), (ins SPR:$a, SPR:$b),
|
|||
|
||||
def VABSD : ADuI<0b11101, 0b11, 0b0000, 0b11, 0, (outs DPR:$dst), (ins DPR:$a),
|
||||
IIC_fpUNA64, "vabs", ".f64\t$dst, $a",
|
||||
[(set DPR:$dst, (fabs DPR:$a))]>;
|
||||
[(set DPR:$dst, (fabs (f64 DPR:$a)))]>;
|
||||
|
||||
def VABSS : ASuIn<0b11101, 0b11, 0b0000, 0b11, 0,(outs SPR:$dst), (ins SPR:$a),
|
||||
IIC_fpUNA32, "vabs", ".f32\t$dst, $a",
|
||||
|
|
@ -195,7 +195,7 @@ def VABSS : ASuIn<0b11101, 0b11, 0b0000, 0b11, 0,(outs SPR:$dst), (ins SPR:$a),
|
|||
let Defs = [FPSCR] in {
|
||||
def VCMPEZD : ADuI<0b11101, 0b11, 0b0101, 0b11, 0, (outs), (ins DPR:$a),
|
||||
IIC_fpCMP64, "vcmpe", ".f64\t$a, #0",
|
||||
[(arm_cmpfp0 DPR:$a)]>;
|
||||
[(arm_cmpfp0 (f64 DPR:$a))]>;
|
||||
|
||||
def VCMPZD : ADuI<0b11101, 0b11, 0b0101, 0b01, 0, (outs), (ins DPR:$a),
|
||||
IIC_fpCMP64, "vcmp", ".f64\t$a, #0",
|
||||
|
|
@ -253,7 +253,7 @@ def VMOVS: ASuI<0b11101, 0b11, 0b0000, 0b01, 0, (outs SPR:$dst), (ins SPR:$a),
|
|||
|
||||
def VNEGD : ADuI<0b11101, 0b11, 0b0001, 0b01, 0, (outs DPR:$dst), (ins DPR:$a),
|
||||
IIC_fpUNA64, "vneg", ".f64\t$dst, $a",
|
||||
[(set DPR:$dst, (fneg DPR:$a))]>;
|
||||
[(set DPR:$dst, (fneg (f64 DPR:$a)))]>;
|
||||
|
||||
def VNEGS : ASuIn<0b11101, 0b11, 0b0001, 0b01, 0,(outs SPR:$dst), (ins SPR:$a),
|
||||
IIC_fpUNA32, "vneg", ".f32\t$dst, $a",
|
||||
|
|
@ -261,7 +261,7 @@ def VNEGS : ASuIn<0b11101, 0b11, 0b0001, 0b01, 0,(outs SPR:$dst), (ins SPR:$a),
|
|||
|
||||
def VSQRTD : ADuI<0b11101, 0b11, 0b0001, 0b11, 0, (outs DPR:$dst), (ins DPR:$a),
|
||||
IIC_fpSQRT64, "vsqrt", ".f64\t$dst, $a",
|
||||
[(set DPR:$dst, (fsqrt DPR:$a))]>;
|
||||
[(set DPR:$dst, (fsqrt (f64 DPR:$a)))]>;
|
||||
|
||||
def VSQRTS : ASuI<0b11101, 0b11, 0b0001, 0b11, 0, (outs SPR:$dst), (ins SPR:$a),
|
||||
IIC_fpSQRT32, "vsqrt", ".f32\t$dst, $a",
|
||||
|
|
@ -325,7 +325,7 @@ def VMOVSRR : AVConv5I<0b11000100, 0b1010,
|
|||
def VSITOD : AVConv1I<0b11101, 0b11, 0b1000, 0b1011,
|
||||
(outs DPR:$dst), (ins SPR:$a),
|
||||
IIC_fpCVTID, "vcvt", ".f64.s32\t$dst, $a",
|
||||
[(set DPR:$dst, (arm_sitof SPR:$a))]> {
|
||||
[(set DPR:$dst, (f64 (arm_sitof SPR:$a)))]> {
|
||||
let Inst{7} = 1; // s32
|
||||
}
|
||||
|
||||
|
|
@ -339,7 +339,7 @@ def VSITOS : AVConv1In<0b11101, 0b11, 0b1000, 0b1010,
|
|||
def VUITOD : AVConv1I<0b11101, 0b11, 0b1000, 0b1011,
|
||||
(outs DPR:$dst), (ins SPR:$a),
|
||||
IIC_fpCVTID, "vcvt", ".f64.u32\t$dst, $a",
|
||||
[(set DPR:$dst, (arm_uitof SPR:$a))]> {
|
||||
[(set DPR:$dst, (f64 (arm_uitof SPR:$a)))]> {
|
||||
let Inst{7} = 0; // u32
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +356,7 @@ def VUITOS : AVConv1In<0b11101, 0b11, 0b1000, 0b1010,
|
|||
def VTOSIZD : AVConv1I<0b11101, 0b11, 0b1101, 0b1011,
|
||||
(outs SPR:$dst), (ins DPR:$a),
|
||||
IIC_fpCVTDI, "vcvt", ".s32.f64\t$dst, $a",
|
||||
[(set SPR:$dst, (arm_ftosi DPR:$a))]> {
|
||||
[(set SPR:$dst, (arm_ftosi (f64 DPR:$a)))]> {
|
||||
let Inst{7} = 1; // Z bit
|
||||
}
|
||||
|
||||
|
|
@ -370,7 +370,7 @@ def VTOSIZS : AVConv1In<0b11101, 0b11, 0b1101, 0b1010,
|
|||
def VTOUIZD : AVConv1I<0b11101, 0b11, 0b1100, 0b1011,
|
||||
(outs SPR:$dst), (ins DPR:$a),
|
||||
IIC_fpCVTDI, "vcvt", ".u32.f64\t$dst, $a",
|
||||
[(set SPR:$dst, (arm_ftoui DPR:$a))]> {
|
||||
[(set SPR:$dst, (arm_ftoui (f64 DPR:$a)))]> {
|
||||
let Inst{7} = 1; // Z bit
|
||||
}
|
||||
|
||||
|
|
@ -514,7 +514,8 @@ def VULTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 1,
|
|||
def VMLAD : ADbI<0b11100, 0b00, 0, 0,
|
||||
(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b),
|
||||
IIC_fpMAC64, "vmla", ".f64\t$dst, $a, $b",
|
||||
[(set DPR:$dst, (fadd (fmul DPR:$a, DPR:$b), DPR:$dstin))]>,
|
||||
[(set DPR:$dst, (fadd (fmul DPR:$a, DPR:$b),
|
||||
(f64 DPR:$dstin)))]>,
|
||||
RegConstraint<"$dstin = $dst">;
|
||||
|
||||
def VMLAS : ASbIn<0b11100, 0b00, 0, 0,
|
||||
|
|
@ -526,7 +527,8 @@ def VMLAS : ASbIn<0b11100, 0b00, 0, 0,
|
|||
def VNMLSD : ADbI<0b11100, 0b01, 0, 0,
|
||||
(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b),
|
||||
IIC_fpMAC64, "vnmls", ".f64\t$dst, $a, $b",
|
||||
[(set DPR:$dst, (fsub (fmul DPR:$a, DPR:$b), DPR:$dstin))]>,
|
||||
[(set DPR:$dst, (fsub (fmul DPR:$a, DPR:$b),
|
||||
(f64 DPR:$dstin)))]>,
|
||||
RegConstraint<"$dstin = $dst">;
|
||||
|
||||
def VNMLSS : ASbI<0b11100, 0b01, 0, 0,
|
||||
|
|
@ -538,7 +540,8 @@ def VNMLSS : ASbI<0b11100, 0b01, 0, 0,
|
|||
def VMLSD : ADbI<0b11100, 0b00, 1, 0,
|
||||
(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b),
|
||||
IIC_fpMAC64, "vmls", ".f64\t$dst, $a, $b",
|
||||
[(set DPR:$dst, (fadd (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>,
|
||||
[(set DPR:$dst, (fadd (fneg (fmul DPR:$a, DPR:$b)),
|
||||
(f64 DPR:$dstin)))]>,
|
||||
RegConstraint<"$dstin = $dst">;
|
||||
|
||||
def VMLSS : ASbIn<0b11100, 0b00, 1, 0,
|
||||
|
|
@ -547,7 +550,7 @@ def VMLSS : ASbIn<0b11100, 0b00, 1, 0,
|
|||
[(set SPR:$dst, (fadd (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>,
|
||||
RegConstraint<"$dstin = $dst">;
|
||||
|
||||
def : Pat<(fsub DPR:$dstin, (fmul DPR:$a, DPR:$b)),
|
||||
def : Pat<(fsub DPR:$dstin, (fmul DPR:$a, (f64 DPR:$b))),
|
||||
(VMLSD DPR:$dstin, DPR:$a, DPR:$b)>, Requires<[DontUseNEONForFP]>;
|
||||
def : Pat<(fsub SPR:$dstin, (fmul SPR:$a, SPR:$b)),
|
||||
(VMLSS SPR:$dstin, SPR:$a, SPR:$b)>, Requires<[DontUseNEONForFP]>;
|
||||
|
|
@ -555,7 +558,8 @@ def : Pat<(fsub SPR:$dstin, (fmul SPR:$a, SPR:$b)),
|
|||
def VNMLAD : ADbI<0b11100, 0b01, 1, 0,
|
||||
(outs DPR:$dst), (ins DPR:$dstin, DPR:$a, DPR:$b),
|
||||
IIC_fpMAC64, "vnmla", ".f64\t$dst, $a, $b",
|
||||
[(set DPR:$dst, (fsub (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>,
|
||||
[(set DPR:$dst, (fsub (fneg (fmul DPR:$a, DPR:$b)),
|
||||
(f64 DPR:$dstin)))]>,
|
||||
RegConstraint<"$dstin = $dst">;
|
||||
|
||||
def VNMLAS : ASbI<0b11100, 0b01, 1, 0,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() {
|
|||
|
||||
// Exceptions handling
|
||||
ExceptionsType = ExceptionHandling::SjLj;
|
||||
AbsoluteEHSectionOffsets = false;
|
||||
}
|
||||
|
||||
ARMELFMCAsmInfo::ARMELFMCAsmInfo() {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ UseMOVT("arm-use-movt",
|
|||
|
||||
ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
|
||||
bool isT)
|
||||
: ARMArchVersion(V4T)
|
||||
: ARMArchVersion(V4)
|
||||
, ARMFPUType(None)
|
||||
, UseNEONForSinglePrecisionFP(UseNEONFP)
|
||||
, IsThumb(isT)
|
||||
|
|
@ -54,6 +54,11 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
|
|||
// Parse features string.
|
||||
CPUString = ParseSubtargetFeatures(FS, CPUString);
|
||||
|
||||
// When no arch is specified either by CPU or by attributes, make the default
|
||||
// ARMv4T.
|
||||
if (CPUString == "generic" && (FS.empty() || FS == "generic"))
|
||||
ARMArchVersion = V4T;
|
||||
|
||||
// Set the boolean corresponding to the current target triple, or the default
|
||||
// if one cannot be determined, to true.
|
||||
unsigned Len = TT.length();
|
||||
|
|
@ -68,25 +73,28 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
|
|||
}
|
||||
if (Idx) {
|
||||
unsigned SubVer = TT[Idx];
|
||||
if (SubVer > '4' && SubVer <= '9') {
|
||||
if (SubVer >= '7') {
|
||||
ARMArchVersion = V7A;
|
||||
} else if (SubVer == '6') {
|
||||
ARMArchVersion = V6;
|
||||
if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
|
||||
ARMArchVersion = V6T2;
|
||||
} else if (SubVer == '5') {
|
||||
ARMArchVersion = V5T;
|
||||
if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e')
|
||||
ARMArchVersion = V5TE;
|
||||
}
|
||||
if (ARMArchVersion >= V6T2)
|
||||
ThumbMode = Thumb2;
|
||||
if (SubVer >= '7' && SubVer <= '9') {
|
||||
ARMArchVersion = V7A;
|
||||
} else if (SubVer == '6') {
|
||||
ARMArchVersion = V6;
|
||||
if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
|
||||
ARMArchVersion = V6T2;
|
||||
} else if (SubVer == '5') {
|
||||
ARMArchVersion = V5T;
|
||||
if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e')
|
||||
ARMArchVersion = V5TE;
|
||||
} else if (SubVer == '4') {
|
||||
if (Len >= Idx+2 && TT[Idx+1] == 't')
|
||||
ARMArchVersion = V4T;
|
||||
else
|
||||
ARMArchVersion = V4;
|
||||
}
|
||||
}
|
||||
|
||||
// Thumb2 implies at least V6T2.
|
||||
if (ARMArchVersion < V6T2 && ThumbMode >= Thumb2)
|
||||
if (ARMArchVersion >= V6T2)
|
||||
ThumbMode = Thumb2;
|
||||
else if (ThumbMode >= Thumb2)
|
||||
ARMArchVersion = V6T2;
|
||||
|
||||
if (Len >= 10) {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class GlobalValue;
|
|||
class ARMSubtarget : public TargetSubtarget {
|
||||
protected:
|
||||
enum ARMArchEnum {
|
||||
V4T, V5T, V5TE, V6, V6T2, V7A
|
||||
V4, V4T, V5T, V5TE, V6, V6T2, V7A
|
||||
};
|
||||
|
||||
enum ARMFPEnum {
|
||||
|
|
@ -38,7 +38,7 @@ protected:
|
|||
Thumb2
|
||||
};
|
||||
|
||||
/// ARMArchVersion - ARM architecture version: V4T (base), V5T, V5TE,
|
||||
/// ARMArchVersion - ARM architecture version: V4, V4T (base), V5T, V5TE,
|
||||
/// V6, V6T2, V7A.
|
||||
ARMArchEnum ARMArchVersion;
|
||||
|
||||
|
|
|
|||
54
lib/Target/ARM/ARMTargetObjectFile.cpp
Normal file
54
lib/Target/ARM/ARMTargetObjectFile.cpp
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
//===-- llvm/Target/ARMTargetObjectFile.cpp - ARM Object Info Impl --------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ARMTargetObjectFile.h"
|
||||
#include "ARMSubtarget.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
using namespace llvm;
|
||||
using namespace dwarf;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ELF Target
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void ARMElfTargetObjectFile::Initialize(MCContext &Ctx,
|
||||
const TargetMachine &TM) {
|
||||
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
|
||||
|
||||
if (TM.getSubtarget<ARMSubtarget>().isAAPCS_ABI()) {
|
||||
StaticCtorSection =
|
||||
getELFSection(".init_array", MCSectionELF::SHT_INIT_ARRAY,
|
||||
MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC,
|
||||
SectionKind::getDataRel());
|
||||
StaticDtorSection =
|
||||
getELFSection(".fini_array", MCSectionELF::SHT_FINI_ARRAY,
|
||||
MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC,
|
||||
SectionKind::getDataRel());
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Mach-O Target
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void ARMMachOTargetObjectFile::Initialize(MCContext &Ctx,
|
||||
const TargetMachine &TM) {
|
||||
TargetLoweringObjectFileMachO::Initialize(Ctx, TM);
|
||||
|
||||
// Exception Handling.
|
||||
LSDASection = getMachOSection("__TEXT", "__gcc_except_tab", 0,
|
||||
SectionKind::getReadOnlyWithRel());
|
||||
}
|
||||
|
||||
unsigned ARMMachOTargetObjectFile::getTTypeEncoding() const {
|
||||
return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4;
|
||||
}
|
||||
|
|
@ -11,29 +11,31 @@
|
|||
#define LLVM_TARGET_ARM_TARGETOBJECTFILE_H
|
||||
|
||||
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF {
|
||||
public:
|
||||
ARMElfTargetObjectFile() : TargetLoweringObjectFileELF() {}
|
||||
class MCContext;
|
||||
class TargetMachine;
|
||||
|
||||
void Initialize(MCContext &Ctx, const TargetMachine &TM) {
|
||||
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
|
||||
class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF {
|
||||
public:
|
||||
ARMElfTargetObjectFile() : TargetLoweringObjectFileELF() {}
|
||||
|
||||
virtual void Initialize(MCContext &Ctx, const TargetMachine &TM);
|
||||
};
|
||||
|
||||
// FIXME: This subclass isn't 100% necessary. It will become obsolete once we
|
||||
// can place all LSDAs into the TEXT section. See
|
||||
// <rdar://problem/6804645>.
|
||||
class ARMMachOTargetObjectFile : public TargetLoweringObjectFileMachO {
|
||||
public:
|
||||
ARMMachOTargetObjectFile() : TargetLoweringObjectFileMachO() {}
|
||||
|
||||
virtual void Initialize(MCContext &Ctx, const TargetMachine &TM);
|
||||
|
||||
virtual unsigned getTTypeEncoding() const;
|
||||
};
|
||||
|
||||
if (TM.getSubtarget<ARMSubtarget>().isAAPCS_ABI()) {
|
||||
StaticCtorSection =
|
||||
getELFSection(".init_array", MCSectionELF::SHT_INIT_ARRAY,
|
||||
MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC,
|
||||
SectionKind::getDataRel());
|
||||
StaticDtorSection =
|
||||
getELFSection(".fini_array", MCSectionELF::SHT_FINI_ARRAY,
|
||||
MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC,
|
||||
SectionKind::getDataRel());
|
||||
}
|
||||
}
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
||||
#include "llvm/MC/MCAsmInfo.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"
|
||||
|
|
@ -848,7 +849,7 @@ GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
|
|||
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
|
||||
<< getFunctionNumber() << '_' << uid << '_' << uid2
|
||||
<< "_set_" << MBB->getNumber();
|
||||
return OutContext.GetOrCreateSymbol(Name.str());
|
||||
return OutContext.GetOrCreateTemporarySymbol(Name.str());
|
||||
}
|
||||
|
||||
MCSymbol *ARMAsmPrinter::
|
||||
|
|
@ -856,7 +857,7 @@ GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
|
|||
SmallString<60> Name;
|
||||
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
|
||||
<< getFunctionNumber() << '_' << uid << '_' << uid2;
|
||||
return OutContext.GetOrCreateSymbol(Name.str());
|
||||
return OutContext.GetOrCreateTemporarySymbol(Name.str());
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) {
|
||||
|
|
@ -1128,17 +1129,40 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
|
|||
OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
|
||||
EmitAlignment(2);
|
||||
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
|
||||
O << *Stubs[i].first << ":\n\t.indirect_symbol ";
|
||||
O << *Stubs[i].second << "\n\t.long\t0\n";
|
||||
// L_foo$stub:
|
||||
OutStreamer.EmitLabel(Stubs[i].first);
|
||||
// .indirect_symbol _foo
|
||||
MCSymbol *MCSym = Stubs[i].second;
|
||||
OutStreamer.EmitSymbolAttribute(MCSym, MCSA_IndirectSymbol);
|
||||
|
||||
if (MCSym->isUndefined())
|
||||
// External to current translation unit.
|
||||
OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
|
||||
else
|
||||
// Internal to current translation unit.
|
||||
OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym, OutContext),
|
||||
4/*size*/, 0/*addrspace*/);
|
||||
}
|
||||
|
||||
Stubs.clear();
|
||||
OutStreamer.AddBlankLine();
|
||||
}
|
||||
|
||||
Stubs = MMIMacho.GetHiddenGVStubList();
|
||||
if (!Stubs.empty()) {
|
||||
OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
|
||||
EmitAlignment(2);
|
||||
for (unsigned i = 0, e = Stubs.size(); i != e; ++i)
|
||||
O << *Stubs[i].first << ":\n\t.long " << *Stubs[i].second << "\n";
|
||||
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
|
||||
// L_foo$stub:
|
||||
OutStreamer.EmitLabel(Stubs[i].first);
|
||||
// .long _foo
|
||||
OutStreamer.EmitValue(MCSymbolRefExpr::Create(Stubs[i].second,
|
||||
OutContext),
|
||||
4/*size*/, 0/*addrspace*/);
|
||||
}
|
||||
|
||||
Stubs.clear();
|
||||
OutStreamer.AddBlankLine();
|
||||
}
|
||||
|
||||
// Funny Darwin hack: This flag tells the linker that no global symbols
|
||||
|
|
@ -1168,7 +1192,7 @@ void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) {
|
|||
// FIXME: MOVE TO SHARED PLACE.
|
||||
unsigned Id = (unsigned)MI->getOperand(2).getImm();
|
||||
const char *Prefix = MAI->getPrivateGlobalPrefix();
|
||||
MCSymbol *Label =OutContext.GetOrCreateSymbol(Twine(Prefix)
|
||||
MCSymbol *Label =OutContext.GetOrCreateTemporarySymbol(Twine(Prefix)
|
||||
+ "PC" + Twine(getFunctionNumber()) + "_" + Twine(Id));
|
||||
OutStreamer.EmitLabel(Label);
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ GetJumpTableSymbol(const MachineOperand &MO) const {
|
|||
#endif
|
||||
|
||||
// Create a symbol for the name.
|
||||
return Ctx.GetOrCreateSymbol(Name.str());
|
||||
return Ctx.GetOrCreateTemporarySymbol(Name.str());
|
||||
}
|
||||
|
||||
MCSymbol *ARMMCInstLower::
|
||||
|
|
@ -90,7 +90,7 @@ GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
|
|||
#endif
|
||||
|
||||
// Create a symbol for the name.
|
||||
return Ctx.GetOrCreateSymbol(Name.str());
|
||||
return Ctx.GetOrCreateTemporarySymbol(Name.str());
|
||||
}
|
||||
|
||||
MCOperand ARMMCInstLower::
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ add_llvm_target(ARMCodeGen
|
|||
ARMRegisterInfo.cpp
|
||||
ARMSubtarget.cpp
|
||||
ARMTargetMachine.cpp
|
||||
ARMTargetObjectFile.cpp
|
||||
NEONMoveFix.cpp
|
||||
NEONPreAllocPass.cpp
|
||||
Thumb1InstrInfo.cpp
|
||||
|
|
|
|||
|
|
@ -33,10 +33,13 @@
|
|||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
extern cl::opt<bool> ReuseFrameIndexVals;
|
||||
|
||||
Thumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii,
|
||||
const ARMSubtarget &sti)
|
||||
: ARMBaseRegisterInfo(tii, sti) {
|
||||
|
|
@ -426,7 +429,7 @@ Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB,
|
|||
|
||||
unsigned
|
||||
Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, int *Value,
|
||||
int SPAdj, FrameIndexValue *Value,
|
||||
RegScavenger *RS) const{
|
||||
unsigned VReg = 0;
|
||||
unsigned i = 0;
|
||||
|
|
@ -638,8 +641,10 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||
} else if (Desc.mayStore()) {
|
||||
VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass);
|
||||
assert (Value && "Frame index virtual allocated, but Value arg is NULL!");
|
||||
*Value = Offset;
|
||||
bool UseRR = false;
|
||||
bool TrackVReg = true;
|
||||
Value->first = FrameReg; // use the frame register as a kind indicator
|
||||
Value->second = Offset;
|
||||
|
||||
if (Opcode == ARM::tSpill) {
|
||||
if (FrameReg == ARM::SP)
|
||||
|
|
@ -648,6 +653,7 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||
else {
|
||||
emitLoadConstPool(MBB, II, dl, VReg, 0, Offset);
|
||||
UseRR = true;
|
||||
TrackVReg = false;
|
||||
}
|
||||
} else
|
||||
emitThumbRegPlusImmediate(MBB, II, VReg, FrameReg, Offset, TII,
|
||||
|
|
@ -658,6 +664,8 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||
MI.addOperand(MachineOperand::CreateReg(FrameReg, false));
|
||||
else // tSTR has an extra register operand.
|
||||
MI.addOperand(MachineOperand::CreateReg(0, false));
|
||||
if (!ReuseFrameIndexVals || !TrackVReg)
|
||||
VReg = 0;
|
||||
} else
|
||||
assert(false && "Unexpected opcode!");
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public:
|
|||
const TargetRegisterClass *RC,
|
||||
unsigned Reg) const;
|
||||
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, int *Value = NULL,
|
||||
int SPAdj, FrameIndexValue *Value = NULL,
|
||||
RegScavenger *RS = NULL) const;
|
||||
|
||||
void emitPrologue(MachineFunction &MF) const;
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
|
|||
continue;
|
||||
}
|
||||
|
||||
bool HasCCOut = true;
|
||||
if (BaseReg == ARM::SP) {
|
||||
// sub sp, sp, #imm7
|
||||
if (DestReg == ARM::SP && (ThisVal < ((1 << 7)-1) * 4)) {
|
||||
|
|
@ -195,6 +196,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
|
|||
NumBytes = 0;
|
||||
} else if (ThisVal < 4096) {
|
||||
Opc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12;
|
||||
HasCCOut = false;
|
||||
NumBytes = 0;
|
||||
} else {
|
||||
// FIXME: Move this to ARMAddressingModes.h?
|
||||
|
|
@ -207,9 +209,12 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
|
|||
}
|
||||
|
||||
// Build the new ADD / SUB.
|
||||
AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
|
||||
.addReg(BaseReg, RegState::Kill)
|
||||
.addImm(ThisVal)));
|
||||
MachineInstrBuilder MIB =
|
||||
AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
|
||||
.addReg(BaseReg, RegState::Kill)
|
||||
.addImm(ThisVal));
|
||||
if (HasCCOut)
|
||||
AddDefaultCC(MIB);
|
||||
|
||||
BaseReg = DestReg;
|
||||
}
|
||||
|
|
@ -328,7 +333,6 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
|
|||
if (Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {
|
||||
Offset += MI.getOperand(FrameRegIdx+1).getImm();
|
||||
|
||||
bool isSP = FrameReg == ARM::SP;
|
||||
unsigned PredReg;
|
||||
if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) {
|
||||
// Turn it into a move.
|
||||
|
|
@ -342,6 +346,9 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool isSP = FrameReg == ARM::SP;
|
||||
bool HasCCOut = Opcode != ARM::t2ADDri12;
|
||||
|
||||
if (Offset < 0) {
|
||||
Offset = -Offset;
|
||||
isSub = true;
|
||||
|
|
@ -354,17 +361,24 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
|
|||
if (ARM_AM::getT2SOImmVal(Offset) != -1) {
|
||||
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
|
||||
MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
|
||||
// Add cc_out operand if the original instruction did not have one.
|
||||
if (!HasCCOut)
|
||||
MI.addOperand(MachineOperand::CreateReg(0, false));
|
||||
Offset = 0;
|
||||
return true;
|
||||
}
|
||||
// Another common case: imm12.
|
||||
if (Offset < 4096) {
|
||||
if (Offset < 4096 &&
|
||||
(!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) {
|
||||
unsigned NewOpc = isSP
|
||||
? (isSub ? ARM::t2SUBrSPi12 : ARM::t2ADDrSPi12)
|
||||
: (isSub ? ARM::t2SUBri12 : ARM::t2ADDri12);
|
||||
MI.setDesc(TII.get(NewOpc));
|
||||
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
|
||||
MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
|
||||
// Remove the cc_out operand.
|
||||
if (HasCCOut)
|
||||
MI.RemoveOperand(MI.getNumOperands()-1);
|
||||
Offset = 0;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -380,6 +394,10 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
|
|||
assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
|
||||
"Bit extraction didn't work?");
|
||||
MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
|
||||
// Add cc_out operand if the original instruction did not have one.
|
||||
if (!HasCCOut)
|
||||
MI.addOperand(MachineOperand::CreateReg(0, false));
|
||||
|
||||
} else {
|
||||
|
||||
// AddrMode4 and AddrMode6 cannot handle any offset.
|
||||
|
|
|
|||
|
|
@ -892,7 +892,7 @@ def : Pat<(brcond (setge GPRC:$RA, 0), bb:$DISP),
|
|||
(COND_BRANCH_I (immBRCond 2), GPRC:$RA, bb:$DISP)>;
|
||||
def : Pat<(brcond (setgt GPRC:$RA, 0), bb:$DISP),
|
||||
(COND_BRANCH_I (immBRCond 3), GPRC:$RA, bb:$DISP)>;
|
||||
def : Pat<(brcond (and GPRC:$RA, 1), bb:$DISP),
|
||||
def : Pat<(brcond (and GPRC:$RA, 1), bb:$DISP),
|
||||
(COND_BRANCH_I (immBRCond 6), GPRC:$RA, bb:$DISP)>;
|
||||
def : Pat<(brcond (setle GPRC:$RA, 0), bb:$DISP),
|
||||
(COND_BRANCH_I (immBRCond 4), GPRC:$RA, bb:$DISP)>;
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
|||
|
||||
unsigned
|
||||
AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, int *Value,
|
||||
int SPAdj, FrameIndexValue *Value,
|
||||
RegScavenger *RS) const {
|
||||
assert(SPAdj == 0 && "Unexpected");
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo {
|
|||
MachineBasicBlock::iterator I) const;
|
||||
|
||||
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, int *Value = NULL,
|
||||
int SPAdj, FrameIndexValue *Value = NULL,
|
||||
RegScavenger *RS = NULL) const;
|
||||
|
||||
//void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ static unsigned findScratchRegister(MachineBasicBlock::iterator II,
|
|||
|
||||
unsigned
|
||||
BlackfinRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, int *Value,
|
||||
int SPAdj, FrameIndexValue *Value,
|
||||
RegScavenger *RS) const {
|
||||
MachineInstr &MI = *II;
|
||||
MachineBasicBlock &MBB = *MI.getParent();
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ namespace llvm {
|
|||
MachineBasicBlock::iterator I) const;
|
||||
|
||||
unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, int *Value = NULL,
|
||||
int SPAdj, FrameIndexValue *Value = NULL,
|
||||
RegScavenger *RS = NULL) const;
|
||||
|
||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ def CellSDKnand:
|
|||
// Shift/rotate intrinsics:
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* FIXME: These have (currently unenforced) type conflicts. */
|
||||
def CellSDKshli:
|
||||
Pat<(int_spu_si_shli (v4i32 VECREG:$rA), uimm7:$val),
|
||||
(SHLIv4i32 VECREG:$rA, uimm7:$val)>;
|
||||
|
|
|
|||
|
|
@ -2370,7 +2370,7 @@ class ROTHInst<dag OOL, dag IOL, list<dag> pattern>:
|
|||
class ROTHVecInst<ValueType vectype>:
|
||||
ROTHInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
|
||||
[(set (vectype VECREG:$rT),
|
||||
(SPUvec_rotl VECREG:$rA, VECREG:$rB))]>;
|
||||
(SPUvec_rotl VECREG:$rA, (v8i16 VECREG:$rB)))]>;
|
||||
|
||||
class ROTHRegInst<RegisterClass rclass>:
|
||||
ROTHInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ def : Pat<(mul (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)),
|
|||
def MPYv4i32:
|
||||
Pat<(mul (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)),
|
||||
(Av4i32
|
||||
(Av4i32 (MPYHv4i32 VECREG:$rA, VECREG:$rB),
|
||||
(MPYHv4i32 VECREG:$rB, VECREG:$rA)),
|
||||
(MPYUv4i32 VECREG:$rA, VECREG:$rB))>;
|
||||
(v4i32 (Av4i32 (v4i32 (MPYHv4i32 VECREG:$rA, VECREG:$rB)),
|
||||
(v4i32 (MPYHv4i32 VECREG:$rB, VECREG:$rA)))),
|
||||
(v4i32 (MPYUv4i32 VECREG:$rA, VECREG:$rB)))>;
|
||||
|
||||
def MPYi32:
|
||||
Pat<(mul R32C:$rA, R32C:$rB),
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue