Update LLVM to r100181.

This commit is contained in:
Roman Divacky 2010-04-02 08:54:30 +00:00
parent 2f12f10af3
commit 104bd8179f
390 changed files with 10314 additions and 6109 deletions

View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -1090,8 +1090,8 @@ def FADDS : AForm_2&lt;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 -&gt; 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>

View File

@ -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&lt;llvm::Instruction *, 16&gt;(B-&gt;begin(), B-&gt;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-&gt;use_begin(), e = F-&gt;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-&gt;op_begin(), e = pi-&gt;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>

View File

@ -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>

View File

@ -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 &lt;&lt; 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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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"];;

View File

@ -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"];;

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);
};

View File

@ -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(); }

View File

@ -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.

View File

@ -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();

View File

@ -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.
//===--------------------------------------------------------------------===//

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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));
}

View File

@ -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;

View File

@ -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

View File

@ -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],

View File

@ -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.

View File

@ -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]>;
}

View File

@ -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;

View File

@ -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

View File

@ -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
/// @{

View File

@ -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;

View File

@ -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
/// @{

View File

@ -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;
};

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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 *);
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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

View File

@ -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();

View File

@ -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.

View File

@ -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; }

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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;
}

View File

@ -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; }

View File

@ -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

View File

@ -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 {

View File

@ -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.

View File

@ -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;
}
};

View File

@ -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.

View File

@ -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,

View File

@ -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
};

View File

@ -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);

View File

@ -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<>

View File

@ -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.

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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 ||

View File

@ -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

View File

@ -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();

View File

@ -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)

View File

@ -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());

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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));

View File

@ -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

View File

@ -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()

View File

@ -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; }

View File

@ -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.

View File

@ -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);

View File

@ -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))

View File

@ -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
}

View File

@ -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

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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();
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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