1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

Land the long talked about "type system rewrite" patch. This

patch brings numerous advantages to LLVM.  One way to look at it
is through diffstat:
 109 files changed, 3005 insertions(+), 5906 deletions(-)

Removing almost 3K lines of code is a good thing.  Other advantages
include:

1. Value::getType() is a simple load that can be CSE'd, not a mutating
   union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
   uniques them.  This means that the compiler doesn't merge them structurally
   which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
   struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
   in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead 
   "const Type *" everywhere.

Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.  
"LLVM 3.0" is the right time to do this.

There are still some cleanups pending after this, this patch is large enough
as-is.

llvm-svn: 134829
This commit is contained in:
Chris Lattner 2011-07-09 17:41:24 +00:00
parent 997adcdcee
commit a106725fc5
109 changed files with 3158 additions and 6059 deletions

View File

@ -74,16 +74,14 @@
<ol>
<li><a href="#t_array">Array Type</a></li>
<li><a href="#t_struct">Structure Type</a></li>
<li><a href="#t_pstruct">Packed Structure Type</a></li>
<li><a href="#t_opaque">Opaque Type</a></li>
<li><a href="#t_vector">Vector Type</a></li>
</ol>
</li>
<li><a href="#t_function">Function Type</a></li>
<li><a href="#t_pointer">Pointer Type</a></li>
<li><a href="#t_opaque">Opaque Type</a></li>
</ol>
</li>
<li><a href="#t_uprefs">Type Up-references</a></li>
</ol>
</li>
<li><a href="#constants">Constants</a>
@ -1535,7 +1533,6 @@ synchronization behavior.</p>
<a href="#t_function">function</a>,
<a href="#t_pointer">pointer</a>,
<a href="#t_struct">structure</a>,
<a href="#t_pstruct">packed structure</a>,
<a href="#t_vector">vector</a>,
<a href="#t_opaque">opaque</a>.
</td>
@ -1703,7 +1700,9 @@ synchronization behavior.</p>
possible to have a two dimensional array, using an array as the element type
of another array.</p>
</div>
<!-- _______________________________________________________________________ -->
<h4>
<a name="t_aggregate">Aggregate Types</a>
@ -1842,9 +1841,7 @@ synchronization behavior.</p>
<h5>Overview:</h5>
<p>The structure type is used to represent a collection of data members together
in memory. The packing of the field types is defined to match the ABI of the
underlying processor. The elements of a structure may be any type that has a
size.</p>
in memory. The elements of a structure may be any type that has a size.</p>
<p>Structures in memory are accessed using '<tt><a href="#i_load">load</a></tt>'
and '<tt><a href="#i_store">store</a></tt>' by getting a pointer to a field
@ -1852,66 +1849,76 @@ synchronization behavior.</p>
Structures in registers are accessed using the
'<tt><a href="#i_extractvalue">extractvalue</a></tt>' and
'<tt><a href="#i_insertvalue">insertvalue</a></tt>' instructions.</p>
<p>Structures may optionally be "packed" structures, which indicate that the
alignment of the struct is one byte, and that there is no padding between
the elements. In non-packed structs, padding between field types is defined
by the target data string to match the underlying processor.</p>
<p>Structures can either be "anonymous" or "named". An anonymous structure is
defined inline with other types (e.g. <tt>{i32, i32}*</tt>) and a named types
are always defined at the top level with a name. Anonmyous types are uniqued
by their contents and can never be recursive since there is no way to write
one. Named types can be recursive.
</p>
<h5>Syntax:</h5>
<pre>
{ &lt;type list&gt; }
%T1 = type { &lt;type list&gt; } <i>; Named normal struct type</i>
%T2 = type &lt;{ &lt;type list&gt; }&gt; <i>; Named packed struct type</i>
</pre>
<h5>Examples:</h5>
<table class="layout">
<tr class="layout">
<td class="left"><tt>{ i32, i32, i32 }</tt></td>
<td class="left">A triple of three <tt>i32</tt> values</td>
</tr><tr class="layout">
</tr>
<tr class="layout">
<td class="left"><tt>{&nbsp;float,&nbsp;i32&nbsp;(i32)&nbsp;*&nbsp;}</tt></td>
<td class="left">A pair, where the first element is a <tt>float</tt> and the
second element is a <a href="#t_pointer">pointer</a> to a
<a href="#t_function">function</a> that takes an <tt>i32</tt>, returning
an <tt>i32</tt>.</td>
</tr>
<tr class="layout">
<td class="left"><tt>&lt;{ i8, i32 }&gt;</tt></td>
<td class="left">A packed struct known to be 5 bytes in size.</td>
</tr>
</table>
</div>
<!-- _______________________________________________________________________ -->
<h4>
<a name="t_pstruct">Packed Structure Type</a>
<a name="t_opaque">Opaque Type</a>
</h4>
<div>
<h5>Overview:</h5>
<p>The packed structure type is used to represent a collection of data members
together in memory. There is no padding between fields. Further, the
alignment of a packed structure is 1 byte. The elements of a packed
structure may be any type that has a size.</p>
<p>Structures are accessed using '<tt><a href="#i_load">load</a></tt> and
'<tt><a href="#i_store">store</a></tt>' by getting a pointer to a field with
the '<tt><a href="#i_getelementptr">getelementptr</a></tt>' instruction.</p>
<p>Opaque types are used to represent named structure types that do not have a
body specified. This corresponds (for example) to the C notion of a forward
declared structure.</p>
<h5>Syntax:</h5>
<pre>
&lt; { &lt;type list&gt; } &gt;
%X = type opaque
%52 = type opaque
</pre>
<h5>Examples:</h5>
<table class="layout">
<tr class="layout">
<td class="left"><tt>&lt; { i32, i32, i32 } &gt;</tt></td>
<td class="left">A triple of three <tt>i32</tt> values</td>
</tr><tr class="layout">
<td class="left">
<tt>&lt;&nbsp;{&nbsp;float,&nbsp;i32&nbsp;(i32)*&nbsp;}&nbsp;&gt;</tt></td>
<td class="left">A pair, where the first element is a <tt>float</tt> and the
second element is a <a href="#t_pointer">pointer</a> to a
<a href="#t_function">function</a> that takes an <tt>i32</tt>, returning
an <tt>i32</tt>.</td>
<td class="left"><tt>opaque</tt></td>
<td class="left">An opaque type.</td>
</tr>
</table>
</div>
<!-- _______________________________________________________________________ -->
<h4>
<a name="t_pointer">Pointer Type</a>
@ -1999,86 +2006,6 @@ synchronization behavior.</p>
</div>
<!-- _______________________________________________________________________ -->
<h4>
<a name="t_opaque">Opaque Type</a>
</h4>
<div>
<h5>Overview:</h5>
<p>Opaque types are used to represent unknown types in the system. This
corresponds (for example) to the C notion of a forward declared structure
type. In LLVM, opaque types can eventually be resolved to any type (not just
a structure type).</p>
<h5>Syntax:</h5>
<pre>
opaque
</pre>
<h5>Examples:</h5>
<table class="layout">
<tr class="layout">
<td class="left"><tt>opaque</tt></td>
<td class="left">An opaque type.</td>
</tr>
</table>
</div>
</div>
<!-- ======================================================================= -->
<h3>
<a name="t_uprefs">Type Up-references</a>
</h3>
<div>
<h5>Overview:</h5>
<p>An "up reference" allows you to refer to a lexically enclosing type without
requiring it to have a name. For instance, a structure declaration may
contain a pointer to any of the types it is lexically a member of. Example
of up references (with their equivalent as named type declarations)
include:</p>
<pre>
{ \2 * } %x = type { %x* }
{ \2 }* %y = type { %y }*
\1* %z = type %z*
</pre>
<p>An up reference is needed by the asmprinter for printing out cyclic types
when there is no declared name for a type in the cycle. Because the
asmprinter does not want to print out an infinite type string, it needs a
syntax to handle recursive types that have no names (all names are optional
in llvm IR).</p>
<h5>Syntax:</h5>
<pre>
\&lt;level&gt;
</pre>
<p>The level is the count of the lexical type that is being referred to.</p>
<h5>Examples:</h5>
<table class="layout">
<tr class="layout">
<td class="left"><tt>\1*</tt></td>
<td class="left">Self-referential pointer.</td>
</tr>
<tr class="layout">
<td class="left"><tt>{ { \3*, i8 }, i32 }</tt></td>
<td class="left">Recursive structure where the upref refers to the out-most
structure.</td>
</tr>
</table>
</div>
</div>
<!-- *********************************************************************** -->
<h2><a name="constants">Constants</a></h2>
<!-- *********************************************************************** -->

View File

@ -160,15 +160,8 @@ with another <tt>Value</tt></a> </li>
<li><a href="#advanced">Advanced Topics</a>
<ul>
<li><a href="#TypeResolve">LLVM Type Resolution</a>
<ul>
<li><a href="#BuildRecType">Basic Recursive Type Construction</a></li>
<li><a href="#refineAbstractTypeTo">The <tt>refineAbstractTypeTo</tt> method</a></li>
<li><a href="#PATypeHolder">The PATypeHolder Class</a></li>
<li><a href="#AbstractTypeUser">The AbstractTypeUser Class</a></li>
</ul></li>
<li><a href="#SymbolTable">The <tt>ValueSymbolTable</tt> and <tt>TypeSymbolTable</tt> classes</a></li>
<li><a href="#SymbolTable">The <tt>ValueSymbolTable</tt> class</a></li>
<li><a href="#UserLayout">The <tt>User</tt> and owned <tt>Use</tt> classes' memory layout</a></li>
</ul></li>
@ -2645,173 +2638,10 @@ do not need to be aware of. These API's tend manage the inner workings of the
LLVM system, and only need to be accessed in unusual circumstances.
</p>
<!-- ======================================================================= -->
<h3>
<a name="TypeResolve">LLVM Type Resolution</a>
</h3>
<div>
<p>
The LLVM type system has a very simple goal: allow clients to compare types for
structural equality with a simple pointer comparison (aka a shallow compare).
This goal makes clients much simpler and faster, and is used throughout the LLVM
system.
</p>
<p>
Unfortunately achieving this goal is not a simple matter. In particular,
recursive types and late resolution of opaque types makes the situation very
difficult to handle. Fortunately, for the most part, our implementation makes
most clients able to be completely unaware of the nasty internal details. The
primary case where clients are exposed to the inner workings of it are when
building a recursive type. In addition to this case, the LLVM bitcode reader,
assembly parser, and linker also have to be aware of the inner workings of this
system.
</p>
<p>
For our purposes below, we need three concepts. First, an "Opaque Type" is
exactly as defined in the <a href="LangRef.html#t_opaque">language
reference</a>. Second an "Abstract Type" is any type which includes an
opaque type as part of its type graph (for example "<tt>{ opaque, i32 }</tt>").
Third, a concrete type is a type that is not an abstract type (e.g. "<tt>{ i32,
float }</tt>").
</p>
<!-- ______________________________________________________________________ -->
<h4>
<a name="BuildRecType">Basic Recursive Type Construction</a>
</h4>
<div>
<p>
Because the most common question is "how do I build a recursive type with LLVM",
we answer it now and explain it as we go. Here we include enough to cause this
to be emitted to an output .ll file:
</p>
<div class="doc_code">
<pre>
%mylist = type { %mylist*, i32 }
</pre>
</div>
<p>
To build this, use the following LLVM APIs:
</p>
<div class="doc_code">
<pre>
// <i>Create the initial outer struct</i>
<a href="#PATypeHolder">PATypeHolder</a> StructTy = OpaqueType::get();
std::vector&lt;const Type*&gt; Elts;
Elts.push_back(PointerType::getUnqual(StructTy));
Elts.push_back(Type::Int32Ty);
StructType *NewSTy = StructType::get(Elts);
// <i>At this point, NewSTy = "{ opaque*, i32 }". Tell VMCore that</i>
// <i>the struct and the opaque type are actually the same.</i>
cast&lt;OpaqueType&gt;(StructTy.get())-&gt;<a href="#refineAbstractTypeTo">refineAbstractTypeTo</a>(NewSTy);
// <i>NewSTy is potentially invalidated, but StructTy (a <a href="#PATypeHolder">PATypeHolder</a>) is</i>
// <i>kept up-to-date</i>
NewSTy = cast&lt;StructType&gt;(StructTy.get());
// <i>Add a name for the type to the module symbol table (optional)</i>
MyModule-&gt;addTypeName("mylist", NewSTy);
</pre>
</div>
<p>
This code shows the basic approach used to build recursive types: build a
non-recursive type using 'opaque', then use type unification to close the cycle.
The type unification step is performed by the <tt><a
href="#refineAbstractTypeTo">refineAbstractTypeTo</a></tt> method, which is
described next. After that, we describe the <a
href="#PATypeHolder">PATypeHolder class</a>.
</p>
</div>
<!-- ______________________________________________________________________ -->
<h4>
<a name="refineAbstractTypeTo">The <tt>refineAbstractTypeTo</tt> method</a>
</h4>
<div>
<p>
The <tt>refineAbstractTypeTo</tt> method starts the type unification process.
While this method is actually a member of the DerivedType class, it is most
often used on OpaqueType instances. Type unification is actually a recursive
process. After unification, types can become structurally isomorphic to
existing types, and all duplicates are deleted (to preserve pointer equality).
</p>
<p>
In the example above, the OpaqueType object is definitely deleted.
Additionally, if there is an "{ \2*, i32}" type already created in the system,
the pointer and struct type created are <b>also</b> deleted. Obviously whenever
a type is deleted, any "Type*" pointers in the program are invalidated. As
such, it is safest to avoid having <i>any</i> "Type*" pointers to abstract types
live across a call to <tt>refineAbstractTypeTo</tt> (note that non-abstract
types can never move or be deleted). To deal with this, the <a
href="#PATypeHolder">PATypeHolder</a> class is used to maintain a stable
reference to a possibly refined type, and the <a
href="#AbstractTypeUser">AbstractTypeUser</a> class is used to update more
complex datastructures.
</p>
</div>
<!-- ______________________________________________________________________ -->
<h4>
<a name="PATypeHolder">The PATypeHolder Class</a>
</h4>
<div>
<p>
PATypeHolder is a form of a "smart pointer" for Type objects. When VMCore
happily goes about nuking types that become isomorphic to existing types, it
automatically updates all PATypeHolder objects to point to the new type. In the
example above, this allows the code to maintain a pointer to the resultant
resolved recursive type, even though the Type*'s are potentially invalidated.
</p>
<p>
PATypeHolder is an extremely light-weight object that uses a lazy union-find
implementation to update pointers. For example the pointer from a Value to its
Type is maintained by PATypeHolder objects.
</p>
</div>
<!-- ______________________________________________________________________ -->
<h4>
<a name="AbstractTypeUser">The AbstractTypeUser Class</a>
</h4>
<div>
<p>
Some data structures need more to perform more complex updates when types get
resolved. To support this, a class can derive from the AbstractTypeUser class.
This class
allows it to get callbacks when certain types are resolved. To register to get
callbacks for a particular type, the DerivedType::{add/remove}AbstractTypeUser
methods can be called on a type. Note that these methods only work for <i>
abstract</i> types. Concrete types (those that do not include any opaque
objects) can never be refined.
</p>
</div>
</div>
<!-- ======================================================================= -->
<h3>
<a name="SymbolTable">The <tt>ValueSymbolTable</tt> and
<tt>TypeSymbolTable</tt> classes</a>
<a name="SymbolTable">The <tt>ValueSymbolTable</tt> class</a>
</h3>
<div>
@ -2820,9 +2650,7 @@ ValueSymbolTable</a></tt> class provides a symbol table that the <a
href="#Function"><tt>Function</tt></a> and <a href="#Module">
<tt>Module</tt></a> classes use for naming value definitions. The symbol table
can provide a name for any <a href="#Value"><tt>Value</tt></a>.
The <tt><a href="http://llvm.org/doxygen/classllvm_1_1TypeSymbolTable.html">
TypeSymbolTable</a></tt> class is used by the <tt>Module</tt> class to store
names for types.</p>
</p>
<p>Note that the <tt>SymbolTable</tt> class should not be directly accessed
by most clients. It should only be used when iteration over the symbol table
@ -2832,13 +2660,12 @@ all LLVM
an empty name) do not exist in the symbol table.
</p>
<p>These symbol tables support iteration over the values/types in the symbol
<p>Symbol tables support iteration over the values in the symbol
table with <tt>begin/end/iterator</tt> and supports querying to see if a
specific name is in the symbol table (with <tt>lookup</tt>). The
<tt>ValueSymbolTable</tt> class exposes no public mutator methods, instead,
simply call <tt>setName</tt> on a value, which will autoinsert it into the
appropriate symbol table. For types, use the Module::addTypeName method to
insert entries into the symbol table.</p>
appropriate symbol table.</p>
</div>
@ -3128,9 +2955,6 @@ the <tt>lib/VMCore</tt> directory.</p>
<li><tt>bool isFloatingPointTy()</tt>: Return true if this is one of the five
floating point types.</li>
<li><tt>bool isAbstract()</tt>: Return true if the type is abstract (contains
an OpaqueType anywhere in its definition).</li>
<li><tt>bool isSized()</tt>: Return true if the type has known size. Things
that don't have a size are abstract types, labels and void.</li>
@ -3192,14 +3016,6 @@ the <tt>lib/VMCore</tt> directory.</p>
number of formal parameters.</li>
</ul>
</dd>
<dt><tt>OpaqueType</tt></dt>
<dd>Sublcass of DerivedType for abstract types. This class
defines no content and is used as a placeholder for some other type. Note
that OpaqueType is used (temporarily) during type resolution for forward
references of types. Once the referenced type is resolved, the OpaqueType
is replaced with the actual type. OpaqueType can also be used for data
abstraction. At link time opaque types can be resolved to actual types
of the same name.</dd>
</dl>
</div>

View File

@ -68,13 +68,6 @@ typedef struct LLVMOpaqueModule *LLVMModuleRef;
*/
typedef struct LLVMOpaqueType *LLVMTypeRef;
/**
* When building recursive types using LLVMRefineType, LLVMTypeRef values may
* become invalid; use LLVMTypeHandleRef to resolve this problem. See the
* llvm::AbstractTypeHolder class.
*/
typedef struct LLVMOpaqueTypeHandle *LLVMTypeHandleRef;
typedef struct LLVMOpaqueValue *LLVMValueRef;
typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef;
typedef struct LLVMOpaqueBuilder *LLVMBuilderRef;
@ -206,7 +199,6 @@ typedef enum {
LLVMStructTypeKind, /**< Structures */
LLVMArrayTypeKind, /**< Arrays */
LLVMPointerTypeKind, /**< Pointers */
LLVMOpaqueTypeKind, /**< Opaque: type with unknown structure */
LLVMVectorTypeKind, /**< SIMD 'packed' format, or other vector type */
LLVMMetadataTypeKind, /**< Metadata */
LLVMX86_MMXTypeKind /**< X86 MMX */
@ -320,12 +312,6 @@ void LLVMSetDataLayout(LLVMModuleRef M, const char *Triple);
const char *LLVMGetTarget(LLVMModuleRef M);
void LLVMSetTarget(LLVMModuleRef M, const char *Triple);
/** See Module::addTypeName. */
LLVMBool LLVMAddTypeName(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty);
void LLVMDeleteTypeName(LLVMModuleRef M, const char *Name);
LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name);
const char *LLVMGetTypeName(LLVMModuleRef M, LLVMTypeRef Ty);
/** See Module::dump. */
void LLVMDumpModule(LLVMModuleRef M);
@ -418,7 +404,6 @@ unsigned LLVMGetVectorSize(LLVMTypeRef VectorTy);
/* Operations on other types */
LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMOpaqueTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMVoidType(void);
@ -426,13 +411,6 @@ LLVMTypeRef LLVMLabelType(void);
LLVMTypeRef LLVMOpaqueType(void);
LLVMTypeRef LLVMX86MMXType(void);
/* Operations on type handles */
LLVMTypeHandleRef LLVMCreateTypeHandle(LLVMTypeRef PotentiallyAbstractTy);
void LLVMRefineType(LLVMTypeRef AbstractTy, LLVMTypeRef ConcreteTy);
LLVMTypeRef LLVMResolveTypeHandle(LLVMTypeHandleRef TypeHandle);
void LLVMDisposeTypeHandle(LLVMTypeHandleRef TypeHandle);
/*===-- Values ------------------------------------------------------------===*/
/* The bulk of LLVM's object model consists of values, which comprise a very
@ -1117,7 +1095,6 @@ namespace llvm {
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module, LLVMModuleRef )
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef )
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRBuilder<>, LLVMBuilderRef )
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PATypeHolder, LLVMTypeHandleRef )
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef )
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef )
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef )

View File

@ -30,9 +30,6 @@ void LLVMAddConstantMergePass(LLVMPassManagerRef PM);
/** See llvm::createDeadArgEliminationPass function. */
void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM);
/** See llvm::createDeadTypeEliminationPass function. */
void LLVMAddDeadTypeEliminationPass(LLVMPassManagerRef PM);
/** See llvm::createFunctionAttrsPass function. */
void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM);

View File

@ -1,205 +0,0 @@
//===-- llvm/AbstractTypeUser.h - AbstractTypeUser Interface ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the AbstractTypeUser class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ABSTRACT_TYPE_USER_H
#define LLVM_ABSTRACT_TYPE_USER_H
#if !defined(LLVM_TYPE_H) && !defined(LLVM_VALUE_H)
#error Do not include this file directly. Include Type.h instead.
#error Some versions of GCC (e.g. 3.4 and 4.1) can not handle the inlined method
#error PATypeHolder::dropRef() correctly otherwise.
#endif
// This is the "master" include for <cassert> Whether this file needs it or not,
// it must always include <cassert> for the files which include
// llvm/AbstractTypeUser.h
//
// In this way, most every LLVM source file will have access to the assert()
// macro without having to #include <cassert> directly.
//
#include <cassert>
namespace llvm {
class Value;
class Type;
class DerivedType;
template<typename T> struct simplify_type;
/// The AbstractTypeUser class is an interface to be implemented by classes who
/// could possibly use an abstract type. Abstract types are denoted by the
/// isAbstract flag set to true in the Type class. These are classes that
/// contain an Opaque type in their structure somewhere.
///
/// Classes must implement this interface so that they may be notified when an
/// abstract type is resolved. Abstract types may be resolved into more
/// concrete types through: linking, parsing, and bitcode reading. When this
/// happens, all of the users of the type must be updated to reference the new,
/// more concrete type. They are notified through the AbstractTypeUser
/// interface.
///
/// In addition to this, AbstractTypeUsers must keep the use list of the
/// potentially abstract type that they reference up-to-date. To do this in a
/// nice, transparent way, the PATypeHandle class is used to hold "Potentially
/// Abstract Types", and keep the use list of the abstract types up-to-date.
/// @brief LLVM Abstract Type User Representation
class AbstractTypeUser {
protected:
virtual ~AbstractTypeUser(); // Derive from me
/// setType - It's normally not possible to change a Value's type in place,
/// but an AbstractTypeUser subclass that knows what its doing can be
/// permitted to do so with care.
void setType(Value *V, const Type *NewTy);
public:
/// refineAbstractType - The callback method invoked when an abstract type is
/// resolved to another type. An object must override this method to update
/// its internal state to reference NewType instead of OldType.
///
virtual void refineAbstractType(const DerivedType *OldTy,
const Type *NewTy) = 0;
/// The other case which AbstractTypeUsers must be aware of is when a type
/// makes the transition from being abstract (where it has clients on its
/// AbstractTypeUsers list) to concrete (where it does not). This method
/// notifies ATU's when this occurs for a type.
///
virtual void typeBecameConcrete(const DerivedType *AbsTy) = 0;
// for debugging...
virtual void dump() const = 0;
};
/// PATypeHandle - Handle to a Type subclass. This class is used to keep the
/// use list of abstract types up-to-date.
///
class PATypeHandle {
const Type *Ty;
AbstractTypeUser * const User;
// These functions are defined at the bottom of Type.h. See the comment there
// for justification.
void addUser();
void removeUser();
public:
// ctor - Add use to type if abstract. Note that Ty must not be null
inline PATypeHandle(const Type *ty, AbstractTypeUser *user)
: Ty(ty), User(user) {
addUser();
}
// ctor - Add use to type if abstract.
inline PATypeHandle(const PATypeHandle &T) : Ty(T.Ty), User(T.User) {
addUser();
}
// dtor - Remove reference to type...
inline ~PATypeHandle() { removeUser(); }
// Automatic casting operator so that the handle may be used naturally
inline operator Type *() const { return const_cast<Type*>(Ty); }
inline Type *get() const { return const_cast<Type*>(Ty); }
// operator= - Allow assignment to handle
inline Type *operator=(const Type *ty) {
if (Ty != ty) { // Ensure we don't accidentally drop last ref to Ty
removeUser();
Ty = ty;
addUser();
}
return get();
}
// operator= - Allow assignment to handle
inline const Type *operator=(const PATypeHandle &T) {
return operator=(T.Ty);
}
inline bool operator==(const Type *ty) {
return Ty == ty;
}
// operator-> - Allow user to dereference handle naturally...
inline const Type *operator->() const { return Ty; }
};
/// PATypeHolder - Holder class for a potentially abstract type. This uses
/// efficient union-find techniques to handle dynamic type resolution. Unless
/// you need to do custom processing when types are resolved, you should always
/// use PATypeHolders in preference to PATypeHandles.
///
class PATypeHolder {
mutable const Type *Ty;
void destroy();
public:
PATypeHolder() : Ty(0) {}
PATypeHolder(const Type *ty) : Ty(ty) {
addRef();
}
PATypeHolder(const PATypeHolder &T) : Ty(T.Ty) {
addRef();
}
~PATypeHolder() { dropRef(); }
operator Type *() const { return get(); }
Type *get() const;
// operator-> - Allow user to dereference handle naturally...
Type *operator->() const { return get(); }
// operator= - Allow assignment to handle
Type *operator=(const Type *ty) {
if (Ty != ty) { // Don't accidentally drop last ref to Ty.
dropRef();
Ty = ty;
addRef();
}
return get();
}
Type *operator=(const PATypeHolder &H) {
return operator=(H.Ty);
}
/// getRawType - This should only be used to implement the vmcore library.
///
const Type *getRawType() const { return Ty; }
private:
void addRef();
void dropRef();
friend class TypeMapBase;
};
// simplify_type - Allow clients to treat uses just like values when using
// casting operators.
template<> struct simplify_type<PATypeHolder> {
typedef const Type* SimpleType;
static SimpleType getSimplifiedValue(const PATypeHolder &Val) {
return static_cast<SimpleType>(Val.get());
}
};
template<> struct simplify_type<const PATypeHolder> {
typedef const Type* SimpleType;
static SimpleType getSimplifiedValue(const PATypeHolder &Val) {
return static_cast<SimpleType>(Val.get());
}
};
} // End llvm namespace
#endif

View File

@ -29,13 +29,23 @@ namespace bitc {
// Module sub-block id's.
PARAMATTR_BLOCK_ID,
TYPE_BLOCK_ID,
/// TYPE_BLOCK_ID_OLD - This is the type descriptor block in LLVM 2.9 and
/// earlier, replaced with TYPE_BLOCK_ID2. FIXME: Remove in LLVM 3.1.
TYPE_BLOCK_ID_OLD,
CONSTANTS_BLOCK_ID,
FUNCTION_BLOCK_ID,
TYPE_SYMTAB_BLOCK_ID,
/// TYPE_SYMTAB_BLOCK_ID_OLD - This type descriptor is from LLVM 2.9 and
/// earlier bitcode files. FIXME: Remove in LLVM 3.1
TYPE_SYMTAB_BLOCK_ID_OLD,
VALUE_SYMTAB_BLOCK_ID,
METADATA_BLOCK_ID,
METADATA_ATTACHMENT_ID
METADATA_ATTACHMENT_ID,
TYPE_BLOCK_ID_NEW
};
@ -72,31 +82,38 @@ namespace bitc {
/// TYPE blocks have codes for each type primitive they use.
enum TypeCodes {
TYPE_CODE_NUMENTRY = 1, // NUMENTRY: [numentries]
TYPE_CODE_NUMENTRY = 1, // NUMENTRY: [numentries]
// Type Codes
TYPE_CODE_VOID = 2, // VOID
TYPE_CODE_FLOAT = 3, // FLOAT
TYPE_CODE_DOUBLE = 4, // DOUBLE
TYPE_CODE_LABEL = 5, // LABEL
TYPE_CODE_OPAQUE = 6, // OPAQUE
TYPE_CODE_INTEGER = 7, // INTEGER: [width]
TYPE_CODE_POINTER = 8, // POINTER: [pointee type]
TYPE_CODE_FUNCTION = 9, // FUNCTION: [vararg, retty, paramty x N]
TYPE_CODE_STRUCT = 10, // STRUCT: [ispacked, eltty x N]
TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty]
TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty]
TYPE_CODE_VOID = 2, // VOID
TYPE_CODE_FLOAT = 3, // FLOAT
TYPE_CODE_DOUBLE = 4, // DOUBLE
TYPE_CODE_LABEL = 5, // LABEL
TYPE_CODE_OPAQUE = 6, // OPAQUE
TYPE_CODE_INTEGER = 7, // INTEGER: [width]
TYPE_CODE_POINTER = 8, // POINTER: [pointee type]
TYPE_CODE_FUNCTION = 9, // FUNCTION: [vararg, retty, paramty x N]
// FIXME: This is the encoding used for structs in LLVM 2.9 and earlier.
// REMOVE this in LLVM 3.1
TYPE_CODE_STRUCT_OLD = 10, // STRUCT: [ispacked, eltty x N]
TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty]
TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty]
// These are not with the other floating point types because they're
// a late addition, and putting them in the right place breaks
// binary compatibility.
TYPE_CODE_X86_FP80 = 13, // X86 LONG DOUBLE
TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa)
TYPE_CODE_PPC_FP128= 15, // PPC LONG DOUBLE (2 doubles)
TYPE_CODE_X86_FP80 = 13, // X86 LONG DOUBLE
TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa)
TYPE_CODE_PPC_FP128= 15, // PPC LONG DOUBLE (2 doubles)
TYPE_CODE_METADATA = 16, // METADATA
TYPE_CODE_METADATA = 16, // METADATA
TYPE_CODE_X86_MMX = 17 // X86 MMX
TYPE_CODE_X86_MMX = 17, // X86 MMX
TYPE_CODE_STRUCT_ANON = 18, // STRUCT_ANON: [ispacked, eltty x N]
TYPE_CODE_STRUCT_NAME = 19, // STRUCT_NAME: [strchr x N]
TYPE_CODE_STRUCT_NAMED = 20 // STRUCT_NAMED: [ispacked, eltty x N]
};
// The type symbol table only has one code (TST_ENTRY_CODE).

View File

@ -912,10 +912,18 @@ public:
Constant *getWithOperandReplaced(unsigned OpNo, Constant *Op) const;
/// getWithOperands - This returns the current constant expression with the
/// operands replaced with the specified values. The specified operands must
/// match count and type with the existing ones.
Constant *getWithOperands(ArrayRef<Constant*> Ops) const;
/// operands replaced with the specified values. The specified array must
/// have the same number of operands as our current one.
Constant *getWithOperands(ArrayRef<Constant*> Ops) const {
return getWithOperands(Ops, getType());
}
/// getWithOperands - This returns the current constant expression with the
/// operands replaced with the specified values and with the specified result
/// type. The specified array must have the same number of operands as our
/// current one.
Constant *getWithOperands(ArrayRef<Constant*> Ops, const Type *Ty) const;
virtual void destroyConstant();
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);

View File

@ -29,7 +29,6 @@ extern unsigned char ConstantMergeID;
extern unsigned char CorrelatedValuePropagationID;
extern unsigned char DeadArgEliminationID;
extern unsigned char DeadStoreEliminationID;
extern unsigned char DeadTypeEliminationID;
extern unsigned char EarlyCSEID;
extern unsigned char FunctionAttrsID;
extern unsigned char FunctionInliningID;

View File

@ -24,51 +24,16 @@
namespace llvm {
class Value;
template<class ValType, class TypeClass> class TypeMap;
class FunctionValType;
class ArrayValType;
class StructValType;
class PointerValType;
class VectorValType;
class IntegerValType;
class APInt;
class LLVMContext;
template<typename T> class ArrayRef;
class StringRef;
class DerivedType : public Type {
friend class Type;
protected:
explicit DerivedType(LLVMContext &C, TypeID id) : Type(C, id) {}
/// notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type
/// that the current type has transitioned from being abstract to being
/// concrete.
///
void notifyUsesThatTypeBecameConcrete();
/// dropAllTypeUses - When this (abstract) type is resolved to be equal to
/// another (more concrete) type, we must eliminate all references to other
/// types, to avoid some circular reference problems.
///
void dropAllTypeUses();
public:
//===--------------------------------------------------------------------===//
// Abstract Type handling methods - These types have special lifetimes, which
// are managed by (add|remove)AbstractTypeUser. See comments in
// AbstractTypeUser.h for more information.
/// refineAbstractTypeTo - This function is used to when it is discovered that
/// the 'this' abstract type is actually equivalent to the NewType specified.
/// This causes all users of 'this' to switch to reference the more concrete
/// type NewType and for 'this' to be deleted.
///
void refineAbstractTypeTo(const Type *NewType);
void dump() const { Type::dump(); }
// Methods for support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const DerivedType *) { return true; }
static inline bool classof(const Type *T) {
@ -88,7 +53,6 @@ protected:
DerivedType(C, IntegerTyID) {
setSubclassData(NumBits);
}
friend class TypeMap<IntegerValType, IntegerType>;
public:
/// This enum is just used to hold constants we need for IntegerType.
enum {
@ -103,7 +67,7 @@ public:
/// that instance will be returned. Otherwise a new one will be created. Only
/// one instance with a given NumBits value is ever created.
/// @brief Get or create an IntegerType instance.
static const IntegerType *get(LLVMContext &C, unsigned NumBits);
static IntegerType *get(LLVMContext &C, unsigned NumBits);
/// @brief Get the number of bits in this IntegerType
unsigned getBitWidth() const { return getSubclassData(); }
@ -143,11 +107,9 @@ public:
/// FunctionType - Class to represent function types
///
class FunctionType : public DerivedType {
friend class TypeMap<FunctionValType, FunctionType>;
FunctionType(const FunctionType &); // Do not implement
const FunctionType &operator=(const FunctionType &); // Do not implement
FunctionType(const Type *Result, ArrayRef<const Type*> Params,
bool IsVarArgs);
FunctionType(const Type *Result, ArrayRef<Type*> Params, bool IsVarArgs);
public:
/// FunctionType::get - This static method is the primary way of constructing
@ -155,6 +117,8 @@ public:
///
static FunctionType *get(const Type *Result,
ArrayRef<const Type*> Params, bool isVarArg);
static FunctionType *get(const Type *Result,
ArrayRef<Type*> Params, bool isVarArg);
/// FunctionType::get - Create a FunctionType taking no parameters.
///
@ -169,24 +133,20 @@ public:
static bool isValidArgumentType(const Type *ArgTy);
bool isVarArg() const { return getSubclassData(); }
const Type *getReturnType() const { return ContainedTys[0]; }
Type *getReturnType() const { return ContainedTys[0]; }
typedef Type::subtype_iterator param_iterator;
param_iterator param_begin() const { return ContainedTys + 1; }
param_iterator param_end() const { return &ContainedTys[NumContainedTys]; }
// Parameter type accessors.
const Type *getParamType(unsigned i) const { return ContainedTys[i+1]; }
Type *getParamType(unsigned i) const { return ContainedTys[i+1]; }
/// getNumParams - Return the number of fixed parameters this function type
/// requires. This does not consider varargs.
///
unsigned getNumParams() const { return NumContainedTys - 1; }
// Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
virtual void typeBecameConcrete(const DerivedType *AbsTy);
// Methods for support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const FunctionType *) { return true; }
static inline bool classof(const Type *T) {
@ -205,8 +165,8 @@ public:
/// getTypeAtIndex - Given an index value into the type, return the type of
/// the element.
///
const Type *getTypeAtIndex(const Value *V) const;
const Type *getTypeAtIndex(unsigned Idx) const;
Type *getTypeAtIndex(const Value *V) const;
Type *getTypeAtIndex(unsigned Idx) const;
bool indexValid(const Value *V) const;
bool indexValid(unsigned Idx) const;
@ -222,18 +182,49 @@ public:
/// StructType - Class to represent struct types, both normal and packed.
/// Besides being optionally packed, structs can be either "anonymous" or may
/// have an identity. Anonymous structs are uniqued by structural equivalence,
/// but types are each unique when created, and optionally have a name.
///
class StructType : public CompositeType {
friend class TypeMap<StructValType, StructType>;
StructType(const StructType &); // Do not implement
const StructType &operator=(const StructType &); // Do not implement
StructType(LLVMContext &C, ArrayRef<const Type*> Types, bool isPacked);
StructType(LLVMContext &C)
: CompositeType(C, StructTyID), SymbolTableEntry(0) {}
enum {
// This is the contents of the SubClassData field.
SCDB_HasBody = 1,
SCDB_Packed = 2,
SCDB_IsAnonymous = 4
};
/// SymbolTableEntry - For a named struct that actually has a name, this is a
/// pointer to the symbol table entry (maintained by LLVMContext) for the
/// struct. This is null if the type is an anonymous struct or if it is
///
void *SymbolTableEntry;
public:
/// StructType::createNamed - This creates a named struct with no body
/// specified. If the name is empty, it creates an unnamed struct, which has
/// a unique identity but no actual name.
static StructType *createNamed(LLVMContext &Context, StringRef Name);
static StructType *createNamed(StringRef Name, ArrayRef<Type*> Elements,
bool isPacked = false);
static StructType *createNamed(LLVMContext &Context, StringRef Name,
ArrayRef<Type*> Elements,
bool isPacked = false);
static StructType *createNamed(StringRef Name, Type *elt1, ...) END_WITH_NULL;
/// StructType::get - This static method is the primary way to create a
/// StructType.
///
/// FIXME: Remove the 'const Type*' version of this when types are pervasively
/// de-constified.
static StructType *get(LLVMContext &Context, ArrayRef<const Type*> Elements,
bool isPacked = false);
static StructType *get(LLVMContext &Context, ArrayRef<Type*> Elements,
bool isPacked = false);
/// StructType::get - Create an empty structure type.
///
@ -245,11 +236,37 @@ public:
/// element type.
static StructType *get(const Type *elt1, ...) END_WITH_NULL;
bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; }
/// isAnonymous - Return true if this type is uniqued by structural
/// equivalence, false if it has an identity.
bool isAnonymous() const {return (getSubclassData() & SCDB_IsAnonymous) != 0;}
/// isOpaque - Return true if this is a type with an identity that has no body
/// specified yet. These prints as 'opaque' in .ll files.
bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; }
/// hasName - Return true if this is a named struct that has a non-empty name.
bool hasName() const { return SymbolTableEntry != 0; }
/// getName - Return the name for this struct type if it has an identity.
/// This may return an empty string for an unnamed struct type. Do not call
/// this on an anonymous type.
StringRef getName() const;
/// setName - Change the name of this type to the specified name, or to a name
/// with a suffix if there is a collision. Do not call this on an anonymous
/// type.
void setName(StringRef Name);
/// setBody - Specify a body for an opaque type.
void setBody(ArrayRef<Type*> Elements, bool isPacked = false);
void setBody(Type *elt1, ...) END_WITH_NULL;
/// isValidElementType - Return true if the specified type is valid as a
/// element type.
static bool isValidElementType(const Type *ElemTy);
bool isPacked() const { return getSubclassData() != 0 ? true : false; }
// Iterator access to the elements.
typedef Type::subtype_iterator element_iterator;
@ -258,22 +275,15 @@ public:
/// isLayoutIdentical - Return true if this is layout identical to the
/// specified struct.
bool isLayoutIdentical(const StructType *Other) const {
return this == Other;
}
bool isLayoutIdentical(const StructType *Other) const;
// Random access to the elements
unsigned getNumElements() const { return NumContainedTys; }
const Type *getElementType(unsigned N) const {
Type *getElementType(unsigned N) const {
assert(N < NumContainedTys && "Element number out of range!");
return ContainedTys[N];
}
// Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
virtual void typeBecameConcrete(const DerivedType *AbsTy);
// Methods for support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const StructType *) { return true; }
static inline bool classof(const Type *T) {
@ -290,21 +300,19 @@ public:
/// components out in memory identically.
///
class SequentialType : public CompositeType {
PATypeHandle ContainedType; ///< Storage for the single contained type.
Type *ContainedType; ///< Storage for the single contained type.
SequentialType(const SequentialType &); // Do not implement!
const SequentialType &operator=(const SequentialType &); // Do not implement!
// avoiding warning: 'this' : used in base member initializer list
SequentialType *this_() { return this; }
protected:
SequentialType(TypeID TID, const Type *ElType)
: CompositeType(ElType->getContext(), TID), ContainedType(ElType, this_()) {
SequentialType(TypeID TID, Type *ElType)
: CompositeType(ElType->getContext(), TID), ContainedType(ElType) {
ContainedTys = &ContainedType;
NumContainedTys = 1;
}
public:
const Type *getElementType() const { return ContainedTys[0]; }
Type *getElementType() const { return ContainedTys[0]; }
// Methods for support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const SequentialType *) { return true; }
@ -319,12 +327,11 @@ public:
/// ArrayType - Class to represent array types.
///
class ArrayType : public SequentialType {
friend class TypeMap<ArrayValType, ArrayType>;
uint64_t NumElements;
ArrayType(const ArrayType &); // Do not implement
const ArrayType &operator=(const ArrayType &); // Do not implement
ArrayType(const Type *ElType, uint64_t NumEl);
ArrayType(Type *ElType, uint64_t NumEl);
public:
/// ArrayType::get - This static method is the primary way to construct an
/// ArrayType
@ -337,10 +344,6 @@ public:
uint64_t getNumElements() const { return NumElements; }
// Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
virtual void typeBecameConcrete(const DerivedType *AbsTy);
// Methods for support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const ArrayType *) { return true; }
static inline bool classof(const Type *T) {
@ -351,12 +354,11 @@ public:
/// VectorType - Class to represent vector types.
///
class VectorType : public SequentialType {
friend class TypeMap<VectorValType, VectorType>;
unsigned NumElements;
VectorType(const VectorType &); // Do not implement
const VectorType &operator=(const VectorType &); // Do not implement
VectorType(const Type *ElType, unsigned NumEl);
VectorType(Type *ElType, unsigned NumEl);
public:
/// VectorType::get - This static method is the primary way to construct an
/// VectorType.
@ -369,7 +371,7 @@ public:
///
static VectorType *getInteger(const VectorType *VTy) {
unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
const Type *EltTy = IntegerType::get(VTy->getContext(), EltBits);
Type *EltTy = IntegerType::get(VTy->getContext(), EltBits);
return VectorType::get(EltTy, VTy->getNumElements());
}
@ -379,7 +381,7 @@ public:
///
static VectorType *getExtendedElementVectorType(const VectorType *VTy) {
unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
const Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2);
Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2);
return VectorType::get(EltTy, VTy->getNumElements());
}
@ -391,7 +393,7 @@ public:
unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
assert((EltBits & 1) == 0 &&
"Cannot truncate vector element with odd bit-width");
const Type *EltTy = IntegerType::get(VTy->getContext(), EltBits / 2);
Type *EltTy = IntegerType::get(VTy->getContext(), EltBits / 2);
return VectorType::get(EltTy, VTy->getNumElements());
}
@ -407,10 +409,6 @@ public:
return NumElements * getElementType()->getPrimitiveSizeInBits();
}
// Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
virtual void typeBecameConcrete(const DerivedType *AbsTy);
// Methods for support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const VectorType *) { return true; }
static inline bool classof(const Type *T) {
@ -422,11 +420,9 @@ public:
/// PointerType - Class to represent pointers.
///
class PointerType : public SequentialType {
friend class TypeMap<PointerValType, PointerType>;
PointerType(const PointerType &); // Do not implement
const PointerType &operator=(const PointerType &); // Do not implement
explicit PointerType(const Type *ElType, unsigned AddrSpace);
explicit PointerType(Type *ElType, unsigned AddrSpace);
public:
/// PointerType::get - This constructs a pointer to an object of the specified
/// type in a numbered address space.
@ -445,10 +441,6 @@ public:
/// @brief Return the address space of the Pointer type.
inline unsigned getAddressSpace() const { return getSubclassData(); }
// Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
virtual void typeBecameConcrete(const DerivedType *AbsTy);
// Implement support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const PointerType *) { return true; }
static inline bool classof(const Type *T) {
@ -456,26 +448,6 @@ public:
}
};
/// OpaqueType - Class to represent opaque types.
///
class OpaqueType : public DerivedType {
friend class LLVMContextImpl;
OpaqueType(const OpaqueType &); // DO NOT IMPLEMENT
const OpaqueType &operator=(const OpaqueType &); // DO NOT IMPLEMENT
OpaqueType(LLVMContext &C);
public:
/// OpaqueType::get - Static factory method for the OpaqueType class.
///
static OpaqueType *get(LLVMContext &C);
// Implement support for type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const OpaqueType *) { return true; }
static inline bool classof(const Type *T) {
return T->getTypeID() == OpaqueTyID;
}
};
} // End llvm namespace
#endif

View File

@ -128,8 +128,8 @@ public:
~Function();
const Type *getReturnType() const; // Return the type of the ret val
const FunctionType *getFunctionType() const; // Return the FunctionType for me
Type *getReturnType() const; // Return the type of the ret val
FunctionType *getFunctionType() const; // Return the FunctionType for me
/// getContext - Return a pointer to the LLVMContext associated with this
/// function, or NULL if this function is not bound to a context yet.

View File

@ -63,23 +63,23 @@ public:
virtual void eraseFromParent();
/// set/getAliasee - These methods retrive and set alias target.
void setAliasee(Constant* GV);
const Constant* getAliasee() const {
void setAliasee(Constant *GV);
const Constant *getAliasee() const {
return cast_or_null<Constant>(getOperand(0));
}
Constant* getAliasee() {
Constant *getAliasee() {
return cast_or_null<Constant>(getOperand(0));
}
/// getAliasedGlobal() - Aliasee can be either global or bitcast of
/// global. This method retrives the global for both aliasee flavours.
const GlobalValue* getAliasedGlobal() const;
const GlobalValue *getAliasedGlobal() const;
/// resolveAliasedGlobal() - This method tries to ultimately resolve the alias
/// by going through the aliasing chain and trying to find the very last
/// global. Returns NULL if a cycle was found. If stopOnWeak is false, then
/// the whole chain aliasing chain is traversed, otherwise - only strong
/// aliases.
const GlobalValue* resolveAliasedGlobal(bool stopOnWeak = true) const;
const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const;
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const GlobalAlias *) { return true; }

View File

@ -106,8 +106,8 @@ public:
bool use_empty_except_constants();
/// getType - Global values are always pointers.
inline const PointerType *getType() const {
return reinterpret_cast<const PointerType*>(User::getType());
inline PointerType *getType() const {
return reinterpret_cast<PointerType*>(User::getType());
}
static LinkageTypes getLinkOnceLinkage(bool ODR) {

View File

@ -84,7 +84,6 @@ void initializeDAEPass(PassRegistry&);
void initializeDAHPass(PassRegistry&);
void initializeDCEPass(PassRegistry&);
void initializeDSEPass(PassRegistry&);
void initializeDTEPass(PassRegistry&);
void initializeDeadInstEliminationPass(PassRegistry&);
void initializeDeadMachineInstructionElimPass(PassRegistry&);
void initializeDomOnlyPrinterPass(PassRegistry&);

View File

@ -76,7 +76,7 @@ public:
/// getAllocatedType - Return the type that is being allocated by the
/// instruction.
///
const Type *getAllocatedType() const;
Type *getAllocatedType() const;
/// getAlignment - Return the alignment of the memory that is being allocated
/// by the instruction.
@ -271,10 +271,10 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value)
// GetElementPtrInst Class
//===----------------------------------------------------------------------===//
// checkType - Simple wrapper function to give a better assertion failure
// checkGEPType - Simple wrapper function to give a better assertion failure
// message on bad indexes for a gep instruction.
//
static inline const Type *checkType(const Type *Ty) {
static inline const Type *checkGEPType(const Type *Ty) {
assert(Ty && "Invalid GetElementPtrInst indices for type!");
return Ty;
}
@ -315,13 +315,13 @@ class GetElementPtrInst : public Instruction {
/// pointer type.
///
template<typename RandomAccessIterator>
static const Type *getIndexedType(const Type *Ptr,
RandomAccessIterator IdxBegin,
RandomAccessIterator IdxEnd,
// This argument ensures that we
// have an iterator we can do
// arithmetic on in constant time
std::random_access_iterator_tag) {
static Type *getIndexedType(const Type *Ptr,
RandomAccessIterator IdxBegin,
RandomAccessIterator IdxEnd,
// This argument ensures that we
// have an iterator we can do
// arithmetic on in constant time
std::random_access_iterator_tag) {
unsigned NumIdx = static_cast<unsigned>(std::distance(IdxBegin, IdxEnd));
if (NumIdx > 0)
@ -446,24 +446,22 @@ public:
/// pointer type.
///
template<typename RandomAccessIterator>
static const Type *getIndexedType(const Type *Ptr,
RandomAccessIterator IdxBegin,
RandomAccessIterator IdxEnd) {
static Type *getIndexedType(const Type *Ptr, RandomAccessIterator IdxBegin,
RandomAccessIterator IdxEnd) {
return getIndexedType(Ptr, IdxBegin, IdxEnd,
typename std::iterator_traits<RandomAccessIterator>::
iterator_category());
}
static const Type *getIndexedType(const Type *Ptr,
Value* const *Idx, unsigned NumIdx);
// FIXME: Use ArrayRef
static Type *getIndexedType(const Type *Ptr,
Value* const *Idx, unsigned NumIdx);
static Type *getIndexedType(const Type *Ptr,
Constant* const *Idx, unsigned NumIdx);
static const Type *getIndexedType(const Type *Ptr,
Constant* const *Idx, unsigned NumIdx);
static const Type *getIndexedType(const Type *Ptr,
uint64_t const *Idx, unsigned NumIdx);
static const Type *getIndexedType(const Type *Ptr, Value *Idx);
static Type *getIndexedType(const Type *Ptr,
uint64_t const *Idx, unsigned NumIdx);
static Type *getIndexedType(const Type *Ptr, Value *Idx);
inline op_iterator idx_begin() { return op_begin()+1; }
inline const_op_iterator idx_begin() const { return op_begin()+1; }
@ -538,7 +536,7 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr,
unsigned Values,
const Twine &NameStr,
Instruction *InsertBefore)
: Instruction(PointerType::get(checkType(
: Instruction(PointerType::get(checkGEPType(
getIndexedType(Ptr->getType(),
IdxBegin, IdxEnd)),
cast<PointerType>(Ptr->getType())
@ -557,7 +555,7 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr,
unsigned Values,
const Twine &NameStr,
BasicBlock *InsertAtEnd)
: Instruction(PointerType::get(checkType(
: Instruction(PointerType::get(checkGEPType(
getIndexedType(Ptr->getType(),
IdxBegin, IdxEnd)),
cast<PointerType>(Ptr->getType())
@ -1459,17 +1457,18 @@ class ExtractValueInst : public UnaryInstruction {
///
/// Null is returned if the indices are invalid for the specified type.
///
static const Type *getIndexedType(const Type *Agg,
const unsigned *Idx, unsigned NumIdx);
/// FIXME: Use ArrayRef
static Type *getIndexedType(const Type *Agg,
const unsigned *Idx, unsigned NumIdx);
template<typename RandomAccessIterator>
static const Type *getIndexedType(const Type *Ptr,
RandomAccessIterator IdxBegin,
RandomAccessIterator IdxEnd,
// This argument ensures that we
// have an iterator we can do
// arithmetic on in constant time
std::random_access_iterator_tag) {
static Type *getIndexedType(const Type *Ptr,
RandomAccessIterator IdxBegin,
RandomAccessIterator IdxEnd,
// This argument ensures that we
// have an iterator we can do
// arithmetic on in constant time
std::random_access_iterator_tag) {
unsigned NumIdx = static_cast<unsigned>(std::distance(IdxBegin, IdxEnd));
if (NumIdx > 0)
@ -1542,15 +1541,16 @@ public:
///
/// Null is returned if the indices are invalid for the specified type.
///
/// FIXME: Remove the templates and just use ArrayRef.
template<typename RandomAccessIterator>
static const Type *getIndexedType(const Type *Ptr,
RandomAccessIterator IdxBegin,
RandomAccessIterator IdxEnd) {
static Type *getIndexedType(const Type *Ptr,
RandomAccessIterator IdxBegin,
RandomAccessIterator IdxEnd) {
return getIndexedType(Ptr, IdxBegin, IdxEnd,
typename std::iterator_traits<RandomAccessIterator>::
iterator_category());
}
static const Type *getIndexedType(const Type *Ptr, unsigned Idx);
static Type *getIndexedType(const Type *Ptr, unsigned Idx);
typedef const unsigned* idx_iterator;
inline idx_iterator idx_begin() const { return Indices.begin(); }
@ -1590,8 +1590,8 @@ ExtractValueInst::ExtractValueInst(Value *Agg,
RandomAccessIterator IdxEnd,
const Twine &NameStr,
Instruction *InsertBefore)
: UnaryInstruction(checkType(getIndexedType(Agg->getType(),
IdxBegin, IdxEnd)),
: UnaryInstruction(checkGEPType(getIndexedType(Agg->getType(),
IdxBegin, IdxEnd)),
ExtractValue, Agg, InsertBefore) {
init(IdxBegin, IdxEnd, NameStr,
typename std::iterator_traits<RandomAccessIterator>
@ -1603,8 +1603,8 @@ ExtractValueInst::ExtractValueInst(Value *Agg,
RandomAccessIterator IdxEnd,
const Twine &NameStr,
BasicBlock *InsertAtEnd)
: UnaryInstruction(checkType(getIndexedType(Agg->getType(),
IdxBegin, IdxEnd)),
: UnaryInstruction(checkGEPType(getIndexedType(Agg->getType(),
IdxBegin, IdxEnd)),
ExtractValue, Agg, InsertAtEnd) {
init(IdxBegin, IdxEnd, NameStr,
typename std::iterator_traits<RandomAccessIterator>

View File

@ -62,7 +62,6 @@ namespace {
(void) llvm::createDeadCodeEliminationPass();
(void) llvm::createDeadInstEliminationPass();
(void) llvm::createDeadStoreEliminationPass();
(void) llvm::createDeadTypeEliminationPass();
(void) llvm::createDomOnlyPrinterPass();
(void) llvm::createDomPrinterPass();
(void) llvm::createDomOnlyViewerPass();

View File

@ -28,6 +28,10 @@ namespace llvm {
class FunctionType;
class GVMaterializer;
class LLVMContext;
class StructType;
template<typename T> struct DenseMapInfo;
template<typename KeyT, typename ValueT,
typename KeyInfoT, typename ValueInfoT> class DenseMap;
template<> struct ilist_traits<Function>
: public SymbolTableListTraits<Function, Module> {
@ -145,7 +149,6 @@ private:
NamedMDListType NamedMDList; ///< The named metadata in the module
std::string GlobalScopeAsm; ///< Inline Asm at global scope.
ValueSymbolTable *ValSymTab; ///< Symbol table for values
TypeSymbolTable *TypeSymTab; ///< Symbol table for types
OwningPtr<GVMaterializer> Materializer; ///< Used to materialize GlobalValues
std::string ModuleID; ///< Human readable identifier for the module
std::string TargetTriple; ///< Platform target triple Module compiled on
@ -231,7 +234,7 @@ public:
/// @name Generic Value Accessors
/// @{
/// getNamedValue - Return the first global value in the module with
/// getNamedValue - Return the global value in the module with
/// the specified name, of arbitrary type. This method returns null
/// if a global with the specified name is not found.
GlobalValue *getNamedValue(StringRef Name) const;
@ -244,6 +247,18 @@ public:
/// custom metadata IDs registered in this LLVMContext.
void getMDKindNames(SmallVectorImpl<StringRef> &Result) const;
typedef DenseMap<StructType*, unsigned, DenseMapInfo<StructType*>,
DenseMapInfo<unsigned> > NumeredTypesMapTy;
/// findUsedStructTypes - Walk the entire module and find all of the
/// struct types that are in use, returning them in a vector.
void findUsedStructTypes(std::vector<StructType*> &StructTypes) const;
/// getTypeByName - Return the type with the specified name, or null if there
/// is none by that name.
StructType *getTypeByName(StringRef Name) const;
/// @}
/// @name Function Accessors
/// @{
@ -296,7 +311,7 @@ public:
GlobalVariable *getGlobalVariable(StringRef Name,
bool AllowInternal = false) const;
/// getNamedGlobal - Return the first global variable in the module with the
/// getNamedGlobal - Return the global variable in the module with the
/// specified name, of arbitrary type. This method returns null if a global
/// with the specified name is not found.
GlobalVariable *getNamedGlobal(StringRef Name) const {
@ -316,7 +331,7 @@ public:
/// @name Global Alias Accessors
/// @{
/// getNamedAlias - Return the first global alias in the module with the
/// getNamedAlias - Return the global alias in the module with the
/// specified name, of arbitrary type. This method returns null if a global
/// with the specified name is not found.
GlobalAlias *getNamedAlias(StringRef Name) const;
@ -325,12 +340,12 @@ public:
/// @name Named Metadata Accessors
/// @{
/// getNamedMetadata - Return the first NamedMDNode in the module with the
/// getNamedMetadata - Return the NamedMDNode in the module with the
/// specified name. This method returns null if a NamedMDNode with the
/// specified name is not found.
NamedMDNode *getNamedMetadata(const Twine &Name) const;
/// getOrInsertNamedMetadata - Return the first named MDNode in the module
/// getOrInsertNamedMetadata - Return the named MDNode in the module
/// with the specified name. This method returns a new NamedMDNode if a
/// NamedMDNode with the specified name is not found.
NamedMDNode *getOrInsertNamedMetadata(StringRef Name);
@ -339,23 +354,6 @@ public:
/// and delete it.
void eraseNamedMetadata(NamedMDNode *NMD);
/// @}
/// @name Type Accessors
/// @{
/// addTypeName - Insert an entry in the symbol table mapping Str to Type. If
/// there is already an entry for this name, true is returned and the symbol
/// table is not modified.
bool addTypeName(StringRef Name, const Type *Ty);
/// getTypeName - If there is at least one entry in the symbol table for the
/// specified type, return it.
std::string getTypeName(const Type *Ty) const;
/// getTypeByName - Return the type with the specified name in this module, or
/// null if there is none by that name.
const Type *getTypeByName(StringRef Name) const;
/// @}
/// @name Materialization
/// @{
@ -429,41 +427,26 @@ public:
const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; }
/// Get the Module's symbol table of global variable and function identifiers.
ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; }
/// Get the symbol table of types
const TypeSymbolTable &getTypeSymbolTable() const { return *TypeSymTab; }
/// Get the Module's symbol table of types
TypeSymbolTable &getTypeSymbolTable() { return *TypeSymTab; }
/// @}
/// @name Global Variable Iteration
/// @{
/// Get an iterator to the first global variable
global_iterator global_begin() { return GlobalList.begin(); }
/// Get a constant iterator to the first global variable
const_global_iterator global_begin() const { return GlobalList.begin(); }
/// Get an iterator to the last global variable
global_iterator global_end () { return GlobalList.end(); }
/// Get a constant iterator to the last global variable
const_global_iterator global_end () const { return GlobalList.end(); }
/// Determine if the list of globals is empty.
bool global_empty() const { return GlobalList.empty(); }
/// @}
/// @name Function Iteration
/// @{
/// Get an iterator to the first function.
iterator begin() { return FunctionList.begin(); }
/// Get a constant iterator to the first function.
const_iterator begin() const { return FunctionList.begin(); }
/// Get an iterator to the last function.
iterator end () { return FunctionList.end(); }
/// Get a constant iterator to the last function.
const_iterator end () const { return FunctionList.end(); }
/// Determine how many functions are in the Module's list of functions.
size_t size() const { return FunctionList.size(); }
/// Determine if the list of functions is empty.
bool empty() const { return FunctionList.empty(); }
/// @}
@ -487,17 +470,11 @@ public:
/// @name Alias Iteration
/// @{
/// Get an iterator to the first alias.
alias_iterator alias_begin() { return AliasList.begin(); }
/// Get a constant iterator to the first alias.
const_alias_iterator alias_begin() const { return AliasList.begin(); }
/// Get an iterator to the last alias.
alias_iterator alias_end () { return AliasList.end(); }
/// Get a constant iterator to the last alias.
const_alias_iterator alias_end () const { return AliasList.end(); }
/// Determine how many aliases are in the Module's list of aliases.
size_t alias_size () const { return AliasList.size(); }
/// Determine if the list of aliases is empty.
bool alias_empty() const { return AliasList.empty(); }
@ -505,24 +482,17 @@ public:
/// @name Named Metadata Iteration
/// @{
/// Get an iterator to the first named metadata.
named_metadata_iterator named_metadata_begin() { return NamedMDList.begin(); }
/// Get a constant iterator to the first named metadata.
const_named_metadata_iterator named_metadata_begin() const {
return NamedMDList.begin();
}
/// Get an iterator to the last named metadata.
named_metadata_iterator named_metadata_end() { return NamedMDList.end(); }
/// Get a constant iterator to the last named metadata.
const_named_metadata_iterator named_metadata_end() const {
return NamedMDList.end();
}
/// Determine how many NamedMDNodes are in the Module's list of named
/// metadata.
size_t named_metadata_size() const { return NamedMDList.size(); }
/// Determine if the list of named metadata is empty.
bool named_metadata_empty() const { return NamedMDList.empty(); }
@ -530,11 +500,13 @@ public:
/// @name Utility functions for printing and dumping Module objects
/// @{
/// Print the module to an output stream with AssemblyAnnotationWriter.
/// Print the module to an output stream with an optional
/// AssemblyAnnotationWriter.
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const;
/// Dump the module to stderr (for debugging).
void dump() const;
/// This function causes all the subinstructions to "let go" of all references
/// that they are maintaining. This allows one to 'delete' a whole class at
/// a time, even though there may be circular references... first all

View File

@ -237,8 +237,8 @@ public:
MPM.add(createInstructionCombiningPass()); // Clean up after everything.
if (!DisableUnitAtATime) {
// FIXME: We shouldn't bother with this anymore.
MPM.add(createStripDeadPrototypesPass()); // Get rid of dead prototypes
MPM.add(createDeadTypeEliminationPass()); // Eliminate dead types
// GlobalOpt already deletes dead functions and globals, at -O3 try a
// late pass of GlobalDCE. It is capable of deleting dead cycles.

View File

@ -73,13 +73,6 @@ ModulePass *createConstantMergePass();
ModulePass *createGlobalOptimizerPass();
//===----------------------------------------------------------------------===//
/// createDeadTypeEliminationPass - Return a new pass that eliminates symbol
/// table entries for types that are never used.
///
ModulePass *createDeadTypeEliminationPass();
//===----------------------------------------------------------------------===//
/// createGlobalDCEPass - This transform is designed to eliminate unreachable
/// internal globals (functions or global variables)

View File

@ -22,6 +22,18 @@ namespace llvm {
class Instruction;
typedef ValueMap<const Value *, TrackingVH<Value> > ValueToValueMapTy;
/// ValueMapTypeRemapper - This is a class that can be implemented by clients
/// to remap types when cloning constants and instructions.
class ValueMapTypeRemapper {
virtual void Anchor(); // Out of line method.
public:
~ValueMapTypeRemapper() {}
/// remapType - The client should implement this method if they want to
/// remap types while mapping values.
virtual Type *remapType(Type *SrcTy) = 0;
};
/// RemapFlags - These are flags that the value mapping APIs allow.
enum RemapFlags {
RF_None = 0,
@ -42,9 +54,27 @@ namespace llvm {
}
Value *MapValue(const Value *V, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None);
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = 0);
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None);
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = 0);
/// MapValue - provide versions that preserve type safety for MDNode and
/// Constants.
inline MDNode *MapValue(const MDNode *V, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = 0) {
return (MDNode*)MapValue((const Value*)V, VM, Flags, TypeMapper);
}
inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = 0) {
return (Constant*)MapValue((const Value*)V, VM, Flags, TypeMapper);
}
} // End llvm namespace
#endif

View File

@ -15,19 +15,17 @@
#ifndef LLVM_TYPE_H
#define LLVM_TYPE_H
#include "llvm/AbstractTypeUser.h"
#include "llvm/Support/Casting.h"
#include <vector>
namespace llvm {
class DerivedType;
class PointerType;
class IntegerType;
class TypeMapBase;
class raw_ostream;
class Module;
class LLVMContext;
class LLVMContextImpl;
template<class GraphType> struct GraphTraits;
/// The instances of the Type class are immutable: once they are created,
@ -35,29 +33,10 @@ template<class GraphType> struct GraphTraits;
/// type is ever created. Thus seeing if two types are equal is a matter of
/// doing a trivial pointer comparison. To enforce that no two equal instances
/// are created, Type instances can only be created via static factory methods
/// in class Type and in derived classes.
/// in class Type and in derived classes. Once allocated, Types are never
/// free'd.
///
/// Once allocated, Types are never free'd, unless they are an abstract type
/// that is resolved to a more concrete type.
///
/// Types themself don't have a name, and can be named either by:
/// - using SymbolTable instance, typically from some Module,
/// - using convenience methods in the Module class (which uses module's
/// SymbolTable too).
///
/// Opaque types are simple derived types with no state. There may be many
/// different Opaque type objects floating around, but two are only considered
/// identical if they are pointer equals of each other. This allows us to have
/// two opaque types that end up resolving to different concrete types later.
///
/// Opaque types are also kinda weird and scary and different because they have
/// to keep a list of uses of the type. When, through linking, parsing, or
/// bitcode reading, they become resolved, they need to find and update all
/// users of the unknown type, causing them to reference a new, more concrete
/// type. Opaque types are deleted when their use list dwindles to zero users.
///
/// @brief Root of type hierarchy
class Type : public AbstractTypeUser {
class Type {
public:
//===--------------------------------------------------------------------===//
/// Definitions of all of the base types for the Type system. Based on this
@ -85,8 +64,7 @@ public:
StructTyID, ///< 11: Structures
ArrayTyID, ///< 12: Arrays
PointerTyID, ///< 13: Pointers
OpaqueTyID, ///< 14: Opaque: type with unknown structure
VectorTyID, ///< 15: SIMD 'packed' format, or other vector type
VectorTyID, ///< 14: SIMD 'packed' format, or other vector type
NumTypeIDs, // Must remain as last defined ID
LastPrimitiveTyID = X86_MMXTyID,
@ -94,86 +72,42 @@ public:
};
private:
TypeID ID : 8; // The current base type of this type.
bool Abstract : 1; // True if type contains an OpaqueType
unsigned SubclassData : 23; //Space for subclasses to store data
/// RefCount - This counts the number of PATypeHolders that are pointing to
/// this type. When this number falls to zero, if the type is abstract and
/// has no AbstractTypeUsers, the type is deleted. This is only sensical for
/// derived types.
///
mutable unsigned RefCount;
/// Context - This refers to the LLVMContext in which this type was uniqued.
LLVMContext &Context;
friend class LLVMContextImpl;
const Type *getForwardedTypeInternal() const;
// When the last reference to a forwarded type is removed, it is destroyed.
void destroy() const;
TypeID ID : 8; // The current base type of this type.
unsigned SubclassData : 24; // Space for subclasses to store data
protected:
explicit Type(LLVMContext &C, TypeID id) :
ID(id), Abstract(false), SubclassData(0),
RefCount(0), Context(C),
ForwardType(0), NumContainedTys(0),
ContainedTys(0) {}
virtual ~Type() {
assert(AbstractTypeUsers.empty() && "Abstract types remain");
}
/// Types can become nonabstract later, if they are refined.
///
inline void setAbstract(bool Val) { Abstract = Val; }
unsigned getRefCount() const { return RefCount; }
friend class LLVMContextImpl;
explicit Type(LLVMContext &C, TypeID tid)
: Context(C), ID(tid), SubclassData(0),
NumContainedTys(0), ContainedTys(0) {}
~Type() {}
unsigned getSubclassData() const { return SubclassData; }
void setSubclassData(unsigned val) { SubclassData = val; }
void setSubclassData(unsigned val) {
SubclassData = val;
// Ensure we don't have any accidental truncation.
assert(SubclassData == val && "Subclass data too large for field");
}
/// ForwardType - This field is used to implement the union find scheme for
/// abstract types. When types are refined to other types, this field is set
/// to the more refined type. Only abstract types can be forwarded.
mutable const Type *ForwardType;
/// AbstractTypeUsers - Implement a list of the users that need to be notified
/// if I am a type, and I get resolved into a more concrete type.
///
mutable std::vector<AbstractTypeUser *> AbstractTypeUsers;
/// NumContainedTys - Keeps track of how many PATypeHandle instances there
/// are at the end of this type instance for the list of contained types. It
/// is the subclasses responsibility to set this up. Set to 0 if there are no
/// contained types in this type.
/// NumContainedTys - Keeps track of how many Type*'s there are in the
/// ContainedTys list.
unsigned NumContainedTys;
/// ContainedTys - A pointer to the array of Types (PATypeHandle) contained
/// by this Type. For example, this includes the arguments of a function
/// type, the elements of a structure, the pointee of a pointer, the element
/// type of an array, etc. This pointer may be 0 for types that don't
/// contain other types (Integer, Double, Float). In general, the subclass
/// should arrange for space for the PATypeHandles to be included in the
/// allocation of the type object and set this pointer to the address of the
/// first element. This allows the Type class to manipulate the ContainedTys
/// without understanding the subclass's placement for this array. keeping
/// it here also allows the subtype_* members to be implemented MUCH more
/// efficiently, and dynamically very few types do not contain any elements.
PATypeHandle *ContainedTys;
/// ContainedTys - A pointer to the array of Types contained by this Type.
/// For example, this includes the arguments of a function type, the elements
/// of a structure, the pointee of a pointer, the element type of an array,
/// etc. This pointer may be 0 for types that don't contain other types
/// (Integer, Double, Float).
Type * const *ContainedTys;
public:
void print(raw_ostream &O) const;
/// @brief Debugging support: print to stderr
void dump() const;
/// @brief Debugging support: print to stderr (use type names from context
/// module).
void dump(const Module *Context) const;
/// getContext - Fetch the LLVMContext in which this type was uniqued.
/// getContext - Return the LLVMContext in which this type was uniqued.
LLVMContext &getContext() const { return Context; }
//===--------------------------------------------------------------------===//
@ -205,8 +139,10 @@ public:
/// isFloatingPointTy - Return true if this is one of the five floating point
/// types
bool isFloatingPointTy() const { return ID == FloatTyID || ID == DoubleTyID ||
ID == X86_FP80TyID || ID == FP128TyID || ID == PPC_FP128TyID; }
bool isFloatingPointTy() const {
return ID == FloatTyID || ID == DoubleTyID ||
ID == X86_FP80TyID || ID == FP128TyID || ID == PPC_FP128TyID;
}
/// isX86_MMXTy - Return true if this is X86 MMX.
bool isX86_MMXTy() const { return ID == X86_MMXTyID; }
@ -249,19 +185,10 @@ public:
///
bool isPointerTy() const { return ID == PointerTyID; }
/// isOpaqueTy - True if this is an instance of OpaqueType.
///
bool isOpaqueTy() const { return ID == OpaqueTyID; }
/// isVectorTy - True if this is an instance of VectorType.
///
bool isVectorTy() const { return ID == VectorTyID; }
/// isAbstract - True if the type is either an Opaque type, or is a derived
/// type that includes an opaque type somewhere in it.
///
inline bool isAbstract() const { return Abstract; }
/// canLosslesslyBitCastTo - Return true if this type could be converted
/// with a lossless BitCast to type 'Ty'. For example, i8* to i32*. BitCasts
/// are valid for types of the same size only where no re-interpretation of
@ -276,24 +203,22 @@ public:
/// Here are some useful little methods to query what type derived types are
/// Note that all other types can just compare to see if this == Type::xxxTy;
///
inline bool isPrimitiveType() const { return ID <= LastPrimitiveTyID; }
inline bool isDerivedType() const { return ID >= FirstDerivedTyID; }
bool isPrimitiveType() const { return ID <= LastPrimitiveTyID; }
bool isDerivedType() const { return ID >= FirstDerivedTyID; }
/// isFirstClassType - Return true if the type is "first class", meaning it
/// is a valid type for a Value.
///
inline bool isFirstClassType() const {
// There are more first-class kinds than non-first-class kinds, so a
// negative test is simpler than a positive one.
return ID != FunctionTyID && ID != VoidTyID && ID != OpaqueTyID;
bool isFirstClassType() const {
return ID != FunctionTyID && ID != VoidTyID;
}
/// isSingleValueType - Return true if the type is a valid type for a
/// virtual register in codegen. This includes all first-class types
/// except struct and array types.
/// register in codegen. This includes all first-class types except struct
/// and array types.
///
inline bool isSingleValueType() const {
return (ID != VoidTyID && ID <= LastPrimitiveTyID) ||
bool isSingleValueType() const {
return (ID != VoidTyID && isPrimitiveType()) ||
ID == IntegerTyID || ID == PointerTyID || ID == VectorTyID;
}
@ -302,7 +227,7 @@ public:
/// extractvalue instruction. This includes struct and array types, but
/// does not include vector types.
///
inline bool isAggregateType() const {
bool isAggregateType() const {
return ID == StructTyID || ID == ArrayTyID;
}
@ -319,9 +244,8 @@ public:
// it doesn't have a size.
if (ID != StructTyID && ID != ArrayTyID && ID != VectorTyID)
return false;
// If it is something that can have a size and it's concrete, it definitely
// has a size, otherwise we have to try harder to decide.
return !isAbstract() || isSizedDerivedType();
// Otherwise we have to try harder to decide.
return isSizedDerivedType();
}
/// getPrimitiveSizeInBits - Return the basic size of this type if it is a
@ -346,23 +270,14 @@ public:
/// have a stable mantissa (e.g. ppc long double), this method returns -1.
int getFPMantissaWidth() const;
/// getForwardedType - Return the type that this type has been resolved to if
/// it has been resolved to anything. This is used to implement the
/// union-find algorithm for type resolution, and shouldn't be used by general
/// purpose clients.
const Type *getForwardedType() const {
if (!ForwardType) return 0;
return getForwardedTypeInternal();
}
/// getScalarType - If this is a vector type, return the element type,
/// otherwise return this.
/// otherwise return 'this'.
const Type *getScalarType() const;
//===--------------------------------------------------------------------===//
// Type Iteration support
// Type Iteration support.
//
typedef PATypeHandle *subtype_iterator;
typedef Type * const *subtype_iterator;
subtype_iterator subtype_begin() const { return ContainedTys; }
subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];}
@ -370,9 +285,9 @@ public:
/// (defined a the end of the file). For derived types, this returns the
/// types 'contained' in the derived type.
///
const Type *getContainedType(unsigned i) const {
Type *getContainedType(unsigned i) const {
assert(i < NumContainedTys && "Index out of range!");
return ContainedTys[i].get();
return ContainedTys[i];
}
/// getNumContainedTypes - Return the number of types in the derived type.
@ -385,140 +300,77 @@ public:
//
/// getPrimitiveType - Return a type based on an identifier.
static const Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber);
static Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber);
//===--------------------------------------------------------------------===//
// These are the builtin types that are always available...
// These are the builtin types that are always available.
//
static const Type *getVoidTy(LLVMContext &C);
static const Type *getLabelTy(LLVMContext &C);
static const Type *getFloatTy(LLVMContext &C);
static const Type *getDoubleTy(LLVMContext &C);
static const Type *getMetadataTy(LLVMContext &C);
static const Type *getX86_FP80Ty(LLVMContext &C);
static const Type *getFP128Ty(LLVMContext &C);
static const Type *getPPC_FP128Ty(LLVMContext &C);
static const Type *getX86_MMXTy(LLVMContext &C);
static const IntegerType *getIntNTy(LLVMContext &C, unsigned N);
static const IntegerType *getInt1Ty(LLVMContext &C);
static const IntegerType *getInt8Ty(LLVMContext &C);
static const IntegerType *getInt16Ty(LLVMContext &C);
static const IntegerType *getInt32Ty(LLVMContext &C);
static const IntegerType *getInt64Ty(LLVMContext &C);
static Type *getVoidTy(LLVMContext &C);
static Type *getLabelTy(LLVMContext &C);
static Type *getFloatTy(LLVMContext &C);
static Type *getDoubleTy(LLVMContext &C);
static Type *getMetadataTy(LLVMContext &C);
static Type *getX86_FP80Ty(LLVMContext &C);
static Type *getFP128Ty(LLVMContext &C);
static Type *getPPC_FP128Ty(LLVMContext &C);
static Type *getX86_MMXTy(LLVMContext &C);
static IntegerType *getIntNTy(LLVMContext &C, unsigned N);
static IntegerType *getInt1Ty(LLVMContext &C);
static IntegerType *getInt8Ty(LLVMContext &C);
static IntegerType *getInt16Ty(LLVMContext &C);
static IntegerType *getInt32Ty(LLVMContext &C);
static IntegerType *getInt64Ty(LLVMContext &C);
//===--------------------------------------------------------------------===//
// Convenience methods for getting pointer types with one of the above builtin
// types as pointee.
//
static const PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0);
static const PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0);
static const PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0);
static const PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0);
static const PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0);
static const PointerType *getX86_MMXPtrTy(LLVMContext &C, unsigned AS = 0);
static const PointerType *getIntNPtrTy(LLVMContext &C, unsigned N,
unsigned AS = 0);
static const PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0);
static const PointerType *getInt8PtrTy(LLVMContext &C, unsigned AS = 0);
static const PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0);
static const PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0);
static const PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getX86_MMXPtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS = 0);
static PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getInt8PtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0);
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Type *) { return true; }
void addRef() const {
assert(isAbstract() && "Cannot add a reference to a non-abstract type!");
++RefCount;
}
void dropRef() const {
assert(isAbstract() && "Cannot drop a reference to a non-abstract type!");
assert(RefCount && "No objects are currently referencing this object!");
// If this is the last PATypeHolder using this object, and there are no
// PATypeHandles using it, the type is dead, delete it now.
if (--RefCount == 0 && AbstractTypeUsers.empty())
this->destroy();
}
/// addAbstractTypeUser - Notify an abstract type that there is a new user of
/// it. This function is called primarily by the PATypeHandle class.
///
void addAbstractTypeUser(AbstractTypeUser *U) const;
/// removeAbstractTypeUser - Notify an abstract type that a user of the class
/// no longer has a handle to the type. This function is called primarily by
/// the PATypeHandle class. When there are no users of the abstract type, it
/// is annihilated, because there is no way to get a reference to it ever
/// again.
///
void removeAbstractTypeUser(AbstractTypeUser *U) const;
/// getPointerTo - Return a pointer to the current type. This is equivalent
/// to PointerType::get(Foo, AddrSpace).
const PointerType *getPointerTo(unsigned AddrSpace = 0) const;
PointerType *getPointerTo(unsigned AddrSpace = 0) const;
private:
/// isSizedDerivedType - Derived types like structures and arrays are sized
/// iff all of the members of the type are sized as well. Since asking for
/// their size is relatively uncommon, move this operation out of line.
bool isSizedDerivedType() const;
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
virtual void typeBecameConcrete(const DerivedType *AbsTy);
protected:
// PromoteAbstractToConcrete - This is an internal method used to calculate
// change "Abstract" from true to false when types are refined.
void PromoteAbstractToConcrete();
friend class TypeMapBase;
};
//===----------------------------------------------------------------------===//
// Define some inline methods for the AbstractTypeUser.h:PATypeHandle class.
// These are defined here because they MUST be inlined, yet are dependent on
// the definition of the Type class.
//
inline void PATypeHandle::addUser() {
assert(Ty && "Type Handle has a null type!");
if (Ty->isAbstract())
Ty->addAbstractTypeUser(User);
}
inline void PATypeHandle::removeUser() {
if (Ty->isAbstract())
Ty->removeAbstractTypeUser(User);
}
// Define inline methods for PATypeHolder.
/// get - This implements the forwarding part of the union-find algorithm for
/// abstract types. Before every access to the Type*, we check to see if the
/// type we are pointing to is forwarding to a new type. If so, we drop our
/// reference to the type.
///
inline Type *PATypeHolder::get() const {
if (Ty == 0) return 0;
const Type *NewTy = Ty->getForwardedType();
if (!NewTy) return const_cast<Type*>(Ty);
return *const_cast<PATypeHolder*>(this) = NewTy;
}
inline void PATypeHolder::addRef() {
if (Ty && Ty->isAbstract())
Ty->addRef();
}
inline void PATypeHolder::dropRef() {
if (Ty && Ty->isAbstract())
Ty->dropRef();
// Printing of types.
static inline raw_ostream &operator<<(raw_ostream &OS, const Type &T) {
T.print(OS);
return OS;
}
// allow isa<PointerType>(x) to work without DerivedTypes.h included.
template <> struct isa_impl<PointerType, Type> {
static inline bool doit(const Type &Ty) {
return Ty.getTypeID() == Type::PointerTyID;
}
};
//===----------------------------------------------------------------------===//
// Provide specializations of GraphTraits to be able to treat a type as a
// graph of sub types.
template <> struct GraphTraits<Type*> {
typedef Type NodeType;
typedef Type::subtype_iterator ChildIteratorType;
@ -545,14 +397,6 @@ template <> struct GraphTraits<const Type*> {
}
};
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);
} // End llvm namespace
#endif

View File

@ -1,152 +0,0 @@
//===-- llvm/TypeSymbolTable.h - Implement a Type Symtab --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the name/type symbol table for LLVM.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TYPE_SYMBOL_TABLE_H
#define LLVM_TYPE_SYMBOL_TABLE_H
#include "llvm/Type.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include <map>
namespace llvm {
/// This class provides a symbol table of name/type pairs with operations to
/// support constructing, searching and iterating over the symbol table. The
/// class derives from AbstractTypeUser so that the contents of the symbol
/// table can be updated when abstract types become concrete.
class TypeSymbolTable : public AbstractTypeUser {
/// @name Types
/// @{
public:
/// @brief A mapping of names to types.
typedef std::map<const std::string, const Type*> TypeMap;
/// @brief An iterator over the TypeMap.
typedef TypeMap::iterator iterator;
/// @brief A const_iterator over the TypeMap.
typedef TypeMap::const_iterator const_iterator;
/// @}
/// @name Constructors
/// @{
public:
TypeSymbolTable():LastUnique(0) {}
~TypeSymbolTable();
/// @}
/// @name Accessors
/// @{
public:
/// Generates a unique name for a type based on the \p BaseName by
/// incrementing an integer and appending it to the name, if necessary
/// @returns the unique name
/// @brief Get a unique name for a type
std::string getUniqueName(StringRef BaseName) const;
/// This method finds the type with the given \p name in the type map
/// and returns it.
/// @returns null if the name is not found, otherwise the Type
/// associated with the \p name.
/// @brief Lookup a type by name.
Type *lookup(StringRef name) const;
/// Lookup the type associated with name.
/// @returns end() if the name is not found, or an iterator at the entry for
/// Type.
iterator find(StringRef Name) {
return tmap.find(Name);
}
/// Lookup the type associated with name.
/// @returns end() if the name is not found, or an iterator at the entry for
/// Type.
const_iterator find(StringRef Name) const {
return tmap.find(Name);
}
/// @returns true iff the symbol table is empty.
/// @brief Determine if the symbol table is empty
inline bool empty() const { return tmap.empty(); }
/// @returns the size of the symbol table
/// @brief The number of name/type pairs is returned.
inline unsigned size() const { return unsigned(tmap.size()); }
/// This function can be used from the debugger to display the
/// content of the symbol table while debugging.
/// @brief Print out symbol table on stderr
void dump() const;
/// @}
/// @name Iteration
/// @{
public:
/// Get an iterator to the start of the symbol table
inline iterator begin() { return tmap.begin(); }
/// @brief Get a const_iterator to the start of the symbol table
inline const_iterator begin() const { return tmap.begin(); }
/// Get an iterator to the end of the symbol table.
inline iterator end() { return tmap.end(); }
/// Get a const_iterator to the end of the symbol table.
inline const_iterator end() const { return tmap.end(); }
/// @}
/// @name Mutators
/// @{
public:
/// Inserts a type into the symbol table with the specified name. There can be
/// a many-to-one mapping between names and types. This method allows a type
/// with an existing entry in the symbol table to get a new name.
/// @brief Insert a type under a new name.
void insert(StringRef Name, const Type *Typ);
/// Remove a type at the specified position in the symbol table.
/// @returns the removed Type.
/// @returns the Type that was erased from the symbol table.
Type* remove(iterator TI);
/// @}
/// @name AbstractTypeUser Methods
/// @{
private:
/// This function is called when one of the types in the type plane
/// is refined.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
/// This function marks a type as being concrete (defined).
virtual void typeBecameConcrete(const DerivedType *AbsTy);
/// @}
/// @name Internal Data
/// @{
private:
TypeMap tmap; ///< This is the mapping of names to types.
mutable uint32_t LastUnique; ///< Counter for tracking unique names
/// @}
};
} // End llvm namespace
#endif

View File

@ -14,7 +14,6 @@
#ifndef LLVM_VALUE_H
#define LLVM_VALUE_H
#include "llvm/AbstractTypeUser.h"
#include "llvm/Use.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
@ -32,7 +31,6 @@ class GlobalVariable;
class GlobalAlias;
class InlineAsm;
class ValueSymbolTable;
class TypeSymbolTable;
template<typename ValueTy> class StringMapEntry;
template <typename ValueTy = Value>
class AssertingVH;
@ -43,6 +41,7 @@ class ValueHandleBase;
class LLVMContext;
class Twine;
class MDNode;
class Type;
//===----------------------------------------------------------------------===//
// Value Class
@ -77,12 +76,11 @@ private:
/// This field is initialized to zero by the ctor.
unsigned short SubclassData;
PATypeHolder VTy;
Type *VTy;
Use *UseList;
friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name.
friend class ValueHandleBase;
friend class AbstractTypeUser;
ValueName *Name;
void operator=(const Value &); // Do not implement
@ -107,13 +105,13 @@ public:
/// All values are typed, get the type of this value.
///
inline const Type *getType() const { return VTy; }
Type *getType() const { return VTy; }
/// All values hold a context through their type.
LLVMContext &getContext() const;
// All values can potentially be named...
inline bool hasName() const { return Name != 0; }
bool hasName() const { return Name != 0; }
ValueName *getValueName() const { return Name; }
/// getName() - Return a constant reference to the value's name. This is cheap
@ -279,10 +277,6 @@ public:
return true; // Values are always values.
}
/// getRawType - This should only be used to implement the vmcore library.
///
const Type *getRawType() const { return VTy.getRawType(); }
/// stripPointerCasts - This method strips off any unneeded pointer
/// casts from the specified value, returning the original uncasted value.
/// Note that the returned value has pointer type if the specified value does.
@ -310,6 +304,15 @@ public:
/// load, store, and alloca instructions, and global values.
static const unsigned MaximumAlignment = 1u << 29;
/// mutateType - Mutate the type of this Value to be of the specified type.
/// Note that this is an extremely dangerous operation which can create
/// completely invalid IR very easily. It is strongly recommended that you
/// recreate IR objects with the right types instead of mutating them in
/// place.
void mutateType(Type *Ty) {
VTy = Ty;
}
protected:
unsigned short getSubclassDataFromValue() const { return SubclassData; }
void setValueSubclassData(unsigned short D) { SubclassData = D; }

View File

@ -38,7 +38,7 @@ namespace llvm {
lltok::Kind CurKind;
std::string StrVal;
unsigned UIntVal;
const Type *TyVal;
Type *TyVal;
APFloat APFloatVal;
APSInt APSIntVal;
@ -56,7 +56,7 @@ namespace llvm {
LocTy getLoc() const { return SMLoc::getFromPointer(TokStart); }
lltok::Kind getKind() const { return CurKind; }
const std::string &getStrVal() const { return StrVal; }
const Type *getTyVal() const { return TyVal; }
Type *getTyVal() const { return TyVal; }
unsigned getUIntVal() const { return UIntVal; }
const APSInt &getAPSIntVal() const { return APSIntVal; }
const APFloat &getAPFloatVal() const { return APFloatVal; }

View File

@ -89,15 +89,16 @@ bool LLParser::ValidateEndOfModule() {
ForwardRefBlockAddresses.erase(ForwardRefBlockAddresses.begin());
}
if (!ForwardRefTypes.empty())
return Error(ForwardRefTypes.begin()->second.second,
"use of undefined type named '" +
ForwardRefTypes.begin()->first + "'");
if (!ForwardRefTypeIDs.empty())
return Error(ForwardRefTypeIDs.begin()->second.second,
"use of undefined type '%" +
Twine(ForwardRefTypeIDs.begin()->first) + "'");
for (unsigned i = 0, e = NumberedTypes.size(); i != e; ++i)
if (NumberedTypes[i].second.isValid())
return Error(NumberedTypes[i].second,
"use of undefined type '%" + Twine(i) + "'");
for (StringMap<std::pair<Type*, LocTy> >::iterator I =
NamedTypes.begin(), E = NamedTypes.end(); I != E; ++I)
if (I->second.second.isValid())
return Error(I->second.second,
"use of undefined type named '" + I->getKey() + "'");
if (!ForwardRefVals.empty())
return Error(ForwardRefVals.begin()->second.second,
@ -293,36 +294,32 @@ bool LLParser::ParseDepLibs() {
/// ::= LocalVarID '=' 'type' type
bool LLParser::ParseUnnamedType() {
LocTy TypeLoc = Lex.getLoc();
unsigned TypeID = NumberedTypes.size();
if (Lex.getUIntVal() != TypeID)
return Error(Lex.getLoc(), "type expected to be numbered '%" +
Twine(TypeID) + "'");
unsigned TypeID = Lex.getUIntVal();
Lex.Lex(); // eat LocalVarID;
if (ParseToken(lltok::equal, "expected '=' after name") ||
ParseToken(lltok::kw_type, "expected 'type' after '='"))
return true;
PATypeHolder Ty(Type::getVoidTy(Context));
if (ParseType(Ty)) return true;
// See if this type was previously referenced.
std::map<unsigned, std::pair<PATypeHolder, LocTy> >::iterator
FI = ForwardRefTypeIDs.find(TypeID);
if (FI != ForwardRefTypeIDs.end()) {
if (FI->second.first.get() == Ty)
return Error(TypeLoc, "self referential type is invalid");
cast<DerivedType>(FI->second.first.get())->refineAbstractTypeTo(Ty);
Ty = FI->second.first.get();
ForwardRefTypeIDs.erase(FI);
if (TypeID >= NumberedTypes.size())
NumberedTypes.resize(TypeID+1);
Type *Result = 0;
if (ParseStructDefinition(TypeLoc, "",
NumberedTypes[TypeID], Result)) return true;
if (!isa<StructType>(Result)) {
std::pair<Type*, LocTy> &Entry = NumberedTypes[TypeID];
if (Entry.first)
return Error(TypeLoc, "non-struct types may not be recursive");
Entry.first = Result;
Entry.second = SMLoc();
}
NumberedTypes.push_back(Ty);
return false;
}
/// toplevelentity
/// ::= LocalVar '=' 'type' type
bool LLParser::ParseNamedType() {
@ -330,37 +327,23 @@ bool LLParser::ParseNamedType() {
LocTy NameLoc = Lex.getLoc();
Lex.Lex(); // eat LocalVar.
PATypeHolder Ty(Type::getVoidTy(Context));
if (ParseToken(lltok::equal, "expected '=' after name") ||
ParseToken(lltok::kw_type, "expected 'type' after name") ||
ParseType(Ty))
ParseToken(lltok::kw_type, "expected 'type' after name"))
return true;
// Set the type name, checking for conflicts as we do so.
bool AlreadyExists = M->addTypeName(Name, Ty);
if (!AlreadyExists) return false;
// See if this type is a forward reference. We need to eagerly resolve
// types to allow recursive type redefinitions below.
std::map<std::string, std::pair<PATypeHolder, LocTy> >::iterator
FI = ForwardRefTypes.find(Name);
if (FI != ForwardRefTypes.end()) {
if (FI->second.first.get() == Ty)
return Error(NameLoc, "self referential type is invalid");
cast<DerivedType>(FI->second.first.get())->refineAbstractTypeTo(Ty);
Ty = FI->second.first.get();
ForwardRefTypes.erase(FI);
return false;
Type *Result = 0;
if (ParseStructDefinition(NameLoc, Name,
NamedTypes[Name], Result)) return true;
if (!isa<StructType>(Result)) {
std::pair<Type*, LocTy> &Entry = NamedTypes[Name];
if (Entry.first)
return Error(NameLoc, "non-struct types may not be recursive");
Entry.first = Result;
Entry.second = SMLoc();
}
// Inserting a name that is already defined, get the existing name.
assert(M->getTypeByName(Name) && "Conflict but no matching type?!");
// Otherwise, this is an attempt to redefine a type, report the error.
return Error(NameLoc, "redefinition of type named '" + Name + "' of type '" +
getTypeString(Ty) + "'");
return false;
}
@ -536,7 +519,7 @@ bool LLParser::ParseStandaloneMetadata() {
unsigned MetadataID = 0;
LocTy TyLoc;
PATypeHolder Ty(Type::getVoidTy(Context));
Type *Ty = 0;
SmallVector<Value *, 16> Elts;
if (ParseUInt32(MetadataID) ||
ParseToken(lltok::equal, "expected '=' here") ||
@ -668,7 +651,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
LocTy UnnamedAddrLoc;
LocTy TyLoc;
PATypeHolder Ty(Type::getVoidTy(Context));
Type *Ty = 0;
if (ParseOptionalToken(lltok::kw_thread_local, ThreadLocal) ||
ParseOptionalAddrSpace(AddrSpace) ||
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
@ -792,18 +775,11 @@ GlobalValue *LLParser::GetGlobalVal(const std::string &Name, const Type *Ty,
// Otherwise, create a new forward reference for this value and remember it.
GlobalValue *FwdVal;
if (const FunctionType *FT = dyn_cast<FunctionType>(PTy->getElementType())) {
// Function types can return opaque but functions can't.
if (FT->getReturnType()->isOpaqueTy()) {
Error(Loc, "function may not return opaque type");
return 0;
}
if (const FunctionType *FT = dyn_cast<FunctionType>(PTy->getElementType()))
FwdVal = Function::Create(FT, GlobalValue::ExternalWeakLinkage, Name, M);
} else {
else
FwdVal = new GlobalVariable(*M, PTy->getElementType(), false,
GlobalValue::ExternalWeakLinkage, 0, Name);
}
ForwardRefVals[Name] = std::make_pair(FwdVal, Loc);
return FwdVal;
@ -837,17 +813,11 @@ GlobalValue *LLParser::GetGlobalVal(unsigned ID, const Type *Ty, LocTy Loc) {
// Otherwise, create a new forward reference for this value and remember it.
GlobalValue *FwdVal;
if (const FunctionType *FT = dyn_cast<FunctionType>(PTy->getElementType())) {
// Function types can return opaque but functions can't.
if (FT->getReturnType()->isOpaqueTy()) {
Error(Loc, "function may not return opaque type");
return 0;
}
if (const FunctionType *FT = dyn_cast<FunctionType>(PTy->getElementType()))
FwdVal = Function::Create(FT, GlobalValue::ExternalWeakLinkage, "", M);
} else {
else
FwdVal = new GlobalVariable(*M, PTy->getElementType(), false,
GlobalValue::ExternalWeakLinkage, 0, "");
}
ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc);
return FwdVal;
@ -1228,165 +1198,68 @@ bool LLParser::ParseIndexList(SmallVectorImpl<unsigned> &Indices,
// Type Parsing.
//===----------------------------------------------------------------------===//
/// ParseType - Parse and resolve a full type.
bool LLParser::ParseType(PATypeHolder &Result, bool AllowVoid) {
LocTy TypeLoc = Lex.getLoc();
if (ParseTypeRec(Result)) return true;
// Verify no unresolved uprefs.
if (!UpRefs.empty())
return Error(UpRefs.back().Loc, "invalid unresolved type up reference");
if (!AllowVoid && Result.get()->isVoidTy())
return Error(TypeLoc, "void type only allowed for function results");
return false;
}
/// HandleUpRefs - Every time we finish a new layer of types, this function is
/// called. It loops through the UpRefs vector, which is a list of the
/// currently active types. For each type, if the up-reference is contained in
/// the newly completed type, we decrement the level count. When the level
/// count reaches zero, the up-referenced type is the type that is passed in:
/// thus we can complete the cycle.
///
PATypeHolder LLParser::HandleUpRefs(const Type *ty) {
// If Ty isn't abstract, or if there are no up-references in it, then there is
// nothing to resolve here.
if (!ty->isAbstract() || UpRefs.empty()) return ty;
PATypeHolder Ty(ty);
#if 0
dbgs() << "Type '" << *Ty
<< "' newly formed. Resolving upreferences.\n"
<< UpRefs.size() << " upreferences active!\n";
#endif
// If we find any resolvable upreferences (i.e., those whose NestingLevel goes
// to zero), we resolve them all together before we resolve them to Ty. At
// the end of the loop, if there is anything to resolve to Ty, it will be in
// this variable.
OpaqueType *TypeToResolve = 0;
for (unsigned i = 0; i != UpRefs.size(); ++i) {
// Determine if 'Ty' directly contains this up-references 'LastContainedTy'.
bool ContainsType =
std::find(Ty->subtype_begin(), Ty->subtype_end(),
UpRefs[i].LastContainedTy) != Ty->subtype_end();
#if 0
dbgs() << " UR#" << i << " - TypeContains(" << *Ty << ", "
<< *UpRefs[i].LastContainedTy << ") = "
<< (ContainsType ? "true" : "false")
<< " level=" << UpRefs[i].NestingLevel << "\n";
#endif
if (!ContainsType)
continue;
// Decrement level of upreference
unsigned Level = --UpRefs[i].NestingLevel;
UpRefs[i].LastContainedTy = Ty;
// If the Up-reference has a non-zero level, it shouldn't be resolved yet.
if (Level != 0)
continue;
#if 0
dbgs() << " * Resolving upreference for " << UpRefs[i].UpRefTy << "\n";
#endif
if (!TypeToResolve)
TypeToResolve = UpRefs[i].UpRefTy;
else
UpRefs[i].UpRefTy->refineAbstractTypeTo(TypeToResolve);
UpRefs.erase(UpRefs.begin()+i); // Remove from upreference list.
--i; // Do not skip the next element.
}
if (TypeToResolve)
TypeToResolve->refineAbstractTypeTo(Ty);
return Ty;
}
/// ParseTypeRec - The recursive function used to process the internal
/// implementation details of types.
bool LLParser::ParseTypeRec(PATypeHolder &Result) {
/// ParseType - Parse a type.
bool LLParser::ParseType(Type *&Result, bool AllowVoid) {
SMLoc TypeLoc = Lex.getLoc();
switch (Lex.getKind()) {
default:
return TokError("expected type");
case lltok::Type:
// TypeRec ::= 'float' | 'void' (etc)
// Type ::= 'float' | 'void' (etc)
Result = Lex.getTyVal();
Lex.Lex();
break;
case lltok::kw_opaque:
// TypeRec ::= 'opaque'
Result = OpaqueType::get(Context);
Lex.Lex();
break;
case lltok::lbrace:
// TypeRec ::= '{' ... '}'
if (ParseStructType(Result, false))
// Type ::= StructType
if (ParseAnonStructType(Result, false))
return true;
break;
case lltok::lsquare:
// TypeRec ::= '[' ... ']'
// Type ::= '[' ... ']'
Lex.Lex(); // eat the lsquare.
if (ParseArrayVectorType(Result, false))
return true;
break;
case lltok::less: // Either vector or packed struct.
// TypeRec ::= '<' ... '>'
// Type ::= '<' ... '>'
Lex.Lex();
if (Lex.getKind() == lltok::lbrace) {
if (ParseStructType(Result, true) ||
if (ParseAnonStructType(Result, true) ||
ParseToken(lltok::greater, "expected '>' at end of packed struct"))
return true;
} else if (ParseArrayVectorType(Result, true))
return true;
break;
case lltok::LocalVar:
// TypeRec ::= %foo
if (const Type *T = M->getTypeByName(Lex.getStrVal())) {
Result = T;
} else {
Result = OpaqueType::get(Context);
ForwardRefTypes.insert(std::make_pair(Lex.getStrVal(),
std::make_pair(Result,
Lex.getLoc())));
M->addTypeName(Lex.getStrVal(), Result.get());
case lltok::LocalVar: {
// Type ::= %foo
std::pair<Type*, LocTy> &Entry = NamedTypes[Lex.getStrVal()];
// If the type hasn't been defined yet, create a forward definition and
// remember where that forward def'n was seen (in case it never is defined).
if (Entry.first == 0) {
Entry.first = StructType::createNamed(Context, Lex.getStrVal());
Entry.second = Lex.getLoc();
}
Result = Entry.first;
Lex.Lex();
break;
}
case lltok::LocalVarID:
// TypeRec ::= %4
if (Lex.getUIntVal() < NumberedTypes.size())
Result = NumberedTypes[Lex.getUIntVal()];
else {
std::map<unsigned, std::pair<PATypeHolder, LocTy> >::iterator
I = ForwardRefTypeIDs.find(Lex.getUIntVal());
if (I != ForwardRefTypeIDs.end())
Result = I->second.first;
else {
Result = OpaqueType::get(Context);
ForwardRefTypeIDs.insert(std::make_pair(Lex.getUIntVal(),
std::make_pair(Result,
Lex.getLoc())));
}
case lltok::LocalVarID: {
// Type ::= %4
if (Lex.getUIntVal() >= NumberedTypes.size())
NumberedTypes.resize(Lex.getUIntVal()+1);
std::pair<Type*, LocTy> &Entry = NumberedTypes[Lex.getUIntVal()];
// If the type hasn't been defined yet, create a forward definition and
// remember where that forward def'n was seen (in case it never is defined).
if (Entry.first == 0) {
Entry.first = StructType::createNamed(Context, "");
Entry.second = Lex.getLoc();
}
Result = Entry.first;
Lex.Lex();
break;
case lltok::backslash: {
// TypeRec ::= '\' 4
Lex.Lex();
unsigned Val;
if (ParseUInt32(Val)) return true;
OpaqueType *OT = OpaqueType::get(Context); //Use temporary placeholder.
UpRefs.push_back(UpRefRecord(Lex.getLoc(), Val, OT));
Result = OT;
break;
}
}
@ -1394,34 +1267,37 @@ bool LLParser::ParseTypeRec(PATypeHolder &Result) {
while (1) {
switch (Lex.getKind()) {
// End of type.
default: return false;
default:
if (!AllowVoid && Result->isVoidTy())
return Error(TypeLoc, "void type only allowed for function results");
return false;
// TypeRec ::= TypeRec '*'
// Type ::= Type '*'
case lltok::star:
if (Result.get()->isLabelTy())
if (Result->isLabelTy())
return TokError("basic block pointers are invalid");
if (Result.get()->isVoidTy())
return TokError("pointers to void are invalid; use i8* instead");
if (!PointerType::isValidElementType(Result.get()))
if (Result->isVoidTy())
return TokError("pointers to void are invalid - use i8* instead");
if (!PointerType::isValidElementType(Result))
return TokError("pointer to this type is invalid");
Result = HandleUpRefs(PointerType::getUnqual(Result.get()));
Result = PointerType::getUnqual(Result);
Lex.Lex();
break;
// TypeRec ::= TypeRec 'addrspace' '(' uint32 ')' '*'
// Type ::= Type 'addrspace' '(' uint32 ')' '*'
case lltok::kw_addrspace: {
if (Result.get()->isLabelTy())
if (Result->isLabelTy())
return TokError("basic block pointers are invalid");
if (Result.get()->isVoidTy())
if (Result->isVoidTy())
return TokError("pointers to void are invalid; use i8* instead");
if (!PointerType::isValidElementType(Result.get()))
if (!PointerType::isValidElementType(Result))
return TokError("pointer to this type is invalid");
unsigned AddrSpace;
if (ParseOptionalAddrSpace(AddrSpace) ||
ParseToken(lltok::star, "expected '*' in address space"))
return true;
Result = HandleUpRefs(PointerType::get(Result.get(), AddrSpace));
Result = PointerType::get(Result, AddrSpace);
break;
}
@ -1452,7 +1328,7 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
// Parse the argument.
LocTy ArgLoc;
PATypeHolder ArgTy(Type::getVoidTy(Context));
Type *ArgTy = 0;
unsigned ArgAttrs1 = Attribute::None;
unsigned ArgAttrs2 = Attribute::None;
Value *V;
@ -1472,7 +1348,7 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
/// ParseArgumentList - Parse the argument list for a function type or function
/// prototype. If 'inType' is true then we are parsing a FunctionType.
/// prototype.
/// ::= '(' ArgTypeListI ')'
/// ArgTypeListI
/// ::= /*empty*/
@ -1480,8 +1356,8 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
/// ::= ArgTypeList ',' '...'
/// ::= ArgType (',' ArgType)*
///
bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
bool &isVarArg, bool inType) {
bool LLParser::ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
bool &isVarArg){
isVarArg = false;
assert(Lex.getKind() == lltok::lparen);
Lex.Lex(); // eat the (.
@ -1493,14 +1369,11 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
Lex.Lex();
} else {
LocTy TypeLoc = Lex.getLoc();
PATypeHolder ArgTy(Type::getVoidTy(Context));
Type *ArgTy = 0;
unsigned Attrs;
std::string Name;
// If we're parsing a type, use ParseTypeRec, because we allow recursive
// types (such as a function returning a pointer to itself). If parsing a
// function prototype, we require fully resolved types.
if ((inType ? ParseTypeRec(ArgTy) : ParseType(ArgTy)) ||
if (ParseType(ArgTy) ||
ParseOptionalAttrs(Attrs, 0)) return true;
if (ArgTy->isVoidTy())
@ -1525,8 +1398,7 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
// Otherwise must be an argument type.
TypeLoc = Lex.getLoc();
if ((inType ? ParseTypeRec(ArgTy) : ParseType(ArgTy)) ||
ParseOptionalAttrs(Attrs, 0)) return true;
if (ParseType(ArgTy) || ParseOptionalAttrs(Attrs, 0)) return true;
if (ArgTy->isVoidTy())
return Error(TypeLoc, "argument can not have void type");
@ -1538,7 +1410,7 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
Name = "";
}
if (!ArgTy->isFirstClassType() && !ArgTy->isOpaqueTy())
if (!ArgTy->isFirstClassType())
return Error(TypeLoc, "invalid type for function argument");
ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attrs, Name));
@ -1550,15 +1422,15 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
/// ParseFunctionType
/// ::= Type ArgumentList OptionalAttrs
bool LLParser::ParseFunctionType(PATypeHolder &Result) {
bool LLParser::ParseFunctionType(Type *&Result) {
assert(Lex.getKind() == lltok::lparen);
if (!FunctionType::isValidReturnType(Result))
return TokError("invalid function return type");
std::vector<ArgInfo> ArgList;
SmallVector<ArgInfo, 8> ArgList;
bool isVarArg;
if (ParseArgumentList(ArgList, isVarArg, true))
if (ParseArgumentList(ArgList, isVarArg))
return true;
// Reject names on the arguments lists.
@ -1570,68 +1442,122 @@ bool LLParser::ParseFunctionType(PATypeHolder &Result) {
"argument attributes invalid in function type");
}
std::vector<const Type*> ArgListTy;
SmallVector<const Type*, 16> ArgListTy;
for (unsigned i = 0, e = ArgList.size(); i != e; ++i)
ArgListTy.push_back(ArgList[i].Type);
ArgListTy.push_back(ArgList[i].Ty);
Result = HandleUpRefs(FunctionType::get(Result.get(),
ArgListTy, isVarArg));
Result = FunctionType::get(Result, ArgListTy, isVarArg);
return false;
}
/// ParseAnonStructType - Parse an anonymous struct type, which is inlined into
/// other structs.
bool LLParser::ParseAnonStructType(Type *&Result, bool Packed) {
SmallVector<Type*, 8> Elts;
if (ParseStructBody(Elts)) return true;
Result = StructType::get(Context, Elts, Packed);
return false;
}
/// ParseStructDefinition - Parse a struct in a 'type' definition.
bool LLParser::ParseStructDefinition(SMLoc TypeLoc, StringRef Name,
std::pair<Type*, LocTy> &Entry,
Type *&ResultTy) {
// If the type was already defined, diagnose the redefinition.
if (Entry.first && !Entry.second.isValid())
return Error(TypeLoc, "redefinition of type");
// If we have opaque, just return without filling in the definition for the
// struct. This counts as a definition as far as the .ll file goes.
if (EatIfPresent(lltok::kw_opaque)) {
// This type is being defined, so clear the location to indicate this.
Entry.second = SMLoc();
// If this type number has never been uttered, create it.
if (Entry.first == 0)
Entry.first = StructType::createNamed(Context, Name);
ResultTy = Entry.first;
return false;
}
// If the type starts with '<', then it is either a packed struct or a vector.
bool isPacked = EatIfPresent(lltok::less);
// If we don't have a struct, then we have a random type alias, which we
// accept for compatibility with old files. These types are not allowed to be
// forward referenced and not allowed to be recursive.
if (Lex.getKind() != lltok::lbrace) {
if (Entry.first)
return Error(TypeLoc, "forward references to non-struct type");
ResultTy = 0;
if (isPacked)
return ParseArrayVectorType(ResultTy, true);
return ParseType(ResultTy);
}
// This type is being defined, so clear the location to indicate this.
Entry.second = SMLoc();
// If this type number has never been uttered, create it.
if (Entry.first == 0)
Entry.first = StructType::createNamed(Context, Name);
StructType *STy = cast<StructType>(Entry.first);
SmallVector<Type*, 8> Body;
if (ParseStructBody(Body) ||
(isPacked && ParseToken(lltok::greater, "expected '>' in packed struct")))
return true;
STy->setBody(Body, isPacked);
ResultTy = STy;
return false;
}
/// ParseStructType: Handles packed and unpacked types. </> parsed elsewhere.
/// TypeRec
/// StructType
/// ::= '{' '}'
/// ::= '{' TypeRec (',' TypeRec)* '}'
/// ::= '{' Type (',' Type)* '}'
/// ::= '<' '{' '}' '>'
/// ::= '<' '{' TypeRec (',' TypeRec)* '}' '>'
bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) {
/// ::= '<' '{' Type (',' Type)* '}' '>'
bool LLParser::ParseStructBody(SmallVectorImpl<Type*> &Body) {
assert(Lex.getKind() == lltok::lbrace);
Lex.Lex(); // Consume the '{'
if (EatIfPresent(lltok::rbrace)) {
Result = StructType::get(Context, Packed);
// Handle the empty struct.
if (EatIfPresent(lltok::rbrace))
return false;
}
std::vector<PATypeHolder> ParamsList;
LocTy EltTyLoc = Lex.getLoc();
if (ParseTypeRec(Result)) return true;
ParamsList.push_back(Result);
Type *Ty = 0;
if (ParseType(Ty)) return true;
Body.push_back(Ty);
if (Result->isVoidTy())
return Error(EltTyLoc, "struct element can not have void type");
if (!StructType::isValidElementType(Result))
if (!StructType::isValidElementType(Ty))
return Error(EltTyLoc, "invalid element type for struct");
while (EatIfPresent(lltok::comma)) {
EltTyLoc = Lex.getLoc();
if (ParseTypeRec(Result)) return true;
if (ParseType(Ty)) return true;
if (Result->isVoidTy())
return Error(EltTyLoc, "struct element can not have void type");
if (!StructType::isValidElementType(Result))
if (!StructType::isValidElementType(Ty))
return Error(EltTyLoc, "invalid element type for struct");
ParamsList.push_back(Result);
Body.push_back(Ty);
}
if (ParseToken(lltok::rbrace, "expected '}' at end of struct"))
return true;
std::vector<const Type*> ParamsListTy;
for (unsigned i = 0, e = ParamsList.size(); i != e; ++i)
ParamsListTy.push_back(ParamsList[i].get());
Result = HandleUpRefs(StructType::get(Context, ParamsListTy, Packed));
return false;
return ParseToken(lltok::rbrace, "expected '}' at end of struct");
}
/// ParseArrayVectorType - Parse an array or vector type, assuming the first
/// token has already been consumed.
/// TypeRec
/// Type
/// ::= '[' APSINTVAL 'x' Types ']'
/// ::= '<' APSINTVAL 'x' Types '>'
bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) {
bool LLParser::ParseArrayVectorType(Type *&Result, bool isVector) {
if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned() ||
Lex.getAPSIntVal().getBitWidth() > 64)
return TokError("expected number in address space");
@ -1644,11 +1570,8 @@ bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) {
return true;
LocTy TypeLoc = Lex.getLoc();
PATypeHolder EltTy(Type::getVoidTy(Context));
if (ParseTypeRec(EltTy)) return true;
if (EltTy->isVoidTy())
return Error(TypeLoc, "array and vector element type cannot be void");
Type *EltTy = 0;
if (ParseType(EltTy)) return true;
if (ParseToken(isVector ? lltok::greater : lltok::rsquare,
"expected end of sequential type"))
@ -1665,7 +1588,7 @@ bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) {
} else {
if (!ArrayType::isValidElementType(EltTy))
return Error(TypeLoc, "invalid array element type");
Result = HandleUpRefs(ArrayType::get(EltTy, Size));
Result = ArrayType::get(EltTy, Size);
}
return false;
}
@ -1770,7 +1693,7 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name,
}
// Don't make placeholders with invalid type.
if (!Ty->isFirstClassType() && !Ty->isOpaqueTy() && !Ty->isLabelTy()) {
if (!Ty->isFirstClassType() && !Ty->isLabelTy()) {
P.Error(Loc, "invalid use of a non-first-class type");
return 0;
}
@ -1811,7 +1734,7 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, const Type *Ty,
return 0;
}
if (!Ty->isFirstClassType() && !Ty->isOpaqueTy() && !Ty->isLabelTy()) {
if (!Ty->isFirstClassType() && !Ty->isLabelTy()) {
P.Error(Loc, "invalid use of a non-first-class type");
return 0;
}
@ -1987,9 +1910,10 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
ParseToken(lltok::rbrace, "expected end of struct constant"))
return true;
// FIXME: Get this type from context instead of reconstructing it!
ID.ConstantVal = ConstantStruct::getAnon(Context, Elts);
ID.Kind = ValID::t_Constant;
ID.ConstantStructElts = new Constant*[Elts.size()];
ID.UIntVal = Elts.size();
memcpy(ID.ConstantStructElts, Elts.data(), Elts.size()*sizeof(Elts[0]));
ID.Kind = ValID::t_ConstantStruct;
return false;
}
case lltok::less: {
@ -2007,9 +1931,10 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
return true;
if (isPackedStruct) {
// FIXME: Get this type from context instead of reconstructing it!
ID.ConstantVal = ConstantStruct::getAnon(Context, Elts, true);
ID.Kind = ValID::t_Constant;
ID.ConstantStructElts = new Constant*[Elts.size()];
memcpy(ID.ConstantStructElts, Elts.data(), Elts.size()*sizeof(Elts[0]));
ID.UIntVal = Elts.size();
ID.Kind = ValID::t_PackedConstantStruct;
return false;
}
@ -2131,7 +2056,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
case lltok::kw_inttoptr:
case lltok::kw_ptrtoint: {
unsigned Opc = Lex.getUIntVal();
PATypeHolder DestTy(Type::getVoidTy(Context));
Type *DestTy = 0;
Constant *SrcVal;
Lex.Lex();
if (ParseToken(lltok::lparen, "expected '(' after constantexpr cast") ||
@ -2414,9 +2339,9 @@ bool LLParser::ParseGlobalValue(const Type *Ty, Constant *&C) {
}
bool LLParser::ParseGlobalTypeAndValue(Constant *&V) {
PATypeHolder Type(Type::getVoidTy(Context));
return ParseType(Type) ||
ParseGlobalValue(Type, V);
Type *Ty = 0;
return ParseType(Ty) ||
ParseGlobalValue(Ty, V);
}
/// ParseGlobalValueVector
@ -2562,8 +2487,7 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V,
return false;
case ValID::t_Undef:
// FIXME: LabelTy should not be a first-class type.
if ((!Ty->isFirstClassType() || Ty->isLabelTy()) &&
!Ty->isOpaqueTy())
if (!Ty->isFirstClassType() || Ty->isLabelTy())
return Error(ID.Loc, "invalid type for undef constant");
V = UndefValue::get(Ty);
return false;
@ -2584,20 +2508,40 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V,
V = ID.ConstantVal;
return false;
case ValID::t_ConstantStruct:
case ValID::t_PackedConstantStruct:
if (const StructType *ST = dyn_cast<StructType>(Ty)) {
if (ST->getNumElements() != ID.UIntVal)
return Error(ID.Loc,
"initializer with struct type has wrong # elements");
if (ST->isPacked() != (ID.Kind == ValID::t_PackedConstantStruct))
return Error(ID.Loc, "packed'ness of initializer and type don't match");
// Verify that the elements are compatible with the structtype.
for (unsigned i = 0, e = ID.UIntVal; i != e; ++i)
if (ID.ConstantStructElts[i]->getType() != ST->getElementType(i))
return Error(ID.Loc, "element " + Twine(i) +
" of struct initializer doesn't match struct element type");
V = ConstantStruct::get(ST, ArrayRef<Constant*>(ID.ConstantStructElts,
ID.UIntVal));
} else
return Error(ID.Loc, "constant expression type mismatch");
return false;
}
}
bool LLParser::ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS) {
bool LLParser::ParseValue(const Type *Ty, Value *&V, PerFunctionState *PFS) {
V = 0;
ValID ID;
return ParseValID(ID, &PFS) ||
ConvertValIDToValue(Ty, ID, V, &PFS);
return ParseValID(ID, PFS) ||
ConvertValIDToValue(Ty, ID, V, PFS);
}
bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState &PFS) {
PATypeHolder T(Type::getVoidTy(Context));
return ParseType(T) ||
ParseValue(T, V, PFS);
bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState *PFS) {
Type *Ty = 0;
return ParseType(Ty) ||
ParseValue(Ty, V, PFS);
}
bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc,
@ -2623,7 +2567,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
unsigned Visibility, RetAttrs;
CallingConv::ID CC;
PATypeHolder RetType(Type::getVoidTy(Context));
Type *RetType = 0;
LocTy RetTypeLoc = Lex.getLoc();
if (ParseOptionalLinkage(Linkage) ||
ParseOptionalVisibility(Visibility) ||
@ -2660,8 +2604,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
return Error(LinkageLoc, "invalid function linkage type");
}
if (!FunctionType::isValidReturnType(RetType) ||
RetType->isOpaqueTy())
if (!FunctionType::isValidReturnType(RetType))
return Error(RetTypeLoc, "invalid function return type");
LocTy NameLoc = Lex.getLoc();
@ -2684,7 +2627,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
if (Lex.getKind() != lltok::lparen)
return TokError("expected '(' in function argument list");
std::vector<ArgInfo> ArgList;
SmallVector<ArgInfo, 8> ArgList;
bool isVarArg;
unsigned FuncAttrs;
std::string Section;
@ -2693,7 +2636,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
bool UnnamedAddr;
LocTy UnnamedAddrLoc;
if (ParseArgumentList(ArgList, isVarArg, false) ||
if (ParseArgumentList(ArgList, isVarArg) ||
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
&UnnamedAddrLoc) ||
ParseOptionalAttrs(FuncAttrs, 2) ||
@ -2719,7 +2662,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
Attrs.push_back(AttributeWithIndex::get(0, RetAttrs));
for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {
ParamTypeList.push_back(ArgList[i].Type);
ParamTypeList.push_back(ArgList[i].Ty);
if (ArgList[i].Attrs != Attribute::None)
Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs));
}
@ -3052,11 +2995,18 @@ bool LLParser::ParseCmpPredicate(unsigned &P, unsigned Opc) {
/// ::= 'ret' void (',' !dbg, !1)*
/// ::= 'ret' TypeAndValue (',' !dbg, !1)*
bool LLParser::ParseRet(Instruction *&Inst, BasicBlock *BB,
PerFunctionState &PFS) {
PATypeHolder Ty(Type::getVoidTy(Context));
PerFunctionState &PFS) {
SMLoc TypeLoc = Lex.getLoc();
Type *Ty = 0;
if (ParseType(Ty, true /*void allowed*/)) return true;
Type *ResType = PFS.getFunction().getReturnType();
if (Ty->isVoidTy()) {
if (!ResType->isVoidTy())
return Error(TypeLoc, "value doesn't match function result type '" +
getTypeString(ResType) + "'");
Inst = ReturnInst::Create(Context);
return false;
}
@ -3064,6 +3014,10 @@ bool LLParser::ParseRet(Instruction *&Inst, BasicBlock *BB,
Value *RV;
if (ParseValue(Ty, RV, PFS)) return true;
if (ResType != RV->getType())
return Error(TypeLoc, "value doesn't match function result type '" +
getTypeString(ResType) + "'");
Inst = ReturnInst::Create(Context, RV);
return false;
}
@ -3191,7 +3145,7 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
LocTy CallLoc = Lex.getLoc();
unsigned RetAttrs, FnAttrs;
CallingConv::ID CC;
PATypeHolder RetType(Type::getVoidTy(Context));
Type *RetType = 0;
LocTy RetTypeLoc;
ValID CalleeID;
SmallVector<ParamInfo, 16> ArgList;
@ -3369,8 +3323,9 @@ bool LLParser::ParseCompare(Instruction *&Inst, PerFunctionState &PFS,
/// ::= CastOpc TypeAndValue 'to' Type
bool LLParser::ParseCast(Instruction *&Inst, PerFunctionState &PFS,
unsigned Opc) {
LocTy Loc; Value *Op;
PATypeHolder DestTy(Type::getVoidTy(Context));
LocTy Loc;
Value *Op;
Type *DestTy = 0;
if (ParseTypeAndValue(Op, Loc, PFS) ||
ParseToken(lltok::kw_to, "expected 'to' after cast value") ||
ParseType(DestTy))
@ -3409,7 +3364,7 @@ bool LLParser::ParseSelect(Instruction *&Inst, PerFunctionState &PFS) {
/// ::= 'va_arg' TypeAndValue ',' Type
bool LLParser::ParseVA_Arg(Instruction *&Inst, PerFunctionState &PFS) {
Value *Op;
PATypeHolder EltTy(Type::getVoidTy(Context));
Type *EltTy = 0;
LocTy TypeLoc;
if (ParseTypeAndValue(Op, PFS) ||
ParseToken(lltok::comma, "expected ',' after vaarg operand") ||
@ -3481,11 +3436,10 @@ bool LLParser::ParseShuffleVector(Instruction *&Inst, PerFunctionState &PFS) {
/// ParsePHI
/// ::= 'phi' Type '[' Value ',' Value ']' (',' '[' Value ',' Value ']')*
int LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) {
PATypeHolder Ty(Type::getVoidTy(Context));
Type *Ty = 0; LocTy TypeLoc;
Value *Op0, *Op1;
LocTy TypeLoc = Lex.getLoc();
if (ParseType(Ty) ||
if (ParseType(Ty, TypeLoc) ||
ParseToken(lltok::lsquare, "expected '[' in phi value list") ||
ParseValue(Ty, Op0, PFS) ||
ParseToken(lltok::comma, "expected ',' after insertelement value") ||
@ -3531,7 +3485,7 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
bool isTail) {
unsigned RetAttrs, FnAttrs;
CallingConv::ID CC;
PATypeHolder RetType(Type::getVoidTy(Context));
Type *RetType = 0;
LocTy RetTypeLoc;
ValID CalleeID;
SmallVector<ParamInfo, 16> ArgList;
@ -3620,10 +3574,10 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
/// ParseAlloc
/// ::= 'alloca' Type (',' TypeAndValue)? (',' OptionalInfo)?
int LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS) {
PATypeHolder Ty(Type::getVoidTy(Context));
Value *Size = 0;
LocTy SizeLoc;
unsigned Alignment = 0;
Type *Ty = 0;
if (ParseType(Ty)) return true;
bool AteExtraComma = false;
@ -3787,12 +3741,7 @@ bool LLParser::ParseMDNodeVector(SmallVectorImpl<Value*> &Elts,
}
Value *V = 0;
PATypeHolder Ty(Type::getVoidTy(Context));
ValID ID;
if (ParseType(Ty) || ParseValID(ID, PFS) ||
ConvertValIDToValue(Ty, ID, V, PFS))
return true;
if (ParseTypeAndValue(V, PFS)) return true;
Elts.push_back(V);
} while (EatIfPresent(lltok::comma));

View File

@ -18,6 +18,7 @@
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/ValueHandle.h"
#include <map>
@ -32,6 +33,7 @@ namespace llvm {
class GlobalValue;
class MDString;
class MDNode;
class StructType;
/// ValID - Represents a reference of a definition of some sort with no type.
/// There are several cases where we have to parse the value but where the
@ -47,7 +49,9 @@ namespace llvm {
t_Constant, // Value in ConstantVal.
t_InlineAsm, // Value in StrVal/StrVal2/UIntVal.
t_MDNode, // Value in MDNodeVal.
t_MDString // Value in MDStringVal.
t_MDString, // Value in MDStringVal.
t_ConstantStruct, // Value in ConstantStructElts.
t_PackedConstantStruct // Value in ConstantStructElts.
} Kind;
LLLexer::LocTy Loc;
@ -58,12 +62,19 @@ namespace llvm {
Constant *ConstantVal;
MDNode *MDNodeVal;
MDString *MDStringVal;
ValID() : APFloatVal(0.0) {}
Constant **ConstantStructElts;
ValID() : Kind(t_LocalID), APFloatVal(0.0) {}
~ValID() {
if (Kind == t_ConstantStruct || Kind == t_PackedConstantStruct)
delete [] ConstantStructElts;
}
bool operator<(const ValID &RHS) const {
if (Kind == t_LocalID || Kind == t_GlobalID)
return UIntVal < RHS.UIntVal;
assert((Kind == t_LocalName || Kind == t_GlobalName) &&
assert((Kind == t_LocalName || Kind == t_GlobalName ||
Kind == t_ConstantStruct || Kind == t_PackedConstantStruct) &&
"Ordering not defined for this ValID kind yet");
return StrVal < RHS.StrVal;
}
@ -93,33 +104,13 @@ namespace llvm {
};
DenseMap<Instruction*, std::vector<MDRef> > ForwardRefInstMetadata;
// Type resolution handling data structures.
std::map<std::string, std::pair<PATypeHolder, LocTy> > ForwardRefTypes;
std::map<unsigned, std::pair<PATypeHolder, LocTy> > ForwardRefTypeIDs;
std::vector<PATypeHolder> NumberedTypes;
// Type resolution handling data structures. The location is set when we
// have processed a use of the type but not a definition yet.
StringMap<std::pair<Type*, LocTy> > NamedTypes;
std::vector<std::pair<Type*, LocTy> > NumberedTypes;
std::vector<TrackingVH<MDNode> > NumberedMetadata;
std::map<unsigned, std::pair<TrackingVH<MDNode>, LocTy> > ForwardRefMDNodes;
struct UpRefRecord {
/// Loc - This is the location of the upref.
LocTy Loc;
/// NestingLevel - The number of nesting levels that need to be popped
/// before this type is resolved.
unsigned NestingLevel;
/// LastContainedTy - This is the type at the current binding level for
/// the type. Every time we reduce the nesting level, this gets updated.
const Type *LastContainedTy;
/// UpRefTy - This is the actual opaque type that the upreference is
/// represented with.
OpaqueType *UpRefTy;
UpRefRecord(LocTy L, unsigned NL, OpaqueType *URTy)
: Loc(L), NestingLevel(NL), LastContainedTy((Type*)URTy),
UpRefTy(URTy) {}
};
std::vector<UpRefRecord> UpRefs;
// Global Value reference information.
std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals;
@ -137,7 +128,7 @@ namespace llvm {
M(m) {}
bool Run();
LLVMContext& getContext() { return Context; }
LLVMContext &getContext() { return Context; }
private:
@ -222,16 +213,19 @@ namespace llvm {
bool ParseMDNodeID(MDNode *&Result, unsigned &SlotNo);
// Type Parsing.
bool ParseType(PATypeHolder &Result, bool AllowVoid = false);
bool ParseType(PATypeHolder &Result, LocTy &Loc, bool AllowVoid = false) {
bool ParseType(Type *&Result, bool AllowVoid = false);
bool ParseType(Type *&Result, LocTy &Loc, bool AllowVoid = false) {
Loc = Lex.getLoc();
return ParseType(Result, AllowVoid);
}
bool ParseTypeRec(PATypeHolder &H);
bool ParseStructType(PATypeHolder &H, bool Packed);
bool ParseArrayVectorType(PATypeHolder &H, bool isVector);
bool ParseFunctionType(PATypeHolder &Result);
PATypeHolder HandleUpRefs(const Type *Ty);
bool ParseAnonStructType(Type *&Result, bool Packed);
bool ParseStructBody(SmallVectorImpl<Type*> &Body);
bool ParseStructDefinition(SMLoc TypeLoc, StringRef Name,
std::pair<Type*, LocTy> &Entry,
Type *&ResultTy);
bool ParseArrayVectorType(Type *&Result, bool isVector);
bool ParseFunctionType(Type *&Result);
// Function Semantic Analysis.
class PerFunctionState {
@ -278,14 +272,20 @@ namespace llvm {
bool ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V,
PerFunctionState *PFS);
bool ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS);
bool ParseValue(const Type *Ty, Value *&V, PerFunctionState *PFS);
bool ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS) {
return ParseValue(Ty, V, &PFS);
}
bool ParseValue(const Type *Ty, Value *&V, LocTy &Loc,
PerFunctionState &PFS) {
Loc = Lex.getLoc();
return ParseValue(Ty, V, PFS);
return ParseValue(Ty, V, &PFS);
}
bool ParseTypeAndValue(Value *&V, PerFunctionState &PFS);
bool ParseTypeAndValue(Value *&V, PerFunctionState *PFS);
bool ParseTypeAndValue(Value *&V, PerFunctionState &PFS) {
return ParseTypeAndValue(V, &PFS);
}
bool ParseTypeAndValue(Value *&V, LocTy &Loc, PerFunctionState &PFS) {
Loc = Lex.getLoc();
return ParseTypeAndValue(V, PFS);
@ -321,14 +321,13 @@ namespace llvm {
// Function Parsing.
struct ArgInfo {
LocTy Loc;
PATypeHolder Type;
Type *Ty;
unsigned Attrs;
std::string Name;
ArgInfo(LocTy L, PATypeHolder Ty, unsigned Attr, const std::string &N)
: Loc(L), Type(Ty), Attrs(Attr), Name(N) {}
ArgInfo(LocTy L, Type *ty, unsigned Attr, const std::string &N)
: Loc(L), Ty(ty), Attrs(Attr), Name(N) {}
};
bool ParseArgumentList(std::vector<ArgInfo> &ArgList,
bool &isVarArg, bool inType);
bool ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList, bool &isVarArg);
bool ParseFunctionHeader(Function *&Fn, bool isDefine);
bool ParseFunctionBody(Function &Fn);
bool ParseBasicBlock(PerFunctionState &PFS);

View File

@ -31,7 +31,7 @@ void BitcodeReader::FreeState() {
if (BufferOwned)
delete Buffer;
Buffer = 0;
std::vector<PATypeHolder>().swap(TypeList);
std::vector<Type*>().swap(TypeList);
ValueList.clear();
MDValueList.clear();
@ -352,19 +352,28 @@ Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
return V;
}
const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) {
// If the TypeID is in range, return it.
if (ID < TypeList.size())
return TypeList[ID].get();
if (!isTypeTable) return 0;
Type *BitcodeReader::getTypeByID(unsigned ID) {
// The type table size is always specified correctly.
if (ID >= TypeList.size())
return 0;
if (Type *Ty = TypeList[ID])
return Ty;
// The type table allows forward references. Push as many Opaque types as
// needed to get up to ID.
while (TypeList.size() <= ID)
TypeList.push_back(OpaqueType::get(Context));
return TypeList.back().get();
// If we have a forward reference, the only possible case is when it is to a
// named struct. Just create a placeholder for now.
return TypeList[ID] = StructType::createNamed(Context, "");
}
/// FIXME: Remove in LLVM 3.1, only used by ParseOldTypeTable.
Type *BitcodeReader::getTypeByIDOrNull(unsigned ID) {
if (ID >= TypeList.size())
TypeList.resize(ID+1);
return TypeList[ID];
}
//===----------------------------------------------------------------------===//
// Functions for parsing blocks from the bitcode file
//===----------------------------------------------------------------------===//
@ -471,17 +480,22 @@ bool BitcodeReader::ParseAttributeBlock() {
}
}
bool BitcodeReader::ParseTypeTable() {
if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID))
if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_NEW))
return Error("Malformed block record");
return ParseTypeTableBody();
}
bool BitcodeReader::ParseTypeTableBody() {
if (!TypeList.empty())
return Error("Multiple TYPE_BLOCKs found!");
SmallVector<uint64_t, 64> Record;
unsigned NumRecords = 0;
SmallString<64> TypeName;
// Read all the records for this type table.
while (1) {
unsigned Code = Stream.ReadCode();
@ -508,17 +522,15 @@ bool BitcodeReader::ParseTypeTable() {
// Read a record.
Record.clear();
const Type *ResultTy = 0;
Type *ResultTy = 0;
switch (Stream.ReadRecord(Code, Record)) {
default: // Default behavior: unknown type.
ResultTy = 0;
break;
default: return Error("unknown type in type table");
case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
// TYPE_CODE_NUMENTRY contains a count of the number of types in the
// type list. This allows us to reserve space.
if (Record.size() < 1)
return Error("Invalid TYPE_CODE_NUMENTRY record");
TypeList.reserve(Record[0]);
TypeList.resize(Record[0]);
continue;
case bitc::TYPE_CODE_VOID: // VOID
ResultTy = Type::getVoidTy(Context);
@ -541,9 +553,6 @@ bool BitcodeReader::ParseTypeTable() {
case bitc::TYPE_CODE_LABEL: // LABEL
ResultTy = Type::getLabelTy(Context);
break;
case bitc::TYPE_CODE_OPAQUE: // OPAQUE
ResultTy = 0;
break;
case bitc::TYPE_CODE_METADATA: // METADATA
ResultTy = Type::getMetadataTy(Context);
break;
@ -563,8 +572,9 @@ bool BitcodeReader::ParseTypeTable() {
unsigned AddressSpace = 0;
if (Record.size() == 2)
AddressSpace = Record[1];
ResultTy = PointerType::get(getTypeByID(Record[0], true),
AddressSpace);
ResultTy = getTypeByID(Record[0]);
if (ResultTy == 0) return Error("invalid element type in pointer type");
ResultTy = PointerType::get(ResultTy, AddressSpace);
break;
}
case bitc::TYPE_CODE_FUNCTION: {
@ -573,68 +583,305 @@ bool BitcodeReader::ParseTypeTable() {
if (Record.size() < 3)
return Error("Invalid FUNCTION type record");
std::vector<const Type*> ArgTys;
for (unsigned i = 3, e = Record.size(); i != e; ++i)
ArgTys.push_back(getTypeByID(Record[i], true));
for (unsigned i = 3, e = Record.size(); i != e; ++i) {
if (Type *T = getTypeByID(Record[i]))
ArgTys.push_back(T);
else
break;
}
ResultTy = getTypeByID(Record[2]);
if (ResultTy == 0 || ArgTys.size() < Record.size()-3)
return Error("invalid type in function type");
ResultTy = FunctionType::get(getTypeByID(Record[2], true), ArgTys,
Record[0]);
ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
break;
}
case bitc::TYPE_CODE_STRUCT: { // STRUCT: [ispacked, eltty x N]
case bitc::TYPE_CODE_STRUCT_ANON: { // STRUCT: [ispacked, eltty x N]
if (Record.size() < 1)
return Error("Invalid STRUCT type record");
std::vector<const Type*> EltTys;
for (unsigned i = 1, e = Record.size(); i != e; ++i)
EltTys.push_back(getTypeByID(Record[i], true));
std::vector<Type*> EltTys;
for (unsigned i = 1, e = Record.size(); i != e; ++i) {
if (Type *T = getTypeByID(Record[i]))
EltTys.push_back(T);
else
break;
}
if (EltTys.size() != Record.size()-1)
return Error("invalid type in struct type");
ResultTy = StructType::get(Context, EltTys, Record[0]);
break;
}
case bitc::TYPE_CODE_STRUCT_NAME: // STRUCT_NAME: [strchr x N]
if (ConvertToString(Record, 0, TypeName))
return Error("Invalid STRUCT_NAME record");
continue;
case bitc::TYPE_CODE_STRUCT_NAMED: { // STRUCT: [ispacked, eltty x N]
if (Record.size() < 1)
return Error("Invalid STRUCT type record");
if (NumRecords >= TypeList.size())
return Error("invalid TYPE table");
// Check to see if this was forward referenced, if so fill in the temp.
StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
if (Res) {
Res->setName(TypeName);
TypeList[NumRecords] = 0;
} else // Otherwise, create a new struct.
Res = StructType::createNamed(Context, TypeName);
TypeName.clear();
SmallVector<Type*, 8> EltTys;
for (unsigned i = 1, e = Record.size(); i != e; ++i) {
if (Type *T = getTypeByID(Record[i]))
EltTys.push_back(T);
else
break;
}
if (EltTys.size() != Record.size()-1)
return Error("invalid STRUCT type record");
Res->setBody(EltTys, Record[0]);
ResultTy = Res;
break;
}
case bitc::TYPE_CODE_OPAQUE: { // OPAQUE: []
if (Record.size() != 1)
return Error("Invalid OPAQUE type record");
if (NumRecords >= TypeList.size())
return Error("invalid TYPE table");
// Check to see if this was forward referenced, if so fill in the temp.
StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
if (Res) {
Res->setName(TypeName);
TypeList[NumRecords] = 0;
} else // Otherwise, create a new struct with no body.
Res = StructType::createNamed(Context, TypeName);
TypeName.clear();
ResultTy = Res;
break;
}
case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty]
if (Record.size() < 2)
return Error("Invalid ARRAY type record");
if ((ResultTy = getTypeByID(Record[1])))
ResultTy = ArrayType::get(ResultTy, Record[0]);
else
return Error("Invalid ARRAY type element");
break;
case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty]
if (Record.size() < 2)
return Error("Invalid VECTOR type record");
if ((ResultTy = getTypeByID(Record[1])))
ResultTy = VectorType::get(ResultTy, Record[0]);
else
return Error("Invalid ARRAY type element");
break;
}
if (NumRecords >= TypeList.size())
return Error("invalid TYPE table");
assert(ResultTy && "Didn't read a type?");
assert(TypeList[NumRecords] == 0 && "Already read type?");
TypeList[NumRecords++] = ResultTy;
}
}
// FIXME: Remove in LLVM 3.1
bool BitcodeReader::ParseOldTypeTable() {
if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_OLD))
return Error("Malformed block record");
if (!TypeList.empty())
return Error("Multiple TYPE_BLOCKs found!");
// While horrible, we have no good ordering of types in the bc file. Just
// iteratively parse types out of the bc file in multiple passes until we get
// them all. Do this by saving a cursor for the start of the type block.
BitstreamCursor StartOfTypeBlockCursor(Stream);
unsigned NumTypesRead = 0;
SmallVector<uint64_t, 64> Record;
RestartScan:
unsigned NextTypeID = 0;
bool ReadAnyTypes = false;
// Read all the records for this type table.
while (1) {
unsigned Code = Stream.ReadCode();
if (Code == bitc::END_BLOCK) {
if (NextTypeID != TypeList.size())
return Error("Invalid type forward reference in TYPE_BLOCK_ID_OLD");
// If we haven't read all of the types yet, iterate again.
if (NumTypesRead != TypeList.size()) {
// If we didn't successfully read any types in this pass, then we must
// have an unhandled forward reference.
if (!ReadAnyTypes)
return Error("Obsolete bitcode contains unhandled recursive type");
Stream = StartOfTypeBlockCursor;
goto RestartScan;
}
if (Stream.ReadBlockEnd())
return Error("Error at end of type table block");
return false;
}
if (Code == bitc::ENTER_SUBBLOCK) {
// No known subblocks, always skip them.
Stream.ReadSubBlockID();
if (Stream.SkipBlock())
return Error("Malformed block record");
continue;
}
if (Code == bitc::DEFINE_ABBREV) {
Stream.ReadAbbrevRecord();
continue;
}
// Read a record.
Record.clear();
Type *ResultTy = 0;
switch (Stream.ReadRecord(Code, Record)) {
default: return Error("unknown type in type table");
case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
// TYPE_CODE_NUMENTRY contains a count of the number of types in the
// type list. This allows us to reserve space.
if (Record.size() < 1)
return Error("Invalid TYPE_CODE_NUMENTRY record");
TypeList.resize(Record[0]);
continue;
case bitc::TYPE_CODE_VOID: // VOID
ResultTy = Type::getVoidTy(Context);
break;
case bitc::TYPE_CODE_FLOAT: // FLOAT
ResultTy = Type::getFloatTy(Context);
break;
case bitc::TYPE_CODE_DOUBLE: // DOUBLE
ResultTy = Type::getDoubleTy(Context);
break;
case bitc::TYPE_CODE_X86_FP80: // X86_FP80
ResultTy = Type::getX86_FP80Ty(Context);
break;
case bitc::TYPE_CODE_FP128: // FP128
ResultTy = Type::getFP128Ty(Context);
break;
case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128
ResultTy = Type::getPPC_FP128Ty(Context);
break;
case bitc::TYPE_CODE_LABEL: // LABEL
ResultTy = Type::getLabelTy(Context);
break;
case bitc::TYPE_CODE_METADATA: // METADATA
ResultTy = Type::getMetadataTy(Context);
break;
case bitc::TYPE_CODE_X86_MMX: // X86_MMX
ResultTy = Type::getX86_MMXTy(Context);
break;
case bitc::TYPE_CODE_INTEGER: // INTEGER: [width]
if (Record.size() < 1)
return Error("Invalid Integer type record");
ResultTy = IntegerType::get(Context, Record[0]);
break;
case bitc::TYPE_CODE_OPAQUE: // OPAQUE
if (NextTypeID < TypeList.size() && TypeList[NextTypeID] == 0)
ResultTy = StructType::createNamed(Context, "");
break;
case bitc::TYPE_CODE_STRUCT_OLD: {// STRUCT_OLD
if (NextTypeID >= TypeList.size()) break;
// If we already read it, don't reprocess.
if (TypeList[NextTypeID] &&
!cast<StructType>(TypeList[NextTypeID])->isOpaque())
break;
// Set a type.
if (TypeList[NextTypeID] == 0)
TypeList[NextTypeID] = StructType::createNamed(Context, "");
std::vector<Type*> EltTys;
for (unsigned i = 1, e = Record.size(); i != e; ++i) {
if (Type *Elt = getTypeByIDOrNull(Record[i]))
EltTys.push_back(Elt);
else
break;
}
if (EltTys.size() != Record.size()-1)
break; // Not all elements are ready.
cast<StructType>(TypeList[NextTypeID])->setBody(EltTys, Record[0]);
ResultTy = TypeList[NextTypeID];
TypeList[NextTypeID] = 0;
break;
}
case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
// [pointee type, address space]
if (Record.size() < 1)
return Error("Invalid POINTER type record");
unsigned AddressSpace = 0;
if (Record.size() == 2)
AddressSpace = Record[1];
if ((ResultTy = getTypeByIDOrNull(Record[0])))
ResultTy = PointerType::get(ResultTy, AddressSpace);
break;
}
case bitc::TYPE_CODE_FUNCTION: {
// FIXME: attrid is dead, remove it in LLVM 3.0
// FUNCTION: [vararg, attrid, retty, paramty x N]
if (Record.size() < 3)
return Error("Invalid FUNCTION type record");
std::vector<const Type*> ArgTys;
for (unsigned i = 3, e = Record.size(); i != e; ++i) {
if (Type *Elt = getTypeByIDOrNull(Record[i]))
ArgTys.push_back(Elt);
else
break;
}
if (ArgTys.size()+3 != Record.size())
break; // Something was null.
if ((ResultTy = getTypeByIDOrNull(Record[2])))
ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
break;
}
case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty]
if (Record.size() < 2)
return Error("Invalid ARRAY type record");
ResultTy = ArrayType::get(getTypeByID(Record[1], true), Record[0]);
if ((ResultTy = getTypeByIDOrNull(Record[1])))
ResultTy = ArrayType::get(ResultTy, Record[0]);
break;
case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty]
if (Record.size() < 2)
return Error("Invalid VECTOR type record");
ResultTy = VectorType::get(getTypeByID(Record[1], true), Record[0]);
if ((ResultTy = getTypeByIDOrNull(Record[1])))
ResultTy = VectorType::get(ResultTy, Record[0]);
break;
}
if (NumRecords == TypeList.size()) {
// If this is a new type slot, just append it.
TypeList.push_back(ResultTy ? ResultTy : OpaqueType::get(Context));
++NumRecords;
} else if (ResultTy == 0) {
// Otherwise, this was forward referenced, so an opaque type was created,
// but the result type is actually just an opaque. Leave the one we
// created previously.
++NumRecords;
} else {
// Otherwise, this was forward referenced, so an opaque type was created.
// Resolve the opaque type to the real type now.
assert(NumRecords < TypeList.size() && "Typelist imbalance");
const OpaqueType *OldTy = cast<OpaqueType>(TypeList[NumRecords++].get());
// Don't directly push the new type on the Tab. Instead we want to replace
// the opaque type we previously inserted with the new concrete value. The
// refinement from the abstract (opaque) type to the new type causes all
// uses of the abstract type to use the concrete type (NewTy). This will
// also cause the opaque type to be deleted.
const_cast<OpaqueType*>(OldTy)->refineAbstractTypeTo(ResultTy);
// This should have replaced the old opaque type with the new type in the
// value table... or with a preexisting type that was already in the
// system. Let's just make sure it did.
assert(TypeList[NumRecords-1].get() != OldTy &&
"refineAbstractType didn't work!");
if (NextTypeID >= TypeList.size())
return Error("invalid TYPE table");
if (ResultTy && TypeList[NextTypeID] == 0) {
++NumTypesRead;
ReadAnyTypes = true;
TypeList[NextTypeID] = ResultTy;
}
++NextTypeID;
}
}
bool BitcodeReader::ParseTypeSymbolTable() {
if (Stream.EnterSubBlock(bitc::TYPE_SYMTAB_BLOCK_ID))
bool BitcodeReader::ParseOldTypeSymbolTable() {
if (Stream.EnterSubBlock(bitc::TYPE_SYMTAB_BLOCK_ID_OLD))
return Error("Malformed block record");
SmallVector<uint64_t, 64> Record;
@ -674,7 +921,10 @@ bool BitcodeReader::ParseTypeSymbolTable() {
if (TypeID >= TypeList.size())
return Error("Invalid Type ID in TST_ENTRY record");
TheModule->addTypeName(TypeName, TypeList[TypeID].get());
// Only apply the type name to a struct type with no name.
if (StructType *STy = dyn_cast<StructType>(TypeList[TypeID]))
if (!STy->isAnonymous() && !STy->hasName())
STy->setName(TypeName);
TypeName.clear();
break;
}
@ -1310,12 +1560,16 @@ bool BitcodeReader::ParseModule() {
if (ParseAttributeBlock())
return true;
break;
case bitc::TYPE_BLOCK_ID:
case bitc::TYPE_BLOCK_ID_NEW:
if (ParseTypeTable())
return true;
break;
case bitc::TYPE_SYMTAB_BLOCK_ID:
if (ParseTypeSymbolTable())
case bitc::TYPE_BLOCK_ID_OLD:
if (ParseOldTypeTable())
return true;
break;
case bitc::TYPE_SYMTAB_BLOCK_ID_OLD:
if (ParseOldTypeSymbolTable())
return true;
break;
case bitc::VALUE_SYMTAB_BLOCK_ID:
@ -2307,7 +2561,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
SmallVector<Value*, 16> Args;
// Read the fixed params.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
if (FTy->getParamType(i)->getTypeID()==Type::LabelTyID)
if (FTy->getParamType(i)->isLabelTy())
Args.push_back(getBasicBlock(Record[OpNum]));
else
Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));

View File

@ -131,7 +131,7 @@ class BitcodeReader : public GVMaterializer {
const char *ErrorString;
std::vector<PATypeHolder> TypeList;
std::vector<Type*> TypeList;
BitcodeReaderValueList ValueList;
BitcodeReaderMDValueList MDValueList;
SmallVector<Instruction *, 64> InstructionList;
@ -210,7 +210,8 @@ public:
/// @returns true if an error occurred.
bool ParseTriple(std::string &Triple);
private:
const Type *getTypeByID(unsigned ID, bool isTypeTable = false);
Type *getTypeByID(unsigned ID);
Type *getTypeByIDOrNull(unsigned ID);
Value *getFnValueByID(unsigned ID, const Type *Ty) {
if (Ty && Ty->isMetadataTy())
return MDValueList.getValueFwdRef(ID);
@ -258,7 +259,10 @@ private:
bool ParseModule();
bool ParseAttributeBlock();
bool ParseTypeTable();
bool ParseTypeSymbolTable();
bool ParseOldTypeTable(); // FIXME: Remove in LLVM 3.1
bool ParseTypeTableBody();
bool ParseOldTypeSymbolTable(); // FIXME: Remove in LLVM 3.1
bool ParseValueSymbolTable();
bool ParseConstants();
bool RememberAndSkipFunctionBody();

View File

@ -21,7 +21,6 @@
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Operator.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ErrorHandling.h"
@ -29,6 +28,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Program.h"
#include <cctype>
#include <map>
using namespace llvm;
/// These are manifest constants used by the bitcode writer. They do not need to
@ -101,13 +101,16 @@ static unsigned GetEncodedBinaryOpcode(unsigned Opcode) {
}
}
static void WriteStringRecord(unsigned Code, const std::string &Str,
static void WriteStringRecord(unsigned Code, StringRef Str,
unsigned AbbrevToUse, BitstreamWriter &Stream) {
SmallVector<unsigned, 64> Vals;
// Code: [strchar x N]
for (unsigned i = 0, e = Str.size(); i != e; ++i)
for (unsigned i = 0, e = Str.size(); i != e; ++i) {
if (AbbrevToUse && !BitCodeAbbrevOp::isChar6(Str[i]))
AbbrevToUse = 0;
Vals.push_back(Str[i]);
}
// Emit the finished record.
Stream.EmitRecord(Code, Vals, AbbrevToUse);
@ -151,7 +154,7 @@ static void WriteAttributeTable(const ValueEnumerator &VE,
static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
const ValueEnumerator::TypeList &TypeList = VE.getTypes();
Stream.EnterSubblock(bitc::TYPE_BLOCK_ID, 4 /*count from # abbrevs */);
Stream.EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */);
SmallVector<uint64_t, 64> TypeVals;
// Abbrev for TYPE_CODE_POINTER.
@ -172,15 +175,32 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
Log2_32_Ceil(VE.getTypes().size()+1)));
unsigned FunctionAbbrev = Stream.EmitAbbrev(Abbv);
// Abbrev for TYPE_CODE_STRUCT.
// Abbrev for TYPE_CODE_STRUCT_ANON.
Abbv = new BitCodeAbbrev();
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT));
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_ANON));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(VE.getTypes().size()+1)));
unsigned StructAbbrev = Stream.EmitAbbrev(Abbv);
unsigned StructAnonAbbrev = Stream.EmitAbbrev(Abbv);
// Abbrev for TYPE_CODE_STRUCT_NAME.
Abbv = new BitCodeAbbrev();
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_NAME));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
unsigned StructNameAbbrev = Stream.EmitAbbrev(Abbv);
// Abbrev for TYPE_CODE_STRUCT_NAMED.
Abbv = new BitCodeAbbrev();
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_NAMED));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(VE.getTypes().size()+1)));
unsigned StructNamedAbbrev = Stream.EmitAbbrev(Abbv);
// Abbrev for TYPE_CODE_ARRAY.
Abbv = new BitCodeAbbrev();
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY));
@ -202,16 +222,15 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
switch (T->getTypeID()) {
default: llvm_unreachable("Unknown type!");
case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break;
case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break;
case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break;
case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break;
case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break;
case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break;
case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break;
case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break;
case Type::PPC_FP128TyID: Code = bitc::TYPE_CODE_PPC_FP128; break;
case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break;
case Type::OpaqueTyID: Code = bitc::TYPE_CODE_OPAQUE; break;
case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break;
case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break;
case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break;
case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break;
case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break;
case Type::IntegerTyID:
// INTEGER: [width]
Code = bitc::TYPE_CODE_INTEGER;
@ -242,13 +261,28 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
case Type::StructTyID: {
const StructType *ST = cast<StructType>(T);
// STRUCT: [ispacked, eltty x N]
Code = bitc::TYPE_CODE_STRUCT;
TypeVals.push_back(ST->isPacked());
// Output all of the element types.
for (StructType::element_iterator I = ST->element_begin(),
E = ST->element_end(); I != E; ++I)
TypeVals.push_back(VE.getTypeID(*I));
AbbrevToUse = StructAbbrev;
if (ST->isAnonymous()) {
Code = bitc::TYPE_CODE_STRUCT_ANON;
AbbrevToUse = StructAnonAbbrev;
} else {
if (ST->isOpaque()) {
Code = bitc::TYPE_CODE_OPAQUE;
} else {
Code = bitc::TYPE_CODE_STRUCT_NAMED;
AbbrevToUse = StructNamedAbbrev;
}
// Emit the name if it is present.
if (!ST->getName().empty())
WriteStringRecord(bitc::TYPE_CODE_STRUCT_NAME, ST->getName(),
StructNameAbbrev, Stream);
}
break;
}
case Type::ArrayTyID: {
@ -1278,46 +1312,6 @@ static void WriteFunction(const Function &F, ValueEnumerator &VE,
Stream.ExitBlock();
}
/// WriteTypeSymbolTable - Emit a block for the specified type symtab.
static void WriteTypeSymbolTable(const TypeSymbolTable &TST,
const ValueEnumerator &VE,
BitstreamWriter &Stream) {
if (TST.empty()) return;
Stream.EnterSubblock(bitc::TYPE_SYMTAB_BLOCK_ID, 3);
// 7-bit fixed width VST_CODE_ENTRY strings.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(VE.getTypes().size()+1)));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
unsigned V7Abbrev = Stream.EmitAbbrev(Abbv);
SmallVector<unsigned, 64> NameVals;
for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
TI != TE; ++TI) {
// TST_ENTRY: [typeid, namechar x N]
NameVals.push_back(VE.getTypeID(TI->second));
const std::string &Str = TI->first;
bool is7Bit = true;
for (unsigned i = 0, e = Str.size(); i != e; ++i) {
NameVals.push_back((unsigned char)Str[i]);
if (Str[i] & 128)
is7Bit = false;
}
// Emit the finished record.
Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, is7Bit ? V7Abbrev : 0);
NameVals.clear();
}
Stream.ExitBlock();
}
// Emit blockinfo, which defines the standard abbreviations etc.
static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) {
// We only want to emit block info records for blocks that have multiple
@ -1521,9 +1515,6 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) {
// Emit metadata.
WriteModuleMetadataStore(M, Stream);
// Emit the type symbol table information.
WriteTypeSymbolTable(M->getTypeSymbolTable(), VE, Stream);
// Emit names for globals/functions etc.
WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream);

View File

@ -17,7 +17,6 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/Instructions.h"
#include <algorithm>
@ -59,9 +58,6 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
I != E; ++I)
EnumerateValue(I->getAliasee());
// Enumerate types used by the type symbol table.
EnumerateTypeSymbolTable(M->getTypeSymbolTable());
// Insert constants and metadata that are named at module level into the slot
// pool so that the module symbol table can refer to them...
EnumerateValueSymbolTable(M->getValueSymbolTable());
@ -109,78 +105,12 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
// Optimize constant ordering.
OptimizeConstants(FirstConstant, Values.size());
OptimizeTypes();
// Now that we rearranged the type table, rebuild TypeMap.
for (unsigned i = 0, e = Types.size(); i != e; ++i)
TypeMap[Types[i]] = i+1;
}
struct TypeAndDeps {
const Type *Ty;
unsigned NumDeps;
};
static int CompareByDeps(const void *a, const void *b) {
const TypeAndDeps &ta = *(const TypeAndDeps*) a;
const TypeAndDeps &tb = *(const TypeAndDeps*) b;
return ta.NumDeps - tb.NumDeps;
}
static void VisitType(const Type *Ty, SmallPtrSet<const Type*, 16> &Visited,
std::vector<const Type*> &Out) {
if (Visited.count(Ty))
return;
Visited.insert(Ty);
for (Type::subtype_iterator I2 = Ty->subtype_begin(),
E2 = Ty->subtype_end(); I2 != E2; ++I2) {
const Type *InnerType = I2->get();
VisitType(InnerType, Visited, Out);
}
Out.push_back(Ty);
}
void ValueEnumerator::OptimizeTypes(void) {
// If the types form a DAG, this will compute a topological sort and
// no forward references will be needed when reading them in.
// If there are cycles, this is a simple but reasonable heuristic for
// the minimum feedback arc set problem.
const unsigned NumTypes = Types.size();
std::vector<TypeAndDeps> TypeDeps;
TypeDeps.resize(NumTypes);
for (unsigned I = 0; I < NumTypes; ++I) {
const Type *Ty = Types[I];
TypeDeps[I].Ty = Ty;
TypeDeps[I].NumDeps = 0;
}
for (unsigned I = 0; I < NumTypes; ++I) {
const Type *Ty = TypeDeps[I].Ty;
for (Type::subtype_iterator I2 = Ty->subtype_begin(),
E2 = Ty->subtype_end(); I2 != E2; ++I2) {
const Type *InnerType = I2->get();
unsigned InnerIndex = TypeMap.lookup(InnerType) - 1;
TypeDeps[InnerIndex].NumDeps++;
}
}
array_pod_sort(TypeDeps.begin(), TypeDeps.end(), CompareByDeps);
SmallPtrSet<const Type*, 16> Visited;
Types.clear();
Types.reserve(NumTypes);
for (unsigned I = 0; I < NumTypes; ++I) {
VisitType(TypeDeps[I].Ty, Visited, Types);
}
}
unsigned ValueEnumerator::getInstructionID(const Instruction *Inst) const {
InstructionMapType::const_iterator I = InstructionMap.find(Inst);
assert (I != InstructionMap.end() && "Instruction is not mapped!");
assert(I != InstructionMap.end() && "Instruction is not mapped!");
return I->second;
}
@ -235,14 +165,6 @@ void ValueEnumerator::OptimizeConstants(unsigned CstStart, unsigned CstEnd) {
}
/// EnumerateTypeSymbolTable - Insert all of the types in the specified symbol
/// table.
void ValueEnumerator::EnumerateTypeSymbolTable(const TypeSymbolTable &TST) {
for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
TI != TE; ++TI)
EnumerateType(TI->second);
}
/// EnumerateValueSymbolTable - Insert all of the values in the specified symbol
/// table into the values table.
void ValueEnumerator::EnumerateValueSymbolTable(const ValueSymbolTable &VST) {
@ -394,20 +316,40 @@ void ValueEnumerator::EnumerateValue(const Value *V) {
void ValueEnumerator::EnumerateType(const Type *Ty) {
unsigned &TypeID = TypeMap[Ty];
unsigned *TypeID = &TypeMap[Ty];
// We've already seen this type.
if (TypeID)
if (*TypeID)
return;
// First time we saw this type, add it.
Types.push_back(Ty);
TypeID = Types.size();
// Enumerate subtypes.
// If it is a non-anonymous struct, mark the type as being visited so that we
// don't recursively visit it. This is safe because we allow forward
// references of these in the bitcode reader.
if (const StructType *STy = dyn_cast<StructType>(Ty))
if (!STy->isAnonymous())
*TypeID = ~0U;
// Enumerate all of the subtypes before we enumerate this type. This ensures
// that the type will be enumerated in an order that can be directly built.
for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
I != E; ++I)
EnumerateType(*I);
// Refresh the TypeID pointer in case the table rehashed.
TypeID = &TypeMap[Ty];
// Check to see if we got the pointer another way. This can happen when
// enumerating recursive types that hit the base case deeper than they start.
//
// If this is actually a struct that we are treating as forward ref'able,
// then emit the definition now that all of its contents are available.
if (*TypeID && *TypeID != ~0U)
return;
// Add this type now that its contents are all happily enumerated.
Types.push_back(Ty);
*TypeID = Types.size();
}
// Enumerate the types for the specified value. If the value is a constant,

View File

@ -30,7 +30,6 @@ class Module;
class MDNode;
class NamedMDNode;
class AttrListPtr;
class TypeSymbolTable;
class ValueSymbolTable;
class MDSymbolTable;
@ -135,7 +134,6 @@ public:
private:
void OptimizeConstants(unsigned CstStart, unsigned CstEnd);
void OptimizeTypes();
void EnumerateMDNodeOperands(const MDNode *N);
void EnumerateMetadata(const Value *MD);
@ -146,7 +144,6 @@ private:
void EnumerateOperandType(const Value *V);
void EnumerateAttributes(const AttrListPtr &PAL);
void EnumerateTypeSymbolTable(const TypeSymbolTable &ST);
void EnumerateValueSymbolTable(const ValueSymbolTable &ST);
void EnumerateNamedMetadata(const Module *M);
};

View File

@ -45,7 +45,8 @@ namespace {
/// StackEntryTy - Abstract type of a link in the shadow stack.
///
const StructType *StackEntryTy;
StructType *StackEntryTy;
StructType *FrameMapTy;
/// Roots - GC roots in the current function. Each is a pair of the
/// intrinsic call and its corresponding alloca.
@ -211,18 +212,14 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) {
};
Constant *DescriptorElts[] = {
ConstantStruct::get(StructType::get(Int32Ty, Int32Ty, NULL), BaseElts),
ConstantStruct::get(FrameMapTy, BaseElts),
ConstantArray::get(ArrayType::get(VoidPtr, NumMeta), Metadata)
};
Constant *FrameMap =
ConstantStruct::get(StructType::get(DescriptorElts[0]->getType(),
DescriptorElts[1]->getType(), NULL),
DescriptorElts);
std::string TypeName("gc_map.");
TypeName += utostr(NumMeta);
F.getParent()->addTypeName(TypeName, FrameMap->getType());
Type *EltTys[] = { DescriptorElts[0]->getType(),DescriptorElts[1]->getType()};
StructType *STy = StructType::createNamed("gc_map."+utostr(NumMeta), EltTys);
Constant *FrameMap = ConstantStruct::get(STy, DescriptorElts);
// FIXME: Is this actually dangerous as WritingAnLLVMPass.html claims? Seems
// that, short of multithreaded LLVM, it should be safe; all that is
@ -250,17 +247,12 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) {
const Type* ShadowStackGC::GetConcreteStackEntryType(Function &F) {
// doInitialization creates the generic version of this type.
std::vector<const Type*> EltTys;
std::vector<Type*> EltTys;
EltTys.push_back(StackEntryTy);
for (size_t I = 0; I != Roots.size(); I++)
EltTys.push_back(Roots[I].second->getAllocatedType());
Type *Ty = StructType::get(F.getContext(), EltTys);
std::string TypeName("gc_stackentry.");
TypeName += F.getName();
F.getParent()->addTypeName(TypeName, Ty);
return Ty;
return StructType::createNamed("gc_stackentry."+F.getName().str(), EltTys);
}
/// doInitialization - If this module uses the GC intrinsics, find them now. If
@ -271,13 +263,12 @@ bool ShadowStackGC::initializeCustomLowering(Module &M) {
// int32_t NumMeta; // Number of metadata descriptors. May be < NumRoots.
// void *Meta[]; // May be absent for roots without metadata.
// };
std::vector<const Type*> EltTys;
std::vector<Type*> EltTys;
// 32 bits is ok up to a 32GB stack frame. :)
EltTys.push_back(Type::getInt32Ty(M.getContext()));
// Specifies length of variable length array.
EltTys.push_back(Type::getInt32Ty(M.getContext()));
StructType *FrameMapTy = StructType::get(M.getContext(), EltTys);
M.addTypeName("gc_map", FrameMapTy);
FrameMapTy = StructType::createNamed("gc_map", EltTys);
PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy);
// struct StackEntry {
@ -285,18 +276,14 @@ bool ShadowStackGC::initializeCustomLowering(Module &M) {
// FrameMap *Map; // Pointer to constant FrameMap.
// void *Roots[]; // Stack roots (in-place array, so we pretend).
// };
OpaqueType *RecursiveTy = OpaqueType::get(M.getContext());
StackEntryTy = StructType::createNamed(M.getContext(), "gc_stackentry");
EltTys.clear();
EltTys.push_back(PointerType::getUnqual(RecursiveTy));
EltTys.push_back(PointerType::getUnqual(StackEntryTy));
EltTys.push_back(FrameMapPtrTy);
PATypeHolder LinkTyH = StructType::get(M.getContext(), EltTys);
RecursiveTy->refineAbstractTypeTo(LinkTyH.get());
StackEntryTy = cast<StructType>(LinkTyH.get());
StackEntryTy->setBody(EltTys);
const PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy);
M.addTypeName("gc_stackentry", LinkTyH.get()); // FIXME: Is this safe from
// a FunctionPass?
// Get the root chain if it already exists.
Head = M.getGlobalVariable("llvm_gc_root_chain");
@ -403,7 +390,7 @@ bool ShadowStackGC::performCustomLowering(Function &F) {
Instruction *CurrentHead = AtEntry.CreateLoad(Head, "gc_currhead");
Instruction *EntryMapPtr = CreateGEP(Context, AtEntry, StackEntry,
0,1,"gc_frame.map");
AtEntry.CreateStore(FrameMap, EntryMapPtr);
AtEntry.CreateStore(FrameMap, EntryMapPtr);
// After all the allocas...
for (unsigned I = 0, E = Roots.size(); I != E; ++I) {

View File

@ -78,7 +78,6 @@ static char getTypeID(const Type *Ty) {
case Type::FunctionTyID:return 'M';
case Type::StructTyID: return 'T';
case Type::ArrayTyID: return 'A';
case Type::OpaqueTyID: return 'O';
default: return 'U';
}
}

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,6 @@
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Intrinsics.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/InlineAsm.h"
@ -74,29 +73,6 @@ namespace {
PrivateGlobalPrefix = "";
}
};
/// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for
/// any unnamed structure types that are used by the program, and merges
/// external functions with the same name.
///
class CBackendNameAllUsedStructsAndMergeFunctions : public ModulePass {
public:
static char ID;
CBackendNameAllUsedStructsAndMergeFunctions()
: ModulePass(ID) {
initializeFindUsedTypesPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<FindUsedTypes>();
}
virtual const char *getPassName() const {
return "C backend type canonicalizer";
}
virtual bool runOnModule(Module &M);
};
char CBackendNameAllUsedStructsAndMergeFunctions::ID = 0;
/// CWriter - This class is the main chunk of code that converts an LLVM
/// module to a C translation unit.
@ -109,7 +85,7 @@ namespace {
const MCAsmInfo* TAsm;
MCContext *TCtx;
const TargetData* TD;
std::map<const Type *, std::string> TypeNames;
std::map<const ConstantFP *, unsigned> FPConstantMap;
std::set<Function*> intrinsicPrototypesAlreadyGenerated;
std::set<const Argument*> ByValParams;
@ -118,6 +94,10 @@ namespace {
DenseMap<const Value*, unsigned> AnonValueNumbers;
unsigned NextAnonValueNumber;
/// UnnamedStructIDs - This contains a unique ID for each struct that is
/// either anonymous or has no name.
DenseMap<const StructType*, unsigned> UnnamedStructIDs;
public:
static char ID;
explicit CWriter(formatted_raw_ostream &o)
@ -163,9 +143,9 @@ namespace {
delete TCtx;
delete TAsm;
FPConstantMap.clear();
TypeNames.clear();
ByValParams.clear();
intrinsicPrototypesAlreadyGenerated.clear();
UnnamedStructIDs.clear();
return false;
}
@ -182,6 +162,8 @@ namespace {
const AttrListPtr &PAL,
const PointerType *Ty);
std::string getStructName(const StructType *ST);
/// writeOperandDeref - Print the result of dereferencing the specified
/// operand with '*'. This is equivalent to printing '*' then using
/// writeOperand, but avoids excess syntax in some cases.
@ -214,8 +196,8 @@ namespace {
/// intrinsics which need to be explicitly defined in the CBackend.
void printIntrinsicDefinition(const Function &F, raw_ostream &Out);
void printModuleTypes(const TypeSymbolTable &ST);
void printContainedStructs(const Type *Ty, std::set<const Type *> &);
void printModuleTypes();
void printContainedStructs(const Type *Ty, SmallPtrSet<const Type *, 16> &);
void printFloatingPointConstants(Function &F);
void printFloatingPointConstants(const Constant *C);
void printFunctionSignature(const Function *F, bool Prototype);
@ -359,6 +341,7 @@ namespace {
char CWriter::ID = 0;
static std::string CBEMangle(const std::string &S) {
std::string Result;
@ -374,90 +357,14 @@ static std::string CBEMangle(const std::string &S) {
return Result;
}
/// This method inserts names for any unnamed structure types that are used by
/// the program, and removes names from structure types that are not used by the
/// program.
///
bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) {
// Get a set of types that are used by the program...
SetVector<const Type *> UT = getAnalysis<FindUsedTypes>().getTypes();
// Loop over the module symbol table, removing types from UT that are
// already named, and removing names for types that are not used.
//
TypeSymbolTable &TST = M.getTypeSymbolTable();
for (TypeSymbolTable::iterator TI = TST.begin(), TE = TST.end();
TI != TE; ) {
TypeSymbolTable::iterator I = TI++;
// If this isn't a struct or array type, remove it from our set of types
// to name. This simplifies emission later.
if (!I->second->isStructTy() && !I->second->isOpaqueTy() &&
!I->second->isArrayTy()) {
TST.remove(I);
} else {
// If this is not used, remove it from the symbol table.
if (!UT.count(I->second))
TST.remove(I);
else
UT.remove(I->second); // Only keep one name for this type.
}
}
// UT now contains types that are not named. Loop over it, naming
// structure types.
//
bool Changed = false;
unsigned RenameCounter = 0;
for (SetVector<const Type *>::const_iterator I = UT.begin(), E = UT.end();
I != E; ++I)
if ((*I)->isStructTy() || (*I)->isArrayTy()) {
while (M.addTypeName("unnamed"+utostr(RenameCounter), *I))
++RenameCounter;
Changed = true;
}
// Loop over all external functions and globals. If we have two with
// identical names, merge them.
// FIXME: This code should disappear when we don't allow values with the same
// names when they have different types!
std::map<std::string, GlobalValue*> ExtSymbols;
for (Module::iterator I = M.begin(), E = M.end(); I != E;) {
Function *GV = I++;
if (GV->isDeclaration() && GV->hasName()) {
std::pair<std::map<std::string, GlobalValue*>::iterator, bool> X
= ExtSymbols.insert(std::make_pair(GV->getName(), GV));
if (!X.second) {
// Found a conflict, replace this global with the previous one.
GlobalValue *OldGV = X.first->second;
GV->replaceAllUsesWith(ConstantExpr::getBitCast(OldGV, GV->getType()));
GV->eraseFromParent();
Changed = true;
}
}
}
// Do the same for globals.
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E;) {
GlobalVariable *GV = I++;
if (GV->isDeclaration() && GV->hasName()) {
std::pair<std::map<std::string, GlobalValue*>::iterator, bool> X
= ExtSymbols.insert(std::make_pair(GV->getName(), GV));
if (!X.second) {
// Found a conflict, replace this global with the previous one.
GlobalValue *OldGV = X.first->second;
GV->replaceAllUsesWith(ConstantExpr::getBitCast(OldGV, GV->getType()));
GV->eraseFromParent();
Changed = true;
}
}
}
return Changed;
std::string CWriter::getStructName(const StructType *ST) {
if (!ST->isAnonymous() && !ST->getName().empty())
return CBEMangle("l_"+ST->getName().str());
return "l_unnamed_" + utostr(UnnamedStructIDs[ST]);
}
/// printStructReturnPointerFunctionType - This is like printType for a struct
/// return type, except, instead of printing the type as void (*)(Struct*, ...)
/// print it as "Struct (*)(...)", for struct return functions.
@ -471,7 +378,7 @@ void CWriter::printStructReturnPointerFunctionType(raw_ostream &Out,
bool PrintedType = false;
FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end();
const Type *RetTy = cast<PointerType>(I->get())->getElementType();
const Type *RetTy = cast<PointerType>(*I)->getElementType();
unsigned Idx = 1;
for (++I, ++Idx; I != E; ++I, ++Idx) {
if (PrintedType)
@ -559,12 +466,6 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
return Out;
}
// Check to see if the type is named.
if (!IgnoreName || Ty->isOpaqueTy()) {
std::map<const Type *, std::string>::iterator I = TypeNames.find(Ty);
if (I != TypeNames.end()) return Out << I->second << ' ' << NameSoFar;
}
switch (Ty->getTypeID()) {
case Type::FunctionTyID: {
const FunctionType *FTy = cast<FunctionType>(Ty);
@ -599,6 +500,11 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
}
case Type::StructTyID: {
const StructType *STy = cast<StructType>(Ty);
// Check to see if the type is named.
if (!IgnoreName)
return Out << getStructName(STy) << ' ' << NameSoFar;
Out << NameSoFar + " {\n";
unsigned Idx = 0;
for (StructType::element_iterator I = STy->element_begin(),
@ -639,12 +545,6 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
return Out << "; }";
}
case Type::OpaqueTyID: {
std::string TyName = "struct opaque_" + itostr(OpaqueCounter++);
assert(TypeNames.find(Ty) == TypeNames.end());
TypeNames[Ty] = TyName;
return Out << TyName << ' ' << NameSoFar;
}
default:
llvm_unreachable("Unhandled case in getTypeProps!");
}
@ -1829,8 +1729,8 @@ bool CWriter::doInitialization(Module &M) {
<< "/* End Module asm statements */\n";
}
// Loop over the symbol table, emitting all named constants...
printModuleTypes(M.getTypeSymbolTable());
// Loop over the symbol table, emitting all named constants.
printModuleTypes();
// Global variable declarations...
if (!M.global_empty()) {
@ -2119,11 +2019,10 @@ void CWriter::printFloatingPointConstants(const Constant *C) {
}
/// printSymbolTable - Run through symbol table looking for type names. If a
/// type name is found, emit its declaration...
///
void CWriter::printModuleTypes(const TypeSymbolTable &TST) {
void CWriter::printModuleTypes() {
Out << "/* Helper union for bitcasts */\n";
Out << "typedef union {\n";
Out << " unsigned int Int32;\n";
@ -2132,46 +2031,42 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) {
Out << " double Double;\n";
Out << "} llvmBitCastUnion;\n";
// We are only interested in the type plane of the symbol table.
TypeSymbolTable::const_iterator I = TST.begin();
TypeSymbolTable::const_iterator End = TST.end();
// Get all of the struct types used in the module.
std::vector<StructType*> StructTypes;
TheModule->findUsedStructTypes(StructTypes);
// If there are no type names, exit early.
if (I == End) return;
if (StructTypes.empty()) return;
// Print out forward declarations for structure types before anything else!
Out << "/* Structure forward decls */\n";
for (; I != End; ++I) {
std::string Name = "struct " + CBEMangle("l_"+I->first);
Out << Name << ";\n";
TypeNames.insert(std::make_pair(I->second, Name));
unsigned NextTypeID = 0;
// If any of them are missing names, add a unique ID to UnnamedStructIDs.
// Print out forward declarations for structure types.
for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) {
StructType *ST = StructTypes[i];
if (ST->isAnonymous() || ST->getName().empty())
UnnamedStructIDs[ST] = NextTypeID++;
std::string Name = getStructName(ST);
Out << "typedef struct " << Name << ' ' << Name << ";\n";
}
Out << '\n';
// Now we can print out typedefs. Above, we guaranteed that this can only be
// for struct or opaque types.
Out << "/* Typedefs */\n";
for (I = TST.begin(); I != End; ++I) {
std::string Name = CBEMangle("l_"+I->first);
Out << "typedef ";
printType(Out, I->second, false, Name);
Out << ";\n";
}
Out << '\n';
// Keep track of which structures have been printed so far...
std::set<const Type *> StructPrinted;
// Keep track of which structures have been printed so far.
SmallPtrSet<const Type *, 16> StructPrinted;
// Loop over all structures then push them into the stack so they are
// printed in the correct order.
//
Out << "/* Structure contents */\n";
for (I = TST.begin(); I != End; ++I)
if (I->second->isStructTy() || I->second->isArrayTy())
for (unsigned i = 0, e = StructTypes.size(); i != e; ++i)
if (StructTypes[i]->isStructTy())
// Only print out used types!
printContainedStructs(I->second, StructPrinted);
printContainedStructs(StructTypes[i], StructPrinted);
}
// Push the struct onto the stack and recursively push all structs
@ -2180,7 +2075,7 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) {
// TODO: Make this work properly with vector types
//
void CWriter::printContainedStructs(const Type *Ty,
std::set<const Type*> &StructPrinted) {
SmallPtrSet<const Type *, 16> &StructPrinted) {
// Don't walk through pointers.
if (Ty->isPointerTy() || Ty->isPrimitiveType() || Ty->isIntegerTy())
return;
@ -2190,14 +2085,13 @@ void CWriter::printContainedStructs(const Type *Ty,
E = Ty->subtype_end(); I != E; ++I)
printContainedStructs(*I, StructPrinted);
if (Ty->isStructTy() || Ty->isArrayTy()) {
if (const StructType *ST = dyn_cast<StructType>(Ty)) {
// Check to see if we have already printed this struct.
if (StructPrinted.insert(Ty).second) {
// Print structure type out.
std::string Name = TypeNames[Ty];
printType(Out, Ty, false, Name, true);
Out << ";\n\n";
}
if (!StructPrinted.insert(Ty)) return;
// Print structure type out.
printType(Out, ST, false, getStructName(ST), true);
Out << ";\n\n";
}
}
@ -2847,10 +2741,12 @@ static void printLimitValue(const IntegerType &Ty, bool isSigned, bool isMax,
Out << "U" << type << (isMax ? "_MAX" : "0");
}
#ifndef NDEBUG
static bool isSupportedIntegerSize(const IntegerType &T) {
return T.getBitWidth() == 8 || T.getBitWidth() == 16 ||
T.getBitWidth() == 32 || T.getBitWidth() == 64;
}
#endif
void CWriter::printIntrinsicDefinition(const Function &F, raw_ostream &Out) {
const FunctionType *funT = F.getFunctionType();
@ -3704,7 +3600,6 @@ bool CTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
PM.add(createGCLoweringPass());
PM.add(createLowerInvokePass());
PM.add(createCFGSimplificationPass()); // clean up after lower invoke.
PM.add(new CBackendNameAllUsedStructsAndMergeFunctions());
PM.add(new CWriter(o));
PM.add(createGCInfoDeleter());
return false;

View File

@ -22,7 +22,7 @@
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/CommandLine.h"
@ -33,7 +33,7 @@
#include "llvm/Config/config.h"
#include <algorithm>
#include <set>
#include <map>
using namespace llvm;
static cl::opt<std::string>
@ -193,26 +193,11 @@ static std::string getTypePrefix(const Type *Ty) {
case Type::ArrayTyID: return "array_";
case Type::PointerTyID: return "ptr_";
case Type::VectorTyID: return "packed_";
case Type::OpaqueTyID: return "opaque_";
default: return "other_";
}
return "unknown_";
}
// Looks up the type in the symbol table and returns a pointer to its name or
// a null pointer if it wasn't found. Note that this isn't the same as the
// Mode::getTypeName function which will return an empty string, not a null
// pointer if the name is not found.
static const std::string *
findTypeName(const TypeSymbolTable& ST, const Type* Ty) {
TypeSymbolTable::const_iterator TI = ST.begin();
TypeSymbolTable::const_iterator TE = ST.end();
for (;TI != TE; ++TI)
if (TI->second == Ty)
return &(TI->first);
return 0;
}
void CppWriter::error(const std::string& msg) {
report_fatal_error(msg);
}
@ -384,18 +369,20 @@ std::string CppWriter::getCppName(const Type* Ty) {
case Type::StructTyID: prefix = "StructTy_"; break;
case Type::ArrayTyID: prefix = "ArrayTy_"; break;
case Type::PointerTyID: prefix = "PointerTy_"; break;
case Type::OpaqueTyID: prefix = "OpaqueTy_"; break;
case Type::VectorTyID: prefix = "VectorTy_"; break;
default: prefix = "OtherTy_"; break; // prevent breakage
}
// See if the type has a name in the symboltable and build accordingly
const std::string* tName = findTypeName(TheModule->getTypeSymbolTable(), Ty);
std::string name;
if (tName)
name = std::string(prefix) + *tName;
else
name = std::string(prefix) + utostr(uniqueNum++);
if (const StructType *STy = dyn_cast<StructType>(Ty))
if (STy->hasName())
name = STy->getName();
if (name.empty())
name = utostr(uniqueNum++);
name = std::string(prefix) + name;
sanitize(name);
// Save the name
@ -590,8 +577,18 @@ bool CppWriter::printTypeInternal(const Type* Ty) {
Out << ");";
nl(Out);
}
Out << "StructType* " << typeName << " = StructType::get("
<< typeName << "_fields, /*isPacked=*/"
Out << "StructType *" << typeName << " = ";
if (ST->isAnonymous()) {
Out << "StructType::get(" << "mod->getContext(), ";
} else {
Out << "StructType::createNamed(mod->getContext(), \"";
printEscapedString(ST->getName());
Out << "\");";
nl(Out);
Out << typeName << "->setBody(";
}
Out << typeName << "_fields, /*isPacked=*/"
<< (ST->isPacked() ? "true" : "false") << ");";
nl(Out);
break;
@ -629,25 +626,10 @@ bool CppWriter::printTypeInternal(const Type* Ty) {
nl(Out);
break;
}
case Type::OpaqueTyID: {
Out << "OpaqueType* " << typeName;
Out << " = OpaqueType::get(mod->getContext());";
nl(Out);
break;
}
default:
error("Invalid TypeID");
}
// If the type had a name, make sure we recreate it.
const std::string* progTypeName =
findTypeName(TheModule->getTypeSymbolTable(),Ty);
if (progTypeName) {
Out << "mod->addTypeName(\"" << *progTypeName << "\", "
<< typeName << ");";
nl(Out);
}
// Pop us off the type stack
TypeStack.pop_back();
@ -670,7 +652,6 @@ bool CppWriter::printTypeInternal(const Type* Ty) {
case Type::StructTyID: Out << "StructType"; break;
case Type::VectorTyID: Out << "VectorType"; break;
case Type::PointerTyID: Out << "PointerType"; break;
case Type::OpaqueTyID: Out << "OpaqueType"; break;
default: Out << "NoSuchDerivedType"; break;
}
Out << ">(" << I->second << "_fwd.get());";
@ -695,26 +676,7 @@ void CppWriter::printType(const Type* Ty) {
}
void CppWriter::printTypes(const Module* M) {
// Walk the symbol table and print out all its types
const TypeSymbolTable& symtab = M->getTypeSymbolTable();
for (TypeSymbolTable::const_iterator TI = symtab.begin(), TE = symtab.end();
TI != TE; ++TI) {
// For primitive types and types already defined, just add a name
TypeMap::const_iterator TNI = TypeNames.find(TI->second);
if (TI->second->isIntegerTy() || TI->second->isPrimitiveType() ||
TNI != TypeNames.end()) {
Out << "mod->addTypeName(\"";
printEscapedString(TI->first);
Out << "\", " << getCppName(TI->second) << ");";
nl(Out);
// For everything else, define the type
} else {
printType(TI->second);
}
}
// Add all of the global variables to the value table...
// Add all of the global variables to the value table.
for (Module::const_global_iterator I = TheModule->global_begin(),
E = TheModule->global_end(); I != E; ++I) {
if (I->hasInitializer())
@ -1959,8 +1921,8 @@ void CppWriter::printVariable(const std::string& fname,
Out << "}\n";
}
void CppWriter::printType(const std::string& fname,
const std::string& typeName) {
void CppWriter::printType(const std::string &fname,
const std::string &typeName) {
const Type* Ty = TheModule->getTypeByName(typeName);
if (!Ty) {
error(std::string("Type '") + typeName + "' not found in input module");

View File

@ -42,6 +42,7 @@ char TargetData::ID = 0;
//===----------------------------------------------------------------------===//
StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
assert(!ST->isOpaque() && "Cannot get layout of opaque structs");
StructAlignment = 0;
StructSize = 0;
NumElements = ST->getNumElements();
@ -313,52 +314,16 @@ unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType,
namespace {
class StructLayoutMap : public AbstractTypeUser {
class StructLayoutMap {
typedef DenseMap<const StructType*, StructLayout*> LayoutInfoTy;
LayoutInfoTy LayoutInfo;
void RemoveEntry(LayoutInfoTy::iterator I, bool WasAbstract) {
I->second->~StructLayout();
free(I->second);
if (WasAbstract)
I->first->removeAbstractTypeUser(this);
LayoutInfo.erase(I);
}
/// refineAbstractType - The callback method invoked when an abstract type is
/// resolved to another type. An object must override this method to update
/// its internal state to reference NewType instead of OldType.
///
virtual void refineAbstractType(const DerivedType *OldTy,
const Type *) {
LayoutInfoTy::iterator I = LayoutInfo.find(cast<const StructType>(OldTy));
assert(I != LayoutInfo.end() && "Using type but not in map?");
RemoveEntry(I, true);
}
/// typeBecameConcrete - The other case which AbstractTypeUsers must be aware
/// of is when a type makes the transition from being abstract (where it has
/// clients on its AbstractTypeUsers list) to concrete (where it does not).
/// This method notifies ATU's when this occurs for a type.
///
virtual void typeBecameConcrete(const DerivedType *AbsTy) {
LayoutInfoTy::iterator I = LayoutInfo.find(cast<const StructType>(AbsTy));
assert(I != LayoutInfo.end() && "Using type but not in map?");
RemoveEntry(I, true);
}
public:
virtual ~StructLayoutMap() {
// Remove any layouts.
for (LayoutInfoTy::iterator
I = LayoutInfo.begin(), E = LayoutInfo.end(); I != E; ++I) {
const Type *Key = I->first;
for (LayoutInfoTy::iterator I = LayoutInfo.begin(), E = LayoutInfo.end();
I != E; ++I) {
StructLayout *Value = I->second;
if (Key->isAbstract())
Key->removeAbstractTypeUser(this);
Value->~StructLayout();
free(Value);
}
@ -367,7 +332,10 @@ public:
void InvalidateEntry(const StructType *Ty) {
LayoutInfoTy::iterator I = LayoutInfo.find(Ty);
if (I == LayoutInfo.end()) return;
RemoveEntry(I, Ty->isAbstract());
I->second->~StructLayout();
free(I->second);
LayoutInfo.erase(I);
}
StructLayout *&operator[](const StructType *STy) {
@ -404,9 +372,6 @@ const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
new (L) StructLayout(Ty, *this);
if (Ty->isAbstract())
Ty->addAbstractTypeUser(STM);
return L;
}

View File

@ -2,7 +2,6 @@ add_llvm_library(LLVMipo
ArgumentPromotion.cpp
ConstantMerge.cpp
DeadArgumentElimination.cpp
DeadTypeElimination.cpp
ExtractGV.cpp
FunctionAttrs.cpp
GlobalDCE.cpp

View File

@ -1,112 +0,0 @@
//===- DeadTypeElimination.cpp - Eliminate unused types for symbol table --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass is used to cleanup the output of GCC. It eliminate names for types
// that are unused in the entire translation unit, using the FindUsedTypes pass.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "deadtypeelim"
#include "llvm/Transforms/IPO.h"
#include "llvm/Analysis/FindUsedTypes.h"
#include "llvm/Module.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
STATISTIC(NumKilled, "Number of unused typenames removed from symtab");
namespace {
struct DTE : public ModulePass {
static char ID; // Pass identification, replacement for typeid
DTE() : ModulePass(ID) {
initializeDTEPass(*PassRegistry::getPassRegistry());
}
// doPassInitialization - For this pass, it removes global symbol table
// entries for primitive types. These are never used for linking in GCC and
// they make the output uglier to look at, so we nuke them.
//
// Also, initialize instance variables.
//
bool runOnModule(Module &M);
// getAnalysisUsage - This function needs FindUsedTypes to do its job...
//
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<FindUsedTypes>();
}
};
}
char DTE::ID = 0;
INITIALIZE_PASS_BEGIN(DTE, "deadtypeelim", "Dead Type Elimination",
false, false)
INITIALIZE_PASS_DEPENDENCY(FindUsedTypes)
INITIALIZE_PASS_END(DTE, "deadtypeelim", "Dead Type Elimination", false, false)
ModulePass *llvm::createDeadTypeEliminationPass() {
return new DTE();
}
// ShouldNukeSymtabEntry - Return true if this module level symbol table entry
// should be eliminated.
//
static inline bool ShouldNukeSymtabEntry(const Type *Ty){
// Nuke all names for primitive types!
if (Ty->isPrimitiveType() || Ty->isIntegerTy())
return true;
// Nuke all pointers to primitive types as well...
if (const PointerType *PT = dyn_cast<PointerType>(Ty))
if (PT->getElementType()->isPrimitiveType() ||
PT->getElementType()->isIntegerTy())
return true;
return false;
}
// run - For this pass, it removes global symbol table entries for primitive
// types. These are never used for linking in GCC and they make the output
// uglier to look at, so we nuke them. Also eliminate types that are never used
// in the entire program as indicated by FindUsedTypes.
//
bool DTE::runOnModule(Module &M) {
bool Changed = false;
TypeSymbolTable &ST = M.getTypeSymbolTable();
const SetVector<const Type*> &T = getAnalysis<FindUsedTypes>().getTypes();
std::set<const Type*> UsedTypes(T.begin(), T.end());
// Check the symbol table for superfluous type entries...
//
// Grab the 'type' plane of the module symbol...
TypeSymbolTable::iterator TI = ST.begin();
TypeSymbolTable::iterator TE = ST.end();
while ( TI != TE ) {
// If this entry should be unconditionally removed, or if we detect that
// the type is not used, remove it.
const Type *RHS = TI->second;
if (ShouldNukeSymtabEntry(RHS) || !UsedTypes.count(RHS)) {
ST.remove(TI++);
++NumKilled;
Changed = true;
} else {
++TI;
// We only need to leave one name for each type.
UsedTypes.erase(RHS);
}
}
return Changed;
}
// vim: sw=2

View File

@ -25,7 +25,6 @@ void llvm::initializeIPO(PassRegistry &Registry) {
initializeConstantMergePass(Registry);
initializeDAEPass(Registry);
initializeDAHPass(Registry);
initializeDTEPass(Registry);
initializeFunctionAttrsPass(Registry);
initializeGlobalDCEPass(Registry);
initializeGlobalOptPass(Registry);
@ -63,10 +62,6 @@ void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createDeadArgEliminationPass());
}
void LLVMAddDeadTypeEliminationPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createDeadTypeEliminationPass());
}
void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createFunctionAttrsPass());
}

View File

@ -218,7 +218,6 @@ bool FunctionComparator::isEquivalentType(const Type *Ty1,
llvm_unreachable("Unknown type!");
// Fall through in Release mode.
case Type::IntegerTyID:
case Type::OpaqueTyID:
case Type::VectorTyID:
// Ty1 == Ty2 would have returned true earlier.
return false;

View File

@ -28,8 +28,8 @@
#include "llvm/Pass.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;
@ -174,13 +174,19 @@ static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
}
}
// Strip the symbol table of its names.
static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) {
for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) {
if (PreserveDbgInfo && StringRef(TI->first).startswith("llvm.dbg"))
++TI;
else
ST.remove(TI++);
// Strip any named types of their names.
static void StripTypeNames(Module &M, bool PreserveDbgInfo) {
std::vector<StructType*> StructTypes;
M.findUsedStructTypes(StructTypes);
for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) {
StructType *STy = StructTypes[i];
if (STy->isAnonymous() || STy->getName().empty()) continue;
if (PreserveDbgInfo && STy->getName().startswith("llvm.dbg"))
continue;
STy->setName("");
}
}
@ -221,7 +227,7 @@ static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
}
// Remove all names from types.
StripTypeSymtab(M.getTypeSymbolTable(), PreserveDbgInfo);
StripTypeNames(M, PreserveDbgInfo);
return true;
}

View File

@ -15,7 +15,6 @@
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Constant.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
using namespace llvm;
@ -32,20 +31,13 @@ Module *llvm::CloneModule(const Module *M) {
return CloneModule(M, VMap);
}
Module *llvm::CloneModule(const Module *M,
ValueToValueMapTy &VMap) {
// First off, we need to create the new module...
Module *llvm::CloneModule(const Module *M, ValueToValueMapTy &VMap) {
// First off, we need to create the new module.
Module *New = new Module(M->getModuleIdentifier(), M->getContext());
New->setDataLayout(M->getDataLayout());
New->setTargetTriple(M->getTargetTriple());
New->setModuleInlineAsm(M->getModuleInlineAsm());
// Copy all of the type symbol table entries over.
const TypeSymbolTable &TST = M->getTypeSymbolTable();
for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
TI != TE; ++TI)
New->addTypeName(TI->first, TI->second);
// Copy all of the dependent libraries over.
for (Module::lib_iterator I = M->lib_begin(), E = M->lib_end(); I != E; ++I)
New->addLibrary(*I);
@ -88,8 +80,7 @@ Module *llvm::CloneModule(const Module *M,
I != E; ++I) {
GlobalVariable *GV = cast<GlobalVariable>(VMap[I]);
if (I->hasInitializer())
GV->setInitializer(cast<Constant>(MapValue(I->getInitializer(),
VMap, RF_None)));
GV->setInitializer(MapValue(I->getInitializer(), VMap));
GV->setLinkage(I->getLinkage());
GV->setThreadLocal(I->isThreadLocal());
GV->setConstant(I->isConstant());
@ -119,8 +110,8 @@ Module *llvm::CloneModule(const Module *M,
I != E; ++I) {
GlobalAlias *GA = cast<GlobalAlias>(VMap[I]);
GA->setLinkage(I->getLinkage());
if (const Constant* C = I->getAliasee())
GA->setAliasee(cast<Constant>(MapValue(C, VMap, RF_None)));
if (const Constant *C = I->getAliasee())
GA->setAliasee(MapValue(C, VMap));
}
// And named metadata....
@ -129,8 +120,7 @@ Module *llvm::CloneModule(const Module *M,
const NamedMDNode &NMD = *I;
NamedMDNode *NewNMD = New->getOrInsertNamedMetadata(NMD.getName());
for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
NewNMD->addOperand(cast<MDNode>(MapValue(NMD.getOperand(i), VMap,
RF_None)));
NewNMD->addOperand(MapValue(NMD.getOperand(i), VMap));
}
return New;

View File

@ -66,7 +66,7 @@ namespace {
Constant *AbortFn;
// Used for expensive EH support.
const Type *JBLinkTy;
StructType *JBLinkTy;
GlobalVariable *JBListHead;
Constant *SetJmpFn, *LongJmpFn, *StackSaveFn, *StackRestoreFn;
bool useExpensiveEHSupport;
@ -120,24 +120,16 @@ FunctionPass *llvm::createLowerInvokePass(const TargetLowering *TLI,
// doInitialization - Make sure that there is a prototype for abort in the
// current module.
bool LowerInvoke::doInitialization(Module &M) {
const Type *VoidPtrTy =
Type::getInt8PtrTy(M.getContext());
const Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext());
if (useExpensiveEHSupport) {
// Insert a type for the linked list of jump buffers.
unsigned JBSize = TLI ? TLI->getJumpBufSize() : 0;
JBSize = JBSize ? JBSize : 200;
const Type *JmpBufTy = ArrayType::get(VoidPtrTy, JBSize);
Type *JmpBufTy = ArrayType::get(VoidPtrTy, JBSize);
{ // The type is recursive, so use a type holder.
std::vector<const Type*> Elements;
Elements.push_back(JmpBufTy);
OpaqueType *OT = OpaqueType::get(M.getContext());
Elements.push_back(PointerType::getUnqual(OT));
PATypeHolder JBLType(StructType::get(M.getContext(), Elements));
OT->refineAbstractTypeTo(JBLType.get()); // Complete the cycle.
JBLinkTy = JBLType.get();
M.addTypeName("llvm.sjljeh.jmpbufty", JBLinkTy);
}
JBLinkTy = StructType::createNamed(M.getContext(), "llvm.sjljeh.jmpbufty");
Type *Elts[] = { JmpBufTy, PointerType::getUnqual(JBLinkTy) };
JBLinkTy->setBody(Elts);
const Type *PtrJBList = PointerType::getUnqual(JBLinkTy);

View File

@ -13,16 +13,17 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/ValueMapper.h"
#include "llvm/Type.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Metadata.h"
#include "llvm/ADT/SmallVector.h"
using namespace llvm;
Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM,
RemapFlags Flags) {
// Out of line method to get vtable etc for class.
void ValueMapTypeRemapper::Anchor() {}
Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags,
ValueMapTypeRemapper *TypeMapper) {
ValueToValueMapTy::iterator I = VM.find(V);
// If the value already exists in the map, use it.
@ -46,14 +47,14 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM,
// Check all operands to see if any need to be remapped.
for (unsigned i = 0, e = MD->getNumOperands(); i != e; ++i) {
Value *OP = MD->getOperand(i);
if (OP == 0 || MapValue(OP, VM, Flags) == OP) continue;
if (OP == 0 || MapValue(OP, VM, Flags, TypeMapper) == OP) continue;
// Ok, at least one operand needs remapping.
SmallVector<Value*, 4> Elts;
Elts.reserve(MD->getNumOperands());
for (i = 0; i != e; ++i) {
Value *Op = MD->getOperand(i);
Elts.push_back(Op ? MapValue(Op, VM, Flags) : 0);
Elts.push_back(Op ? MapValue(Op, VM, Flags, TypeMapper) : 0);
}
MDNode *NewMD = MDNode::get(V->getContext(), Elts);
Dummy->replaceAllUsesWith(NewMD);
@ -76,51 +77,75 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM,
return 0;
if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) {
Function *F = cast<Function>(MapValue(BA->getFunction(), VM, Flags));
Function *F =
cast<Function>(MapValue(BA->getFunction(), VM, Flags, TypeMapper));
BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(), VM,
Flags));
Flags, TypeMapper));
return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock());
}
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) {
Value *Op = C->getOperand(i);
Value *Mapped = MapValue(Op, VM, Flags);
if (Mapped == C) continue;
// Okay, the operands don't all match. We've already processed some or all
// of the operands, set them up now.
std::vector<Constant*> Ops;
Ops.reserve(C->getNumOperands());
for (unsigned j = 0; j != i; ++j)
Ops.push_back(cast<Constant>(C->getOperand(i)));
Ops.push_back(cast<Constant>(Mapped));
// Map the rest of the operands that aren't processed yet.
for (++i; i != e; ++i)
Ops.push_back(cast<Constant>(MapValue(C->getOperand(i), VM, Flags)));
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
return VM[V] = CE->getWithOperands(Ops);
if (ConstantArray *CA = dyn_cast<ConstantArray>(C))
return VM[V] = ConstantArray::get(CA->getType(), Ops);
if (ConstantStruct *CS = dyn_cast<ConstantStruct>(C))
return VM[V] = ConstantStruct::get(CS->getType(), Ops);
assert(isa<ConstantVector>(C) && "Unknown mapped constant type");
return VM[V] = ConstantVector::get(Ops);
// Otherwise, we have some other constant to remap. Start by checking to see
// if all operands have an identity remapping.
unsigned OpNo = 0, NumOperands = C->getNumOperands();
Value *Mapped = 0;
for (; OpNo != NumOperands; ++OpNo) {
Value *Op = C->getOperand(OpNo);
Mapped = MapValue(Op, VM, Flags, TypeMapper);
if (Mapped != C) break;
}
// See if the type mapper wants to remap the type as well.
Type *NewTy = C->getType();
if (TypeMapper)
NewTy = TypeMapper->remapType(NewTy);
// If we reach here, all of the operands of the constant match.
return VM[V] = C;
// If the result type and all operands match up, then just insert an identity
// mapping.
if (OpNo == NumOperands && NewTy == C->getType())
return VM[V] = C;
// Okay, we need to create a new constant. We've already processed some or
// all of the operands, set them all up now.
SmallVector<Constant*, 8> Ops;
Ops.reserve(NumOperands);
for (unsigned j = 0; j != OpNo; ++j)
Ops.push_back(cast<Constant>(C->getOperand(j)));
// If one of the operands mismatch, push it and the other mapped operands.
if (OpNo != NumOperands) {
Ops.push_back(cast<Constant>(Mapped));
// Map the rest of the operands that aren't processed yet.
for (++OpNo; OpNo != NumOperands; ++OpNo)
Ops.push_back(MapValue(cast<Constant>(C->getOperand(OpNo)), VM,
Flags, TypeMapper));
}
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
return VM[V] = CE->getWithOperands(Ops, NewTy);
if (isa<ConstantArray>(C))
return VM[V] = ConstantArray::get(cast<ArrayType>(NewTy), Ops);
if (isa<ConstantStruct>(C))
return VM[V] = ConstantStruct::get(cast<StructType>(NewTy), Ops);
if (isa<ConstantVector>(C))
return VM[V] = ConstantVector::get(Ops);
// If this is a no-operand constant, it must be because the type was remapped.
if (isa<UndefValue>(C))
return VM[V] = UndefValue::get(NewTy);
if (isa<ConstantAggregateZero>(C))
return VM[V] = ConstantAggregateZero::get(NewTy);
assert(isa<ConstantPointerNull>(C));
return VM[V] = ConstantPointerNull::get(cast<PointerType>(NewTy));
}
/// RemapInstruction - Convert the instruction operands from referencing the
/// current values into those specified by VMap.
///
void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap,
RemapFlags Flags) {
RemapFlags Flags, ValueMapTypeRemapper *TypeMapper){
// Remap operands.
for (User::op_iterator op = I->op_begin(), E = I->op_end(); op != E; ++op) {
Value *V = MapValue(*op, VMap, Flags);
Value *V = MapValue(*op, VMap, Flags, TypeMapper);
// If we aren't ignoring missing entries, assert that something happened.
if (V != 0)
*op = V;
@ -147,9 +172,13 @@ void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap,
I->getAllMetadata(MDs);
for (SmallVectorImpl<std::pair<unsigned, MDNode *> >::iterator
MI = MDs.begin(), ME = MDs.end(); MI != ME; ++MI) {
Value *Old = MI->second;
Value *New = MapValue(Old, VMap, Flags);
MDNode *Old = MI->second;
MDNode *New = MapValue(Old, VMap, Flags, TypeMapper);
if (New != Old)
I->setMetadata(MI->first, cast<MDNode>(New));
I->setMetadata(MI->first, New);
}
// If the instruction's type is being remapped, do so now.
if (TypeMapper)
I->mutateType(TypeMapper->remapType(I->getType()));
}

View File

@ -26,8 +26,7 @@
#include "llvm/Operator.h"
#include "llvm/Module.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
@ -137,72 +136,57 @@ static void PrintLLVMName(raw_ostream &OS, const Value *V) {
/// TypePrinting - Type printing machinery.
namespace {
class TypePrinting {
DenseMap<const Type *, std::string> TypeNames;
TypePrinting(const TypePrinting &); // DO NOT IMPLEMENT
void operator=(const TypePrinting&); // DO NOT IMPLEMENT
public:
/// NamedTypes - The named types that are used by the current module.
std::vector<StructType*> NamedTypes;
/// NumberedTypes - The numbered types, along with their value.
DenseMap<StructType*, unsigned> NumberedTypes;
TypePrinting() {}
~TypePrinting() {}
void clear() {
TypeNames.clear();
}
void incorporateTypes(const Module &M);
void print(const Type *Ty, raw_ostream &OS, bool IgnoreTopLevelName = false);
void print(Type *Ty, raw_ostream &OS);
void printAtLeastOneLevel(const Type *Ty, raw_ostream &OS) {
print(Ty, OS, true);
}
/// hasTypeName - Return true if the type has a name in TypeNames, false
/// otherwise.
bool hasTypeName(const Type *Ty) const {
return TypeNames.count(Ty);
}
/// addTypeName - Add a name for the specified type if it doesn't already have
/// one. This name will be printed instead of the structural version of the
/// type in order to make the output more concise.
void addTypeName(const Type *Ty, const std::string &N) {
TypeNames.insert(std::make_pair(Ty, N));
}
private:
void CalcTypeName(const Type *Ty, SmallVectorImpl<const Type *> &TypeStack,
raw_ostream &OS, bool IgnoreTopLevelName = false);
void printStructBody(StructType *Ty, raw_ostream &OS);
};
} // end anonymous namespace.
void TypePrinting::incorporateTypes(const Module &M) {
M.findUsedStructTypes(NamedTypes);
// The list of struct types we got back includes all the struct types, split
// the unnamed ones out to a numbering and remove the anonymous structs.
unsigned NextNumber = 0;
std::vector<StructType*>::iterator NextToUse = NamedTypes.begin(), I, E;
for (I = NamedTypes.begin(), E = NamedTypes.end(); I != E; ++I) {
StructType *STy = *I;
// Ignore anonymous types.
if (STy->isAnonymous())
continue;
if (STy->getName().empty())
NumberedTypes[STy] = NextNumber++;
else
*NextToUse++ = STy;
}
NamedTypes.erase(NextToUse, NamedTypes.end());
}
/// CalcTypeName - Write the specified type to the specified raw_ostream, making
/// use of type names or up references to shorten the type name where possible.
void TypePrinting::CalcTypeName(const Type *Ty,
SmallVectorImpl<const Type *> &TypeStack,
raw_ostream &OS, bool IgnoreTopLevelName) {
// Check to see if the type is named.
if (!IgnoreTopLevelName) {
DenseMap<const Type *, std::string> &TM = TypeNames;
DenseMap<const Type *, std::string>::iterator I = TM.find(Ty);
if (I != TM.end()) {
OS << I->second;
return;
}
}
// Check to see if the Type is already on the stack...
unsigned Slot = 0, CurSize = TypeStack.size();
while (Slot < CurSize && TypeStack[Slot] != Ty) ++Slot; // Scan for type
// This is another base case for the recursion. In this case, we know
// that we have looped back to a type that we have previously visited.
// Generate the appropriate upreference to handle this.
if (Slot < CurSize) {
OS << '\\' << unsigned(CurSize-Slot); // Here's the upreference
return;
}
TypeStack.push_back(Ty); // Recursive case: Add us to the stack..
void TypePrinting::print(Type *Ty, raw_ostream &OS) {
switch (Ty->getTypeID()) {
case Type::VoidTyID: OS << "void"; break;
case Type::FloatTyID: OS << "float"; break;
@ -215,257 +199,100 @@ void TypePrinting::CalcTypeName(const Type *Ty,
case Type::X86_MMXTyID: OS << "x86_mmx"; break;
case Type::IntegerTyID:
OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
break;
return;
case Type::FunctionTyID: {
const FunctionType *FTy = cast<FunctionType>(Ty);
CalcTypeName(FTy->getReturnType(), TypeStack, OS);
FunctionType *FTy = cast<FunctionType>(Ty);
print(FTy->getReturnType(), OS);
OS << " (";
for (FunctionType::param_iterator I = FTy->param_begin(),
E = FTy->param_end(); I != E; ++I) {
if (I != FTy->param_begin())
OS << ", ";
CalcTypeName(*I, TypeStack, OS);
print(*I, OS);
}
if (FTy->isVarArg()) {
if (FTy->getNumParams()) OS << ", ";
OS << "...";
}
OS << ')';
break;
return;
}
case Type::StructTyID: {
const StructType *STy = cast<StructType>(Ty);
if (STy->isPacked())
OS << '<';
OS << '{';
for (StructType::element_iterator I = STy->element_begin(),
E = STy->element_end(); I != E; ++I) {
OS << ' ';
CalcTypeName(*I, TypeStack, OS);
if (llvm::next(I) == STy->element_end())
OS << ' ';
else
OS << ',';
}
OS << '}';
if (STy->isPacked())
OS << '>';
break;
StructType *STy = cast<StructType>(Ty);
if (STy->isAnonymous())
return printStructBody(STy, OS);
if (!STy->getName().empty())
return PrintLLVMName(OS, STy->getName(), LocalPrefix);
DenseMap<StructType*, unsigned>::iterator I = NumberedTypes.find(STy);
if (I != NumberedTypes.end())
OS << '%' << I->second;
else // Not enumerated, print the hex address.
OS << "%\"type 0x" << STy << '\"';
return;
}
case Type::PointerTyID: {
const PointerType *PTy = cast<PointerType>(Ty);
CalcTypeName(PTy->getElementType(), TypeStack, OS);
PointerType *PTy = cast<PointerType>(Ty);
print(PTy->getElementType(), OS);
if (unsigned AddressSpace = PTy->getAddressSpace())
OS << " addrspace(" << AddressSpace << ')';
OS << '*';
break;
return;
}
case Type::ArrayTyID: {
const ArrayType *ATy = cast<ArrayType>(Ty);
ArrayType *ATy = cast<ArrayType>(Ty);
OS << '[' << ATy->getNumElements() << " x ";
CalcTypeName(ATy->getElementType(), TypeStack, OS);
print(ATy->getElementType(), OS);
OS << ']';
break;
return;
}
case Type::VectorTyID: {
const VectorType *PTy = cast<VectorType>(Ty);
VectorType *PTy = cast<VectorType>(Ty);
OS << "<" << PTy->getNumElements() << " x ";
CalcTypeName(PTy->getElementType(), TypeStack, OS);
print(PTy->getElementType(), OS);
OS << '>';
break;
return;
}
case Type::OpaqueTyID:
OS << "opaque";
break;
default:
OS << "<unrecognized-type>";
break;
return;
}
TypeStack.pop_back(); // Remove self from stack.
}
/// printTypeInt - The internal guts of printing out a type that has a
/// potentially named portion.
///
void TypePrinting::print(const Type *Ty, raw_ostream &OS,
bool IgnoreTopLevelName) {
// Check to see if the type is named.
if (!IgnoreTopLevelName) {
DenseMap<const Type*, std::string>::iterator I = TypeNames.find(Ty);
if (I != TypeNames.end()) {
OS << I->second;
return;
}
void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) {
if (STy->isOpaque()) {
OS << "opaque";
return;
}
// Otherwise we have a type that has not been named but is a derived type.
// Carefully recurse the type hierarchy to print out any contained symbolic
// names.
SmallVector<const Type *, 16> TypeStack;
std::string TypeName;
raw_string_ostream TypeOS(TypeName);
CalcTypeName(Ty, TypeStack, TypeOS, IgnoreTopLevelName);
OS << TypeOS.str();
// Cache type name for later use.
if (!IgnoreTopLevelName)
TypeNames.insert(std::make_pair(Ty, TypeOS.str()));
}
namespace {
class TypeFinder {
// To avoid walking constant expressions multiple times and other IR
// objects, we keep several helper maps.
DenseSet<const Value*> VisitedConstants;
DenseSet<const Type*> VisitedTypes;
TypePrinting &TP;
std::vector<const Type*> &NumberedTypes;
public:
TypeFinder(TypePrinting &tp, std::vector<const Type*> &numberedTypes)
: TP(tp), NumberedTypes(numberedTypes) {}
void Run(const Module &M) {
// Get types from the type symbol table. This gets opaque types referened
// only through derived named types.
const TypeSymbolTable &ST = M.getTypeSymbolTable();
for (TypeSymbolTable::const_iterator TI = ST.begin(), E = ST.end();
TI != E; ++TI)
IncorporateType(TI->second);
// Get types from global variables.
for (Module::const_global_iterator I = M.global_begin(),
E = M.global_end(); I != E; ++I) {
IncorporateType(I->getType());
if (I->hasInitializer())
IncorporateValue(I->getInitializer());
}
// Get types from aliases.
for (Module::const_alias_iterator I = M.alias_begin(),
E = M.alias_end(); I != E; ++I) {
IncorporateType(I->getType());
IncorporateValue(I->getAliasee());
}
// Get types from functions.
for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) {
IncorporateType(FI->getType());
for (Function::const_iterator BB = FI->begin(), E = FI->end();
BB != E;++BB)
for (BasicBlock::const_iterator II = BB->begin(),
E = BB->end(); II != E; ++II) {
const Instruction &I = *II;
// Incorporate the type of the instruction and all its operands.
IncorporateType(I.getType());
for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end();
OI != OE; ++OI)
IncorporateValue(*OI);
}
}
if (STy->isPacked())
OS << '<';
if (STy->getNumElements() == 0) {
OS << "{}";
} else {
StructType::element_iterator I = STy->element_begin();
OS << "{ ";
print(*I++, OS);
for (StructType::element_iterator E = STy->element_end(); I != E; ++I) {
OS << ", ";
print(*I, OS);
}
private:
void IncorporateType(const Type *Ty) {
// Check to see if we're already visited this type.
if (!VisitedTypes.insert(Ty).second)
return;
// If this is a structure or opaque type, add a name for the type.
if (((Ty->isStructTy() && cast<StructType>(Ty)->getNumElements())
|| Ty->isOpaqueTy()) && !TP.hasTypeName(Ty)) {
TP.addTypeName(Ty, "%"+utostr(unsigned(NumberedTypes.size())));
NumberedTypes.push_back(Ty);
}
// Recursively walk all contained types.
for (Type::subtype_iterator I = Ty->subtype_begin(),
E = Ty->subtype_end(); I != E; ++I)
IncorporateType(*I);
}
/// IncorporateValue - This method is used to walk operand lists finding
/// types hiding in constant expressions and other operands that won't be
/// walked in other ways. GlobalValues, basic blocks, instructions, and
/// inst operands are all explicitly enumerated.
void IncorporateValue(const Value *V) {
if (V == 0 || !isa<Constant>(V) || isa<GlobalValue>(V)) return;
// Already visited?
if (!VisitedConstants.insert(V).second)
return;
// Check this type.
IncorporateType(V->getType());
// Look in operands for types.
const Constant *C = cast<Constant>(V);
for (Constant::const_op_iterator I = C->op_begin(),
E = C->op_end(); I != E;++I)
IncorporateValue(*I);
}
};
} // end anonymous namespace
/// AddModuleTypesToPrinter - Add all of the symbolic type names for types in
/// the specified module to the TypePrinter and all numbered types to it and the
/// NumberedTypes table.
static void AddModuleTypesToPrinter(TypePrinting &TP,
std::vector<const Type*> &NumberedTypes,
const Module *M) {
if (M == 0) return;
// If the module has a symbol table, take all global types and stuff their
// names into the TypeNames map.
const TypeSymbolTable &ST = M->getTypeSymbolTable();
for (TypeSymbolTable::const_iterator TI = ST.begin(), E = ST.end();
TI != E; ++TI) {
const Type *Ty = cast<Type>(TI->second);
// As a heuristic, don't insert pointer to primitive types, because
// they are used too often to have a single useful name.
if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
const Type *PETy = PTy->getElementType();
if ((PETy->isPrimitiveType() || PETy->isIntegerTy()) &&
!PETy->isOpaqueTy())
continue;
}
// Likewise don't insert primitives either.
if (Ty->isIntegerTy() || Ty->isPrimitiveType())
continue;
// Get the name as a string and insert it into TypeNames.
std::string NameStr;
raw_string_ostream NameROS(NameStr);
formatted_raw_ostream NameOS(NameROS);
PrintLLVMName(NameOS, TI->first, LocalPrefix);
NameOS.flush();
TP.addTypeName(Ty, NameStr);
OS << " }";
}
// Walk the entire module to find references to unnamed structure and opaque
// types. This is required for correctness by opaque types (because multiple
// uses of an unnamed opaque type needs to be referred to by the same ID) and
// it shrinks complex recursive structure types substantially in some cases.
TypeFinder(TP, NumberedTypes).Run(*M);
if (STy->isPacked())
OS << '>';
}
/// WriteTypeSymbolic - This attempts to write the specified type as a symbolic
/// type, iff there is an entry in the modules symbol table for the specified
/// type or one of it's component types.
///
void llvm::WriteTypeSymbolic(raw_ostream &OS, const Type *Ty, const Module *M) {
TypePrinting Printer;
std::vector<const Type*> NumberedTypes;
AddModuleTypesToPrinter(Printer, NumberedTypes, M);
Printer.print(Ty, OS);
// FIXME: remove this function.
OS << *Ty;
}
//===----------------------------------------------------------------------===//
@ -986,7 +813,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
// As a special case, print the array as a string if it is an array of
// i8 with ConstantInt values.
//
const Type *ETy = CA->getType()->getElementType();
Type *ETy = CA->getType()->getElementType();
if (CA->isString()) {
Out << "c\"";
PrintEscapedString(CA->getAsString(), Out);
@ -1043,7 +870,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
}
if (const ConstantVector *CP = dyn_cast<ConstantVector>(CV)) {
const Type *ETy = CP->getType()->getElementType();
Type *ETy = CP->getType()->getElementType();
assert(CP->getNumOperands() > 0 &&
"Number of operands for a PackedConst must be > 0");
Out << '<';
@ -1241,8 +1068,8 @@ void llvm::WriteAsOperand(raw_ostream &Out, const Value *V,
if (Context == 0) Context = getModuleFromVal(V);
TypePrinting TypePrinter;
std::vector<const Type*> NumberedTypes;
AddModuleTypesToPrinter(TypePrinter, NumberedTypes, Context);
if (Context)
TypePrinter.incorporateTypes(*Context);
if (PrintType) {
TypePrinter.print(V->getType(), Out);
Out << ' ';
@ -1259,14 +1086,14 @@ class AssemblyWriter {
const Module *TheModule;
TypePrinting TypePrinter;
AssemblyAnnotationWriter *AnnotationWriter;
std::vector<const Type*> NumberedTypes;
public:
inline AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
const Module *M,
AssemblyAnnotationWriter *AAW)
: Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW) {
AddModuleTypesToPrinter(TypePrinter, NumberedTypes, M);
if (M)
TypePrinter.incorporateTypes(*M);
}
void printMDNodeBody(const MDNode *MD);
@ -1279,7 +1106,7 @@ public:
void writeAllMDNodes();
void printTypeSymbolTable(const TypeSymbolTable &ST);
void printTypeIdentities();
void printGlobal(const GlobalVariable *GV);
void printAlias(const GlobalAlias *GV);
void printFunction(const Function *F);
@ -1374,9 +1201,7 @@ void AssemblyWriter::printModule(const Module *M) {
Out << " ]";
}
// Loop over the symbol table, emitting all id'd types.
if (!M->getTypeSymbolTable().empty() || !NumberedTypes.empty()) Out << '\n';
printTypeSymbolTable(M->getTypeSymbolTable());
printTypeIdentities();
// Output all globals.
if (!M->global_empty()) Out << '\n';
@ -1534,7 +1359,10 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
const Constant *Aliasee = GA->getAliasee();
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Aliasee)) {
if (Aliasee == 0) {
TypePrinter.print(GA->getType(), Out);
Out << " <<NULL ALIASEE>>";
} else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Aliasee)) {
TypePrinter.print(GV->getType(), Out);
Out << ' ';
PrintLLVMName(Out, GV);
@ -1560,26 +1388,40 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
Out << '\n';
}
void AssemblyWriter::printTypeSymbolTable(const TypeSymbolTable &ST) {
void AssemblyWriter::printTypeIdentities() {
if (TypePrinter.NumberedTypes.empty() &&
TypePrinter.NamedTypes.empty())
return;
Out << '\n';
// We know all the numbers that each type is used and we know that it is a
// dense assignment. Convert the map to an index table.
std::vector<StructType*> NumberedTypes(TypePrinter.NumberedTypes.size());
for (DenseMap<StructType*, unsigned>::iterator I =
TypePrinter.NumberedTypes.begin(), E = TypePrinter.NumberedTypes.end();
I != E; ++I) {
assert(I->second < NumberedTypes.size() && "Didn't get a dense numbering?");
NumberedTypes[I->second] = I->first;
}
// Emit all numbered types.
for (unsigned i = 0, e = NumberedTypes.size(); i != e; ++i) {
Out << '%' << i << " = type ";
// Make sure we print out at least one level of the type structure, so
// that we do not get %2 = type %2
TypePrinter.printAtLeastOneLevel(NumberedTypes[i], Out);
TypePrinter.printStructBody(NumberedTypes[i], Out);
Out << '\n';
}
// Print the named types.
for (TypeSymbolTable::const_iterator TI = ST.begin(), TE = ST.end();
TI != TE; ++TI) {
PrintLLVMName(Out, TI->first, LocalPrefix);
for (unsigned i = 0, e = TypePrinter.NamedTypes.size(); i != e; ++i) {
PrintLLVMName(Out, TypePrinter.NamedTypes[i]->getName(), LocalPrefix);
Out << " = type ";
// Make sure we print out at least one level of the type structure, so
// that we do not get %FILE = type %FILE
TypePrinter.printAtLeastOneLevel(TI->second, Out);
TypePrinter.printStructBody(TypePrinter.NamedTypes[i], Out);
Out << '\n';
}
}
@ -1893,9 +1735,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
}
Operand = CI->getCalledValue();
const PointerType *PTy = cast<PointerType>(Operand->getType());
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
const Type *RetTy = FTy->getReturnType();
PointerType *PTy = cast<PointerType>(Operand->getType());
FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
Type *RetTy = FTy->getReturnType();
const AttrListPtr &PAL = CI->getAttributes();
if (PAL.getRetAttributes() != Attribute::None)
@ -1926,9 +1768,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
Out << ' ' << Attribute::getAsString(PAL.getFnAttributes());
} else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
Operand = II->getCalledValue();
const PointerType *PTy = cast<PointerType>(Operand->getType());
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
const Type *RetTy = FTy->getReturnType();
PointerType *PTy = cast<PointerType>(Operand->getType());
FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
Type *RetTy = FTy->getReturnType();
const AttrListPtr &PAL = II->getAttributes();
// Print the calling convention being used.
@ -2011,7 +1853,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
// omit the type from all but the first operand. If the instruction has
// different type operands (for example br), then they are all printed.
bool PrintAllTypes = false;
const Type *TheType = Operand->getType();
Type *TheType = Operand->getType();
// Select, Store and ShuffleVector always print all types.
if (isa<SelectInst>(I) || isa<StoreInst>(I) || isa<ShuffleVectorInst>(I)
@ -2131,7 +1973,15 @@ void Type::print(raw_ostream &OS) const {
OS << "<null Type>";
return;
}
TypePrinting().print(this, OS);
TypePrinting TP;
TP.print(const_cast<Type*>(this), OS);
// If the type is a named struct type, print the body as well.
if (StructType *STy = dyn_cast<StructType>(const_cast<Type*>(this)))
if (!STy->isAnonymous()) {
OS << " = type ";
TP.printStructBody(STy, OS);
}
}
void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const {
@ -2187,14 +2037,7 @@ void Value::printCustom(raw_ostream &OS) const {
void Value::dump() const { print(dbgs()); dbgs() << '\n'; }
// Type::dump - allow easy printing of Types from the debugger.
// This one uses type names from the given context module
void Type::dump(const Module *Context) const {
WriteTypeSymbolic(dbgs(), this, Context);
dbgs() << '\n';
}
// Type::dump - allow easy printing of Types from the debugger.
void Type::dump() const { dump(0); }
void Type::dump() const { print(dbgs()); }
// Module::dump() - Allow printing of Modules from the debugger.
void Module::dump() const { print(dbgs(), 0); }

View File

@ -29,7 +29,6 @@ add_llvm_library(LLVMCore
PassRegistry.cpp
PrintModulePass.cpp
Type.cpp
TypeSymbolTable.cpp
Use.cpp
User.cpp
Value.cpp

View File

@ -1466,8 +1466,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
/// isZeroSizedType - This type is zero sized if its an array or structure of
/// zero sized types. The only leaf zero sized type is an empty structure.
static bool isMaybeZeroSizedType(const Type *Ty) {
if (Ty->isOpaqueTy()) return true; // Can't say.
if (const StructType *STy = dyn_cast<StructType>(Ty)) {
if (STy->isOpaque()) return true; // Can't say.
// If all of elements have zero size, this does too.
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)

View File

@ -31,6 +31,7 @@
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
#include <cstdarg>
using namespace llvm;
@ -639,13 +640,13 @@ ConstantStruct::ConstantStruct(const StructType *T,
: Constant(T, ConstantStructVal,
OperandTraits<ConstantStruct>::op_end(this) - V.size(),
V.size()) {
assert(V.size() == T->getNumElements() &&
assert((T->isOpaque() || V.size() == T->getNumElements()) &&
"Invalid initializer vector for constant structure");
Use *OL = OperandList;
for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
I != E; ++I, ++OL) {
Constant *C = *I;
assert(C->getType() == T->getElementType(I-V.begin()) &&
assert((T->isOpaque() || C->getType() == T->getElementType(I-V.begin())) &&
"Initializer for struct element doesn't match struct element type!");
*OL = C;
}
@ -653,14 +654,13 @@ ConstantStruct::ConstantStruct(const StructType *T,
// ConstantStruct accessors.
Constant *ConstantStruct::get(const StructType *ST, ArrayRef<Constant*> V) {
assert(ST->getNumElements() == V.size() &&
"Incorrect # elements specified to ConstantStruct::get");
// Create a ConstantAggregateZero value if all elements are zeros.
for (unsigned i = 0, e = V.size(); i != e; ++i)
if (!V[i]->isNullValue())
return ST->getContext().pImpl->StructConstants.getOrCreate(ST, V);
assert((ST->isOpaque() || ST->getNumElements() == V.size()) &&
"Incorrect # elements specified to ConstantStruct::get");
return ConstantAggregateZero::get(ST);
}
@ -839,17 +839,15 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
}
/// getWithOperands - This returns the current constant expression with the
/// operands replaced with the specified values. The specified operands must
/// match count and type with the existing ones.
/// operands replaced with the specified values. The specified array must
/// have the same number of operands as our current one.
Constant *ConstantExpr::
getWithOperands(ArrayRef<Constant*> Ops) const {
getWithOperands(ArrayRef<Constant*> Ops, const Type *Ty) const {
assert(Ops.size() == getNumOperands() && "Operand count mismatch!");
bool AnyChange = false;
for (unsigned i = 0; i != Ops.size(); ++i) {
assert(Ops[i]->getType() == getOperand(i)->getType() &&
"Operand type mismatch!");
bool AnyChange = Ty != getType();
for (unsigned i = 0; i != Ops.size(); ++i)
AnyChange |= Ops[i] != getOperand(i);
}
if (!AnyChange) // No operands changed, return self.
return const_cast<ConstantExpr*>(this);
@ -866,7 +864,7 @@ getWithOperands(ArrayRef<Constant*> Ops) const {
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
return ConstantExpr::getCast(getOpcode(), Ops[0], getType());
return ConstantExpr::getCast(getOpcode(), Ops[0], Ty);
case Instruction::Select:
return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]);
case Instruction::InsertElement:
@ -964,14 +962,14 @@ ConstantAggregateZero* ConstantAggregateZero::get(const Type* Ty) {
/// destroyConstant - Remove the constant from the constant table...
///
void ConstantAggregateZero::destroyConstant() {
getRawType()->getContext().pImpl->AggZeroConstants.remove(this);
getType()->getContext().pImpl->AggZeroConstants.remove(this);
destroyConstantImpl();
}
/// destroyConstant - Remove the constant from the constant table...
///
void ConstantArray::destroyConstant() {
getRawType()->getContext().pImpl->ArrayConstants.remove(this);
getType()->getContext().pImpl->ArrayConstants.remove(this);
destroyConstantImpl();
}
@ -1050,14 +1048,14 @@ namespace llvm {
// destroyConstant - Remove the constant from the constant table...
//
void ConstantStruct::destroyConstant() {
getRawType()->getContext().pImpl->StructConstants.remove(this);
getType()->getContext().pImpl->StructConstants.remove(this);
destroyConstantImpl();
}
// destroyConstant - Remove the constant from the constant table...
//
void ConstantVector::destroyConstant() {
getRawType()->getContext().pImpl->VectorConstants.remove(this);
getType()->getContext().pImpl->VectorConstants.remove(this);
destroyConstantImpl();
}
@ -1098,7 +1096,7 @@ ConstantPointerNull *ConstantPointerNull::get(const PointerType *Ty) {
// destroyConstant - Remove the constant from the constant table...
//
void ConstantPointerNull::destroyConstant() {
getRawType()->getContext().pImpl->NullPtrConstants.remove(this);
getType()->getContext().pImpl->NullPtrConstants.remove(this);
destroyConstantImpl();
}
@ -1113,7 +1111,7 @@ UndefValue *UndefValue::get(const Type *Ty) {
// destroyConstant - Remove the constant from the constant table.
//
void UndefValue::destroyConstant() {
getRawType()->getContext().pImpl->UndefValueConstants.remove(this);
getType()->getContext().pImpl->UndefValueConstants.remove(this);
destroyConstantImpl();
}
@ -1147,7 +1145,7 @@ BlockAddress::BlockAddress(Function *F, BasicBlock *BB)
// destroyConstant - Remove the constant from the constant table.
//
void BlockAddress::destroyConstant() {
getFunction()->getRawType()->getContext().pImpl
getFunction()->getType()->getContext().pImpl
->BlockAddresses.erase(std::make_pair(getFunction(), getBasicBlock()));
getBasicBlock()->AdjustBlockAddressRefCount(-1);
destroyConstantImpl();
@ -1921,7 +1919,7 @@ Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2, bool isExact) {
// destroyConstant - Remove the constant from the constant table...
//
void ConstantExpr::destroyConstant() {
getRawType()->getContext().pImpl->ExprConstants.remove(this);
getType()->getContext().pImpl->ExprConstants.remove(this);
destroyConstantImpl();
}
@ -1962,10 +1960,10 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
LLVMContextImpl *pImpl = getRawType()->getContext().pImpl;
LLVMContextImpl *pImpl = getType()->getContext().pImpl;
std::pair<LLVMContextImpl::ArrayConstantsTy::MapKey, ConstantArray*> Lookup;
Lookup.first.first = cast<ArrayType>(getRawType());
Lookup.first.first = cast<ArrayType>(getType());
Lookup.second = this;
std::vector<Constant*> &Values = Lookup.first.second;
@ -1999,7 +1997,7 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
Constant *Replacement = 0;
if (isAllZeros) {
Replacement = ConstantAggregateZero::get(getRawType());
Replacement = ConstantAggregateZero::get(getType());
} else {
// Check to see if we have this array type already.
bool Exists;
@ -2050,7 +2048,7 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
std::pair<LLVMContextImpl::StructConstantsTy::MapKey, ConstantStruct*> Lookup;
Lookup.first.first = cast<StructType>(getRawType());
Lookup.first.first = cast<StructType>(getType());
Lookup.second = this;
std::vector<Constant*> &Values = Lookup.first.second;
Values.reserve(getNumOperands()); // Build replacement struct.
@ -2072,11 +2070,11 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
}
Values[OperandToUpdate] = ToC;
LLVMContextImpl *pImpl = getRawType()->getContext().pImpl;
LLVMContextImpl *pImpl = getContext().pImpl;
Constant *Replacement = 0;
if (isAllZeros) {
Replacement = ConstantAggregateZero::get(getRawType());
Replacement = ConstantAggregateZero::get(getType());
} else {
// Check to see if we have this struct type already.
bool Exists;
@ -2167,7 +2165,7 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
&Indices[0], Indices.size());
} else if (isCast()) {
assert(getOperand(0) == From && "Cast only has one use!");
Replacement = ConstantExpr::getCast(getOpcode(), To, getRawType());
Replacement = ConstantExpr::getCast(getOpcode(), To, getType());
} else if (getOpcode() == Instruction::Select) {
Constant *C1 = getOperand(0);
Constant *C2 = getOperand(1);

View File

@ -570,13 +570,11 @@ struct ConstantKeyData<InlineAsm> {
template<class ValType, class ValRefType, class TypeClass, class ConstantClass,
bool HasLargeKey = false /*true for arrays and structs*/ >
class ConstantUniqueMap : public AbstractTypeUser {
class ConstantUniqueMap {
public:
typedef std::pair<const TypeClass*, ValType> MapKey;
typedef std::map<MapKey, ConstantClass *> MapTy;
typedef std::map<ConstantClass *, typename MapTy::iterator> InverseMapTy;
typedef std::map<const DerivedType*, typename MapTy::iterator>
AbstractTypeMapTy;
private:
/// Map - This is the main map from the element descriptor to the Constants.
/// This is the primary way we avoid creating two of the same shape
@ -589,10 +587,6 @@ private:
/// through the map with very large keys.
InverseMapTy InverseMap;
/// AbstractTypeMap - Map for abstract type constants.
///
AbstractTypeMapTy AbstractTypeMap;
public:
typename MapTy::iterator map_begin() { return Map.begin(); }
typename MapTy::iterator map_end() { return Map.end(); }
@ -629,7 +623,7 @@ private:
}
typename MapTy::iterator I =
Map.find(MapKey(static_cast<const TypeClass*>(CP->getRawType()),
Map.find(MapKey(static_cast<const TypeClass*>(CP->getType()),
ConstantKeyData<ConstantClass>::getValType(CP)));
if (I == Map.end() || I->second != CP) {
// FIXME: This should not use a linear scan. If this gets to be a
@ -639,24 +633,8 @@ private:
}
return I;
}
void AddAbstractTypeUser(const Type *Ty, typename MapTy::iterator I) {
// If the type of the constant is abstract, make sure that an entry
// exists for it in the AbstractTypeMap.
if (Ty->isAbstract()) {
const DerivedType *DTy = static_cast<const DerivedType *>(Ty);
typename AbstractTypeMapTy::iterator TI = AbstractTypeMap.find(DTy);
if (TI == AbstractTypeMap.end()) {
// Add ourselves to the ATU list of the type.
cast<DerivedType>(DTy)->addAbstractTypeUser(this);
AbstractTypeMap.insert(TI, std::make_pair(DTy, I));
}
}
}
ConstantClass* Create(const TypeClass *Ty, ValRefType V,
ConstantClass *Create(const TypeClass *Ty, ValRefType V,
typename MapTy::iterator I) {
ConstantClass* Result =
ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V);
@ -667,8 +645,6 @@ private:
if (HasLargeKey) // Remember the reverse mapping if needed.
InverseMap.insert(std::make_pair(Result, I));
AddAbstractTypeUser(Ty, I);
return Result;
}
public:
@ -692,43 +668,6 @@ public:
return Result;
}
void UpdateAbstractTypeMap(const DerivedType *Ty,
typename MapTy::iterator I) {
assert(AbstractTypeMap.count(Ty) &&
"Abstract type not in AbstractTypeMap?");
typename MapTy::iterator &ATMEntryIt = AbstractTypeMap[Ty];
if (ATMEntryIt == I) {
// Yes, we are removing the representative entry for this type.
// See if there are any other entries of the same type.
typename MapTy::iterator TmpIt = ATMEntryIt;
// First check the entry before this one...
if (TmpIt != Map.begin()) {
--TmpIt;
if (TmpIt->first.first != Ty) // Not the same type, move back...
++TmpIt;
}
// If we didn't find the same type, try to move forward...
if (TmpIt == ATMEntryIt) {
++TmpIt;
if (TmpIt == Map.end() || TmpIt->first.first != Ty)
--TmpIt; // No entry afterwards with the same type
}
// If there is another entry in the map of the same abstract type,
// update the AbstractTypeMap entry now.
if (TmpIt != ATMEntryIt) {
ATMEntryIt = TmpIt;
} else {
// Otherwise, we are removing the last instance of this type
// from the table. Remove from the ATM, and from user list.
cast<DerivedType>(Ty)->removeAbstractTypeUser(this);
AbstractTypeMap.erase(Ty);
}
}
}
void remove(ConstantClass *CP) {
typename MapTy::iterator I = FindExistingElement(CP);
assert(I != Map.end() && "Constant not found in constant table!");
@ -736,12 +675,6 @@ public:
if (HasLargeKey) // Remember the reverse mapping if needed.
InverseMap.erase(CP);
// Now that we found the entry, make sure this isn't the entry that
// the AbstractTypeMap points to.
const TypeClass *Ty = I->first.first;
if (Ty->isAbstract())
UpdateAbstractTypeMap(static_cast<const DerivedType *>(Ty), I);
Map.erase(I);
}
@ -755,22 +688,7 @@ public:
assert(OldI != Map.end() && "Constant not found in constant table!");
assert(OldI->second == C && "Didn't find correct element?");
// If this constant is the representative element for its abstract type,
// update the AbstractTypeMap so that the representative element is I.
//
// This must use getRawType() because if the type is under refinement, we
// will get the refineAbstractType callback below, and we don't want to
// kick union find in on the constant.
if (C->getRawType()->isAbstract()) {
typename AbstractTypeMapTy::iterator ATI =
AbstractTypeMap.find(cast<DerivedType>(C->getRawType()));
assert(ATI != AbstractTypeMap.end() &&
"Abstract type not in AbstractTypeMap?");
if (ATI->second == OldI)
ATI->second = I;
}
// Remove the old entry from the map.
// Remove the old entry from the map.
Map.erase(OldI);
// Update the inverse map so that we know that this constant is now
@ -780,58 +698,6 @@ public:
InverseMap[C] = I;
}
}
void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
typename AbstractTypeMapTy::iterator I = AbstractTypeMap.find(OldTy);
assert(I != AbstractTypeMap.end() &&
"Abstract type not in AbstractTypeMap?");
// Convert a constant at a time until the last one is gone. The last one
// leaving will remove() itself, causing the AbstractTypeMapEntry to be
// eliminated eventually.
do {
ConstantClass *C = I->second->second;
MapKey Key(cast<TypeClass>(NewTy),
ConstantKeyData<ConstantClass>::getValType(C));
std::pair<typename MapTy::iterator, bool> IP =
Map.insert(std::make_pair(Key, C));
if (IP.second) {
// The map didn't previously have an appropriate constant in the
// new type.
// Remove the old entry.
typename MapTy::iterator OldI =
Map.find(MapKey(cast<TypeClass>(OldTy), IP.first->first.second));
assert(OldI != Map.end() && "Constant not in map!");
UpdateAbstractTypeMap(OldTy, OldI);
Map.erase(OldI);
// Set the constant's type. This is done in place!
setType(C, NewTy);
// Update the inverse map so that we know that this constant is now
// located at descriptor I.
if (HasLargeKey)
InverseMap[C] = IP.first;
AddAbstractTypeUser(NewTy, IP.first);
} else {
// The map already had an appropriate constant in the new type, so
// there's no longer a need for the old constant.
C->uncheckedReplaceAllUsesWith(IP.first->second);
C->destroyConstant(); // This constant is now dead, destroy it.
}
I = AbstractTypeMap.find(OldTy);
} while (I != AbstractTypeMap.end());
}
// If the type became concrete without being refined to any other existing
// type, we just remove ourselves from the ATU list.
void typeBecameConcrete(const DerivedType *AbsTy) {
AbsTy->removeAbstractTypeUser(this);
}
void dump() const {
DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");

View File

@ -19,7 +19,6 @@
#include "llvm/GlobalVariable.h"
#include "llvm/GlobalAlias.h"
#include "llvm/LLVMContext.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/InlineAsm.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/PassManager.h"
@ -111,27 +110,6 @@ void LLVMSetTarget(LLVMModuleRef M, const char *Triple) {
unwrap(M)->setTargetTriple(Triple);
}
/*--.. Type names ..........................................................--*/
LLVMBool LLVMAddTypeName(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty) {
return unwrap(M)->addTypeName(Name, unwrap(Ty));
}
void LLVMDeleteTypeName(LLVMModuleRef M, const char *Name) {
TypeSymbolTable &TST = unwrap(M)->getTypeSymbolTable();
TypeSymbolTable::iterator I = TST.find(Name);
if (I != TST.end())
TST.remove(I);
}
LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name) {
return wrap(unwrap(M)->getTypeByName(Name));
}
const char *LLVMGetTypeName(LLVMModuleRef M, LLVMTypeRef Ty) {
return unwrap(M)->getTypeName(unwrap(Ty)).c_str();
}
void LLVMDumpModule(LLVMModuleRef M) {
unwrap(M)->dump();
}
@ -182,8 +160,6 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
return LLVMArrayTypeKind;
case Type::PointerTyID:
return LLVMPointerTypeKind;
case Type::OpaqueTyID:
return LLVMOpaqueTypeKind;
case Type::VectorTyID:
return LLVMVectorTypeKind;
case Type::X86_MMXTyID:
@ -382,9 +358,6 @@ LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C) {
LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C) {
return wrap(Type::getLabelTy(*unwrap(C)));
}
LLVMTypeRef LLVMOpaqueTypeInContext(LLVMContextRef C) {
return wrap(OpaqueType::get(*unwrap(C)));
}
LLVMTypeRef LLVMVoidType(void) {
return LLVMVoidTypeInContext(LLVMGetGlobalContext());
@ -392,28 +365,6 @@ LLVMTypeRef LLVMVoidType(void) {
LLVMTypeRef LLVMLabelType(void) {
return LLVMLabelTypeInContext(LLVMGetGlobalContext());
}
LLVMTypeRef LLVMOpaqueType(void) {
return LLVMOpaqueTypeInContext(LLVMGetGlobalContext());
}
/*--.. Operations on type handles ..........................................--*/
LLVMTypeHandleRef LLVMCreateTypeHandle(LLVMTypeRef PotentiallyAbstractTy) {
return wrap(new PATypeHolder(unwrap(PotentiallyAbstractTy)));
}
void LLVMDisposeTypeHandle(LLVMTypeHandleRef TypeHandle) {
delete unwrap(TypeHandle);
}
LLVMTypeRef LLVMResolveTypeHandle(LLVMTypeHandleRef TypeHandle) {
return wrap(unwrap(TypeHandle)->get());
}
void LLVMRefineType(LLVMTypeRef AbstractTy, LLVMTypeRef ConcreteTy) {
unwrap<DerivedType>(AbstractTy)->refineAbstractTypeTo(unwrap(ConcreteTy));
}
/*===-- Operations on values ----------------------------------------------===*/

View File

@ -134,7 +134,7 @@ LLVMContext &Function::getContext() const {
return getType()->getContext();
}
const FunctionType *Function::getFunctionType() const {
FunctionType *Function::getFunctionType() const {
return cast<FunctionType>(getType()->getElementType());
}
@ -142,7 +142,7 @@ bool Function::isVarArg() const {
return getFunctionType()->isVarArg();
}
const Type *Function::getReturnType() const {
Type *Function::getReturnType() const {
return getFunctionType()->getReturnType();
}
@ -163,7 +163,7 @@ Function::Function(const FunctionType *Ty, LinkageTypes Linkage,
: GlobalValue(PointerType::getUnqual(Ty),
Value::FunctionVal, 0, 0, Linkage, name) {
assert(FunctionType::isValidReturnType(getReturnType()) &&
!getReturnType()->isOpaqueTy() && "invalid return type");
"invalid return type");
SymTab = new ValueSymbolTable();
// If the function has arguments, mark them as lazily built.

View File

@ -51,6 +51,7 @@ void GlobalValue::copyAttributesFrom(const GlobalValue *Src) {
setAlignment(Src->getAlignment());
setSection(Src->getSection());
setVisibility(Src->getVisibility());
setUnnamedAddr(Src->hasUnnamedAddr());
}
void GlobalValue::setAlignment(unsigned Align) {

View File

@ -47,7 +47,7 @@ InlineAsm::InlineAsm(const PointerType *Ty, const std::string &asmString,
}
void InlineAsm::destroyConstant() {
getRawType()->getContext().pImpl->InlineAsms.remove(this);
getType()->getContext().pImpl->InlineAsms.remove(this);
delete this;
}

View File

@ -372,7 +372,7 @@ static Instruction *createMalloc(Instruction *InsertBefore,
// Create the call to Malloc.
BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
Module* M = BB->getParent()->getParent();
const Type *BPTy = Type::getInt8PtrTy(BB->getContext());
Type *BPTy = Type::getInt8PtrTy(BB->getContext());
Value *MallocFunc = MallocF;
if (!MallocFunc)
// prototype malloc as "void *malloc(size_t)"
@ -823,7 +823,7 @@ bool AllocaInst::isArrayAllocation() const {
return true;
}
const Type *AllocaInst::getAllocatedType() const {
Type *AllocaInst::getAllocatedType() const {
return getType()->getElementType();
}
@ -1098,7 +1098,7 @@ GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI)
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const Twine &Name, Instruction *InBe)
: Instruction(PointerType::get(
checkType(getIndexedType(Ptr->getType(),Idx)), retrieveAddrSpace(Ptr)),
checkGEPType(getIndexedType(Ptr->getType(),Idx)), retrieveAddrSpace(Ptr)),
GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - 2,
2, InBe) {
@ -1108,7 +1108,7 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const Twine &Name, BasicBlock *IAE)
: Instruction(PointerType::get(
checkType(getIndexedType(Ptr->getType(),Idx)),
checkGEPType(getIndexedType(Ptr->getType(),Idx)),
retrieveAddrSpace(Ptr)),
GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - 2,
@ -1126,60 +1126,50 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
/// pointer type.
///
template <typename IndexTy>
static const Type* getIndexedTypeInternal(const Type *Ptr, IndexTy const *Idxs,
unsigned NumIdx) {
static Type *getIndexedTypeInternal(const Type *Ptr, IndexTy const *Idxs,
unsigned NumIdx) {
const PointerType *PTy = dyn_cast<PointerType>(Ptr);
if (!PTy) return 0; // Type isn't a pointer type!
const Type *Agg = PTy->getElementType();
Type *Agg = PTy->getElementType();
// Handle the special case of the empty set index set, which is always valid.
if (NumIdx == 0)
return Agg;
// If there is at least one index, the top level type must be sized, otherwise
// it cannot be 'stepped over'. We explicitly allow abstract types (those
// that contain opaque types) under the assumption that it will be resolved to
// a sane type later.
if (!Agg->isSized() && !Agg->isAbstract())
// it cannot be 'stepped over'.
if (!Agg->isSized())
return 0;
unsigned CurIdx = 1;
for (; CurIdx != NumIdx; ++CurIdx) {
const CompositeType *CT = dyn_cast<CompositeType>(Agg);
CompositeType *CT = dyn_cast<CompositeType>(Agg);
if (!CT || CT->isPointerTy()) return 0;
IndexTy Index = Idxs[CurIdx];
if (!CT->indexValid(Index)) return 0;
Agg = CT->getTypeAtIndex(Index);
// If the new type forwards to another type, then it is in the middle
// of being refined to another type (and hence, may have dropped all
// references to what it was using before). So, use the new forwarded
// type.
if (const Type *Ty = Agg->getForwardedType())
Agg = Ty;
}
return CurIdx == NumIdx ? Agg : 0;
}
const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
Value* const *Idxs,
unsigned NumIdx) {
Type *GetElementPtrInst::getIndexedType(const Type *Ptr, Value* const *Idxs,
unsigned NumIdx) {
return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
}
const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
Constant* const *Idxs,
unsigned NumIdx) {
Type *GetElementPtrInst::getIndexedType(const Type *Ptr,
Constant* const *Idxs,
unsigned NumIdx) {
return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
}
const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
uint64_t const *Idxs,
unsigned NumIdx) {
Type *GetElementPtrInst::getIndexedType(const Type *Ptr,
uint64_t const *Idxs,
unsigned NumIdx) {
return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
}
const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) {
Type *GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) {
const PointerType *PTy = dyn_cast<PointerType>(Ptr);
if (!PTy) return 0; // Type isn't a pointer type!
@ -1482,9 +1472,9 @@ ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
// A null type is returned if the indices are invalid for the specified
// pointer type.
//
const Type* ExtractValueInst::getIndexedType(const Type *Agg,
const unsigned *Idxs,
unsigned NumIdx) {
Type *ExtractValueInst::getIndexedType(const Type *Agg,
const unsigned *Idxs,
unsigned NumIdx) {
for (unsigned CurIdx = 0; CurIdx != NumIdx; ++CurIdx) {
unsigned Index = Idxs[CurIdx];
// We can't use CompositeType::indexValid(Index) here.
@ -1505,19 +1495,11 @@ const Type* ExtractValueInst::getIndexedType(const Type *Agg,
}
Agg = cast<CompositeType>(Agg)->getTypeAtIndex(Index);
// If the new type forwards to another type, then it is in the middle
// of being refined to another type (and hence, may have dropped all
// references to what it was using before). So, use the new forwarded
// type.
if (const Type *Ty = Agg->getForwardedType())
Agg = Ty;
}
return Agg;
return const_cast<Type*>(Agg);
}
const Type* ExtractValueInst::getIndexedType(const Type *Agg,
unsigned Idx) {
Type *ExtractValueInst::getIndexedType(const Type *Agg, unsigned Idx) {
return getIndexedType(Agg, &Idx, 1);
}

View File

@ -31,14 +31,10 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
Int8Ty(C, 8),
Int16Ty(C, 16),
Int32Ty(C, 32),
Int64Ty(C, 64),
AlwaysOpaqueTy(new OpaqueType(C)) {
Int64Ty(C, 64) {
InlineAsmDiagHandler = 0;
InlineAsmDiagContext = 0;
// Make sure the AlwaysOpaqueTy stays alive as long as the Context.
AlwaysOpaqueTy->addRef();
OpaqueTypes.insert(AlwaysOpaqueTy);
NamedStructTypesUniqueID = 0;
}
namespace {
@ -86,12 +82,7 @@ LLVMContextImpl::~LLVMContextImpl() {
I != E; ++I) {
delete I->second;
}
AlwaysOpaqueTy->dropRef();
for (OpaqueTypesTy::iterator I = OpaqueTypes.begin(), E = OpaqueTypes.end();
I != E; ++I) {
(*I)->AbstractTypeUsers.clear();
delete *I;
}
// Destroy MDNodes. ~MDNode can move and remove nodes between the MDNodeSet
// and the NonUniquedMDNodes sets, so copy the values out first.
SmallVector<MDNode*, 8> MDNodes;
@ -109,7 +100,6 @@ LLVMContextImpl::~LLVMContextImpl() {
"Destroying all MDNodes didn't empty the Context's sets.");
// Destroy MDStrings.
for (StringMap<MDString*>::iterator I = MDStringCache.begin(),
E = MDStringCache.end(); I != E; ++I) {
E = MDStringCache.end(); I != E; ++I)
delete I->second;
}
}

View File

@ -15,10 +15,9 @@
#ifndef LLVM_LLVMCONTEXT_IMPL_H
#define LLVM_LLVMCONTEXT_IMPL_H
#include "llvm/LLVMContext.h"
#include "ConstantsContext.h"
#include "LeaksContext.h"
#include "TypesContext.h"
#include "llvm/LLVMContext.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Metadata.h"
@ -170,34 +169,22 @@ public:
LeakDetectorImpl<Value> LLVMObjects;
// Basic type instances.
const Type VoidTy;
const Type LabelTy;
const Type FloatTy;
const Type DoubleTy;
const Type MetadataTy;
const Type X86_FP80Ty;
const Type FP128Ty;
const Type PPC_FP128Ty;
const Type X86_MMXTy;
const IntegerType Int1Ty;
const IntegerType Int8Ty;
const IntegerType Int16Ty;
const IntegerType Int32Ty;
const IntegerType Int64Ty;
Type VoidTy, LabelTy, FloatTy, DoubleTy, MetadataTy;
Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy;
IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty;
TypeMap<ArrayValType, ArrayType> ArrayTypes;
TypeMap<VectorValType, VectorType> VectorTypes;
TypeMap<PointerValType, PointerType> PointerTypes;
TypeMap<FunctionValType, FunctionType> FunctionTypes;
TypeMap<StructValType, StructType> StructTypes;
TypeMap<IntegerValType, IntegerType> IntegerTypes;
// Opaque types are not structurally uniqued, so don't use TypeMap.
typedef SmallPtrSet<const OpaqueType*, 8> OpaqueTypesTy;
OpaqueTypesTy OpaqueTypes;
/// Used as an abstract type that will never be resolved.
OpaqueType *const AlwaysOpaqueTy;
DenseMap<unsigned, IntegerType*> IntegerTypes;
// TODO: Optimize FunctionTypes/AnonStructTypes!
std::map<std::vector<Type*>, FunctionType*> FunctionTypes;
std::map<std::vector<Type*>, StructType*> AnonStructTypes;
StringMap<StructType*> NamedStructTypes;
unsigned NamedStructTypesUniqueID;
DenseMap<std::pair<Type *, uint64_t>, ArrayType*> ArrayTypes;
DenseMap<std::pair<Type *, unsigned>, VectorType*> VectorTypes;
DenseMap<Type*, PointerType*> PointerTypes; // Pointers in AddrSpace = 0
DenseMap<std::pair<Type*, unsigned>, PointerType*> ASPointerTypes;
/// ValueHandles - This map keeps track of all of the value handles that are

View File

@ -19,6 +19,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/STLExtras.h"
#include "SymbolTableListTraitsImpl.h"
#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/ValueHandle.h"

View File

@ -17,12 +17,12 @@
#include "llvm/DerivedTypes.h"
#include "llvm/GVMaterializer.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/LeakDetector.h"
#include "SymbolTableListTraitsImpl.h"
#include "llvm/TypeSymbolTable.h"
#include <algorithm>
#include <cstdarg>
#include <cstdlib>
@ -60,7 +60,6 @@ template class llvm::SymbolTableListTraits<GlobalAlias, Module>;
Module::Module(StringRef MID, LLVMContext& C)
: Context(C), Materializer(NULL), ModuleID(MID) {
ValSymTab = new ValueSymbolTable();
TypeSymTab = new TypeSymbolTable();
NamedMDSymTab = new StringMap<NamedMDNode *>();
Context.addModule(this);
}
@ -74,11 +73,10 @@ Module::~Module() {
LibraryList.clear();
NamedMDList.clear();
delete ValSymTab;
delete TypeSymTab;
delete static_cast<StringMap<NamedMDNode *> *>(NamedMDSymTab);
}
/// Target endian information...
/// Target endian information.
Module::Endianness Module::getEndianness() const {
StringRef temp = DataLayout;
Module::Endianness ret = AnyEndianness;
@ -340,51 +338,6 @@ void Module::eraseNamedMetadata(NamedMDNode *NMD) {
NamedMDList.erase(NMD);
}
//===----------------------------------------------------------------------===//
// Methods for easy access to the types in the module.
//
// addTypeName - Insert an entry in the symbol table mapping Str to Type. If
// there is already an entry for this name, true is returned and the symbol
// table is not modified.
//
bool Module::addTypeName(StringRef Name, const Type *Ty) {
TypeSymbolTable &ST = getTypeSymbolTable();
if (ST.lookup(Name)) return true; // Already in symtab...
// Not in symbol table? Set the name with the Symtab as an argument so the
// type knows what to update...
ST.insert(Name, Ty);
return false;
}
/// getTypeByName - Return the type with the specified name in this module, or
/// null if there is none by that name.
const Type *Module::getTypeByName(StringRef Name) const {
const TypeSymbolTable &ST = getTypeSymbolTable();
return cast_or_null<Type>(ST.lookup(Name));
}
// getTypeName - If there is at least one entry in the symbol table for the
// specified type, return it.
//
std::string Module::getTypeName(const Type *Ty) const {
const TypeSymbolTable &ST = getTypeSymbolTable();
TypeSymbolTable::const_iterator TI = ST.begin();
TypeSymbolTable::const_iterator TE = ST.end();
if ( TI == TE ) return ""; // No names for types
while (TI != TE && TI->second != Ty)
++TI;
if (TI != TE) // Must have found an entry!
return TI->first;
return ""; // Must not have found anything...
}
//===----------------------------------------------------------------------===//
// Methods to control the materialization of GlobalValues in the Module.
@ -471,3 +424,130 @@ void Module::removeLibrary(StringRef Lib) {
return;
}
}
//===----------------------------------------------------------------------===//
// Type finding functionality.
//===----------------------------------------------------------------------===//
namespace {
/// TypeFinder - Walk over a module, identifying all of the types that are
/// used by the module.
class TypeFinder {
// To avoid walking constant expressions multiple times and other IR
// objects, we keep several helper maps.
DenseSet<const Value*> VisitedConstants;
DenseSet<const Type*> VisitedTypes;
std::vector<StructType*> &StructTypes;
public:
TypeFinder(std::vector<StructType*> &structTypes)
: StructTypes(structTypes) {}
void run(const Module &M) {
// Get types from global variables.
for (Module::const_global_iterator I = M.global_begin(),
E = M.global_end(); I != E; ++I) {
incorporateType(I->getType());
if (I->hasInitializer())
incorporateValue(I->getInitializer());
}
// Get types from aliases.
for (Module::const_alias_iterator I = M.alias_begin(),
E = M.alias_end(); I != E; ++I) {
incorporateType(I->getType());
if (const Value *Aliasee = I->getAliasee())
incorporateValue(Aliasee);
}
SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst;
// Get types from functions.
for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) {
incorporateType(FI->getType());
for (Function::const_iterator BB = FI->begin(), E = FI->end();
BB != E;++BB)
for (BasicBlock::const_iterator II = BB->begin(),
E = BB->end(); II != E; ++II) {
const Instruction &I = *II;
// Incorporate the type of the instruction and all its operands.
incorporateType(I.getType());
for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end();
OI != OE; ++OI)
incorporateValue(*OI);
// Incorporate types hiding in metadata.
I.getAllMetadata(MDForInst);
for (unsigned i = 0, e = MDForInst.size(); i != e; ++i)
incorporateMDNode(MDForInst[i].second);
MDForInst.clear();
}
}
for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
E = M.named_metadata_end(); I != E; ++I) {
const NamedMDNode *NMD = I;
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i)
incorporateMDNode(NMD->getOperand(i));
}
}
private:
void incorporateType(Type *Ty) {
// Check to see if we're already visited this type.
if (!VisitedTypes.insert(Ty).second)
return;
// If this is a structure or opaque type, add a name for the type.
if (StructType *STy = dyn_cast<StructType>(Ty))
StructTypes.push_back(STy);
// Recursively walk all contained types.
for (Type::subtype_iterator I = Ty->subtype_begin(),
E = Ty->subtype_end(); I != E; ++I)
incorporateType(*I);
}
/// incorporateValue - This method is used to walk operand lists finding
/// types hiding in constant expressions and other operands that won't be
/// walked in other ways. GlobalValues, basic blocks, instructions, and
/// inst operands are all explicitly enumerated.
void incorporateValue(const Value *V) {
if (const MDNode *M = dyn_cast<MDNode>(V))
return incorporateMDNode(M);
if (!isa<Constant>(V) || isa<GlobalValue>(V)) return;
// Already visited?
if (!VisitedConstants.insert(V).second)
return;
// Check this type.
incorporateType(V->getType());
// Look in operands for types.
const User *U = cast<User>(V);
for (Constant::const_op_iterator I = U->op_begin(),
E = U->op_end(); I != E;++I)
incorporateValue(*I);
}
void incorporateMDNode(const MDNode *V) {
// Already visited?
if (!VisitedConstants.insert(V).second)
return;
// Look in operands for types.
for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i)
if (Value *Op = V->getOperand(i))
incorporateValue(Op);
}
};
} // end anonymous namespace
void Module::findUsedStructTypes(std::vector<StructType*> &StructTypes) const {
TypeFinder(StructTypes).run(*this);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,168 +0,0 @@
//===-- TypeSymbolTable.cpp - Implement the TypeSymbolTable class ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the TypeSymbolTable class for the VMCore library.
//
//===----------------------------------------------------------------------===//
#include "llvm/TypeSymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;
#define DEBUG_SYMBOL_TABLE 0
#define DEBUG_ABSTYPE 0
TypeSymbolTable::~TypeSymbolTable() {
// Drop all abstract type references in the type plane...
for (iterator TI = tmap.begin(), TE = tmap.end(); TI != TE; ++TI) {
if (TI->second->isAbstract()) // If abstract, drop the reference...
cast<DerivedType>(TI->second)->removeAbstractTypeUser(this);
}
}
std::string TypeSymbolTable::getUniqueName(StringRef BaseName) const {
std::string TryName = BaseName;
const_iterator End = tmap.end();
// See if the name exists
while (tmap.find(TryName) != End) // Loop until we find a free
TryName = BaseName.str() + utostr(++LastUnique); // name in the symbol table
return TryName;
}
// lookup a type by name - returns null on failure
Type* TypeSymbolTable::lookup(StringRef Name) const {
const_iterator TI = tmap.find(Name);
Type* result = 0;
if (TI != tmap.end())
result = const_cast<Type*>(TI->second);
return result;
}
// remove - Remove a type from the symbol table...
Type* TypeSymbolTable::remove(iterator Entry) {
assert(Entry != tmap.end() && "Invalid entry to remove!");
const Type* Result = Entry->second;
#if DEBUG_SYMBOL_TABLE
dump();
dbgs() << " Removing Value: " << *Result << "\n";
#endif
tmap.erase(Entry);
// If we are removing an abstract type, remove the symbol table from it's use
// list...
if (Result->isAbstract()) {
#if DEBUG_ABSTYPE
dbgs() << "Removing abstract type from symtab"
<< *Result << "\n";
#endif
cast<DerivedType>(Result)->removeAbstractTypeUser(this);
}
return const_cast<Type*>(Result);
}
// insert - Insert a type into the symbol table with the specified name...
void TypeSymbolTable::insert(StringRef Name, const Type* T) {
assert(T && "Can't insert null type into symbol table!");
if (tmap.insert(std::make_pair(Name, T)).second) {
// Type inserted fine with no conflict.
#if DEBUG_SYMBOL_TABLE
dump();
dbgs() << " Inserted type: " << Name << ": " << *T << "\n";
#endif
} else {
// If there is a name conflict...
// Check to see if there is a naming conflict. If so, rename this type!
std::string UniqueName = Name;
if (lookup(Name))
UniqueName = getUniqueName(Name);
#if DEBUG_SYMBOL_TABLE
dump();
dbgs() << " Inserting type: " << UniqueName << ": "
<< *T << "\n";
#endif
// Insert the tmap entry
tmap.insert(make_pair(UniqueName, T));
}
// If we are adding an abstract type, add the symbol table to it's use list.
if (T->isAbstract()) {
cast<DerivedType>(T)->addAbstractTypeUser(this);
#if DEBUG_ABSTYPE
dbgs() << "Added abstract type to ST: " << *T << "\n";
#endif
}
}
// This function is called when one of the types in the type plane are refined
void TypeSymbolTable::refineAbstractType(const DerivedType *OldType,
const Type *NewType) {
// Loop over all of the types in the symbol table, replacing any references
// to OldType with references to NewType. Note that there may be multiple
// occurrences, and although we only need to remove one at a time, it's
// faster to remove them all in one pass.
//
for (iterator I = begin(), E = end(); I != E; ++I) {
// FIXME when Types aren't const.
if (I->second == const_cast<DerivedType *>(OldType)) {
#if DEBUG_ABSTYPE
dbgs() << "Removing type " << *OldType << "\n";
#endif
OldType->removeAbstractTypeUser(this);
// TODO FIXME when types aren't const
I->second = const_cast<Type *>(NewType);
if (NewType->isAbstract()) {
#if DEBUG_ABSTYPE
dbgs() << "Added type " << *NewType << "\n";
#endif
cast<DerivedType>(NewType)->addAbstractTypeUser(this);
}
}
}
}
// Handle situation where type becomes Concreate from Abstract
void TypeSymbolTable::typeBecameConcrete(const DerivedType *AbsTy) {
// Loop over all of the types in the symbol table, dropping any abstract
// type user entries for AbsTy which occur because there are names for the
// type.
for (iterator TI = begin(), TE = end(); TI != TE; ++TI)
if (TI->second == const_cast<Type*>(static_cast<const Type*>(AbsTy)))
AbsTy->removeAbstractTypeUser(this);
}
static void DumpTypes(const std::pair<const std::string, const Type*>& T ) {
dbgs() << " '" << T.first << "' = ";
T.second->dump();
dbgs() << "\n";
}
void TypeSymbolTable::dump() const {
dbgs() << "TypeSymbolPlane: ";
for_each(tmap.begin(), tmap.end(), DumpTypes);
}

View File

@ -1,426 +0,0 @@
//===-- TypesContext.h - Types-related Context Internals ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines various helper methods and classes used by
// LLVMContextImpl for creating and managing types.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TYPESCONTEXT_H
#define LLVM_TYPESCONTEXT_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include <map>
//===----------------------------------------------------------------------===//
// Derived Type Factory Functions
//===----------------------------------------------------------------------===//
namespace llvm {
/// getSubElementHash - Generate a hash value for all of the SubType's of this
/// type. The hash value is guaranteed to be zero if any of the subtypes are
/// an opaque type. Otherwise we try to mix them in as well as possible, but do
/// not look at the subtype's subtype's.
static unsigned getSubElementHash(const Type *Ty) {
unsigned HashVal = 0;
for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
I != E; ++I) {
HashVal *= 32;
const Type *SubTy = I->get();
HashVal += SubTy->getTypeID();
switch (SubTy->getTypeID()) {
default: break;
case Type::OpaqueTyID: return 0; // Opaque -> hash = 0 no matter what.
case Type::IntegerTyID:
HashVal ^= (cast<IntegerType>(SubTy)->getBitWidth() << 3);
break;
case Type::FunctionTyID:
HashVal ^= cast<FunctionType>(SubTy)->getNumParams()*2 +
cast<FunctionType>(SubTy)->isVarArg();
break;
case Type::ArrayTyID:
HashVal ^= cast<ArrayType>(SubTy)->getNumElements();
break;
case Type::VectorTyID:
HashVal ^= cast<VectorType>(SubTy)->getNumElements();
break;
case Type::StructTyID:
HashVal ^= cast<StructType>(SubTy)->getNumElements();
break;
case Type::PointerTyID:
HashVal ^= cast<PointerType>(SubTy)->getAddressSpace();
break;
}
}
return HashVal ? HashVal : 1; // Do not return zero unless opaque subty.
}
//===----------------------------------------------------------------------===//
// Integer Type Factory...
//
class IntegerValType {
uint32_t bits;
public:
IntegerValType(uint32_t numbits) : bits(numbits) {}
static IntegerValType get(const IntegerType *Ty) {
return IntegerValType(Ty->getBitWidth());
}
static unsigned hashTypeStructure(const IntegerType *Ty) {
return (unsigned)Ty->getBitWidth();
}
inline bool operator<(const IntegerValType &IVT) const {
return bits < IVT.bits;
}
};
// PointerValType - Define a class to hold the key that goes into the TypeMap
//
class PointerValType {
const Type *ValTy;
unsigned AddressSpace;
public:
PointerValType(const Type *val, unsigned as) : ValTy(val), AddressSpace(as) {}
static PointerValType get(const PointerType *PT) {
return PointerValType(PT->getElementType(), PT->getAddressSpace());
}
static unsigned hashTypeStructure(const PointerType *PT) {
return getSubElementHash(PT);
}
bool operator<(const PointerValType &MTV) const {
if (AddressSpace < MTV.AddressSpace) return true;
return AddressSpace == MTV.AddressSpace && ValTy < MTV.ValTy;
}
};
//===----------------------------------------------------------------------===//
// Array Type Factory...
//
class ArrayValType {
const Type *ValTy;
uint64_t Size;
public:
ArrayValType(const Type *val, uint64_t sz) : ValTy(val), Size(sz) {}
static ArrayValType get(const ArrayType *AT) {
return ArrayValType(AT->getElementType(), AT->getNumElements());
}
static unsigned hashTypeStructure(const ArrayType *AT) {
return (unsigned)AT->getNumElements();
}
inline bool operator<(const ArrayValType &MTV) const {
if (Size < MTV.Size) return true;
return Size == MTV.Size && ValTy < MTV.ValTy;
}
};
//===----------------------------------------------------------------------===//
// Vector Type Factory...
//
class VectorValType {
const Type *ValTy;
unsigned Size;
public:
VectorValType(const Type *val, int sz) : ValTy(val), Size(sz) {}
static VectorValType get(const VectorType *PT) {
return VectorValType(PT->getElementType(), PT->getNumElements());
}
static unsigned hashTypeStructure(const VectorType *PT) {
return PT->getNumElements();
}
inline bool operator<(const VectorValType &MTV) const {
if (Size < MTV.Size) return true;
return Size == MTV.Size && ValTy < MTV.ValTy;
}
};
// StructValType - Define a class to hold the key that goes into the TypeMap
//
class StructValType {
std::vector<const Type*> ElTypes;
bool packed;
public:
StructValType(ArrayRef<const Type*> args, bool isPacked)
: ElTypes(args.vec()), packed(isPacked) {}
static StructValType get(const StructType *ST) {
std::vector<const Type *> ElTypes;
ElTypes.reserve(ST->getNumElements());
for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
ElTypes.push_back(ST->getElementType(i));
return StructValType(ElTypes, ST->isPacked());
}
static unsigned hashTypeStructure(const StructType *ST) {
return ST->getNumElements();
}
inline bool operator<(const StructValType &STV) const {
if (ElTypes < STV.ElTypes) return true;
else if (ElTypes > STV.ElTypes) return false;
else return (int)packed < (int)STV.packed;
}
};
// FunctionValType - Define a class to hold the key that goes into the TypeMap
//
class FunctionValType {
const Type *RetTy;
std::vector<const Type*> ArgTypes;
bool isVarArg;
public:
FunctionValType(const Type *ret, ArrayRef<const Type*> args, bool isVA)
: RetTy(ret), ArgTypes(args.vec()), isVarArg(isVA) {}
static FunctionValType get(const FunctionType *FT);
static unsigned hashTypeStructure(const FunctionType *FT) {
unsigned Result = FT->getNumParams()*2 + FT->isVarArg();
return Result;
}
inline bool operator<(const FunctionValType &MTV) const {
if (RetTy < MTV.RetTy) return true;
if (RetTy > MTV.RetTy) return false;
if (isVarArg < MTV.isVarArg) return true;
if (isVarArg > MTV.isVarArg) return false;
if (ArgTypes < MTV.ArgTypes) return true;
if (ArgTypes > MTV.ArgTypes) return false;
return false;
}
};
class TypeMapBase {
protected:
/// TypesByHash - Keep track of types by their structure hash value. Note
/// that we only keep track of types that have cycles through themselves in
/// this map.
///
std::multimap<unsigned, PATypeHolder> TypesByHash;
~TypeMapBase() {
// PATypeHolder won't destroy non-abstract types.
// We can't destroy them by simply iterating, because
// they may contain references to each-other.
for (std::multimap<unsigned, PATypeHolder>::iterator I
= TypesByHash.begin(), E = TypesByHash.end(); I != E; ++I) {
Type *Ty = const_cast<Type*>(I->second.Ty);
I->second.destroy();
// We can't invoke destroy or delete, because the type may
// contain references to already freed types.
// So we have to destruct the object the ugly way.
if (Ty) {
Ty->AbstractTypeUsers.clear();
static_cast<const Type*>(Ty)->Type::~Type();
operator delete(Ty);
}
}
}
public:
void RemoveFromTypesByHash(unsigned Hash, const Type *Ty) {
std::multimap<unsigned, PATypeHolder>::iterator I =
TypesByHash.lower_bound(Hash);
for (; I != TypesByHash.end() && I->first == Hash; ++I) {
if (I->second == Ty) {
TypesByHash.erase(I);
return;
}
}
// This must be do to an opaque type that was resolved. Switch down to hash
// code of zero.
assert(Hash && "Didn't find type entry!");
RemoveFromTypesByHash(0, Ty);
}
/// TypeBecameConcrete - When Ty gets a notification that TheType just became
/// concrete, drop uses and make Ty non-abstract if we should.
void TypeBecameConcrete(DerivedType *Ty, const DerivedType *TheType) {
// If the element just became concrete, remove 'ty' from the abstract
// type user list for the type. Do this for as many times as Ty uses
// OldType.
for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
I != E; ++I)
if (I->get() == TheType)
TheType->removeAbstractTypeUser(Ty);
// If the type is currently thought to be abstract, rescan all of our
// subtypes to see if the type has just become concrete! Note that this
// may send out notifications to AbstractTypeUsers that types become
// concrete.
if (Ty->isAbstract())
Ty->PromoteAbstractToConcrete();
}
};
// TypeMap - Make sure that only one instance of a particular type may be
// created on any given run of the compiler... note that this involves updating
// our map if an abstract type gets refined somehow.
//
template<class ValType, class TypeClass>
class TypeMap : public TypeMapBase {
std::map<ValType, PATypeHolder> Map;
public:
typedef typename std::map<ValType, PATypeHolder>::iterator iterator;
inline TypeClass *get(const ValType &V) {
iterator I = Map.find(V);
return I != Map.end() ? cast<TypeClass>((Type*)I->second.get()) : 0;
}
inline void add(const ValType &V, TypeClass *Ty) {
Map.insert(std::make_pair(V, Ty));
// If this type has a cycle, remember it.
TypesByHash.insert(std::make_pair(ValType::hashTypeStructure(Ty), Ty));
print("add");
}
/// RefineAbstractType - This method is called after we have merged a type
/// with another one. We must now either merge the type away with
/// some other type or reinstall it in the map with it's new configuration.
void RefineAbstractType(TypeClass *Ty, const DerivedType *OldType,
const Type *NewType) {
#ifdef DEBUG_MERGE_TYPES
DEBUG(dbgs() << "RefineAbstractType(" << (void*)OldType << "[" << *OldType
<< "], " << (void*)NewType << " [" << *NewType << "])\n");
#endif
// Otherwise, we are changing one subelement type into another. Clearly the
// OldType must have been abstract, making us abstract.
assert(Ty->isAbstract() && "Refining a non-abstract type!");
assert(OldType != NewType);
// Make a temporary type holder for the type so that it doesn't disappear on
// us when we erase the entry from the map.
PATypeHolder TyHolder = Ty;
// The old record is now out-of-date, because one of the children has been
// updated. Remove the obsolete entry from the map.
unsigned NumErased = Map.erase(ValType::get(Ty));
assert(NumErased && "Element not found!"); (void)NumErased;
// Remember the structural hash for the type before we start hacking on it,
// in case we need it later.
unsigned OldTypeHash = ValType::hashTypeStructure(Ty);
// Find the type element we are refining... and change it now!
for (unsigned i = 0, e = Ty->getNumContainedTypes(); i != e; ++i)
if (Ty->ContainedTys[i] == OldType)
Ty->ContainedTys[i] = NewType;
unsigned NewTypeHash = ValType::hashTypeStructure(Ty);
// If there are no cycles going through this node, we can do a simple,
// efficient lookup in the map, instead of an inefficient nasty linear
// lookup.
if (!TypeHasCycleThroughItself(Ty)) {
typename std::map<ValType, PATypeHolder>::iterator I;
bool Inserted;
tie(I, Inserted) = Map.insert(std::make_pair(ValType::get(Ty), Ty));
if (!Inserted) {
// Refined to a different type altogether?
RemoveFromTypesByHash(OldTypeHash, Ty);
// We already have this type in the table. Get rid of the newly refined
// type.
TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
Ty->refineAbstractTypeTo(NewTy);
return;
}
} else {
// Now we check to see if there is an existing entry in the table which is
// structurally identical to the newly refined type. If so, this type
// gets refined to the pre-existing type.
//
std::multimap<unsigned, PATypeHolder>::iterator I, E, Entry;
tie(I, E) = TypesByHash.equal_range(NewTypeHash);
Entry = E;
for (; I != E; ++I) {
if (I->second == Ty) {
// Remember the position of the old type if we see it in our scan.
Entry = I;
continue;
}
if (!TypesEqual(Ty, I->second))
continue;
TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
// Remove the old entry form TypesByHash. If the hash values differ
// now, remove it from the old place. Otherwise, continue scanning
// within this hashcode to reduce work.
if (NewTypeHash != OldTypeHash) {
RemoveFromTypesByHash(OldTypeHash, Ty);
} else {
if (Entry == E) {
// Find the location of Ty in the TypesByHash structure if we
// haven't seen it already.
while (I->second != Ty) {
++I;
assert(I != E && "Structure doesn't contain type??");
}
Entry = I;
}
TypesByHash.erase(Entry);
}
Ty->refineAbstractTypeTo(NewTy);
return;
}
// If there is no existing type of the same structure, we reinsert an
// updated record into the map.
Map.insert(std::make_pair(ValType::get(Ty), Ty));
}
// If the hash codes differ, update TypesByHash
if (NewTypeHash != OldTypeHash) {
RemoveFromTypesByHash(OldTypeHash, Ty);
TypesByHash.insert(std::make_pair(NewTypeHash, Ty));
}
// If the type is currently thought to be abstract, rescan all of our
// subtypes to see if the type has just become concrete! Note that this
// may send out notifications to AbstractTypeUsers that types become
// concrete.
if (Ty->isAbstract())
Ty->PromoteAbstractToConcrete();
}
void print(const char *Arg) const {
#ifdef DEBUG_MERGE_TYPES
DEBUG(dbgs() << "TypeMap<>::" << Arg << " table contents:\n");
unsigned i = 0;
for (typename std::map<ValType, PATypeHolder>::const_iterator I
= Map.begin(), E = Map.end(); I != E; ++I)
DEBUG(dbgs() << " " << (++i) << ". " << (void*)I->second.get() << " "
<< *I->second.get() << "\n");
#endif
}
void dump() const { print("dump output"); }
};
}
#endif

View File

@ -35,22 +35,21 @@ using namespace llvm;
// Value Class
//===----------------------------------------------------------------------===//
static inline const Type *checkType(const Type *Ty) {
static inline Type *checkType(const Type *Ty) {
assert(Ty && "Value defined with a null type: Error!");
return Ty;
return const_cast<Type*>(Ty);
}
Value::Value(const Type *ty, unsigned scid)
: SubclassID(scid), HasValueHandle(0),
SubclassOptionalData(0), SubclassData(0), VTy(checkType(ty)),
SubclassOptionalData(0), SubclassData(0), VTy((Type*)checkType(ty)),
UseList(0), Name(0) {
// FIXME: Why isn't this in the subclass gunk??
if (isa<CallInst>(this) || isa<InvokeInst>(this))
assert((VTy->isFirstClassType() || VTy->isVoidTy() ||
ty->isOpaqueTy() || VTy->isStructTy()) &&
"invalid CallInst type!");
assert((VTy->isFirstClassType() || VTy->isVoidTy() || VTy->isStructTy()) &&
"invalid CallInst type!");
else if (!isa<Constant>(this) && !isa<BasicBlock>(this))
assert((VTy->isFirstClassType() || VTy->isVoidTy() ||
ty->isOpaqueTy()) &&
assert((VTy->isFirstClassType() || VTy->isVoidTy()) &&
"Cannot create non-first-class values except for constants!");
}

View File

@ -49,7 +49,6 @@
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/ValueTypes.h"
@ -109,54 +108,6 @@ INITIALIZE_PASS(PreVerifier, "preverify", "Preliminary module verification",
static char &PreVerifyID = PreVerifier::ID;
namespace {
class TypeSet : public AbstractTypeUser {
public:
TypeSet() {}
/// Insert a type into the set of types.
bool insert(const Type *Ty) {
if (!Types.insert(Ty))
return false;
if (Ty->isAbstract())
Ty->addAbstractTypeUser(this);
return true;
}
// Remove ourselves as abstract type listeners for any types that remain
// abstract when the TypeSet is destroyed.
~TypeSet() {
for (SmallSetVector<const Type *, 16>::iterator I = Types.begin(),
E = Types.end(); I != E; ++I) {
const Type *Ty = *I;
if (Ty->isAbstract())
Ty->removeAbstractTypeUser(this);
}
}
// Abstract type user interface.
/// Remove types from the set when refined. Do not insert the type it was
/// refined to because that type hasn't been verified yet.
void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
Types.remove(OldTy);
OldTy->removeAbstractTypeUser(this);
}
/// Stop listening for changes to a type which is no longer abstract.
void typeBecameConcrete(const DerivedType *AbsTy) {
AbsTy->removeAbstractTypeUser(this);
}
void dump() const {}
private:
SmallSetVector<const Type *, 16> Types;
// Disallow copying.
TypeSet(const TypeSet &);
TypeSet &operator=(const TypeSet &);
};
struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
static char ID; // Pass ID, replacement for typeid
bool Broken; // Is this module found to be broken?
@ -176,9 +127,6 @@ namespace {
/// an instruction in the same block.
SmallPtrSet<Instruction*, 16> InstsInThisBlock;
/// Types - keep track of the types that have been checked already.
TypeSet Types;
/// MDNodes - keep track of the metadata nodes that have been checked
/// already.
SmallPtrSet<MDNode *, 32> MDNodes;
@ -199,7 +147,6 @@ namespace {
bool doInitialization(Module &M) {
Mod = &M;
Context = &M.getContext();
verifyTypeSymbolTable(M.getTypeSymbolTable());
// If this is a real pass, in a pass manager, we must abort before
// returning back to the pass manager, or else the pass manager may try to
@ -285,7 +232,6 @@ namespace {
// Verification methods...
void verifyTypeSymbolTable(TypeSymbolTable &ST);
void visitGlobalValue(GlobalValue &GV);
void visitGlobalVariable(GlobalVariable &GV);
void visitGlobalAlias(GlobalAlias &GA);
@ -345,7 +291,6 @@ namespace {
bool isReturnValue, const Value *V);
void VerifyFunctionAttrs(const FunctionType *FT, const AttrListPtr &Attrs,
const Value *V);
void VerifyType(const Type *Ty);
void WriteValue(const Value *V) {
if (!V) return;
@ -359,8 +304,7 @@ namespace {
void WriteType(const Type *T) {
if (!T) return;
MessagesStr << ' ';
WriteTypeSymbolic(MessagesStr, T, Mod);
MessagesStr << ' ' << *T;
}
@ -568,11 +512,6 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) {
}
}
void Verifier::verifyTypeSymbolTable(TypeSymbolTable &ST) {
for (TypeSymbolTable::iterator I = ST.begin(), E = ST.end(); I != E; ++I)
VerifyType(I->second);
}
// VerifyParameterAttrs - Check the given attributes for an argument or return
// value of the specified type. The value V is printed in error messages.
void Verifier::VerifyParameterAttrs(Attributes Attrs, const Type *Ty,
@ -1192,11 +1131,11 @@ void Verifier::VerifyCallSite(CallSite CS) {
}
// Verify that there's no metadata unless it's a direct call to an intrinsic.
if (!CS.getCalledFunction() ||
if (CS.getCalledFunction() == 0 ||
!CS.getCalledFunction()->getName().startswith("llvm.")) {
for (FunctionType::param_iterator PI = FTy->param_begin(),
PE = FTy->param_end(); PI != PE; ++PI)
Assert1(!PI->get()->isMetadataTy(),
Assert1(!(*PI)->isMetadataTy(),
"Function has metadata parameter but isn't an intrinsic", I);
}
@ -1542,69 +1481,6 @@ void Verifier::visitInstruction(Instruction &I) {
}
}
InstsInThisBlock.insert(&I);
VerifyType(I.getType());
}
/// VerifyType - Verify that a type is well formed.
///
void Verifier::VerifyType(const Type *Ty) {
if (!Types.insert(Ty)) return;
Assert1(Context == &Ty->getContext(),
"Type context does not match Module context!", Ty);
switch (Ty->getTypeID()) {
case Type::FunctionTyID: {
const FunctionType *FTy = cast<FunctionType>(Ty);
const Type *RetTy = FTy->getReturnType();
Assert2(FunctionType::isValidReturnType(RetTy),
"Function type with invalid return type", RetTy, FTy);
VerifyType(RetTy);
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) {
const Type *ElTy = FTy->getParamType(i);
Assert2(FunctionType::isValidArgumentType(ElTy),
"Function type with invalid parameter type", ElTy, FTy);
VerifyType(ElTy);
}
break;
}
case Type::StructTyID: {
const StructType *STy = cast<StructType>(Ty);
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
const Type *ElTy = STy->getElementType(i);
Assert2(StructType::isValidElementType(ElTy),
"Structure type with invalid element type", ElTy, STy);
VerifyType(ElTy);
}
break;
}
case Type::ArrayTyID: {
const ArrayType *ATy = cast<ArrayType>(Ty);
Assert1(ArrayType::isValidElementType(ATy->getElementType()),
"Array type with invalid element type", ATy);
VerifyType(ATy->getElementType());
break;
}
case Type::PointerTyID: {
const PointerType *PTy = cast<PointerType>(Ty);
Assert1(PointerType::isValidElementType(PTy->getElementType()),
"Pointer type with invalid element type", PTy);
VerifyType(PTy->getElementType());
break;
}
case Type::VectorTyID: {
const VectorType *VTy = cast<VectorType>(Ty);
Assert1(VectorType::isValidElementType(VTy->getElementType()),
"Vector type with invalid element type", VTy);
VerifyType(VTy->getElementType());
break;
}
default:
break;
}
}
// Flags used by TableGen to mark intrinsic parameters with the

View File

@ -3,12 +3,10 @@
;
; RUN: llvm-as < %s | llvm-dis | llvm-as
%ty = type void (i32)
declare %ty* @foo()
declare void (i32)* @foo()
define void @test() {
call %ty* ()* @foo( ) ; <%ty*>:1 [#uses=0]
call void (i32)* ()* @foo( ) ; <%ty*>:1 [#uses=0]
ret void
}

View File

@ -4,4 +4,4 @@
@X1 = external global %T*
@X2 = external global i32*
%T = type i32
%T = type {i32}

View File

@ -1,4 +1,4 @@
; RUN: not llvm-as < %s >/dev/null |& grep {constant expression type mismatch}
; RUN: not llvm-as < %s >/dev/null |& grep {struct initializer doesn't match struct element type}
; Test the case of a misformed constant initializer
; This should cause an assembler error, not an assertion failure!
constant { i32 } { float 1.0 }

View File

@ -1,4 +1,4 @@
; Found by inspection of the code
; RUN: not llvm-as < %s > /dev/null |& grep {constant expression type mismatch}
; RUN: not llvm-as < %s > /dev/null |& grep {initializer with struct type has wrong # elements}
global {} { i32 7, float 1.0, i32 7, i32 8 }

View File

@ -1,4 +1,4 @@
; Test for PR463. This program is erroneous, but should not crash llvm-as.
; RUN: not llvm-as %s -o /dev/null |& grep {invalid type for null constant}
; RUN: not llvm-as %s -o /dev/null |& grep {use of undefined type named 'struct.none'}
@.FOO = internal global %struct.none zeroinitializer

View File

@ -9,13 +9,13 @@
;; Verify that i16 indices work.
@x = external global {i32, i32}
@y = global i32* getelementptr ({i32, i32}* @x, i16 42, i32 0)
; CHECK: @y = global i32* getelementptr (%0* @x, i16 42, i32 0)
@y = global i32* getelementptr ({ i32, i32 }* @x, i16 42, i32 0)
; CHECK: @y = global i32* getelementptr ({ i32, i32 }* @x, i16 42, i32 0)
; see if i92 indices work too.
define i32 *@test({i32, i32}* %t, i92 %n) {
; CHECK: @test
; CHECK: %B = getelementptr %0* %t, i92 %n, i32 0
; CHECK: %B = getelementptr { i32, i32 }* %t, i92 %n, i32 0
%B = getelementptr {i32, i32}* %t, i92 %n, i32 0
ret i32* %B
}

View File

@ -1,7 +1,7 @@
; RUN: llc %s -o -
; PR6332
%struct.AVCodecTag = type opaque
%struct.AVCodecTag = type {}
@ff_codec_bmp_tags = external global [0 x %struct.AVCodecTag]
@tags = global [1 x %struct.AVCodecTag*] [%struct.AVCodecTag* getelementptr
inbounds ([0 x %struct.AVCodecTag]* @ff_codec_bmp_tags, i32 0, i32 0)]

View File

@ -22,6 +22,7 @@ module asm "\09.ident\09\22GCC: (GNU) 4.5.0 20100212 (experimental) LLVM: 95975\
%0 = type { %"union gimple_statement_d"* }
%"BITMAP_WORD[]" = type [2 x i64]
%"uchar[]" = type [1 x i8]
%"char[]" = type [4 x i8]
%"enum dom_state[]" = type [2 x i32]
%"int[]" = type [4 x i32]
@ -61,6 +62,7 @@ module asm "\09.ident\09\22GCC: (GNU) 4.5.0 20100212 (experimental) LLVM: 95975\
%"struct gimple_seq_d" = type { %"struct gimple_seq_node_d"*, %"struct gimple_seq_node_d"*, %"struct gimple_seq_d"* }
%"struct gimple_seq_node_d" = type { %"union gimple_statement_d"*, %"struct gimple_seq_node_d"*, %"struct gimple_seq_node_d"* }
%"struct gimple_statement_base" = type { i8, i8, i16, i32, i32, i32, %"struct basic_block_def"*, %"union tree_node"* }
%"struct phi_arg_d[]" = type [1 x %"struct phi_arg_d"]
%"struct gimple_statement_phi" = type { %"struct gimple_statement_base", i32, i32, %"union tree_node"*, %"struct phi_arg_d[]" }
%"struct htab" = type { i32 (i8*)*, i32 (i8*, i8*)*, void (i8*)*, i8**, i64, i64, i64, i32, i32, i8* (i64, i64)*, void (i8*)*, i8*, i8* (i8*, i64, i64)*, void (i8*, i8*)*, i32 }
%"struct iv" = type { %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, i8, i8, i32 }
@ -78,7 +80,6 @@ module asm "\09.ident\09\22GCC: (GNU) 4.5.0 20100212 (experimental) LLVM: 95975\
%"struct object_block" = type { %"union section"*, i32, i64, %"struct VEC_rtx_gc"*, %"struct VEC_rtx_gc"* }
%"struct obstack" = type { i64, %"struct _obstack_chunk"*, i8*, i8*, i8*, i64, i32, %"struct _obstack_chunk"* (i8*, i64)*, void (i8*, %"struct _obstack_chunk"*)*, i8*, i8 }
%"struct phi_arg_d" = type { %"struct ssa_use_operand_d", %"union tree_node"*, i32 }
%"struct phi_arg_d[]" = type [1 x %"struct phi_arg_d"]
%"struct pointer_map_t" = type opaque
%"struct pt_solution" = type { i8, %"struct bitmap_head_def"* }
%"struct rtx_def" = type { i16, i8, i8, %"union u" }
@ -98,7 +99,6 @@ module asm "\09.ident\09\22GCC: (GNU) 4.5.0 20100212 (experimental) LLVM: 95975\
%"struct unnamed_section" = type { %"struct section_common", void (i8*)*, i8*, %"union section"* }
%"struct use_optype_d" = type { %"struct use_optype_d"*, %"struct ssa_use_operand_d" }
%"struct version_info" = type { %"union tree_node"*, %"struct iv"*, i8, i32, i8 }
%"uchar[]" = type [1 x i8]
%"union basic_block_il_dependent" = type { %"struct gimple_bb_info"* }
%"union edge_def_insns" = type { %"struct gimple_seq_d"* }
%"union gimple_statement_d" = type { %"struct gimple_statement_phi" }

View File

@ -5,11 +5,11 @@ target triple = "x86_64-unknown-linux-gnu"
module asm "\09.ident\09\22GCC: (GNU) 4.5.2 20100914 (prerelease) LLVM: 114628\22"
%"int[]" = type [4 x i32]
%0 = type { %"int[]" }
%float = type float
%"float[]" = type [4 x float]
%int = type i32
%"int[]" = type [4 x i32]
%"long unsigned int" = type i64
define void @swizzle(i8* %a, %0* %b, %0* %c) nounwind {

View File

@ -5,7 +5,7 @@
; This is basically this code on x86-64:
; _Complex long double test() { return 1.0; }
define {x86_fp80, x86_fp80} @test() {
define %0 @test() {
%A = fpext double 1.0 to x86_fp80
%B = fpext double 0.0 to x86_fp80
%mrv = insertvalue %0 undef, x86_fp80 %A, 0
@ -18,7 +18,7 @@ define {x86_fp80, x86_fp80} @test() {
; fld1
; fld %st(0)
; ret
define {x86_fp80, x86_fp80} @test2() {
define %0 @test2() {
%A = fpext double 1.0 to x86_fp80
%mrv = insertvalue %0 undef, x86_fp80 %A, 0
%mrv1 = insertvalue %0 %mrv, x86_fp80 %A, 1
@ -27,39 +27,39 @@ define {x86_fp80, x86_fp80} @test2() {
; Uses both values.
define void @call1(x86_fp80 *%P1, x86_fp80 *%P2) {
%a = call {x86_fp80,x86_fp80} @test()
%b = extractvalue {x86_fp80,x86_fp80} %a, 0
%a = call %0 @test()
%b = extractvalue %0 %a, 0
store x86_fp80 %b, x86_fp80* %P1
%c = extractvalue {x86_fp80,x86_fp80} %a, 1
%c = extractvalue %0 %a, 1
store x86_fp80 %c, x86_fp80* %P2
ret void
}
; Uses both values, requires fxch
define void @call2(x86_fp80 *%P1, x86_fp80 *%P2) {
%a = call {x86_fp80,x86_fp80} @test()
%b = extractvalue {x86_fp80,x86_fp80} %a, 1
%a = call %0 @test()
%b = extractvalue %0 %a, 1
store x86_fp80 %b, x86_fp80* %P1
%c = extractvalue {x86_fp80,x86_fp80} %a, 0
%c = extractvalue %0 %a, 0
store x86_fp80 %c, x86_fp80* %P2
ret void
}
; Uses ST(0), ST(1) is dead but must be popped.
define void @call3(x86_fp80 *%P1, x86_fp80 *%P2) {
%a = call {x86_fp80,x86_fp80} @test()
%b = extractvalue {x86_fp80,x86_fp80} %a, 0
%a = call %0 @test()
%b = extractvalue %0 %a, 0
store x86_fp80 %b, x86_fp80* %P1
ret void
}
; Uses ST(1), ST(0) is dead and must be popped.
define void @call4(x86_fp80 *%P1, x86_fp80 *%P2) {
%a = call {x86_fp80,x86_fp80} @test()
%a = call %0 @test()
%c = extractvalue {x86_fp80,x86_fp80} %a, 1
%c = extractvalue %0 %a, 1
store x86_fp80 %c, x86_fp80* %P2
ret void
}

View File

@ -1,6 +1,7 @@
; RUN: llc < %s -march=x86
; PR3317
%VT = type [0 x i32 (...)*]
%ArraySInt16 = type { %JavaObject, i8*, [0 x i16] }
%ArraySInt8 = type { %JavaObject, i8*, [0 x i8] }
%Attribut = type { %ArraySInt16*, i32, i32 }
@ -14,7 +15,6 @@
%JavaObject = type { %VT*, %JavaCommonClass*, i8* }
%TaskClassMirror = type { i32, i8* }
%UTF8 = type { %JavaObject, i8*, [0 x i16] }
%VT = type [0 x i32 (...)*]
declare void @jnjvmNullPointerException()

View File

@ -3,7 +3,7 @@
; RUN: diff %t1.ll %t2.ll
@MyVar = external global i32 ; <i32*> [#uses=1]
@MyIntList = external global { \2*, i32 } ; <{ \2*, i32 }*> [#uses=1]
@MyIntList = external global { i32*, i32 } ; <{ \2*, i32 }*> [#uses=1]
external global i32 ; <i32*>:0 [#uses=0]
@AConst = constant i32 123 ; <i32*> [#uses=0]
@AString = constant [4 x i8] c"test" ; <[4 x i8]*> [#uses=0]
@ -11,7 +11,7 @@ external global i32 ; <i32*>:0 [#uses=0]
define i32 @foo(i32 %blah) {
store i32 5, i32* @MyVar
%idx = getelementptr { \2*, i32 }* @MyIntList, i64 0, i32 1 ; <i32*> [#uses=1]
%idx = getelementptr { i32*, i32 }* @MyIntList, i64 0, i32 1 ; <i32*> [#uses=1]
store i32 12, i32* %idx
ret i32 %blah
}

View File

@ -7,13 +7,13 @@
%inners = type { float, { i8 } }
%struct = type { i32, %inners, i64 }
%fwdref = type { %fwd* }
%fwd = type %fwdref*
%fwdref = type { %fwd* }
; same as above with unnamed types
%0 = type { %1* }
%1 = type %0*
%test = type %1
%0 = type { %1* }
%test2 = type [2 x i32]
;%x = type %undefined*

View File

@ -5,7 +5,7 @@
#include <mmintrin.h>
#include <stdint.h>
// CHECK: type { x86_mmx, x86_mmx, x86_mmx, x86_mmx, x86_mmx, x86_mmx, x86_mmx }
// CHECK: { x86_mmx, x86_mmx, x86_mmx, x86_mmx, x86_mmx, x86_mmx, x86_mmx }
void foo(__m64 vfill) {
__m64 v1, v2, v3, v4, v5, v6, v7;

View File

@ -5,5 +5,6 @@
; RUN: llvm-as < %s > %t.2.bc
; RUN: llvm-link %t.1.bc %t.2.bc -S | grep {%Ty } | not grep opaque
%Ty = type i32
%Ty = type {i32}
@GV = global %Ty* null

View File

@ -1,5 +1,5 @@
; RUN: llvm-as < %s > %t.out1.bc
; RUN: echo {@S = external global \{ i32, opaque* \} declare void @F(opaque*)}\
; RUN: echo {%T1 = type opaque %T2 = type opaque @S = external global \{ i32, %T1* \} declare void @F(%T2*)}\
; RUN: | llvm-as > %t.out2.bc
; RUN: llvm-link %t.out1.bc %t.out2.bc -S | not grep opaque

View File

@ -5,5 +5,6 @@
; RUN: echo "%M = type { %M*, i32* }" | llvm-as > %t.out2.bc
; RUN: llvm-link %t.out1.bc %t.out2.bc
%M = type { %M*, opaque* }
%T1 = type opaque
%M = type { %M*, %T1* }

View File

@ -1,5 +1,5 @@
; RUN: llvm-as < %s > %t.out1.bc
; RUN: echo "%M = type i32" | llvm-as > %t.out2.bc
; RUN: echo "%M = type { i32} " | llvm-as > %t.out2.bc
; RUN: llvm-link %t.out2.bc %t.out1.bc
%M = type opaque

View File

@ -1,42 +1,95 @@
; RUN: llvm-as < %s > %t.bc
; RUN: llvm-as < %p/testlink2.ll > %t2.bc
; RUN: llvm-link %t.bc %t2.bc
; RUN: llvm-link %t.bc %t2.bc -S | FileCheck %s
; CHECK: %Ty2 = type { %Ty1* }
; CHECK: %Ty1 = type { %Ty2* }
%Ty1 = type opaque
%Ty2 = type { %Ty1* }
; CHECK: %intlist = type { %intlist*, i32 }
%intlist = type { %intlist*, i32 }
; The uses of intlist in the other file should be remapped.
; CHECK-NOT: {{%intlist.[0-9]}}
%Struct1 = type opaque
@S1GV = external global %Struct1*
@GVTy1 = external global %Ty1*
@GVTy2 = global %Ty2* null
; This should stay the same
; CHECK: @MyIntList = global %intlist { %intlist* null, i32 17 }
@MyIntList = global %intlist { %intlist* null, i32 17 }
; Nothing to link here.
; CHECK: @0 = external global i32
@0 = external global i32
; CHECK: @Inte = global i32 1
@Inte = global i32 1
; Intern1 is intern in both files, rename testlink2's.
; CHECK: @Intern1 = internal constant i32 42
@Intern1 = internal constant i32 42
; This should get renamed since there is a definition that is non-internal in
; the other module.
; CHECK: @Intern2{{[0-9]+}} = internal constant i32 792
@Intern2 = internal constant i32 792
; CHECK: @MyVarPtr = linkonce global { i32* } { i32* @MyVar }
@MyVarPtr = linkonce global { i32* } { i32* @MyVar }
; CHECK: @MyVar = global i32 4
@MyVar = external global i32
; Take value from other module.
; CHECK: AConst = constant i32 1234
@AConst = linkonce constant i32 123
; Renamed version of Intern1.
; CHECK: @Intern1{{[0-9]+}} = internal constant i32 52
; Globals linked from testlink2.
; CHECK: @Intern2 = constant i32 12345
; CHECK: @MyIntListPtr = constant
; CHECK: @1 = constant i32 412
@MyVar = external global i32 ; <i32*> [#uses=3]
@MyIntList = global { \2*, i32 } { { \2*, i32 }* null, i32 17 } ; <{ \2*, i32 }*> [#uses=1]
external global i32 ; <i32*>:0 [#uses=0]
@Inte = global i32 1 ; <i32*> [#uses=0]
@AConst = linkonce constant i32 123 ; <i32*> [#uses=0]
@Intern1 = internal constant i32 42 ; <i32*> [#uses=0]
@Intern2 = internal constant i32 792 ; <i32*> [#uses=0]
@MyVarPtr = linkonce global { i32* } { i32* @MyVar } ; <{ i32* }*> [#uses=0]
declare i32 @foo(i32)
declare void @print(i32)
define void @main() {
%v1 = load i32* @MyVar ; <i32> [#uses=1]
call void @print( i32 %v1 )
%idx = getelementptr { \2*, i32 }* @MyIntList, i64 0, i32 1 ; <i32*> [#uses=2]
%v2 = load i32* %idx ; <i32> [#uses=1]
call void @print( i32 %v2 )
call i32 @foo( i32 5 ) ; <i32>:1 [#uses=0]
%v3 = load i32* @MyVar ; <i32> [#uses=1]
call void @print( i32 %v3 )
%v4 = load i32* %idx ; <i32> [#uses=1]
call void @print( i32 %v4 )
ret void
%v1 = load i32* @MyVar
call void @print(i32 %v1)
%idx = getelementptr %intlist* @MyIntList, i64 0, i32 1
%v2 = load i32* %idx
call void @print(i32 %v2)
%1 = call i32 @foo(i32 5)
%v3 = load i32* @MyVar
call void @print(i32 %v3)
%v4 = load i32* %idx
call void @print(i32 %v4)
ret void
}
define internal void @testintern() {
ret void
ret void
}
define internal void @Testintern() {
ret void
ret void
}
define void @testIntern() {
ret void
ret void
}

View File

@ -2,40 +2,54 @@
;
; RUN: true
@MyVar = global i32 4 ; <i32*> [#uses=2]
@MyIntList = external global { \2*, i32 } ; <{ \2*, i32 }*> [#uses=2]
@AConst = constant i32 123 ; <i32*> [#uses=0]
%intlist = type { %intlist*, i32 }
%Ty1 = type { %Ty2* }
%Ty2 = type opaque
@GVTy1 = global %Ty1* null
@GVTy2 = external global %Ty2*
@MyVar = global i32 4
@MyIntList = external global %intlist
@AConst = constant i32 1234
;; Intern in both testlink[12].ll
@Intern1 = internal constant i32 52 ; <i32*> [#uses=0]
@Intern1 = internal constant i32 52
;; Intern in one but not in other
@Intern2 = constant i32 12345 ; <i32*> [#uses=0]
@Intern2 = constant i32 12345
@MyIntListPtr = constant { { \2*, i32 }* } { { \2*, i32 }* @MyIntList } ; <{ { \2*, i32 }* }*> [#uses=0]
@MyVarPtr = linkonce global { i32* } { i32* @MyVar } ; <{ i32* }*> [#uses=0]
constant i32 412 ; <i32*>:0 [#uses=1]
@MyIntListPtr = constant { %intlist* } { %intlist* @MyIntList }
@MyVarPtr = linkonce global { i32* } { i32* @MyVar }
@0 = constant i32 412
; Provides definition of Struct1 and of S1GV.
%Struct1 = type { i32 }
@S1GV = global %Struct1* null
define i32 @foo(i32 %blah) {
store i32 %blah, i32* @MyVar
%idx = getelementptr { \2*, i32 }* @MyIntList, i64 0, i32 1 ; <i32*> [#uses=1]
store i32 12, i32* %idx
%ack = load i32* @0 ; <i32> [#uses=1]
%fzo = add i32 %ack, %blah ; <i32> [#uses=1]
ret i32 %fzo
store i32 %blah, i32* @MyVar
%idx = getelementptr %intlist* @MyIntList, i64 0, i32 1
store i32 12, i32* %idx
%ack = load i32* @0
%fzo = add i32 %ack, %blah
ret i32 %fzo
}
declare void @unimp(float, double)
define internal void @testintern() {
ret void
ret void
}
define void @Testintern() {
ret void
ret void
}
define internal void @testIntern() {
ret void
ret void
}

View File

@ -10,15 +10,15 @@
@c = common unnamed_addr global i32 0
; CHECK: @c = common unnamed_addr global i32 0
@d = external global i32
; CHECK: @d = global i32 42
; CHECK: @d = unnamed_addr global i32 42
@e = external unnamed_addr global i32
; CHECK: @e = unnamed_addr global i32 42
@f = weak global i32 42
; CHECK: @f = global i32 42
; CHECK: @f = unnamed_addr global i32 42
; Other file has non-unnamed_addr definition
@g = common unnamed_addr global i32 0
; CHECK: @g = common global i32 0
; CHECK: @g = common unnamed_addr global i32 0
@h = external global i32
; CHECK: @h = global i32 42
@i = external unnamed_addr global i32

View File

@ -13,20 +13,6 @@
; "SCEV" - ScalarEvolution but no targetdata.
; RUN: opt -analyze -scalar-evolution < %s | FileCheck --check-prefix=SCEV %s
; ScalarEvolution with targetdata isn't interesting on these testcases
; because ScalarEvolution doesn't attempt to duplicate all of instcombine's
; and the constant folders' folding.
; PLAIN: %0 = type { i1, double }
; PLAIN: %1 = type { double, float, double, double }
; PLAIN: %2 = type { i1, i1* }
; PLAIN: %3 = type { i64, i64 }
; PLAIN: %4 = type { i32, i32 }
; OPT: %0 = type { i1, double }
; OPT: %1 = type { double, float, double, double }
; OPT: %2 = type { i1, i1* }
; OPT: %3 = type { i64, i64 }
; OPT: %4 = type { i32, i32 }
; The automatic constant folder in opt does not have targetdata access, so
; it can't fold gep arithmetic, in general. However, the constant folder run
@ -63,23 +49,23 @@
; target-dependent folder should fold these down to constants.
; PLAIN: @a = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310)
; PLAIN: @b = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64)
; PLAIN: @b = constant i64 ptrtoint (double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64)
; PLAIN: @c = constant i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2)
; PLAIN: @d = constant i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11)
; PLAIN: @e = constant i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64)
; PLAIN: @e = constant i64 ptrtoint (double* getelementptr ({ double, float, double, double }* null, i64 0, i32 2) to i64)
; PLAIN: @f = constant i64 1
; PLAIN: @g = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64)
; PLAIN: @g = constant i64 ptrtoint (double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64)
; PLAIN: @h = constant i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64)
; PLAIN: @i = constant i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64)
; PLAIN: @i = constant i64 ptrtoint (i1** getelementptr ({ i1, i1* }* null, i64 0, i32 1) to i64)
; OPT: @a = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310)
; OPT: @b = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64)
; OPT: @b = constant i64 ptrtoint (double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64)
; OPT: @c = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2)
; OPT: @d = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11)
; OPT: @e = constant i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64)
; OPT: @e = constant i64 ptrtoint (double* getelementptr ({ double, float, double, double }* null, i64 0, i32 2) to i64)
; OPT: @f = constant i64 1
; OPT: @g = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64)
; OPT: @g = constant i64 ptrtoint (double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64)
; OPT: @h = constant i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64)
; OPT: @i = constant i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64)
; OPT: @i = constant i64 ptrtoint (i1** getelementptr ({ i1, i1* }* null, i64 0, i32 1) to i64)
; TO: @a = constant i64 18480
; TO: @b = constant i64 8
; TO: @c = constant i64 16
@ -103,10 +89,10 @@
; The target-dependent folder should cast GEP indices to integer-sized pointers.
; PLAIN: @M = constant i64* getelementptr (i64* null, i32 1)
; PLAIN: @N = constant i64* getelementptr (%3* null, i32 0, i32 1)
; PLAIN: @N = constant i64* getelementptr ({ i64, i64 }* null, i32 0, i32 1)
; PLAIN: @O = constant i64* getelementptr ([2 x i64]* null, i32 0, i32 1)
; OPT: @M = constant i64* getelementptr (i64* null, i32 1)
; OPT: @N = constant i64* getelementptr (%3* null, i32 0, i32 1)
; OPT: @N = constant i64* getelementptr ({ i64, i64 }* null, i32 0, i32 1)
; OPT: @O = constant i64* getelementptr ([2 x i64]* null, i32 0, i32 1)
; TO: @M = constant i64* inttoptr (i64 8 to i64*)
; TO: @N = constant i64* inttoptr (i64 8 to i64*)
@ -119,9 +105,9 @@
; Fold GEP of a GEP. Theoretically some of these cases could be folded
; without using targetdata, however that's not implemented yet.
; PLAIN: @Z = global i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x %4]* @ext, i64 0, i64 1, i32 0), i64 1)
; OPT: @Z = global i32* getelementptr (i32* getelementptr inbounds ([3 x %4]* @ext, i64 0, i64 1, i32 0), i64 1)
; TO: @Z = global i32* getelementptr inbounds ([3 x %0]* @ext, i64 0, i64 1, i32 1)
; PLAIN: @Z = global i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1)
; OPT: @Z = global i32* getelementptr (i32* getelementptr inbounds ([3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1)
; TO: @Z = global i32* getelementptr inbounds ([3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1)
@ext = external global [3 x { i32, i32 }]
@Z = global i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1)
@ -236,7 +222,7 @@ define i1* @hoo1() nounwind {
; PLAIN: ret i64 %t
; PLAIN: }
; PLAIN: define i64 @fb() nounwind {
; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64
; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64) to i64
; PLAIN: ret i64 %t
; PLAIN: }
; PLAIN: define i64 @fc() nounwind {
@ -248,7 +234,7 @@ define i1* @hoo1() nounwind {
; PLAIN: ret i64 %t
; PLAIN: }
; PLAIN: define i64 @fe() nounwind {
; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) to i64
; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr ({ double, float, double, double }* null, i64 0, i32 2) to i64) to i64
; PLAIN: ret i64 %t
; PLAIN: }
; PLAIN: define i64 @ff() nounwind {
@ -256,7 +242,7 @@ define i1* @hoo1() nounwind {
; PLAIN: ret i64 %t
; PLAIN: }
; PLAIN: define i64 @fg() nounwind {
; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64
; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64) to i64
; PLAIN: ret i64 %t
; PLAIN: }
; PLAIN: define i64 @fh() nounwind {
@ -264,14 +250,14 @@ define i1* @hoo1() nounwind {
; PLAIN: ret i64 %t
; PLAIN: }
; PLAIN: define i64 @fi() nounwind {
; PLAIN: %t = bitcast i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) to i64
; PLAIN: %t = bitcast i64 ptrtoint (i1** getelementptr ({ i1, i1* }* null, i64 0, i32 1) to i64) to i64
; PLAIN: ret i64 %t
; PLAIN: }
; OPT: define i64 @fa() nounwind {
; OPT: ret i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310)
; OPT: }
; OPT: define i64 @fb() nounwind {
; OPT: ret i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64)
; OPT: ret i64 ptrtoint (double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64)
; OPT: }
; OPT: define i64 @fc() nounwind {
; OPT: ret i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2)
@ -280,19 +266,19 @@ define i1* @hoo1() nounwind {
; OPT: ret i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11)
; OPT: }
; OPT: define i64 @fe() nounwind {
; OPT: ret i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64)
; OPT: ret i64 ptrtoint (double* getelementptr ({ double, float, double, double }* null, i64 0, i32 2) to i64)
; OPT: }
; OPT: define i64 @ff() nounwind {
; OPT: ret i64 1
; OPT: }
; OPT: define i64 @fg() nounwind {
; OPT: ret i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64)
; OPT: ret i64 ptrtoint (double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64)
; OPT: }
; OPT: define i64 @fh() nounwind {
; OPT: ret i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64)
; OPT: }
; OPT: define i64 @fi() nounwind {
; OPT: ret i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64)
; OPT: ret i64 ptrtoint (i1** getelementptr ({ i1, i1* }* null, i64 0, i32 1) to i64)
; OPT: }
; TO: define i64 @fa() nounwind {
; TO: ret i64 18480
@ -325,7 +311,7 @@ define i1* @hoo1() nounwind {
; SCEV: %t = bitcast i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) to i64
; SCEV: --> (2310 * sizeof(double))
; SCEV: Classifying expressions for: @fb
; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64
; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64) to i64
; SCEV: --> alignof(double)
; SCEV: Classifying expressions for: @fc
; SCEV: %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2) to i64
@ -334,19 +320,19 @@ define i1* @hoo1() nounwind {
; SCEV: %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11) to i64
; SCEV: --> (11 * sizeof(double))
; SCEV: Classifying expressions for: @fe
; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) to i64
; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr ({ double, float, double, double }* null, i64 0, i32 2) to i64) to i64
; SCEV: --> offsetof({ double, float, double, double }, 2)
; SCEV: Classifying expressions for: @ff
; SCEV: %t = bitcast i64 1 to i64
; SCEV: --> 1
; SCEV: Classifying expressions for: @fg
; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64
; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64) to i64
; SCEV: --> alignof(double)
; SCEV: Classifying expressions for: @fh
; SCEV: %t = bitcast i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) to i64
; SCEV: --> sizeof(i1*)
; SCEV: Classifying expressions for: @fi
; SCEV: %t = bitcast i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) to i64
; SCEV: %t = bitcast i64 ptrtoint (i1** getelementptr ({ i1, i1* }* null, i64 0, i32 1) to i64) to i64
; SCEV: --> alignof(i1*)
define i64 @fa() nounwind {
@ -391,7 +377,7 @@ define i64 @fi() nounwind {
; PLAIN: ret i64* %t
; PLAIN: }
; PLAIN: define i64* @fN() nounwind {
; PLAIN: %t = bitcast i64* getelementptr (%3* null, i32 0, i32 1) to i64*
; PLAIN: %t = bitcast i64* getelementptr ({ i64, i64 }* null, i32 0, i32 1) to i64*
; PLAIN: ret i64* %t
; PLAIN: }
; PLAIN: define i64* @fO() nounwind {
@ -402,7 +388,7 @@ define i64 @fi() nounwind {
; OPT: ret i64* getelementptr (i64* null, i32 1)
; OPT: }
; OPT: define i64* @fN() nounwind {
; OPT: ret i64* getelementptr (%3* null, i32 0, i32 1)
; OPT: ret i64* getelementptr ({ i64, i64 }* null, i32 0, i32 1)
; OPT: }
; OPT: define i64* @fO() nounwind {
; OPT: ret i64* getelementptr ([2 x i64]* null, i32 0, i32 1)
@ -420,7 +406,7 @@ define i64 @fi() nounwind {
; SCEV: %t = bitcast i64* getelementptr (i64* null, i32 1) to i64*
; SCEV: --> sizeof(i64)
; SCEV: Classifying expressions for: @fN
; SCEV: %t = bitcast i64* getelementptr (%3* null, i32 0, i32 1) to i64*
; SCEV: %t = bitcast i64* getelementptr ({ i64, i64 }* null, i32 0, i32 1) to i64*
; SCEV: --> sizeof(i64)
; SCEV: Classifying expressions for: @fO
; SCEV: %t = bitcast i64* getelementptr ([2 x i64]* null, i32 0, i32 1) to i64*
@ -440,17 +426,17 @@ define i64* @fO() nounwind {
}
; PLAIN: define i32* @fZ() nounwind {
; PLAIN: %t = bitcast i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x %4]* @ext, i64 0, i64 1, i32 0), i64 1) to i32*
; PLAIN: %t = bitcast i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1) to i32*
; PLAIN: ret i32* %t
; PLAIN: }
; OPT: define i32* @fZ() nounwind {
; OPT: ret i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x %4]* @ext, i64 0, i64 1, i32 0), i64 1)
; OPT: ret i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1)
; OPT: }
; TO: define i32* @fZ() nounwind {
; TO: ret i32* getelementptr inbounds ([3 x %0]* @ext, i64 0, i64 1, i32 1)
; TO: ret i32* getelementptr inbounds ([3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1)
; TO: }
; SCEV: Classifying expressions for: @fZ
; SCEV: %t = bitcast i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x %4]* @ext, i64 0, i64 1, i32 0), i64 1) to i32*
; SCEV: %t = bitcast i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1) to i32*
; SCEV: --> ((3 * sizeof(i32)) + @ext)
define i32* @fZ() nounwind {

View File

@ -1,7 +1,6 @@
; RUN: opt < %s -constprop -S | FileCheck %s
%struct = type { i32, [4 x i8] }
%array = type [3 x %struct]
define i32 @test1() {
%A = extractvalue %struct { i32 2, [4 x i8] c"foo\00" }, 0
@ -18,7 +17,7 @@ define i8 @test2() {
}
define i32 @test3() {
%A = extractvalue %array [ %struct { i32 0, [4 x i8] c"aaaa" }, %struct { i32 1, [4 x i8] c"bbbb" }, %struct { i32 2, [4 x i8] c"cccc" } ], 1, 0
%A = extractvalue [3 x %struct] [ %struct { i32 0, [4 x i8] c"aaaa" }, %struct { i32 1, [4 x i8] c"bbbb" }, %struct { i32 2, [4 x i8] c"cccc" } ], 1, 0
ret i32 %A
; CHECK: @test3
; CHECK: ret i32 1
@ -39,7 +38,7 @@ define i8 @zeroinitializer-test2() {
}
define i32 @zeroinitializer-test3() {
%A = extractvalue %array zeroinitializer, 1, 0
%A = extractvalue [3 x %struct] zeroinitializer, 1, 0
ret i32 %A
; CHECK: @zeroinitializer-test3
; CHECK: ret i32 0
@ -60,7 +59,7 @@ define i8 @undef-test2() {
}
define i32 @undef-test3() {
%A = extractvalue %array undef, 1, 0
%A = extractvalue [3 x %struct] undef, 1, 0
ret i32 %A
; CHECK: @undef-test3
; CHECK: ret i32 undef

View File

@ -1,7 +1,6 @@
; RUN: opt < %s -constprop -S | FileCheck %s
%struct = type { i32, [4 x i8] }
%array = type [3 x %struct]
define %struct @test1() {
%A = insertvalue %struct { i32 2, [4 x i8] c"foo\00" }, i32 1, 0
@ -17,11 +16,11 @@ define %struct @test2() {
; CHECK: ret %struct { i32 2, [4 x i8] c"fo\01\00" }
}
define %array @test3() {
%A = insertvalue %array [ %struct { i32 0, [4 x i8] c"aaaa" }, %struct { i32 1, [4 x i8] c"bbbb" }, %struct { i32 2, [4 x i8] c"cccc" } ], i32 -1, 1, 0
ret %array %A
define [3 x %struct] @test3() {
%A = insertvalue [3 x %struct] [ %struct { i32 0, [4 x i8] c"aaaa" }, %struct { i32 1, [4 x i8] c"bbbb" }, %struct { i32 2, [4 x i8] c"cccc" } ], i32 -1, 1, 0
ret [3 x %struct] %A
; CHECK: @test3
; CHECK:ret %array [%struct { i32 0, [4 x i8] c"aaaa" }, %struct { i32 -1, [4 x i8] c"bbbb" }, %struct { i32 2, [4 x i8] c"cccc" }]
; CHECK:ret [3 x %struct] [%struct { i32 0, [4 x i8] c"aaaa" }, %struct { i32 -1, [4 x i8] c"bbbb" }, %struct { i32 2, [4 x i8] c"cccc" }]
}
define %struct @zeroinitializer-test1() {
@ -38,11 +37,11 @@ define %struct @zeroinitializer-test2() {
; CHECK: ret %struct { i32 0, [4 x i8] c"\00\00\01\00" }
}
define %array @zeroinitializer-test3() {
%A = insertvalue %array zeroinitializer, i32 1, 1, 0
ret %array %A
define [3 x %struct] @zeroinitializer-test3() {
%A = insertvalue [3 x %struct] zeroinitializer, i32 1, 1, 0
ret [3 x %struct] %A
; CHECK: @zeroinitializer-test3
; CHECK: ret %array [%struct zeroinitializer, %struct { i32 1, [4 x i8] zeroinitializer }, %struct zeroinitializer]
; CHECK: ret [3 x %struct] [%struct zeroinitializer, %struct { i32 1, [4 x i8] zeroinitializer }, %struct zeroinitializer]
}
define %struct @undef-test1() {
@ -59,10 +58,10 @@ define %struct @undef-test2() {
; CHECK: ret %struct { i32 undef, [4 x i8] [i8 undef, i8 undef, i8 0, i8 undef] }
}
define %array @undef-test3() {
%A = insertvalue %array undef, i32 0, 1, 0
ret %array %A
define [3 x %struct] @undef-test3() {
%A = insertvalue [3 x %struct] undef, i32 0, 1, 0
ret [3 x %struct] %A
; CHECK: @undef-test3
; CHECK: ret %array [%struct undef, %struct { i32 0, [4 x i8] undef }, %struct undef]
; CHECK: ret [3 x %struct] [%struct undef, %struct { i32 0, [4 x i8] undef }, %struct undef]
}

View File

@ -1,6 +1,5 @@
; RUN: opt < %s -constprop -S | FileCheck %s
%i8i1 = type {i8, i1}
declare {i8, i1} @llvm.uadd.with.overflow.i8(i8, i8)
declare {i8, i1} @llvm.usub.with.overflow.i8(i8, i8)
@ -20,7 +19,7 @@ entry:
ret {i8, i1} %t
; CHECK: @uadd_1
; CHECK: ret %i8i1 { i8 -114, i1 false }
; CHECK: ret { i8, i1 } { i8 -114, i1 false }
}
define {i8, i1} @uadd_2() nounwind {
@ -29,7 +28,7 @@ entry:
ret {i8, i1} %t
; CHECK: @uadd_2
; CHECK: ret %i8i1 { i8 6, i1 true }
; CHECK: ret { i8, i1 } { i8 6, i1 true }
}
;;-----------------------------
@ -42,7 +41,7 @@ entry:
ret {i8, i1} %t
; CHECK: @usub_1
; CHECK: ret %i8i1 { i8 2, i1 false }
; CHECK: ret { i8, i1 } { i8 2, i1 false }
}
define {i8, i1} @usub_2() nounwind {
@ -51,7 +50,7 @@ entry:
ret {i8, i1} %t
; CHECK: @usub_2
; CHECK: ret %i8i1 { i8 -2, i1 true }
; CHECK: ret { i8, i1 } { i8 -2, i1 true }
}
;;-----------------------------
@ -64,7 +63,7 @@ entry:
ret {i8, i1} %t
; CHECK: @umul_1
; CHECK: ret %i8i1 { i8 44, i1 true }
; CHECK: ret { i8, i1 } { i8 44, i1 true }
}
define {i8, i1} @umul_2() nounwind {
@ -73,7 +72,7 @@ entry:
ret {i8, i1} %t
; CHECK: @umul_2
; CHECK: ret %i8i1 { i8 -56, i1 false }
; CHECK: ret { i8, i1 } { i8 -56, i1 false }
}
;;-----------------------------
@ -86,7 +85,7 @@ entry:
ret {i8, i1} %t
; CHECK: @sadd_1
; CHECK: ret %i8i1 { i8 44, i1 false }
; CHECK: ret { i8, i1 } { i8 44, i1 false }
}
define {i8, i1} @sadd_2() nounwind {
@ -95,7 +94,7 @@ entry:
ret {i8, i1} %t
; CHECK: @sadd_2
; CHECK: ret %i8i1 { i8 -126, i1 true }
; CHECK: ret { i8, i1 } { i8 -126, i1 true }
}
define {i8, i1} @sadd_3() nounwind {
@ -104,7 +103,7 @@ entry:
ret {i8, i1} %t
; CHECK: @sadd_3
; CHECK: ret %i8i1 { i8 -110, i1 false }
; CHECK: ret { i8, i1 } { i8 -110, i1 false }
}
define {i8, i1} @sadd_4() nounwind {
@ -113,7 +112,7 @@ entry:
ret {i8, i1} %t
; CHECK: @sadd_4
; CHECK: ret %i8i1 { i8 126, i1 true }
; CHECK: ret { i8, i1 } { i8 126, i1 true }
}
define {i8, i1} @sadd_5() nounwind {
@ -122,7 +121,7 @@ entry:
ret {i8, i1} %t
; CHECK: @sadd_5
; CHECK: ret %i8i1 { i8 -8, i1 false }
; CHECK: ret { i8, i1 } { i8 -8, i1 false }
}
@ -136,7 +135,7 @@ entry:
ret {i8, i1} %t
; CHECK: @ssub_1
; CHECK: ret %i8i1 { i8 2, i1 false }
; CHECK: ret { i8, i1 } { i8 2, i1 false }
}
define {i8, i1} @ssub_2() nounwind {
@ -145,7 +144,7 @@ entry:
ret {i8, i1} %t
; CHECK: @ssub_2
; CHECK: ret %i8i1 { i8 -2, i1 false }
; CHECK: ret { i8, i1 } { i8 -2, i1 false }
}
define {i8, i1} @ssub_3() nounwind {
@ -154,7 +153,7 @@ entry:
ret {i8, i1} %t
; CHECK: @ssub_3
; CHECK: ret %i8i1 { i8 126, i1 true }
; CHECK: ret { i8, i1 } { i8 126, i1 true }
}
define {i8, i1} @ssub_3b() nounwind {
@ -163,7 +162,7 @@ entry:
ret {i8, i1} %t
; CHECK: @ssub_3b
; CHECK: ret %i8i1 { i8 -20, i1 false }
; CHECK: ret { i8, i1 } { i8 -20, i1 false }
}
define {i8, i1} @ssub_4() nounwind {
@ -172,7 +171,7 @@ entry:
ret {i8, i1} %t
; CHECK: @ssub_4
; CHECK: ret %i8i1 { i8 -126, i1 true }
; CHECK: ret { i8, i1 } { i8 -126, i1 true }
}
define {i8, i1} @ssub_4b() nounwind {
@ -181,7 +180,7 @@ entry:
ret {i8, i1} %t
; CHECK: @ssub_4b
; CHECK: ret %i8i1 { i8 30, i1 false }
; CHECK: ret { i8, i1 } { i8 30, i1 false }
}
define {i8, i1} @ssub_5() nounwind {
@ -190,7 +189,7 @@ entry:
ret {i8, i1} %t
; CHECK: @ssub_5
; CHECK: ret %i8i1 { i8 -10, i1 false }
; CHECK: ret { i8, i1 } { i8 -10, i1 false }
}
;;-----------------------------
@ -204,5 +203,5 @@ entry:
ret {i8, i1} %t
; CHECK: @smul_1
; CHECK: ret %i8i1 { i8 -56, i1 true }
; CHECK: ret { i8, i1 } { i8 -56, i1 true }
}

View File

@ -1,6 +1,6 @@
; RUN: opt < %s -deadargelim -S > %t
; RUN: grep {define internal zeroext i32 @test1() nounwind} %t
; RUN: grep {define internal %Ty @test2} %t
; RUN: grep {define internal <{ i32, i32 }> @test2} %t
%Ty = type <{ i32, i32 }>

View File

@ -2,7 +2,7 @@
%RPyString = type { i32, %arraytype.Char }
%arraytype.Char = type { i32, [0 x i8] }
%arraytype.Signed = type { i32, [0 x i32] }
%functiontype.1 = type %RPyString* (i32)
%functiontype.1 = type { %RPyString* (i32) *}
%structtype.test = type { i32, %arraytype.Signed }
@structinstance.test = internal global { i32, { i32, [2 x i32] } } { i32 41, { i32, [2 x i32] } { i32 2, [2 x i32] [ i32 100, i32 101 ] } } ; <{ i32, { i32, [2 x i32] } }*> [#uses=1]

View File

@ -5,8 +5,8 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
target triple = "i686-pc-linux-gnu"
%opaque_t = type opaque
%op_ts = type {opaque, i32}
%opaque2 = type opaque
%op_ts = type {%opaque2, i32}
@g = external global %opaque_t
@h = external global %op_ts

View File

@ -40,7 +40,7 @@ define i32* @test4({ i32 }* %I) {
%B = getelementptr { i32 }* %A, i64 0, i32 0
ret i32* %B
; CHECK: @test4
; CHECK: getelementptr %intstruct* %I, i64 1, i32 0
; CHECK: getelementptr { i32 }* %I, i64 1, i32 0
}
define void @test5(i8 %B) {
@ -86,7 +86,7 @@ define i1 @test10({ i32, i32 }* %x, { i32, i32 }* %y) {
%tmp.4 = icmp eq i32* %tmp.1, %tmp.3
ret i1 %tmp.4
; CHECK: @test10
; CHECK: icmp eq %pair* %x, %y
; CHECK: icmp eq { i32, i32 }* %x, %y
}
define i1 @test11({ i32, i32 }* %X) {
@ -94,7 +94,7 @@ define i1 @test11({ i32, i32 }* %X) {
%Q = icmp eq i32* %P, null
ret i1 %Q
; CHECK: @test11
; CHECK: icmp eq %pair* %X, null
; CHECK: icmp eq { i32, i32 }* %X, null
}
@ -228,19 +228,6 @@ define i1 @test23() {
; CHECK: ret i1 false
}
%"java/lang/Object" = type { %struct.llvm_java_object_base }
%"java/lang/StringBuffer" = type { %"java/lang/Object", i32, { %"java/lang/Object", i32, [0 x i16] }*, i1 }
%struct.llvm_java_object_base = type opaque
define void @test24() {
bc0:
%tmp53 = getelementptr %"java/lang/StringBuffer"* null, i32 0, i32 1 ; <i32*> [#uses=1]
store i32 0, i32* %tmp53
ret void
; CHECK: @test24
; CHECK: store i32 0, i32* getelementptr (%"java/lang/StringBuffer"* null, i64 0, i32 1)
}
define void @test25() {
entry:
%tmp = getelementptr { i64, i64, i64, i64 }* null, i32 0, i32 3 ; <i64*> [#uses=1]

View File

@ -139,7 +139,7 @@ BB2:
; CHECK: @test8
; CHECK-NOT: phi
; CHECK: BB2:
; CHECK-NEXT: %B = getelementptr %0
; CHECK-NEXT: %B = getelementptr { i32, i32 }* %A
; CHECK-NEXT: ret i32* %B
}

View File

@ -1,12 +1,10 @@
; RUN: opt < %s -instcombine -S | \
; RUN: grep {fadd float}
; RUN: opt < %s -instcombine -S | grep {fadd float}
%V = type <4 x float>
define float @test(%V %A, %V %B, float %f) {
%C = insertelement %V %A, float %f, i32 0 ; <%V> [#uses=1]
%D = fadd %V %C, %B ; <%V> [#uses=1]
%E = extractelement %V %D, i32 0 ; <float> [#uses=1]
define float @test(<4 x float> %A, <4 x float> %B, float %f) {
%C = insertelement <4 x float> %A, float %f, i32 0 ; <%V> [#uses=1]
%D = fadd <4 x float> %C, %B ; <%V> [#uses=1]
%E = extractelement <4 x float> %D, i32 0 ; <float> [#uses=1]
ret float %E
}

View File

@ -1,28 +1,25 @@
; RUN: opt < %s -instcombine -S | FileCheck %s
%T = type <4 x float>
define %T @test1(%T %v1) {
define <4 x float> @test1(<4 x float> %v1) {
; CHECK: @test1
; CHECK: ret %T %v1
%v2 = shufflevector %T %v1, %T undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret %T %v2
; CHECK: ret <4 x float> %v1
%v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x float> %v2
}
define %T @test2(%T %v1) {
define <4 x float> @test2(<4 x float> %v1) {
; CHECK: @test2
; CHECK: ret %T %v1
%v2 = shufflevector %T %v1, %T %v1, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
ret %T %v2
; CHECK: ret <4 x float> %v1
%v2 = shufflevector <4 x float> %v1, <4 x float> %v1, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
ret <4 x float> %v2
}
define float @test3(%T %A, %T %B, float %f) {
define float @test3(<4 x float> %A, <4 x float> %B, float %f) {
; CHECK: @test3
; CHECK: ret float %f
%C = insertelement %T %A, float %f, i32 0
%D = shufflevector %T %C, %T %B, <4 x i32> <i32 5, i32 0, i32 2, i32 7>
%E = extractelement %T %D, i32 1
%C = insertelement <4 x float> %A, float %f, i32 0
%D = shufflevector <4 x float> %C, <4 x float> %B, <4 x i32> <i32 5, i32 0, i32 2, i32 7>
%E = extractelement <4 x float> %D, i32 1
ret float %E
}
@ -57,7 +54,7 @@ define float @test6(<4 x float> %X) {
define <4 x float> @test7(<4 x float> %tmp45.i) {
; CHECK: @test7
; CHECK-NEXT: ret %T %tmp45.i
; CHECK-NEXT: ret <4 x float> %tmp45.i
%tmp1642.i = shufflevector <4 x float> %tmp45.i, <4 x float> undef, <4 x i32> < i32 0, i32 1, i32 6, i32 7 >
ret <4 x float> %tmp1642.i
}

View File

@ -1,6 +1,5 @@
; RUN: opt < %s -lowersetjmp -S | grep invoke
%JmpBuf = type i32
@.str_1 = internal constant [13 x i8] c"returned %d\0A\00" ; <[13 x i8]*> [#uses=1]
declare void @llvm.longjmp(i32*, i32)

View File

@ -6,7 +6,7 @@ target triple = "i686-apple-darwin9"
%0 = type { x86_fp80, x86_fp80 }
%1 = type { i32, i32 }
define void @test1({ x86_fp80, x86_fp80 }* sret %agg.result, x86_fp80 %z.0, x86_fp80 %z.1) nounwind {
define void @test1(%0* sret %agg.result, x86_fp80 %z.0, x86_fp80 %z.1) nounwind {
entry:
%tmp2 = alloca %0
%memtmp = alloca %0, align 16
@ -29,7 +29,7 @@ entry:
; CHECK: ret void
}
declare void @ccoshl({ x86_fp80, x86_fp80 }* sret , x86_fp80, x86_fp80) nounwind
declare void @ccoshl(%0* sret , x86_fp80, x86_fp80) nounwind
; The intermediate alloca and one of the memcpy's should be eliminated, the
@ -49,9 +49,9 @@ define void @test2(i8* %P, i8* %Q) nounwind {
@x = external global { x86_fp80, x86_fp80 }
@x = external global %0
define void @test3({ x86_fp80, x86_fp80 }* noalias sret %agg.result) nounwind {
define void @test3(%0* noalias sret %agg.result) nounwind {
%x.0 = alloca %0
%x.01 = bitcast %0* %x.0 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x.01, i8* bitcast (%0* @x to i8*), i32 32, i32 16, i1 false)

View File

@ -3,8 +3,6 @@
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
target triple = "i386-gnu-linux"
%ada__tags__T15s = type void ()
define void @exp_averages_intraday__deviation() {
entry:
%0 = load i32* undef, align 4

View File

@ -126,7 +126,7 @@ B:
; CHECK: define i64 @test5b()
; CHECK: A:
; CHECK-NEXT: %c = call i64 @test5c(%0 %a)
; CHECK-NEXT: %c = call i64 @test5c({ i64, i64 } %a)
; CHECK-NEXT: ret i64 5
define internal i64 @test5c({i64,i64} %a) {
@ -153,7 +153,7 @@ define i64 @test6b() {
%T = type {i32,i32}
define internal {i32, i32} @test7a(i32 %A) {
define internal %T @test7a(i32 %A) {
%X = add i32 1, %A
%mrv0 = insertvalue %T undef, i32 %X, 0
%mrv1 = insertvalue %T %mrv0, i32 %A, 1
@ -164,8 +164,8 @@ define internal {i32, i32} @test7a(i32 %A) {
}
define i32 @test7b() {
%X = call {i32, i32} @test7a(i32 17)
%Y = extractvalue {i32, i32} %X, 0
%X = call %T @test7a(i32 17)
%Y = extractvalue %T %X, 0
%Z = add i32 %Y, %Y
ret i32 %Z
; CHECK: define i32 @test7b

View File

@ -6,10 +6,10 @@ declare i32 @.callback_1(i8*)
declare void @.iter_2(i32 (i8*)*, i8*)
define i32 @main() {
%d = alloca { [80 x i8], i32, i32 } ; <{ [80 x i8], i32, i32 }*> [#uses=2]
%tmp.0 = getelementptr { [80 x i8], i32, i32 }* %d, i64 0, i32 2 ; <i32*> [#uses=1]
%d = alloca %T ; <{ [80 x i8], i32, i32 }*> [#uses=2]
%tmp.0 = getelementptr %T* %d, i64 0, i32 2 ; <i32*> [#uses=1]
store i32 0, i32* %tmp.0
%tmp.1 = getelementptr { [80 x i8], i32, i32 }* %d, i64 0, i32 0, i64 0 ; <i8*> [#uses=1]
%tmp.1 = getelementptr %T* %d, i64 0, i32 0, i64 0 ; <i8*> [#uses=1]
call void @.iter_2( i32 (i8*)* @.callback_1, i8* %tmp.1 )
ret i32 0
}

Some files were not shown because too many files have changed in this diff Show More