Update LLVM to r100181.
This commit is contained in:
parent
2f12f10af3
commit
104bd8179f
2
Makefile
2
Makefile
@ -214,7 +214,7 @@ update:
|
||||
$(SVN) $(SVN-UPDATE-OPTIONS) update $(LLVM_SRC_ROOT)
|
||||
@ $(SVN) status $(LLVM_SRC_ROOT) | $(SUB-SVN-DIRS) | xargs $(SVN) $(SVN-UPDATE-OPTIONS) update
|
||||
|
||||
happiness: update all check unittests
|
||||
happiness: update all check-all
|
||||
|
||||
.PHONY: srpm rpm update happiness
|
||||
|
||||
|
@ -110,6 +110,11 @@ do
|
||||
llvm-tv) AC_CONFIG_SUBDIRS([projects/llvm-tv]) ;;
|
||||
safecode) AC_CONFIG_SUBDIRS([projects/safecode]) ;;
|
||||
llvm-kernel) AC_CONFIG_SUBDIRS([projects/llvm-kernel]) ;;
|
||||
llvm-gcc) ;;
|
||||
test-suite) ;;
|
||||
llvm-test) ;;
|
||||
poolalloc) ;;
|
||||
llvm-poolalloc) ;;
|
||||
*)
|
||||
AC_MSG_WARN([Unknown project (${i}) won't be configured automatically])
|
||||
;;
|
||||
|
7
configure
vendored
7
configure
vendored
@ -1999,6 +1999,11 @@ do
|
||||
;;
|
||||
llvm-kernel) subdirs="$subdirs projects/llvm-kernel"
|
||||
;;
|
||||
llvm-gcc) ;;
|
||||
test-suite) ;;
|
||||
llvm-test) ;;
|
||||
poolalloc) ;;
|
||||
llvm-poolalloc) ;;
|
||||
*)
|
||||
{ echo "$as_me:$LINENO: WARNING: Unknown project (${i}) won't be configured automatically" >&5
|
||||
echo "$as_me: WARNING: Unknown project (${i}) won't be configured automatically" >&2;}
|
||||
@ -11151,7 +11156,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 11154 "configure"
|
||||
#line 11159 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
|
@ -1090,8 +1090,8 @@ def FADDS : AForm_2<59, 21,
|
||||
<p>The portion of the instruction definition in bold indicates the pattern used
|
||||
to match the instruction. The DAG operators
|
||||
(like <tt>fmul</tt>/<tt>fadd</tt>) are defined in
|
||||
the <tt>lib/Target/TargetSelectionDAG.td</tt> file. "<tt>F4RC</tt>" is the
|
||||
register class of the input and result values.</p>
|
||||
the <tt>include/llvm/Target/TargetSelectionDAG.td</tt> file. "
|
||||
<tt>F4RC</tt>" is the register class of the input and result values.</p>
|
||||
|
||||
<p>The TableGen DAG instruction selector generator reads the instruction
|
||||
patterns in the <tt>.td</tt> file and automatically builds parts of the
|
||||
@ -2162,7 +2162,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-11 01:22:57 +0100 (Thu, 11 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-25 01:03:04 +0100 (Thu, 25 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -1211,14 +1211,14 @@ and erasing, but does not support iteration.</p>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>SmallPtrSet has all the advantages of SmallSet (and a SmallSet of pointers is
|
||||
transparently implemented with a SmallPtrSet), but also supports iterators. If
|
||||
<p>SmallPtrSet has all the advantages of <tt>SmallSet</tt> (and a <tt>SmallSet</tt> of pointers is
|
||||
transparently implemented with a <tt>SmallPtrSet</tt>), but also supports iterators. If
|
||||
more than 'N' insertions are performed, a single quadratically
|
||||
probed hash table is allocated and grows as needed, providing extremely
|
||||
efficient access (constant time insertion/deleting/queries with low constant
|
||||
factors) and is very stingy with malloc traffic.</p>
|
||||
|
||||
<p>Note that, unlike std::set, the iterators of SmallPtrSet are invalidated
|
||||
<p>Note that, unlike <tt>std::set</tt>, the iterators of <tt>SmallPtrSet</tt> are invalidated
|
||||
whenever an insertion occurs. Also, the values visited by the iterators are not
|
||||
visited in sorted order.</p>
|
||||
|
||||
@ -1843,6 +1843,21 @@ void printNextInstruction(Instruction* inst) {
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>Unfortunately, these implicit conversions come at a cost; they prevent
|
||||
these iterators from conforming to standard iterator conventions, and thus
|
||||
from being usable with standard algorithms and containers. For example, they
|
||||
prevent the following code, where <tt>B</tt> is a <tt>BasicBlock</tt>,
|
||||
from compiling:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
llvm::SmallVector<llvm::Instruction *, 16>(B->begin(), B->end());
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>Because of this, these implicit conversions may be removed some day,
|
||||
and <tt>operator*</tt> changed to return a pointer instead of a reference.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!--_______________________________________________________________________-->
|
||||
@ -1962,7 +1977,11 @@ for (Value::use_iterator i = F->use_begin(), e = F->use_end(); i != e; ++i
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>Alternately, it's common to have an instance of the <a
|
||||
<p>Note that dereferencing a <tt>Value::use_iterator</tt> is not a very cheap
|
||||
operation. Instead of performing <tt>*i</tt> above several times, consider
|
||||
doing it only once in the loop body and reusing its result.</p>
|
||||
|
||||
<p>Alternatively, it's common to have an instance of the <a
|
||||
href="/doxygen/classllvm_1_1User.html">User Class</a> and need to know what
|
||||
<tt>Value</tt>s are used by it. The list of all <tt>Value</tt>s used by a
|
||||
<tt>User</tt> is known as a <i>use-def</i> chain. Instances of class
|
||||
@ -1981,10 +2000,13 @@ for (User::op_iterator i = pi->op_begin(), e = pi->op_end(); i != e; ++i)
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
def-use chains ("finding all users of"): Value::use_begin/use_end
|
||||
use-def chains ("finding all values used"): User::op_begin/op_end [op=operand]
|
||||
-->
|
||||
<p>Declaring objects as <tt>const</tt> is an important tool of enforcing
|
||||
mutation free algorithms (such as analyses, etc.). For this purpose above
|
||||
iterators come in constant flavors as <tt>Value::const_use_iterator</tt>
|
||||
and <tt>Value::const_op_iterator</tt>. They automatically arise when
|
||||
calling <tt>use/op_begin()</tt> on <tt>const Value*</tt>s or
|
||||
<tt>const User*</tt>s respectively. Upon dereferencing, they return
|
||||
<tt>const Use*</tt>s. Otherwise the above patterns remain unchanged.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -3058,7 +3080,7 @@ the <tt>lib/VMCore</tt> directory.</p>
|
||||
<dt><tt><a name="FunctionType">FunctionType</a></tt></dt>
|
||||
<dd>Subclass of DerivedTypes for function types.
|
||||
<ul>
|
||||
<li><tt>bool isVarArg() const</tt>: Returns true if its a vararg
|
||||
<li><tt>bool isVarArg() const</tt>: Returns true if it's a vararg
|
||||
function</li>
|
||||
<li><tt> const Type * getReturnType() const</tt>: Returns the
|
||||
return type of the function.</li>
|
||||
@ -3276,7 +3298,7 @@ simplifies the representation and makes it easier to manipulate.</p>
|
||||
<ul>
|
||||
<li><tt>Value::use_iterator</tt> - Typedef for iterator over the
|
||||
use-list<br>
|
||||
<tt>Value::use_const_iterator</tt> - Typedef for const_iterator over
|
||||
<tt>Value::const_use_iterator</tt> - Typedef for const_iterator over
|
||||
the use-list<br>
|
||||
<tt>unsigned use_size()</tt> - Returns the number of users of the
|
||||
value.<br>
|
||||
@ -3921,7 +3943,7 @@ arguments. An argument has a pointer to the parent Function.</p>
|
||||
<a href="mailto:dhurjati@cs.uiuc.edu">Dinakar Dhurjati</a> and
|
||||
<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-26 00:51:27 +0100 (Fri, 26 Feb 2010) $
|
||||
Last modified: $Date: 2010-04-02 02:08:26 +0200 (Fri, 02 Apr 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -127,8 +127,21 @@ development. Here we include updates on these subprojects.
|
||||
<p>In the LLVM 2.7 time-frame, the Clang team has made many improvements:</p>
|
||||
|
||||
<ul>
|
||||
<li>...</li>
|
||||
include a link to cxx_compatibility.html
|
||||
<li>FIXME: C++! Include a link to cxx_compatibility.html</li>
|
||||
|
||||
<li>FIXME: Static Analyzer improvements?</li>
|
||||
|
||||
<li>CIndex API and Python bindings: Clang now includes a C API as part of the
|
||||
CIndex library. Although we make make some changes to the API in the future, it
|
||||
is intended to be stable and has been designed for use by external projects. See
|
||||
the Clang
|
||||
doxygen <a href="http://clang.llvm.org/doxygen/group__CINDEX.html">CIndex</a>
|
||||
documentation for more details. The CIndex API also includings an preliminary
|
||||
set of Python bindings.</li>
|
||||
|
||||
<li>ARM Support: Clang now has ABI support for both the Darwin and Linux ARM
|
||||
ABIs. Coupled with many improvements to the LLVM ARM backend, Clang is now
|
||||
suitable for use as a a beta quality ARM compiler.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -162,13 +175,23 @@ implementation of the CLI) using LLVM for static and just-in-time
|
||||
compilation.</p>
|
||||
|
||||
<p>
|
||||
VMKit version ?? builds with LLVM 2.7 and you can find it on its
|
||||
<a href="http://vmkit.llvm.org/releases/">web page</a>. The release includes
|
||||
bug fixes, cleanup and new features. The major changes are:</p>
|
||||
With the release of LLVM 2.7, VMKit has shifted to a great framework for writing
|
||||
virtual machines. VMKit now offers precise and efficient garbage collection with
|
||||
multi-threading support, thanks to the MMTk memory management toolkit, as well
|
||||
as just in time and ahead of time compilation with LLVM. The major changes in
|
||||
VMKit 0.27 are:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>...</li>
|
||||
<li>Garbage collection: VMKit now uses the MMTk toolkit for garbage collectors.
|
||||
The first collector to be ported is the MarkSweep collector, which is precise,
|
||||
and drastically improves the performance of VMKit.</li>
|
||||
<li>Line number information in the JVM: by using the debug metadata of LLVM, the
|
||||
JVM now supports precise line number information, useful when printing a stack
|
||||
trace.</li>
|
||||
<li>Interface calls in the JVM: we implemented a variant of the Interface Method
|
||||
Table technique for interface calls in the JVM.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
@ -391,6 +414,27 @@ code.-->
|
||||
</div>
|
||||
|
||||
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_subsection">
|
||||
<a name="tce">TTA-based Codesign Environment (TCE)</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
<p>
|
||||
<a href="http://tce.cs.tut.fi/">TCE</a> is a toolset for designing
|
||||
application-specific processors (ASP) based on the Transport triggered
|
||||
architecture (TTA). The toolset provides a complete co-design flow from C/C++
|
||||
programs down to synthesizable VHDL and parallel program binaries. Processor
|
||||
customization points include the register files, function units, supported
|
||||
operations, and the interconnection network.</p>
|
||||
|
||||
<p>TCE uses llvm-gcc/Clang and LLVM for C/C++ language support, target
|
||||
independent optimizations and also for parts of code generation. It generates
|
||||
new LLVM-based code generators "on the fly" for the designed TTA processors and
|
||||
loads them in to the compiler backend as runtime libraries to avoid per-target
|
||||
recompilation of larger parts of the compiler chain.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<div class="doc_section">
|
||||
@ -439,7 +483,7 @@ New llvm/Support/Regex.h API. FileCheck now does regex's
|
||||
Many subtle pointer invalidation bugs in Callgraph have been fixed and it now uses asserting value handles.
|
||||
MC Disassembler (with blog post), MCInstPrinter. Many X86 backend and AsmPrinter simplifications
|
||||
Various tools like llc and opt now read either .ll or .bc files as input.
|
||||
Malloc and free instructions got removed.
|
||||
Malloc and free instructions got removed, along with LowerAllocations pass.
|
||||
compiler-rt support for ARM.
|
||||
completely llvm-gcc NEON support.
|
||||
Can transcode from GAS to intel syntax with "llvm-mc foo.s -output-asm-variant=1"
|
||||
@ -456,8 +500,12 @@ x86 sibcall optimization
|
||||
New LSR with full strength reduction mode
|
||||
The most awesome sext / zext optimization pass. ?
|
||||
|
||||
The ARM backend now has good support for ARMv4 backend (tested on StrongARM
|
||||
hardware), previously only supported ARMv4T and newer.
|
||||
|
||||
|
||||
|
||||
Defaults to RTTI off, packagers should build with make REQUIRE_RTTI=1.
|
||||
CondProp pass removed (functionality merged into jump threading).
|
||||
AndersAA got removed (from 2.7 or mainline?)
|
||||
PredSimplify, LoopVR, GVNPRE got removed.
|
||||
@ -978,20 +1026,6 @@ ignored</a>.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="ocaml-bindings">Known problems with the O'Caml bindings</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>The <tt>Llvm.Linkage</tt> module is broken, and has incorrect values. Only
|
||||
<tt>Llvm.Linkage.External</tt>, <tt>Llvm.Linkage.Available_externally</tt>, and
|
||||
<tt>Llvm.Linkage.Link_once</tt> will be correct. If you need any of the other linkage
|
||||
modes, you'll have to write an external C library in order to expose the
|
||||
functionality. This has been fixed in the trunk.</p>
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<div class="doc_section">
|
||||
<a name="additionalinfo">Additional Information</a>
|
||||
@ -1024,7 +1058,7 @@ lists</a>.</p>
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-03-19 04:18:05 +0100 (Fri, 19 Mar 2010) $
|
||||
Last modified: $Date: 2010-04-01 03:53:24 +0200 (Thu, 01 Apr 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -289,26 +289,25 @@ height="369">
|
||||
0x1000.)</p>
|
||||
|
||||
<p>The fields of debug descriptors used internally by LLVM
|
||||
are restricted to only the simple data types <tt>int</tt>, <tt>uint</tt>,
|
||||
<tt>bool</tt>, <tt>float</tt>, <tt>double</tt>, <tt>mdstring</tt> and
|
||||
<tt>mdnode</tt>. </p>
|
||||
are restricted to only the simple data types <tt>i32</tt>, <tt>i1</tt>,
|
||||
<tt>float</tt>, <tt>double</tt>, <tt>mdstring</tt> and <tt>mdnode</tt>. </p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
!1 = metadata !{
|
||||
uint, ;; A tag
|
||||
i32, ;; A tag
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p><a name="LLVMDebugVersion">The first field of a descriptor is always an
|
||||
<tt>uint</tt> containing a tag value identifying the content of the
|
||||
<tt>i32</tt> containing a tag value identifying the content of the
|
||||
descriptor. The remaining fields are specific to the descriptor. The values
|
||||
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 = 8 << 16 or 0x80000 or
|
||||
with the current debug version (LLVMDebugVersion = 8 << 16 or 0x80000 or
|
||||
524288.)</a></p>
|
||||
|
||||
<p>The details of the various descriptors follow.</p>
|
||||
@ -829,8 +828,8 @@ DW_TAG_return_variable = 258
|
||||
rules.</p>
|
||||
|
||||
<p>In order to handle this, the LLVM debug format uses the metadata attached to
|
||||
llvm instructions to encode line nuber and scoping information. Consider the
|
||||
following C fragment, for example:</p>
|
||||
llvm instructions to encode line number and scoping information. Consider
|
||||
the following C fragment, for example:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
@ -1069,6 +1068,18 @@ int main(int argc, char *argv[]) {
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>llvm::Instruction provides easy access to metadata attached with an
|
||||
instruction. One can extract line number information encoded in LLVM IR
|
||||
using <tt>Instruction::getMetadata()</tt> and
|
||||
<tt>DILocation::getLineNumber()</tt>.
|
||||
<pre>
|
||||
if (MDNode *N = I->getMetadata("dbg")) { // Here I is an LLVM instruction
|
||||
DILocation Loc(N); // DILocation is in DebugInfo.h
|
||||
unsigned Line = Loc.getLineNumber();
|
||||
StringRef File = Loc.getFilename();
|
||||
StringRef Dir = Loc.getDirectory();
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
@ -1762,7 +1773,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-03-17 16:01:50 +0100 (Wed, 17 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-31 09:50:17 +0200 (Wed, 31 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -768,9 +768,6 @@ patterns:</p>
|
||||
<dd>an implicitly defined physical register. This tells the dag instruction
|
||||
selection emitter the input pattern's extra definitions matches implicit
|
||||
physical register definitions.</dd>
|
||||
<dt><tt>(parallel (a), (b))</tt></dt>
|
||||
<dd>a list of dags specifying parallel operations which map to the same
|
||||
instruction.</dd>
|
||||
|
||||
</div>
|
||||
|
||||
@ -797,7 +794,7 @@ This should highlight the APIs in <tt>TableGen/Record.h</tt>.</p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-02-28 00:47:46 +0100 (Sun, 28 Feb 2010) $
|
||||
Last modified: $Date: 2010-03-27 03:53:27 +0100 (Sat, 27 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -821,7 +821,7 @@ ocaml_lib ~extern:true "llvm_executionengine";;
|
||||
ocaml_lib ~extern:true "llvm_target";;
|
||||
ocaml_lib ~extern:true "llvm_scalar_opts";;
|
||||
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"; A"-cclib"; A"-rdynamic"]);;
|
||||
dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
|
||||
</pre>
|
||||
</dd>
|
||||
@ -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-03-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-22 00:15:13 +0100 (Mon, 22 Mar 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -999,7 +999,7 @@ ocaml_lib ~extern:true "llvm_executionengine";;
|
||||
ocaml_lib ~extern:true "llvm_target";;
|
||||
ocaml_lib ~extern:true "llvm_scalar_opts";;
|
||||
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"; A"-cclib"; A"-rdynamic"]);;
|
||||
dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
|
||||
</pre>
|
||||
</dd>
|
||||
@ -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-08 20:32:18 +0100 (Mon, 08 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-22 00:15:13 +0100 (Mon, 22 Mar 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -6,5 +6,5 @@ ocaml_lib ~extern:true "llvm_executionengine";;
|
||||
ocaml_lib ~extern:true "llvm_target";;
|
||||
ocaml_lib ~extern:true "llvm_scalar_opts";;
|
||||
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"; A"-cclib"; A"-rdynamic"]);;
|
||||
dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
|
||||
|
@ -6,5 +6,5 @@ ocaml_lib ~extern:true "llvm_executionengine";;
|
||||
ocaml_lib ~extern:true "llvm_target";;
|
||||
ocaml_lib ~extern:true "llvm_scalar_opts";;
|
||||
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"; A"-cclib"; A"-rdynamic"]);;
|
||||
dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
|
||||
|
@ -124,7 +124,7 @@ namespace llvm {
|
||||
}
|
||||
|
||||
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
|
||||
static PointerUnion getFromOpaqueValue(void *VP) {
|
||||
static inline PointerUnion getFromOpaqueValue(void *VP) {
|
||||
PointerUnion V;
|
||||
V.Val = ValTy::getFromOpaqueValue(VP);
|
||||
return V;
|
||||
@ -227,7 +227,7 @@ namespace llvm {
|
||||
}
|
||||
|
||||
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
|
||||
static PointerUnion3 getFromOpaqueValue(void *VP) {
|
||||
static inline PointerUnion3 getFromOpaqueValue(void *VP) {
|
||||
PointerUnion3 V;
|
||||
V.Val = ValTy::getFromOpaqueValue(VP);
|
||||
return V;
|
||||
@ -338,7 +338,7 @@ namespace llvm {
|
||||
}
|
||||
|
||||
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
|
||||
static PointerUnion4 getFromOpaqueValue(void *VP) {
|
||||
static inline PointerUnion4 getFromOpaqueValue(void *VP) {
|
||||
PointerUnion4 V;
|
||||
V.Val = ValTy::getFromOpaqueValue(VP);
|
||||
return V;
|
||||
|
@ -239,11 +239,20 @@ class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
|
||||
/// starting with "Dest", constructing elements into it as needed.
|
||||
template<typename It1, typename It2>
|
||||
static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
|
||||
// Use memcpy for PODs: std::uninitialized_copy optimizes to memmove, memcpy
|
||||
// is better.
|
||||
memcpy(&*Dest, &*I, (E-I)*sizeof(T));
|
||||
// Arbitrary iterator types; just use the basic implementation.
|
||||
std::uninitialized_copy(I, E, Dest);
|
||||
}
|
||||
|
||||
|
||||
/// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
|
||||
/// starting with "Dest", constructing elements into it as needed.
|
||||
template<typename T1, typename T2>
|
||||
static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) {
|
||||
// Use memcpy for PODs iterated by pointers (which includes SmallVector
|
||||
// iterators): std::uninitialized_copy optimizes to memmove, but we can
|
||||
// use memcpy here.
|
||||
memcpy(Dest, I, (E-I)*sizeof(T));
|
||||
}
|
||||
|
||||
/// grow - double the size of the allocated memory, guaranteeing space for at
|
||||
/// least one more element or MinSize if specified.
|
||||
void grow(size_t MinSize = 0) {
|
||||
@ -501,10 +510,13 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
|
||||
|
||||
// Replace the overwritten part.
|
||||
std::copy(From, From+NumOverwritten, I);
|
||||
for (; NumOverwritten > 0; --NumOverwritten) {
|
||||
*I = *From;
|
||||
++I; ++From;
|
||||
}
|
||||
|
||||
// Insert the non-overwritten middle part.
|
||||
this->uninitialized_copy(From+NumOverwritten, To, OldEnd);
|
||||
this->uninitialized_copy(From, To, OldEnd);
|
||||
return I;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "llvm/System/Atomic.h"
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
|
||||
class Statistic {
|
||||
public:
|
||||
@ -113,6 +114,15 @@ class Statistic {
|
||||
#define STATISTIC(VARNAME, DESC) \
|
||||
static llvm::Statistic VARNAME = { DEBUG_TYPE, DESC, 0, 0 }
|
||||
|
||||
/// \brief Enable the collection and printing of statistics.
|
||||
void EnableStatistics();
|
||||
|
||||
/// \brief Print statistics to the file returned by CreateInfoOutputFile().
|
||||
void PrintStatistics();
|
||||
|
||||
/// \brief Print statistics to the given output stream.
|
||||
void PrintStatistics(raw_ostream &OS);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -216,6 +216,14 @@ class StringMapEntry : public StringMapEntryBase {
|
||||
static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) {
|
||||
return GetStringMapEntryFromValue(const_cast<ValueTy&>(V));
|
||||
}
|
||||
|
||||
/// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
|
||||
/// into a StringMapEntry, return the StringMapEntry itself.
|
||||
static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
|
||||
char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
|
||||
return *reinterpret_cast<StringMapEntry*>(Ptr);
|
||||
}
|
||||
|
||||
|
||||
/// Destroy - Destroy this StringMapEntry, releasing memory back to the
|
||||
/// specified allocator.
|
||||
|
@ -395,8 +395,21 @@ namespace llvm {
|
||||
}
|
||||
unsigned isArtificial() const { return getUnsignedField(14); }
|
||||
|
||||
StringRef getFilename() const { return getCompileUnit().getFilename();}
|
||||
StringRef getDirectory() const { return getCompileUnit().getDirectory();}
|
||||
StringRef getFilename() const {
|
||||
if (getVersion() == llvm::LLVMDebugVersion7)
|
||||
return getCompileUnit().getFilename();
|
||||
|
||||
DIFile F = getFieldAs<DIFile>(6);
|
||||
return F.getFilename();
|
||||
}
|
||||
|
||||
StringRef getDirectory() const {
|
||||
if (getVersion() == llvm::LLVMDebugVersion7)
|
||||
return getCompileUnit().getFilename();
|
||||
|
||||
DIFile F = getFieldAs<DIFile>(6);
|
||||
return F.getDirectory();
|
||||
}
|
||||
|
||||
/// Verify - Verify that a subprogram descriptor is well formed.
|
||||
bool Verify() const;
|
||||
|
@ -116,12 +116,12 @@ class DomTreeNodeBase {
|
||||
return true;
|
||||
|
||||
SmallPtrSet<NodeT *, 4> OtherChildren;
|
||||
for(iterator I = Other->begin(), E = Other->end(); I != E; ++I) {
|
||||
for (iterator I = Other->begin(), E = Other->end(); I != E; ++I) {
|
||||
NodeT *Nd = (*I)->getBlock();
|
||||
OtherChildren.insert(Nd);
|
||||
}
|
||||
|
||||
for(iterator I = begin(), E = end(); I != E; ++I) {
|
||||
for (iterator I = begin(), E = end(); I != E; ++I) {
|
||||
NodeT *N = (*I)->getBlock();
|
||||
if (OtherChildren.count(N) == 0)
|
||||
return true;
|
||||
@ -240,8 +240,9 @@ class DominatorTreeBase : public DominatorBase<NodeT> {
|
||||
template<class N, class GraphT>
|
||||
void Split(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType* NewBB) {
|
||||
assert(std::distance(GraphT::child_begin(NewBB), GraphT::child_end(NewBB)) == 1
|
||||
&& "NewBB should have a single successor!");
|
||||
assert(std::distance(GraphT::child_begin(NewBB),
|
||||
GraphT::child_end(NewBB)) == 1 &&
|
||||
"NewBB should have a single successor!");
|
||||
typename GraphT::NodeType* NewBBSucc = *GraphT::child_begin(NewBB);
|
||||
|
||||
std::vector<typename GraphT::NodeType*> PredBlocks;
|
||||
@ -374,8 +375,8 @@ class DominatorTreeBase : public DominatorBase<NodeT> {
|
||||
/// isReachableFromEntry - Return true if A is dominated by the entry
|
||||
/// block of the function containing it.
|
||||
bool isReachableFromEntry(NodeT* A) {
|
||||
assert (!this->isPostDominator()
|
||||
&& "This is not implemented for post dominators");
|
||||
assert(!this->isPostDominator() &&
|
||||
"This is not implemented for post dominators");
|
||||
return dominates(&A->getParent()->front(), A);
|
||||
}
|
||||
|
||||
@ -393,8 +394,9 @@ class DominatorTreeBase : public DominatorBase<NodeT> {
|
||||
// Compare the result of the tree walk and the dfs numbers, if expensive
|
||||
// checks are enabled.
|
||||
#ifdef XDEBUG
|
||||
assert(!DFSInfoValid
|
||||
|| (dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A)));
|
||||
assert((!DFSInfoValid ||
|
||||
(dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) &&
|
||||
"Tree walk disagrees with dfs numbers!");
|
||||
#endif
|
||||
|
||||
if (DFSInfoValid)
|
||||
@ -430,16 +432,16 @@ class DominatorTreeBase : public DominatorBase<NodeT> {
|
||||
/// findNearestCommonDominator - Find nearest common dominator basic block
|
||||
/// for basic block A and B. If there is no such block then return NULL.
|
||||
NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) {
|
||||
assert(A->getParent() == B->getParent() &&
|
||||
"Two blocks are not in same function");
|
||||
|
||||
assert (!this->isPostDominator()
|
||||
&& "This is not implemented for post dominators");
|
||||
assert (A->getParent() == B->getParent()
|
||||
&& "Two blocks are not in same function");
|
||||
|
||||
// If either A or B is a entry block then it is nearest common dominator.
|
||||
NodeT &Entry = A->getParent()->front();
|
||||
if (A == &Entry || B == &Entry)
|
||||
return &Entry;
|
||||
// If either A or B is a entry block then it is nearest common dominator
|
||||
// (for forward-dominators).
|
||||
if (!this->isPostDominator()) {
|
||||
NodeT &Entry = A->getParent()->front();
|
||||
if (A == &Entry || B == &Entry)
|
||||
return &Entry;
|
||||
}
|
||||
|
||||
// If B dominates A then B is nearest common dominator.
|
||||
if (dominates(B, A))
|
||||
@ -463,7 +465,7 @@ class DominatorTreeBase : public DominatorBase<NodeT> {
|
||||
|
||||
// Walk NodeB immediate dominators chain and find common dominator node.
|
||||
DomTreeNodeBase<NodeT> *IDomB = NodeB->getIDom();
|
||||
while(IDomB) {
|
||||
while (IDomB) {
|
||||
if (NodeADoms.count(IDomB) != 0)
|
||||
return IDomB->getBlock();
|
||||
|
||||
@ -508,8 +510,8 @@ class DominatorTreeBase : public DominatorBase<NodeT> {
|
||||
/// children list. Deletes dominator node associated with basic block BB.
|
||||
void eraseNode(NodeT *BB) {
|
||||
DomTreeNodeBase<NodeT> *Node = getNode(BB);
|
||||
assert (Node && "Removing node that isn't in dominator tree.");
|
||||
assert (Node->getChildren().empty() && "Node is not a leaf node.");
|
||||
assert(Node && "Removing node that isn't in dominator tree.");
|
||||
assert(Node->getChildren().empty() && "Node is not a leaf node.");
|
||||
|
||||
// Remove node from immediate dominator's children list.
|
||||
DomTreeNodeBase<NodeT> *IDom = Node->getIDom();
|
||||
@ -952,7 +954,7 @@ class DominanceFrontierBase : public FunctionPass {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!tmpSet.empty())
|
||||
if (!tmpSet.empty())
|
||||
// There are nodes that are in DS2 but not in DS1.
|
||||
return true;
|
||||
|
||||
|
@ -47,7 +47,6 @@ namespace llvm {
|
||||
class MCSection;
|
||||
class MCStreamer;
|
||||
class MCSymbol;
|
||||
class MDNode;
|
||||
class DwarfWriter;
|
||||
class Mangler;
|
||||
class MCAsmInfo;
|
||||
@ -138,9 +137,6 @@ namespace llvm {
|
||||
mutable unsigned Counter;
|
||||
mutable unsigned SetCounter;
|
||||
|
||||
// Private state for processDebugLoc()
|
||||
mutable const MDNode *PrevDLT;
|
||||
|
||||
protected:
|
||||
explicit AsmPrinter(formatted_raw_ostream &o, TargetMachine &TM,
|
||||
MCStreamer &Streamer);
|
||||
|
@ -83,19 +83,11 @@ class DwarfWriter : public ImmutablePass {
|
||||
///
|
||||
void EndFunction(const MachineFunction *MF);
|
||||
|
||||
/// 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);
|
||||
|
||||
/// getRecordSourceLineCount - Count source lines.
|
||||
unsigned getRecordSourceLineCount();
|
||||
|
||||
/// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should
|
||||
/// be emitted.
|
||||
bool ShouldEmitDwarfDebug() const;
|
||||
|
||||
void BeginScope(const MachineInstr *MI, MCSymbol *Label);
|
||||
void BeginScope(const MachineInstr *MI);
|
||||
void EndScope(const MachineInstr *MI);
|
||||
};
|
||||
|
||||
|
@ -67,7 +67,7 @@ namespace llvm {
|
||||
} cr;
|
||||
|
||||
public:
|
||||
|
||||
typedef SpecificBumpPtrAllocator<VNInfo> Allocator;
|
||||
typedef SmallVector<SlotIndex, 4> KillSet;
|
||||
|
||||
/// The ID number of this value.
|
||||
@ -330,12 +330,7 @@ namespace llvm {
|
||||
}
|
||||
|
||||
void clear() {
|
||||
while (!valnos.empty()) {
|
||||
VNInfo *VNI = valnos.back();
|
||||
valnos.pop_back();
|
||||
VNI->~VNInfo();
|
||||
}
|
||||
|
||||
valnos.clear();
|
||||
ranges.clear();
|
||||
}
|
||||
|
||||
@ -370,10 +365,8 @@ namespace llvm {
|
||||
/// getNextValue - Create a new value number and return it. MIIdx specifies
|
||||
/// the instruction that defines the value number.
|
||||
VNInfo *getNextValue(SlotIndex def, MachineInstr *CopyMI,
|
||||
bool isDefAccurate, BumpPtrAllocator &VNInfoAllocator){
|
||||
VNInfo *VNI =
|
||||
static_cast<VNInfo*>(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo),
|
||||
alignof<VNInfo>()));
|
||||
bool isDefAccurate, VNInfo::Allocator &VNInfoAllocator) {
|
||||
VNInfo *VNI = VNInfoAllocator.Allocate();
|
||||
new (VNI) VNInfo((unsigned)valnos.size(), def, CopyMI);
|
||||
VNI->setIsDefAccurate(isDefAccurate);
|
||||
valnos.push_back(VNI);
|
||||
@ -383,11 +376,8 @@ namespace llvm {
|
||||
/// Create a copy of the given value. The new value will be identical except
|
||||
/// for the Value number.
|
||||
VNInfo *createValueCopy(const VNInfo *orig,
|
||||
BumpPtrAllocator &VNInfoAllocator) {
|
||||
VNInfo *VNI =
|
||||
static_cast<VNInfo*>(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo),
|
||||
alignof<VNInfo>()));
|
||||
|
||||
VNInfo::Allocator &VNInfoAllocator) {
|
||||
VNInfo *VNI = VNInfoAllocator.Allocate();
|
||||
new (VNI) VNInfo((unsigned)valnos.size(), *orig);
|
||||
valnos.push_back(VNI);
|
||||
return VNI;
|
||||
@ -427,14 +417,14 @@ namespace llvm {
|
||||
/// VNInfoAllocator since it will create a new val#.
|
||||
void MergeInClobberRanges(LiveIntervals &li_,
|
||||
const LiveInterval &Clobbers,
|
||||
BumpPtrAllocator &VNInfoAllocator);
|
||||
VNInfo::Allocator &VNInfoAllocator);
|
||||
|
||||
/// MergeInClobberRange - Same as MergeInClobberRanges except it merge in a
|
||||
/// single LiveRange only.
|
||||
void MergeInClobberRange(LiveIntervals &li_,
|
||||
SlotIndex Start,
|
||||
SlotIndex End,
|
||||
BumpPtrAllocator &VNInfoAllocator);
|
||||
VNInfo::Allocator &VNInfoAllocator);
|
||||
|
||||
/// MergeValueInAsValue - Merge all of the live ranges of a specific val#
|
||||
/// in RHS into this live interval as the specified value number.
|
||||
@ -454,7 +444,7 @@ namespace llvm {
|
||||
/// Copy - Copy the specified live interval. This copies all the fields
|
||||
/// except for the register of the interval.
|
||||
void Copy(const LiveInterval &RHS, MachineRegisterInfo *MRI,
|
||||
BumpPtrAllocator &VNInfoAllocator);
|
||||
VNInfo::Allocator &VNInfoAllocator);
|
||||
|
||||
bool empty() const { return ranges.empty(); }
|
||||
|
||||
|
@ -55,7 +55,7 @@ namespace llvm {
|
||||
|
||||
/// Special pool allocator for VNInfo's (LiveInterval val#).
|
||||
///
|
||||
BumpPtrAllocator VNInfoAllocator;
|
||||
VNInfo::Allocator VNInfoAllocator;
|
||||
|
||||
typedef DenseMap<unsigned, LiveInterval*> Reg2IntervalMap;
|
||||
Reg2IntervalMap r2iMap_;
|
||||
@ -221,7 +221,7 @@ namespace llvm {
|
||||
indexes_->renumberIndexes();
|
||||
}
|
||||
|
||||
BumpPtrAllocator& getVNInfoAllocator() { return VNInfoAllocator; }
|
||||
VNInfo::Allocator& getVNInfoAllocator() { return VNInfoAllocator; }
|
||||
|
||||
/// getVNInfoSourceReg - Helper function that parses the specified VNInfo
|
||||
/// copy field and returns the source register that defines it.
|
||||
|
@ -27,7 +27,7 @@ namespace llvm {
|
||||
class LiveStacks : public MachineFunctionPass {
|
||||
/// Special pool allocator for VNInfo's (LiveInterval val#).
|
||||
///
|
||||
BumpPtrAllocator VNInfoAllocator;
|
||||
VNInfo::Allocator VNInfoAllocator;
|
||||
|
||||
/// S2IMap - Stack slot indices to live interval mapping.
|
||||
///
|
||||
@ -91,7 +91,7 @@ namespace llvm {
|
||||
return I->second;
|
||||
}
|
||||
|
||||
BumpPtrAllocator& getVNInfoAllocator() { return VNInfoAllocator; }
|
||||
VNInfo::Allocator& getVNInfoAllocator() { return VNInfoAllocator; }
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual void releaseMemory();
|
||||
|
@ -285,6 +285,11 @@ class MachineOperand {
|
||||
IsEarlyClobber = Val;
|
||||
}
|
||||
|
||||
void setIsDebug(bool Val = true) {
|
||||
assert(isReg() && IsDef && "Wrong MachineOperand accessor");
|
||||
IsDebug = Val;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Accessors for various operand types.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -169,6 +169,8 @@ namespace RTLIB {
|
||||
FPTOSINT_F32_I32,
|
||||
FPTOSINT_F32_I64,
|
||||
FPTOSINT_F32_I128,
|
||||
FPTOSINT_F64_I8,
|
||||
FPTOSINT_F64_I16,
|
||||
FPTOSINT_F64_I32,
|
||||
FPTOSINT_F64_I64,
|
||||
FPTOSINT_F64_I128,
|
||||
@ -183,6 +185,8 @@ namespace RTLIB {
|
||||
FPTOUINT_F32_I32,
|
||||
FPTOUINT_F32_I64,
|
||||
FPTOUINT_F32_I128,
|
||||
FPTOUINT_F64_I8,
|
||||
FPTOUINT_F64_I16,
|
||||
FPTOUINT_F64_I32,
|
||||
FPTOUINT_F64_I64,
|
||||
FPTOUINT_F64_I128,
|
||||
|
@ -34,6 +34,7 @@ class FunctionLoweringInfo;
|
||||
class MachineConstantPoolValue;
|
||||
class MachineFunction;
|
||||
class MachineModuleInfo;
|
||||
class MDNode;
|
||||
class SDNodeOrdering;
|
||||
class SDDbgValue;
|
||||
class TargetLowering;
|
||||
@ -60,42 +61,40 @@ template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> {
|
||||
|
||||
/// SDDbgInfo - Keeps track of dbg_value information through SDISel. We do
|
||||
/// not build SDNodes for these so as not to perturb the generated code;
|
||||
/// instead the info is kept off to the side in this structure. SDNodes may
|
||||
/// have an associated dbg_value entry in DbgValMap. Debug info that is not
|
||||
/// associated with any SDNode is held in DbgConstMap. It is possible for
|
||||
/// optimizations to change a variable to a constant, in which case the
|
||||
/// corresponding debug info is moved from the variable to the constant table
|
||||
/// (NYI).
|
||||
/// instead the info is kept off to the side in this structure. Each SDNode may
|
||||
/// have one or more associated dbg_value entries. This information is kept in
|
||||
/// DbgValMap.
|
||||
class SDDbgInfo {
|
||||
DenseMap<const SDNode*, SDDbgValue*> DbgVblMap;
|
||||
SmallVector<SDDbgValue*, 4> DbgConstMap;
|
||||
SmallVector<SDDbgValue*, 32> DbgValues;
|
||||
DenseMap<const SDNode*, SmallVector<SDDbgValue*, 2> > DbgValMap;
|
||||
|
||||
void operator=(const SDDbgInfo&); // Do not implement.
|
||||
SDDbgInfo(const SDDbgInfo&); // Do not implement.
|
||||
public:
|
||||
SDDbgInfo() {}
|
||||
|
||||
void add(const SDNode *Node, SDDbgValue *V) {
|
||||
DbgVblMap[Node] = V;
|
||||
void add(SDDbgValue *V, const SDNode *Node = 0) {
|
||||
if (Node)
|
||||
DbgValMap[Node].push_back(V);
|
||||
DbgValues.push_back(V);
|
||||
}
|
||||
void add(SDDbgValue *V) { DbgConstMap.push_back(V); }
|
||||
void remove(const SDNode *Node) {
|
||||
DenseMap<const SDNode*, SDDbgValue*>::iterator Itr =
|
||||
DbgVblMap.find(Node);
|
||||
if (Itr != DbgVblMap.end())
|
||||
DbgVblMap.erase(Itr);
|
||||
}
|
||||
// No need to remove a constant.
|
||||
|
||||
void clear() {
|
||||
DbgVblMap.clear();
|
||||
DbgConstMap.clear();
|
||||
DbgValMap.clear();
|
||||
DbgValues.clear();
|
||||
}
|
||||
SDDbgValue *getSDDbgValue(const SDNode *Node) {
|
||||
return DbgVblMap[Node];
|
||||
|
||||
bool empty() const {
|
||||
return DbgValues.empty();
|
||||
}
|
||||
typedef SmallVector<SDDbgValue*, 4>::iterator ConstDbgIterator;
|
||||
ConstDbgIterator DbgConstBegin() { return DbgConstMap.begin(); }
|
||||
ConstDbgIterator DbgConstEnd() { return DbgConstMap.end(); }
|
||||
|
||||
SmallVector<SDDbgValue*,2> &getSDDbgValues(const SDNode *Node) {
|
||||
return DbgValMap[Node];
|
||||
}
|
||||
|
||||
typedef SmallVector<SDDbgValue*,32>::iterator DbgIterator;
|
||||
DbgIterator DbgBegin() { return DbgValues.begin(); }
|
||||
DbgIterator DbgEnd() { return DbgValues.end(); }
|
||||
};
|
||||
|
||||
enum CombineLevel {
|
||||
@ -769,6 +768,15 @@ class SelectionDAG {
|
||||
SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs,
|
||||
const SDValue *Ops, unsigned NumOps);
|
||||
|
||||
/// getDbgValue - Creates a SDDbgValue node.
|
||||
///
|
||||
SDDbgValue *getDbgValue(MDNode *MDPtr, SDNode *N, unsigned R, uint64_t Off,
|
||||
DebugLoc DL, unsigned O);
|
||||
SDDbgValue *getDbgValue(MDNode *MDPtr, Value *C, uint64_t Off,
|
||||
DebugLoc DL, unsigned O);
|
||||
SDDbgValue *getDbgValue(MDNode *MDPtr, unsigned FI, uint64_t Off,
|
||||
DebugLoc DL, unsigned O);
|
||||
|
||||
/// DAGUpdateListener - Clients of various APIs that cause global effects on
|
||||
/// the DAG can optionally implement this interface. This allows the clients
|
||||
/// to handle the various sorts of updates that happen.
|
||||
@ -871,19 +879,21 @@ class SelectionDAG {
|
||||
/// GetOrdering - Get the order for the SDNode.
|
||||
unsigned GetOrdering(const SDNode *SD) const;
|
||||
|
||||
/// AssignDbgInfo - Assign debug info to the SDNode.
|
||||
void AssignDbgInfo(SDNode *SD, SDDbgValue *db);
|
||||
/// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the
|
||||
/// value is produced by SD.
|
||||
void AddDbgValue(SDDbgValue *DB, SDNode *SD = 0);
|
||||
|
||||
/// RememberDbgInfo - Remember debug info with no associated SDNode.
|
||||
void RememberDbgInfo(SDDbgValue *db);
|
||||
|
||||
/// GetDbgInfo - Get the debug info for the SDNode.
|
||||
SDDbgValue *GetDbgInfo(const SDNode* SD);
|
||||
|
||||
SDDbgInfo::ConstDbgIterator DbgConstBegin() {
|
||||
return DbgInfo->DbgConstBegin();
|
||||
/// GetDbgValues - Get the debug values which reference the given SDNode.
|
||||
SmallVector<SDDbgValue*,2> &GetDbgValues(const SDNode* SD) {
|
||||
return DbgInfo->getSDDbgValues(SD);
|
||||
}
|
||||
SDDbgInfo::ConstDbgIterator DbgConstEnd() { return DbgInfo->DbgConstEnd(); }
|
||||
|
||||
/// hasDebugValues - Return true if there are any SDDbgValue nodes associated
|
||||
/// with this SelectionDAG.
|
||||
bool hasDebugValues() const { return !DbgInfo->empty(); }
|
||||
|
||||
SDDbgInfo::DbgIterator DbgBegin() { return DbgInfo->DbgBegin(); }
|
||||
SDDbgInfo::DbgIterator DbgEnd() { return DbgInfo->DbgEnd(); }
|
||||
|
||||
void dump() const;
|
||||
|
||||
|
@ -136,6 +136,8 @@ class SelectionDAGISel : public MachineFunctionPass {
|
||||
OPC_EmitRegister,
|
||||
OPC_EmitConvertToTarget,
|
||||
OPC_EmitMergeInputChains,
|
||||
OPC_EmitMergeInputChains1_0,
|
||||
OPC_EmitMergeInputChains1_1,
|
||||
OPC_EmitCopyToReg,
|
||||
OPC_EmitNodeXForm,
|
||||
OPC_EmitNode,
|
||||
|
@ -616,7 +616,7 @@ namespace ISD {
|
||||
/// which do not reference a specific memory location should be less than
|
||||
/// this value. Those that do must not be less than this value, and can
|
||||
/// be used with SelectionDAG::getMemIntrinsicNode.
|
||||
static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+80;
|
||||
static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+100;
|
||||
|
||||
/// Node predicates
|
||||
|
||||
|
@ -409,8 +409,11 @@ class Function : public GlobalValue,
|
||||
void dropAllReferences();
|
||||
|
||||
/// hasAddressTaken - returns true if there are any uses of this function
|
||||
/// other than direct calls or invokes to it.
|
||||
bool hasAddressTaken() const;
|
||||
/// other than direct calls or invokes to it. Optionally passes back the
|
||||
/// offending user for diagnostic purposes.
|
||||
///
|
||||
bool hasAddressTaken(const User** = 0) const;
|
||||
|
||||
private:
|
||||
// Shadow Value::setValueSubclassData with a private forwarding method so that
|
||||
// subclasses cannot accidentally use it.
|
||||
|
@ -24,8 +24,17 @@ namespace llvm {
|
||||
class PointerType;
|
||||
class FunctionType;
|
||||
class Module;
|
||||
struct InlineAsmKeyType;
|
||||
template<class ValType, class TypeClass, class ConstantClass, bool HasLargeKey>
|
||||
class ConstantUniqueMap;
|
||||
template<class ConstantClass, class TypeClass, class ValType>
|
||||
struct ConstantCreator;
|
||||
|
||||
class InlineAsm : public Value {
|
||||
friend struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType>;
|
||||
friend class ConstantUniqueMap<InlineAsmKeyType, PointerType, InlineAsm,
|
||||
false>;
|
||||
|
||||
InlineAsm(const InlineAsm &); // do not implement
|
||||
void operator=(const InlineAsm&); // do not implement
|
||||
|
||||
@ -33,10 +42,14 @@ class InlineAsm : public Value {
|
||||
bool HasSideEffects;
|
||||
bool IsAlignStack;
|
||||
|
||||
InlineAsm(const FunctionType *Ty, StringRef AsmString,
|
||||
StringRef Constraints, bool hasSideEffects,
|
||||
bool isAlignStack = false);
|
||||
InlineAsm(const PointerType *Ty, const std::string &AsmString,
|
||||
const std::string &Constraints, bool hasSideEffects,
|
||||
bool isAlignStack);
|
||||
virtual ~InlineAsm();
|
||||
|
||||
/// When the ConstantUniqueMap merges two types and makes two InlineAsms
|
||||
/// identical, it destroys one of them with this method.
|
||||
void destroyConstant();
|
||||
public:
|
||||
|
||||
/// InlineAsm::get - Return the specified uniqued inline asm string.
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "llvm/User.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/Support/DebugLoc.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -31,6 +32,7 @@ class Instruction : public User, public ilist_node<Instruction> {
|
||||
Instruction(const Instruction &); // Do not implement
|
||||
|
||||
BasicBlock *Parent;
|
||||
NewDebugLoc DbgLoc; // 'dbg' Metadata cache.
|
||||
|
||||
enum {
|
||||
/// HasMetadataBit - This is a bit stored in the SubClassData field which
|
||||
@ -123,7 +125,13 @@ class Instruction : public User, public ilist_node<Instruction> {
|
||||
/// hasMetadata() - Return true if this instruction has any metadata attached
|
||||
/// to it.
|
||||
bool hasMetadata() const {
|
||||
return (getSubclassDataFromValue() & HasMetadataBit) != 0;
|
||||
return !DbgLoc.isUnknown() || hasMetadataHashEntry();
|
||||
}
|
||||
|
||||
/// hasMetadataOtherThanDebugLoc - Return true if this instruction has
|
||||
/// metadata attached to it other than a debug location.
|
||||
bool hasMetadataOtherThanDebugLoc() const {
|
||||
return hasMetadataHashEntry();
|
||||
}
|
||||
|
||||
/// getMetadata - Get the metadata of given kind attached to this Instruction.
|
||||
@ -148,17 +156,49 @@ class Instruction : public User, public ilist_node<Instruction> {
|
||||
getAllMetadataImpl(MDs);
|
||||
}
|
||||
|
||||
/// getAllMetadataOtherThanDebugLoc - This does the same thing as
|
||||
/// getAllMetadata, except that it filters out the debug location.
|
||||
void getAllMetadataOtherThanDebugLoc(SmallVectorImpl<std::pair<unsigned,
|
||||
MDNode*> > &MDs) const {
|
||||
if (hasMetadataOtherThanDebugLoc())
|
||||
getAllMetadataOtherThanDebugLocImpl(MDs);
|
||||
}
|
||||
|
||||
/// setMetadata - Set the metadata of the specified kind to the specified
|
||||
/// node. This updates/replaces metadata if already present, or removes it if
|
||||
/// Node is null.
|
||||
void setMetadata(unsigned KindID, MDNode *Node);
|
||||
void setMetadata(const char *Kind, MDNode *Node);
|
||||
|
||||
/// setDbgMetadata - This is just an optimized helper function that is
|
||||
/// equivalent to setMetadata("dbg", Node);
|
||||
void setDbgMetadata(MDNode *Node);
|
||||
|
||||
/// getDbgMetadata - This is just an optimized helper function that is
|
||||
/// equivalent to calling getMetadata("dbg").
|
||||
MDNode *getDbgMetadata() const {
|
||||
return DbgLoc.getAsMDNode(getContext());
|
||||
}
|
||||
|
||||
/// setDebugLoc - Set the debug location information for this instruction.
|
||||
void setDebugLoc(const NewDebugLoc &Loc) { DbgLoc = Loc; }
|
||||
|
||||
/// getDebugLoc - Return the debug location for this node as a DebugLoc.
|
||||
const NewDebugLoc &getDebugLoc() const { return DbgLoc; }
|
||||
|
||||
private:
|
||||
/// hasMetadataHashEntry - Return true if we have an entry in the on-the-side
|
||||
/// metadata hash.
|
||||
bool hasMetadataHashEntry() const {
|
||||
return (getSubclassDataFromValue() & HasMetadataBit) != 0;
|
||||
}
|
||||
|
||||
// These are all implemented in Metadata.cpp.
|
||||
MDNode *getMetadataImpl(unsigned KindID) const;
|
||||
MDNode *getMetadataImpl(const char *Kind) const;
|
||||
void getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned,MDNode*> > &)const;
|
||||
void getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl<std::pair<unsigned,
|
||||
MDNode*> > &) const;
|
||||
void removeAllMetadata();
|
||||
public:
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -315,7 +355,7 @@ class Instruction : public User, public ilist_node<Instruction> {
|
||||
return Value::getSubclassDataFromValue();
|
||||
}
|
||||
|
||||
void setHasMetadata(bool V) {
|
||||
void setHasMetadataHashEntry(bool V) {
|
||||
setValueSubclassData((getSubclassDataFromValue() & ~HasMetadataBit) |
|
||||
(V ? HasMetadataBit : 0));
|
||||
}
|
||||
|
@ -971,6 +971,13 @@ class CallInst : public Instruction {
|
||||
unsigned getParamAlignment(unsigned i) const {
|
||||
return AttributeList.getParamAlignment(i);
|
||||
}
|
||||
|
||||
/// @brief Return true if the call should not be inlined.
|
||||
bool isNoInline() const { return paramHasAttr(~0, Attribute::NoInline); }
|
||||
void setIsNoInline(bool Value) {
|
||||
if (Value) addAttribute(~0, Attribute::NoInline);
|
||||
else removeAttribute(~0, Attribute::NoInline);
|
||||
}
|
||||
|
||||
/// @brief Determine if the call does not access memory.
|
||||
bool doesNotAccessMemory() const {
|
||||
@ -2456,6 +2463,13 @@ class InvokeInst : public TerminatorInst {
|
||||
return AttributeList.getParamAlignment(i);
|
||||
}
|
||||
|
||||
/// @brief Return true if the call should not be inlined.
|
||||
bool isNoInline() const { return paramHasAttr(~0, Attribute::NoInline); }
|
||||
void setIsNoInline(bool Value) {
|
||||
if (Value) addAttribute(~0, Attribute::NoInline);
|
||||
else removeAttribute(~0, Attribute::NoInline);
|
||||
}
|
||||
|
||||
/// @brief Determine if the call does not access memory.
|
||||
bool doesNotAccessMemory() const {
|
||||
return paramHasAttr(~0, Attribute::ReadNone);
|
||||
@ -2508,32 +2522,31 @@ class InvokeInst : public TerminatorInst {
|
||||
/// indirect function invocation.
|
||||
///
|
||||
Function *getCalledFunction() const {
|
||||
return dyn_cast<Function>(getOperand(0));
|
||||
return dyn_cast<Function>(Op<-3>());
|
||||
}
|
||||
|
||||
/// getCalledValue - Get a pointer to the function that is invoked by this
|
||||
/// instruction
|
||||
const Value *getCalledValue() const { return getOperand(0); }
|
||||
Value *getCalledValue() { return getOperand(0); }
|
||||
const Value *getCalledValue() const { return Op<-3>(); }
|
||||
Value *getCalledValue() { return Op<-3>(); }
|
||||
|
||||
/// setCalledFunction - Set the function called.
|
||||
void setCalledFunction(Value* Fn) {
|
||||
Op<0>() = Fn;
|
||||
Op<-3>() = Fn;
|
||||
}
|
||||
|
||||
// get*Dest - Return the destination basic blocks...
|
||||
BasicBlock *getNormalDest() const {
|
||||
return cast<BasicBlock>(getOperand(1));
|
||||
return cast<BasicBlock>(Op<-2>());
|
||||
}
|
||||
BasicBlock *getUnwindDest() const {
|
||||
return cast<BasicBlock>(getOperand(2));
|
||||
return cast<BasicBlock>(Op<-1>());
|
||||
}
|
||||
void setNormalDest(BasicBlock *B) {
|
||||
setOperand(1, (Value*)B);
|
||||
Op<-2>() = reinterpret_cast<Value*>(B);
|
||||
}
|
||||
|
||||
void setUnwindDest(BasicBlock *B) {
|
||||
setOperand(2, (Value*)B);
|
||||
Op<-1>() = reinterpret_cast<Value*>(B);
|
||||
}
|
||||
|
||||
BasicBlock *getSuccessor(unsigned i) const {
|
||||
@ -2543,7 +2556,7 @@ class InvokeInst : public TerminatorInst {
|
||||
|
||||
void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
|
||||
assert(idx < 2 && "Successor # out of range for invoke!");
|
||||
setOperand(idx+1, (Value*)NewSucc);
|
||||
*(&Op<-2>() + idx) = reinterpret_cast<Value*>(NewSucc);
|
||||
}
|
||||
|
||||
unsigned getNumSuccessors() const { return 2; }
|
||||
@ -2556,6 +2569,7 @@ class InvokeInst : public TerminatorInst {
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
|
||||
private:
|
||||
virtual BasicBlock *getSuccessorV(unsigned idx) const;
|
||||
virtual unsigned getNumSuccessorsV() const;
|
||||
|
@ -176,19 +176,19 @@ class GCCBuiltin<string name> {
|
||||
//===--------------- Variable Argument Handling Intrinsics ----------------===//
|
||||
//
|
||||
|
||||
def int_vastart : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [], "llvm.va_start">;
|
||||
def int_vacopy : Intrinsic<[llvm_void_ty], [llvm_ptr_ty, llvm_ptr_ty], [],
|
||||
def int_vastart : Intrinsic<[], [llvm_ptr_ty], [], "llvm.va_start">;
|
||||
def int_vacopy : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [],
|
||||
"llvm.va_copy">;
|
||||
def int_vaend : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [], "llvm.va_end">;
|
||||
def int_vaend : Intrinsic<[], [llvm_ptr_ty], [], "llvm.va_end">;
|
||||
|
||||
//===------------------- Garbage Collection Intrinsics --------------------===//
|
||||
//
|
||||
def int_gcroot : Intrinsic<[llvm_void_ty],
|
||||
def int_gcroot : Intrinsic<[],
|
||||
[llvm_ptrptr_ty, llvm_ptr_ty]>;
|
||||
def int_gcread : Intrinsic<[llvm_ptr_ty],
|
||||
[llvm_ptr_ty, llvm_ptrptr_ty],
|
||||
[IntrReadArgMem]>;
|
||||
def int_gcwrite : Intrinsic<[llvm_void_ty],
|
||||
def int_gcwrite : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_ptr_ty, llvm_ptrptr_ty],
|
||||
[IntrWriteArgMem, NoCapture<1>, NoCapture<2>]>;
|
||||
|
||||
@ -201,37 +201,37 @@ def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>;
|
||||
// model their dependencies on allocas.
|
||||
def int_stacksave : Intrinsic<[llvm_ptr_ty]>,
|
||||
GCCBuiltin<"__builtin_stack_save">;
|
||||
def int_stackrestore : Intrinsic<[llvm_void_ty], [llvm_ptr_ty]>,
|
||||
def int_stackrestore : Intrinsic<[], [llvm_ptr_ty]>,
|
||||
GCCBuiltin<"__builtin_stack_restore">;
|
||||
|
||||
// IntrWriteArgMem is more pessimistic than strictly necessary for prefetch,
|
||||
// however it does conveniently prevent the prefetch from being reordered
|
||||
// with respect to nearby accesses to the same memory.
|
||||
def int_prefetch : Intrinsic<[llvm_void_ty],
|
||||
def int_prefetch : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrWriteArgMem, NoCapture<0>]>;
|
||||
def int_pcmarker : Intrinsic<[llvm_void_ty], [llvm_i32_ty]>;
|
||||
def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>;
|
||||
|
||||
def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>;
|
||||
|
||||
// Stack Protector Intrinsic - The stackprotector intrinsic writes the stack
|
||||
// guard to the correct place on the stack frame.
|
||||
def int_stackprotector : Intrinsic<[llvm_void_ty],
|
||||
def int_stackprotector : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_ptrptr_ty],
|
||||
[IntrWriteMem]>;
|
||||
|
||||
//===------------------- Standard C Library Intrinsics --------------------===//
|
||||
//
|
||||
|
||||
def int_memcpy : Intrinsic<[llvm_void_ty],
|
||||
def int_memcpy : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_ptr_ty, llvm_anyint_ty,
|
||||
llvm_i32_ty],
|
||||
[IntrWriteArgMem, NoCapture<0>, NoCapture<1>]>;
|
||||
def int_memmove : Intrinsic<[llvm_void_ty],
|
||||
def int_memmove : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_ptr_ty, llvm_anyint_ty,
|
||||
llvm_i32_ty],
|
||||
[IntrWriteArgMem, NoCapture<0>, NoCapture<1>]>;
|
||||
def int_memset : Intrinsic<[llvm_void_ty],
|
||||
def int_memset : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_i8_ty, llvm_anyint_ty,
|
||||
llvm_i32_ty],
|
||||
[IntrWriteArgMem, NoCapture<0>]>;
|
||||
@ -255,9 +255,9 @@ let Properties = [IntrReadMem] in {
|
||||
|
||||
// NOTE: these are internal interfaces.
|
||||
def int_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>;
|
||||
def int_longjmp : Intrinsic<[llvm_void_ty], [llvm_ptr_ty, llvm_i32_ty]>;
|
||||
def int_longjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty]>;
|
||||
def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>;
|
||||
def int_siglongjmp : Intrinsic<[llvm_void_ty], [llvm_ptr_ty, llvm_i32_ty]>;
|
||||
def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty]>;
|
||||
|
||||
// Internal interface for object size checking
|
||||
def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_ptr_ty, llvm_i1_ty],
|
||||
@ -282,9 +282,9 @@ let Properties = [IntrNoMem] in {
|
||||
// optimizers can change them aggressively. Special handling needed in a few
|
||||
// places.
|
||||
let Properties = [IntrNoMem] in {
|
||||
def int_dbg_declare : Intrinsic<[llvm_void_ty],
|
||||
def int_dbg_declare : Intrinsic<[],
|
||||
[llvm_metadata_ty, llvm_metadata_ty]>;
|
||||
def int_dbg_value : Intrinsic<[llvm_void_ty],
|
||||
def int_dbg_value : Intrinsic<[],
|
||||
[llvm_metadata_ty, llvm_i64_ty,
|
||||
llvm_metadata_ty]>;
|
||||
}
|
||||
@ -297,24 +297,24 @@ def int_eh_selector : Intrinsic<[llvm_i32_ty],
|
||||
|
||||
def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>;
|
||||
|
||||
def int_eh_return_i32 : Intrinsic<[llvm_void_ty], [llvm_i32_ty, llvm_ptr_ty]>;
|
||||
def int_eh_return_i64 : Intrinsic<[llvm_void_ty], [llvm_i64_ty, llvm_ptr_ty]>;
|
||||
def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>;
|
||||
def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>;
|
||||
|
||||
def int_eh_unwind_init: Intrinsic<[llvm_void_ty]>,
|
||||
def int_eh_unwind_init: Intrinsic<[]>,
|
||||
GCCBuiltin<"__builtin_unwind_init">;
|
||||
|
||||
def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>;
|
||||
|
||||
let Properties = [IntrNoMem] in {
|
||||
def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>;
|
||||
def int_eh_sjlj_longjmp : Intrinsic<[llvm_void_ty], [llvm_ptr_ty]>;
|
||||
def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty]>;
|
||||
def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>;
|
||||
def int_eh_sjlj_callsite: Intrinsic<[llvm_void_ty], [llvm_i32_ty]>;
|
||||
def int_eh_sjlj_callsite: Intrinsic<[], [llvm_i32_ty]>;
|
||||
}
|
||||
|
||||
//===---------------- Generic Variable Attribute Intrinsics----------------===//
|
||||
//
|
||||
def int_var_annotation : Intrinsic<[llvm_void_ty],
|
||||
def int_var_annotation : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_ptr_ty,
|
||||
llvm_ptr_ty, llvm_i32_ty],
|
||||
[], "llvm.var.annotation">;
|
||||
@ -361,7 +361,7 @@ def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
|
||||
|
||||
//===------------------------- Atomic Intrinsics --------------------------===//
|
||||
//
|
||||
def int_memory_barrier : Intrinsic<[llvm_void_ty],
|
||||
def int_memory_barrier : Intrinsic<[],
|
||||
[llvm_i1_ty, llvm_i1_ty,
|
||||
llvm_i1_ty, llvm_i1_ty, llvm_i1_ty], []>,
|
||||
GCCBuiltin<"__builtin_llvm_memory_barrier">;
|
||||
@ -429,16 +429,16 @@ def int_atomic_load_umax : Intrinsic<[llvm_anyint_ty],
|
||||
|
||||
//===------------------------- Memory Use Markers -------------------------===//
|
||||
//
|
||||
def int_lifetime_start : Intrinsic<[llvm_void_ty],
|
||||
def int_lifetime_start : Intrinsic<[],
|
||||
[llvm_i64_ty, llvm_ptr_ty],
|
||||
[IntrWriteArgMem, NoCapture<1>]>;
|
||||
def int_lifetime_end : Intrinsic<[llvm_void_ty],
|
||||
def int_lifetime_end : Intrinsic<[],
|
||||
[llvm_i64_ty, llvm_ptr_ty],
|
||||
[IntrWriteArgMem, NoCapture<1>]>;
|
||||
def int_invariant_start : Intrinsic<[llvm_descriptor_ty],
|
||||
[llvm_i64_ty, llvm_ptr_ty],
|
||||
[IntrReadArgMem, NoCapture<1>]>;
|
||||
def int_invariant_end : Intrinsic<[llvm_void_ty],
|
||||
def int_invariant_end : Intrinsic<[],
|
||||
[llvm_descriptor_ty, llvm_i64_ty,
|
||||
llvm_ptr_ty],
|
||||
[IntrWriteArgMem, NoCapture<2>]>;
|
||||
@ -447,7 +447,7 @@ def int_invariant_end : Intrinsic<[llvm_void_ty],
|
||||
//
|
||||
def int_flt_rounds : Intrinsic<[llvm_i32_ty]>,
|
||||
GCCBuiltin<"__builtin_flt_rounds">;
|
||||
def int_trap : Intrinsic<[llvm_void_ty]>,
|
||||
def int_trap : Intrinsic<[]>,
|
||||
GCCBuiltin<"__builtin_trap">;
|
||||
|
||||
// Intrisics to support half precision floating point format
|
||||
|
@ -344,31 +344,31 @@ let TargetPrefix = "arm" in {
|
||||
[IntrReadArgMem]>;
|
||||
|
||||
// Interleaving vector stores from N-element structures.
|
||||
def int_arm_neon_vst1 : Intrinsic<[llvm_void_ty],
|
||||
def int_arm_neon_vst1 : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_anyvector_ty],
|
||||
[IntrWriteArgMem]>;
|
||||
def int_arm_neon_vst2 : Intrinsic<[llvm_void_ty],
|
||||
def int_arm_neon_vst2 : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_anyvector_ty,
|
||||
LLVMMatchType<0>], [IntrWriteArgMem]>;
|
||||
def int_arm_neon_vst3 : Intrinsic<[llvm_void_ty],
|
||||
def int_arm_neon_vst3 : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_anyvector_ty,
|
||||
LLVMMatchType<0>, LLVMMatchType<0>],
|
||||
[IntrWriteArgMem]>;
|
||||
def int_arm_neon_vst4 : Intrinsic<[llvm_void_ty],
|
||||
def int_arm_neon_vst4 : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_anyvector_ty,
|
||||
LLVMMatchType<0>, LLVMMatchType<0>,
|
||||
LLVMMatchType<0>], [IntrWriteArgMem]>;
|
||||
|
||||
// Vector store N-element structure from one lane.
|
||||
def int_arm_neon_vst2lane : Intrinsic<[llvm_void_ty],
|
||||
def int_arm_neon_vst2lane : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_anyvector_ty,
|
||||
LLVMMatchType<0>, llvm_i32_ty],
|
||||
[IntrWriteArgMem]>;
|
||||
def int_arm_neon_vst3lane : Intrinsic<[llvm_void_ty],
|
||||
def int_arm_neon_vst3lane : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_anyvector_ty,
|
||||
LLVMMatchType<0>, LLVMMatchType<0>,
|
||||
llvm_i32_ty], [IntrWriteArgMem]>;
|
||||
def int_arm_neon_vst4lane : Intrinsic<[llvm_void_ty],
|
||||
def int_arm_neon_vst4lane : Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_anyvector_ty,
|
||||
LLVMMatchType<0>, LLVMMatchType<0>,
|
||||
LLVMMatchType<0>, llvm_i32_ty],
|
||||
|
@ -18,17 +18,17 @@
|
||||
// Non-altivec intrinsics.
|
||||
let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
|
||||
// dcba/dcbf/dcbi/dcbst/dcbt/dcbz/dcbzl(PPC970) instructions.
|
||||
def int_ppc_dcba : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbf : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbi : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbst : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbt : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbtst: Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbz : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbzl : Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcba : Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbf : Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbi : Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
|
||||
// sync instruction
|
||||
def int_ppc_sync : Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>;
|
||||
def int_ppc_sync : Intrinsic<[], [], [IntrWriteMem]>;
|
||||
}
|
||||
|
||||
|
||||
@ -86,23 +86,23 @@ class PowerPC_Vec_WWW_Intrinsic<string GCCIntSuffix>
|
||||
let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
|
||||
// Data Stream Control.
|
||||
def int_ppc_altivec_dss : GCCBuiltin<"__builtin_altivec_dss">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_i32_ty], [IntrWriteMem]>;
|
||||
Intrinsic<[], [llvm_i32_ty], [IntrWriteMem]>;
|
||||
def int_ppc_altivec_dssall : GCCBuiltin<"__builtin_altivec_dssall">,
|
||||
Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>;
|
||||
Intrinsic<[], [], [IntrWriteMem]>;
|
||||
def int_ppc_altivec_dst : GCCBuiltin<"__builtin_altivec_dst">,
|
||||
Intrinsic<[llvm_void_ty],
|
||||
Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrWriteMem]>;
|
||||
def int_ppc_altivec_dstt : GCCBuiltin<"__builtin_altivec_dstt">,
|
||||
Intrinsic<[llvm_void_ty],
|
||||
Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrWriteMem]>;
|
||||
def int_ppc_altivec_dstst : GCCBuiltin<"__builtin_altivec_dstst">,
|
||||
Intrinsic<[llvm_void_ty],
|
||||
Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrWriteMem]>;
|
||||
def int_ppc_altivec_dststt : GCCBuiltin<"__builtin_altivec_dststt">,
|
||||
Intrinsic<[llvm_void_ty],
|
||||
Intrinsic<[],
|
||||
[llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrWriteMem]>;
|
||||
|
||||
@ -110,7 +110,7 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
|
||||
def int_ppc_altivec_mfvscr : GCCBuiltin<"__builtin_altivec_mfvscr">,
|
||||
Intrinsic<[llvm_v8i16_ty], [], [IntrReadMem]>;
|
||||
def int_ppc_altivec_mtvscr : GCCBuiltin<"__builtin_altivec_mtvscr">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_v4i32_ty], [IntrWriteMem]>;
|
||||
Intrinsic<[], [llvm_v4i32_ty], [IntrWriteMem]>;
|
||||
|
||||
|
||||
// Loads. These don't map directly to GCC builtins because they represent the
|
||||
@ -129,19 +129,19 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
|
||||
// Stores. These don't map directly to GCC builtins because they represent the
|
||||
// source address with a single pointer.
|
||||
def int_ppc_altivec_stvx :
|
||||
Intrinsic<[llvm_void_ty], [llvm_v4i32_ty, llvm_ptr_ty],
|
||||
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
|
||||
[IntrWriteMem]>;
|
||||
def int_ppc_altivec_stvxl :
|
||||
Intrinsic<[llvm_void_ty], [llvm_v4i32_ty, llvm_ptr_ty],
|
||||
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
|
||||
[IntrWriteMem]>;
|
||||
def int_ppc_altivec_stvebx :
|
||||
Intrinsic<[llvm_void_ty], [llvm_v16i8_ty, llvm_ptr_ty],
|
||||
Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty],
|
||||
[IntrWriteMem]>;
|
||||
def int_ppc_altivec_stvehx :
|
||||
Intrinsic<[llvm_void_ty], [llvm_v8i16_ty, llvm_ptr_ty],
|
||||
Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty],
|
||||
[IntrWriteMem]>;
|
||||
def int_ppc_altivec_stvewx :
|
||||
Intrinsic<[llvm_void_ty], [llvm_v4i32_ty, llvm_ptr_ty],
|
||||
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
|
||||
[IntrWriteMem]>;
|
||||
|
||||
// Comparisons setting a vector.
|
||||
|
@ -142,25 +142,25 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
// SIMD store ops
|
||||
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_sse_storeu_ps : GCCBuiltin<"__builtin_ia32_storeups">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty,
|
||||
Intrinsic<[], [llvm_ptr_ty,
|
||||
llvm_v4f32_ty], [IntrWriteMem]>;
|
||||
}
|
||||
|
||||
// Cacheability support ops
|
||||
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_sse_movnt_ps : GCCBuiltin<"__builtin_ia32_movntps">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty,
|
||||
Intrinsic<[], [llvm_ptr_ty,
|
||||
llvm_v4f32_ty], [IntrWriteMem]>;
|
||||
def int_x86_sse_sfence : GCCBuiltin<"__builtin_ia32_sfence">,
|
||||
Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>;
|
||||
Intrinsic<[], [], [IntrWriteMem]>;
|
||||
}
|
||||
|
||||
// Control register.
|
||||
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_sse_stmxcsr :
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_x86_sse_ldmxcsr :
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
}
|
||||
|
||||
// Misc.
|
||||
@ -458,26 +458,26 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
// SIMD store ops
|
||||
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_sse2_storeu_pd : GCCBuiltin<"__builtin_ia32_storeupd">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty,
|
||||
Intrinsic<[], [llvm_ptr_ty,
|
||||
llvm_v2f64_ty], [IntrWriteMem]>;
|
||||
def int_x86_sse2_storeu_dq : GCCBuiltin<"__builtin_ia32_storedqu">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty,
|
||||
Intrinsic<[], [llvm_ptr_ty,
|
||||
llvm_v16i8_ty], [IntrWriteMem]>;
|
||||
def int_x86_sse2_storel_dq : GCCBuiltin<"__builtin_ia32_storelv4si">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty,
|
||||
Intrinsic<[], [llvm_ptr_ty,
|
||||
llvm_v4i32_ty], [IntrWriteMem]>;
|
||||
}
|
||||
|
||||
// Cacheability support ops
|
||||
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_sse2_movnt_dq : GCCBuiltin<"__builtin_ia32_movntdq">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty,
|
||||
Intrinsic<[], [llvm_ptr_ty,
|
||||
llvm_v2i64_ty], [IntrWriteMem]>;
|
||||
def int_x86_sse2_movnt_pd : GCCBuiltin<"__builtin_ia32_movntpd">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty,
|
||||
Intrinsic<[], [llvm_ptr_ty,
|
||||
llvm_v2f64_ty], [IntrWriteMem]>;
|
||||
def int_x86_sse2_movnt_i : GCCBuiltin<"__builtin_ia32_movnti">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty,
|
||||
Intrinsic<[], [llvm_ptr_ty,
|
||||
llvm_i32_ty], [IntrWriteMem]>;
|
||||
}
|
||||
|
||||
@ -497,14 +497,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_sse2_pmovmskb_128 : GCCBuiltin<"__builtin_ia32_pmovmskb128">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>;
|
||||
def int_x86_sse2_maskmov_dqu : GCCBuiltin<"__builtin_ia32_maskmovdqu">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_v16i8_ty,
|
||||
Intrinsic<[], [llvm_v16i8_ty,
|
||||
llvm_v16i8_ty, llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_x86_sse2_clflush : GCCBuiltin<"__builtin_ia32_clflush">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
Intrinsic<[], [llvm_ptr_ty], [IntrWriteMem]>;
|
||||
def int_x86_sse2_lfence : GCCBuiltin<"__builtin_ia32_lfence">,
|
||||
Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>;
|
||||
Intrinsic<[], [], [IntrWriteMem]>;
|
||||
def int_x86_sse2_mfence : GCCBuiltin<"__builtin_ia32_mfence">,
|
||||
Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>;
|
||||
Intrinsic<[], [], [IntrWriteMem]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -545,10 +545,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
// Thread synchronization ops.
|
||||
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_sse3_monitor : GCCBuiltin<"__builtin_ia32_monitor">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty,
|
||||
Intrinsic<[], [llvm_ptr_ty,
|
||||
llvm_i32_ty, llvm_i32_ty], [IntrWriteMem]>;
|
||||
def int_x86_sse3_mwait : GCCBuiltin<"__builtin_ia32_mwait">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_i32_ty,
|
||||
Intrinsic<[], [llvm_i32_ty,
|
||||
llvm_i32_ty], [IntrWriteMem]>;
|
||||
}
|
||||
|
||||
@ -779,6 +779,29 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
[IntrNoMem, Commutative]>;
|
||||
}
|
||||
|
||||
// Advanced Encryption Standard (AES) Instructions
|
||||
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_aesni_aesimc : GCCBuiltin<"__builtin_ia32_aesimc128">,
|
||||
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_aesni_aesenc : GCCBuiltin<"__builtin_ia32_aesenc128">,
|
||||
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_aesni_aesenclast : GCCBuiltin<"__builtin_ia32_aesenclast128">,
|
||||
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_aesni_aesdec : GCCBuiltin<"__builtin_ia32_aesdec128">,
|
||||
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_aesni_aesdeclast : GCCBuiltin<"__builtin_ia32_aesdeclast128">,
|
||||
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_aesni_aeskeygenassist :
|
||||
GCCBuiltin<"__builtin_ia32_aeskeygenassist">,
|
||||
Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
}
|
||||
|
||||
// Vector pack
|
||||
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_sse41_packusdw : GCCBuiltin<"__builtin_ia32_packusdw128">,
|
||||
@ -791,9 +814,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_sse41_pmuldq : GCCBuiltin<"__builtin_ia32_pmuldq128">,
|
||||
Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
|
||||
[IntrNoMem, Commutative]>;
|
||||
def int_x86_sse41_pmulld : GCCBuiltin<"__builtin_ia32_pmulld128">,
|
||||
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty],
|
||||
[IntrNoMem, Commutative]>;
|
||||
}
|
||||
|
||||
// Vector extract
|
||||
@ -973,9 +993,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
// Empty MMX state op.
|
||||
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_mmx_emms : GCCBuiltin<"__builtin_ia32_emms">,
|
||||
Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>;
|
||||
Intrinsic<[], [], [IntrWriteMem]>;
|
||||
def int_x86_mmx_femms : GCCBuiltin<"__builtin_ia32_femms">,
|
||||
Intrinsic<[llvm_void_ty], [], [IntrWriteMem]>;
|
||||
Intrinsic<[], [], [IntrWriteMem]>;
|
||||
}
|
||||
|
||||
// Integer arithmetic ops.
|
||||
@ -1151,7 +1171,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
// Misc.
|
||||
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_mmx_maskmovq : GCCBuiltin<"__builtin_ia32_maskmovq">,
|
||||
Intrinsic<[llvm_void_ty],
|
||||
Intrinsic<[],
|
||||
[llvm_v8i8_ty, llvm_v8i8_ty, llvm_ptr_ty],
|
||||
[IntrWriteMem]>;
|
||||
|
||||
@ -1159,6 +1179,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
Intrinsic<[llvm_i32_ty], [llvm_v8i8_ty], [IntrNoMem]>;
|
||||
|
||||
def int_x86_mmx_movnt_dq : GCCBuiltin<"__builtin_ia32_movntq">,
|
||||
Intrinsic<[llvm_void_ty], [llvm_ptr_ty,
|
||||
Intrinsic<[], [llvm_ptr_ty,
|
||||
llvm_v1i64_ty], [IntrWriteMem]>;
|
||||
}
|
||||
|
@ -36,6 +36,12 @@ class LLVMContext {
|
||||
LLVMContext();
|
||||
~LLVMContext();
|
||||
|
||||
// Pinned metadata names, which always have the same value. This is a
|
||||
// compile-time performance optimization, not a correctness optimization.
|
||||
enum {
|
||||
MD_dbg = 1 // "dbg" -> 1.
|
||||
};
|
||||
|
||||
/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
|
||||
/// This ID is uniqued across modules in the current LLVMContext.
|
||||
unsigned getMDKindID(StringRef Name) const;
|
||||
|
@ -12,6 +12,9 @@
|
||||
|
||||
namespace llvm {
|
||||
class MCAssembler;
|
||||
class MCFragment;
|
||||
class MCSectionData;
|
||||
class MCSymbolData;
|
||||
|
||||
/// Encapsulates the layout of an assembly file at a particular point in time.
|
||||
///
|
||||
@ -29,6 +32,64 @@ class MCAsmLayout {
|
||||
|
||||
/// Get the assembler object this is a layout for.
|
||||
MCAssembler &getAssembler() const { return Assembler; }
|
||||
|
||||
/// \brief Update the layout because a fragment has been resized. The
|
||||
/// fragments size should have already been updated, the \arg SlideAmount is
|
||||
/// the delta from the old size.
|
||||
void UpdateForSlide(MCFragment *F, int SlideAmount);
|
||||
|
||||
/// @name Fragment Layout Data
|
||||
/// @{
|
||||
|
||||
/// \brief Get the effective size of the given fragment, as computed in the
|
||||
/// current layout.
|
||||
uint64_t getFragmentEffectiveSize(const MCFragment *F) const;
|
||||
|
||||
/// \brief Set the effective size of the given fragment.
|
||||
void setFragmentEffectiveSize(MCFragment *F, uint64_t Value);
|
||||
|
||||
/// \brief Get the offset of the given fragment inside its containing section.
|
||||
uint64_t getFragmentOffset(const MCFragment *F) const;
|
||||
|
||||
/// \brief Set the offset of the given fragment inside its containing section.
|
||||
void setFragmentOffset(MCFragment *F, uint64_t Value);
|
||||
|
||||
/// @}
|
||||
/// @name Section Layout Data
|
||||
/// @{
|
||||
|
||||
/// \brief Get the computed address of the given section.
|
||||
uint64_t getSectionAddress(const MCSectionData *SD) const;
|
||||
|
||||
/// \brief Set the computed address of the given section.
|
||||
void setSectionAddress(MCSectionData *SD, uint64_t Value);
|
||||
|
||||
/// \brief Get the data size of the given section, as emitted to the object
|
||||
/// file. This may include additional padding, or be 0 for virtual sections.
|
||||
uint64_t getSectionFileSize(const MCSectionData *SD) const;
|
||||
|
||||
/// \brief Set the data size of the given section.
|
||||
void setSectionFileSize(MCSectionData *SD, uint64_t Value);
|
||||
|
||||
/// \brief Get the actual data size of the given section.
|
||||
uint64_t getSectionSize(const MCSectionData *SD) const;
|
||||
|
||||
/// \brief Set the actual data size of the given section.
|
||||
void setSectionSize(MCSectionData *SD, uint64_t Value);
|
||||
|
||||
/// @}
|
||||
/// @name Utility Functions
|
||||
/// @{
|
||||
|
||||
/// \brief Get the address of the given fragment, as computed in the current
|
||||
/// layout.
|
||||
uint64_t getFragmentAddress(const MCFragment *F) const;
|
||||
|
||||
/// \brief Get the address of the given symbol, as computed in the current
|
||||
/// layout.
|
||||
uint64_t getSymbolAddress(const MCSymbolData *SD) const;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <vector> // FIXME: Shouldn't be needed.
|
||||
|
||||
@ -37,6 +38,8 @@ class TargetAsmBackend;
|
||||
/// MCAsmFixup - Represent a fixed size region of bytes inside some fragment
|
||||
/// which needs to be rewritten. This region will either be rewritten by the
|
||||
/// assembler or cause a relocation entry to be generated.
|
||||
//
|
||||
// FIXME: This should probably just be merged with MCFixup.
|
||||
class MCAsmFixup {
|
||||
public:
|
||||
/// Offset - The offset inside the fragment which needs to be rewritten.
|
||||
@ -54,14 +57,17 @@ class MCAsmFixup {
|
||||
};
|
||||
|
||||
class MCFragment : public ilist_node<MCFragment> {
|
||||
friend class MCAsmLayout;
|
||||
|
||||
MCFragment(const MCFragment&); // DO NOT IMPLEMENT
|
||||
void operator=(const MCFragment&); // DO NOT IMPLEMENT
|
||||
|
||||
public:
|
||||
enum FragmentType {
|
||||
FT_Data,
|
||||
FT_Align,
|
||||
FT_Data,
|
||||
FT_Fill,
|
||||
FT_Inst,
|
||||
FT_Org,
|
||||
FT_ZeroFill
|
||||
};
|
||||
@ -81,8 +87,13 @@ class MCFragment : public ilist_node<MCFragment> {
|
||||
/// initialized.
|
||||
uint64_t Offset;
|
||||
|
||||
/// FileSize - The file size of this section. This is ~0 until initialized.
|
||||
uint64_t FileSize;
|
||||
/// EffectiveSize - The compute size of this section. This is ~0 until
|
||||
/// initialized.
|
||||
uint64_t EffectiveSize;
|
||||
|
||||
/// Ordinal - The global index of this fragment. This is the index across all
|
||||
/// sections, not just the parent section.
|
||||
unsigned Ordinal;
|
||||
|
||||
/// @}
|
||||
|
||||
@ -99,35 +110,8 @@ class MCFragment : public ilist_node<MCFragment> {
|
||||
MCSectionData *getParent() const { return Parent; }
|
||||
void setParent(MCSectionData *Value) { Parent = Value; }
|
||||
|
||||
// FIXME: This should be abstract, fix sentinel.
|
||||
virtual uint64_t getMaxFileSize() const {
|
||||
assert(0 && "Invalid getMaxFileSize call!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @name Assembler Backend Support
|
||||
/// @{
|
||||
//
|
||||
// FIXME: This could all be kept private to the assembler implementation.
|
||||
|
||||
uint64_t getAddress() const;
|
||||
|
||||
uint64_t getFileSize() const {
|
||||
assert(FileSize != ~UINT64_C(0) && "File size not set!");
|
||||
return FileSize;
|
||||
}
|
||||
void setFileSize(uint64_t Value) {
|
||||
assert(Value <= getMaxFileSize() && "Invalid file size!");
|
||||
FileSize = Value;
|
||||
}
|
||||
|
||||
uint64_t getOffset() const {
|
||||
assert(Offset != ~UINT64_C(0) && "File offset not set!");
|
||||
return Offset;
|
||||
}
|
||||
void setOffset(uint64_t Value) { Offset = Value; }
|
||||
|
||||
/// @}
|
||||
unsigned getOrdinal() const { return Ordinal; }
|
||||
void setOrdinal(unsigned Value) { Ordinal = Value; }
|
||||
|
||||
static bool classof(const MCFragment *O) { return true; }
|
||||
|
||||
@ -150,15 +134,10 @@ class MCDataFragment : public MCFragment {
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
uint64_t getMaxFileSize() const {
|
||||
return Contents.size();
|
||||
}
|
||||
|
||||
SmallString<32> &getContents() { return Contents; }
|
||||
const SmallString<32> &getContents() const { return Contents; }
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Fixup Access
|
||||
/// @{
|
||||
|
||||
@ -190,6 +169,68 @@ class MCDataFragment : public MCFragment {
|
||||
virtual void dump();
|
||||
};
|
||||
|
||||
// FIXME: This current incarnation of MCInstFragment doesn't make much sense, as
|
||||
// it is almost entirely a duplicate of MCDataFragment. If we decide to stick
|
||||
// with this approach (as opposed to making MCInstFragment a very light weight
|
||||
// object with just the MCInst and a code size, then we should just change
|
||||
// MCDataFragment to have an optional MCInst at its end.
|
||||
class MCInstFragment : public MCFragment {
|
||||
/// Inst - The instruction this is a fragment for.
|
||||
MCInst Inst;
|
||||
|
||||
/// InstSize - The size of the currently encoded instruction.
|
||||
SmallString<8> Code;
|
||||
|
||||
/// Fixups - The list of fixups in this fragment.
|
||||
SmallVector<MCAsmFixup, 1> Fixups;
|
||||
|
||||
public:
|
||||
typedef SmallVectorImpl<MCAsmFixup>::const_iterator const_fixup_iterator;
|
||||
typedef SmallVectorImpl<MCAsmFixup>::iterator fixup_iterator;
|
||||
|
||||
public:
|
||||
MCInstFragment(MCInst _Inst, MCSectionData *SD = 0)
|
||||
: MCFragment(FT_Inst, SD), Inst(_Inst) {
|
||||
}
|
||||
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
SmallVectorImpl<char> &getCode() { return Code; }
|
||||
const SmallVectorImpl<char> &getCode() const { return Code; }
|
||||
|
||||
unsigned getInstSize() const { return Code.size(); }
|
||||
|
||||
MCInst &getInst() { return Inst; }
|
||||
const MCInst &getInst() const { return Inst; }
|
||||
|
||||
void setInst(MCInst Value) { Inst = Value; }
|
||||
|
||||
/// @}
|
||||
/// @name Fixup Access
|
||||
/// @{
|
||||
|
||||
SmallVectorImpl<MCAsmFixup> &getFixups() { return Fixups; }
|
||||
const SmallVectorImpl<MCAsmFixup> &getFixups() const { return Fixups; }
|
||||
|
||||
fixup_iterator fixup_begin() { return Fixups.begin(); }
|
||||
const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
|
||||
|
||||
fixup_iterator fixup_end() {return Fixups.end();}
|
||||
const_fixup_iterator fixup_end() const {return Fixups.end();}
|
||||
|
||||
size_t fixup_size() const { return Fixups.size(); }
|
||||
|
||||
/// @}
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
return F->getKind() == MCFragment::FT_Inst;
|
||||
}
|
||||
static bool classof(const MCInstFragment *) { return true; }
|
||||
|
||||
virtual void dump();
|
||||
};
|
||||
|
||||
class MCAlignFragment : public MCFragment {
|
||||
/// Alignment - The alignment to ensure, in bytes.
|
||||
unsigned Alignment;
|
||||
@ -219,10 +260,6 @@ class MCAlignFragment : public MCFragment {
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
uint64_t getMaxFileSize() const {
|
||||
return std::max(Alignment - 1, MaxBytesToEmit);
|
||||
}
|
||||
|
||||
unsigned getAlignment() const { return Alignment; }
|
||||
|
||||
int64_t getValue() const { return Value; }
|
||||
@ -262,10 +299,6 @@ class MCFillFragment : public MCFragment {
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
uint64_t getMaxFileSize() const {
|
||||
return ValueSize * Count;
|
||||
}
|
||||
|
||||
int64_t getValue() const { return Value; }
|
||||
|
||||
unsigned getValueSize() const { return ValueSize; }
|
||||
@ -297,11 +330,6 @@ class MCOrgFragment : public MCFragment {
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
uint64_t getMaxFileSize() const {
|
||||
// FIXME: This doesn't make much sense.
|
||||
return ~UINT64_C(0);
|
||||
}
|
||||
|
||||
const MCExpr &getOffset() const { return *Offset; }
|
||||
|
||||
uint8_t getValue() const { return Value; }
|
||||
@ -333,11 +361,6 @@ class MCZeroFillFragment : public MCFragment {
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
uint64_t getMaxFileSize() const {
|
||||
// FIXME: This also doesn't make much sense, this method is misnamed.
|
||||
return ~UINT64_C(0);
|
||||
}
|
||||
|
||||
uint64_t getSize() const { return Size; }
|
||||
|
||||
unsigned getAlignment() const { return Alignment; }
|
||||
@ -356,6 +379,8 @@ class MCZeroFillFragment : public MCFragment {
|
||||
// we anticipate the fast path being through an MCAssembler, the only reason to
|
||||
// keep it out is for API abstraction.
|
||||
class MCSectionData : public ilist_node<MCSectionData> {
|
||||
friend class MCAsmLayout;
|
||||
|
||||
MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT
|
||||
void operator=(const MCSectionData&); // DO NOT IMPLEMENT
|
||||
|
||||
@ -372,6 +397,9 @@ class MCSectionData : public ilist_node<MCSectionData> {
|
||||
iplist<MCFragment> Fragments;
|
||||
const MCSection *Section;
|
||||
|
||||
/// Ordinal - The section index in the assemblers section list.
|
||||
unsigned Ordinal;
|
||||
|
||||
/// Alignment - The maximum alignment seen in this section.
|
||||
unsigned Alignment;
|
||||
|
||||
@ -407,6 +435,12 @@ class MCSectionData : public ilist_node<MCSectionData> {
|
||||
unsigned getAlignment() const { return Alignment; }
|
||||
void setAlignment(unsigned Value) { Alignment = Value; }
|
||||
|
||||
bool hasInstructions() const { return HasInstructions; }
|
||||
void setHasInstructions(bool Value) { HasInstructions = Value; }
|
||||
|
||||
unsigned getOrdinal() const { return Ordinal; }
|
||||
void setOrdinal(unsigned Value) { Ordinal = Value; }
|
||||
|
||||
/// @name Fragment Access
|
||||
/// @{
|
||||
|
||||
@ -429,36 +463,9 @@ class MCSectionData : public ilist_node<MCSectionData> {
|
||||
|
||||
bool empty() const { return Fragments.empty(); }
|
||||
|
||||
/// @}
|
||||
/// @name Assembler Backend Support
|
||||
/// @{
|
||||
//
|
||||
// FIXME: This could all be kept private to the assembler implementation.
|
||||
|
||||
uint64_t getAddress() const {
|
||||
assert(Address != ~UINT64_C(0) && "Address not set!");
|
||||
return Address;
|
||||
}
|
||||
void setAddress(uint64_t Value) { Address = Value; }
|
||||
|
||||
uint64_t getSize() const {
|
||||
assert(Size != ~UINT64_C(0) && "File size not set!");
|
||||
return Size;
|
||||
}
|
||||
void setSize(uint64_t Value) { Size = Value; }
|
||||
|
||||
uint64_t getFileSize() const {
|
||||
assert(FileSize != ~UINT64_C(0) && "File size not set!");
|
||||
return FileSize;
|
||||
}
|
||||
void setFileSize(uint64_t Value) { FileSize = Value; }
|
||||
|
||||
bool hasInstructions() const { return HasInstructions; }
|
||||
void setHasInstructions(bool Value) { HasInstructions = Value; }
|
||||
|
||||
/// @}
|
||||
|
||||
void dump();
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
// FIXME: Same concerns as with SectionData.
|
||||
@ -515,11 +522,6 @@ class MCSymbolData : public ilist_node<MCSymbolData> {
|
||||
uint64_t getOffset() const { return Offset; }
|
||||
void setOffset(uint64_t Value) { Offset = Value; }
|
||||
|
||||
uint64_t getAddress() const {
|
||||
assert(getFragment() && "Invalid getAddress() on undefined symbol!");
|
||||
return getFragment()->getAddress() + getOffset();
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Symbol Attributes
|
||||
/// @{
|
||||
@ -578,6 +580,8 @@ struct IndirectSymbolData {
|
||||
};
|
||||
|
||||
class MCAssembler {
|
||||
friend class MCAsmLayout;
|
||||
|
||||
public:
|
||||
typedef iplist<MCSectionData> SectionDataListType;
|
||||
typedef iplist<MCSymbolData> SymbolDataListType;
|
||||
@ -620,6 +624,7 @@ class MCAssembler {
|
||||
|
||||
std::vector<IndirectSymbolData> IndirectSymbols;
|
||||
|
||||
unsigned RelaxAll : 1;
|
||||
unsigned SubsectionsViaSymbols : 1;
|
||||
|
||||
private:
|
||||
@ -637,35 +642,49 @@ class MCAssembler {
|
||||
/// \arg Value result is fixed, otherwise the value may change due to
|
||||
/// relocation.
|
||||
bool EvaluateFixup(const MCAsmLayout &Layout,
|
||||
MCAsmFixup &Fixup, MCDataFragment *DF,
|
||||
const MCAsmFixup &Fixup, const MCFragment *DF,
|
||||
MCValue &Target, uint64_t &Value) const;
|
||||
|
||||
/// Check whether a fixup can be satisfied, or whether it needs to be relaxed
|
||||
/// (increased in size, in order to hold its value correctly).
|
||||
bool FixupNeedsRelaxation(MCAsmFixup &Fixup, MCDataFragment *DF);
|
||||
bool FixupNeedsRelaxation(const MCAsmFixup &Fixup, const MCFragment *DF,
|
||||
const MCAsmLayout &Layout) const;
|
||||
|
||||
/// LayoutSection - Assign offsets and sizes to the fragments in the section
|
||||
/// \arg SD, and update the section size. The section file offset should
|
||||
/// already have been computed.
|
||||
void LayoutSection(MCSectionData &SD);
|
||||
/// Check whether the given fragment needs relaxation.
|
||||
bool FragmentNeedsRelaxation(const MCInstFragment *IF,
|
||||
const MCAsmLayout &Layout) const;
|
||||
|
||||
/// LayoutSection - Assign the section the given \arg StartAddress, and then
|
||||
/// assign offsets and sizes to the fragments in the section \arg SD, and
|
||||
/// update the section size.
|
||||
///
|
||||
/// \return The address at the end of the section, for use in laying out the
|
||||
/// succeeding section.
|
||||
uint64_t LayoutSection(MCSectionData &SD, MCAsmLayout &Layout,
|
||||
uint64_t StartAddress);
|
||||
|
||||
/// LayoutOnce - Perform one layout iteration and return true if any offsets
|
||||
/// were adjusted.
|
||||
bool LayoutOnce();
|
||||
bool LayoutOnce(MCAsmLayout &Layout);
|
||||
|
||||
/// FinishLayout - Finalize a layout, including fragment lowering.
|
||||
void FinishLayout(MCAsmLayout &Layout);
|
||||
|
||||
public:
|
||||
/// Find the symbol which defines the atom containing given address, inside
|
||||
/// the given section, or null if there is no such symbol.
|
||||
//
|
||||
// FIXME: Eliminate this, it is very slow.
|
||||
const MCSymbolData *getAtomForAddress(const MCSectionData *Section,
|
||||
// FIXME-PERF: Eliminate this, it is very slow.
|
||||
const MCSymbolData *getAtomForAddress(const MCAsmLayout &Layout,
|
||||
const MCSectionData *Section,
|
||||
uint64_t Address) const;
|
||||
|
||||
/// Find the symbol which defines the atom containing the given symbol, or
|
||||
/// null if there is no such symbol.
|
||||
//
|
||||
// FIXME: Eliminate this, it is very slow.
|
||||
const MCSymbolData *getAtom(const MCSymbolData *Symbol) const;
|
||||
// FIXME-PERF: Eliminate this, it is very slow.
|
||||
const MCSymbolData *getAtom(const MCAsmLayout &Layout,
|
||||
const MCSymbolData *Symbol) const;
|
||||
|
||||
/// Check whether a particular symbol is visible to the linker and is required
|
||||
/// in the symbol table, or whether it can be discarded by the assembler. This
|
||||
@ -676,7 +695,8 @@ class MCAssembler {
|
||||
/// Emit the section contents using the given object writer.
|
||||
//
|
||||
// FIXME: Should MCAssembler always have a reference to the object writer?
|
||||
void WriteSectionData(const MCSectionData *Section, MCObjectWriter *OW) const;
|
||||
void WriteSectionData(const MCSectionData *Section, const MCAsmLayout &Layout,
|
||||
MCObjectWriter *OW) const;
|
||||
|
||||
public:
|
||||
/// Construct a new assembler instance.
|
||||
@ -708,6 +728,9 @@ class MCAssembler {
|
||||
SubsectionsViaSymbols = Value;
|
||||
}
|
||||
|
||||
bool getRelaxAll() const { return RelaxAll; }
|
||||
void setRelaxAll(bool Value) { RelaxAll = Value; }
|
||||
|
||||
/// @name Section List Access
|
||||
/// @{
|
||||
|
||||
|
@ -65,19 +65,8 @@ namespace llvm {
|
||||
/// reference and return it.
|
||||
///
|
||||
/// @param Name - The symbol name, which must be unique across all symbols.
|
||||
MCSymbol *GetOrCreateSymbol(StringRef Name, bool isTemporary = false);
|
||||
MCSymbol *GetOrCreateSymbol(const Twine &Name, bool isTemporary = false);
|
||||
|
||||
/// 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.
|
||||
MCSymbol *GetOrCreateTemporarySymbol(StringRef Name) {
|
||||
return GetOrCreateSymbol(Name, true);
|
||||
}
|
||||
MCSymbol *GetOrCreateTemporarySymbol(const Twine &Name);
|
||||
MCSymbol *GetOrCreateSymbol(StringRef Name);
|
||||
MCSymbol *GetOrCreateSymbol(const Twine &Name);
|
||||
|
||||
/// LookupSymbol - Get the symbol for \p Name, or null.
|
||||
MCSymbol *LookupSymbol(StringRef Name) const;
|
||||
|
@ -160,11 +160,6 @@ class MCSymbolRefExpr : public MCExpr {
|
||||
static const MCSymbolRefExpr *Create(StringRef Name, VariantKind Kind,
|
||||
MCContext &Ctx);
|
||||
|
||||
/// CreateTemp - Create a reference to an assembler temporary label with the
|
||||
/// specified name.
|
||||
static const MCSymbolRefExpr *CreateTemp(StringRef Name, VariantKind Kind,
|
||||
MCContext &Ctx);
|
||||
|
||||
/// @}
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
@ -17,11 +17,13 @@
|
||||
#define LLVM_MC_MCINST_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
class MCAsmInfo;
|
||||
class MCInstPrinter;
|
||||
class MCExpr;
|
||||
|
||||
/// MCOperand - Instances of this class represent operands of the MCInst class.
|
||||
@ -125,6 +127,13 @@ class MCInst {
|
||||
|
||||
void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
|
||||
void dump() const;
|
||||
|
||||
/// \brief Dump the MCInst as prettily as possible using the additional MC
|
||||
/// structures, if given. Operators are separated by the \arg Separator
|
||||
/// string.
|
||||
void dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI = 0,
|
||||
const MCInstPrinter *Printer = 0,
|
||||
StringRef Separator = " ") const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -16,8 +16,9 @@
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmFixup;
|
||||
class MCAsmLayout;
|
||||
class MCAssembler;
|
||||
class MCDataFragment;
|
||||
class MCFragment;
|
||||
class MCValue;
|
||||
class raw_ostream;
|
||||
|
||||
@ -69,7 +70,8 @@ class MCObjectWriter {
|
||||
/// information about the relocation so that it can be emitted during
|
||||
/// WriteObject().
|
||||
virtual void RecordRelocation(const MCAssembler &Asm,
|
||||
const MCDataFragment &Fragment,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCAsmFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue) = 0;
|
||||
|
||||
@ -78,7 +80,8 @@ class MCObjectWriter {
|
||||
/// This routine is called by the assembler after layout and relaxation is
|
||||
/// complete, fixups have been evaluate and applied, and relocations
|
||||
/// generated.
|
||||
virtual void WriteObject(const MCAssembler &Asm) = 0;
|
||||
virtual void WriteObject(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) = 0;
|
||||
|
||||
/// @}
|
||||
/// @name Binary Output
|
||||
|
@ -42,9 +42,8 @@ namespace llvm {
|
||||
};
|
||||
|
||||
class MCSectionCOFF : public MCSection {
|
||||
// FIXME: This memory is leaked because MCSectionCOFF is bump pointer
|
||||
// allocated and this never gets freed.
|
||||
std::string Name;
|
||||
// The memory for this string is stored in the same MCContext as *this.
|
||||
StringRef Name;
|
||||
|
||||
/// IsDirective - This is true if the section name is a directive, not
|
||||
/// something that should be printed with ".section".
|
||||
@ -61,7 +60,7 @@ namespace llvm {
|
||||
static MCSectionCOFF *Create(StringRef Name, bool IsDirective,
|
||||
SectionKind K, MCContext &Ctx);
|
||||
|
||||
const std::string &getName() const { return Name; }
|
||||
StringRef getName() const { return Name; }
|
||||
bool isDirective() const { return IsDirective; }
|
||||
|
||||
virtual void PrintSwitchToSection(const MCAsmInfo &MAI,
|
||||
|
@ -88,7 +88,7 @@ class TargetAsmBackend;
|
||||
/// @name Symbol & Section Management
|
||||
/// @{
|
||||
|
||||
/// getCurrentSection - Return the current seciton that the streamer is
|
||||
/// getCurrentSection - Return the current section that the streamer is
|
||||
/// emitting code to.
|
||||
const MCSection *getCurrentSection() const { return CurSection; }
|
||||
|
||||
@ -308,7 +308,8 @@ class TargetAsmBackend;
|
||||
/// createMachOStream - Create a machine code streamer which will generative
|
||||
/// Mach-O format object files.
|
||||
MCStreamer *createMachOStreamer(MCContext &Ctx, TargetAsmBackend &TAB,
|
||||
raw_ostream &OS, MCCodeEmitter *CE);
|
||||
raw_ostream &OS, MCCodeEmitter *CE,
|
||||
bool RelaxAll = false);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
namespace llvm {
|
||||
class MCAsmFixup;
|
||||
class MCAssembler;
|
||||
class MCDataFragment;
|
||||
class MCFragment;
|
||||
class MCValue;
|
||||
class raw_ostream;
|
||||
|
||||
@ -31,11 +31,12 @@ class MachObjectWriter : public MCObjectWriter {
|
||||
virtual void ExecutePostLayoutBinding(MCAssembler &Asm);
|
||||
|
||||
virtual void RecordRelocation(const MCAssembler &Asm,
|
||||
const MCDataFragment &Fragment,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCAsmFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue);
|
||||
|
||||
virtual void WriteObject(const MCAssembler &Asm);
|
||||
virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -413,7 +413,6 @@ class PMDataManager {
|
||||
/// It batches all function passes and basic block pass managers together and
|
||||
/// sequence them to process one function at a time before processing next
|
||||
/// function.
|
||||
|
||||
class FPPassManager : public ModulePass, public PMDataManager {
|
||||
public:
|
||||
static char ID;
|
||||
@ -462,8 +461,7 @@ class FPPassManager : public ModulePass, public PMDataManager {
|
||||
}
|
||||
};
|
||||
|
||||
extern Timer *StartPassTimer(Pass *);
|
||||
extern void StopPassTimer(Pass *, Timer *);
|
||||
Timer *getPassTimer(Pass *);
|
||||
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,7 @@ class BumpPtrAllocator {
|
||||
|
||||
static MallocSlabAllocator DefaultSlabAllocator;
|
||||
|
||||
template<typename T> friend class SpecificBumpPtrAllocator;
|
||||
public:
|
||||
BumpPtrAllocator(size_t size = 4096, size_t threshold = 4096,
|
||||
SlabAllocator &allocator = DefaultSlabAllocator);
|
||||
@ -176,6 +177,45 @@ class BumpPtrAllocator {
|
||||
void PrintStats() const;
|
||||
};
|
||||
|
||||
/// SpecificBumpPtrAllocator - Same as BumpPtrAllocator but allows only
|
||||
/// elements of one type to be allocated. This allows calling the destructor
|
||||
/// in DestroyAll() and when the allocator is destroyed.
|
||||
template <typename T>
|
||||
class SpecificBumpPtrAllocator {
|
||||
BumpPtrAllocator Allocator;
|
||||
public:
|
||||
SpecificBumpPtrAllocator(size_t size = 4096, size_t threshold = 4096,
|
||||
SlabAllocator &allocator = BumpPtrAllocator::DefaultSlabAllocator)
|
||||
: Allocator(size, threshold, allocator) {}
|
||||
|
||||
~SpecificBumpPtrAllocator() {
|
||||
DestroyAll();
|
||||
}
|
||||
|
||||
/// Call the destructor of each allocated object and deallocate all but the
|
||||
/// current slab and reset the current pointer to the beginning of it, freeing
|
||||
/// all memory allocated so far.
|
||||
void DestroyAll() {
|
||||
MemSlab *Slab = Allocator.CurSlab;
|
||||
while (Slab) {
|
||||
char *End = Slab == Allocator.CurSlab ? Allocator.CurPtr :
|
||||
(char *)Slab + Slab->Size;
|
||||
for (char *Ptr = (char*)Slab+1; Ptr < End; Ptr += sizeof(T)) {
|
||||
Ptr = Allocator.AlignPtr(Ptr, alignof<T>());
|
||||
if (Ptr + sizeof(T) <= End)
|
||||
reinterpret_cast<T*>(Ptr)->~T();
|
||||
}
|
||||
Slab = Slab->NextPtr;
|
||||
}
|
||||
Allocator.Reset();
|
||||
}
|
||||
|
||||
/// Allocate space for a specific count of elements.
|
||||
T *Allocate(size_t num = 1) {
|
||||
return Allocator.Allocate<T>(num);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) {
|
||||
|
@ -67,15 +67,15 @@ class PredIterator : public std::iterator<std::forward_iterator_tag,
|
||||
|
||||
typedef PredIterator<BasicBlock, Value::use_iterator> pred_iterator;
|
||||
typedef PredIterator<const BasicBlock,
|
||||
Value::use_const_iterator> pred_const_iterator;
|
||||
Value::const_use_iterator> const_pred_iterator;
|
||||
|
||||
inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); }
|
||||
inline pred_const_iterator pred_begin(const BasicBlock *BB) {
|
||||
return pred_const_iterator(BB);
|
||||
inline const_pred_iterator pred_begin(const BasicBlock *BB) {
|
||||
return const_pred_iterator(BB);
|
||||
}
|
||||
inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);}
|
||||
inline pred_const_iterator pred_end(const BasicBlock *BB) {
|
||||
return pred_const_iterator(BB, true);
|
||||
inline const_pred_iterator pred_end(const BasicBlock *BB) {
|
||||
return const_pred_iterator(BB, true);
|
||||
}
|
||||
|
||||
|
||||
@ -268,7 +268,7 @@ template <> struct GraphTraits<Inverse<BasicBlock*> > {
|
||||
|
||||
template <> struct GraphTraits<Inverse<const BasicBlock*> > {
|
||||
typedef const BasicBlock NodeType;
|
||||
typedef pred_const_iterator ChildIteratorType;
|
||||
typedef const_pred_iterator ChildIteratorType;
|
||||
static NodeType *getEntryNode(Inverse<const BasicBlock*> G) {
|
||||
return G.Graph;
|
||||
}
|
||||
|
@ -8,15 +8,18 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the CallSite class, which is a handy wrapper for code that
|
||||
// wants to treat Call and Invoke instructions in a generic way.
|
||||
// wants to treat Call and Invoke instructions in a generic way. When in non-
|
||||
// mutation context (e.g. an analysis) ImmutableCallSite should be used.
|
||||
// Finally, when some degree of customization is necessary between these two
|
||||
// extremes, CallSiteBase<> can be supplied with fine-tuned parameters.
|
||||
//
|
||||
// NOTE: This class is supposed to have "value semantics". So it should be
|
||||
// passed by value, not by reference; it should not be "new"ed or "delete"d. It
|
||||
// is efficiently copyable, assignable and constructable, with cost equivalent
|
||||
// to copying a pointer (notice that it has only a single data member).
|
||||
// The internal representation carries a flag which indicates which of the two
|
||||
// variants is enclosed. This allows for cheaper checks when various accessors
|
||||
// of CallSite are employed.
|
||||
// NOTE: These classes are supposed to have "value semantics". So they should be
|
||||
// passed by value, not by reference; they should not be "new"ed or "delete"d.
|
||||
// They are efficiently copyable, assignable and constructable, with cost
|
||||
// equivalent to copying a pointer (notice that they have only a single data
|
||||
// member). The internal representation carries a flag which indicates which of
|
||||
// the two variants is enclosed. This allows for cheaper checks when various
|
||||
// accessors of CallSite are employed.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -34,13 +37,166 @@ namespace llvm {
|
||||
class CallInst;
|
||||
class InvokeInst;
|
||||
|
||||
class CallSite {
|
||||
PointerIntPair<Instruction*, 1, bool> I;
|
||||
template <typename FunTy = const Function,
|
||||
typename ValTy = const Value,
|
||||
typename UserTy = const User,
|
||||
typename InstrTy = const Instruction,
|
||||
typename CallTy = const CallInst,
|
||||
typename InvokeTy = const InvokeInst,
|
||||
typename IterTy = User::const_op_iterator>
|
||||
class CallSiteBase {
|
||||
protected:
|
||||
PointerIntPair<InstrTy*, 1, bool> I;
|
||||
public:
|
||||
CallSite() : I(0, false) {}
|
||||
CallSite(CallInst *CI) : I(reinterpret_cast<Instruction*>(CI), true) {}
|
||||
CallSite(InvokeInst *II) : I(reinterpret_cast<Instruction*>(II), false) {}
|
||||
CallSite(Instruction *C);
|
||||
CallSiteBase() : I(0, false) {}
|
||||
CallSiteBase(CallTy *CI) : I(reinterpret_cast<InstrTy*>(CI), true) {}
|
||||
CallSiteBase(InvokeTy *II) : I(reinterpret_cast<InstrTy*>(II), false) {}
|
||||
CallSiteBase(ValTy *II) { *this = get(II); }
|
||||
CallSiteBase(InstrTy *II) {
|
||||
assert(II && "Null instruction given?");
|
||||
*this = get(II);
|
||||
assert(I.getPointer());
|
||||
}
|
||||
|
||||
/// CallSiteBase::get - This static method is sort of like a constructor. It
|
||||
/// will create an appropriate call site for a Call or Invoke instruction, but
|
||||
/// it can also create a null initialized CallSiteBase object for something
|
||||
/// which is NOT a call site.
|
||||
///
|
||||
static CallSiteBase get(ValTy *V) {
|
||||
if (InstrTy *II = dyn_cast<InstrTy>(V)) {
|
||||
if (II->getOpcode() == Instruction::Call)
|
||||
return CallSiteBase(reinterpret_cast<CallTy*>(II));
|
||||
else if (II->getOpcode() == Instruction::Invoke)
|
||||
return CallSiteBase(reinterpret_cast<InvokeTy*>(II));
|
||||
}
|
||||
return CallSiteBase();
|
||||
}
|
||||
|
||||
/// isCall - true if a CallInst is enclosed.
|
||||
/// Note that !isCall() does not mean it is an InvokeInst enclosed,
|
||||
/// it also could signify a NULL Instruction pointer.
|
||||
bool isCall() const { return I.getInt(); }
|
||||
|
||||
/// isInvoke - true if a InvokeInst is enclosed.
|
||||
///
|
||||
bool isInvoke() const { return getInstruction() && !I.getInt(); }
|
||||
|
||||
InstrTy *getInstruction() const { return I.getPointer(); }
|
||||
InstrTy *operator->() const { return I.getPointer(); }
|
||||
operator bool() const { return I.getPointer(); }
|
||||
|
||||
/// getCalledValue - Return the pointer to function that is being called...
|
||||
///
|
||||
ValTy *getCalledValue() const {
|
||||
assert(getInstruction() && "Not a call or invoke instruction!");
|
||||
return *getCallee();
|
||||
}
|
||||
|
||||
/// getCalledFunction - Return the function being called if this is a direct
|
||||
/// call, otherwise return null (if it's an indirect call).
|
||||
///
|
||||
FunTy *getCalledFunction() const {
|
||||
return dyn_cast<FunTy>(getCalledValue());
|
||||
}
|
||||
|
||||
/// setCalledFunction - Set the callee to the specified value...
|
||||
///
|
||||
void setCalledFunction(Value *V) {
|
||||
assert(getInstruction() && "Not a call or invoke instruction!");
|
||||
*getCallee() = V;
|
||||
}
|
||||
|
||||
/// isCallee - Determine whether the passed iterator points to the
|
||||
/// callee operand's Use.
|
||||
///
|
||||
bool isCallee(value_use_iterator<UserTy> UI) const {
|
||||
return getCallee() == &UI.getUse();
|
||||
}
|
||||
|
||||
ValTy *getArgument(unsigned ArgNo) const {
|
||||
assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!");
|
||||
return *(arg_begin()+ArgNo);
|
||||
}
|
||||
|
||||
void setArgument(unsigned ArgNo, Value* newVal) {
|
||||
assert(getInstruction() && "Not a call or invoke instruction!");
|
||||
assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!");
|
||||
getInstruction()->setOperand(getArgumentOffset() + ArgNo, newVal);
|
||||
}
|
||||
|
||||
/// Given a value use iterator, returns the argument that corresponds to it.
|
||||
/// Iterator must actually correspond to an argument.
|
||||
unsigned getArgumentNo(value_use_iterator<UserTy> I) const {
|
||||
assert(getInstruction() && "Not a call or invoke instruction!");
|
||||
assert(arg_begin() <= &I.getUse() && &I.getUse() < arg_end()
|
||||
&& "Argument # out of range!");
|
||||
return &I.getUse() - arg_begin();
|
||||
}
|
||||
|
||||
/// arg_iterator - The type of iterator to use when looping over actual
|
||||
/// arguments at this call site...
|
||||
typedef IterTy arg_iterator;
|
||||
|
||||
/// arg_begin/arg_end - Return iterators corresponding to the actual argument
|
||||
/// list for a call site.
|
||||
IterTy arg_begin() const {
|
||||
assert(getInstruction() && "Not a call or invoke instruction!");
|
||||
// Skip non-arguments
|
||||
return (*this)->op_begin() + getArgumentOffset();
|
||||
}
|
||||
|
||||
IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); }
|
||||
bool arg_empty() const { return arg_end() == arg_begin(); }
|
||||
unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); }
|
||||
|
||||
private:
|
||||
/// Returns the operand number of the first argument
|
||||
unsigned getArgumentOffset() const {
|
||||
if (isCall())
|
||||
return 1; // Skip Function (ATM)
|
||||
else
|
||||
return 0; // Args are at the front
|
||||
}
|
||||
|
||||
unsigned getArgumentEndOffset() const {
|
||||
if (isCall())
|
||||
return 0; // Unchanged (ATM)
|
||||
else
|
||||
return 3; // Skip BB, BB, Function
|
||||
}
|
||||
|
||||
IterTy getCallee() const {
|
||||
// FIXME: this is slow, since we do not have the fast versions
|
||||
// of the op_*() functions here. See CallSite::getCallee.
|
||||
//
|
||||
if (isCall())
|
||||
return getInstruction()->op_begin(); // Unchanged (ATM)
|
||||
else
|
||||
return getInstruction()->op_end() - 3; // Skip BB, BB, Function
|
||||
}
|
||||
};
|
||||
|
||||
/// ImmutableCallSite - establish a view to a call site for examination
|
||||
class ImmutableCallSite : public CallSiteBase<> {
|
||||
typedef CallSiteBase<> _Base;
|
||||
public:
|
||||
ImmutableCallSite(const Value* V) : _Base(V) {}
|
||||
ImmutableCallSite(const CallInst *CI) : _Base(CI) {}
|
||||
ImmutableCallSite(const InvokeInst *II) : _Base(II) {}
|
||||
ImmutableCallSite(const Instruction *II) : _Base(II) {}
|
||||
};
|
||||
|
||||
class CallSite : public CallSiteBase<Function, Value, User, Instruction,
|
||||
CallInst, InvokeInst, User::op_iterator> {
|
||||
typedef CallSiteBase<Function, Value, User, Instruction,
|
||||
CallInst, InvokeInst, User::op_iterator> _Base;
|
||||
public:
|
||||
CallSite() {}
|
||||
CallSite(_Base B) : _Base(B) {}
|
||||
CallSite(CallInst *CI) : _Base(CI) {}
|
||||
CallSite(InvokeInst *II) : _Base(II) {}
|
||||
CallSite(Instruction *II) : _Base(II) {}
|
||||
|
||||
bool operator==(const CallSite &CS) const { return I == CS.I; }
|
||||
bool operator!=(const CallSite &CS) const { return I != CS.I; }
|
||||
@ -51,13 +207,7 @@ class CallSite {
|
||||
/// NOT a call site.
|
||||
///
|
||||
static CallSite get(Value *V) {
|
||||
if (Instruction *I = dyn_cast<Instruction>(V)) {
|
||||
if (I->getOpcode() == Instruction::Call)
|
||||
return CallSite(reinterpret_cast<CallInst*>(I));
|
||||
else if (I->getOpcode() == Instruction::Invoke)
|
||||
return CallSite(reinterpret_cast<InvokeInst*>(I));
|
||||
}
|
||||
return CallSite();
|
||||
return _Base::get(V);
|
||||
}
|
||||
|
||||
/// getCallingConv/setCallingConv - get or set the calling convention of the
|
||||
@ -76,6 +226,10 @@ class CallSite {
|
||||
/// @brief Extract the alignment for a call or parameter (0=unknown).
|
||||
uint16_t getParamAlignment(uint16_t i) const;
|
||||
|
||||
/// @brief Return true if the call should not be inlined.
|
||||
bool isNoInline() const;
|
||||
void setIsNoInline(bool Value = true);
|
||||
|
||||
/// @brief Determine if the call does not access memory.
|
||||
bool doesNotAccessMemory() const;
|
||||
void setDoesNotAccessMemory(bool doesNotAccessMemory = true);
|
||||
@ -94,103 +248,22 @@ class CallSite {
|
||||
|
||||
/// getType - Return the type of the instruction that generated this call site
|
||||
///
|
||||
const Type *getType() const { return getInstruction()->getType(); }
|
||||
|
||||
/// isCall - true if a CallInst is enclosed.
|
||||
/// Note that !isCall() does not mean it is an InvokeInst enclosed,
|
||||
/// it also could signify a NULL Instruction pointer.
|
||||
bool isCall() const { return I.getInt(); }
|
||||
|
||||
/// isInvoke - true if a InvokeInst is enclosed.
|
||||
///
|
||||
bool isInvoke() const { return getInstruction() && !I.getInt(); }
|
||||
|
||||
/// getInstruction - Return the instruction this call site corresponds to
|
||||
///
|
||||
Instruction *getInstruction() const { return I.getPointer(); }
|
||||
const Type *getType() const { return (*this)->getType(); }
|
||||
|
||||
/// getCaller - Return the caller function for this call site
|
||||
///
|
||||
Function *getCaller() const { return getInstruction()
|
||||
->getParent()->getParent(); }
|
||||
|
||||
/// getCalledValue - Return the pointer to function that is being called...
|
||||
///
|
||||
Value *getCalledValue() const {
|
||||
assert(getInstruction() && "Not a call or invoke instruction!");
|
||||
return getInstruction()->getOperand(0);
|
||||
}
|
||||
|
||||
/// getCalledFunction - Return the function being called if this is a direct
|
||||
/// call, otherwise return null (if it's an indirect call).
|
||||
///
|
||||
Function *getCalledFunction() const {
|
||||
return dyn_cast<Function>(getCalledValue());
|
||||
}
|
||||
|
||||
/// setCalledFunction - Set the callee to the specified value...
|
||||
///
|
||||
void setCalledFunction(Value *V) {
|
||||
assert(getInstruction() && "Not a call or invoke instruction!");
|
||||
getInstruction()->setOperand(0, V);
|
||||
}
|
||||
|
||||
Value *getArgument(unsigned ArgNo) const {
|
||||
assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!");
|
||||
return *(arg_begin()+ArgNo);
|
||||
}
|
||||
|
||||
void setArgument(unsigned ArgNo, Value* newVal) {
|
||||
assert(getInstruction() && "Not a call or invoke instruction!");
|
||||
assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!");
|
||||
getInstruction()->setOperand(getArgumentOffset() + ArgNo, newVal);
|
||||
}
|
||||
|
||||
/// Given an operand number, returns the argument that corresponds to it.
|
||||
/// OperandNo must be a valid operand number that actually corresponds to an
|
||||
/// argument.
|
||||
unsigned getArgumentNo(unsigned OperandNo) const {
|
||||
assert(OperandNo >= getArgumentOffset() && "Operand number passed was not "
|
||||
"a valid argument");
|
||||
return OperandNo - getArgumentOffset();
|
||||
}
|
||||
Function *getCaller() const { return (*this)->getParent()->getParent(); }
|
||||
|
||||
/// hasArgument - Returns true if this CallSite passes the given Value* as an
|
||||
/// argument to the called function.
|
||||
bool hasArgument(const Value *Arg) const;
|
||||
|
||||
/// arg_iterator - The type of iterator to use when looping over actual
|
||||
/// arguments at this call site...
|
||||
typedef User::op_iterator arg_iterator;
|
||||
|
||||
/// arg_begin/arg_end - Return iterators corresponding to the actual argument
|
||||
/// list for a call site.
|
||||
arg_iterator arg_begin() const {
|
||||
assert(getInstruction() && "Not a call or invoke instruction!");
|
||||
// Skip non-arguments
|
||||
return getInstruction()->op_begin() + getArgumentOffset();
|
||||
}
|
||||
|
||||
arg_iterator arg_end() const { return getInstruction()->op_end(); }
|
||||
bool arg_empty() const { return arg_end() == arg_begin(); }
|
||||
unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); }
|
||||
|
||||
bool operator<(const CallSite &CS) const {
|
||||
return getInstruction() < CS.getInstruction();
|
||||
}
|
||||
|
||||
bool isCallee(Value::use_iterator UI) const {
|
||||
return getInstruction()->op_begin() == &UI.getUse();
|
||||
}
|
||||
|
||||
private:
|
||||
/// Returns the operand number of the first argument
|
||||
unsigned getArgumentOffset() const {
|
||||
if (isCall())
|
||||
return 1; // Skip Function
|
||||
else
|
||||
return 3; // Skip Function, BB, BB
|
||||
}
|
||||
User::op_iterator getCallee() const;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -50,9 +50,11 @@ template<typename From> struct simplify_type<const From> {
|
||||
// if (isa<Type*>(myVal)) { ... }
|
||||
//
|
||||
template <typename To, typename From>
|
||||
inline bool isa_impl(const From &Val) {
|
||||
return To::classof(&Val);
|
||||
}
|
||||
struct isa_impl {
|
||||
static inline bool doit(const From &Val) {
|
||||
return To::classof(&Val);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, typename From, typename SimpleType>
|
||||
struct isa_impl_wrap {
|
||||
@ -68,7 +70,7 @@ template<typename To, typename FromTy>
|
||||
struct isa_impl_wrap<To, const FromTy, const FromTy> {
|
||||
// When From == SimpleType, we are as simple as we are going to get.
|
||||
static bool doit(const FromTy &Val) {
|
||||
return isa_impl<To,FromTy>(Val);
|
||||
return isa_impl<To,FromTy>::doit(Val);
|
||||
}
|
||||
};
|
||||
|
||||
@ -251,10 +253,12 @@ struct foo {
|
||||
}*/
|
||||
};
|
||||
|
||||
template <> inline bool isa_impl<foo,bar>(const bar &Val) {
|
||||
dbgs() << "Classof: " << &Val << "\n";
|
||||
return true;
|
||||
}
|
||||
template <> struct isa_impl<foo,bar> {
|
||||
static inline bool doit(const bar &Val) {
|
||||
dbgs() << "Classof: " << &Val << "\n";
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
bar *fub();
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===---- llvm/DebugLoc.h - Debug Location Information ----------*- C++ -*-===//
|
||||
//===---- llvm/Support/DebugLoc.h - Debug Location Information --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -20,12 +20,71 @@
|
||||
|
||||
namespace llvm {
|
||||
class MDNode;
|
||||
class LLVMContext;
|
||||
|
||||
/// DebugLoc - Debug location id. This is carried by Instruction, SDNode,
|
||||
/// and MachineInstr to compactly encode file/line/scope information for an
|
||||
/// operation.
|
||||
class NewDebugLoc {
|
||||
/// LineCol - This 32-bit value encodes the line and column number for the
|
||||
/// location, encoded as 24-bits for line and 8 bits for col. A value of 0
|
||||
/// for either means unknown.
|
||||
unsigned LineCol;
|
||||
|
||||
/// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information,
|
||||
/// decoded by LLVMContext. 0 is unknown.
|
||||
int ScopeIdx;
|
||||
public:
|
||||
NewDebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown.
|
||||
|
||||
/// get - Get a new DebugLoc that corresponds to the specified line/col
|
||||
/// scope/inline location.
|
||||
static NewDebugLoc get(unsigned Line, unsigned Col,
|
||||
MDNode *Scope, MDNode *InlinedAt = 0);
|
||||
|
||||
/// getFromDILocation - Translate the DILocation quad into a NewDebugLoc.
|
||||
static NewDebugLoc getFromDILocation(MDNode *N);
|
||||
|
||||
/// isUnknown - Return true if this is an unknown location.
|
||||
bool isUnknown() const { return ScopeIdx == 0; }
|
||||
|
||||
unsigned getLine() const {
|
||||
return (LineCol << 8) >> 8; // Mask out column.
|
||||
}
|
||||
|
||||
unsigned getCol() const {
|
||||
return LineCol >> 24;
|
||||
}
|
||||
|
||||
/// getScope - This returns the scope pointer for this DebugLoc, or null if
|
||||
/// invalid.
|
||||
MDNode *getScope(const LLVMContext &Ctx) const;
|
||||
|
||||
/// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or
|
||||
/// null if invalid or not present.
|
||||
MDNode *getInlinedAt(const LLVMContext &Ctx) const;
|
||||
|
||||
/// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values.
|
||||
void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
|
||||
const LLVMContext &Ctx) const;
|
||||
|
||||
|
||||
/// getAsMDNode - This method converts the compressed DebugLoc node into a
|
||||
/// DILocation compatible MDNode.
|
||||
MDNode *getAsMDNode(const LLVMContext &Ctx) const;
|
||||
|
||||
bool operator==(const NewDebugLoc &DL) const {
|
||||
return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx;
|
||||
}
|
||||
bool operator!=(const NewDebugLoc &DL) const { return !(*this == DL); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// DebugLoc - Debug location id. This is carried by SDNode and MachineInstr
|
||||
/// to index into a vector of unique debug location tuples.
|
||||
class DebugLoc {
|
||||
unsigned Idx;
|
||||
|
||||
public:
|
||||
DebugLoc() : Idx(~0U) {} // Defaults to invalid.
|
||||
|
||||
@ -42,7 +101,7 @@ namespace llvm {
|
||||
bool operator!=(const DebugLoc &DL) const { return !(*this == DL); }
|
||||
};
|
||||
|
||||
/// DebugLocTracker - This class tracks debug location information.
|
||||
/// DebugLocTracker - This class tracks debug location information.
|
||||
///
|
||||
struct DebugLocTracker {
|
||||
/// DebugLocations - A vector of unique DebugLocTuple's.
|
||||
|
@ -40,6 +40,8 @@ namespace llvm {
|
||||
sys::Path Filename;
|
||||
bool DeleteIt;
|
||||
public:
|
||||
FileRemover() : DeleteIt(false) {}
|
||||
|
||||
explicit FileRemover(const sys::Path &filename, bool deleteIt = true)
|
||||
: Filename(filename), DeleteIt(deleteIt) {}
|
||||
|
||||
@ -50,6 +52,17 @@ namespace llvm {
|
||||
}
|
||||
}
|
||||
|
||||
/// setFile - Give ownership of the file to the FileRemover so it will
|
||||
/// be removed when the object is destroyed. If the FileRemover already
|
||||
/// had ownership of a file, remove it first.
|
||||
void setFile(const sys::Path &filename, bool deleteIt = true) {
|
||||
if (DeleteIt)
|
||||
Filename.eraseFromDisk();
|
||||
|
||||
Filename = filename;
|
||||
DeleteIt = deleteIt;
|
||||
}
|
||||
|
||||
/// releaseFile - Take ownership of the file away from the FileRemover so it
|
||||
/// will not be removed when the object is destroyed.
|
||||
void releaseFile() { DeleteIt = false; }
|
||||
|
@ -40,8 +40,7 @@ class IRBuilderDefaultInserter {
|
||||
|
||||
/// IRBuilderBase - Common base class shared among various IRBuilders.
|
||||
class IRBuilderBase {
|
||||
unsigned DbgMDKind;
|
||||
MDNode *CurDbgLocation;
|
||||
NewDebugLoc CurDbgLocation;
|
||||
protected:
|
||||
BasicBlock *BB;
|
||||
BasicBlock::iterator InsertPt;
|
||||
@ -49,7 +48,7 @@ class IRBuilderBase {
|
||||
public:
|
||||
|
||||
IRBuilderBase(LLVMContext &context)
|
||||
: DbgMDKind(0), CurDbgLocation(0), Context(context) {
|
||||
: Context(context) {
|
||||
ClearInsertionPoint();
|
||||
}
|
||||
|
||||
@ -65,6 +64,7 @@ class IRBuilderBase {
|
||||
|
||||
BasicBlock *GetInsertBlock() const { return BB; }
|
||||
BasicBlock::iterator GetInsertPoint() const { return InsertPt; }
|
||||
LLVMContext &getContext() const { return Context; }
|
||||
|
||||
/// SetInsertPoint - This specifies that created instructions should be
|
||||
/// appended to the end of the specified block.
|
||||
@ -82,12 +82,20 @@ class IRBuilderBase {
|
||||
|
||||
/// SetCurrentDebugLocation - Set location information used by debugging
|
||||
/// information.
|
||||
void SetCurrentDebugLocation(MDNode *L);
|
||||
MDNode *getCurrentDebugLocation() const { return CurDbgLocation; }
|
||||
void SetCurrentDebugLocation(const NewDebugLoc &L) {
|
||||
CurDbgLocation = L;
|
||||
}
|
||||
|
||||
/// getCurrentDebugLocation - Get location information used by debugging
|
||||
/// information.
|
||||
const NewDebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; }
|
||||
|
||||
/// SetInstDebugLocation - If this builder has a current debug location, set
|
||||
/// it on the specified instruction.
|
||||
void SetInstDebugLocation(Instruction *I) const;
|
||||
void SetInstDebugLocation(Instruction *I) const {
|
||||
if (!CurDbgLocation.isUnknown())
|
||||
I->setDebugLoc(CurDbgLocation);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Miscellaneous creation methods.
|
||||
@ -208,7 +216,7 @@ class IRBuilder : public IRBuilderBase, public Inserter {
|
||||
template<typename InstTy>
|
||||
InstTy *Insert(InstTy *I, const Twine &Name = "") const {
|
||||
this->InsertHelper(I, Name, BB, InsertPt);
|
||||
if (getCurrentDebugLocation() != 0)
|
||||
if (!getCurrentDebugLocation().isUnknown())
|
||||
this->SetInstDebugLocation(I);
|
||||
return I;
|
||||
}
|
||||
|
@ -32,35 +32,43 @@ inline uint32_t Lo_32(uint64_t Value) {
|
||||
return static_cast<uint32_t>(Value);
|
||||
}
|
||||
|
||||
/// is?Type - these functions produce optimal testing for integer data types.
|
||||
inline bool isInt8 (int64_t Value) {
|
||||
return static_cast<int8_t>(Value) == Value;
|
||||
}
|
||||
inline bool isUInt8 (int64_t Value) {
|
||||
return static_cast<uint8_t>(Value) == Value;
|
||||
}
|
||||
inline bool isInt16 (int64_t Value) {
|
||||
return static_cast<int16_t>(Value) == Value;
|
||||
}
|
||||
inline bool isUInt16(int64_t Value) {
|
||||
return static_cast<uint16_t>(Value) == Value;
|
||||
}
|
||||
inline bool isInt32 (int64_t Value) {
|
||||
return static_cast<int32_t>(Value) == Value;
|
||||
}
|
||||
inline bool isUInt32(int64_t Value) {
|
||||
return static_cast<uint32_t>(Value) == Value;
|
||||
}
|
||||
|
||||
/// isInt - Checks if an integer fits into the given bit width.
|
||||
template<unsigned N>
|
||||
inline bool isInt(int64_t x) {
|
||||
return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1)));
|
||||
}
|
||||
// Template specializations to get better code for common cases.
|
||||
template<>
|
||||
inline bool isInt<8>(int64_t x) {
|
||||
return static_cast<int8_t>(x) == x;
|
||||
}
|
||||
template<>
|
||||
inline bool isInt<16>(int64_t x) {
|
||||
return static_cast<int16_t>(x) == x;
|
||||
}
|
||||
template<>
|
||||
inline bool isInt<32>(int64_t x) {
|
||||
return static_cast<int32_t>(x) == x;
|
||||
}
|
||||
|
||||
/// isUInt - Checks if an unsigned integer fits into the given bit width.
|
||||
template<unsigned N>
|
||||
inline bool isUint(uint64_t x) {
|
||||
inline bool isUInt(uint64_t x) {
|
||||
return N >= 64 || x < (UINT64_C(1)<<N);
|
||||
}
|
||||
// Template specializations to get better code for common cases.
|
||||
template<>
|
||||
inline bool isUInt<8>(uint64_t x) {
|
||||
return static_cast<uint8_t>(x) == x;
|
||||
}
|
||||
template<>
|
||||
inline bool isUInt<16>(uint64_t x) {
|
||||
return static_cast<uint16_t>(x) == x;
|
||||
}
|
||||
template<>
|
||||
inline bool isUInt<32>(uint64_t x) {
|
||||
return static_cast<uint32_t>(x) == x;
|
||||
}
|
||||
|
||||
/// isMask_32 - This function returns true if the argument is a sequence of ones
|
||||
/// starting at the least significant bit with the remainder zero (32 bit
|
||||
|
@ -16,16 +16,63 @@
|
||||
#define LLVM_SUPPORT_TIMER_H
|
||||
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include "llvm/System/Mutex.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Timer;
|
||||
class TimerGroup;
|
||||
class raw_ostream;
|
||||
|
||||
class TimeRecord {
|
||||
double WallTime; // Wall clock time elapsed in seconds
|
||||
double UserTime; // User time elapsed
|
||||
double SystemTime; // System time elapsed
|
||||
ssize_t MemUsed; // Memory allocated (in bytes)
|
||||
public:
|
||||
TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {}
|
||||
|
||||
/// getCurrentTime - Get the current time and memory usage. If Start is true
|
||||
/// we get the memory usage before the time, otherwise we get time before
|
||||
/// memory usage. This matters if the time to get the memory usage is
|
||||
/// significant and shouldn't be counted as part of a duration.
|
||||
static TimeRecord getCurrentTime(bool Start = true);
|
||||
|
||||
double getProcessTime() const { return UserTime+SystemTime; }
|
||||
double getUserTime() const { return UserTime; }
|
||||
double getSystemTime() const { return SystemTime; }
|
||||
double getWallTime() const { return WallTime; }
|
||||
ssize_t getMemUsed() const { return MemUsed; }
|
||||
|
||||
|
||||
// operator< - Allow sorting.
|
||||
bool operator<(const TimeRecord &T) const {
|
||||
// Sort by Wall Time elapsed, as it is the only thing really accurate
|
||||
return WallTime < T.WallTime;
|
||||
}
|
||||
|
||||
void operator+=(const TimeRecord &RHS) {
|
||||
WallTime += RHS.WallTime;
|
||||
UserTime += RHS.UserTime;
|
||||
SystemTime += RHS.SystemTime;
|
||||
MemUsed += RHS.MemUsed;
|
||||
}
|
||||
void operator-=(const TimeRecord &RHS) {
|
||||
WallTime -= RHS.WallTime;
|
||||
UserTime -= RHS.UserTime;
|
||||
SystemTime -= RHS.SystemTime;
|
||||
MemUsed -= RHS.MemUsed;
|
||||
}
|
||||
|
||||
/// print - Print the current timer to standard error, and reset the "Started"
|
||||
/// flag.
|
||||
void print(const TimeRecord &Total, raw_ostream &OS) const;
|
||||
};
|
||||
|
||||
/// Timer - This class is used to track the amount of time spent between
|
||||
/// invocations of its startTimer()/stopTimer() methods. Given appropriate OS
|
||||
/// support it can also keep track of the RSS of the program at various points.
|
||||
@ -35,65 +82,32 @@ class raw_ostream;
|
||||
/// if they are never started.
|
||||
///
|
||||
class Timer {
|
||||
double Elapsed; // Wall clock time elapsed in seconds
|
||||
double UserTime; // User time elapsed
|
||||
double SystemTime; // System time elapsed
|
||||
ssize_t MemUsed; // Memory allocated (in bytes)
|
||||
size_t PeakMem; // Peak memory used
|
||||
size_t PeakMemBase; // Temporary for peak calculation...
|
||||
std::string Name; // The name of this time variable
|
||||
TimeRecord Time;
|
||||
std::string Name; // The name of this time variable.
|
||||
bool Started; // Has this time variable ever been started?
|
||||
TimerGroup *TG; // The TimerGroup this Timer is in.
|
||||
mutable sys::SmartMutex<true> Lock; // Mutex for the contents of this Timer.
|
||||
|
||||
Timer **Prev, *Next; // Doubly linked list of timers in the group.
|
||||
public:
|
||||
explicit Timer(const std::string &N);
|
||||
Timer(const std::string &N, TimerGroup &tg);
|
||||
Timer(const Timer &T);
|
||||
~Timer();
|
||||
|
||||
double getProcessTime() const { return UserTime+SystemTime; }
|
||||
double getWallTime() const { return Elapsed; }
|
||||
ssize_t getMemUsed() const { return MemUsed; }
|
||||
size_t getPeakMem() const { return PeakMem; }
|
||||
std::string getName() const { return Name; }
|
||||
|
||||
explicit Timer(StringRef N) : TG(0) { init(N); }
|
||||
Timer(StringRef N, TimerGroup &tg) : TG(0) { init(N, tg); }
|
||||
Timer(const Timer &RHS) : TG(0) {
|
||||
assert(RHS.TG == 0 && "Can only copy uninitialized timers");
|
||||
}
|
||||
const Timer &operator=(const Timer &T) {
|
||||
if (&T < this) {
|
||||
T.Lock.acquire();
|
||||
Lock.acquire();
|
||||
} else {
|
||||
Lock.acquire();
|
||||
T.Lock.acquire();
|
||||
}
|
||||
|
||||
Elapsed = T.Elapsed;
|
||||
UserTime = T.UserTime;
|
||||
SystemTime = T.SystemTime;
|
||||
MemUsed = T.MemUsed;
|
||||
PeakMem = T.PeakMem;
|
||||
PeakMemBase = T.PeakMemBase;
|
||||
Name = T.Name;
|
||||
Started = T.Started;
|
||||
assert(TG == T.TG && "Can only assign timers in the same TimerGroup!");
|
||||
|
||||
if (&T < this) {
|
||||
T.Lock.release();
|
||||
Lock.release();
|
||||
} else {
|
||||
Lock.release();
|
||||
T.Lock.release();
|
||||
}
|
||||
|
||||
assert(TG == 0 && T.TG == 0 && "Can only assign uninit timers");
|
||||
return *this;
|
||||
}
|
||||
~Timer();
|
||||
|
||||
// operator< - Allow sorting...
|
||||
bool operator<(const Timer &T) const {
|
||||
// Sort by Wall Time elapsed, as it is the only thing really accurate
|
||||
return Elapsed < T.Elapsed;
|
||||
}
|
||||
bool operator>(const Timer &T) const { return T.operator<(*this); }
|
||||
|
||||
// Create an uninitialized timer, client must use 'init'.
|
||||
explicit Timer() : TG(0) {}
|
||||
void init(StringRef N);
|
||||
void init(StringRef N, TimerGroup &tg);
|
||||
|
||||
const std::string &getName() const { return Name; }
|
||||
bool isInitialized() const { return TG != 0; }
|
||||
|
||||
/// startTimer - Start the timer running. Time between calls to
|
||||
/// startTimer/stopTimer is counted by the Timer class. Note that these calls
|
||||
/// must be correctly paired.
|
||||
@ -104,25 +118,8 @@ class Timer {
|
||||
///
|
||||
void stopTimer();
|
||||
|
||||
/// addPeakMemoryMeasurement - This method should be called whenever memory
|
||||
/// usage needs to be checked. It adds a peak memory measurement to the
|
||||
/// currently active timers, which will be printed when the timer group prints
|
||||
///
|
||||
static void addPeakMemoryMeasurement();
|
||||
|
||||
/// print - Print the current timer to standard error, and reset the "Started"
|
||||
/// flag.
|
||||
void print(const Timer &Total, raw_ostream &OS);
|
||||
|
||||
private:
|
||||
friend class TimerGroup;
|
||||
|
||||
// Copy ctor, initialize with no TG member.
|
||||
Timer(bool, const Timer &T);
|
||||
|
||||
/// sum - Add the time accumulated in the specified timer into this timer.
|
||||
///
|
||||
void sum(const Timer &T);
|
||||
};
|
||||
|
||||
|
||||
@ -139,12 +136,10 @@ class TimeRegion {
|
||||
T->startTimer();
|
||||
}
|
||||
explicit TimeRegion(Timer *t) : T(t) {
|
||||
if (T)
|
||||
T->startTimer();
|
||||
if (T) T->startTimer();
|
||||
}
|
||||
~TimeRegion() {
|
||||
if (T)
|
||||
T->stopTimer();
|
||||
if (T) T->stopTimer();
|
||||
}
|
||||
};
|
||||
|
||||
@ -155,9 +150,8 @@ class TimeRegion {
|
||||
/// is primarily used for debugging and for hunting performance problems.
|
||||
///
|
||||
struct NamedRegionTimer : public TimeRegion {
|
||||
explicit NamedRegionTimer(const std::string &Name);
|
||||
explicit NamedRegionTimer(const std::string &Name,
|
||||
const std::string &GroupName);
|
||||
explicit NamedRegionTimer(StringRef Name);
|
||||
explicit NamedRegionTimer(StringRef Name, StringRef GroupName);
|
||||
};
|
||||
|
||||
|
||||
@ -168,20 +162,29 @@ struct NamedRegionTimer : public TimeRegion {
|
||||
///
|
||||
class TimerGroup {
|
||||
std::string Name;
|
||||
unsigned NumTimers;
|
||||
std::vector<Timer> TimersToPrint;
|
||||
Timer *FirstTimer; // First timer in the group.
|
||||
std::vector<std::pair<TimeRecord, std::string> > TimersToPrint;
|
||||
|
||||
TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's.
|
||||
TimerGroup(const TimerGroup &TG); // DO NOT IMPLEMENT
|
||||
void operator=(const TimerGroup &TG); // DO NOT IMPLEMENT
|
||||
public:
|
||||
explicit TimerGroup(const std::string &name) : Name(name), NumTimers(0) {}
|
||||
~TimerGroup() {
|
||||
assert(NumTimers == 0 &&
|
||||
"TimerGroup destroyed before all contained timers!");
|
||||
}
|
||||
explicit TimerGroup(StringRef name);
|
||||
~TimerGroup();
|
||||
|
||||
void setName(StringRef name) { Name.assign(name.begin(), name.end()); }
|
||||
|
||||
/// print - Print any started timers in this group and zero them.
|
||||
void print(raw_ostream &OS);
|
||||
|
||||
/// printAll - This static method prints all timers and clears them all out.
|
||||
static void printAll(raw_ostream &OS);
|
||||
|
||||
private:
|
||||
friend class Timer;
|
||||
void addTimer();
|
||||
void removeTimer();
|
||||
void addTimerToPrint(const Timer &T);
|
||||
void addTimer(Timer &T);
|
||||
void removeTimer(Timer &T);
|
||||
void PrintQueuedTimers(raw_ostream &OS);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -284,8 +284,7 @@ class TrackingVH : public ValueHandleBase {
|
||||
Value *VP = ValueHandleBase::getValPtr();
|
||||
|
||||
// Null is always ok.
|
||||
if (!VP)
|
||||
return;
|
||||
if (!VP) return;
|
||||
|
||||
// Check that this value is valid (i.e., it hasn't been deleted). We
|
||||
// explicitly delay this check until access to avoid requiring clients to be
|
||||
@ -302,7 +301,7 @@ class TrackingVH : public ValueHandleBase {
|
||||
|
||||
ValueTy *getValPtr() const {
|
||||
CheckValidity();
|
||||
return static_cast<ValueTy*>(ValueHandleBase::getValPtr());
|
||||
return (ValueTy*)ValueHandleBase::getValPtr();
|
||||
}
|
||||
void setValPtr(ValueTy *P) {
|
||||
CheckValidity();
|
||||
|
@ -89,6 +89,7 @@ class raw_ostream {
|
||||
|
||||
/// has_error - Return the value of the flag in this raw_ostream indicating
|
||||
/// whether an output error has been encountered.
|
||||
/// This doesn't implicitly flush any pending output.
|
||||
bool has_error() const {
|
||||
return Error;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace sys {
|
||||
/// @brief Memory block abstraction.
|
||||
class MemoryBlock {
|
||||
public:
|
||||
MemoryBlock() { }
|
||||
MemoryBlock() : Address(0), Size(0) { }
|
||||
MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { }
|
||||
void *base() const { return Address; }
|
||||
size_t size() const { return Size; }
|
||||
|
@ -15,8 +15,12 @@
|
||||
namespace llvm {
|
||||
class MCAsmFixup;
|
||||
class MCDataFragment;
|
||||
class MCInst;
|
||||
class MCInstFragment;
|
||||
class MCObjectWriter;
|
||||
class MCSection;
|
||||
template<typename T>
|
||||
class SmallVectorImpl;
|
||||
class Target;
|
||||
class raw_ostream;
|
||||
|
||||
@ -95,6 +99,27 @@ class TargetAsmBackend {
|
||||
/// fixup kind as appropriate.
|
||||
virtual void ApplyFixup(const MCAsmFixup &Fixup, MCDataFragment &Fragment,
|
||||
uint64_t Value) const = 0;
|
||||
|
||||
/// MayNeedRelaxation - Check whether the given instruction may need
|
||||
/// relaxation.
|
||||
///
|
||||
/// \arg Inst - The instruction to test.
|
||||
/// \arg Fixups - The actual fixups this instruction encoded to, for potential
|
||||
/// use by the target backend.
|
||||
virtual bool MayNeedRelaxation(const MCInst &Inst,
|
||||
const SmallVectorImpl<MCAsmFixup> &Fixups) const = 0;
|
||||
|
||||
/// RelaxInstruction - Relax the instruction in the given fragment to the next
|
||||
/// wider instruction.
|
||||
virtual void RelaxInstruction(const MCInstFragment *IF,
|
||||
MCInst &Res) const = 0;
|
||||
|
||||
/// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given
|
||||
/// output. If the target cannot generate such a sequence, it should return an
|
||||
/// error.
|
||||
///
|
||||
/// \return - True on success.
|
||||
virtual bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const = 0;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -204,6 +204,16 @@ class TargetInstrDesc {
|
||||
return ImplicitUses;
|
||||
}
|
||||
|
||||
/// getNumImplicitUses - Return the number of implicit uses this instruction
|
||||
/// has.
|
||||
unsigned getNumImplicitUses() const {
|
||||
if (ImplicitUses == 0) return 0;
|
||||
unsigned i = 0;
|
||||
for (; ImplicitUses[i]; ++i) /*empty*/;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/// getImplicitDefs - Return a list of registers that are potentially
|
||||
/// written by any instance of this machine instruction. For example, on X86,
|
||||
/// many instructions implicitly set the flags register. In this case, they
|
||||
@ -218,6 +228,15 @@ class TargetInstrDesc {
|
||||
return ImplicitDefs;
|
||||
}
|
||||
|
||||
/// getNumImplicitDefs - Return the number of implicit defs this instruction
|
||||
/// has.
|
||||
unsigned getNumImplicitDefs() const {
|
||||
if (ImplicitDefs == 0) return 0;
|
||||
unsigned i = 0;
|
||||
for (; ImplicitDefs[i]; ++i) /*empty*/;
|
||||
return i;
|
||||
}
|
||||
|
||||
/// hasImplicitUseOfPhysReg - Return true if this instruction implicitly
|
||||
/// uses the specified physical register.
|
||||
bool hasImplicitUseOfPhysReg(unsigned Reg) const {
|
||||
|
@ -469,29 +469,6 @@ class TargetLowering {
|
||||
getIndexedStoreAction(IdxMode, VT) == Custom);
|
||||
}
|
||||
|
||||
/// getConvertAction - Return how the conversion should be treated:
|
||||
/// either it is legal, needs to be promoted to a larger size, needs to be
|
||||
/// expanded to some other code sequence, or the target has a custom expander
|
||||
/// for it.
|
||||
LegalizeAction
|
||||
getConvertAction(EVT FromVT, EVT ToVT) const {
|
||||
assert((unsigned)FromVT.getSimpleVT().SimpleTy <
|
||||
array_lengthof(ConvertActions) &&
|
||||
(unsigned)ToVT.getSimpleVT().SimpleTy <
|
||||
sizeof(ConvertActions[0])*4 &&
|
||||
"Table isn't big enough!");
|
||||
return (LegalizeAction)((ConvertActions[FromVT.getSimpleVT().SimpleTy] >>
|
||||
(2*ToVT.getSimpleVT().SimpleTy)) & 3);
|
||||
}
|
||||
|
||||
/// isConvertLegal - Return true if the specified conversion is legal
|
||||
/// on this target.
|
||||
bool isConvertLegal(EVT FromVT, EVT ToVT) const {
|
||||
return isTypeLegal(FromVT) && isTypeLegal(ToVT) &&
|
||||
(getConvertAction(FromVT, ToVT) == Legal ||
|
||||
getConvertAction(FromVT, ToVT) == Custom);
|
||||
}
|
||||
|
||||
/// getCondCodeAction - Return how the condition code should be treated:
|
||||
/// either it is legal, needs to be expanded to some other code sequence,
|
||||
/// or the target has a custom expander for it.
|
||||
@ -545,7 +522,7 @@ class TargetLowering {
|
||||
/// counterpart (e.g. structs), otherwise it will assert.
|
||||
EVT getValueType(const Type *Ty, bool AllowUnknown = false) const {
|
||||
EVT VT = EVT::getEVT(Ty, AllowUnknown);
|
||||
return VT == MVT:: iPTR ? PointerTy : VT;
|
||||
return VT == MVT::iPTR ? PointerTy : VT;
|
||||
}
|
||||
|
||||
/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
|
||||
@ -657,11 +634,14 @@ class TargetLowering {
|
||||
|
||||
/// getOptimalMemOpType - Returns the target specific optimal type for load
|
||||
/// and store operations as a result of memset, memcpy, and memmove lowering.
|
||||
/// 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 {
|
||||
/// If DstAlign is zero that means it's safe to destination alignment can
|
||||
/// satisfy any constraint. Similarly if SrcAlign is zero it means there isn't
|
||||
/// a need to check it against alignment requirement, probably because the
|
||||
/// source does not need to be loaded. It returns EVT::Other if SelectionDAG
|
||||
/// should be responsible for determining it.
|
||||
virtual EVT getOptimalMemOpType(uint64_t Size,
|
||||
unsigned DstAlign, unsigned SrcAlign,
|
||||
bool SafeToUseFP, SelectionDAG &DAG) const {
|
||||
return MVT::Other;
|
||||
}
|
||||
|
||||
@ -990,7 +970,7 @@ class TargetLowering {
|
||||
}
|
||||
|
||||
/// setLoadExtAction - Indicate that the specified load with extension does
|
||||
/// not work with the with specified type and indicate what to do about it.
|
||||
/// not work with the specified type and indicate what to do about it.
|
||||
void setLoadExtAction(unsigned ExtType, MVT VT,
|
||||
LegalizeAction Action) {
|
||||
assert((unsigned)VT.SimpleTy*2 < 63 &&
|
||||
@ -1001,7 +981,7 @@ class TargetLowering {
|
||||
}
|
||||
|
||||
/// setTruncStoreAction - Indicate that the specified truncating store does
|
||||
/// not work with the with specified type and indicate what to do about it.
|
||||
/// not work with the specified type and indicate what to do about it.
|
||||
void setTruncStoreAction(MVT ValVT, MVT MemVT,
|
||||
LegalizeAction Action) {
|
||||
assert((unsigned)ValVT.SimpleTy < array_lengthof(TruncStoreActions) &&
|
||||
@ -1012,7 +992,7 @@ class TargetLowering {
|
||||
}
|
||||
|
||||
/// setIndexedLoadAction - Indicate that the specified indexed load does or
|
||||
/// does not work with the with specified type and indicate what to do abort
|
||||
/// does not work with the specified type and indicate what to do abort
|
||||
/// it. NOTE: All indexed mode loads are initialized to Expand in
|
||||
/// TargetLowering.cpp
|
||||
void setIndexedLoadAction(unsigned IdxMode, MVT VT,
|
||||
@ -1024,7 +1004,7 @@ class TargetLowering {
|
||||
}
|
||||
|
||||
/// setIndexedStoreAction - Indicate that the specified indexed store does or
|
||||
/// does not work with the with specified type and indicate what to do about
|
||||
/// does not work with the specified type and indicate what to do about
|
||||
/// it. NOTE: All indexed mode stores are initialized to Expand in
|
||||
/// TargetLowering.cpp
|
||||
void setIndexedStoreAction(unsigned IdxMode, MVT VT,
|
||||
@ -1035,17 +1015,6 @@ class TargetLowering {
|
||||
IndexedModeActions[(unsigned)VT.SimpleTy][1][IdxMode] = (uint8_t)Action;
|
||||
}
|
||||
|
||||
/// setConvertAction - Indicate that the specified conversion does or does
|
||||
/// not work with the with specified type and indicate what to do about it.
|
||||
void setConvertAction(MVT FromVT, MVT ToVT,
|
||||
LegalizeAction Action) {
|
||||
assert((unsigned)FromVT.SimpleTy < array_lengthof(ConvertActions) &&
|
||||
(unsigned)ToVT.SimpleTy < MVT::LAST_VALUETYPE &&
|
||||
"Table isn't big enough!");
|
||||
ConvertActions[FromVT.SimpleTy] &= ~(uint64_t(3UL) << ToVT.SimpleTy*2);
|
||||
ConvertActions[FromVT.SimpleTy] |= (uint64_t)Action << ToVT.SimpleTy*2;
|
||||
}
|
||||
|
||||
/// setCondCodeAction - Indicate that the specified condition code is or isn't
|
||||
/// supported on the target and indicate what to do about it.
|
||||
void setCondCodeAction(ISD::CondCode CC, MVT VT,
|
||||
@ -1674,13 +1643,6 @@ class TargetLowering {
|
||||
/// represents the various modes for load store.
|
||||
uint8_t IndexedModeActions[MVT::LAST_VALUETYPE][2][ISD::LAST_INDEXED_MODE];
|
||||
|
||||
/// ConvertActions - For each conversion from source type to destination type,
|
||||
/// keep a LegalizeAction that indicates how instruction selection should
|
||||
/// deal with the conversion.
|
||||
/// Currently, this is used only for floating->floating conversions
|
||||
/// (FP_EXTEND and FP_ROUND).
|
||||
uint64_t ConvertActions[MVT::LAST_VALUETYPE];
|
||||
|
||||
/// CondCodeActions - For each condition code (ISD::CondCode) keep a
|
||||
/// LegalizeAction that indicates how instruction selection should
|
||||
/// deal with the condition code.
|
||||
|
@ -192,7 +192,7 @@ class TargetMachine {
|
||||
formatted_raw_ostream &,
|
||||
CodeGenFileType,
|
||||
CodeGenOpt::Level,
|
||||
bool DisableVerify = true) {
|
||||
bool = true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -205,7 +205,7 @@ class TargetMachine {
|
||||
virtual bool addPassesToEmitMachineCode(PassManagerBase &,
|
||||
JITCodeEmitter &,
|
||||
CodeGenOpt::Level,
|
||||
bool DisableVerify = true) {
|
||||
bool = true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -216,7 +216,7 @@ class TargetMachine {
|
||||
virtual bool addPassesToEmitWholeFile(PassManager &, formatted_raw_ostream &,
|
||||
CodeGenFileType,
|
||||
CodeGenOpt::Level,
|
||||
bool DisableVerify = true) {
|
||||
bool = true) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -92,6 +92,10 @@ def SDTIntBinOp : SDTypeProfile<1, 2, [ // add, and, or, xor, udiv, etc.
|
||||
def SDTIntShiftOp : SDTypeProfile<1, 2, [ // shl, sra, srl
|
||||
SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisInt<2>
|
||||
]>;
|
||||
def SDTIntBinHiLoOp : SDTypeProfile<2, 2, [ // mulhi, mullo, sdivrem, udivrem
|
||||
SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>,SDTCisInt<0>
|
||||
]>;
|
||||
|
||||
def SDTFPBinOp : SDTypeProfile<1, 2, [ // fadd, fmul, etc.
|
||||
SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisFP<0>
|
||||
]>;
|
||||
@ -235,7 +239,6 @@ class SDNode<string opcode, SDTypeProfile typeprof,
|
||||
// Special TableGen-recognized dag nodes
|
||||
def set;
|
||||
def implicit;
|
||||
def parallel;
|
||||
def node;
|
||||
def srcvalue;
|
||||
|
||||
@ -282,10 +285,14 @@ def mul : SDNode<"ISD::MUL" , SDTIntBinOp,
|
||||
[SDNPCommutative, SDNPAssociative]>;
|
||||
def mulhs : SDNode<"ISD::MULHS" , SDTIntBinOp, [SDNPCommutative]>;
|
||||
def mulhu : SDNode<"ISD::MULHU" , SDTIntBinOp, [SDNPCommutative]>;
|
||||
def smullohi : SDNode<"ISD::SMUL_LOHI" , SDTIntBinHiLoOp, [SDNPCommutative]>;
|
||||
def umullohi : SDNode<"ISD::UMUL_LOHI" , SDTIntBinHiLoOp, [SDNPCommutative]>;
|
||||
def sdiv : SDNode<"ISD::SDIV" , SDTIntBinOp>;
|
||||
def udiv : SDNode<"ISD::UDIV" , SDTIntBinOp>;
|
||||
def srem : SDNode<"ISD::SREM" , SDTIntBinOp>;
|
||||
def urem : SDNode<"ISD::UREM" , SDTIntBinOp>;
|
||||
def sdivrem : SDNode<"ISD::SDIVREM" , SDTIntBinHiLoOp>;
|
||||
def udivrem : SDNode<"ISD::UDIVREM" , SDTIntBinHiLoOp>;
|
||||
def srl : SDNode<"ISD::SRL" , SDTIntShiftOp>;
|
||||
def sra : SDNode<"ISD::SRA" , SDTIntShiftOp>;
|
||||
def shl : SDNode<"ISD::SHL" , SDTIntShiftOp>;
|
||||
@ -485,22 +492,15 @@ def vtFP : PatLeaf<(vt), [{ return N->getVT().isFloatingPoint(); }]>;
|
||||
def immAllOnesV: PatLeaf<(build_vector), [{
|
||||
return ISD::isBuildVectorAllOnes(N);
|
||||
}]>;
|
||||
def immAllOnesV_bc: PatLeaf<(bitconvert), [{
|
||||
return ISD::isBuildVectorAllOnes(N);
|
||||
}]>;
|
||||
def immAllZerosV: PatLeaf<(build_vector), [{
|
||||
return ISD::isBuildVectorAllZeros(N);
|
||||
}]>;
|
||||
def immAllZerosV_bc: PatLeaf<(bitconvert), [{
|
||||
return ISD::isBuildVectorAllZeros(N);
|
||||
}]>;
|
||||
|
||||
|
||||
|
||||
// Other helper fragments.
|
||||
def not : PatFrag<(ops node:$in), (xor node:$in, -1)>;
|
||||
def vnot : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV)>;
|
||||
def vnot_conv : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV_bc)>;
|
||||
def ineg : PatFrag<(ops node:$in), (sub 0, node:$in)>;
|
||||
|
||||
// load fragments.
|
||||
|
@ -49,6 +49,12 @@ namespace llvm {
|
||||
Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len,
|
||||
unsigned Align, IRBuilder<> &B, const TargetData *TD);
|
||||
|
||||
/// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder.
|
||||
/// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src
|
||||
/// are pointers.
|
||||
Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
|
||||
IRBuilder<> &B, const TargetData *TD);
|
||||
|
||||
/// EmitMemMove - Emit a call to the memmove function to the builder. This
|
||||
/// always expects that the size has type 'intptr_t' and Dst/Src are pointers.
|
||||
Value *EmitMemMove(Value *Dst, Value *Src, Value *Len,
|
||||
|
@ -27,22 +27,28 @@ namespace llvm {
|
||||
/// transformation wants to rewrite a set of uses of one value with uses of a
|
||||
/// set of values.
|
||||
class SSAUpdater {
|
||||
public:
|
||||
class BBInfo;
|
||||
|
||||
private:
|
||||
/// AvailableVals - This keeps track of which value to use on a per-block
|
||||
/// basis. When we insert PHI nodes, we keep track of them here. We use
|
||||
/// TrackingVH's for the value of the map because we RAUW PHI nodes when we
|
||||
/// eliminate them, and want the TrackingVH's to track this.
|
||||
//typedef DenseMap<BasicBlock*, TrackingVH<Value> > AvailableValsTy;
|
||||
/// basis. When we insert PHI nodes, we keep track of them here.
|
||||
//typedef DenseMap<BasicBlock*, Value*> AvailableValsTy;
|
||||
void *AV;
|
||||
|
||||
/// PrototypeValue is an arbitrary representative value, which we derive names
|
||||
/// and a type for PHI nodes.
|
||||
Value *PrototypeValue;
|
||||
|
||||
/// IncomingPredInfo - We use this as scratch space when doing our recursive
|
||||
/// walk. This should only be used in GetValueInBlockInternal, normally it
|
||||
/// should be empty.
|
||||
//std::vector<std::pair<BasicBlock*, TrackingVH<Value> > > IncomingPredInfo;
|
||||
void *IPI;
|
||||
/// BBMap - The GetValueAtEndOfBlock method maintains this mapping from
|
||||
/// basic blocks to BBInfo structures.
|
||||
/// typedef DenseMap<BasicBlock*, BBInfo*> BBMapTy;
|
||||
void *BM;
|
||||
|
||||
/// Allocator - The GetValueAtEndOfBlock method uses this BumpPtrAllocator to
|
||||
/// hold its internal data. The allocator and its storage is created and
|
||||
/// discarded for each invocation of GetValueAtEndOfBlock.
|
||||
void *BPA;
|
||||
|
||||
/// InsertedPHIs - If this is non-null, the SSAUpdater adds all PHI nodes that
|
||||
/// it creates to the vector.
|
||||
@ -99,6 +105,14 @@ class SSAUpdater {
|
||||
|
||||
private:
|
||||
Value *GetValueAtEndOfBlockInternal(BasicBlock *BB);
|
||||
void FindPHIPlacement(BasicBlock *BB, BBInfo *Info, bool &Changed,
|
||||
unsigned Counter);
|
||||
void FindAvailableVal(BasicBlock *BB, BBInfo *Info, unsigned Counter);
|
||||
void FindExistingPHI(BasicBlock *BB);
|
||||
bool CheckIfPHIMatches(PHINode *PHI);
|
||||
void RecordMatchingPHI(PHINode *PHI);
|
||||
void ClearPHITags(PHINode *PHI);
|
||||
|
||||
void operator=(const SSAUpdater&); // DO NOT IMPLEMENT
|
||||
SSAUpdater(const SSAUpdater&); // DO NOT IMPLEMENT
|
||||
};
|
||||
|
@ -548,9 +548,11 @@ template <> struct GraphTraits<const Type*> {
|
||||
}
|
||||
};
|
||||
|
||||
template <> inline bool isa_impl<PointerType, Type>(const Type &Ty) {
|
||||
return Ty.getTypeID() == Type::PointerTyID;
|
||||
}
|
||||
template <> struct isa_impl<PointerType, Type> {
|
||||
static inline bool doit(const Type &Ty) {
|
||||
return Ty.getTypeID() == Type::PointerTyID;
|
||||
}
|
||||
};
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const Type &T);
|
||||
|
||||
|
@ -157,13 +157,13 @@ class Value {
|
||||
// Methods for handling the chain of uses of this Value.
|
||||
//
|
||||
typedef value_use_iterator<User> use_iterator;
|
||||
typedef value_use_iterator<const User> use_const_iterator;
|
||||
typedef value_use_iterator<const User> const_use_iterator;
|
||||
|
||||
bool use_empty() const { return UseList == 0; }
|
||||
use_iterator use_begin() { return use_iterator(UseList); }
|
||||
use_const_iterator use_begin() const { return use_const_iterator(UseList); }
|
||||
const_use_iterator use_begin() const { return const_use_iterator(UseList); }
|
||||
use_iterator use_end() { return use_iterator(0); }
|
||||
use_const_iterator use_end() const { return use_const_iterator(0); }
|
||||
const_use_iterator use_end() const { return const_use_iterator(0); }
|
||||
User *use_back() { return *use_begin(); }
|
||||
const User *use_back() const { return *use_begin(); }
|
||||
|
||||
@ -172,7 +172,7 @@ class Value {
|
||||
/// traversing the whole use list.
|
||||
///
|
||||
bool hasOneUse() const {
|
||||
use_const_iterator I = use_begin(), E = use_end();
|
||||
const_use_iterator I = use_begin(), E = use_end();
|
||||
if (I == E) return false;
|
||||
return ++I == E;
|
||||
}
|
||||
@ -324,39 +324,67 @@ void Use::set(Value *V) {
|
||||
// isa - Provide some specializations of isa so that we don't have to include
|
||||
// the subtype header files to test to see if the value is a subclass...
|
||||
//
|
||||
template <> inline bool isa_impl<Constant, Value>(const Value &Val) {
|
||||
return Val.getValueID() >= Value::ConstantFirstVal &&
|
||||
Val.getValueID() <= Value::ConstantLastVal;
|
||||
}
|
||||
template <> inline bool isa_impl<Argument, Value>(const Value &Val) {
|
||||
return Val.getValueID() == Value::ArgumentVal;
|
||||
}
|
||||
template <> inline bool isa_impl<InlineAsm, Value>(const Value &Val) {
|
||||
return Val.getValueID() == Value::InlineAsmVal;
|
||||
}
|
||||
template <> inline bool isa_impl<Instruction, Value>(const Value &Val) {
|
||||
return Val.getValueID() >= Value::InstructionVal;
|
||||
}
|
||||
template <> inline bool isa_impl<BasicBlock, Value>(const Value &Val) {
|
||||
return Val.getValueID() == Value::BasicBlockVal;
|
||||
}
|
||||
template <> inline bool isa_impl<Function, Value>(const Value &Val) {
|
||||
return Val.getValueID() == Value::FunctionVal;
|
||||
}
|
||||
template <> inline bool isa_impl<GlobalVariable, Value>(const Value &Val) {
|
||||
return Val.getValueID() == Value::GlobalVariableVal;
|
||||
}
|
||||
template <> inline bool isa_impl<GlobalAlias, Value>(const Value &Val) {
|
||||
return Val.getValueID() == Value::GlobalAliasVal;
|
||||
}
|
||||
template <> inline bool isa_impl<GlobalValue, Value>(const Value &Val) {
|
||||
return isa<GlobalVariable>(Val) || isa<Function>(Val) ||
|
||||
isa<GlobalAlias>(Val);
|
||||
}
|
||||
template <> inline bool isa_impl<MDNode, Value>(const Value &Val) {
|
||||
return Val.getValueID() == Value::MDNodeVal;
|
||||
}
|
||||
|
||||
template <> struct isa_impl<Constant, Value> {
|
||||
static inline bool doit(const Value &Val) {
|
||||
return Val.getValueID() >= Value::ConstantFirstVal &&
|
||||
Val.getValueID() <= Value::ConstantLastVal;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct isa_impl<Argument, Value> {
|
||||
static inline bool doit (const Value &Val) {
|
||||
return Val.getValueID() == Value::ArgumentVal;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct isa_impl<InlineAsm, Value> {
|
||||
static inline bool doit(const Value &Val) {
|
||||
return Val.getValueID() == Value::InlineAsmVal;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct isa_impl<Instruction, Value> {
|
||||
static inline bool doit(const Value &Val) {
|
||||
return Val.getValueID() >= Value::InstructionVal;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct isa_impl<BasicBlock, Value> {
|
||||
static inline bool doit(const Value &Val) {
|
||||
return Val.getValueID() == Value::BasicBlockVal;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct isa_impl<Function, Value> {
|
||||
static inline bool doit(const Value &Val) {
|
||||
return Val.getValueID() == Value::FunctionVal;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct isa_impl<GlobalVariable, Value> {
|
||||
static inline bool doit(const Value &Val) {
|
||||
return Val.getValueID() == Value::GlobalVariableVal;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct isa_impl<GlobalAlias, Value> {
|
||||
static inline bool doit(const Value &Val) {
|
||||
return Val.getValueID() == Value::GlobalAliasVal;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct isa_impl<GlobalValue, Value> {
|
||||
static inline bool doit(const Value &Val) {
|
||||
return isa<GlobalVariable>(Val) || isa<Function>(Val) ||
|
||||
isa<GlobalAlias>(Val);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct isa_impl<MDNode, Value> {
|
||||
static inline bool doit(const Value &Val) {
|
||||
return Val.getValueID() == Value::MDNodeVal;
|
||||
}
|
||||
};
|
||||
|
||||
// Value* is only 4-byte aligned.
|
||||
template<>
|
||||
|
@ -49,7 +49,7 @@ bool llvm::PointerMayBeCaptured(const Value *V,
|
||||
SmallSet<Use*, Threshold> Visited;
|
||||
int Count = 0;
|
||||
|
||||
for (Value::use_const_iterator UI = V->use_begin(), UE = V->use_end();
|
||||
for (Value::const_use_iterator UI = V->use_begin(), UE = V->use_end();
|
||||
UI != UE; ++UI) {
|
||||
// If there are lots of uses, conservatively say that the value
|
||||
// is captured to avoid taking too much compile time.
|
||||
|
@ -96,9 +96,8 @@ DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const {
|
||||
if (DbgNode == 0)
|
||||
return DIDescriptor();
|
||||
|
||||
if (Elt < DbgNode->getNumOperands() && DbgNode->getOperand(Elt))
|
||||
return DIDescriptor(dyn_cast<MDNode>(DbgNode->getOperand(Elt)));
|
||||
|
||||
if (Elt < DbgNode->getNumOperands())
|
||||
return DIDescriptor(dyn_cast_or_null<MDNode>(DbgNode->getOperand(Elt)));
|
||||
return DIDescriptor();
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,13 @@
|
||||
|
||||
#define DEBUG_TYPE "cgscc-passmgr"
|
||||
#include "llvm/CallGraphSCCPass.h"
|
||||
#include "llvm/IntrinsicInst.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/PassManagers.h"
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/ADT/SCCIterator.h"
|
||||
#include "llvm/PassManagers.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/IntrinsicInst.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
@ -102,9 +103,10 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
|
||||
CallGraphUpToDate = true;
|
||||
}
|
||||
|
||||
Timer *T = StartPassTimer(CGSP);
|
||||
Changed = CGSP->runOnSCC(CurSCC);
|
||||
StopPassTimer(CGSP, T);
|
||||
{
|
||||
TimeRegion PassTimer(getPassTimer(CGSP));
|
||||
Changed = CGSP->runOnSCC(CurSCC);
|
||||
}
|
||||
|
||||
// After the CGSCCPass is done, when assertions are enabled, use
|
||||
// RefreshCallGraph to verify that the callgraph was correctly updated.
|
||||
@ -125,9 +127,8 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
|
||||
for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) {
|
||||
if (Function *F = CurSCC[i]->getFunction()) {
|
||||
dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName());
|
||||
Timer *T = StartPassTimer(FPP);
|
||||
TimeRegion PassTimer(getPassTimer(FPP));
|
||||
Changed |= FPP->runOnFunction(*F);
|
||||
StopPassTimer(FPP, T);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,7 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
||||
} else if (InvokeInst *II = dyn_cast<InvokeInst>(*UI)) {
|
||||
// Make sure that this is just the function being called, not that it is
|
||||
// passing into the function.
|
||||
for (unsigned i = 3, e = II->getNumOperands(); i != e; ++i)
|
||||
for (unsigned i = 0, e = II->getNumOperands() - 3; i != e; ++i)
|
||||
if (II->getOperand(i) == V) return true;
|
||||
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(*UI)) {
|
||||
if (CE->getOpcode() == Instruction::GetElementPtr ||
|
||||
|
@ -255,9 +255,11 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
|
||||
Function *Caller = TheCall->getParent()->getParent();
|
||||
|
||||
// Don't inline functions which can be redefined at link-time to mean
|
||||
// something else. Don't inline functions marked noinline.
|
||||
// something else. Don't inline functions marked noinline or call sites
|
||||
// marked noinline.
|
||||
if (Callee->mayBeOverridden() ||
|
||||
Callee->hasFnAttr(Attribute::NoInline) || NeverInline.count(Callee))
|
||||
Callee->hasFnAttr(Attribute::NoInline) || NeverInline.count(Callee) ||
|
||||
CS.isNoInline())
|
||||
return llvm::InlineCost::getNever();
|
||||
|
||||
// InlineCost - This value measures how good of an inline candidate this call
|
||||
|
@ -125,7 +125,7 @@ LiveValues::Memo &LiveValues::compute(const Value *V) {
|
||||
bool LiveOutOfDefBB = false;
|
||||
|
||||
// Examine each use of the value.
|
||||
for (Value::use_const_iterator I = V->use_begin(), E = V->use_end();
|
||||
for (Value::const_use_iterator I = V->use_begin(), E = V->use_end();
|
||||
I != E; ++I) {
|
||||
const User *U = *I;
|
||||
const BasicBlock *UseBB = cast<Instruction>(U)->getParent();
|
||||
|
@ -14,6 +14,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
using namespace llvm;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -221,22 +222,22 @@ bool LPPassManager::runOnFunction(Function &F) {
|
||||
LoopPass *P = (LoopPass*)getContainedPass(Index);
|
||||
|
||||
dumpPassInfo(P, EXECUTION_MSG, ON_LOOP_MSG,
|
||||
CurrentLoop->getHeader()->getNameStr());
|
||||
CurrentLoop->getHeader()->getName());
|
||||
dumpRequiredSet(P);
|
||||
|
||||
initializeAnalysisImpl(P);
|
||||
|
||||
{
|
||||
PassManagerPrettyStackEntry X(P, *CurrentLoop->getHeader());
|
||||
Timer *T = StartPassTimer(P);
|
||||
TimeRegion PassTimer(getPassTimer(P));
|
||||
|
||||
Changed |= P->runOnLoop(CurrentLoop, *this);
|
||||
StopPassTimer(P, T);
|
||||
}
|
||||
|
||||
if (Changed)
|
||||
dumpPassInfo(P, MODIFICATION_MSG, ON_LOOP_MSG,
|
||||
skipThisLoop ? "<deleted>" :
|
||||
CurrentLoop->getHeader()->getNameStr());
|
||||
CurrentLoop->getHeader()->getName());
|
||||
dumpPreservedSet(P);
|
||||
|
||||
if (!skipThisLoop) {
|
||||
@ -245,9 +246,10 @@ bool LPPassManager::runOnFunction(Function &F) {
|
||||
// is a function pass and it's really expensive to verify every
|
||||
// loop in the function every time. That level of checking can be
|
||||
// enabled with the -verify-loop-info option.
|
||||
Timer *T = StartPassTimer(LI);
|
||||
CurrentLoop->verifyLoop();
|
||||
StopPassTimer(LI, T);
|
||||
{
|
||||
TimeRegion PassTimer(getPassTimer(LI));
|
||||
CurrentLoop->verifyLoop();
|
||||
}
|
||||
|
||||
// Then call the regular verifyAnalysis functions.
|
||||
verifyPreservedAnalysis(P);
|
||||
@ -257,7 +259,7 @@ bool LPPassManager::runOnFunction(Function &F) {
|
||||
recordAvailableAnalysis(P);
|
||||
removeDeadPasses(P,
|
||||
skipThisLoop ? "<deleted>" :
|
||||
CurrentLoop->getHeader()->getNameStr(),
|
||||
CurrentLoop->getHeader()->getName(),
|
||||
ON_LOOP_MSG);
|
||||
|
||||
if (skipThisLoop)
|
||||
|
@ -139,7 +139,7 @@ const PointerType *llvm::getMallocType(const CallInst *CI) {
|
||||
unsigned NumOfBitCastUses = 0;
|
||||
|
||||
// Determine if CallInst has a bitcast use.
|
||||
for (Value::use_const_iterator UI = CI->use_begin(), E = CI->use_end();
|
||||
for (Value::const_use_iterator UI = CI->use_begin(), E = CI->use_end();
|
||||
UI != E; )
|
||||
if (const BitCastInst *BCI = dyn_cast<BitCastInst>(*UI++)) {
|
||||
MallocType = cast<PointerType>(BCI->getDestTy());
|
||||
|
@ -398,7 +398,7 @@ bool ProfileEstimatorPass::runOnFunction(Function &F) {
|
||||
for (Function::const_iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) {
|
||||
const BasicBlock *BB = &(*FI);
|
||||
BlockInformation[&F][BB] = 0;
|
||||
pred_const_iterator predi = pred_begin(BB), prede = pred_end(BB);
|
||||
const_pred_iterator predi = pred_begin(BB), prede = pred_end(BB);
|
||||
if (predi == prede) {
|
||||
Edge e = getEdge(0,BB);
|
||||
setEdgeWeight(e,0);
|
||||
|
@ -67,7 +67,7 @@ ProfileInfoT<Function,BasicBlock>::getExecutionCount(const BasicBlock *BB) {
|
||||
|
||||
double Count = MissingValue;
|
||||
|
||||
pred_const_iterator PI = pred_begin(BB), PE = pred_end(BB);
|
||||
const_pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
|
||||
|
||||
// Are there zero predecessors of this block?
|
||||
if (PI == PE) {
|
||||
@ -508,7 +508,7 @@ bool ProfileInfoT<Function,BasicBlock>::
|
||||
// have no value
|
||||
double incount = 0;
|
||||
SmallSet<const BasicBlock*,8> pred_visited;
|
||||
pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
if (bbi==bbe) {
|
||||
Edge e = getEdge(0,BB);
|
||||
incount += readEdgeOrRemember(e, getEdgeWeight(e) ,edgetocalc,uncalculated);
|
||||
@ -582,7 +582,7 @@ bool ProfileInfoT<Function,BasicBlock>::EstimateMissingEdges(const BasicBlock *B
|
||||
double inWeight = 0;
|
||||
std::set<Edge> inMissing;
|
||||
std::set<const BasicBlock*> ProcessedPreds;
|
||||
pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
if (bbi == bbe) {
|
||||
readEdge(this,getEdge(0,BB),inWeight,inMissing);
|
||||
}
|
||||
@ -639,7 +639,7 @@ void ProfileInfoT<Function,BasicBlock>::repair(const Function *F) {
|
||||
// FI != FE; ++FI) {
|
||||
// const BasicBlock* BB = &(*FI);
|
||||
// {
|
||||
// pred_const_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
// const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
// if (NBB == End) {
|
||||
// setEdgeWeight(getEdge(0,BB),0);
|
||||
// }
|
||||
@ -779,7 +779,7 @@ void ProfileInfoT<Function,BasicBlock>::repair(const Function *F) {
|
||||
// Calculate incoming flow.
|
||||
double iw = 0; unsigned inmissing = 0; unsigned incount = 0; unsigned invalid = 0;
|
||||
std::set<const BasicBlock *> Processed;
|
||||
for (pred_const_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
NBB != End; ++NBB) {
|
||||
if (Processed.insert(*NBB).second) {
|
||||
Edge e = getEdge(*NBB, BB);
|
||||
@ -869,7 +869,7 @@ void ProfileInfoT<Function,BasicBlock>::repair(const Function *F) {
|
||||
if (getEdgeWeight(e) == MissingValue) {
|
||||
double iw = 0;
|
||||
std::set<const BasicBlock *> Processed;
|
||||
for (pred_const_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
NBB != End; ++NBB) {
|
||||
if (Processed.insert(*NBB).second) {
|
||||
Edge e = getEdge(*NBB, BB);
|
||||
@ -893,7 +893,7 @@ void ProfileInfoT<Function,BasicBlock>::repair(const Function *F) {
|
||||
const BasicBlock *Dest;
|
||||
Path P;
|
||||
bool BackEdgeFound = false;
|
||||
for (pred_const_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
NBB != End; ++NBB) {
|
||||
Dest = GetPath(BB, *NBB, P, GetPathToDest | GetPathWithNewEdges);
|
||||
if (Dest == *NBB) {
|
||||
@ -935,7 +935,7 @@ void ProfileInfoT<Function,BasicBlock>::repair(const Function *F) {
|
||||
// Calculate incoming flow.
|
||||
double iw = 0;
|
||||
std::set<const BasicBlock *> Processed;
|
||||
for (pred_const_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
NBB != End; ++NBB) {
|
||||
if (Processed.insert(*NBB).second) {
|
||||
Edge e = getEdge(*NBB, BB);
|
||||
@ -965,7 +965,7 @@ void ProfileInfoT<Function,BasicBlock>::repair(const Function *F) {
|
||||
while(FI != FE && !FoundPath) {
|
||||
const BasicBlock *BB = *FI; ++FI;
|
||||
|
||||
for (pred_const_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
||||
NBB != End; ++NBB) {
|
||||
Edge e = getEdge(*NBB,BB);
|
||||
double w = getEdgeWeight(e);
|
||||
|
@ -119,7 +119,7 @@ void LoaderPass::recurseBasicBlock(const BasicBlock *BB) {
|
||||
bbi != bbe; ++bbi) {
|
||||
recurseBasicBlock(*bbi);
|
||||
}
|
||||
for (pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
for (const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
bbi != bbe; ++bbi) {
|
||||
recurseBasicBlock(*bbi);
|
||||
}
|
||||
|
@ -96,8 +96,8 @@ namespace llvm {
|
||||
double inWeight = 0;
|
||||
int inCount = 0;
|
||||
std::set<const BType*> ProcessedPreds;
|
||||
for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
bbi != bbe; ++bbi ) {
|
||||
for (const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
bbi != bbe; ++bbi ) {
|
||||
if (ProcessedPreds.insert(*bbi).second) {
|
||||
typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(*bbi,BB);
|
||||
double EdgeWeight = PI->getEdgeWeight(E);
|
||||
@ -242,7 +242,7 @@ namespace llvm {
|
||||
|
||||
// Read predecessors.
|
||||
std::set<const BType*> ProcessedPreds;
|
||||
pred_const_iterator bpi = pred_begin(BB), bpe = pred_end(BB);
|
||||
const_pred_iterator bpi = pred_begin(BB), bpe = pred_end(BB);
|
||||
// If there are none, check for (0,BB) edge.
|
||||
if (bpi == bpe) {
|
||||
DI.inWeight += ReadOrAssert(PI->getEdge(0,BB));
|
||||
|
@ -1268,19 +1268,8 @@ Value *SCEVExpander::expand(const SCEV *S) {
|
||||
L = L->getParentLoop())
|
||||
if (S->isLoopInvariant(L)) {
|
||||
if (!L) break;
|
||||
if (BasicBlock *Preheader = L->getLoopPreheader()) {
|
||||
if (BasicBlock *Preheader = L->getLoopPreheader())
|
||||
InsertPt = Preheader->getTerminator();
|
||||
BasicBlock::iterator IP = InsertPt;
|
||||
// Back past any debug info instructions. Sometimes we inserted
|
||||
// something earlier before debug info but after any real instructions.
|
||||
// This should behave the same as if debug info was not present.
|
||||
while (IP != Preheader->begin()) {
|
||||
--IP;
|
||||
if (!isa<DbgInfoIntrinsic>(IP))
|
||||
break;
|
||||
InsertPt = IP;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If the SCEV is computable at this level, insert it into the header
|
||||
// after the PHIs (and after any other instructions that we've inserted
|
||||
|
@ -220,7 +220,7 @@ Archive::writeMember(
|
||||
}
|
||||
|
||||
// Now that we have the data in memory, update the
|
||||
// symbol table if its a bitcode file.
|
||||
// symbol table if it's a bitcode file.
|
||||
if (CreateSymbolTable && member.isBitcode()) {
|
||||
std::vector<std::string> symbols;
|
||||
std::string FullMemberName = archPath.str() + "(" + member.getPath().str()
|
||||
|
@ -55,7 +55,7 @@ namespace llvm {
|
||||
typedef SMLoc LocTy;
|
||||
LocTy getLoc() const { return SMLoc::getFromPointer(TokStart); }
|
||||
lltok::Kind getKind() const { return CurKind; }
|
||||
const std::string getStrVal() const { return StrVal; }
|
||||
const std::string &getStrVal() const { return StrVal; }
|
||||
const Type *getTyVal() const { return TyVal; }
|
||||
unsigned getUIntVal() const { return UIntVal; }
|
||||
const APSInt &getAPSIntVal() const { return APSIntVal; }
|
||||
|
@ -39,6 +39,27 @@ bool LLParser::Run() {
|
||||
/// ValidateEndOfModule - Do final validity and sanity checks at the end of the
|
||||
/// module.
|
||||
bool LLParser::ValidateEndOfModule() {
|
||||
// Handle any instruction metadata forward references.
|
||||
if (!ForwardRefInstMetadata.empty()) {
|
||||
for (DenseMap<Instruction*, std::vector<MDRef> >::iterator
|
||||
I = ForwardRefInstMetadata.begin(), E = ForwardRefInstMetadata.end();
|
||||
I != E; ++I) {
|
||||
Instruction *Inst = I->first;
|
||||
const std::vector<MDRef> &MDList = I->second;
|
||||
|
||||
for (unsigned i = 0, e = MDList.size(); i != e; ++i) {
|
||||
unsigned SlotNo = MDList[i].MDSlot;
|
||||
|
||||
if (SlotNo >= NumberedMetadata.size() || NumberedMetadata[SlotNo] == 0)
|
||||
return Error(MDList[i].Loc, "use of undefined metadata '!" +
|
||||
utostr(SlotNo) + "'");
|
||||
Inst->setMetadata(MDList[i].MDKind, NumberedMetadata[SlotNo]);
|
||||
}
|
||||
}
|
||||
ForwardRefInstMetadata.clear();
|
||||
}
|
||||
|
||||
|
||||
// Update auto-upgraded malloc calls to "malloc".
|
||||
// FIXME: Remove in LLVM 3.0.
|
||||
if (MallocF) {
|
||||
@ -472,18 +493,30 @@ bool LLParser::ParseMDString(MDString *&Result) {
|
||||
|
||||
// MDNode:
|
||||
// ::= '!' MDNodeNumber
|
||||
//
|
||||
/// This version of ParseMDNodeID returns the slot number and null in the case
|
||||
/// of a forward reference.
|
||||
bool LLParser::ParseMDNodeID(MDNode *&Result, unsigned &SlotNo) {
|
||||
// !{ ..., !42, ... }
|
||||
if (ParseUInt32(SlotNo)) return true;
|
||||
|
||||
// Check existing MDNode.
|
||||
if (SlotNo < NumberedMetadata.size() && NumberedMetadata[SlotNo] != 0)
|
||||
Result = NumberedMetadata[SlotNo];
|
||||
else
|
||||
Result = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLParser::ParseMDNodeID(MDNode *&Result) {
|
||||
// !{ ..., !42, ... }
|
||||
unsigned MID = 0;
|
||||
if (ParseUInt32(MID)) return true;
|
||||
if (ParseMDNodeID(Result, MID)) return true;
|
||||
|
||||
// Check existing MDNode.
|
||||
if (MID < NumberedMetadata.size() && NumberedMetadata[MID] != 0) {
|
||||
Result = NumberedMetadata[MID];
|
||||
return false;
|
||||
}
|
||||
// If not a forward reference, just return it now.
|
||||
if (Result) return false;
|
||||
|
||||
// Create MDNode forward reference.
|
||||
// Otherwise, create MDNode forward reference.
|
||||
|
||||
// FIXME: This is not unique enough!
|
||||
std::string FwdRefName = "llvm.mdnode.fwdref." + utostr(MID);
|
||||
@ -1078,9 +1111,7 @@ bool LLParser::ParseOptionalCallingConv(CallingConv::ID &CC) {
|
||||
|
||||
/// ParseInstructionMetadata
|
||||
/// ::= !dbg !42 (',' !dbg !57)*
|
||||
bool LLParser::
|
||||
ParseInstructionMetadata(SmallVectorImpl<std::pair<unsigned,
|
||||
MDNode *> > &Result){
|
||||
bool LLParser::ParseInstructionMetadata(Instruction *Inst) {
|
||||
do {
|
||||
if (Lex.getKind() != lltok::MetadataVar)
|
||||
return TokError("expected metadata after comma");
|
||||
@ -1089,12 +1120,21 @@ ParseInstructionMetadata(SmallVectorImpl<std::pair<unsigned,
|
||||
Lex.Lex();
|
||||
|
||||
MDNode *Node;
|
||||
unsigned NodeID;
|
||||
SMLoc Loc = Lex.getLoc();
|
||||
if (ParseToken(lltok::exclaim, "expected '!' here") ||
|
||||
ParseMDNodeID(Node))
|
||||
ParseMDNodeID(Node, NodeID))
|
||||
return true;
|
||||
|
||||
unsigned MDK = M->getMDKindID(Name.c_str());
|
||||
Result.push_back(std::make_pair(MDK, Node));
|
||||
if (Node) {
|
||||
// If we got the node, add it to the instruction.
|
||||
Inst->setMetadata(MDK, Node);
|
||||
} else {
|
||||
MDRef R = { Loc, MDK, NodeID };
|
||||
// Otherwise, remember that this should be resolved later.
|
||||
ForwardRefInstMetadata[Inst].push_back(R);
|
||||
}
|
||||
|
||||
// If this is the end of the list, we're done.
|
||||
} while (EatIfPresent(lltok::comma));
|
||||
@ -2896,22 +2936,17 @@ bool LLParser::ParseBasicBlock(PerFunctionState &PFS) {
|
||||
// With a normal result, we check to see if the instruction is followed by
|
||||
// a comma and metadata.
|
||||
if (EatIfPresent(lltok::comma))
|
||||
if (ParseInstructionMetadata(MetadataOnInst))
|
||||
if (ParseInstructionMetadata(Inst))
|
||||
return true;
|
||||
break;
|
||||
case InstExtraComma:
|
||||
// If the instruction parser ate an extra comma at the end of it, it
|
||||
// *must* be followed by metadata.
|
||||
if (ParseInstructionMetadata(MetadataOnInst))
|
||||
if (ParseInstructionMetadata(Inst))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set metadata attached with this instruction.
|
||||
for (unsigned i = 0, e = MetadataOnInst.size(); i != e; ++i)
|
||||
Inst->setMetadata(MetadataOnInst[i].first, MetadataOnInst[i].second);
|
||||
MetadataOnInst.clear();
|
||||
|
||||
BB->getInstList().push_back(Inst);
|
||||
|
||||
// Set the name on the instruction.
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "LLLexer.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
#include <map>
|
||||
|
||||
@ -76,6 +77,14 @@ namespace llvm {
|
||||
LLVMContext& Context;
|
||||
LLLexer Lex;
|
||||
Module *M;
|
||||
|
||||
// Instruction metadata resolution. Each instruction can have a list of
|
||||
// MDRef info associated with them.
|
||||
struct MDRef {
|
||||
SMLoc Loc;
|
||||
unsigned MDKind, MDSlot;
|
||||
};
|
||||
DenseMap<Instruction*, std::vector<MDRef> > ForwardRefInstMetadata;
|
||||
|
||||
// Type resolution handling data structures.
|
||||
std::map<std::string, std::pair<PATypeHolder, LocTy> > ForwardRefTypes;
|
||||
@ -171,8 +180,7 @@ namespace llvm {
|
||||
bool ParseOptionalCallingConv(CallingConv::ID &CC);
|
||||
bool ParseOptionalAlignment(unsigned &Alignment);
|
||||
bool ParseOptionalStackAlignment(unsigned &Alignment);
|
||||
bool ParseInstructionMetadata(SmallVectorImpl<std::pair<unsigned,
|
||||
MDNode *> > &);
|
||||
bool ParseInstructionMetadata(Instruction *Inst);
|
||||
bool ParseOptionalCommaAlign(unsigned &Alignment, bool &AteExtraComma);
|
||||
bool ParseIndexList(SmallVectorImpl<unsigned> &Indices,bool &AteExtraComma);
|
||||
bool ParseIndexList(SmallVectorImpl<unsigned> &Indices) {
|
||||
@ -204,6 +212,7 @@ namespace llvm {
|
||||
bool ParseNamedMetadata();
|
||||
bool ParseMDString(MDString *&Result);
|
||||
bool ParseMDNodeID(MDNode *&Result);
|
||||
bool ParseMDNodeID(MDNode *&Result, unsigned &SlotNo);
|
||||
|
||||
// Type Parsing.
|
||||
bool ParseType(PATypeHolder &Result, bool AllowVoid = false);
|
||||
|
@ -1527,12 +1527,16 @@ bool BitcodeReader::ParseModule() {
|
||||
bool BitcodeReader::ParseBitcodeInto(Module *M) {
|
||||
TheModule = 0;
|
||||
|
||||
if (Buffer->getBufferSize() & 3)
|
||||
return Error("Bitcode stream should be a multiple of 4 bytes in length");
|
||||
|
||||
unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
|
||||
unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
|
||||
|
||||
if (Buffer->getBufferSize() & 3) {
|
||||
if (!isRawBitcode(BufPtr, BufEnd) && !isBitcodeWrapper(BufPtr, BufEnd))
|
||||
return Error("Invalid bitcode signature");
|
||||
else
|
||||
return Error("Bitcode stream should be a multiple of 4 bytes in length");
|
||||
}
|
||||
|
||||
// If we have a wrapper header, parse it and ignore the non-bc file contents.
|
||||
// The magic number is 0x0B17C0DE stored in little endian.
|
||||
if (isBitcodeWrapper(BufPtr, BufEnd))
|
||||
|
@ -1090,11 +1090,11 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
|
||||
|
||||
// Emit value #'s for the fixed parameters.
|
||||
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
|
||||
Vals.push_back(VE.getValueID(I.getOperand(i+3))); // fixed param.
|
||||
Vals.push_back(VE.getValueID(I.getOperand(i))); // fixed param.
|
||||
|
||||
// Emit type/value pairs for varargs params.
|
||||
if (FTy->isVarArg()) {
|
||||
for (unsigned i = 3+FTy->getNumParams(), e = I.getNumOperands();
|
||||
for (unsigned i = FTy->getNumParams(), e = I.getNumOperands()-3;
|
||||
i != e; ++i)
|
||||
PushValueAndType(I.getOperand(i), InstID, Vals, VE); // vararg
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm,
|
||||
TM(tm), MAI(tm.getMCAsmInfo()), TRI(tm.getRegisterInfo()),
|
||||
OutContext(Streamer.getContext()),
|
||||
OutStreamer(Streamer),
|
||||
LastMI(0), LastFn(0), Counter(~0U), SetCounter(0), PrevDLT(NULL) {
|
||||
LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) {
|
||||
DW = 0; MMI = 0;
|
||||
VerboseAsm = Streamer.isVerboseAsm();
|
||||
}
|
||||
@ -922,8 +922,8 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
|
||||
|
||||
// Otherwise, emit with .set (aka assignment).
|
||||
MCSymbol *SetLabel =
|
||||
OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) +
|
||||
"set" + Twine(SetCounter++));
|
||||
OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) +
|
||||
"set" + Twine(SetCounter++));
|
||||
OutStreamer.EmitAssignment(SetLabel, Diff);
|
||||
OutStreamer.EmitSymbolValue(SetLabel, Size, 0/*AddrSpace*/);
|
||||
}
|
||||
@ -1337,25 +1337,12 @@ void AsmPrinter::processDebugLoc(const MachineInstr *MI,
|
||||
if (!MAI || !DW || !MAI->doesSupportDebugInformation()
|
||||
|| !DW->ShouldEmitDwarfDebug())
|
||||
return;
|
||||
if (MI->getOpcode() == TargetOpcode::DBG_VALUE)
|
||||
return;
|
||||
DebugLoc DL = MI->getDebugLoc();
|
||||
if (DL.isUnknown())
|
||||
return;
|
||||
DILocation CurDLT = MF->getDILocation(DL);
|
||||
if (!CurDLT.getScope().Verify())
|
||||
return;
|
||||
|
||||
if (!BeforePrintingInsn) {
|
||||
if (!BeforePrintingInsn)
|
||||
// After printing instruction
|
||||
DW->EndScope(MI);
|
||||
} else if (CurDLT.getNode() != PrevDLT) {
|
||||
MCSymbol *L = DW->RecordSourceLine(CurDLT.getLineNumber(),
|
||||
CurDLT.getColumnNumber(),
|
||||
CurDLT.getScope().getNode());
|
||||
DW->BeginScope(MI, L);
|
||||
PrevDLT = CurDLT.getNode();
|
||||
}
|
||||
else
|
||||
DW->BeginScope(MI);
|
||||
}
|
||||
|
||||
|
||||
@ -1612,7 +1599,7 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const {
|
||||
|
||||
/// GetCPISymbol - Return the symbol for the specified constant pool entry.
|
||||
MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const {
|
||||
return OutContext.GetOrCreateTemporarySymbol
|
||||
return OutContext.GetOrCreateSymbol
|
||||
(Twine(MAI->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber())
|
||||
+ "_" + Twine(CPID));
|
||||
}
|
||||
@ -1625,7 +1612,7 @@ 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 {
|
||||
return OutContext.GetOrCreateTemporarySymbol
|
||||
return OutContext.GetOrCreateSymbol
|
||||
(Twine(MAI->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" +
|
||||
Twine(UID) + "_set_" + Twine(MBBID));
|
||||
}
|
||||
@ -1639,9 +1626,7 @@ MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV,
|
||||
SmallString<60> NameStr;
|
||||
Mang->getNameWithPrefix(NameStr, GV, ForcePrivate);
|
||||
NameStr.append(Suffix.begin(), Suffix.end());
|
||||
if (!GV->hasPrivateLinkage() && !ForcePrivate)
|
||||
return OutContext.GetOrCreateSymbol(NameStr.str());
|
||||
return OutContext.GetOrCreateTemporarySymbol(NameStr.str());
|
||||
return OutContext.GetOrCreateSymbol(NameStr.str());
|
||||
}
|
||||
|
||||
/// GetExternalSymbolSymbol - Return the MCSymbol for the specified
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
@ -114,10 +115,11 @@ DIE::~DIE() {
|
||||
|
||||
/// addSiblingOffset - Add a sibling offset field to the front of the DIE.
|
||||
///
|
||||
void DIE::addSiblingOffset() {
|
||||
DIEInteger *DI = new DIEInteger(0);
|
||||
DIEValue *DIE::addSiblingOffset(BumpPtrAllocator &A) {
|
||||
DIEInteger *DI = new (A) DIEInteger(0);
|
||||
Values.insert(Values.begin(), DI);
|
||||
Abbrev.AddFirstAttribute(dwarf::DW_AT_sibling, dwarf::DW_FORM_ref4);
|
||||
return DI;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
@ -276,31 +278,6 @@ void DIELabel::print(raw_ostream &O) {
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIESectionOffset Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitValue - Emit delta value.
|
||||
///
|
||||
void DIESectionOffset::EmitValue(DwarfPrinter *D, unsigned Form) const {
|
||||
bool IsSmall = Form == dwarf::DW_FORM_data4;
|
||||
D->EmitSectionOffset(Label, Section, IsSmall, IsEH);
|
||||
}
|
||||
|
||||
/// SizeOf - Determine size of delta value in bytes.
|
||||
///
|
||||
unsigned DIESectionOffset::SizeOf(const TargetData *TD, unsigned Form) const {
|
||||
if (Form == dwarf::DW_FORM_data4) return 4;
|
||||
return TD->getPointerSize();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void DIESectionOffset::print(raw_ostream &O) {
|
||||
O << "Off: " << Label->getName() << "-" << Section->getName()
|
||||
<< "-" << IsEH;
|
||||
}
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEDelta Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -153,7 +153,7 @@ namespace llvm {
|
||||
unsigned getOffset() const { return Offset; }
|
||||
unsigned getSize() const { return Size; }
|
||||
const std::vector<DIE *> &getChildren() const { return Children; }
|
||||
SmallVector<DIEValue*, 32> &getValues() { return Values; }
|
||||
const SmallVector<DIEValue*, 32> &getValues() const { return Values; }
|
||||
DIE *getParent() const { return Parent; }
|
||||
void setTag(unsigned Tag) { Abbrev.setTag(Tag); }
|
||||
void setOffset(unsigned O) { Offset = O; }
|
||||
@ -171,8 +171,10 @@ namespace llvm {
|
||||
unsigned getSiblingOffset() const { return Offset + Size; }
|
||||
|
||||
/// addSiblingOffset - Add a sibling offset field to the front of the DIE.
|
||||
/// The caller is responsible for deleting the return value at or after the
|
||||
/// same time it destroys this DIE.
|
||||
///
|
||||
void addSiblingOffset();
|
||||
DIEValue *addSiblingOffset(BumpPtrAllocator &A);
|
||||
|
||||
/// addChild - Add a child to the DIE.
|
||||
///
|
||||
@ -322,38 +324,6 @@ namespace llvm {
|
||||
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
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIESectionOffset - A section offset DIE.
|
||||
///
|
||||
class DIESectionOffset : public DIEValue {
|
||||
const MCSymbol *Label;
|
||||
const MCSymbol *Section;
|
||||
bool IsEH : 1;
|
||||
public:
|
||||
DIESectionOffset(const MCSymbol *Lab, const MCSymbol *Sec,
|
||||
bool isEH = false)
|
||||
: DIEValue(isSectionOffset), Label(Lab), Section(Sec),
|
||||
IsEH(isEH) {}
|
||||
|
||||
/// EmitValue - Emit section offset.
|
||||
///
|
||||
virtual void EmitValue(DwarfPrinter *D, unsigned Form) const;
|
||||
|
||||
/// SizeOf - Determine size of section offset value in bytes.
|
||||
///
|
||||
virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const;
|
||||
|
||||
// Implement isa/cast/dyncast.
|
||||
static bool classof(const DIESectionOffset *) { return true; }
|
||||
static bool classof(const DIEValue *D) {
|
||||
return D->getType() == isSectionOffset;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void print(raw_ostream &O);
|
||||
#endif
|
||||
|
@ -92,11 +92,11 @@ class CompileUnit {
|
||||
|
||||
/// addGlobal - Add a new global entity to the compile unit.
|
||||
///
|
||||
void addGlobal(const std::string &Name, DIE *Die) { Globals[Name] = Die; }
|
||||
void addGlobal(StringRef Name, DIE *Die) { Globals[Name] = Die; }
|
||||
|
||||
/// addGlobalType - Add a new global type to the compile unit.
|
||||
///
|
||||
void addGlobalType(const std::string &Name, DIE *Die) {
|
||||
void addGlobalType(StringRef Name, DIE *Die) {
|
||||
GlobalTypes[Name] = Die;
|
||||
}
|
||||
|
||||
@ -149,20 +149,26 @@ class DbgVariable {
|
||||
DIVariable Var; // Variable Descriptor.
|
||||
unsigned FrameIndex; // Variable frame index.
|
||||
const MachineInstr *DbgValueMInsn; // DBG_VALUE
|
||||
// DbgValueLabel - DBG_VALUE is effective from this label.
|
||||
MCSymbol *DbgValueLabel;
|
||||
DbgVariable *const AbstractVar; // Abstract variable for this variable.
|
||||
DIE *TheDIE;
|
||||
public:
|
||||
// AbsVar may be NULL.
|
||||
DbgVariable(DIVariable V, unsigned I, DbgVariable *AbsVar)
|
||||
: Var(V), FrameIndex(I), DbgValueMInsn(0), AbstractVar(AbsVar), TheDIE(0) {}
|
||||
: Var(V), FrameIndex(I), DbgValueMInsn(0),
|
||||
DbgValueLabel(0), AbstractVar(AbsVar), TheDIE(0) {}
|
||||
DbgVariable(DIVariable V, const MachineInstr *MI, DbgVariable *AbsVar)
|
||||
: Var(V), FrameIndex(0), DbgValueMInsn(MI), AbstractVar(AbsVar), TheDIE(0)
|
||||
: Var(V), FrameIndex(0), DbgValueMInsn(MI), DbgValueLabel(0),
|
||||
AbstractVar(AbsVar), TheDIE(0)
|
||||
{}
|
||||
|
||||
// Accessors.
|
||||
DIVariable getVariable() const { return Var; }
|
||||
unsigned getFrameIndex() const { return FrameIndex; }
|
||||
const MachineInstr *getDbgValue() const { return DbgValueMInsn; }
|
||||
MCSymbol *getDbgValueLabel() const { return DbgValueLabel; }
|
||||
void setDbgValueLabel(MCSymbol *L) { DbgValueLabel = L; }
|
||||
DbgVariable *getAbstractVariable() const { return AbstractVar; }
|
||||
void setDIE(DIE *D) { TheDIE = D; }
|
||||
DIE *getDIE() const { return TheDIE; }
|
||||
@ -224,14 +230,14 @@ class DbgScope {
|
||||
|
||||
void fixInstructionMarkers(DenseMap<const MachineInstr *,
|
||||
unsigned> &MIIndexMap) {
|
||||
assert (getFirstInsn() && "First instruction is missing!");
|
||||
assert(getFirstInsn() && "First instruction is missing!");
|
||||
|
||||
// Use the end of last child scope as end of this scope.
|
||||
const SmallVector<DbgScope *, 4> &Scopes = getScopes();
|
||||
const MachineInstr *LastInsn = getFirstInsn();
|
||||
unsigned LIndex = 0;
|
||||
if (Scopes.empty()) {
|
||||
assert (getLastInsn() && "Inner most scope does not have last insn!");
|
||||
assert(getLastInsn() && "Inner most scope does not have last insn!");
|
||||
return;
|
||||
}
|
||||
for (SmallVector<DbgScope *, 4>::const_iterator SI = Scopes.begin(),
|
||||
@ -295,15 +301,15 @@ DbgScope::~DbgScope() {
|
||||
DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T)
|
||||
: DwarfPrinter(OS, A, T), ModuleCU(0),
|
||||
AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(),
|
||||
DIEValues(), SectionSourceLines(), didInitial(false), shouldEmit(false),
|
||||
CurrentFnDbgScope(0), DebugTimer(0) {
|
||||
DIEBlocks(), SectionSourceLines(), didInitial(false), shouldEmit(false),
|
||||
CurrentFnDbgScope(0), PrevDILoc(0), DebugTimer(0) {
|
||||
NextStringPoolNumber = 0;
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer = new Timer("Dwarf Debug Writer");
|
||||
}
|
||||
DwarfDebug::~DwarfDebug() {
|
||||
for (unsigned j = 0, M = DIEValues.size(); j < M; ++j)
|
||||
delete DIEValues[j];
|
||||
for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j)
|
||||
DIEBlocks[j]->~DIEBlock();
|
||||
|
||||
delete DebugTimer;
|
||||
}
|
||||
@ -343,8 +349,7 @@ void DwarfDebug::assignAbbrevNumber(DIEAbbrev &Abbrev) {
|
||||
/// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug
|
||||
/// information entry.
|
||||
DIEEntry *DwarfDebug::createDIEEntry(DIE *Entry) {
|
||||
DIEEntry *Value = new DIEEntry(Entry);
|
||||
DIEValues.push_back(Value);
|
||||
DIEEntry *Value = new (DIEValueAllocator) DIEEntry(Entry);
|
||||
return Value;
|
||||
}
|
||||
|
||||
@ -353,8 +358,7 @@ DIEEntry *DwarfDebug::createDIEEntry(DIE *Entry) {
|
||||
void DwarfDebug::addUInt(DIE *Die, unsigned Attribute,
|
||||
unsigned Form, uint64_t Integer) {
|
||||
if (!Form) Form = DIEInteger::BestForm(false, Integer);
|
||||
DIEValue *Value = new DIEInteger(Integer);
|
||||
DIEValues.push_back(Value);
|
||||
DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer);
|
||||
Die->addValue(Attribute, Form, Value);
|
||||
}
|
||||
|
||||
@ -363,8 +367,7 @@ void DwarfDebug::addUInt(DIE *Die, unsigned Attribute,
|
||||
void DwarfDebug::addSInt(DIE *Die, unsigned Attribute,
|
||||
unsigned Form, int64_t Integer) {
|
||||
if (!Form) Form = DIEInteger::BestForm(true, Integer);
|
||||
DIEValue *Value = new DIEInteger(Integer);
|
||||
DIEValues.push_back(Value);
|
||||
DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer);
|
||||
Die->addValue(Attribute, Form, Value);
|
||||
}
|
||||
|
||||
@ -372,8 +375,7 @@ void DwarfDebug::addSInt(DIE *Die, unsigned Attribute,
|
||||
/// keeps string reference.
|
||||
void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
StringRef String) {
|
||||
DIEValue *Value = new DIEString(String);
|
||||
DIEValues.push_back(Value);
|
||||
DIEValue *Value = new (DIEValueAllocator) DIEString(String);
|
||||
Die->addValue(Attribute, Form, Value);
|
||||
}
|
||||
|
||||
@ -381,18 +383,7 @@ void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
///
|
||||
void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
const MCSymbol *Label) {
|
||||
DIEValue *Value = new DIELabel(Label);
|
||||
DIEValues.push_back(Value);
|
||||
Die->addValue(Attribute, Form, Value);
|
||||
}
|
||||
|
||||
/// addSectionOffset - Add a section offset label attribute data and value.
|
||||
///
|
||||
void DwarfDebug::addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
const MCSymbol *Label,const MCSymbol *Section,
|
||||
bool isEH) {
|
||||
DIEValue *Value = new DIESectionOffset(Label, Section, isEH);
|
||||
DIEValues.push_back(Value);
|
||||
DIEValue *Value = new (DIEValueAllocator) DIELabel(Label);
|
||||
Die->addValue(Attribute, Form, Value);
|
||||
}
|
||||
|
||||
@ -400,8 +391,7 @@ void DwarfDebug::addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
///
|
||||
void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
const MCSymbol *Hi, const MCSymbol *Lo) {
|
||||
DIEValue *Value = new DIEDelta(Hi, Lo);
|
||||
DIEValues.push_back(Value);
|
||||
DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo);
|
||||
Die->addValue(Attribute, Form, Value);
|
||||
}
|
||||
|
||||
@ -410,7 +400,7 @@ void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
void DwarfDebug::addBlock(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
DIEBlock *Block) {
|
||||
Block->ComputeSize(TD);
|
||||
DIEValues.push_back(Block);
|
||||
DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on.
|
||||
Die->addValue(Attribute, Block->BestForm(), Block);
|
||||
}
|
||||
|
||||
@ -457,8 +447,8 @@ void DwarfDebug::addSourceLine(DIE *Die, const DISubprogram *SP) {
|
||||
unsigned Line = SP->getLineNumber();
|
||||
if (!SP->getContext().Verify())
|
||||
return;
|
||||
unsigned FileID = GetOrCreateSourceID(SP->getContext().getDirectory(),
|
||||
SP->getContext().getFilename());
|
||||
unsigned FileID = GetOrCreateSourceID(SP->getDirectory(),
|
||||
SP->getFilename());
|
||||
assert(FileID && "Invalid file id");
|
||||
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
|
||||
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
|
||||
@ -564,7 +554,7 @@ void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die,
|
||||
// Decode the original location, and use that as the start of the byref
|
||||
// variable's location.
|
||||
unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false);
|
||||
DIEBlock *Block = new DIEBlock();
|
||||
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
|
||||
|
||||
if (Location.isReg()) {
|
||||
if (Reg < 32) {
|
||||
@ -696,15 +686,15 @@ void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die,
|
||||
}
|
||||
|
||||
// Get the offsets for the forwarding field and the variable field.
|
||||
unsigned int forwardingFieldOffset =
|
||||
unsigned forwardingFieldOffset =
|
||||
DIDerivedType(forwardingField.getNode()).getOffsetInBits() >> 3;
|
||||
unsigned int varFieldOffset =
|
||||
unsigned varFieldOffset =
|
||||
DIDerivedType(varField.getNode()).getOffsetInBits() >> 3;
|
||||
|
||||
// Decode the original location, and use that as the start of the byref
|
||||
// variable's location.
|
||||
unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false);
|
||||
DIEBlock *Block = new DIEBlock();
|
||||
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
|
||||
|
||||
if (Location.isReg()) {
|
||||
if (Reg < 32)
|
||||
@ -759,7 +749,7 @@ void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die,
|
||||
void DwarfDebug::addAddress(DIE *Die, unsigned Attribute,
|
||||
const MachineLocation &Location) {
|
||||
unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false);
|
||||
DIEBlock *Block = new DIEBlock();
|
||||
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
|
||||
|
||||
if (Location.isReg()) {
|
||||
if (Reg < 32) {
|
||||
@ -1106,7 +1096,7 @@ DIE *DwarfDebug::createMemberDIE(const DIDerivedType &DT) {
|
||||
|
||||
addSourceLine(MemberDie, &DT);
|
||||
|
||||
DIEBlock *MemLocationDie = new DIEBlock();
|
||||
DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock();
|
||||
addUInt(MemLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
|
||||
|
||||
uint64_t Size = DT.getSizeInBits();
|
||||
@ -1142,7 +1132,7 @@ DIE *DwarfDebug::createMemberDIE(const DIDerivedType &DT) {
|
||||
// expression to extract appropriate offset from vtable.
|
||||
// BaseAddr = ObAddr + *((*ObAddr) - Offset)
|
||||
|
||||
DIEBlock *VBaseLocationDie = new DIEBlock();
|
||||
DIEBlock *VBaseLocationDie = new (DIEValueAllocator) DIEBlock();
|
||||
addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_dup);
|
||||
addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
|
||||
addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
|
||||
@ -1208,7 +1198,7 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) {
|
||||
unsigned VK = SP.getVirtuality();
|
||||
if (VK) {
|
||||
addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK);
|
||||
DIEBlock *Block = new DIEBlock();
|
||||
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
|
||||
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
|
||||
addUInt(Block, 0, dwarf::DW_FORM_data1, SP.getVirtualIndex());
|
||||
addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block);
|
||||
@ -1244,13 +1234,13 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) {
|
||||
return SPDie;
|
||||
}
|
||||
|
||||
/// getUpdatedDbgScope - Find or create DbgScope assicated with the instruction.
|
||||
/// Initialize scope and update scope hierarchy.
|
||||
/// getUpdatedDbgScope - Find DbgScope assicated with the instruction.
|
||||
/// Update scope hierarchy. Create abstract scope if required.
|
||||
DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI,
|
||||
MDNode *InlinedAt) {
|
||||
assert (N && "Invalid Scope encoding!");
|
||||
assert (MI && "Missing machine instruction!");
|
||||
bool GetConcreteScope = (MI && InlinedAt);
|
||||
MDNode *InlinedAt) {
|
||||
assert(N && "Invalid Scope encoding!");
|
||||
assert(MI && "Missing machine instruction!");
|
||||
bool isAConcreteScope = InlinedAt != 0;
|
||||
|
||||
DbgScope *NScope = NULL;
|
||||
|
||||
@ -1258,17 +1248,17 @@ DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI,
|
||||
NScope = DbgScopeMap.lookup(InlinedAt);
|
||||
else
|
||||
NScope = DbgScopeMap.lookup(N);
|
||||
assert (NScope && "Unable to find working scope!");
|
||||
assert(NScope && "Unable to find working scope!");
|
||||
|
||||
if (NScope->getFirstInsn())
|
||||
return NScope;
|
||||
|
||||
DbgScope *Parent = NULL;
|
||||
if (GetConcreteScope) {
|
||||
if (isAConcreteScope) {
|
||||
DILocation IL(InlinedAt);
|
||||
Parent = getUpdatedDbgScope(IL.getScope().getNode(), MI,
|
||||
IL.getOrigLocation().getNode());
|
||||
assert (Parent && "Unable to find Parent scope!");
|
||||
assert(Parent && "Unable to find Parent scope!");
|
||||
NScope->setParent(Parent);
|
||||
Parent->addScope(NScope);
|
||||
} else if (DIDescriptor(N).isLexicalBlock()) {
|
||||
@ -1286,7 +1276,7 @@ DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI,
|
||||
CurrentFnDbgScope = NScope;
|
||||
}
|
||||
|
||||
if (GetConcreteScope) {
|
||||
if (isAConcreteScope) {
|
||||
ConcreteScopes[InlinedAt] = NScope;
|
||||
getOrCreateAbstractScope(N);
|
||||
}
|
||||
@ -1295,7 +1285,7 @@ DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI,
|
||||
}
|
||||
|
||||
DbgScope *DwarfDebug::getOrCreateAbstractScope(MDNode *N) {
|
||||
assert (N && "Invalid Scope encoding!");
|
||||
assert(N && "Invalid Scope encoding!");
|
||||
|
||||
DbgScope *AScope = AbstractScopes.lookup(N);
|
||||
if (AScope)
|
||||
@ -1377,7 +1367,7 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) {
|
||||
DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) {
|
||||
MCSymbol *Start = Scope->getStartLabel();
|
||||
MCSymbol *End = Scope->getEndLabel();
|
||||
if (Start == 0) return 0;
|
||||
if (Start == 0 || End == 0) return 0;
|
||||
|
||||
assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
|
||||
assert(End->isDefined() && "Invalid end label for an inlined scope!");
|
||||
@ -1400,7 +1390,7 @@ DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) {
|
||||
DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
|
||||
MCSymbol *StartLabel = Scope->getStartLabel();
|
||||
MCSymbol *EndLabel = Scope->getEndLabel();
|
||||
if (StartLabel == 0) return 0;
|
||||
if (StartLabel == 0 || EndLabel == 0) return 0;
|
||||
|
||||
assert(StartLabel->isDefined() &&
|
||||
"Invalid starting label for an inlined scope!");
|
||||
@ -1413,7 +1403,7 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
|
||||
|
||||
DISubprogram InlinedSP = getDISubprogram(DS.getNode());
|
||||
DIE *OriginDIE = ModuleCU->getDIE(InlinedSP.getNode());
|
||||
assert (OriginDIE && "Unable to find Origin DIE!");
|
||||
assert(OriginDIE && "Unable to find Origin DIE!");
|
||||
addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
|
||||
dwarf::DW_FORM_ref4, OriginDIE);
|
||||
|
||||
@ -1477,9 +1467,9 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) {
|
||||
DISubprogram InlinedSP = getDISubprogram(DS.getNode());
|
||||
DIE *OriginSPDIE = ModuleCU->getDIE(InlinedSP.getNode());
|
||||
(void) OriginSPDIE;
|
||||
assert (OriginSPDIE && "Unable to find Origin DIE for the SP!");
|
||||
assert(OriginSPDIE && "Unable to find Origin DIE for the SP!");
|
||||
DIE *AbsDIE = DV->getAbstractVariable()->getDIE();
|
||||
assert (AbsDIE && "Unable to find Origin DIE for the Variable!");
|
||||
assert(AbsDIE && "Unable to find Origin DIE for the Variable!");
|
||||
addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin,
|
||||
dwarf::DW_FORM_ref4, AbsDIE);
|
||||
}
|
||||
@ -1508,12 +1498,18 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) {
|
||||
MachineLocation Location;
|
||||
Location.set(DbgValueInsn->getOperand(0).getReg());
|
||||
addAddress(VariableDie, dwarf::DW_AT_location, Location);
|
||||
if (MCSymbol *VS = DV->getDbgValueLabel())
|
||||
addLabel(VariableDie, dwarf::DW_AT_start_scope, dwarf::DW_FORM_addr,
|
||||
VS);
|
||||
} else if (DbgValueInsn->getOperand(0).getType() ==
|
||||
MachineOperand::MO_Immediate) {
|
||||
DIEBlock *Block = new DIEBlock();
|
||||
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
|
||||
unsigned Imm = DbgValueInsn->getOperand(0).getImm();
|
||||
addUInt(Block, 0, dwarf::DW_FORM_udata, Imm);
|
||||
addBlock(VariableDie, dwarf::DW_AT_const_value, 0, Block);
|
||||
if (MCSymbol *VS = DV->getDbgValueLabel())
|
||||
addLabel(VariableDie, dwarf::DW_AT_start_scope, dwarf::DW_FORM_addr,
|
||||
VS);
|
||||
} else {
|
||||
//FIXME : Handle other operand types.
|
||||
delete VariableDie;
|
||||
@ -1523,7 +1519,8 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) {
|
||||
} else {
|
||||
MachineLocation Location;
|
||||
unsigned FrameReg;
|
||||
int Offset = RI->getFrameIndexReference(*MF, DV->getFrameIndex(), FrameReg);
|
||||
int Offset = RI->getFrameIndexReference(*MF, DV->getFrameIndex(),
|
||||
FrameReg);
|
||||
Location.set(FrameReg, Offset);
|
||||
|
||||
if (VD.hasComplexAddress())
|
||||
@ -1576,10 +1573,9 @@ DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) {
|
||||
else
|
||||
ScopeDIE = updateSubprogramScopeDIE(DS.getNode());
|
||||
}
|
||||
else {
|
||||
else
|
||||
ScopeDIE = constructLexicalScopeDIE(Scope);
|
||||
if (!ScopeDIE) return NULL;
|
||||
}
|
||||
if (!ScopeDIE) return NULL;
|
||||
|
||||
// Add variables to scope.
|
||||
const SmallVector<DbgVariable *, 8> &Variables = Scope->getVariables();
|
||||
@ -1608,7 +1604,7 @@ DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) {
|
||||
/// source file names. If none currently exists, create a new id and insert it
|
||||
/// in the SourceIds map. This can update DirectoryNames and SourceFileNames
|
||||
/// maps as well.
|
||||
unsigned DwarfDebug::GetOrCreateSourceID(StringRef DirName, StringRef FileName) {
|
||||
unsigned DwarfDebug::GetOrCreateSourceID(StringRef DirName, StringRef FileName){
|
||||
unsigned DId;
|
||||
StringMap<unsigned>::iterator DI = DirectoryIdMap.find(DirName);
|
||||
if (DI != DirectoryIdMap.end()) {
|
||||
@ -1666,15 +1662,19 @@ void DwarfDebug::constructCompileUnit(MDNode *N) {
|
||||
unsigned ID = GetOrCreateSourceID(Dir, FN);
|
||||
|
||||
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
|
||||
// FIXME: Why getting the delta between two identical labels??
|
||||
addSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
|
||||
getTempLabel("section_line"), getTempLabel("section_line"),
|
||||
false);
|
||||
addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string,
|
||||
DIUnit.getProducer());
|
||||
addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1,
|
||||
DIUnit.getLanguage());
|
||||
addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
|
||||
addLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
|
||||
getTempLabel("text_begin"));
|
||||
addLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
|
||||
getTempLabel("text_end"));
|
||||
// DW_AT_stmt_list is a offset of line number information for this
|
||||
// compile unit in debug_line section. It is always zero when only one
|
||||
// compile unit is emitted in one object file.
|
||||
addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
|
||||
|
||||
if (!Dir.empty())
|
||||
addString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir);
|
||||
@ -1717,13 +1717,13 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
|
||||
DIDescriptor GVContext = DI_GV.getContext();
|
||||
// Do not create specification DIE if context is either compile unit
|
||||
// or a subprogram.
|
||||
if (DI_GV.isDefinition() && !GVContext.isCompileUnit()
|
||||
&& !GVContext.isFile() && !GVContext.isSubprogram()) {
|
||||
if (DI_GV.isDefinition() && !GVContext.isCompileUnit() &&
|
||||
!GVContext.isFile() && !GVContext.isSubprogram()) {
|
||||
// Create specification DIE.
|
||||
DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable);
|
||||
addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification,
|
||||
dwarf::DW_FORM_ref4, VariableDie);
|
||||
DIEBlock *Block = new DIEBlock();
|
||||
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
|
||||
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
|
||||
addLabel(Block, 0, dwarf::DW_FORM_udata,
|
||||
Asm->Mang->getSymbol(DI_GV.getGlobal()));
|
||||
@ -1731,7 +1731,7 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
|
||||
addUInt(VariableDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
|
||||
ModuleCU->addDie(VariableSpecDIE);
|
||||
} else {
|
||||
DIEBlock *Block = new DIEBlock();
|
||||
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
|
||||
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
|
||||
addLabel(Block, 0, dwarf::DW_FORM_udata,
|
||||
Asm->Mang->getSymbol(DI_GV.getGlobal()));
|
||||
@ -1745,7 +1745,7 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
|
||||
DIType GTy = DI_GV.getType();
|
||||
if (GTy.isCompositeType() && !GTy.getName().empty()) {
|
||||
DIEEntry *Entry = ModuleCU->getDIEEntry(GTy.getNode());
|
||||
assert (Entry && "Missing global type!");
|
||||
assert(Entry && "Missing global type!");
|
||||
ModuleCU->addGlobalType(GTy.getName(), Entry->getEntry());
|
||||
}
|
||||
return;
|
||||
@ -1783,12 +1783,11 @@ void DwarfDebug::constructSubprogramDIE(MDNode *N) {
|
||||
void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) {
|
||||
this->M = M;
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->startTimer();
|
||||
|
||||
if (!MAI->doesSupportDebugInformation())
|
||||
return;
|
||||
|
||||
TimeRegion Timer(DebugTimer);
|
||||
|
||||
DebugInfoFinder DbgFinder;
|
||||
DbgFinder.processModule(*M);
|
||||
|
||||
@ -1836,9 +1835,6 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) {
|
||||
|
||||
// Emit initial sections
|
||||
emitInitial();
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->stopTimer();
|
||||
}
|
||||
|
||||
/// endModule - Emit all Dwarf sections that should come after the content.
|
||||
@ -1847,8 +1843,7 @@ void DwarfDebug::endModule() {
|
||||
if (!ModuleCU)
|
||||
return;
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->startTimer();
|
||||
TimeRegion Timer(DebugTimer);
|
||||
|
||||
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
|
||||
for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
|
||||
@ -1871,7 +1866,7 @@ void DwarfDebug::endModule() {
|
||||
if (!NDie) continue;
|
||||
addDIEEntry(SPDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie);
|
||||
// FIXME - This is not the correct approach.
|
||||
// addDIEEntry(NDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie);
|
||||
//addDIEEntry(NDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie
|
||||
}
|
||||
|
||||
// Standard sections final addresses.
|
||||
@ -1932,9 +1927,6 @@ void DwarfDebug::endModule() {
|
||||
|
||||
delete ModuleCU;
|
||||
ModuleCU = NULL; // Reset for the next Module, if any.
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->stopTimer();
|
||||
}
|
||||
|
||||
/// findAbstractVariable - Find abstract variable, if any, associated with Var.
|
||||
@ -1971,10 +1963,11 @@ DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var,
|
||||
if (!Scope)
|
||||
return NULL;
|
||||
|
||||
AbsDbgVariable = new DbgVariable(Var, MI,
|
||||
AbsDbgVariable = new DbgVariable(Var, MI,
|
||||
NULL /* No more-abstract variable*/);
|
||||
Scope->addVariable(AbsDbgVariable);
|
||||
AbstractVariables[Var.getNode()] = AbsDbgVariable;
|
||||
DbgValueStartMap[MI] = AbsDbgVariable;
|
||||
return AbsDbgVariable;
|
||||
}
|
||||
|
||||
@ -2010,16 +2003,19 @@ void DwarfDebug::collectVariableInfo() {
|
||||
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
|
||||
II != IE; ++II) {
|
||||
const MachineInstr *MInsn = II;
|
||||
if (MInsn->getOpcode() != TargetOpcode::DBG_VALUE)
|
||||
if (!MInsn->isDebugValue())
|
||||
continue;
|
||||
|
||||
// FIXME : Lift this restriction.
|
||||
if (MInsn->getNumOperands() != 3)
|
||||
continue;
|
||||
DIVariable DV((MDNode*)(MInsn->getOperand(MInsn->getNumOperands() - 1).getMetadata()));
|
||||
DIVariable DV((MDNode*)(MInsn->getOperand(MInsn->getNumOperands()
|
||||
- 1).getMetadata()));
|
||||
if (DV.getTag() == dwarf::DW_TAG_arg_variable) {
|
||||
// FIXME Handle inlined subroutine arguments.
|
||||
DbgVariable *ArgVar = new DbgVariable(DV, MInsn, NULL);
|
||||
CurrentFnDbgScope->addVariable(ArgVar);
|
||||
DbgValueStartMap[MInsn] = ArgVar;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2034,19 +2030,54 @@ void DwarfDebug::collectVariableInfo() {
|
||||
if (!Scope)
|
||||
continue;
|
||||
|
||||
DbgVariable *AbsDbgVariable = findAbstractVariable(DV, MInsn,
|
||||
ScopeLoc);
|
||||
DbgVariable *AbsDbgVariable = findAbstractVariable(DV, MInsn, ScopeLoc);
|
||||
DbgVariable *RegVar = new DbgVariable(DV, MInsn, AbsDbgVariable);
|
||||
DbgValueStartMap[MInsn] = RegVar;
|
||||
Scope->addVariable(RegVar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// beginScope - Process beginning of a scope starting at Label.
|
||||
void DwarfDebug::beginScope(const MachineInstr *MI, MCSymbol *Label) {
|
||||
/// beginScope - Process beginning of a scope.
|
||||
void DwarfDebug::beginScope(const MachineInstr *MI) {
|
||||
// Check location.
|
||||
DebugLoc DL = MI->getDebugLoc();
|
||||
if (DL.isUnknown())
|
||||
return;
|
||||
DILocation DILoc = MF->getDILocation(DL);
|
||||
if (!DILoc.getScope().Verify())
|
||||
return;
|
||||
|
||||
// Check and update last known location info.
|
||||
if(DILoc.getNode() == PrevDILoc)
|
||||
return;
|
||||
|
||||
// DBG_VALUE instruction establishes new value.
|
||||
if (MI->isDebugValue()) {
|
||||
DenseMap<const MachineInstr *, DbgVariable *>::iterator DI
|
||||
= DbgValueStartMap.find(MI);
|
||||
if (DI != DbgValueStartMap.end()) {
|
||||
MCSymbol *Label = recordSourceLine(DILoc.getLineNumber(),
|
||||
DILoc.getColumnNumber(),
|
||||
DILoc.getScope().getNode());
|
||||
PrevDILoc = DILoc.getNode();
|
||||
DI->second->setDbgValueLabel(Label);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit a label to indicate location change. This is used for line
|
||||
// table even if this instruction does start a new scope.
|
||||
MCSymbol *Label = recordSourceLine(DILoc.getLineNumber(),
|
||||
DILoc.getColumnNumber(),
|
||||
DILoc.getScope().getNode());
|
||||
PrevDILoc = DILoc.getNode();
|
||||
|
||||
// update DbgScope if this instruction starts a new scope.
|
||||
InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI);
|
||||
if (I == DbgScopeBeginMap.end())
|
||||
return;
|
||||
|
||||
ScopeVector &SD = I->second;
|
||||
for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end();
|
||||
SDI != SDE; ++SDI)
|
||||
@ -2055,6 +2086,19 @@ void DwarfDebug::beginScope(const MachineInstr *MI, MCSymbol *Label) {
|
||||
|
||||
/// endScope - Process end of a scope.
|
||||
void DwarfDebug::endScope(const MachineInstr *MI) {
|
||||
// Ignore DBG_VALUE instruction.
|
||||
if (MI->isDebugValue())
|
||||
return;
|
||||
|
||||
// Check location.
|
||||
DebugLoc DL = MI->getDebugLoc();
|
||||
if (DL.isUnknown())
|
||||
return;
|
||||
DILocation DILoc = MF->getDILocation(DL);
|
||||
if (!DILoc.getScope().Verify())
|
||||
return;
|
||||
|
||||
// Emit a label and update DbgScope if this instruction ends a scope.
|
||||
InsnToDbgScopeMapTy::iterator I = DbgScopeEndMap.find(MI);
|
||||
if (I == DbgScopeEndMap.end())
|
||||
return;
|
||||
@ -2094,7 +2138,7 @@ void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) {
|
||||
}
|
||||
|
||||
/// extractScopeInformation - Scan machine instructions in this function
|
||||
/// and collect DbgScopes. Return true, if atleast one scope was found.
|
||||
/// and collect DbgScopes. Return true, if at least one scope was found.
|
||||
bool DwarfDebug::extractScopeInformation() {
|
||||
// If scope information was extracted using .dbg intrinsics then there is not
|
||||
// any need to extract these information by scanning each instruction.
|
||||
@ -2110,12 +2154,13 @@ bool DwarfDebug::extractScopeInformation() {
|
||||
II != IE; ++II) {
|
||||
const MachineInstr *MInsn = II;
|
||||
// FIXME : Remove DBG_VALUE check.
|
||||
if (MInsn->getOpcode() == TargetOpcode::DBG_VALUE) continue;
|
||||
if (MInsn->isDebugValue()) continue;
|
||||
MIIndexMap[MInsn] = MIIndex++;
|
||||
DebugLoc DL = MInsn->getDebugLoc();
|
||||
if (DL.isUnknown()) continue;
|
||||
DILocation DLT = MF->getDILocation(DL);
|
||||
DIScope DLTScope = DLT.getScope();
|
||||
if (!DLTScope.getNode()) continue;
|
||||
// There is no need to create another DIE for compile unit. For all
|
||||
// other scopes, create one DbgScope now. This will be translated
|
||||
// into a scope DIE at the end.
|
||||
@ -2132,11 +2177,12 @@ bool DwarfDebug::extractScopeInformation() {
|
||||
II != IE; ++II) {
|
||||
const MachineInstr *MInsn = II;
|
||||
// FIXME : Remove DBG_VALUE check.
|
||||
if (MInsn->getOpcode() == TargetOpcode::DBG_VALUE) continue;
|
||||
if (MInsn->isDebugValue()) continue;
|
||||
DebugLoc DL = MInsn->getDebugLoc();
|
||||
if (DL.isUnknown()) continue;
|
||||
DILocation DLT = MF->getDILocation(DL);
|
||||
DIScope DLTScope = DLT.getScope();
|
||||
if (!DLTScope.getNode()) continue;
|
||||
// There is no need to create another DIE for compile unit. For all
|
||||
// other scopes, create one DbgScope now. This will be translated
|
||||
// into a scope DIE at the end.
|
||||
@ -2159,7 +2205,7 @@ bool DwarfDebug::extractScopeInformation() {
|
||||
SmallVector<DbgScope *, 4> WorkList;
|
||||
WorkList.push_back(CurrentFnDbgScope);
|
||||
while (!WorkList.empty()) {
|
||||
DbgScope *S = WorkList.back(); WorkList.pop_back();
|
||||
DbgScope *S = WorkList.pop_back_val();
|
||||
|
||||
const SmallVector<DbgScope *, 4> &Children = S->getScopes();
|
||||
if (!Children.empty())
|
||||
@ -2170,7 +2216,7 @@ bool DwarfDebug::extractScopeInformation() {
|
||||
if (S->isAbstractScope())
|
||||
continue;
|
||||
const MachineInstr *MI = S->getFirstInsn();
|
||||
assert (MI && "DbgScope does not have first instruction!");
|
||||
assert(MI && "DbgScope does not have first instruction!");
|
||||
|
||||
InsnToDbgScopeMapTy::iterator IDI = DbgScopeBeginMap.find(MI);
|
||||
if (IDI != DbgScopeBeginMap.end())
|
||||
@ -2179,7 +2225,7 @@ bool DwarfDebug::extractScopeInformation() {
|
||||
DbgScopeBeginMap[MI].push_back(S);
|
||||
|
||||
MI = S->getLastInsn();
|
||||
assert (MI && "DbgScope does not have last instruction!");
|
||||
assert(MI && "DbgScope does not have last instruction!");
|
||||
IDI = DbgScopeEndMap.find(MI);
|
||||
if (IDI != DbgScopeEndMap.end())
|
||||
IDI->second.push_back(S);
|
||||
@ -2196,12 +2242,10 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
|
||||
this->MF = MF;
|
||||
|
||||
if (!ShouldEmitDwarfDebug()) return;
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->startTimer();
|
||||
|
||||
if (!extractScopeInformation())
|
||||
return;
|
||||
|
||||
TimeRegion Timer(DebugTimer);
|
||||
|
||||
collectVariableInfo();
|
||||
|
||||
@ -2225,20 +2269,15 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
|
||||
|
||||
recordSourceLine(Line, Col, DLT.getScope().getNode());
|
||||
}
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->stopTimer();
|
||||
}
|
||||
|
||||
/// endFunction - Gather and emit post-function debug information.
|
||||
///
|
||||
void DwarfDebug::endFunction(const MachineFunction *MF) {
|
||||
if (!ShouldEmitDwarfDebug()) return;
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->startTimer();
|
||||
|
||||
if (DbgScopeMap.empty())
|
||||
return;
|
||||
if (DbgScopeMap.empty()) return;
|
||||
|
||||
TimeRegion Timer(DebugTimer);
|
||||
|
||||
if (CurrentFnDbgScope) {
|
||||
// Define end label for subprogram.
|
||||
@ -2271,14 +2310,12 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
|
||||
DeleteContainerSeconds(DbgScopeMap);
|
||||
DbgScopeBeginMap.clear();
|
||||
DbgScopeEndMap.clear();
|
||||
DbgValueStartMap.clear();
|
||||
ConcreteScopes.clear();
|
||||
DeleteContainerSeconds(AbstractScopes);
|
||||
AbstractScopesList.clear();
|
||||
AbstractVariables.clear();
|
||||
Lines.clear();
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->stopTimer();
|
||||
}
|
||||
|
||||
/// recordSourceLine - Register a source line with debug info. Returns the
|
||||
@ -2288,8 +2325,7 @@ MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, MDNode *S) {
|
||||
if (!MMI)
|
||||
return 0;
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->startTimer();
|
||||
TimeRegion Timer(DebugTimer);
|
||||
|
||||
StringRef Dir;
|
||||
StringRef Fn;
|
||||
@ -2314,9 +2350,6 @@ MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, MDNode *S) {
|
||||
MCSymbol *Label = MMI->getContext().CreateTempSymbol();
|
||||
Lines.push_back(SrcLineInfo(Line, Col, Src, Label));
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->stopTimer();
|
||||
|
||||
Asm->OutStreamer.EmitLabel(Label);
|
||||
return Label;
|
||||
}
|
||||
@ -2328,15 +2361,8 @@ MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, MDNode *S) {
|
||||
/// well.
|
||||
unsigned DwarfDebug::getOrCreateSourceID(const std::string &DirName,
|
||||
const std::string &FileName) {
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->startTimer();
|
||||
|
||||
unsigned SrcId = GetOrCreateSourceID(DirName.c_str(), FileName.c_str());
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->stopTimer();
|
||||
|
||||
return SrcId;
|
||||
TimeRegion Timer(DebugTimer);
|
||||
return GetOrCreateSourceID(DirName.c_str(), FileName.c_str());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -2351,7 +2377,8 @@ DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) {
|
||||
const std::vector<DIE *> &Children = Die->getChildren();
|
||||
|
||||
// If not last sibling and has children then add sibling offset attribute.
|
||||
if (!Last && !Children.empty()) Die->addSiblingOffset();
|
||||
if (!Last && !Children.empty())
|
||||
Die->addSiblingOffset(DIEValueAllocator);
|
||||
|
||||
// Record the abbreviation.
|
||||
assignAbbrevNumber(Die->getAbbrev());
|
||||
@ -2465,7 +2492,7 @@ void DwarfDebug::emitDIE(DIE *Die) {
|
||||
dwarf::TagString(Abbrev->getTag()));
|
||||
EmitULEB128(AbbrevNumber);
|
||||
|
||||
SmallVector<DIEValue*, 32> &Values = Die->getValues();
|
||||
const SmallVector<DIEValue*, 32> &Values = Die->getValues();
|
||||
const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
|
||||
|
||||
// Emit the DIE attribute values.
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineLocation.h"
|
||||
#include "llvm/Analysis/DebugInfo.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
@ -98,9 +99,11 @@ class DwarfDebug : public DwarfPrinter {
|
||||
/// Lines - List of source line correspondence.
|
||||
std::vector<SrcLineInfo> Lines;
|
||||
|
||||
/// DIEValues - A list of all the unique values in use.
|
||||
///
|
||||
std::vector<DIEValue *> DIEValues;
|
||||
/// DIEBlocks - A list of all the DIEBlocks in use.
|
||||
std::vector<DIEBlock *> DIEBlocks;
|
||||
|
||||
// DIEValueAllocator - All DIEValues are allocated through this allocator.
|
||||
BumpPtrAllocator DIEValueAllocator;
|
||||
|
||||
/// StringPool - A String->Symbol mapping of strings used by indirect
|
||||
/// references.
|
||||
@ -141,12 +144,21 @@ class DwarfDebug : public DwarfPrinter {
|
||||
/// AbstractScopes - Tracks the abstract scopes a module. These scopes are
|
||||
/// not included DbgScopeMap. AbstractScopes owns its DbgScope*s.
|
||||
DenseMap<MDNode *, DbgScope *> AbstractScopes;
|
||||
|
||||
/// AbstractScopesList - Tracks abstract scopes constructed while processing
|
||||
/// a function. This list is cleared during endFunction().
|
||||
SmallVector<DbgScope *, 4>AbstractScopesList;
|
||||
|
||||
/// AbstractVariables - Collection on abstract variables. Owned by the
|
||||
/// DbgScopes in AbstractScopes.
|
||||
DenseMap<MDNode *, DbgVariable *> AbstractVariables;
|
||||
|
||||
/// DbgValueStartMap - Tracks starting scope of variable DIEs.
|
||||
/// If the scope of an object begins sometime after the low pc value for the
|
||||
/// scope most closely enclosing the object, the object entry may have a
|
||||
/// DW_AT_start_scope attribute.
|
||||
DenseMap<const MachineInstr *, DbgVariable *> DbgValueStartMap;
|
||||
|
||||
/// InliendSubprogramDIEs - Collection of subprgram DIEs that are marked
|
||||
/// (at the end of the module) as DW_AT_inline.
|
||||
SmallPtrSet<DIE *, 4> InlinedSubprogramDIEs;
|
||||
@ -181,6 +193,10 @@ class DwarfDebug : public DwarfPrinter {
|
||||
/// function.
|
||||
DenseMap<CompileUnit *, unsigned> CompileUnitOffsets;
|
||||
|
||||
/// Previous instruction's location information. This is used to determine
|
||||
/// label location to indicate scope boundries in dwarf debug info.
|
||||
mutable const MDNode *PrevDILoc;
|
||||
|
||||
/// DebugTimer - Timer for the Dwarf debug writer.
|
||||
Timer *DebugTimer;
|
||||
|
||||
@ -250,12 +266,6 @@ class DwarfDebug : public DwarfPrinter {
|
||||
void addLabel(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
const MCSymbol *Label);
|
||||
|
||||
/// addSectionOffset - Add a section offset label attribute data and value.
|
||||
///
|
||||
void addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
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,
|
||||
@ -545,8 +555,8 @@ class DwarfDebug : public DwarfPrinter {
|
||||
/// collectVariableInfo - Populate DbgScope entries with variables' info.
|
||||
void collectVariableInfo();
|
||||
|
||||
/// beginScope - Process beginning of a scope starting at Label.
|
||||
void beginScope(const MachineInstr *MI, MCSymbol *Label);
|
||||
/// beginScope - Process beginning of a scope.
|
||||
void beginScope(const MachineInstr *MI);
|
||||
|
||||
/// endScope - Prcess end of a scope.
|
||||
void endScope(const MachineInstr *MI);
|
||||
|
@ -419,23 +419,24 @@ bool DwarfException::CallToNoUnwindFunction(const MachineInstr *MI) {
|
||||
for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
|
||||
const MachineOperand &MO = MI->getOperand(I);
|
||||
|
||||
if (MO.isGlobal()) {
|
||||
if (Function *F = dyn_cast<Function>(MO.getGlobal())) {
|
||||
if (SawFunc) {
|
||||
// Be conservative. If we have more than one function operand for this
|
||||
// call, then we can't make the assumption that it's the callee and
|
||||
// not a parameter to the call.
|
||||
//
|
||||
// FIXME: Determine if there's a way to say that `F' is the callee or
|
||||
// parameter.
|
||||
MarkedNoUnwind = false;
|
||||
break;
|
||||
}
|
||||
if (!MO.isGlobal()) continue;
|
||||
|
||||
Function *F = dyn_cast<Function>(MO.getGlobal());
|
||||
if (F == 0) continue;
|
||||
|
||||
MarkedNoUnwind = F->doesNotThrow();
|
||||
SawFunc = true;
|
||||
}
|
||||
if (SawFunc) {
|
||||
// Be conservative. If we have more than one function operand for this
|
||||
// call, then we can't make the assumption that it's the callee and
|
||||
// not a parameter to the call.
|
||||
//
|
||||
// FIXME: Determine if there's a way to say that `F' is the callee or
|
||||
// parameter.
|
||||
MarkedNoUnwind = false;
|
||||
break;
|
||||
}
|
||||
|
||||
MarkedNoUnwind = F->doesNotThrow();
|
||||
SawFunc = true;
|
||||
}
|
||||
|
||||
return MarkedNoUnwind;
|
||||
@ -504,7 +505,10 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
|
||||
LastLabel = LandingPad->EndLabels[P.RangeIndex];
|
||||
assert(BeginLabel && LastLabel && "Invalid landing pad!");
|
||||
|
||||
if (LandingPad->LandingPadLabel) {
|
||||
if (!LandingPad->LandingPadLabel) {
|
||||
// Create a gap.
|
||||
PreviousIsInvoke = false;
|
||||
} else {
|
||||
// This try-range is for an invoke.
|
||||
CallSiteEntry Site = {
|
||||
BeginLabel,
|
||||
@ -536,9 +540,6 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
|
||||
CallSites[SiteNo - 1] = Site;
|
||||
}
|
||||
PreviousIsInvoke = true;
|
||||
} else {
|
||||
// Create a gap.
|
||||
PreviousIsInvoke = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -885,8 +886,7 @@ void DwarfException::EndModule() {
|
||||
if (!shouldEmitMovesModule && !shouldEmitTableModule)
|
||||
return;
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
ExceptionTimer->startTimer();
|
||||
TimeRegion Timer(ExceptionTimer);
|
||||
|
||||
const std::vector<Function *> Personalities = MMI->getPersonalities();
|
||||
|
||||
@ -896,9 +896,6 @@ void DwarfException::EndModule() {
|
||||
for (std::vector<FunctionEHFrameInfo>::iterator
|
||||
I = EHFrames.begin(), E = EHFrames.end(); I != E; ++I)
|
||||
EmitFDE(*I);
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
ExceptionTimer->stopTimer();
|
||||
}
|
||||
|
||||
/// BeginFunction - Gather pre-function exception information. Assumes it's
|
||||
@ -906,9 +903,7 @@ void DwarfException::EndModule() {
|
||||
void DwarfException::BeginFunction(const MachineFunction *MF) {
|
||||
if (!MMI || !MAI->doesSupportExceptionHandling()) return;
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
ExceptionTimer->startTimer();
|
||||
|
||||
TimeRegion Timer(ExceptionTimer);
|
||||
this->MF = MF;
|
||||
shouldEmitTable = shouldEmitMoves = false;
|
||||
|
||||
@ -924,9 +919,6 @@ void DwarfException::BeginFunction(const MachineFunction *MF) {
|
||||
|
||||
shouldEmitTableModule |= shouldEmitTable;
|
||||
shouldEmitMovesModule |= shouldEmitMoves;
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
ExceptionTimer->stopTimer();
|
||||
}
|
||||
|
||||
/// EndFunction - Gather and emit post-function exception information.
|
||||
@ -934,9 +926,7 @@ void DwarfException::BeginFunction(const MachineFunction *MF) {
|
||||
void DwarfException::EndFunction() {
|
||||
if (!shouldEmitMoves && !shouldEmitTable) return;
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
ExceptionTimer->startTimer();
|
||||
|
||||
TimeRegion Timer(ExceptionTimer);
|
||||
Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_end", SubprogramCount));
|
||||
|
||||
// Record if this personality index uses a landing pad.
|
||||
@ -961,7 +951,4 @@ void DwarfException::EndFunction() {
|
||||
!MMI->getLandingPads().empty(),
|
||||
MMI->getFrameMoves(),
|
||||
MF->getFunction()));
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
ExceptionTimer->stopTimer();
|
||||
}
|
||||
|
@ -45,14 +45,14 @@ MCSymbol *DwarfPrinter::getDWLabel(const char *Name, unsigned ID) const {
|
||||
|
||||
//assert(ID && "Should use getTempLabel if no ID");
|
||||
if (ID == 0) return getTempLabel(Name);
|
||||
return Asm->OutContext.GetOrCreateTemporarySymbol
|
||||
return Asm->OutContext.GetOrCreateSymbol
|
||||
(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
|
||||
return Asm->OutContext.GetOrCreateSymbol
|
||||
(Twine(MAI->getPrivateGlobalPrefix()) + Name);
|
||||
}
|
||||
|
||||
|
@ -73,27 +73,14 @@ void DwarfWriter::EndFunction(const MachineFunction *MF) {
|
||||
MMI->EndFunction();
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// getRecordSourceLineCount - Count source lines.
|
||||
unsigned DwarfWriter::getRecordSourceLineCount() {
|
||||
return DD->getSourceLineCount();
|
||||
}
|
||||
|
||||
/// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should
|
||||
/// be emitted.
|
||||
bool DwarfWriter::ShouldEmitDwarfDebug() const {
|
||||
return DD && DD->ShouldEmitDwarfDebug();
|
||||
}
|
||||
|
||||
void DwarfWriter::BeginScope(const MachineInstr *MI, MCSymbol *L) {
|
||||
DD->beginScope(MI, L);
|
||||
void DwarfWriter::BeginScope(const MachineInstr *MI) {
|
||||
DD->beginScope(MI);
|
||||
}
|
||||
void DwarfWriter::EndScope(const MachineInstr *MI) {
|
||||
DD->endScope(MI);
|
||||
|
@ -972,15 +972,21 @@ static bool IsBetterFallthrough(MachineBasicBlock *MBB1,
|
||||
// MBB1 doesn't, we prefer to fall through into MBB1. This allows us to
|
||||
// optimize branches that branch to either a return block or an assert block
|
||||
// into a fallthrough to the return.
|
||||
if (MBB1->empty() || MBB2->empty()) return false;
|
||||
if (IsEmptyBlock(MBB1) || IsEmptyBlock(MBB2)) return false;
|
||||
|
||||
// If there is a clear successor ordering we make sure that one block
|
||||
// will fall through to the next
|
||||
if (MBB1->isSuccessor(MBB2)) return true;
|
||||
if (MBB2->isSuccessor(MBB1)) return false;
|
||||
|
||||
MachineInstr *MBB1I = --MBB1->end();
|
||||
MachineInstr *MBB2I = --MBB2->end();
|
||||
// Neither block consists entirely of debug info (per IsEmptyBlock check),
|
||||
// so we needn't test for falling off the beginning here.
|
||||
MachineBasicBlock::iterator MBB1I = --MBB1->end();
|
||||
while (MBB1I->isDebugValue())
|
||||
--MBB1I;
|
||||
MachineBasicBlock::iterator MBB2I = --MBB2->end();
|
||||
while (MBB2I->isDebugValue())
|
||||
--MBB2I;
|
||||
return MBB2I->getDesc().isCall() && !MBB1I->getDesc().isCall();
|
||||
}
|
||||
|
||||
|
@ -8,19 +8,19 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This pass mulches exception handling code into a form adapted to code
|
||||
// generation. Required if using dwarf exception handling.
|
||||
// generation. Required if using dwarf exception handling.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "dwarfehprepare"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/IntrinsicInst.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
@ -40,6 +40,15 @@ namespace {
|
||||
// The eh.exception intrinsic.
|
||||
Function *ExceptionValueIntrinsic;
|
||||
|
||||
// The eh.selector intrinsic.
|
||||
Function *SelectorIntrinsic;
|
||||
|
||||
// _Unwind_Resume_or_Rethrow call.
|
||||
Constant *URoR;
|
||||
|
||||
// The EH language-specific catch-all type.
|
||||
GlobalVariable *EHCatchAllValue;
|
||||
|
||||
// _Unwind_Resume or the target equivalent.
|
||||
Constant *RewindFunction;
|
||||
|
||||
@ -67,18 +76,88 @@ namespace {
|
||||
Instruction *CreateValueLoad(BasicBlock *BB);
|
||||
|
||||
/// CreateReadOfExceptionValue - Return the result of the eh.exception
|
||||
/// intrinsic by calling the intrinsic if in a landing pad, or loading
|
||||
/// it from the exception value variable otherwise.
|
||||
/// intrinsic by calling the intrinsic if in a landing pad, or loading it
|
||||
/// from the exception value variable otherwise.
|
||||
Instruction *CreateReadOfExceptionValue(BasicBlock *BB) {
|
||||
return LandingPads.count(BB) ?
|
||||
CreateExceptionValueCall(BB) : CreateValueLoad(BB);
|
||||
}
|
||||
|
||||
/// CleanupSelectors - Any remaining eh.selector intrinsic calls which still
|
||||
/// use the ".llvm.eh.catch.all.value" call need to convert to using it's
|
||||
/// initializer instead.
|
||||
bool CleanupSelectors();
|
||||
|
||||
/// FindAllCleanupSelectors - Find all eh.selector calls that are clean-ups.
|
||||
void FindAllCleanupSelectors(SmallPtrSet<IntrinsicInst*, 32> &Sels);
|
||||
|
||||
/// FindAllURoRInvokes - Find all URoR invokes in the function.
|
||||
void FindAllURoRInvokes(SmallPtrSet<InvokeInst*, 32> &URoRInvokes);
|
||||
|
||||
/// HandleURoRInvokes - Handle invokes of "_Unwind_Resume_or_Rethrow"
|
||||
/// calls. The "unwind" part of these invokes jump to a landing pad within
|
||||
/// the current function. This is a candidate to merge the selector
|
||||
/// associated with the URoR invoke with the one from the URoR's landing
|
||||
/// pad.
|
||||
bool HandleURoRInvokes();
|
||||
|
||||
/// FindSelectorAndURoR - Find the eh.selector call and URoR call associated
|
||||
/// with the eh.exception call. This recursively looks past instructions
|
||||
/// which don't change the EH pointer value, like casts or PHI nodes.
|
||||
bool FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke,
|
||||
SmallPtrSet<IntrinsicInst*, 8> &SelCalls);
|
||||
|
||||
/// DoMem2RegPromotion - Take an alloca call and promote it from memory to a
|
||||
/// register.
|
||||
bool DoMem2RegPromotion(Value *V) {
|
||||
AllocaInst *AI = dyn_cast<AllocaInst>(V);
|
||||
if (!AI || !isAllocaPromotable(AI)) return false;
|
||||
|
||||
// Turn the alloca into a register.
|
||||
std::vector<AllocaInst*> Allocas(1, AI);
|
||||
PromoteMemToReg(Allocas, *DT, *DF);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// PromoteStoreInst - Perform Mem2Reg on a StoreInst.
|
||||
bool PromoteStoreInst(StoreInst *SI) {
|
||||
if (!SI || !DT || !DF) return false;
|
||||
if (DoMem2RegPromotion(SI->getOperand(1)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// PromoteEHPtrStore - Promote the storing of an EH pointer into a
|
||||
/// register. This should get rid of the store and subsequent loads.
|
||||
bool PromoteEHPtrStore(IntrinsicInst *II) {
|
||||
if (!DT || !DF) return false;
|
||||
|
||||
bool Changed = false;
|
||||
StoreInst *SI;
|
||||
|
||||
while (1) {
|
||||
SI = 0;
|
||||
for (Value::use_iterator
|
||||
I = II->use_begin(), E = II->use_end(); I != E; ++I) {
|
||||
SI = dyn_cast<StoreInst>(I);
|
||||
if (SI) break;
|
||||
}
|
||||
|
||||
if (!PromoteStoreInst(SI))
|
||||
break;
|
||||
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid.
|
||||
DwarfEHPrepare(const TargetLowering *tli, bool fast) :
|
||||
FunctionPass(&ID), TLI(tli), CompileFast(fast),
|
||||
ExceptionValueIntrinsic(0), RewindFunction(0) {}
|
||||
ExceptionValueIntrinsic(0), SelectorIntrinsic(0),
|
||||
URoR(0), EHCatchAllValue(0), RewindFunction(0) {}
|
||||
|
||||
virtual bool runOnFunction(Function &Fn);
|
||||
|
||||
@ -105,6 +184,233 @@ FunctionPass *llvm::createDwarfEHPass(const TargetLowering *tli, bool fast) {
|
||||
return new DwarfEHPrepare(tli, fast);
|
||||
}
|
||||
|
||||
/// FindAllCleanupSelectors - Find all eh.selector calls that are clean-ups.
|
||||
void DwarfEHPrepare::
|
||||
FindAllCleanupSelectors(SmallPtrSet<IntrinsicInst*, 32> &Sels) {
|
||||
for (Value::use_iterator
|
||||
I = SelectorIntrinsic->use_begin(),
|
||||
E = SelectorIntrinsic->use_end(); I != E; ++I) {
|
||||
IntrinsicInst *SI = cast<IntrinsicInst>(I);
|
||||
if (!SI || SI->getParent()->getParent() != F) continue;
|
||||
|
||||
unsigned NumOps = SI->getNumOperands();
|
||||
if (NumOps > 4) continue;
|
||||
bool IsCleanUp = (NumOps == 3);
|
||||
|
||||
if (!IsCleanUp)
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(SI->getOperand(3)))
|
||||
IsCleanUp = (CI->getZExtValue() == 0);
|
||||
|
||||
if (IsCleanUp)
|
||||
Sels.insert(SI);
|
||||
}
|
||||
}
|
||||
|
||||
/// FindAllURoRInvokes - Find all URoR invokes in the function.
|
||||
void DwarfEHPrepare::
|
||||
FindAllURoRInvokes(SmallPtrSet<InvokeInst*, 32> &URoRInvokes) {
|
||||
for (Value::use_iterator
|
||||
I = URoR->use_begin(),
|
||||
E = URoR->use_end(); I != E; ++I) {
|
||||
if (InvokeInst *II = dyn_cast<InvokeInst>(I))
|
||||
URoRInvokes.insert(II);
|
||||
}
|
||||
}
|
||||
|
||||
/// CleanupSelectors - Any remaining eh.selector intrinsic calls which still use
|
||||
/// the ".llvm.eh.catch.all.value" call need to convert to using it's
|
||||
/// initializer instead.
|
||||
bool DwarfEHPrepare::CleanupSelectors() {
|
||||
if (!EHCatchAllValue) return false;
|
||||
|
||||
if (!SelectorIntrinsic) {
|
||||
SelectorIntrinsic =
|
||||
Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_selector);
|
||||
if (!SelectorIntrinsic) return false;
|
||||
}
|
||||
|
||||
bool Changed = false;
|
||||
for (Value::use_iterator
|
||||
I = SelectorIntrinsic->use_begin(),
|
||||
E = SelectorIntrinsic->use_end(); I != E; ++I) {
|
||||
IntrinsicInst *Sel = dyn_cast<IntrinsicInst>(I);
|
||||
if (!Sel || Sel->getParent()->getParent() != F) continue;
|
||||
|
||||
// Index of the ".llvm.eh.catch.all.value" variable.
|
||||
unsigned OpIdx = Sel->getNumOperands() - 1;
|
||||
GlobalVariable *GV = dyn_cast<GlobalVariable>(Sel->getOperand(OpIdx));
|
||||
if (GV != EHCatchAllValue) continue;
|
||||
Sel->setOperand(OpIdx, EHCatchAllValue->getInitializer());
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
/// FindSelectorAndURoR - Find the eh.selector call associated with the
|
||||
/// eh.exception call. And indicate if there is a URoR "invoke" associated with
|
||||
/// the eh.exception call. This recursively looks past instructions which don't
|
||||
/// change the EH pointer value, like casts or PHI nodes.
|
||||
bool
|
||||
DwarfEHPrepare::FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke,
|
||||
SmallPtrSet<IntrinsicInst*, 8> &SelCalls) {
|
||||
SmallPtrSet<PHINode*, 32> SeenPHIs;
|
||||
bool Changed = false;
|
||||
|
||||
restart:
|
||||
for (Value::use_iterator
|
||||
I = Inst->use_begin(), E = Inst->use_end(); I != E; ++I) {
|
||||
Instruction *II = dyn_cast<Instruction>(I);
|
||||
if (!II || II->getParent()->getParent() != F) continue;
|
||||
|
||||
if (IntrinsicInst *Sel = dyn_cast<IntrinsicInst>(II)) {
|
||||
if (Sel->getIntrinsicID() == Intrinsic::eh_selector)
|
||||
SelCalls.insert(Sel);
|
||||
} else if (InvokeInst *Invoke = dyn_cast<InvokeInst>(II)) {
|
||||
if (Invoke->getCalledFunction() == URoR)
|
||||
URoRInvoke = true;
|
||||
} else if (CastInst *CI = dyn_cast<CastInst>(II)) {
|
||||
Changed |= FindSelectorAndURoR(CI, URoRInvoke, SelCalls);
|
||||
} else if (StoreInst *SI = dyn_cast<StoreInst>(II)) {
|
||||
if (!PromoteStoreInst(SI)) continue;
|
||||
Changed = true;
|
||||
SeenPHIs.clear();
|
||||
goto restart; // Uses may have changed, restart loop.
|
||||
} else if (PHINode *PN = dyn_cast<PHINode>(II)) {
|
||||
if (SeenPHIs.insert(PN))
|
||||
// Don't process a PHI node more than once.
|
||||
Changed |= FindSelectorAndURoR(PN, URoRInvoke, SelCalls);
|
||||
}
|
||||
}
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
/// HandleURoRInvokes - Handle invokes of "_Unwind_Resume_or_Rethrow" calls. The
|
||||
/// "unwind" part of these invokes jump to a landing pad within the current
|
||||
/// function. This is a candidate to merge the selector associated with the URoR
|
||||
/// invoke with the one from the URoR's landing pad.
|
||||
bool DwarfEHPrepare::HandleURoRInvokes() {
|
||||
if (!DT) return CleanupSelectors(); // We require DominatorTree information.
|
||||
|
||||
if (!EHCatchAllValue) {
|
||||
EHCatchAllValue =
|
||||
F->getParent()->getNamedGlobal(".llvm.eh.catch.all.value");
|
||||
if (!EHCatchAllValue) return false;
|
||||
}
|
||||
|
||||
if (!SelectorIntrinsic) {
|
||||
SelectorIntrinsic =
|
||||
Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_selector);
|
||||
if (!SelectorIntrinsic) return false;
|
||||
}
|
||||
|
||||
if (!URoR) {
|
||||
URoR = F->getParent()->getFunction("_Unwind_Resume_or_Rethrow");
|
||||
if (!URoR) return CleanupSelectors();
|
||||
}
|
||||
|
||||
SmallPtrSet<IntrinsicInst*, 32> Sels;
|
||||
SmallPtrSet<InvokeInst*, 32> URoRInvokes;
|
||||
FindAllCleanupSelectors(Sels);
|
||||
FindAllURoRInvokes(URoRInvokes);
|
||||
|
||||
SmallPtrSet<IntrinsicInst*, 32> SelsToConvert;
|
||||
|
||||
for (SmallPtrSet<IntrinsicInst*, 32>::iterator
|
||||
SI = Sels.begin(), SE = Sels.end(); SI != SE; ++SI) {
|
||||
const BasicBlock *SelBB = (*SI)->getParent();
|
||||
for (SmallPtrSet<InvokeInst*, 32>::iterator
|
||||
UI = URoRInvokes.begin(), UE = URoRInvokes.end(); UI != UE; ++UI) {
|
||||
const BasicBlock *URoRBB = (*UI)->getParent();
|
||||
if (SelBB == URoRBB || DT->dominates(SelBB, URoRBB)) {
|
||||
SelsToConvert.insert(*SI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Changed = false;
|
||||
|
||||
if (Sels.size() != SelsToConvert.size()) {
|
||||
// If we haven't been able to convert all of the clean-up selectors, then
|
||||
// loop through the slow way to see if they still need to be converted.
|
||||
if (!ExceptionValueIntrinsic) {
|
||||
ExceptionValueIntrinsic =
|
||||
Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_exception);
|
||||
if (!ExceptionValueIntrinsic) return CleanupSelectors();
|
||||
}
|
||||
|
||||
for (Value::use_iterator
|
||||
I = ExceptionValueIntrinsic->use_begin(),
|
||||
E = ExceptionValueIntrinsic->use_end(); I != E; ++I) {
|
||||
IntrinsicInst *EHPtr = dyn_cast<IntrinsicInst>(I);
|
||||
if (!EHPtr || EHPtr->getParent()->getParent() != F) continue;
|
||||
|
||||
Changed |= PromoteEHPtrStore(EHPtr);
|
||||
|
||||
bool URoRInvoke = false;
|
||||
SmallPtrSet<IntrinsicInst*, 8> SelCalls;
|
||||
Changed |= FindSelectorAndURoR(EHPtr, URoRInvoke, SelCalls);
|
||||
|
||||
if (URoRInvoke) {
|
||||
// This EH pointer is being used by an invoke of an URoR instruction and
|
||||
// an eh.selector intrinsic call. If the eh.selector is a 'clean-up', we
|
||||
// need to convert it to a 'catch-all'.
|
||||
for (SmallPtrSet<IntrinsicInst*, 8>::iterator
|
||||
SI = SelCalls.begin(), SE = SelCalls.end(); SI != SE; ++SI) {
|
||||
IntrinsicInst *II = *SI;
|
||||
unsigned NumOps = II->getNumOperands();
|
||||
|
||||
if (NumOps <= 4) {
|
||||
bool IsCleanUp = (NumOps == 3);
|
||||
|
||||
if (!IsCleanUp)
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(II->getOperand(3)))
|
||||
IsCleanUp = (CI->getZExtValue() == 0);
|
||||
|
||||
if (IsCleanUp)
|
||||
SelsToConvert.insert(II);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!SelsToConvert.empty()) {
|
||||
// Convert all clean-up eh.selectors, which are associated with "invokes" of
|
||||
// URoR calls, into catch-all eh.selectors.
|
||||
Changed = true;
|
||||
|
||||
for (SmallPtrSet<IntrinsicInst*, 8>::iterator
|
||||
SI = SelsToConvert.begin(), SE = SelsToConvert.end();
|
||||
SI != SE; ++SI) {
|
||||
IntrinsicInst *II = *SI;
|
||||
SmallVector<Value*, 8> Args;
|
||||
|
||||
// Use the exception object pointer and the personality function
|
||||
// from the original selector.
|
||||
Args.push_back(II->getOperand(1)); // Exception object pointer.
|
||||
Args.push_back(II->getOperand(2)); // Personality function.
|
||||
Args.push_back(EHCatchAllValue->getInitializer()); // Catch-all indicator.
|
||||
|
||||
CallInst *NewSelector =
|
||||
CallInst::Create(SelectorIntrinsic, Args.begin(), Args.end(),
|
||||
"eh.sel.catch.all", II);
|
||||
|
||||
NewSelector->setTailCall(II->isTailCall());
|
||||
NewSelector->setAttributes(II->getAttributes());
|
||||
NewSelector->setCallingConv(II->getCallingConv());
|
||||
|
||||
II->replaceAllUsesWith(NewSelector);
|
||||
II->eraseFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
Changed |= CleanupSelectors();
|
||||
return Changed;
|
||||
}
|
||||
|
||||
/// NormalizeLandingPads - Normalize and discover landing pads, noting them
|
||||
/// in the LandingPads set. A landing pad is normal if the only CFG edges
|
||||
/// that end at it are unwind edges from invoke instructions. If we inlined
|
||||
@ -422,6 +728,8 @@ bool DwarfEHPrepare::runOnFunction(Function &Fn) {
|
||||
if (!CompileFast)
|
||||
Changed |= PromoteStackTemporaries();
|
||||
|
||||
Changed |= HandleURoRInvokes();
|
||||
|
||||
LandingPads.clear();
|
||||
|
||||
return Changed;
|
||||
|
@ -303,9 +303,7 @@ void LiveInterval::removeRange(SlotIndex Start, SlotIndex End,
|
||||
// otherwise mark it as ~1U so it can be nuked later.
|
||||
if (ValNo->id == getNumValNums()-1) {
|
||||
do {
|
||||
VNInfo *VNI = valnos.back();
|
||||
valnos.pop_back();
|
||||
VNI->~VNInfo();
|
||||
} while (!valnos.empty() && valnos.back()->isUnused());
|
||||
} else {
|
||||
ValNo->setIsUnused(true);
|
||||
@ -351,9 +349,7 @@ void LiveInterval::removeValNo(VNInfo *ValNo) {
|
||||
// otherwise mark it as ~1U so it can be nuked later.
|
||||
if (ValNo->id == getNumValNums()-1) {
|
||||
do {
|
||||
VNInfo *VNI = valnos.back();
|
||||
valnos.pop_back();
|
||||
VNI->~VNInfo();
|
||||
} while (!valnos.empty() && valnos.back()->isUnused());
|
||||
} else {
|
||||
ValNo->setIsUnused(true);
|
||||
@ -579,9 +575,7 @@ void LiveInterval::MergeValueInAsValue(
|
||||
// mark it as ~1U so it can be nuked later.
|
||||
if (V1->id == getNumValNums()-1) {
|
||||
do {
|
||||
VNInfo *VNI = valnos.back();
|
||||
valnos.pop_back();
|
||||
VNI->~VNInfo();
|
||||
} while (!valnos.empty() && valnos.back()->isUnused());
|
||||
} else {
|
||||
V1->setIsUnused(true);
|
||||
@ -597,7 +591,7 @@ void LiveInterval::MergeValueInAsValue(
|
||||
/// used with an unknown definition value.
|
||||
void LiveInterval::MergeInClobberRanges(LiveIntervals &li_,
|
||||
const LiveInterval &Clobbers,
|
||||
BumpPtrAllocator &VNInfoAllocator) {
|
||||
VNInfo::Allocator &VNInfoAllocator) {
|
||||
if (Clobbers.empty()) return;
|
||||
|
||||
DenseMap<VNInfo*, VNInfo*> ValNoMaps;
|
||||
@ -658,14 +652,13 @@ void LiveInterval::MergeInClobberRanges(LiveIntervals &li_,
|
||||
if (UnusedValNo) {
|
||||
// Delete the last unused val#.
|
||||
valnos.pop_back();
|
||||
UnusedValNo->~VNInfo();
|
||||
}
|
||||
}
|
||||
|
||||
void LiveInterval::MergeInClobberRange(LiveIntervals &li_,
|
||||
SlotIndex Start,
|
||||
SlotIndex End,
|
||||
BumpPtrAllocator &VNInfoAllocator) {
|
||||
VNInfo::Allocator &VNInfoAllocator) {
|
||||
// Find a value # to use for the clobber ranges. If there is already a value#
|
||||
// for unknown values, use it.
|
||||
VNInfo *ClobberValNo =
|
||||
@ -749,9 +742,7 @@ VNInfo* LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) {
|
||||
// ~1U so it can be nuked later.
|
||||
if (V1->id == getNumValNums()-1) {
|
||||
do {
|
||||
VNInfo *VNI = valnos.back();
|
||||
valnos.pop_back();
|
||||
VNI->~VNInfo();
|
||||
} while (valnos.back()->isUnused());
|
||||
} else {
|
||||
V1->setIsUnused(true);
|
||||
@ -762,7 +753,7 @@ VNInfo* LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) {
|
||||
|
||||
void LiveInterval::Copy(const LiveInterval &RHS,
|
||||
MachineRegisterInfo *MRI,
|
||||
BumpPtrAllocator &VNInfoAllocator) {
|
||||
VNInfo::Allocator &VNInfoAllocator) {
|
||||
ranges.clear();
|
||||
valnos.clear();
|
||||
std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(RHS.reg);
|
||||
|
@ -91,7 +91,7 @@ void LiveIntervals::releaseMemory() {
|
||||
r2iMap_.clear();
|
||||
|
||||
// Release VNInfo memroy regions after all VNInfo objects are dtor'd.
|
||||
VNInfoAllocator.Reset();
|
||||
VNInfoAllocator.DestroyAll();
|
||||
while (!CloneMIs.empty()) {
|
||||
MachineInstr *MI = CloneMIs.back();
|
||||
CloneMIs.pop_back();
|
||||
@ -819,8 +819,9 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
|
||||
unsigned ImpUse = getReMatImplicitUse(li, MI);
|
||||
if (ImpUse) {
|
||||
const LiveInterval &ImpLi = getInterval(ImpUse);
|
||||
for (MachineRegisterInfo::use_iterator ri = mri_->use_begin(li.reg),
|
||||
re = mri_->use_end(); ri != re; ++ri) {
|
||||
for (MachineRegisterInfo::use_nodbg_iterator
|
||||
ri = mri_->use_nodbg_begin(li.reg), re = mri_->use_nodbg_end();
|
||||
ri != re; ++ri) {
|
||||
MachineInstr *UseMI = &*ri;
|
||||
SlotIndex UseIdx = getInstructionIndex(UseMI);
|
||||
if (li.FindLiveRangeContaining(UseIdx)->valno != ValNo)
|
||||
@ -1052,7 +1053,7 @@ rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI,
|
||||
// all of its uses are rematerialized, simply delete it.
|
||||
if (MI == ReMatOrigDefMI && CanDelete) {
|
||||
DEBUG(dbgs() << "\t\t\t\tErasing re-materializable def: "
|
||||
<< MI << '\n');
|
||||
<< *MI << '\n');
|
||||
RemoveMachineInstrFromMaps(MI);
|
||||
vrm.RemoveMachineInstrFromMaps(MI);
|
||||
MI->eraseFromParent();
|
||||
@ -1520,6 +1521,12 @@ LiveIntervals::handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm,
|
||||
MachineOperand &O = ri.getOperand();
|
||||
MachineInstr *MI = &*ri;
|
||||
++ri;
|
||||
if (MI->isDebugValue()) {
|
||||
// Remove debug info for now.
|
||||
O.setReg(0U);
|
||||
DEBUG(dbgs() << "Removing debug info due to spill:" << "\t" << *MI);
|
||||
continue;
|
||||
}
|
||||
if (O.isDef()) {
|
||||
assert(MI->isImplicitDef() &&
|
||||
"Register def was not rewritten?");
|
||||
@ -2012,6 +2019,8 @@ unsigned LiveIntervals::getNumConflictsWithPhysReg(const LiveInterval &li,
|
||||
E = mri_->reg_end(); I != E; ++I) {
|
||||
MachineOperand &O = I.getOperand();
|
||||
MachineInstr *MI = O.getParent();
|
||||
if (MI->isDebugValue())
|
||||
continue;
|
||||
SlotIndex Index = getInstructionIndex(MI);
|
||||
if (pli.liveAt(Index))
|
||||
++NumConflicts;
|
||||
@ -2052,7 +2061,7 @@ bool LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li,
|
||||
E = mri_->reg_end(); I != E; ++I) {
|
||||
MachineOperand &O = I.getOperand();
|
||||
MachineInstr *MI = O.getParent();
|
||||
if (SeenMIs.count(MI))
|
||||
if (MI->isDebugValue() || SeenMIs.count(MI))
|
||||
continue;
|
||||
SeenMIs.insert(MI);
|
||||
SlotIndex Index = getInstructionIndex(MI);
|
||||
|
@ -36,7 +36,7 @@ void LiveStacks::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
|
||||
void LiveStacks::releaseMemory() {
|
||||
// Release VNInfo memroy regions after all VNInfo objects are dtor'd.
|
||||
VNInfoAllocator.Reset();
|
||||
VNInfoAllocator.DestroyAll();
|
||||
S2IMap.clear();
|
||||
S2RCMap.clear();
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user