Vendor import of llvm release_31 branch r155985:
http://llvm.org/svn/llvm-project/llvm/branches/release_31@155985
This commit is contained in:
parent
63faed5b8e
commit
b61ab53cb7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/llvm/dist/; revision=234971 svn path=/vendor/llvm/llvm-release_31-r155985/; revision=234972; tag=vendor/llvm/llvm-release_31-r155985
@ -213,15 +213,6 @@ if( WIN32 AND NOT CYGWIN )
|
||||
set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools")
|
||||
endif()
|
||||
|
||||
# On Win32 using MS tools, provide an option to set the number of parallel jobs
|
||||
# to use.
|
||||
if( MSVC_IDE AND ( MSVC90 OR MSVC10 ) )
|
||||
# Only Visual Studio 2008 and 2010 officially supports /MP. Visual Studio
|
||||
# 2005 supports it but it is experimental.
|
||||
set(LLVM_COMPILER_JOBS "0" CACHE STRING
|
||||
"Number of parallel compiler jobs. 0 means use all processors. Default is 0.")
|
||||
endif()
|
||||
|
||||
# Define options to control the inclusion and default build behavior for
|
||||
# components which may not strictly be necessary (tools, runtime, examples, and
|
||||
# tests).
|
||||
@ -396,7 +387,6 @@ add_subdirectory(utils/FileUpdate)
|
||||
add_subdirectory(utils/count)
|
||||
add_subdirectory(utils/not)
|
||||
add_subdirectory(utils/llvm-lit)
|
||||
add_subdirectory(utils/json-bench)
|
||||
add_subdirectory(utils/yaml-bench)
|
||||
|
||||
add_subdirectory(projects)
|
||||
|
20
CREDITS.TXT
20
CREDITS.TXT
@ -50,9 +50,15 @@ N: Cameron Buschardt
|
||||
E: buschard@uiuc.edu
|
||||
D: The `mem2reg' pass - promotes values stored in memory to registers
|
||||
|
||||
N: Brendon Cahoon
|
||||
E: bcahoon@codeaurora.org
|
||||
D: Loop unrolling with run-time trip counts.
|
||||
|
||||
N: Chandler Carruth
|
||||
E: chandlerc@gmail.com
|
||||
D: LinkTimeOptimizer for Linux, via binutils integration, and C API
|
||||
D: Hashing algorithms and interfaces
|
||||
D: Inline cost analysis
|
||||
D: Machine block placement pass
|
||||
|
||||
N: Casey Carter
|
||||
E: ccarter@uiuc.edu
|
||||
@ -210,6 +216,10 @@ N: Benjamin Kramer
|
||||
E: benny.kra@gmail.com
|
||||
D: Miscellaneous bug fixes
|
||||
|
||||
N: Sundeep Kushwaha
|
||||
E: sundeepk@codeaurora.org
|
||||
D: Implemented DFA-based target independent VLIW packetizer
|
||||
|
||||
N: Christopher Lamb
|
||||
E: christopher.lamb@gmail.com
|
||||
D: aligned load/store support, parts of noalias and restrict support
|
||||
@ -245,6 +255,10 @@ N: Nick Lewycky
|
||||
E: nicholas@mxc.ca
|
||||
D: PredicateSimplifier pass
|
||||
|
||||
N: Tony Linthicum, et. al.
|
||||
E: tlinth@codeaurora.org
|
||||
D: Backend for Qualcomm's Hexagon VLIW processor.
|
||||
|
||||
N: Bruno Cardoso Lopes
|
||||
E: bruno.cardoso@gmail.com
|
||||
W: http://www.brunocardoso.org
|
||||
@ -271,6 +285,10 @@ N: Scott Michel
|
||||
E: scottm@aero.org
|
||||
D: Added STI Cell SPU backend.
|
||||
|
||||
N: Kai Nacke
|
||||
E: kai@redstar.de
|
||||
D: Support for implicit TLS model used with MS VC runtime
|
||||
|
||||
N: Takumi Nakamura
|
||||
E: geek4civic@gmail.com
|
||||
E: chapuni@hf.rim.or.jp
|
||||
|
@ -838,6 +838,13 @@ AC_ARG_WITH(gcc-toolchain,
|
||||
AC_DEFINE_UNQUOTED(GCC_INSTALL_PREFIX,"$withval",
|
||||
[Directory where gcc is installed.])
|
||||
|
||||
AC_ARG_WITH(default-sysroot,
|
||||
AS_HELP_STRING([--with-default-sysroot],
|
||||
[Add --sysroot=<path> to all compiler invocations.]),,
|
||||
withval="")
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_SYSROOT,"$withval",
|
||||
[Default <path> to all compiler invocations for --sysroot=<path>.])
|
||||
|
||||
dnl Allow linking of LLVM with GPLv3 binutils code.
|
||||
AC_ARG_WITH(binutils-include,
|
||||
AS_HELP_STRING([--with-binutils-include],
|
||||
|
@ -110,9 +110,9 @@ if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 )
|
||||
endif( LLVM_BUILD_32_BITS )
|
||||
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 )
|
||||
|
||||
if( MSVC_IDE AND ( MSVC90 OR MSVC10 ) )
|
||||
# Only Visual Studio 2008 and 2010 officially supports /MP.
|
||||
# Visual Studio 2005 do support it but it's experimental there.
|
||||
# On Win32 using MS tools, provide an option to set the number of parallel jobs
|
||||
# to use.
|
||||
if( MSVC_IDE )
|
||||
set(LLVM_COMPILER_JOBS "0" CACHE STRING
|
||||
"Number of parallel compiler jobs. 0 means use all processors. Default is 0.")
|
||||
if( NOT LLVM_COMPILER_JOBS STREQUAL "1" )
|
||||
|
19
configure
vendored
19
configure
vendored
@ -1442,6 +1442,7 @@ Optional Packages:
|
||||
--with-c-include-dirs Colon separated list of directories clang will
|
||||
search for headers
|
||||
--with-gcc-toolchain Directory where gcc is installed.
|
||||
--with-default-sysroot Add --sysroot=<path> to all compiler invocations.
|
||||
--with-binutils-include Specify path to binutils/include/ containing
|
||||
plugin-api.h file for gold plugin.
|
||||
--with-bug-report-url Specify the URL where bug reports should be
|
||||
@ -3802,7 +3803,7 @@ else
|
||||
llvm_cv_target_os_type="Darwin" ;;
|
||||
*-*-minix*)
|
||||
llvm_cv_target_os_type="Minix" ;;
|
||||
*-*-freebsd*| *-*-kfreebsd-gnu)
|
||||
*-*-freebsd* | *-*-kfreebsd-gnu)
|
||||
llvm_cv_target_os_type="FreeBSD" ;;
|
||||
*-*-openbsd*)
|
||||
llvm_cv_target_os_type="OpenBSD" ;;
|
||||
@ -5583,6 +5584,20 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
# Check whether --with-default-sysroot was given.
|
||||
if test "${with_default_sysroot+set}" = set; then
|
||||
withval=$with_default_sysroot;
|
||||
else
|
||||
withval=""
|
||||
fi
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define DEFAULT_SYSROOT "$withval"
|
||||
_ACEOF
|
||||
|
||||
|
||||
|
||||
# Check whether --with-binutils-include was given.
|
||||
if test "${with_binutils_include+set}" = set; then
|
||||
withval=$with_binutils_include;
|
||||
@ -10386,7 +10401,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 10387 "configure"
|
||||
#line 10404 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
|
@ -1617,9 +1617,9 @@ def : Pat<(i32 imm:$imm),
|
||||
range from 1 to 1023. To see how this numbering is defined for a particular
|
||||
architecture, you can read the <tt>GenRegisterNames.inc</tt> file for that
|
||||
architecture. For instance, by
|
||||
inspecting <tt>lib/Target/X86/X86GenRegisterNames.inc</tt> we see that the
|
||||
32-bit register <tt>EAX</tt> is denoted by 15, and the MMX register
|
||||
<tt>MM0</tt> is mapped to 48.</p>
|
||||
inspecting <tt>lib/Target/X86/X86GenRegisterInfo.inc</tt> we see that the
|
||||
32-bit register <tt>EAX</tt> is denoted by 43, and the MMX register
|
||||
<tt>MM0</tt> is mapped to 65.</p>
|
||||
|
||||
<p>Some architectures contain registers that share the same physical location. A
|
||||
notable example is the X86 platform. For instance, in the X86 architecture,
|
||||
@ -1627,7 +1627,7 @@ def : Pat<(i32 imm:$imm),
|
||||
bits. These physical registers are marked as <i>aliased</i> in LLVM. Given a
|
||||
particular architecture, you can check which registers are aliased by
|
||||
inspecting its <tt>RegisterInfo.td</tt> file. Moreover, the method
|
||||
<tt>TargetRegisterInfo::getAliasSet(p_reg)</tt> returns an array containing
|
||||
<tt>MCRegisterInfo::getAliasSet(p_reg)</tt> returns an array containing
|
||||
all the physical registers aliased to the register <tt>p_reg</tt>.</p>
|
||||
|
||||
<p>Physical registers, in LLVM, are grouped in <i>Register Classes</i>.
|
||||
@ -3182,7 +3182,7 @@ MOVSX32rm16 -> movsx, 32-bit register, 16-bit memory
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2012-03-27 13:25:16 +0200 (Tue, 27 Mar 2012) $
|
||||
Last modified: $Date: 2012-04-15 22:22:36 +0200 (Sun, 15 Apr 2012) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -67,20 +67,20 @@ This syntax says to pipe the current file ("%s") into llvm-as, pipe that into
|
||||
llc, then pipe the output of llc into FileCheck. This means that FileCheck will
|
||||
be verifying its standard input (the llc output) against the filename argument
|
||||
specified (the original .ll file specified by "%s"). To see how this works,
|
||||
lets look at the rest of the .ll file (after the RUN line):
|
||||
let's look at the rest of the .ll file (after the RUN line):
|
||||
|
||||
define void @sub1(i32* %p, i32 %v) {
|
||||
entry:
|
||||
; <b>CHECK: sub1:</b>
|
||||
; <b>CHECK: subl</b>
|
||||
; CHECK: sub1:
|
||||
; CHECK: subl
|
||||
%0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @inc4(i64* %p) {
|
||||
entry:
|
||||
; <b>CHECK: inc4:</b>
|
||||
; <b>CHECK: incq</b>
|
||||
; CHECK: inc4:
|
||||
; CHECK: incq
|
||||
%0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1)
|
||||
ret void
|
||||
}
|
||||
@ -111,18 +111,18 @@ driven from one .ll file. This is useful in many circumstances, for example,
|
||||
testing different architectural variants with llc. Here's a simple example:
|
||||
|
||||
; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse41 \
|
||||
; RUN: | <b>FileCheck %s -check-prefix=X32</b>
|
||||
; RUN: | FileCheck %s -check-prefix=X32>
|
||||
; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=sse41 \
|
||||
; RUN: | <b>FileCheck %s -check-prefix=X64</b>
|
||||
; RUN: | FileCheck %s -check-prefix=X64>
|
||||
|
||||
define <4 x i32> @pinsrd_1(i32 %s, <4 x i32> %tmp) nounwind {
|
||||
%tmp1 = insertelement <4 x i32>; %tmp, i32 %s, i32 1
|
||||
ret <4 x i32> %tmp1
|
||||
; <b>X32:</b> pinsrd_1:
|
||||
; <b>X32:</b> pinsrd $1, 4(%esp), %xmm0
|
||||
; X32: pinsrd_1:
|
||||
; X32: pinsrd $1, 4(%esp), %xmm0
|
||||
|
||||
; <b>X64:</b> pinsrd_1:
|
||||
; <b>X64:</b> pinsrd $1, %edi, %xmm0
|
||||
; X64: pinsrd_1:
|
||||
; X64: pinsrd $1, %edi, %xmm0
|
||||
}
|
||||
|
||||
In this case, we're testing that we get the expected code generation with
|
||||
@ -147,13 +147,13 @@ example, something like this works as you'd expect:
|
||||
store <2 x double> %tmp9, <2 x double>* %r, align 16
|
||||
ret void
|
||||
|
||||
; <b>CHECK:</b> t2:
|
||||
; <b>CHECK:</b> movl 8(%esp), %eax
|
||||
; <b>CHECK-NEXT:</b> movapd (%eax), %xmm0
|
||||
; <b>CHECK-NEXT:</b> movhpd 12(%esp), %xmm0
|
||||
; <b>CHECK-NEXT:</b> movl 4(%esp), %eax
|
||||
; <b>CHECK-NEXT:</b> movapd %xmm0, (%eax)
|
||||
; <b>CHECK-NEXT:</b> ret
|
||||
; CHECK: t2:
|
||||
; CHECK: movl 8(%esp), %eax
|
||||
; CHECK-NEXT: movapd (%eax), %xmm0
|
||||
; CHECK-NEXT: movhpd 12(%esp), %xmm0
|
||||
; CHECK-NEXT: movl 4(%esp), %eax
|
||||
; CHECK-NEXT: movapd %xmm0, (%eax)
|
||||
; CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
CHECK-NEXT: directives reject the input unless there is exactly one newline
|
||||
@ -177,9 +177,9 @@ can be used:
|
||||
|
||||
%A = load i8* %P3
|
||||
ret i8 %A
|
||||
; <b>CHECK:</b> @coerce_offset0
|
||||
; <b>CHECK-NOT:</b> load
|
||||
; <b>CHECK:</b> ret i8
|
||||
; CHECK: @coerce_offset0
|
||||
; CHECK-NOT: load
|
||||
; CHECK: ret i8
|
||||
}
|
||||
|
||||
|
||||
@ -195,7 +195,7 @@ matching for a majority of what we do, FileCheck has been designed to support
|
||||
mixing and matching fixed string matching with regular expressions. This allows
|
||||
you to write things like this:
|
||||
|
||||
; CHECK: movhpd <b>{{[0-9]+}}</b>(%esp), <b>{{%xmm[0-7]}}</b>
|
||||
; CHECK: movhpd {{[0-9]+}}(%esp), {{%xmm[0-7]}}
|
||||
|
||||
In this case, any offset from the ESP register will be allowed, and any xmm
|
||||
register will be allowed.
|
||||
@ -217,20 +217,20 @@ allows named variables to be defined and substituted into patterns. Here is a
|
||||
simple example:
|
||||
|
||||
; CHECK: test5:
|
||||
; CHECK: notw <b>[[REGISTER:%[a-z]+]]</b>
|
||||
; CHECK: andw {{.*}}<b>[[REGISTER]]</b>
|
||||
; CHECK: notw [[REGISTER:%[a-z]+]]
|
||||
; CHECK: andw {{.*}}[REGISTER]]
|
||||
|
||||
The first check line matches a regex (<tt>%[a-z]+</tt>) and captures it into
|
||||
the variables "REGISTER". The second line verifies that whatever is in REGISTER
|
||||
The first check line matches a regex (B<%[a-z]+>) and captures it into
|
||||
the variable "REGISTER". The second line verifies that whatever is in REGISTER
|
||||
occurs later in the file after an "andw". FileCheck variable references are
|
||||
always contained in <tt>[[ ]]</tt> pairs, are named, and their names can be
|
||||
formed with the regex "<tt>[a-zA-Z_][a-zA-Z0-9_]*</tt>". If a colon follows the
|
||||
always contained in B<[[ ]]> pairs, are named, and their names can be
|
||||
formed with the regex "B<[a-zA-Z_][a-zA-Z0-9_]*>". If a colon follows the
|
||||
name, then it is a definition of the variable, if not, it is a use.
|
||||
|
||||
FileCheck variables can be defined multiple times, and uses always get the
|
||||
latest value. Note that variables are all read at the start of a "CHECK" line
|
||||
and are all defined at the end. This means that if you have something like
|
||||
"<tt>CHECK: [[XYZ:.*]]x[[XYZ]]<tt>" that the check line will read the previous
|
||||
"B<CHECK: [[XYZ:.*]]x[[XYZ]]>", the check line will read the previous
|
||||
value of the XYZ variable and define a new one after the match is performed. If
|
||||
you need to do something like this you can probably take advantage of the fact
|
||||
that FileCheck is not actually line-oriented when it matches, this allows you to
|
||||
|
@ -8,93 +8,16 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Debugging JITed Code With GDB</h1>
|
||||
<h1>Debugging JIT-ed Code With GDB</h1>
|
||||
<ol>
|
||||
<li><a href="#example">Example usage</a></li>
|
||||
<li><a href="#background">Background</a></li>
|
||||
<li><a href="#gdbversion">GDB Version</a></li>
|
||||
<li><a href="#mcjitdebug">Debugging MCJIT-ed code</a></li>
|
||||
<ul>
|
||||
<li><a href="#mcjitdebug_example">Example</a></li>
|
||||
</ul>
|
||||
</ol>
|
||||
<div class="doc_author">Written by Reid Kleckner</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
<h2><a name="example">Example usage</a></h2>
|
||||
<!--=========================================================================-->
|
||||
<div>
|
||||
|
||||
<p>In order to debug code JITed by LLVM, you need GDB 7.0 or newer, which is
|
||||
available on most modern distributions of Linux. The version of GDB that Apple
|
||||
ships with XCode has been frozen at 6.3 for a while. LLDB may be a better
|
||||
option for debugging JITed code on Mac OS X.
|
||||
</p>
|
||||
|
||||
<p>Consider debugging the following code compiled with clang and run through
|
||||
lli:
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
#include <stdio.h>
|
||||
|
||||
void foo() {
|
||||
printf("%d\n", *(int*)NULL); // Crash here
|
||||
}
|
||||
|
||||
void bar() {
|
||||
foo();
|
||||
}
|
||||
|
||||
void baz() {
|
||||
bar();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
baz();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Here are the commands to run that application under GDB and print the stack
|
||||
trace at the crash:
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
# Compile foo.c to bitcode. You can use either clang or llvm-gcc with this
|
||||
# command line. Both require -fexceptions, or the calls are all marked
|
||||
# 'nounwind' which disables DWARF exception handling info. Custom frontends
|
||||
# should avoid adding this attribute to JITed code, since it interferes with
|
||||
# DWARF CFA generation at the moment.
|
||||
$ clang foo.c -fexceptions -emit-llvm -c -o foo.bc
|
||||
|
||||
# Run foo.bc under lli with -jit-emit-debug. If you built lli in debug mode,
|
||||
# -jit-emit-debug defaults to true.
|
||||
$ $GDB_INSTALL/gdb --args lli -jit-emit-debug foo.bc
|
||||
...
|
||||
|
||||
# Run the code.
|
||||
(gdb) run
|
||||
Starting program: /tmp/gdb/lli -jit-emit-debug foo.bc
|
||||
[Thread debugging using libthread_db enabled]
|
||||
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
0x00007ffff7f55164 in foo ()
|
||||
|
||||
# Print the backtrace, this time with symbols instead of ??.
|
||||
(gdb) bt
|
||||
#0 0x00007ffff7f55164 in foo ()
|
||||
#1 0x00007ffff7f550f9 in bar ()
|
||||
#2 0x00007ffff7f55099 in baz ()
|
||||
#3 0x00007ffff7f5502a in main ()
|
||||
#4 0x00000000007c0225 in llvm::JIT::runFunction(llvm::Function*,
|
||||
std::vector<llvm::GenericValue,
|
||||
std::allocator<llvm::GenericValue> > const&) ()
|
||||
#5 0x00000000007d6d98 in
|
||||
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
|
||||
std::vector<std::string,
|
||||
std::allocator<std::string> > const&, char const* const*) ()
|
||||
#6 0x00000000004dab76 in main ()
|
||||
</pre>
|
||||
|
||||
<p>As you can see, GDB can correctly unwind the stack and has the appropriate
|
||||
function names.
|
||||
</p>
|
||||
</div>
|
||||
<div class="doc_author">Written by Reid Kleckner and Eli Bendersky</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
<h2><a name="background">Background</a></h2>
|
||||
@ -107,37 +30,144 @@ debug information from the object file of the code, but for JITed code, there is
|
||||
no such file to look for.
|
||||
</p>
|
||||
|
||||
<p>Depending on the architecture, this can impact the debugging experience in
|
||||
different ways. For example, on most 32-bit x86 architectures, you can simply
|
||||
compile with -fno-omit-frame-pointer for GCC and -disable-fp-elim for LLVM.
|
||||
When GDB creates a backtrace, it can properly unwind the stack, but the stack
|
||||
frames owned by JITed code have ??'s instead of the appropriate symbol name.
|
||||
However, on Linux x86_64 in particular, GDB relies on the DWARF call frame
|
||||
address (CFA) debug information to unwind the stack, so even if you compile
|
||||
your program to leave the frame pointer untouched, GDB will usually be unable
|
||||
to unwind the stack past any JITed code stack frames.
|
||||
</p>
|
||||
|
||||
<p>In order to communicate the necessary debug info to GDB, an interface for
|
||||
registering JITed code with debuggers has been designed and implemented for
|
||||
GDB and LLVM. At a high level, whenever LLVM generates new machine code, it
|
||||
also generates an object file in memory containing the debug information. LLVM
|
||||
then adds the object file to the global list of object files and calls a special
|
||||
function (__jit_debug_register_code) marked noinline that GDB knows about. When
|
||||
GDB and LLVM MCJIT. At a high level, whenever MCJIT generates new machine code,
|
||||
it does so in an in-memory object file that contains the debug information in
|
||||
DWARF format. MCJIT then adds this in-memory object file to a global list of
|
||||
dynamically generated object files and calls a special function
|
||||
(<tt>__jit_debug_register_code</tt>) marked noinline that GDB knows about. When
|
||||
GDB attaches to a process, it puts a breakpoint in this function and loads all
|
||||
of the object files in the global list. When LLVM calls the registration
|
||||
of the object files in the global list. When MCJIT calls the registration
|
||||
function, GDB catches the breakpoint signal, loads the new object file from
|
||||
LLVM's memory, and resumes the execution. In this way, GDB can get the
|
||||
the inferior's memory, and resumes the execution. In this way, GDB can get the
|
||||
necessary debug information.
|
||||
</p>
|
||||
|
||||
<p>At the time of this writing, LLVM only supports architectures that use ELF
|
||||
object files and it only generates symbols and DWARF CFA information. However,
|
||||
it would be easy to add more information to the object file, so we don't need to
|
||||
coordinate with GDB to get better debug information.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
<h2><a name="gdbversion">GDB Version</a></h2>
|
||||
<!--=========================================================================-->
|
||||
|
||||
<p>In order to debug code JIT-ed by LLVM, you need GDB 7.0 or newer, which is
|
||||
available on most modern distributions of Linux. The version of GDB that Apple
|
||||
ships with XCode has been frozen at 6.3 for a while. LLDB may be a better
|
||||
option for debugging JIT-ed code on Mac OS X.
|
||||
</p>
|
||||
|
||||
|
||||
<!--=========================================================================-->
|
||||
<h2><a name="mcjitdebug">Debugging MCJIT-ed code</a></h2>
|
||||
<!--=========================================================================-->
|
||||
<div>
|
||||
|
||||
<p>The emerging MCJIT component of LLVM allows full debugging of JIT-ed code with
|
||||
GDB. This is due to MCJIT's ability to use the MC emitter to provide full
|
||||
DWARF debugging information to GDB.</p>
|
||||
|
||||
<p>Note that lli has to be passed the <tt>-use-mcjit</tt> flag to JIT the code
|
||||
with MCJIT instead of the old JIT.</p>
|
||||
|
||||
<h3><a name="mcjitdebug_example">Example</a></h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Consider the following C code (with line numbers added to make the example
|
||||
easier to follow):</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
1 int compute_factorial(int n)
|
||||
2 {
|
||||
3 if (n <= 1)
|
||||
4 return 1;
|
||||
5
|
||||
6 int f = n;
|
||||
7 while (--n > 1)
|
||||
8 f *= n;
|
||||
9 return f;
|
||||
10 }
|
||||
11
|
||||
12
|
||||
13 int main(int argc, char** argv)
|
||||
14 {
|
||||
15 if (argc < 2)
|
||||
16 return -1;
|
||||
17 char firstletter = argv[1][0];
|
||||
18 int result = compute_factorial(firstletter - '0');
|
||||
19
|
||||
20 // Returned result is clipped at 255...
|
||||
21 return result;
|
||||
22 }
|
||||
</pre>
|
||||
|
||||
<p>Here is a sample command line session that shows how to build and run this
|
||||
code via lli inside GDB:
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
$ $BINPATH/clang -cc1 -O0 -g -emit-llvm showdebug.c
|
||||
$ gdb --quiet --args $BINPATH/lli -use-mcjit showdebug.ll 5
|
||||
Reading symbols from $BINPATH/lli...done.
|
||||
(gdb) b showdebug.c:6
|
||||
No source file named showdebug.c.
|
||||
Make breakpoint pending on future shared library load? (y or [n]) y
|
||||
Breakpoint 1 (showdebug.c:6) pending.
|
||||
(gdb) r
|
||||
Starting program: $BINPATH/lli -use-mcjit showdebug.ll 5
|
||||
[Thread debugging using libthread_db enabled]
|
||||
|
||||
Breakpoint 1, compute_factorial (n=5) at showdebug.c:6
|
||||
6 int f = n;
|
||||
(gdb) p n
|
||||
$1 = 5
|
||||
(gdb) p f
|
||||
$2 = 0
|
||||
(gdb) n
|
||||
7 while (--n > 1)
|
||||
(gdb) p f
|
||||
$3 = 5
|
||||
(gdb) b showdebug.c:9
|
||||
Breakpoint 2 at 0x7ffff7ed404c: file showdebug.c, line 9.
|
||||
(gdb) c
|
||||
Continuing.
|
||||
|
||||
Breakpoint 2, compute_factorial (n=1) at showdebug.c:9
|
||||
9 return f;
|
||||
(gdb) p f
|
||||
$4 = 120
|
||||
(gdb) bt
|
||||
#0 compute_factorial (n=1) at showdebug.c:9
|
||||
#1 0x00007ffff7ed40a9 in main (argc=2, argv=0x16677e0) at showdebug.c:18
|
||||
#2 0x3500000001652748 in ?? ()
|
||||
#3 0x00000000016677e0 in ?? ()
|
||||
#4 0x0000000000000002 in ?? ()
|
||||
#5 0x0000000000d953b3 in llvm::MCJIT::runFunction (this=0x16151f0, F=0x1603020, ArgValues=...) at /home/ebenders_test/llvm_svn_rw/lib/ExecutionEngine/MCJIT/MCJIT.cpp:161
|
||||
#6 0x0000000000dc8872 in llvm::ExecutionEngine::runFunctionAsMain (this=0x16151f0, Fn=0x1603020, argv=..., envp=0x7fffffffe040)
|
||||
at /home/ebenders_test/llvm_svn_rw/lib/ExecutionEngine/ExecutionEngine.cpp:397
|
||||
#7 0x000000000059c583 in main (argc=4, argv=0x7fffffffe018, envp=0x7fffffffe040) at /home/ebenders_test/llvm_svn_rw/tools/lli/lli.cpp:324
|
||||
(gdb) finish
|
||||
Run till exit from #0 compute_factorial (n=1) at showdebug.c:9
|
||||
0x00007ffff7ed40a9 in main (argc=2, argv=0x16677e0) at showdebug.c:18
|
||||
18 int result = compute_factorial(firstletter - '0');
|
||||
Value returned is $5 = 120
|
||||
(gdb) p result
|
||||
$6 = 23406408
|
||||
(gdb) n
|
||||
21 return result;
|
||||
(gdb) p result
|
||||
$7 = 120
|
||||
(gdb) c
|
||||
Continuing.
|
||||
|
||||
Program exited with code 0170.
|
||||
(gdb)
|
||||
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<hr>
|
||||
<address>
|
||||
@ -145,9 +175,10 @@ coordinate with GDB to get better debug information.
|
||||
src="http://jigsaw.w3.org/css-validator/images/vcss-blue" alt="Valid CSS"></a>
|
||||
<a href="http://validator.w3.org/check/referer"><img
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
<a href="mailto:reid.kleckner@gmail.com">Reid Kleckner</a><br>
|
||||
<a href="mailto:reid.kleckner@gmail.com">Reid Kleckner</a>,
|
||||
<a href="mailto:eliben@gmail.com">Eli Bendersky</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-10-31 12:21:59 +0100 (Mon, 31 Oct 2011) $
|
||||
Last modified: $Date: 2012-05-01 09:58:54 +0200 (Tue, 01 May 2012) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -101,7 +101,7 @@ $ROOT of project trees for things which can be checked out separately. -->
|
||||
|
||||
<div>
|
||||
<p>As mentioned earlier, LLVM projects are organized into
|
||||
logical <em>components</em>. Every component is typically grouped into it's
|
||||
logical <em>components</em>. Every component is typically grouped into its
|
||||
own subdirectory. Generally, a component is organized around a coherent group
|
||||
of sources which have some kind of clear API separation from other parts of
|
||||
the code.</p>
|
||||
@ -190,7 +190,7 @@ required_libraries = Archive BitReader Core Support TransformUtils
|
||||
number in order for files with multiple components ("component_0",
|
||||
"component_1", and so on).<p>
|
||||
|
||||
<p><b>Section names not matches this format (or the "common" section) are
|
||||
<p><b>Section names not matching this format (or the "common" section) are
|
||||
currently unused and are disallowed.</b></p>
|
||||
|
||||
<p>Every component is defined by the properties in the section. The exact list
|
||||
@ -212,7 +212,7 @@ required_libraries = Archive BitReader Core Support TransformUtils
|
||||
<li><i>parent</i> <b>[required]</b>
|
||||
<p>The name of the logical parent of the component. Components are
|
||||
organized into a logical tree to make it easier to navigate and organize
|
||||
groups of components. The parent's have no semantics as far as the project
|
||||
groups of components. The parents have no semantics as far as the project
|
||||
build is concerned, however. Typically, the parent will be the main
|
||||
component of the parent directory.</p>
|
||||
|
||||
@ -263,7 +263,7 @@ required_libraries = Archive BitReader Core Support TransformUtils
|
||||
<p>If given, a list of the names of Library or LibraryGroup components
|
||||
which must also be linked in whenever this library is used. That is,
|
||||
the link time dependencies for this component. When tools are built,
|
||||
the build system will include the transitive closer of
|
||||
the build system will include the transitive closure of
|
||||
all <i>required_libraries</i> for the components the tool needs.</p></li>
|
||||
|
||||
<li><i>add_to_library_groups</i> <b>[optional]</b>
|
||||
|
@ -103,7 +103,7 @@
|
||||
<li><a href="#metadata">Metadata Nodes and Metadata Strings</a>
|
||||
<ol>
|
||||
<li><a href="#tbaa">'<tt>tbaa</tt>' Metadata</a></li>
|
||||
<li><a href="#fpaccuracy">'<tt>fpaccuracy</tt>' Metadata</a></li>
|
||||
<li><a href="#fpmath">'<tt>fpmath</tt>' Metadata</a></li>
|
||||
<li><a href="#range">'<tt>range</tt>' Metadata</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
@ -3000,16 +3000,16 @@ call void @llvm.dbg.value(metadata !24, i64 0, metadata !25)
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="fpaccuracy">'<tt>fpaccuracy</tt>' Metadata</a>
|
||||
<a name="fpmath">'<tt>fpmath</tt>' Metadata</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<p><tt>fpaccuracy</tt> metadata may be attached to any instruction of floating
|
||||
point type. It expresses the maximum relative error allowed in the result
|
||||
of that instruction, in ULPs, thus potentially allowing the compiler to use
|
||||
a more efficient but less accurate method of computing it.
|
||||
ULP is defined as follows:</p>
|
||||
<p><tt>fpmath</tt> metadata may be attached to any instruction of floating point
|
||||
type. It can be used to express the maximum acceptable error in the result of
|
||||
that instruction, in ULPs, thus potentially allowing the compiler to use a
|
||||
more efficient but less accurate method of computing it. ULP is defined as
|
||||
follows:</p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
@ -3021,13 +3021,12 @@ call void @llvm.dbg.value(metadata !24, i64 0, metadata !25)
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p>The metadata node shall consist of a single non-negative floating
|
||||
point number representing the maximum relative error. For example,
|
||||
2.5 ULP:</p>
|
||||
<p>The metadata node shall consist of a single positive floating point number
|
||||
representing the maximum relative error, for example:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
!0 = metadata !{ float 2.5 }
|
||||
!0 = metadata !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -8506,7 +8505,7 @@ LLVM</a>.</p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2012-04-10 10:22:43 +0200 (Tue, 10 Apr 2012) $
|
||||
Last modified: $Date: 2012-04-16 21:39:33 +0200 (Mon, 16 Apr 2012) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -1734,6 +1734,9 @@ already in the table, and each pair in the map is store in a single allocation
|
||||
|
||||
<p>StringMap also provides query methods that take byte ranges, so it only ever
|
||||
copies a string if a value is inserted into the table.</p>
|
||||
|
||||
<p>StringMap iteratation order, however, is not guaranteed to be deterministic,
|
||||
so any uses which require that should instead use a std::map.</p>
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
@ -4125,7 +4128,7 @@ arguments. An argument has a pointer to the parent Function.</p>
|
||||
<a href="mailto:dhurjati@cs.uiuc.edu">Dinakar Dhurjati</a> and
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2012-03-27 13:25:16 +0200 (Tue, 27 Mar 2012) $
|
||||
Last modified: $Date: 2012-04-18 22:28:55 +0200 (Wed, 18 Apr 2012) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -206,6 +206,36 @@ Release Notes</a>.</h1>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--=========================================================================-->
|
||||
<h3>
|
||||
<a name="Polly">Polly: Polyhedral Optimizer</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p><a href="http://polly.llvm.org/">Polly</a> is an <em>experimental</em>
|
||||
optimizer for data locality and parallelism. It currently provides high-level
|
||||
loop optimizations and automatic parallelisation (using the OpenMP run time).
|
||||
Work in the area of automatic SIMD and accelerator code generation was
|
||||
started.
|
||||
|
||||
<p>Within the LLVM 3.1 time-frame there were the following highlights:</p>
|
||||
|
||||
<ul>
|
||||
<li>Polly became an official LLVM project</li>
|
||||
<li>Polly can be loaded directly into clang (Enabled by '-O3 -mllvm -polly'
|
||||
)</li>
|
||||
<li>An automatic scheduling optimizer (derived from <a
|
||||
href="http://pluto-compiler.sourceforge.net/">Pluto</a>) was integrated. It
|
||||
performs loop transformations to optimize for data-locality and parallelism.
|
||||
The transformations include, but are not limited to interchange, fusion,
|
||||
fission, skewing and tiling.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
@ -269,6 +299,8 @@ Release Notes</a>.</h1>
|
||||
Support to model instruction bundling / packing.</li>
|
||||
<li><a href="#armintegratedassembler">ARM Integrated Assembler</a>,
|
||||
A full featured assembler and direct-to-object support for ARM.</li>
|
||||
<li><a href="#blockplacement">Basic Block Placement</a>
|
||||
Probability driven basic block placement.</li>
|
||||
<li>....</li>
|
||||
</ul>
|
||||
|
||||
@ -292,6 +324,9 @@ Release Notes</a>.</h1>
|
||||
module as a whole to LLVM subsystems.</li>
|
||||
<li>Loads can now have range metadata attached to them to describe the
|
||||
possible values being loaded.</li>
|
||||
<li>Inline cost heuristics have been completely overhauled and now closely
|
||||
model constant propagation through call sites, disregard trivially dead
|
||||
code costs, and can model C++ STL iterator patterns.</li>
|
||||
<li>....</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -308,6 +343,14 @@ Release Notes</a>.</h1>
|
||||
optimizers:</p>
|
||||
|
||||
<ul>
|
||||
<li>The loop unroll pass now is able to unroll loops with run-time trip counts.
|
||||
This feature is turned off by default, and is enabled with the
|
||||
<code>-unroll-runtime</code> flag.</li>
|
||||
<li>A new basic-block autovectorization pass is available. Pass
|
||||
<code>-vectorize</code> to run this pass along with some associated
|
||||
post-vectorization cleanup passes. For more information, see the EuroLLVM
|
||||
2012 slides: <a href="http://llvm.org/devmtg/2012-04-12/Slides/Hal_Finkel.pdf">
|
||||
Autovectorization with LLVM</a>.</li>
|
||||
<li>....</li>
|
||||
</ul>
|
||||
|
||||
@ -373,6 +416,19 @@ Release Notes</a>.</h1>
|
||||
target's schedule description which can be queried to determine
|
||||
legal groupings of instructions in a bundle.</p>
|
||||
|
||||
<p> We have added a new target independent VLIW packetizer based on the
|
||||
DFA infrastructure to group machine instructions into bundles.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<h4>
|
||||
<a name="blockplacement">Basic Block Placement</a>
|
||||
</h4>
|
||||
<div>
|
||||
<p>A probability based block placement and code layout algorithm was added to
|
||||
LLVM's code generator. This layout pass supports probabilities derived from
|
||||
static heuristics as well as source code annotations such as
|
||||
<code>__builtin_expect</code>.</p>
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
@ -391,6 +447,7 @@ Release Notes</a>.</h1>
|
||||
times and better support for different calling conventions. The old WINCALL
|
||||
instructions are no longer needed.</li>
|
||||
<li>DW2 Exception Handling is enabled on Cygwin and MinGW.</li>
|
||||
<li>Support for implicit TLS model used with MS VC runtime</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@ -451,6 +508,8 @@ syntax, there are still significant gaps in that support.</p>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Support for Qualcomm's Hexagon VLIW processor has been added.</p>
|
||||
|
||||
<ul>
|
||||
<li>....</li>
|
||||
|
||||
@ -524,6 +583,8 @@ syntax, there are still significant gaps in that support.</p>
|
||||
<li><code>llvm::getTrapFunctionName()</code></li>
|
||||
<li><code>llvm::EnableSegmentedStacks</code></li>
|
||||
</ul></li>
|
||||
<li>The MDBuilder class has been added to simplify the creation of
|
||||
metadata.</li>
|
||||
<li>....</li>
|
||||
</ul>
|
||||
|
||||
@ -621,7 +682,7 @@ syntax, there are still significant gaps in that support.</p>
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2012-04-12 17:17:35 +0200 (Thu, 12 Apr 2012) $
|
||||
Last modified: $Date: 2012-04-17 03:13:53 +0200 (Tue, 17 Apr 2012) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -299,15 +299,15 @@ clang/test directory. </p>
|
||||
you.</p>
|
||||
|
||||
<p>In order for the regression tests to work, each directory of tests must
|
||||
have a <tt>dg.exp</tt> file. Lit looks for this file to determine how to
|
||||
run the tests. This file is just a Tcl script and it can do anything you want,
|
||||
have a <tt>lit.local.cfg</tt> file. Lit looks for this file to determine how
|
||||
to run the tests. This file is just Python code and thus is very flexible,
|
||||
but we've standardized it for the LLVM regression tests. If you're adding a
|
||||
directory of tests, just copy <tt>dg.exp</tt> from another directory to get
|
||||
running. The standard <tt>dg.exp</tt> simply loads a Tcl library
|
||||
(<tt>test/lib/llvm.exp</tt>) and calls the <tt>llvm_runtests</tt> function
|
||||
defined in that library with a list of file names to run. The names are
|
||||
obtained by using Tcl's glob command. Any directory that contains only
|
||||
directories does not need the <tt>dg.exp</tt> file.</p>
|
||||
directory of tests, just copy <tt>lit.local.cfg</tt> from another directory to
|
||||
get running. The standard <tt>lit.local.cfg</tt> simply specifies which files
|
||||
to look in for tests. Any directory that contains only directories does not
|
||||
need the <tt>lit.local.cfg</tt> file. Read the
|
||||
<a href="http://llvm.org/cmds/lit.html">Lit documentation</a> for more
|
||||
information. </p>
|
||||
|
||||
<p>The <tt>llvm-runtests</tt> function looks at each file that is passed to
|
||||
it and gathers any lines together that match "RUN:". These are the "RUN" lines
|
||||
@ -473,7 +473,7 @@ negatives).</p>
|
||||
llc, then pipe the output of llc into FileCheck. This means that FileCheck will
|
||||
be verifying its standard input (the llc output) against the filename argument
|
||||
specified (the original .ll file specified by "%s"). To see how this works,
|
||||
lets look at the rest of the .ll file (after the RUN line):</p>
|
||||
let's look at the rest of the .ll file (after the RUN line):</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
@ -900,7 +900,7 @@ the <a href="TestSuiteMakefileGuide.html">Test Suite Makefile Guide.</a></p>
|
||||
|
||||
John T. Criswell, Daniel Dunbar, Reid Spencer, and Tanya Lattner<br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2012-03-27 13:25:16 +0200 (Tue, 27 Mar 2012) $
|
||||
Last modified: $Date: 2012-04-18 10:02:25 +0200 (Wed, 18 Apr 2012) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -250,12 +250,6 @@ extern void
|
||||
lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
|
||||
int nargs);
|
||||
|
||||
/**
|
||||
* Enables the internalize pass during LTO optimizations.
|
||||
*/
|
||||
extern void
|
||||
lto_codegen_set_whole_program_optimization(lto_code_gen_t cg);
|
||||
|
||||
/**
|
||||
* Adds to a list of all global symbols that must exist in the final
|
||||
* generated code. If a function is not listed, it might be
|
||||
|
@ -126,9 +126,6 @@ class SmallPtrSetImpl {
|
||||
private:
|
||||
bool isSmall() const { return CurArray == SmallArray; }
|
||||
|
||||
unsigned Hash(const void *Ptr) const {
|
||||
return static_cast<unsigned>(((uintptr_t)Ptr >> 4) & (CurArraySize-1));
|
||||
}
|
||||
const void * const *FindBucketFor(const void *Ptr) const;
|
||||
void shrink_and_clear();
|
||||
|
||||
|
@ -239,7 +239,7 @@ class StringMap : public StringMapImpl {
|
||||
explicit StringMap(AllocatorTy A)
|
||||
: StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
|
||||
|
||||
explicit StringMap(const StringMap &RHS)
|
||||
StringMap(const StringMap &RHS)
|
||||
: StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {
|
||||
assert(RHS.empty() &&
|
||||
"Copy ctor from non-empty stringmap not implemented yet!");
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -37,7 +36,7 @@ class MachineInstr;
|
||||
class MachineLoopInfo;
|
||||
class MachineDominatorTree;
|
||||
class InstrItineraryData;
|
||||
class DefaultVLIWScheduler;
|
||||
class ScheduleDAGInstrs;
|
||||
class SUnit;
|
||||
|
||||
class DFAPacketizer {
|
||||
@ -78,8 +77,6 @@ class DFAPacketizer {
|
||||
// reserveResources - Reserve the resources occupied by a machine
|
||||
// instruction and change the current state to reflect that change.
|
||||
void reserveResources(llvm::MachineInstr *MI);
|
||||
|
||||
const InstrItineraryData *getInstrItins() const { return InstrItins; }
|
||||
};
|
||||
|
||||
// VLIWPacketizerList - Implements a simple VLIW packetizer using DFA. The
|
||||
@ -90,21 +87,20 @@ class DFAPacketizer {
|
||||
// and machine resource is marked as taken. If any dependency is found, a target
|
||||
// API call is made to prune the dependence.
|
||||
class VLIWPacketizerList {
|
||||
protected:
|
||||
const TargetMachine &TM;
|
||||
const MachineFunction &MF;
|
||||
const TargetInstrInfo *TII;
|
||||
|
||||
// The VLIW Scheduler.
|
||||
DefaultVLIWScheduler *VLIWScheduler;
|
||||
// Encapsulate data types not exposed to the target interface.
|
||||
ScheduleDAGInstrs *SchedulerImpl;
|
||||
|
||||
protected:
|
||||
// Vector of instructions assigned to the current packet.
|
||||
std::vector<MachineInstr*> CurrentPacketMIs;
|
||||
// DFA resource tracker.
|
||||
DFAPacketizer *ResourceTracker;
|
||||
|
||||
// Generate MI -> SU map.
|
||||
std::map<MachineInstr*, SUnit*> MIToSUnit;
|
||||
// Scheduling units.
|
||||
std::vector<SUnit> SUnits;
|
||||
|
||||
public:
|
||||
VLIWPacketizerList(
|
||||
@ -122,32 +118,17 @@ class VLIWPacketizerList {
|
||||
DFAPacketizer *getResourceTracker() {return ResourceTracker;}
|
||||
|
||||
// addToPacket - Add MI to the current packet.
|
||||
virtual MachineBasicBlock::iterator addToPacket(MachineInstr *MI) {
|
||||
MachineBasicBlock::iterator MII = MI;
|
||||
CurrentPacketMIs.push_back(MI);
|
||||
ResourceTracker->reserveResources(MI);
|
||||
return MII;
|
||||
}
|
||||
void addToPacket(MachineInstr *MI);
|
||||
|
||||
// endPacket - End the current packet.
|
||||
void endPacket(MachineBasicBlock *MBB, MachineInstr *MI);
|
||||
|
||||
// initPacketizerState - perform initialization before packetizing
|
||||
// an instruction. This function is supposed to be overrided by
|
||||
// the target dependent packetizer.
|
||||
virtual void initPacketizerState(void) { return; }
|
||||
void endPacket(MachineBasicBlock *MBB, MachineInstr *I);
|
||||
|
||||
// ignorePseudoInstruction - Ignore bundling of pseudo instructions.
|
||||
virtual bool ignorePseudoInstruction(MachineInstr *I,
|
||||
MachineBasicBlock *MBB) {
|
||||
return false;
|
||||
}
|
||||
bool ignorePseudoInstruction(MachineInstr *I, MachineBasicBlock *MBB);
|
||||
|
||||
// isSoloInstruction - return true if instruction MI can not be packetized
|
||||
// with any other instruction, which means that MI itself is a packet.
|
||||
virtual bool isSoloInstruction(MachineInstr *MI) {
|
||||
return true;
|
||||
}
|
||||
// isSoloInstruction - return true if instruction I must end previous
|
||||
// packet.
|
||||
bool isSoloInstruction(MachineInstr *I);
|
||||
|
||||
// isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ
|
||||
// together.
|
||||
@ -160,7 +141,6 @@ class VLIWPacketizerList {
|
||||
virtual bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ class TargetPassConfig : public ImmutablePass {
|
||||
|
||||
protected:
|
||||
TargetMachine *TM;
|
||||
PassManagerBase &PM;
|
||||
PassManagerBase *PM;
|
||||
PassConfigImpl *Impl; // Internal data structures
|
||||
bool Initialized; // Flagged after all passes are configured.
|
||||
|
||||
|
@ -181,6 +181,13 @@ namespace llvm {
|
||||
/// the def-side latency only.
|
||||
bool UnitLatencies;
|
||||
|
||||
/// The standard DAG builder does not normally include terminators as DAG
|
||||
/// nodes because it does not create the necessary dependencies to prevent
|
||||
/// reordering. A specialized scheduler can overide
|
||||
/// TargetInstrInfo::isSchedulingBoundary then enable this flag to indicate
|
||||
/// it has taken responsibility for scheduling the terminator correctly.
|
||||
bool CanHandleTerminators;
|
||||
|
||||
/// State specific to the current scheduling region.
|
||||
/// ------------------------------------------------
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
@ -33,8 +34,7 @@ namespace llvm {
|
||||
/// SlotIndexes pass. It should not be used directly. See the
|
||||
/// SlotIndex & SlotIndexes classes for the public interface to this
|
||||
/// information.
|
||||
class IndexListEntry {
|
||||
IndexListEntry *next, *prev;
|
||||
class IndexListEntry : public ilist_node<IndexListEntry> {
|
||||
MachineInstr *mi;
|
||||
unsigned index;
|
||||
|
||||
@ -51,31 +51,26 @@ namespace llvm {
|
||||
void setIndex(unsigned index) {
|
||||
this->index = index;
|
||||
}
|
||||
|
||||
IndexListEntry* getNext() { return next; }
|
||||
const IndexListEntry* getNext() const { return next; }
|
||||
void setNext(IndexListEntry *next) {
|
||||
this->next = next;
|
||||
}
|
||||
|
||||
IndexListEntry* getPrev() { return prev; }
|
||||
const IndexListEntry* getPrev() const { return prev; }
|
||||
void setPrev(IndexListEntry *prev) {
|
||||
this->prev = prev;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialize PointerLikeTypeTraits for IndexListEntry.
|
||||
template <>
|
||||
class PointerLikeTypeTraits<IndexListEntry*> {
|
||||
struct ilist_traits<IndexListEntry> : public ilist_default_traits<IndexListEntry> {
|
||||
private:
|
||||
mutable ilist_half_node<IndexListEntry> Sentinel;
|
||||
public:
|
||||
static inline void* getAsVoidPointer(IndexListEntry *p) {
|
||||
return p;
|
||||
IndexListEntry *createSentinel() const {
|
||||
return static_cast<IndexListEntry*>(&Sentinel);
|
||||
}
|
||||
static inline IndexListEntry* getFromVoidPointer(void *p) {
|
||||
return static_cast<IndexListEntry*>(p);
|
||||
}
|
||||
enum { NumLowBitsAvailable = 3 };
|
||||
void destroySentinel(IndexListEntry *) const {}
|
||||
|
||||
IndexListEntry *provideInitialHead() const { return createSentinel(); }
|
||||
IndexListEntry *ensureHead(IndexListEntry*) const { return createSentinel(); }
|
||||
static void noteHead(IndexListEntry*, IndexListEntry*) {}
|
||||
void deleteNode(IndexListEntry *N) {}
|
||||
|
||||
private:
|
||||
void createNode(const IndexListEntry &);
|
||||
};
|
||||
|
||||
/// SlotIndex - An opaque wrapper around machine indexes.
|
||||
@ -112,13 +107,13 @@ namespace llvm {
|
||||
SlotIndex(IndexListEntry *entry, unsigned slot)
|
||||
: lie(entry, slot) {}
|
||||
|
||||
IndexListEntry& entry() const {
|
||||
IndexListEntry* listEntry() const {
|
||||
assert(isValid() && "Attempt to compare reserved index.");
|
||||
return *lie.getPointer();
|
||||
return lie.getPointer();
|
||||
}
|
||||
|
||||
int getIndex() const {
|
||||
return entry().getIndex() | getSlot();
|
||||
return listEntry()->getIndex() | getSlot();
|
||||
}
|
||||
|
||||
/// Returns the slot for this SlotIndex.
|
||||
@ -150,8 +145,7 @@ namespace llvm {
|
||||
SlotIndex() : lie(0, 0) {}
|
||||
|
||||
// Construct a new slot index from the given one, and set the slot.
|
||||
SlotIndex(const SlotIndex &li, Slot s)
|
||||
: lie(&li.entry(), unsigned(s)) {
|
||||
SlotIndex(const SlotIndex &li, Slot s) : lie(li.listEntry(), unsigned(s)) {
|
||||
assert(lie.getPointer() != 0 &&
|
||||
"Attempt to construct index with 0 pointer.");
|
||||
}
|
||||
@ -179,7 +173,7 @@ namespace llvm {
|
||||
bool operator!=(SlotIndex other) const {
|
||||
return lie != other.lie;
|
||||
}
|
||||
|
||||
|
||||
/// Compare two SlotIndex objects. Return true if the first index
|
||||
/// is strictly lower than the second.
|
||||
bool operator<(SlotIndex other) const {
|
||||
@ -211,7 +205,7 @@ namespace llvm {
|
||||
/// isEarlierInstr - Return true if A refers to an instruction earlier than
|
||||
/// B. This is equivalent to A < B && !isSameInstr(A, B).
|
||||
static bool isEarlierInstr(SlotIndex A, SlotIndex B) {
|
||||
return A.entry().getIndex() < B.entry().getIndex();
|
||||
return A.listEntry()->getIndex() < B.listEntry()->getIndex();
|
||||
}
|
||||
|
||||
/// Return the distance from this index to the given one.
|
||||
@ -236,25 +230,25 @@ namespace llvm {
|
||||
/// is the one associated with the Slot_Block slot for the instruction
|
||||
/// pointed to by this index.
|
||||
SlotIndex getBaseIndex() const {
|
||||
return SlotIndex(&entry(), Slot_Block);
|
||||
return SlotIndex(listEntry(), Slot_Block);
|
||||
}
|
||||
|
||||
/// Returns the boundary index for associated with this index. The boundary
|
||||
/// index is the one associated with the Slot_Block slot for the instruction
|
||||
/// pointed to by this index.
|
||||
SlotIndex getBoundaryIndex() const {
|
||||
return SlotIndex(&entry(), Slot_Dead);
|
||||
return SlotIndex(listEntry(), Slot_Dead);
|
||||
}
|
||||
|
||||
/// Returns the register use/def slot in the current instruction for a
|
||||
/// normal or early-clobber def.
|
||||
SlotIndex getRegSlot(bool EC = false) const {
|
||||
return SlotIndex(&entry(), EC ? Slot_EarlyClobber : Slot_Register);
|
||||
return SlotIndex(listEntry(), EC ? Slot_EarlyClobber : Slot_Register);
|
||||
}
|
||||
|
||||
/// Returns the dead def kill slot for the current instruction.
|
||||
SlotIndex getDeadSlot() const {
|
||||
return SlotIndex(&entry(), Slot_Dead);
|
||||
return SlotIndex(listEntry(), Slot_Dead);
|
||||
}
|
||||
|
||||
/// Returns the next slot in the index list. This could be either the
|
||||
@ -266,15 +260,15 @@ namespace llvm {
|
||||
SlotIndex getNextSlot() const {
|
||||
Slot s = getSlot();
|
||||
if (s == Slot_Dead) {
|
||||
return SlotIndex(entry().getNext(), Slot_Block);
|
||||
return SlotIndex(listEntry()->getNextNode(), Slot_Block);
|
||||
}
|
||||
return SlotIndex(&entry(), s + 1);
|
||||
return SlotIndex(listEntry(), s + 1);
|
||||
}
|
||||
|
||||
/// Returns the next index. This is the index corresponding to the this
|
||||
/// index's slot, but for the next instruction.
|
||||
SlotIndex getNextIndex() const {
|
||||
return SlotIndex(entry().getNext(), getSlot());
|
||||
return SlotIndex(listEntry()->getNextNode(), getSlot());
|
||||
}
|
||||
|
||||
/// Returns the previous slot in the index list. This could be either the
|
||||
@ -286,15 +280,15 @@ namespace llvm {
|
||||
SlotIndex getPrevSlot() const {
|
||||
Slot s = getSlot();
|
||||
if (s == Slot_Block) {
|
||||
return SlotIndex(entry().getPrev(), Slot_Dead);
|
||||
return SlotIndex(listEntry()->getPrevNode(), Slot_Dead);
|
||||
}
|
||||
return SlotIndex(&entry(), s - 1);
|
||||
return SlotIndex(listEntry(), s - 1);
|
||||
}
|
||||
|
||||
/// Returns the previous index. This is the index corresponding to this
|
||||
/// index's slot, but for the previous instruction.
|
||||
SlotIndex getPrevIndex() const {
|
||||
return SlotIndex(entry().getPrev(), getSlot());
|
||||
return SlotIndex(listEntry()->getPrevNode(), getSlot());
|
||||
}
|
||||
|
||||
};
|
||||
@ -315,7 +309,7 @@ namespace llvm {
|
||||
return (LHS == RHS);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <> struct isPodLike<SlotIndex> { static const bool value = true; };
|
||||
|
||||
|
||||
@ -346,8 +340,10 @@ namespace llvm {
|
||||
class SlotIndexes : public MachineFunctionPass {
|
||||
private:
|
||||
|
||||
typedef ilist<IndexListEntry> IndexList;
|
||||
IndexList indexList;
|
||||
|
||||
MachineFunction *mf;
|
||||
IndexListEntry *indexListHead;
|
||||
unsigned functionSize;
|
||||
|
||||
typedef DenseMap<const MachineInstr*, SlotIndex> Mi2IndexMap;
|
||||
@ -374,84 +370,18 @@ namespace llvm {
|
||||
return entry;
|
||||
}
|
||||
|
||||
void initList() {
|
||||
assert(indexListHead == 0 && "Zero entry non-null at initialisation.");
|
||||
indexListHead = createEntry(0, ~0U);
|
||||
indexListHead->setNext(0);
|
||||
indexListHead->setPrev(indexListHead);
|
||||
}
|
||||
|
||||
void clearList() {
|
||||
indexListHead = 0;
|
||||
ileAllocator.Reset();
|
||||
}
|
||||
|
||||
IndexListEntry* getTail() {
|
||||
assert(indexListHead != 0 && "Call to getTail on uninitialized list.");
|
||||
return indexListHead->getPrev();
|
||||
}
|
||||
|
||||
const IndexListEntry* getTail() const {
|
||||
assert(indexListHead != 0 && "Call to getTail on uninitialized list.");
|
||||
return indexListHead->getPrev();
|
||||
}
|
||||
|
||||
// Returns true if the index list is empty.
|
||||
bool empty() const { return (indexListHead == getTail()); }
|
||||
|
||||
IndexListEntry* front() {
|
||||
assert(!empty() && "front() called on empty index list.");
|
||||
return indexListHead;
|
||||
}
|
||||
|
||||
const IndexListEntry* front() const {
|
||||
assert(!empty() && "front() called on empty index list.");
|
||||
return indexListHead;
|
||||
}
|
||||
|
||||
IndexListEntry* back() {
|
||||
assert(!empty() && "back() called on empty index list.");
|
||||
return getTail()->getPrev();
|
||||
}
|
||||
|
||||
const IndexListEntry* back() const {
|
||||
assert(!empty() && "back() called on empty index list.");
|
||||
return getTail()->getPrev();
|
||||
}
|
||||
|
||||
/// Insert a new entry before itr.
|
||||
void insert(IndexListEntry *itr, IndexListEntry *val) {
|
||||
assert(itr != 0 && "itr should not be null.");
|
||||
IndexListEntry *prev = itr->getPrev();
|
||||
val->setNext(itr);
|
||||
val->setPrev(prev);
|
||||
|
||||
if (itr != indexListHead) {
|
||||
prev->setNext(val);
|
||||
}
|
||||
else {
|
||||
indexListHead = val;
|
||||
}
|
||||
itr->setPrev(val);
|
||||
}
|
||||
|
||||
/// Push a new entry on to the end of the list.
|
||||
void push_back(IndexListEntry *val) {
|
||||
insert(getTail(), val);
|
||||
}
|
||||
|
||||
/// Renumber locally after inserting newEntry.
|
||||
void renumberIndexes(IndexListEntry *newEntry);
|
||||
/// Renumber locally after inserting curItr.
|
||||
void renumberIndexes(IndexList::iterator curItr);
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
SlotIndexes() : MachineFunctionPass(ID), indexListHead(0) {
|
||||
SlotIndexes() : MachineFunctionPass(ID) {
|
||||
initializeSlotIndexesPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &au) const;
|
||||
virtual void releaseMemory();
|
||||
virtual void releaseMemory();
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &fn);
|
||||
|
||||
@ -463,22 +393,21 @@ namespace llvm {
|
||||
|
||||
/// Returns the zero index for this analysis.
|
||||
SlotIndex getZeroIndex() {
|
||||
assert(front()->getIndex() == 0 && "First index is not 0?");
|
||||
return SlotIndex(front(), 0);
|
||||
assert(indexList.front().getIndex() == 0 && "First index is not 0?");
|
||||
return SlotIndex(&indexList.front(), 0);
|
||||
}
|
||||
|
||||
/// Returns the base index of the last slot in this analysis.
|
||||
SlotIndex getLastIndex() {
|
||||
return SlotIndex(back(), 0);
|
||||
return SlotIndex(&indexList.back(), 0);
|
||||
}
|
||||
|
||||
/// Returns the distance between the highest and lowest indexes allocated
|
||||
/// so far.
|
||||
unsigned getIndexesLength() const {
|
||||
assert(front()->getIndex() == 0 &&
|
||||
assert(indexList.front().getIndex() == 0 &&
|
||||
"Initial index isn't zero?");
|
||||
|
||||
return back()->getIndex();
|
||||
return indexList.back().getIndex();
|
||||
}
|
||||
|
||||
/// Returns the number of instructions in the function.
|
||||
@ -503,19 +432,15 @@ namespace llvm {
|
||||
/// Returns the instruction for the given index, or null if the given
|
||||
/// index has no instruction associated with it.
|
||||
MachineInstr* getInstructionFromIndex(SlotIndex index) const {
|
||||
return index.isValid() ? index.entry().getInstr() : 0;
|
||||
return index.isValid() ? index.listEntry()->getInstr() : 0;
|
||||
}
|
||||
|
||||
/// Returns the next non-null index.
|
||||
SlotIndex getNextNonNullIndex(SlotIndex index) {
|
||||
SlotIndex nextNonNull = index.getNextIndex();
|
||||
|
||||
while (&nextNonNull.entry() != getTail() &&
|
||||
getInstructionFromIndex(nextNonNull) == 0) {
|
||||
nextNonNull = nextNonNull.getNextIndex();
|
||||
}
|
||||
|
||||
return nextNonNull;
|
||||
IndexList::iterator itr(index.listEntry());
|
||||
++itr;
|
||||
while (itr != indexList.end() && itr->getInstr() == 0) { ++itr; }
|
||||
return SlotIndex(itr, index.getSlot());
|
||||
}
|
||||
|
||||
/// getIndexBefore - Returns the index of the last indexed instruction
|
||||
@ -659,31 +584,31 @@ namespace llvm {
|
||||
assert(mi->getParent() != 0 && "Instr must be added to function.");
|
||||
|
||||
// Get the entries where mi should be inserted.
|
||||
IndexListEntry *prevEntry, *nextEntry;
|
||||
IndexList::iterator prevItr, nextItr;
|
||||
if (Late) {
|
||||
// Insert mi's index immediately before the following instruction.
|
||||
nextEntry = &getIndexAfter(mi).entry();
|
||||
prevEntry = nextEntry->getPrev();
|
||||
nextItr = getIndexAfter(mi).listEntry();
|
||||
prevItr = prior(nextItr);
|
||||
} else {
|
||||
// Insert mi's index immediately after the preceeding instruction.
|
||||
prevEntry = &getIndexBefore(mi).entry();
|
||||
nextEntry = prevEntry->getNext();
|
||||
prevItr = getIndexBefore(mi).listEntry();
|
||||
nextItr = llvm::next(prevItr);
|
||||
}
|
||||
|
||||
// Get a number for the new instr, or 0 if there's no room currently.
|
||||
// In the latter case we'll force a renumber later.
|
||||
unsigned dist = ((nextEntry->getIndex() - prevEntry->getIndex())/2) & ~3u;
|
||||
unsigned newNumber = prevEntry->getIndex() + dist;
|
||||
unsigned dist = ((nextItr->getIndex() - prevItr->getIndex())/2) & ~3u;
|
||||
unsigned newNumber = prevItr->getIndex() + dist;
|
||||
|
||||
// Insert a new list entry for mi.
|
||||
IndexListEntry *newEntry = createEntry(mi, newNumber);
|
||||
insert(nextEntry, newEntry);
|
||||
IndexList::iterator newItr =
|
||||
indexList.insert(nextItr, createEntry(mi, newNumber));
|
||||
|
||||
// Renumber locally if we need to.
|
||||
if (dist == 0)
|
||||
renumberIndexes(newEntry);
|
||||
renumberIndexes(newItr);
|
||||
|
||||
SlotIndex newIndex(newEntry, SlotIndex::Slot_Block);
|
||||
SlotIndex newIndex(&*newItr, SlotIndex::Slot_Block);
|
||||
mi2iMap.insert(std::make_pair(mi, newIndex));
|
||||
return newIndex;
|
||||
}
|
||||
@ -694,7 +619,7 @@ namespace llvm {
|
||||
// MachineInstr -> index mappings
|
||||
Mi2IndexMap::iterator mi2iItr = mi2iMap.find(mi);
|
||||
if (mi2iItr != mi2iMap.end()) {
|
||||
IndexListEntry *miEntry(&mi2iItr->second.entry());
|
||||
IndexListEntry *miEntry(mi2iItr->second.listEntry());
|
||||
assert(miEntry->getInstr() == mi && "Instruction indexes broken.");
|
||||
// FIXME: Eventually we want to actually delete these indexes.
|
||||
miEntry->setInstr(0);
|
||||
@ -709,7 +634,7 @@ namespace llvm {
|
||||
if (mi2iItr == mi2iMap.end())
|
||||
return;
|
||||
SlotIndex replaceBaseIndex = mi2iItr->second;
|
||||
IndexListEntry *miEntry(&replaceBaseIndex.entry());
|
||||
IndexListEntry *miEntry(replaceBaseIndex.listEntry());
|
||||
assert(miEntry->getInstr() == mi &&
|
||||
"Mismatched instruction in index tables.");
|
||||
miEntry->setInstr(newMI);
|
||||
@ -726,13 +651,13 @@ namespace llvm {
|
||||
IndexListEntry *nextEntry = 0;
|
||||
|
||||
if (nextMBB == mbb->getParent()->end()) {
|
||||
nextEntry = getTail();
|
||||
nextEntry = indexList.end();
|
||||
} else {
|
||||
nextEntry = &getMBBStartIdx(nextMBB).entry();
|
||||
nextEntry = getMBBStartIdx(nextMBB).listEntry();
|
||||
}
|
||||
|
||||
insert(nextEntry, startEntry);
|
||||
insert(nextEntry, stopEntry);
|
||||
indexList.insert(nextEntry, startEntry);
|
||||
indexList.insert(nextEntry, stopEntry);
|
||||
|
||||
SlotIndex startIdx(startEntry, SlotIndex::Slot_Block);
|
||||
SlotIndex endIdx(nextEntry, SlotIndex::Slot_Block);
|
||||
@ -766,4 +691,4 @@ namespace llvm {
|
||||
|
||||
}
|
||||
|
||||
#endif // LLVM_CODEGEN_LIVEINDEX_H
|
||||
#endif // LLVM_CODEGEN_SLOTINDEXES_H
|
||||
|
@ -11,9 +11,6 @@
|
||||
/* Relative directory for resource files */
|
||||
#define CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}"
|
||||
|
||||
/* Directory wherelibstdc++ is installed. */
|
||||
#define GCC_INSTALL_PREFIX "${GCC_INSTALL_PREFIX}"
|
||||
|
||||
/* Directories clang will search for headers */
|
||||
#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}"
|
||||
|
||||
|
@ -12,6 +12,9 @@
|
||||
/* Directories clang will search for headers */
|
||||
#undef C_INCLUDE_DIRS
|
||||
|
||||
/* Default <path> to all compiler invocations for --sysroot=<path>. */
|
||||
#undef DEFAULT_SYSROOT
|
||||
|
||||
/* Define if position independent code is enabled */
|
||||
#undef ENABLE_PIC
|
||||
|
||||
|
@ -1091,20 +1091,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
GCCBuiltin<"__builtin_ia32_vperm2f128_si256">,
|
||||
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty,
|
||||
llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>;
|
||||
|
||||
def int_x86_avx_vpermil_pd :
|
||||
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
|
||||
llvm_i8_ty], [IntrNoMem]>;
|
||||
def int_x86_avx_vpermil_ps :
|
||||
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
|
||||
llvm_i8_ty], [IntrNoMem]>;
|
||||
|
||||
def int_x86_avx_vpermil_pd_256 :
|
||||
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty,
|
||||
llvm_i8_ty], [IntrNoMem]>;
|
||||
def int_x86_avx_vpermil_ps_256 :
|
||||
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty,
|
||||
llvm_i8_ty], [IntrNoMem]>;
|
||||
}
|
||||
|
||||
// Vector blend
|
||||
@ -1659,15 +1645,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_avx2_permd : GCCBuiltin<"__builtin_ia32_permvarsi256">,
|
||||
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_avx2_permq : GCCBuiltin<"__builtin_ia32_permdi256">,
|
||||
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i8_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_avx2_permps : GCCBuiltin<"__builtin_ia32_permvarsf256">,
|
||||
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_avx2_permpd : GCCBuiltin<"__builtin_ia32_permdf256">,
|
||||
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i8_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_avx2_vperm2i128 : GCCBuiltin<"__builtin_ia32_permti256">,
|
||||
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
|
||||
llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
|
||||
|
@ -42,7 +42,7 @@ class LLVMContext {
|
||||
MD_dbg = 0, // "dbg"
|
||||
MD_tbaa = 1, // "tbaa"
|
||||
MD_prof = 2, // "prof"
|
||||
MD_fpaccuracy = 3, // "fpaccuracy"
|
||||
MD_fpmath = 3, // "fpmath"
|
||||
MD_range = 4 // "range"
|
||||
};
|
||||
|
||||
|
@ -16,14 +16,11 @@
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
class MemoryBuffer;
|
||||
class SMLoc;
|
||||
class MCAsmInfo;
|
||||
|
||||
/// AsmLexer - Lexer class for assembly files.
|
||||
|
@ -15,8 +15,6 @@
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmLexer;
|
||||
class MCInst;
|
||||
|
||||
/// AsmToken - Target independent representation for an assembler token.
|
||||
class AsmToken {
|
||||
@ -53,6 +51,7 @@ class AsmToken {
|
||||
Greater, GreaterEqual, GreaterGreater, At
|
||||
};
|
||||
|
||||
private:
|
||||
TokenKind Kind;
|
||||
|
||||
/// A reference to the entire token contents; this is always a pointer into
|
||||
|
@ -33,6 +33,15 @@
|
||||
namespace llvm {
|
||||
namespace object {
|
||||
|
||||
// Subclasses of ELFObjectFile may need this for template instantiation
|
||||
inline std::pair<unsigned char, unsigned char>
|
||||
getElfArchType(MemoryBuffer *Object) {
|
||||
if (Object->getBufferSize() < ELF::EI_NIDENT)
|
||||
return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE);
|
||||
return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS]
|
||||
, (uint8_t)Object->getBufferStart()[ELF::EI_DATA]);
|
||||
}
|
||||
|
||||
// Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
|
||||
template<support::endianness target_endianness>
|
||||
struct ELFDataTypeTypedefHelperCommon {
|
||||
|
@ -15,8 +15,9 @@
|
||||
#ifndef LLVM_OPERATOR_H
|
||||
#define LLVM_OPERATOR_H
|
||||
|
||||
#include "llvm/Instruction.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Instruction.h"
|
||||
#include "llvm/Type.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -129,14 +130,15 @@ class PossiblyExactOperator : public Operator {
|
||||
IsExact = (1 << 0)
|
||||
};
|
||||
|
||||
private:
|
||||
~PossiblyExactOperator(); // do not implement
|
||||
|
||||
friend class BinaryOperator;
|
||||
friend class ConstantExpr;
|
||||
void setIsExact(bool B) {
|
||||
SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact);
|
||||
}
|
||||
|
||||
private:
|
||||
~PossiblyExactOperator(); // do not implement
|
||||
public:
|
||||
/// isExact - Test whether this division is known to be exact, with
|
||||
/// zero remainder.
|
||||
@ -161,7 +163,28 @@ class PossiblyExactOperator : public Operator {
|
||||
(isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// FPMathOperator - Utility class for floating point operations which can have
|
||||
/// information about relaxed accuracy requirements attached to them.
|
||||
class FPMathOperator : public Operator {
|
||||
private:
|
||||
~FPMathOperator(); // do not implement
|
||||
|
||||
public:
|
||||
|
||||
/// \brief Get the maximum error permitted by this operation in ULPs. An
|
||||
/// accuracy of 0.0 means that the operation should be performed with the
|
||||
/// default precision.
|
||||
float getFPAccuracy() const;
|
||||
|
||||
static inline bool classof(const FPMathOperator *) { return true; }
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return I->getType()->isFPOrFPVectorTy();
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// ConcreteOperator - A helper template for defining operators for individual
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/BasicBlock.h"
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
@ -331,49 +332,63 @@ template<bool preserveNames = true, typename T = ConstantFolder,
|
||||
typename Inserter = IRBuilderDefaultInserter<preserveNames> >
|
||||
class IRBuilder : public IRBuilderBase, public Inserter {
|
||||
T Folder;
|
||||
MDNode *DefaultFPMathTag;
|
||||
public:
|
||||
IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter())
|
||||
: IRBuilderBase(C), Inserter(I), Folder(F) {
|
||||
IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(),
|
||||
MDNode *FPMathTag = 0)
|
||||
: IRBuilderBase(C), Inserter(I), Folder(F), DefaultFPMathTag(FPMathTag) {
|
||||
}
|
||||
|
||||
explicit IRBuilder(LLVMContext &C) : IRBuilderBase(C), Folder() {
|
||||
explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) : IRBuilderBase(C),
|
||||
Folder(), DefaultFPMathTag(FPMathTag) {
|
||||
}
|
||||
|
||||
explicit IRBuilder(BasicBlock *TheBB, const T &F)
|
||||
: IRBuilderBase(TheBB->getContext()), Folder(F) {
|
||||
explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0)
|
||||
: IRBuilderBase(TheBB->getContext()), Folder(F),
|
||||
DefaultFPMathTag(FPMathTag) {
|
||||
SetInsertPoint(TheBB);
|
||||
}
|
||||
|
||||
explicit IRBuilder(BasicBlock *TheBB)
|
||||
: IRBuilderBase(TheBB->getContext()), Folder() {
|
||||
explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0)
|
||||
: IRBuilderBase(TheBB->getContext()), Folder(),
|
||||
DefaultFPMathTag(FPMathTag) {
|
||||
SetInsertPoint(TheBB);
|
||||
}
|
||||
|
||||
explicit IRBuilder(Instruction *IP)
|
||||
: IRBuilderBase(IP->getContext()), Folder() {
|
||||
explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0)
|
||||
: IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag) {
|
||||
SetInsertPoint(IP);
|
||||
SetCurrentDebugLocation(IP->getDebugLoc());
|
||||
}
|
||||
|
||||
explicit IRBuilder(Use &U)
|
||||
: IRBuilderBase(U->getContext()), Folder() {
|
||||
explicit IRBuilder(Use &U, MDNode *FPMathTag = 0)
|
||||
: IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag) {
|
||||
SetInsertPoint(U);
|
||||
SetCurrentDebugLocation(cast<Instruction>(U.getUser())->getDebugLoc());
|
||||
}
|
||||
|
||||
IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F)
|
||||
: IRBuilderBase(TheBB->getContext()), Folder(F) {
|
||||
IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F,
|
||||
MDNode *FPMathTag = 0)
|
||||
: IRBuilderBase(TheBB->getContext()), Folder(F),
|
||||
DefaultFPMathTag(FPMathTag) {
|
||||
SetInsertPoint(TheBB, IP);
|
||||
}
|
||||
|
||||
IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP)
|
||||
: IRBuilderBase(TheBB->getContext()), Folder() {
|
||||
IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0)
|
||||
: IRBuilderBase(TheBB->getContext()), Folder(),
|
||||
DefaultFPMathTag(FPMathTag) {
|
||||
SetInsertPoint(TheBB, IP);
|
||||
}
|
||||
|
||||
/// getFolder - Get the constant folder being used.
|
||||
const T &getFolder() { return Folder; }
|
||||
|
||||
/// getDefaultFPMathTag - Get the floating point math metadata being used.
|
||||
MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; }
|
||||
|
||||
/// SetDefaultFPMathTag - Set the floating point math metadata to be used.
|
||||
void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; }
|
||||
|
||||
/// isNamePreserving - Return true if this builder is configured to actually
|
||||
/// add the requested names to IR created through it.
|
||||
bool isNamePreserving() const { return preserveNames; }
|
||||
@ -496,6 +511,14 @@ class IRBuilder : public IRBuilderBase, public Inserter {
|
||||
if (HasNSW) BO->setHasNoSignedWrap();
|
||||
return BO;
|
||||
}
|
||||
|
||||
Instruction *AddFPMathTag(Instruction *I, MDNode *FPMathTag) const {
|
||||
if (!FPMathTag)
|
||||
FPMathTag = DefaultFPMathTag;
|
||||
if (FPMathTag)
|
||||
I->setMetadata(LLVMContext::MD_fpmath, FPMathTag);
|
||||
return I;
|
||||
}
|
||||
public:
|
||||
Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||
bool HasNUW = false, bool HasNSW = false) {
|
||||
@ -511,11 +534,13 @@ class IRBuilder : public IRBuilderBase, public Inserter {
|
||||
Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
return CreateAdd(LHS, RHS, Name, true, false);
|
||||
}
|
||||
Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||
MDNode *FPMathTag = 0) {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Insert(Folder.CreateFAdd(LC, RC), Name);
|
||||
return Insert(BinaryOperator::CreateFAdd(LHS, RHS), Name);
|
||||
return Insert(AddFPMathTag(BinaryOperator::CreateFAdd(LHS, RHS),
|
||||
FPMathTag), Name);
|
||||
}
|
||||
Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||
bool HasNUW = false, bool HasNSW = false) {
|
||||
@ -531,11 +556,13 @@ class IRBuilder : public IRBuilderBase, public Inserter {
|
||||
Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
return CreateSub(LHS, RHS, Name, true, false);
|
||||
}
|
||||
Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||
MDNode *FPMathTag = 0) {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Insert(Folder.CreateFSub(LC, RC), Name);
|
||||
return Insert(BinaryOperator::CreateFSub(LHS, RHS), Name);
|
||||
return Insert(AddFPMathTag(BinaryOperator::CreateFSub(LHS, RHS),
|
||||
FPMathTag), Name);
|
||||
}
|
||||
Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||
bool HasNUW = false, bool HasNSW = false) {
|
||||
@ -551,11 +578,13 @@ class IRBuilder : public IRBuilderBase, public Inserter {
|
||||
Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
return CreateMul(LHS, RHS, Name, true, false);
|
||||
}
|
||||
Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||
MDNode *FPMathTag = 0) {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Insert(Folder.CreateFMul(LC, RC), Name);
|
||||
return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name);
|
||||
return Insert(AddFPMathTag(BinaryOperator::CreateFMul(LHS, RHS),
|
||||
FPMathTag), Name);
|
||||
}
|
||||
Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||
bool isExact = false) {
|
||||
@ -581,11 +610,13 @@ class IRBuilder : public IRBuilderBase, public Inserter {
|
||||
Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
return CreateSDiv(LHS, RHS, Name, true);
|
||||
}
|
||||
Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||
MDNode *FPMathTag = 0) {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Insert(Folder.CreateFDiv(LC, RC), Name);
|
||||
return Insert(BinaryOperator::CreateFDiv(LHS, RHS), Name);
|
||||
return Insert(AddFPMathTag(BinaryOperator::CreateFDiv(LHS, RHS),
|
||||
FPMathTag), Name);
|
||||
}
|
||||
Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
@ -599,11 +630,13 @@ class IRBuilder : public IRBuilderBase, public Inserter {
|
||||
return Insert(Folder.CreateSRem(LC, RC), Name);
|
||||
return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name);
|
||||
}
|
||||
Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||
MDNode *FPMathTag = 0) {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Insert(Folder.CreateFRem(LC, RC), Name);
|
||||
return Insert(BinaryOperator::CreateFRem(LHS, RHS), Name);
|
||||
return Insert(AddFPMathTag(BinaryOperator::CreateFRem(LHS, RHS),
|
||||
FPMathTag), Name);
|
||||
}
|
||||
|
||||
Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||
@ -729,10 +762,10 @@ class IRBuilder : public IRBuilderBase, public Inserter {
|
||||
Value *CreateNUWNeg(Value *V, const Twine &Name = "") {
|
||||
return CreateNeg(V, Name, true, false);
|
||||
}
|
||||
Value *CreateFNeg(Value *V, const Twine &Name = "") {
|
||||
Value *CreateFNeg(Value *V, const Twine &Name = "", MDNode *FPMathTag = 0) {
|
||||
if (Constant *VC = dyn_cast<Constant>(V))
|
||||
return Insert(Folder.CreateFNeg(VC), Name);
|
||||
return Insert(BinaryOperator::CreateFNeg(V), Name);
|
||||
return Insert(AddFPMathTag(BinaryOperator::CreateFNeg(V), FPMathTag), Name);
|
||||
}
|
||||
Value *CreateNot(Value *V, const Twine &Name = "") {
|
||||
if (Constant *VC = dyn_cast<Constant>(V))
|
||||
|
@ -1,448 +0,0 @@
|
||||
//===--- JSONParser.h - Simple JSON parser ----------------------*- 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 a JSON parser.
|
||||
//
|
||||
// See http://www.json.org/ for an overview.
|
||||
// See http://www.ietf.org/rfc/rfc4627.txt for the full standard.
|
||||
//
|
||||
// FIXME: Currently this supports a subset of JSON. Specifically, support
|
||||
// for numbers, booleans and null for values is missing.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_JSON_PARSER_H
|
||||
#define LLVM_SUPPORT_JSON_PARSER_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class JSONContainer;
|
||||
class JSONString;
|
||||
class JSONValue;
|
||||
class JSONKeyValuePair;
|
||||
|
||||
/// \brief Base class for a parsable JSON atom.
|
||||
///
|
||||
/// This class has no semantics other than being a unit of JSON data which can
|
||||
/// be parsed out of a JSON document.
|
||||
class JSONAtom {
|
||||
public:
|
||||
/// \brief Possible types of JSON objects.
|
||||
enum Kind { JK_KeyValuePair, JK_Array, JK_Object, JK_String };
|
||||
|
||||
/// \brief Returns the type of this value.
|
||||
Kind getKind() const { return MyKind; }
|
||||
|
||||
static bool classof(const JSONAtom *Atom) { return true; }
|
||||
|
||||
protected:
|
||||
JSONAtom(Kind MyKind) : MyKind(MyKind) {}
|
||||
|
||||
private:
|
||||
Kind MyKind;
|
||||
};
|
||||
|
||||
/// \brief A parser for JSON text.
|
||||
///
|
||||
/// Use an object of JSONParser to iterate over the values of a JSON text.
|
||||
/// All objects are parsed during the iteration, so you can only iterate once
|
||||
/// over the JSON text, but the cost of partial iteration is minimized.
|
||||
/// Create a new JSONParser if you want to iterate multiple times.
|
||||
class JSONParser {
|
||||
public:
|
||||
/// \brief Create a JSONParser for the given input.
|
||||
///
|
||||
/// Parsing is started via parseRoot(). Access to the object returned from
|
||||
/// parseRoot() will parse the input lazily.
|
||||
JSONParser(StringRef Input, SourceMgr *SM);
|
||||
|
||||
/// \brief Returns the outermost JSON value (either an array or an object).
|
||||
///
|
||||
/// Can return NULL if the input does not start with an array or an object.
|
||||
/// The object is not parsed yet - the caller must iterate over the
|
||||
/// returned object to trigger parsing.
|
||||
///
|
||||
/// A JSONValue can be either a JSONString, JSONObject or JSONArray.
|
||||
JSONValue *parseRoot();
|
||||
|
||||
/// \brief Parses the JSON text and returns whether it is valid JSON.
|
||||
///
|
||||
/// In case validate() return false, failed() will return true and
|
||||
/// getErrorMessage() will return the parsing error.
|
||||
bool validate();
|
||||
|
||||
/// \brief Returns true if an error occurs during parsing.
|
||||
///
|
||||
/// If there was an error while parsing an object that was created by
|
||||
/// iterating over the result of 'parseRoot', 'failed' will return true.
|
||||
bool failed() const;
|
||||
|
||||
private:
|
||||
/// \brief These methods manage the implementation details of parsing new JSON
|
||||
/// atoms.
|
||||
/// @{
|
||||
JSONString *parseString();
|
||||
JSONValue *parseValue();
|
||||
JSONKeyValuePair *parseKeyValuePair();
|
||||
/// @}
|
||||
|
||||
/// \brief Helpers to parse the elements out of both forms of containers.
|
||||
/// @{
|
||||
const JSONAtom *parseElement(JSONAtom::Kind ContainerKind);
|
||||
StringRef::iterator parseFirstElement(JSONAtom::Kind ContainerKind,
|
||||
char StartChar, char EndChar,
|
||||
const JSONAtom *&Element);
|
||||
StringRef::iterator parseNextElement(JSONAtom::Kind ContainerKind,
|
||||
char EndChar,
|
||||
const JSONAtom *&Element);
|
||||
/// @}
|
||||
|
||||
/// \brief Whitespace parsing.
|
||||
/// @{
|
||||
void nextNonWhitespace();
|
||||
bool isWhitespace();
|
||||
/// @}
|
||||
|
||||
/// \brief These methods are used for error handling.
|
||||
/// {
|
||||
void setExpectedError(StringRef Expected, StringRef Found);
|
||||
void setExpectedError(StringRef Expected, char Found);
|
||||
bool errorIfAtEndOfFile(StringRef Message);
|
||||
bool errorIfNotAt(char C, StringRef Message);
|
||||
/// }
|
||||
|
||||
/// \brief Skips all elements in the given container.
|
||||
bool skipContainer(const JSONContainer &Container);
|
||||
|
||||
/// \brief Skips to the next position behind the given JSON atom.
|
||||
bool skip(const JSONAtom &Atom);
|
||||
|
||||
/// All nodes are allocated by the parser and will be deallocated when the
|
||||
/// parser is destroyed.
|
||||
BumpPtrAllocator ValueAllocator;
|
||||
|
||||
/// \brief The original input to the parser.
|
||||
MemoryBuffer *InputBuffer;
|
||||
|
||||
/// \brief The source manager used for diagnostics and buffer management.
|
||||
SourceMgr *SM;
|
||||
|
||||
/// \brief The current position in the parse stream.
|
||||
StringRef::iterator Position;
|
||||
|
||||
/// \brief The end position for fast EOF checks without introducing
|
||||
/// unnecessary dereferences.
|
||||
StringRef::iterator End;
|
||||
|
||||
/// \brief If true, an error has occurred.
|
||||
bool Failed;
|
||||
|
||||
friend class JSONContainer;
|
||||
};
|
||||
|
||||
|
||||
/// \brief Base class for JSON value objects.
|
||||
///
|
||||
/// This object represents an abstract JSON value. It is the root node behind
|
||||
/// the group of JSON entities that can represent top-level values in a JSON
|
||||
/// document. It has no API, and is just a placeholder in the type hierarchy of
|
||||
/// nodes.
|
||||
class JSONValue : public JSONAtom {
|
||||
protected:
|
||||
JSONValue(Kind MyKind) : JSONAtom(MyKind) {}
|
||||
|
||||
public:
|
||||
/// \brief dyn_cast helpers
|
||||
///@{
|
||||
static bool classof(const JSONAtom *Atom) {
|
||||
switch (Atom->getKind()) {
|
||||
case JK_Array:
|
||||
case JK_Object:
|
||||
case JK_String:
|
||||
return true;
|
||||
case JK_KeyValuePair:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("Invalid JSONAtom kind");
|
||||
}
|
||||
static bool classof(const JSONValue *Value) { return true; }
|
||||
///@}
|
||||
};
|
||||
|
||||
/// \brief Gives access to the text of a JSON string.
|
||||
///
|
||||
/// FIXME: Implement a method to return the unescaped text.
|
||||
class JSONString : public JSONValue {
|
||||
public:
|
||||
/// \brief Returns the underlying parsed text of the string.
|
||||
///
|
||||
/// This is the unescaped content of the JSON text.
|
||||
/// See http://www.ietf.org/rfc/rfc4627.txt for details.
|
||||
StringRef getRawText() const { return RawText; }
|
||||
|
||||
private:
|
||||
JSONString(StringRef RawText) : JSONValue(JK_String), RawText(RawText) {}
|
||||
|
||||
StringRef RawText;
|
||||
|
||||
friend class JSONParser;
|
||||
|
||||
public:
|
||||
/// \brief dyn_cast helpers
|
||||
///@{
|
||||
static bool classof(const JSONAtom *Atom) {
|
||||
return Atom->getKind() == JK_String;
|
||||
}
|
||||
static bool classof(const JSONString *String) { return true; }
|
||||
///@}
|
||||
};
|
||||
|
||||
/// \brief A (key, value) tuple of type (JSONString *, JSONValue *).
|
||||
///
|
||||
/// Note that JSONKeyValuePair is not a JSONValue, it is a bare JSONAtom.
|
||||
/// JSONKeyValuePairs can be elements of a JSONObject, but not of a JSONArray.
|
||||
/// They are not viable as top-level values either.
|
||||
class JSONKeyValuePair : public JSONAtom {
|
||||
public:
|
||||
const JSONString * const Key;
|
||||
const JSONValue * const Value;
|
||||
|
||||
private:
|
||||
JSONKeyValuePair(const JSONString *Key, const JSONValue *Value)
|
||||
: JSONAtom(JK_KeyValuePair), Key(Key), Value(Value) {}
|
||||
|
||||
friend class JSONParser;
|
||||
|
||||
public:
|
||||
/// \brief dyn_cast helpers
|
||||
///@{
|
||||
static bool classof(const JSONAtom *Atom) {
|
||||
return Atom->getKind() == JK_KeyValuePair;
|
||||
}
|
||||
static bool classof(const JSONKeyValuePair *KeyValuePair) { return true; }
|
||||
///@}
|
||||
};
|
||||
|
||||
/// \brief Implementation of JSON containers (arrays and objects).
|
||||
///
|
||||
/// JSONContainers drive the lazy parsing of JSON arrays and objects via
|
||||
/// forward iterators.
|
||||
class JSONContainer : public JSONValue {
|
||||
private:
|
||||
/// \brief An iterator that parses the underlying container during iteration.
|
||||
///
|
||||
/// Iterators on the same collection use shared state, so when multiple copies
|
||||
/// of an iterator exist, only one is allowed to be used for iteration;
|
||||
/// iterating multiple copies of an iterator of the same collection will lead
|
||||
/// to undefined behavior.
|
||||
class AtomIterator {
|
||||
public:
|
||||
AtomIterator(const AtomIterator &I) : Container(I.Container) {}
|
||||
|
||||
/// \brief Iterator interface.
|
||||
///@{
|
||||
bool operator==(const AtomIterator &I) const {
|
||||
if (isEnd() || I.isEnd())
|
||||
return isEnd() == I.isEnd();
|
||||
return Container->Position == I.Container->Position;
|
||||
}
|
||||
bool operator!=(const AtomIterator &I) const {
|
||||
return !(*this == I);
|
||||
}
|
||||
AtomIterator &operator++() {
|
||||
Container->parseNextElement();
|
||||
return *this;
|
||||
}
|
||||
const JSONAtom *operator*() {
|
||||
return Container->Current;
|
||||
}
|
||||
///@}
|
||||
|
||||
private:
|
||||
/// \brief Create an iterator for which 'isEnd' returns true.
|
||||
AtomIterator() : Container(0) {}
|
||||
|
||||
/// \brief Create an iterator for the given container.
|
||||
AtomIterator(const JSONContainer *Container) : Container(Container) {}
|
||||
|
||||
bool isEnd() const {
|
||||
return Container == 0 || Container->Position == StringRef::iterator();
|
||||
}
|
||||
|
||||
const JSONContainer * const Container;
|
||||
|
||||
friend class JSONContainer;
|
||||
};
|
||||
|
||||
protected:
|
||||
/// \brief An iterator for the specified AtomT.
|
||||
///
|
||||
/// Used for the implementation of iterators for JSONArray and JSONObject.
|
||||
template <typename AtomT>
|
||||
class IteratorTemplate : public std::iterator<std::forward_iterator_tag,
|
||||
const AtomT*> {
|
||||
public:
|
||||
explicit IteratorTemplate(const AtomIterator& AtomI)
|
||||
: AtomI(AtomI) {}
|
||||
|
||||
bool operator==(const IteratorTemplate &I) const {
|
||||
return AtomI == I.AtomI;
|
||||
}
|
||||
bool operator!=(const IteratorTemplate &I) const { return !(*this == I); }
|
||||
|
||||
IteratorTemplate &operator++() {
|
||||
++AtomI;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const AtomT *operator*() { return dyn_cast<AtomT>(*AtomI); }
|
||||
|
||||
private:
|
||||
AtomIterator AtomI;
|
||||
};
|
||||
|
||||
JSONContainer(JSONParser *Parser, char StartChar, char EndChar,
|
||||
JSONAtom::Kind ContainerKind)
|
||||
: JSONValue(ContainerKind), Parser(Parser),
|
||||
Position(), Current(0), Started(false),
|
||||
StartChar(StartChar), EndChar(EndChar) {}
|
||||
|
||||
/// \brief Returns a lazy parsing iterator over the container.
|
||||
///
|
||||
/// As the iterator drives the parse stream, begin() must only be called
|
||||
/// once per container.
|
||||
AtomIterator atom_begin() const {
|
||||
if (Started)
|
||||
report_fatal_error("Cannot parse container twice.");
|
||||
Started = true;
|
||||
// Set up the position and current element when we begin iterating over the
|
||||
// container.
|
||||
Position = Parser->parseFirstElement(getKind(), StartChar, EndChar, Current);
|
||||
return AtomIterator(this);
|
||||
}
|
||||
AtomIterator atom_end() const {
|
||||
return AtomIterator();
|
||||
}
|
||||
|
||||
private:
|
||||
AtomIterator atom_current() const {
|
||||
if (!Started)
|
||||
return atom_begin();
|
||||
|
||||
return AtomIterator(this);
|
||||
}
|
||||
|
||||
/// \brief Parse the next element in the container into the Current element.
|
||||
///
|
||||
/// This routine is called as an iterator into this container walks through
|
||||
/// its elements. It mutates the container's internal current node to point to
|
||||
/// the next atom of the container.
|
||||
void parseNextElement() const {
|
||||
Parser->skip(*Current);
|
||||
Position = Parser->parseNextElement(getKind(), EndChar, Current);
|
||||
}
|
||||
|
||||
// For parsing, JSONContainers call back into the JSONParser.
|
||||
JSONParser * const Parser;
|
||||
|
||||
// 'Position', 'Current' and 'Started' store the state of the parse stream
|
||||
// for iterators on the container, they don't change the container's elements
|
||||
// and are thus marked as mutable.
|
||||
mutable StringRef::iterator Position;
|
||||
mutable const JSONAtom *Current;
|
||||
mutable bool Started;
|
||||
|
||||
const char StartChar;
|
||||
const char EndChar;
|
||||
|
||||
friend class JSONParser;
|
||||
|
||||
public:
|
||||
/// \brief dyn_cast helpers
|
||||
///@{
|
||||
static bool classof(const JSONAtom *Atom) {
|
||||
switch (Atom->getKind()) {
|
||||
case JK_Array:
|
||||
case JK_Object:
|
||||
return true;
|
||||
case JK_KeyValuePair:
|
||||
case JK_String:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("Invalid JSONAtom kind");
|
||||
}
|
||||
static bool classof(const JSONContainer *Container) { return true; }
|
||||
///@}
|
||||
};
|
||||
|
||||
/// \brief A simple JSON array.
|
||||
class JSONArray : public JSONContainer {
|
||||
public:
|
||||
typedef IteratorTemplate<JSONValue> const_iterator;
|
||||
|
||||
/// \brief Returns a lazy parsing iterator over the container.
|
||||
///
|
||||
/// As the iterator drives the parse stream, begin() must only be called
|
||||
/// once per container.
|
||||
const_iterator begin() const { return const_iterator(atom_begin()); }
|
||||
const_iterator end() const { return const_iterator(atom_end()); }
|
||||
|
||||
private:
|
||||
JSONArray(JSONParser *Parser)
|
||||
: JSONContainer(Parser, '[', ']', JSONAtom::JK_Array) {}
|
||||
|
||||
public:
|
||||
/// \brief dyn_cast helpers
|
||||
///@{
|
||||
static bool classof(const JSONAtom *Atom) {
|
||||
return Atom->getKind() == JSONAtom::JK_Array;
|
||||
}
|
||||
static bool classof(const JSONArray *Array) { return true; }
|
||||
///@}
|
||||
|
||||
friend class JSONParser;
|
||||
};
|
||||
|
||||
/// \brief A JSON object: an iterable list of JSON key-value pairs.
|
||||
class JSONObject : public JSONContainer {
|
||||
public:
|
||||
typedef IteratorTemplate<JSONKeyValuePair> const_iterator;
|
||||
|
||||
/// \brief Returns a lazy parsing iterator over the container.
|
||||
///
|
||||
/// As the iterator drives the parse stream, begin() must only be called
|
||||
/// once per container.
|
||||
const_iterator begin() const { return const_iterator(atom_begin()); }
|
||||
const_iterator end() const { return const_iterator(atom_end()); }
|
||||
|
||||
private:
|
||||
JSONObject(JSONParser *Parser)
|
||||
: JSONContainer(Parser, '{', '}', JSONAtom::JK_Object) {}
|
||||
|
||||
public:
|
||||
/// \brief dyn_cast helpers
|
||||
///@{
|
||||
static bool classof(const JSONAtom *Atom) {
|
||||
return Atom->getKind() == JSONAtom::JK_Object;
|
||||
}
|
||||
static bool classof(const JSONObject *Object) { return true; }
|
||||
///@}
|
||||
|
||||
friend class JSONParser;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_SUPPORT_JSON_PARSER_H
|
17
include/llvm/Support/Locale.h
Normal file
17
include/llvm/Support/Locale.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef LLVM_SUPPORT_LOCALE
|
||||
#define LLVM_SUPPORT_LOCALE
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace sys {
|
||||
namespace locale {
|
||||
|
||||
int columnWidth(StringRef s);
|
||||
bool isPrint(int c);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LLVM_SUPPORT_LOCALE
|
118
include/llvm/Support/MDBuilder.h
Normal file
118
include/llvm/Support/MDBuilder.h
Normal file
@ -0,0 +1,118 @@
|
||||
//===---- llvm/Support/MDBuilder.h - Builder for LLVM metadata --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the MDBuilder class, which is used as a convenient way to
|
||||
// create LLVM metadata with a consistent and simplified interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_MDBUILDER_H
|
||||
#define LLVM_SUPPORT_MDBUILDER_H
|
||||
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/Metadata.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MDBuilder {
|
||||
LLVMContext &Context;
|
||||
|
||||
public:
|
||||
MDBuilder(LLVMContext &context) : Context(context) {}
|
||||
|
||||
/// \brief Return the given string as metadata.
|
||||
MDString *createString(StringRef Str) {
|
||||
return MDString::get(Context, Str);
|
||||
}
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// FPMath metadata.
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Return metadata with the given settings. The special value 0.0
|
||||
/// for the Accuracy parameter indicates the default (maximal precision)
|
||||
/// setting.
|
||||
MDNode *createFPMath(float Accuracy) {
|
||||
if (Accuracy == 0.0)
|
||||
return 0;
|
||||
assert(Accuracy > 0.0 && "Invalid fpmath accuracy!");
|
||||
Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy);
|
||||
return MDNode::get(Context, Op);
|
||||
}
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Range metadata.
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Return metadata describing the range [Lo, Hi).
|
||||
MDNode *createRange(const APInt &Lo, const APInt &Hi) {
|
||||
assert(Lo.getBitWidth() == Hi.getBitWidth() && "Mismatched bitwidths!");
|
||||
// If the range is everything then it is useless.
|
||||
if (Hi == Lo)
|
||||
return 0;
|
||||
|
||||
// Return the range [Lo, Hi).
|
||||
Type *Ty = IntegerType::get(Context, Lo.getBitWidth());
|
||||
Value *Range[2] = { ConstantInt::get(Ty, Lo), ConstantInt::get(Ty, Hi) };
|
||||
return MDNode::get(Context, Range);
|
||||
}
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// TBAA metadata.
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Return metadata appropriate for a TBAA root node. Each returned
|
||||
/// node is distinct from all other metadata and will never be identified
|
||||
/// (uniqued) with anything else.
|
||||
MDNode *createAnonymousTBAARoot() {
|
||||
// To ensure uniqueness the root node is self-referential.
|
||||
MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value*>());
|
||||
MDNode *Root = MDNode::get(Context, Dummy);
|
||||
// At this point we have
|
||||
// !0 = metadata !{} <- dummy
|
||||
// !1 = metadata !{metadata !0} <- root
|
||||
// Replace the dummy operand with the root node itself and delete the dummy.
|
||||
Root->replaceOperandWith(0, Root);
|
||||
MDNode::deleteTemporary(Dummy);
|
||||
// We now have
|
||||
// !1 = metadata !{metadata !1} <- self-referential root
|
||||
return Root;
|
||||
}
|
||||
|
||||
/// \brief Return metadata appropriate for a TBAA root node with the given
|
||||
/// name. This may be identified (uniqued) with other roots with the same
|
||||
/// name.
|
||||
MDNode *createTBAARoot(StringRef Name) {
|
||||
return MDNode::get(Context, createString(Name));
|
||||
}
|
||||
|
||||
/// \brief Return metadata for a non-root TBAA node with the given name,
|
||||
/// parent in the TBAA tree, and value for 'pointsToConstantMemory'.
|
||||
MDNode *createTBAANode(StringRef Name, MDNode *Parent,
|
||||
bool isConstant = false) {
|
||||
if (isConstant) {
|
||||
Constant *Flags = ConstantInt::get(Type::getInt64Ty(Context), 1);
|
||||
Value *Ops[3] = { createString(Name), Parent, Flags };
|
||||
return MDNode::get(Context, Ops);
|
||||
} else {
|
||||
Value *Ops[2] = { createString(Name), Parent };
|
||||
return MDNode::get(Context, Ops);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -136,6 +136,10 @@ namespace sys {
|
||||
/// Same as OutputColor, but only enables the bold attribute.
|
||||
static const char *OutputBold(bool bg);
|
||||
|
||||
/// This function returns the escape sequence to reverse forground and
|
||||
/// background colors.
|
||||
static const char *OutputReverse();
|
||||
|
||||
/// Resets the terminals colors, or returns an escape sequence to do so.
|
||||
static const char *ResetColor();
|
||||
/// @}
|
||||
|
@ -128,8 +128,11 @@ class SourceMgr {
|
||||
/// PrintMessage - Emit a message about the specified location with the
|
||||
/// specified string.
|
||||
///
|
||||
/// @param ShowColors - Display colored messages if output is a terminal and
|
||||
/// the default error handler is used.
|
||||
void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
|
||||
ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) const;
|
||||
ArrayRef<SMRange> Ranges = ArrayRef<SMRange>(),
|
||||
bool ShowColors = true) const;
|
||||
|
||||
|
||||
/// GetMessage - Return an SMDiagnostic at the specified location with the
|
||||
@ -188,7 +191,7 @@ class SMDiagnostic {
|
||||
const std::vector<std::pair<unsigned, unsigned> > &getRanges() const {
|
||||
return Ranges;
|
||||
}
|
||||
void print(const char *ProgName, raw_ostream &S) const;
|
||||
void print(const char *ProgName, raw_ostream &S, bool ShowColors = true) const;
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
@ -516,8 +516,11 @@ class document_iterator {
|
||||
document_iterator() : Doc(NullDoc) {}
|
||||
document_iterator(OwningPtr<Document> &D) : Doc(D) {}
|
||||
|
||||
bool operator ==(const document_iterator &Other) {
|
||||
return Doc == Other.Doc;
|
||||
}
|
||||
bool operator !=(const document_iterator &Other) {
|
||||
return Doc != Other.Doc;
|
||||
return !(*this == Other);
|
||||
}
|
||||
|
||||
document_iterator operator ++() {
|
||||
|
@ -222,6 +222,9 @@ class raw_ostream {
|
||||
/// outputting colored text, or before program exit.
|
||||
virtual raw_ostream &resetColor() { return *this; }
|
||||
|
||||
/// Reverses the forground and background colors.
|
||||
virtual raw_ostream &reverseColor() { return *this; }
|
||||
|
||||
/// This function determines if this stream is connected to a "tty" or
|
||||
/// "console" window. That is, the output would be displayed to the user
|
||||
/// rather than being put on a pipe or stored in a file.
|
||||
@ -379,6 +382,8 @@ class raw_fd_ostream : public raw_ostream {
|
||||
bool bg=false);
|
||||
virtual raw_ostream &resetColor();
|
||||
|
||||
virtual raw_ostream &reverseColor();
|
||||
|
||||
virtual bool is_displayed() const;
|
||||
|
||||
/// has_error - Return the value of the flag in this raw_fd_ostream indicating
|
||||
|
@ -29,6 +29,11 @@ class TGError {
|
||||
const std::string &getMessage() const { return Message; }
|
||||
};
|
||||
|
||||
void PrintWarning(SMLoc WarningLoc, const Twine &Msg);
|
||||
void PrintWarning(const char *Loc, const Twine &Msg);
|
||||
void PrintWarning(const Twine &Msg);
|
||||
void PrintWarning(const TGError &Warning);
|
||||
|
||||
void PrintError(SMLoc ErrorLoc, const Twine &Msg);
|
||||
void PrintError(const char *Loc, const Twine &Msg);
|
||||
void PrintError(const Twine &Msg);
|
||||
|
@ -454,7 +454,7 @@ class Init {
|
||||
/// without adding quote markers. This primaruly affects
|
||||
/// StringInits where we will not surround the string value with
|
||||
/// quotes.
|
||||
virtual std::string getAsUnquotedString() const { return getAsString(); }
|
||||
virtual std::string getAsUnquotedString() const { return getAsString(); }
|
||||
|
||||
/// dump - Debugging method that may be called through a debugger, just
|
||||
/// invokes print on stderr.
|
||||
@ -1529,7 +1529,7 @@ struct MultiClass {
|
||||
|
||||
void dump() const;
|
||||
|
||||
MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) :
|
||||
MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) :
|
||||
Rec(Name, Loc, Records) {}
|
||||
};
|
||||
|
||||
|
@ -83,7 +83,7 @@ namespace llvm {
|
||||
/// long double expm1l(long double x);
|
||||
expm1l,
|
||||
/// float expm1f(float x);
|
||||
expl1f,
|
||||
expm1f,
|
||||
/// double fabs(double x);
|
||||
fabs,
|
||||
/// long double fabsl(long double x);
|
||||
@ -159,8 +159,14 @@ namespace llvm {
|
||||
rint,
|
||||
/// float rintf(float x);
|
||||
rintf,
|
||||
/// long dobule rintl(long double x);
|
||||
/// long double rintl(long double x);
|
||||
rintl,
|
||||
/// double round(double x);
|
||||
round,
|
||||
/// float roundf(float x);
|
||||
roundf,
|
||||
/// long double roundl(long double x);
|
||||
roundl,
|
||||
/// double sin(double x);
|
||||
sin,
|
||||
/// long double sinl(long double x);
|
||||
|
@ -205,7 +205,7 @@ struct TargetRegisterInfoDesc {
|
||||
/// Each TargetRegisterClass has a per register weight, and weight
|
||||
/// limit which must be less than the limits of its pressure sets.
|
||||
struct RegClassWeight {
|
||||
unsigned RegWeigt;
|
||||
unsigned RegWeight;
|
||||
unsigned WeightLimit;
|
||||
};
|
||||
|
||||
|
@ -110,7 +110,8 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
|
||||
///
|
||||
BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
|
||||
Pass *P = 0, bool MergeIdenticalEdges = false,
|
||||
bool DontDeleteUselessPHIs = false);
|
||||
bool DontDeleteUselessPHIs = false,
|
||||
bool SplitLandingPads = false);
|
||||
|
||||
inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
|
||||
Pass *P = 0) {
|
||||
|
@ -34,6 +34,9 @@ struct VectorizeConfig {
|
||||
/// @brief Vectorize floating-point values.
|
||||
bool VectorizeFloats;
|
||||
|
||||
/// @brief Vectorize pointer values.
|
||||
bool VectorizePointers;
|
||||
|
||||
/// @brief Vectorize casting (conversion) operations.
|
||||
bool VectorizeCasts;
|
||||
|
||||
@ -43,6 +46,12 @@ struct VectorizeConfig {
|
||||
/// @brief Vectorize the fused-multiply-add intrinsic.
|
||||
bool VectorizeFMA;
|
||||
|
||||
/// @brief Vectorize select instructions.
|
||||
bool VectorizeSelect;
|
||||
|
||||
/// @brief Vectorize getelementptr instructions.
|
||||
bool VectorizeGEP;
|
||||
|
||||
/// @brief Vectorize loads and stores.
|
||||
bool VectorizeMemOps;
|
||||
|
||||
|
@ -681,6 +681,7 @@ static Constant *SymbolicallyEvaluateGEP(ArrayRef<Constant *> Ops,
|
||||
// This makes it easy to determine if the getelementptr is "inbounds".
|
||||
// Also, this helps GlobalOpt do SROA on GlobalVariables.
|
||||
Type *Ty = Ptr->getType();
|
||||
assert(Ty->isPointerTy() && "Forming regular GEP of non-pointer type");
|
||||
SmallVector<Constant*, 32> NewIdxs;
|
||||
do {
|
||||
if (SequentialType *ATy = dyn_cast<SequentialType>(Ty)) {
|
||||
@ -711,10 +712,17 @@ static Constant *SymbolicallyEvaluateGEP(ArrayRef<Constant *> Ops,
|
||||
}
|
||||
Ty = ATy->getElementType();
|
||||
} else if (StructType *STy = dyn_cast<StructType>(Ty)) {
|
||||
// Determine which field of the struct the offset points into. The
|
||||
// getZExtValue is at least as safe as the StructLayout API because we
|
||||
// know the offset is within the struct at this point.
|
||||
// If we end up with an offset that isn't valid for this struct type, we
|
||||
// can't re-form this GEP in a regular form, so bail out. The pointer
|
||||
// operand likely went through casts that are necessary to make the GEP
|
||||
// sensible.
|
||||
const StructLayout &SL = *TD->getStructLayout(STy);
|
||||
if (Offset.uge(SL.getSizeInBytes()))
|
||||
break;
|
||||
|
||||
// Determine which field of the struct the offset points into. The
|
||||
// getZExtValue is fine as we've already ensured that the offset is
|
||||
// within the range representable by the StructLayout API.
|
||||
unsigned ElIdx = SL.getElementContainingOffset(Offset.getZExtValue());
|
||||
NewIdxs.push_back(ConstantInt::get(Type::getInt32Ty(Ty->getContext()),
|
||||
ElIdx));
|
||||
|
@ -3187,7 +3187,7 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
|
||||
|
||||
// Add the total offset from all the GEP indices to the base.
|
||||
return getAddExpr(BaseS, TotalOffset,
|
||||
isInBounds ? SCEV::FlagNUW : SCEV::FlagAnyWrap);
|
||||
isInBounds ? SCEV::FlagNSW : SCEV::FlagAnyWrap);
|
||||
}
|
||||
|
||||
/// GetMinTrailingZeros - Determine the minimum number of zero bits that S is
|
||||
|
@ -564,7 +564,7 @@ void llvm::ComputeMaskedBits(Value *V, APInt &KnownZero, APInt &KnownOne,
|
||||
Depth+1);
|
||||
// If it's known zero, our sign bit is also zero.
|
||||
if (LHSKnownZero.isNegative())
|
||||
KnownZero |= LHSKnownZero;
|
||||
KnownZero.setBit(BitWidth - 1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -36,35 +36,20 @@ const char *DwarfAccelTable::Atom::AtomTypeString(enum AtomType AT) {
|
||||
llvm_unreachable("invalid AtomType!");
|
||||
}
|
||||
|
||||
// The general case would need to have a less hard coded size for the
|
||||
// length of the HeaderData, however, if we're constructing based on a
|
||||
// single Atom then we know it will always be: 4 + 4 + 2 + 2.
|
||||
DwarfAccelTable::DwarfAccelTable(DwarfAccelTable::Atom atom) :
|
||||
Header(12),
|
||||
HeaderData(atom) {
|
||||
}
|
||||
|
||||
// The length of the header data is always going to be 4 + 4 + 4*NumAtoms.
|
||||
DwarfAccelTable::DwarfAccelTable(std::vector<DwarfAccelTable::Atom> &atomList) :
|
||||
DwarfAccelTable::DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom> atomList) :
|
||||
Header(8 + (atomList.size() * 4)),
|
||||
HeaderData(atomList) {
|
||||
}
|
||||
HeaderData(atomList),
|
||||
Entries(Allocator) { }
|
||||
|
||||
DwarfAccelTable::~DwarfAccelTable() {
|
||||
for (size_t i = 0, e = Data.size(); i < e; ++i)
|
||||
delete Data[i];
|
||||
for (StringMap<DataArray>::iterator
|
||||
EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI)
|
||||
for (DataArray::iterator DI = EI->second.begin(),
|
||||
DE = EI->second.end(); DI != DE; ++DI)
|
||||
delete (*DI);
|
||||
}
|
||||
DwarfAccelTable::~DwarfAccelTable() { }
|
||||
|
||||
void DwarfAccelTable::AddName(StringRef Name, DIE* die, char Flags) {
|
||||
assert(Data.empty() && "Already finalized!");
|
||||
// If the string is in the list already then add this die to the list
|
||||
// otherwise add a new one.
|
||||
DataArray &DIEs = Entries[Name];
|
||||
DIEs.push_back(new HashDataContents(die, Flags));
|
||||
DIEs.push_back(new (Allocator) HashDataContents(die, Flags));
|
||||
}
|
||||
|
||||
void DwarfAccelTable::ComputeBucketCount(void) {
|
||||
@ -85,31 +70,23 @@ void DwarfAccelTable::ComputeBucketCount(void) {
|
||||
Header.hashes_count = num;
|
||||
}
|
||||
|
||||
namespace {
|
||||
// DIESorter - comparison predicate that sorts DIEs by their offset.
|
||||
struct DIESorter {
|
||||
bool operator()(const struct DwarfAccelTable::HashDataContents *A,
|
||||
const struct DwarfAccelTable::HashDataContents *B) const {
|
||||
return A->Die->getOffset() < B->Die->getOffset();
|
||||
}
|
||||
};
|
||||
// compareDIEs - comparison predicate that sorts DIEs by their offset.
|
||||
static bool compareDIEs(const DwarfAccelTable::HashDataContents *A,
|
||||
const DwarfAccelTable::HashDataContents *B) {
|
||||
return A->Die->getOffset() < B->Die->getOffset();
|
||||
}
|
||||
|
||||
void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, const char *Prefix) {
|
||||
// Create the individual hash data outputs.
|
||||
for (StringMap<DataArray>::iterator
|
||||
EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
|
||||
struct HashData *Entry = new HashData((*EI).getKeyData());
|
||||
|
||||
// Unique the entries.
|
||||
std::stable_sort(EI->second.begin(), EI->second.end(), DIESorter());
|
||||
std::stable_sort(EI->second.begin(), EI->second.end(), compareDIEs);
|
||||
EI->second.erase(std::unique(EI->second.begin(), EI->second.end()),
|
||||
EI->second.end());
|
||||
|
||||
for (DataArray::const_iterator DI = EI->second.begin(),
|
||||
DE = EI->second.end();
|
||||
DI != DE; ++DI)
|
||||
Entry->addData((*DI));
|
||||
HashData *Entry = new (Allocator) HashData(EI->getKey(), EI->second);
|
||||
Data.push_back(Entry);
|
||||
}
|
||||
|
||||
@ -216,7 +193,7 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) {
|
||||
D->getStringPool());
|
||||
Asm->OutStreamer.AddComment("Num DIEs");
|
||||
Asm->EmitInt32((*HI)->Data.size());
|
||||
for (std::vector<struct HashDataContents*>::const_iterator
|
||||
for (ArrayRef<HashDataContents*>::const_iterator
|
||||
DI = (*HI)->Data.begin(), DE = (*HI)->Data.end();
|
||||
DI != DE; ++DI) {
|
||||
// Emit the DIE offset
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define CODEGEN_ASMPRINTER_DWARFACCELTABLE_H__
|
||||
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
@ -164,22 +165,12 @@ class DwarfAccelTable {
|
||||
|
||||
private:
|
||||
struct TableHeaderData {
|
||||
|
||||
uint32_t die_offset_base;
|
||||
std::vector<Atom> Atoms;
|
||||
SmallVector<Atom, 1> Atoms;
|
||||
|
||||
TableHeaderData(ArrayRef<Atom> AtomList, uint32_t offset = 0)
|
||||
: die_offset_base(offset), Atoms(AtomList.begin(), AtomList.end()) { }
|
||||
|
||||
TableHeaderData(std::vector<DwarfAccelTable::Atom> &AtomList,
|
||||
uint32_t offset = 0) :
|
||||
die_offset_base(offset) {
|
||||
for (size_t i = 0, e = AtomList.size(); i != e; ++i)
|
||||
Atoms.push_back(AtomList[i]);
|
||||
}
|
||||
|
||||
TableHeaderData(DwarfAccelTable::Atom Atom, uint32_t offset = 0)
|
||||
: die_offset_base(offset) {
|
||||
Atoms.push_back(Atom);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void print (raw_ostream &O) {
|
||||
O << "die_offset_base: " << die_offset_base << "\n";
|
||||
@ -221,11 +212,11 @@ class DwarfAccelTable {
|
||||
StringRef Str;
|
||||
uint32_t HashValue;
|
||||
MCSymbol *Sym;
|
||||
std::vector<struct HashDataContents*> Data; // offsets
|
||||
HashData(StringRef S) : Str(S) {
|
||||
ArrayRef<HashDataContents*> Data; // offsets
|
||||
HashData(StringRef S, ArrayRef<HashDataContents*> Data)
|
||||
: Str(S), Data(Data) {
|
||||
HashValue = DwarfAccelTable::HashDJB(S);
|
||||
}
|
||||
void addData(struct HashDataContents *Datum) { Data.push_back(Datum); }
|
||||
#ifndef NDEBUG
|
||||
void print(raw_ostream &O) {
|
||||
O << "Name: " << Str << "\n";
|
||||
@ -255,15 +246,18 @@ class DwarfAccelTable {
|
||||
void EmitHashes(AsmPrinter *);
|
||||
void EmitOffsets(AsmPrinter *, MCSymbol *);
|
||||
void EmitData(AsmPrinter *, DwarfDebug *D);
|
||||
|
||||
|
||||
// Allocator for HashData and HashDataContents.
|
||||
BumpPtrAllocator Allocator;
|
||||
|
||||
// Output Variables
|
||||
TableHeader Header;
|
||||
TableHeaderData HeaderData;
|
||||
std::vector<HashData*> Data;
|
||||
|
||||
// String Data
|
||||
typedef std::vector<struct HashDataContents*> DataArray;
|
||||
typedef StringMap<DataArray> StringEntries;
|
||||
typedef std::vector<HashDataContents*> DataArray;
|
||||
typedef StringMap<DataArray, BumpPtrAllocator&> StringEntries;
|
||||
StringEntries Entries;
|
||||
|
||||
// Buckets/Hashes/Offsets
|
||||
@ -274,8 +268,7 @@ class DwarfAccelTable {
|
||||
|
||||
// Public Implementation
|
||||
public:
|
||||
DwarfAccelTable(DwarfAccelTable::Atom);
|
||||
DwarfAccelTable(std::vector<DwarfAccelTable::Atom> &);
|
||||
DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom>);
|
||||
~DwarfAccelTable();
|
||||
void AddName(StringRef, DIE*, char = 0);
|
||||
void FinalizeTable(AsmPrinter *, const char *);
|
||||
|
@ -1032,9 +1032,10 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
|
||||
// Add function template parameters.
|
||||
addTemplateParams(*SPDie, SP.getTemplateParams());
|
||||
|
||||
// Unfortunately this code needs to stay here to work around
|
||||
// a bug in older gdbs that requires the linkage name to resolve
|
||||
// multiple template functions.
|
||||
// Unfortunately this code needs to stay here instead of below the
|
||||
// AT_specification code in order to work around a bug in older
|
||||
// gdbs that requires the linkage name to resolve multiple template
|
||||
// functions.
|
||||
StringRef LinkageName = SP.getLinkageName();
|
||||
if (!LinkageName.empty())
|
||||
addString(SPDie, dwarf::DW_AT_MIPS_linkage_name,
|
||||
|
@ -23,10 +23,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
|
||||
#include "llvm/CodeGen/DFAPacketizer.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineInstrBundle.h"
|
||||
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/MC/MCInstrItineraries.h"
|
||||
using namespace llvm;
|
||||
@ -100,17 +100,17 @@ void DFAPacketizer::reserveResources(llvm::MachineInstr *MI) {
|
||||
reserveResources(&MID);
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
namespace {
|
||||
// DefaultVLIWScheduler - This class extends ScheduleDAGInstrs and overrides
|
||||
// Schedule method to build the dependence graph.
|
||||
class DefaultVLIWScheduler : public ScheduleDAGInstrs {
|
||||
public:
|
||||
DefaultVLIWScheduler(MachineFunction &MF, MachineLoopInfo &MLI,
|
||||
MachineDominatorTree &MDT, bool IsPostRA);
|
||||
MachineDominatorTree &MDT, bool IsPostRA);
|
||||
// Schedule - Actual scheduling work.
|
||||
void schedule();
|
||||
};
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
DefaultVLIWScheduler::DefaultVLIWScheduler(
|
||||
MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT,
|
||||
@ -129,25 +129,49 @@ VLIWPacketizerList::VLIWPacketizerList(
|
||||
bool IsPostRA) : TM(MF.getTarget()), MF(MF) {
|
||||
TII = TM.getInstrInfo();
|
||||
ResourceTracker = TII->CreateTargetScheduleState(&TM, 0);
|
||||
VLIWScheduler = new DefaultVLIWScheduler(MF, MLI, MDT, IsPostRA);
|
||||
SchedulerImpl = new DefaultVLIWScheduler(MF, MLI, MDT, IsPostRA);
|
||||
}
|
||||
|
||||
// VLIWPacketizerList Dtor
|
||||
VLIWPacketizerList::~VLIWPacketizerList() {
|
||||
if (VLIWScheduler)
|
||||
delete VLIWScheduler;
|
||||
delete SchedulerImpl;
|
||||
delete ResourceTracker;
|
||||
}
|
||||
|
||||
if (ResourceTracker)
|
||||
delete ResourceTracker;
|
||||
// ignorePseudoInstruction - ignore pseudo instructions.
|
||||
bool VLIWPacketizerList::ignorePseudoInstruction(MachineInstr *MI,
|
||||
MachineBasicBlock *MBB) {
|
||||
if (MI->isDebugValue())
|
||||
return true;
|
||||
|
||||
if (TII->isSchedulingBoundary(MI, MBB, MF))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// isSoloInstruction - return true if instruction I must end previous
|
||||
// packet.
|
||||
bool VLIWPacketizerList::isSoloInstruction(MachineInstr *I) {
|
||||
if (I->isInlineAsm())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// addToPacket - Add I to the current packet and reserve resource.
|
||||
void VLIWPacketizerList::addToPacket(MachineInstr *MI) {
|
||||
CurrentPacketMIs.push_back(MI);
|
||||
ResourceTracker->reserveResources(MI);
|
||||
}
|
||||
|
||||
// endPacket - End the current packet, bundle packet instructions and reset
|
||||
// DFA state.
|
||||
void VLIWPacketizerList::endPacket(MachineBasicBlock *MBB,
|
||||
MachineInstr *MI) {
|
||||
MachineInstr *I) {
|
||||
if (CurrentPacketMIs.size() > 1) {
|
||||
MachineInstr *MIFirst = CurrentPacketMIs.front();
|
||||
finalizeBundle(*MBB, MIFirst, MI);
|
||||
finalizeBundle(*MBB, MIFirst, I);
|
||||
}
|
||||
CurrentPacketMIs.clear();
|
||||
ResourceTracker->clearResources();
|
||||
@ -157,36 +181,31 @@ void VLIWPacketizerList::endPacket(MachineBasicBlock *MBB,
|
||||
void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB,
|
||||
MachineBasicBlock::iterator BeginItr,
|
||||
MachineBasicBlock::iterator EndItr) {
|
||||
assert(VLIWScheduler && "VLIW Scheduler is not initialized!");
|
||||
VLIWScheduler->enterRegion(MBB, BeginItr, EndItr, MBB->size());
|
||||
VLIWScheduler->schedule();
|
||||
VLIWScheduler->exitRegion();
|
||||
assert(MBB->end() == EndItr && "Bad EndIndex");
|
||||
|
||||
// Generate MI -> SU map.
|
||||
//std::map <MachineInstr*, SUnit*> MIToSUnit;
|
||||
MIToSUnit.clear();
|
||||
for (unsigned i = 0, e = VLIWScheduler->SUnits.size(); i != e; ++i) {
|
||||
SUnit *SU = &VLIWScheduler->SUnits[i];
|
||||
MIToSUnit[SU->getInstr()] = SU;
|
||||
}
|
||||
SchedulerImpl->enterRegion(MBB, BeginItr, EndItr, MBB->size());
|
||||
|
||||
// Build the DAG without reordering instructions.
|
||||
SchedulerImpl->schedule();
|
||||
|
||||
// Remember scheduling units.
|
||||
SUnits = SchedulerImpl->SUnits;
|
||||
|
||||
// The main packetizer loop.
|
||||
for (; BeginItr != EndItr; ++BeginItr) {
|
||||
MachineInstr *MI = BeginItr;
|
||||
|
||||
this->initPacketizerState();
|
||||
// Ignore pseudo instructions.
|
||||
if (ignorePseudoInstruction(MI, MBB))
|
||||
continue;
|
||||
|
||||
// End the current packet if needed.
|
||||
if (this->isSoloInstruction(MI)) {
|
||||
if (isSoloInstruction(MI)) {
|
||||
endPacket(MBB, MI);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore pseudo instructions.
|
||||
if (this->ignorePseudoInstruction(MI, MBB))
|
||||
continue;
|
||||
|
||||
SUnit *SUI = MIToSUnit[MI];
|
||||
SUnit *SUI = SchedulerImpl->getSUnit(MI);
|
||||
assert(SUI && "Missing SUnit Info!");
|
||||
|
||||
// Ask DFA if machine resource is available for MI.
|
||||
@ -196,13 +215,13 @@ void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB,
|
||||
for (std::vector<MachineInstr*>::iterator VI = CurrentPacketMIs.begin(),
|
||||
VE = CurrentPacketMIs.end(); VI != VE; ++VI) {
|
||||
MachineInstr *MJ = *VI;
|
||||
SUnit *SUJ = MIToSUnit[MJ];
|
||||
SUnit *SUJ = SchedulerImpl->getSUnit(MJ);
|
||||
assert(SUJ && "Missing SUnit Info!");
|
||||
|
||||
// Is it legal to packetize SUI and SUJ together.
|
||||
if (!this->isLegalToPacketizeTogether(SUI, SUJ)) {
|
||||
if (!isLegalToPacketizeTogether(SUI, SUJ)) {
|
||||
// Allow packetization if dependency can be pruned.
|
||||
if (!this->isLegalToPruneDependencies(SUI, SUJ)) {
|
||||
if (!isLegalToPruneDependencies(SUI, SUJ)) {
|
||||
// End the packet if dependency cannot be pruned.
|
||||
endPacket(MBB, MI);
|
||||
break;
|
||||
@ -215,9 +234,11 @@ void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB,
|
||||
}
|
||||
|
||||
// Add MI to the current packet.
|
||||
BeginItr = this->addToPacket(MI);
|
||||
addToPacket(MI);
|
||||
} // For all instructions in BB.
|
||||
|
||||
// End any packet left behind.
|
||||
endPacket(MBB, EndItr);
|
||||
|
||||
SchedulerImpl->exitRegion();
|
||||
}
|
||||
|
@ -1068,9 +1068,9 @@ class LiveIntervals::HMEditor {
|
||||
|
||||
#ifndef NDEBUG
|
||||
LIValidator validator;
|
||||
std::for_each(Entering.begin(), Entering.end(), validator);
|
||||
std::for_each(Internal.begin(), Internal.end(), validator);
|
||||
std::for_each(Exiting.begin(), Exiting.end(), validator);
|
||||
validator = std::for_each(Entering.begin(), Entering.end(), validator);
|
||||
validator = std::for_each(Internal.begin(), Internal.end(), validator);
|
||||
validator = std::for_each(Exiting.begin(), Exiting.end(), validator);
|
||||
assert(validator.rangesOk() && "moveAllOperandsFrom broke liveness.");
|
||||
#endif
|
||||
|
||||
@ -1115,9 +1115,9 @@ class LiveIntervals::HMEditor {
|
||||
|
||||
#ifndef NDEBUG
|
||||
LIValidator validator;
|
||||
std::for_each(Entering.begin(), Entering.end(), validator);
|
||||
std::for_each(Internal.begin(), Internal.end(), validator);
|
||||
std::for_each(Exiting.begin(), Exiting.end(), validator);
|
||||
validator = std::for_each(Entering.begin(), Entering.end(), validator);
|
||||
validator = std::for_each(Internal.begin(), Internal.end(), validator);
|
||||
validator = std::for_each(Exiting.begin(), Exiting.end(), validator);
|
||||
assert(validator.rangesOk() && "moveAllOperandsInto broke liveness.");
|
||||
#endif
|
||||
}
|
||||
|
@ -392,22 +392,44 @@ void MachineBasicBlock::updateTerminator() {
|
||||
TII->InsertBranch(*this, TBB, 0, Cond, dl);
|
||||
}
|
||||
} else {
|
||||
// Walk through the successors and find the successor which is not
|
||||
// a landing pad and is not the conditional branch destination (in TBB)
|
||||
// as the fallthrough successor.
|
||||
MachineBasicBlock *FallthroughBB = 0;
|
||||
for (succ_iterator SI = succ_begin(), SE = succ_end(); SI != SE; ++SI) {
|
||||
if ((*SI)->isLandingPad() || *SI == TBB)
|
||||
continue;
|
||||
assert(!FallthroughBB && "Found more than one fallthrough successor.");
|
||||
FallthroughBB = *SI;
|
||||
}
|
||||
if (!FallthroughBB && canFallThrough()) {
|
||||
// We fallthrough to the same basic block as the conditional jump
|
||||
// targets. Remove the conditional jump, leaving unconditional
|
||||
// fallthrough.
|
||||
// FIXME: This does not seem like a reasonable pattern to support, but it
|
||||
// has been seen in the wild coming out of degenerate ARM test cases.
|
||||
TII->RemoveBranch(*this);
|
||||
|
||||
// Finally update the unconditional successor to be reached via a branch
|
||||
// if it would not be reached by fallthrough.
|
||||
if (!isLayoutSuccessor(TBB))
|
||||
TII->InsertBranch(*this, TBB, 0, Cond, dl);
|
||||
return;
|
||||
}
|
||||
|
||||
// The block has a fallthrough conditional branch.
|
||||
MachineBasicBlock *MBBA = *succ_begin();
|
||||
MachineBasicBlock *MBBB = *llvm::next(succ_begin());
|
||||
if (MBBA == TBB) std::swap(MBBB, MBBA);
|
||||
if (isLayoutSuccessor(TBB)) {
|
||||
if (TII->ReverseBranchCondition(Cond)) {
|
||||
// We can't reverse the condition, add an unconditional branch.
|
||||
Cond.clear();
|
||||
TII->InsertBranch(*this, MBBA, 0, Cond, dl);
|
||||
TII->InsertBranch(*this, FallthroughBB, 0, Cond, dl);
|
||||
return;
|
||||
}
|
||||
TII->RemoveBranch(*this);
|
||||
TII->InsertBranch(*this, MBBA, 0, Cond, dl);
|
||||
} else if (!isLayoutSuccessor(MBBA)) {
|
||||
TII->InsertBranch(*this, FallthroughBB, 0, Cond, dl);
|
||||
} else if (!isLayoutSuccessor(FallthroughBB)) {
|
||||
TII->RemoveBranch(*this);
|
||||
TII->InsertBranch(*this, TBB, MBBA, Cond, dl);
|
||||
TII->InsertBranch(*this, TBB, FallthroughBB, Cond, dl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,13 +102,13 @@ class BlockChain {
|
||||
}
|
||||
|
||||
/// \brief Iterator over blocks within the chain.
|
||||
typedef SmallVectorImpl<MachineBasicBlock *>::const_iterator iterator;
|
||||
typedef SmallVectorImpl<MachineBasicBlock *>::iterator iterator;
|
||||
|
||||
/// \brief Beginning of blocks within the chain.
|
||||
iterator begin() const { return Blocks.begin(); }
|
||||
iterator begin() { return Blocks.begin(); }
|
||||
|
||||
/// \brief End of blocks within the chain.
|
||||
iterator end() const { return Blocks.end(); }
|
||||
iterator end() { return Blocks.end(); }
|
||||
|
||||
/// \brief Merge a block chain into this one.
|
||||
///
|
||||
@ -211,12 +211,15 @@ class MachineBlockPlacement : public MachineFunctionPass {
|
||||
void buildChain(MachineBasicBlock *BB, BlockChain &Chain,
|
||||
SmallVectorImpl<MachineBasicBlock *> &BlockWorkList,
|
||||
const BlockFilterSet *BlockFilter = 0);
|
||||
MachineBasicBlock *findBestLoopTop(MachineFunction &F,
|
||||
MachineLoop &L,
|
||||
MachineBasicBlock *findBestLoopTop(MachineLoop &L,
|
||||
const BlockFilterSet &LoopBlockSet);
|
||||
MachineBasicBlock *findBestLoopExit(MachineFunction &F,
|
||||
MachineLoop &L,
|
||||
const BlockFilterSet &LoopBlockSet);
|
||||
void buildLoopChains(MachineFunction &F, MachineLoop &L);
|
||||
void rotateLoop(BlockChain &LoopChain, MachineBasicBlock *ExitingBB,
|
||||
const BlockFilterSet &LoopBlockSet);
|
||||
void buildCFGChains(MachineFunction &F);
|
||||
void AlignLoops(MachineFunction &F);
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
@ -540,13 +543,74 @@ void MachineBlockPlacement::buildChain(
|
||||
|
||||
/// \brief Find the best loop top block for layout.
|
||||
///
|
||||
/// Look for a block which is strictly better than the loop header for laying
|
||||
/// out at the top of the loop. This looks for one and only one pattern:
|
||||
/// a latch block with no conditional exit. This block will cause a conditional
|
||||
/// jump around it or will be the bottom of the loop if we lay it out in place,
|
||||
/// but if it it doesn't end up at the bottom of the loop for any reason,
|
||||
/// rotation alone won't fix it. Because such a block will always result in an
|
||||
/// unconditional jump (for the backedge) rotating it in front of the loop
|
||||
/// header is always profitable.
|
||||
MachineBasicBlock *
|
||||
MachineBlockPlacement::findBestLoopTop(MachineLoop &L,
|
||||
const BlockFilterSet &LoopBlockSet) {
|
||||
// Check that the header hasn't been fused with a preheader block due to
|
||||
// crazy branches. If it has, we need to start with the header at the top to
|
||||
// prevent pulling the preheader into the loop body.
|
||||
BlockChain &HeaderChain = *BlockToChain[L.getHeader()];
|
||||
if (!LoopBlockSet.count(*HeaderChain.begin()))
|
||||
return L.getHeader();
|
||||
|
||||
DEBUG(dbgs() << "Finding best loop top for: "
|
||||
<< getBlockName(L.getHeader()) << "\n");
|
||||
|
||||
BlockFrequency BestPredFreq;
|
||||
MachineBasicBlock *BestPred = 0;
|
||||
for (MachineBasicBlock::pred_iterator PI = L.getHeader()->pred_begin(),
|
||||
PE = L.getHeader()->pred_end();
|
||||
PI != PE; ++PI) {
|
||||
MachineBasicBlock *Pred = *PI;
|
||||
if (!LoopBlockSet.count(Pred))
|
||||
continue;
|
||||
DEBUG(dbgs() << " header pred: " << getBlockName(Pred) << ", "
|
||||
<< Pred->succ_size() << " successors, "
|
||||
<< MBFI->getBlockFreq(Pred) << " freq\n");
|
||||
if (Pred->succ_size() > 1)
|
||||
continue;
|
||||
|
||||
BlockFrequency PredFreq = MBFI->getBlockFreq(Pred);
|
||||
if (!BestPred || PredFreq > BestPredFreq ||
|
||||
(!(PredFreq < BestPredFreq) &&
|
||||
Pred->isLayoutSuccessor(L.getHeader()))) {
|
||||
BestPred = Pred;
|
||||
BestPredFreq = PredFreq;
|
||||
}
|
||||
}
|
||||
|
||||
// If no direct predecessor is fine, just use the loop header.
|
||||
if (!BestPred)
|
||||
return L.getHeader();
|
||||
|
||||
// Walk backwards through any straight line of predecessors.
|
||||
while (BestPred->pred_size() == 1 &&
|
||||
(*BestPred->pred_begin())->succ_size() == 1 &&
|
||||
*BestPred->pred_begin() != L.getHeader())
|
||||
BestPred = *BestPred->pred_begin();
|
||||
|
||||
DEBUG(dbgs() << " final top: " << getBlockName(BestPred) << "\n");
|
||||
return BestPred;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Find the best loop exiting block for layout.
|
||||
///
|
||||
/// This routine implements the logic to analyze the loop looking for the best
|
||||
/// block to layout at the top of the loop. Typically this is done to maximize
|
||||
/// fallthrough opportunities.
|
||||
MachineBasicBlock *
|
||||
MachineBlockPlacement::findBestLoopTop(MachineFunction &F,
|
||||
MachineLoop &L,
|
||||
const BlockFilterSet &LoopBlockSet) {
|
||||
MachineBlockPlacement::findBestLoopExit(MachineFunction &F,
|
||||
MachineLoop &L,
|
||||
const BlockFilterSet &LoopBlockSet) {
|
||||
// We don't want to layout the loop linearly in all cases. If the loop header
|
||||
// is just a normal basic block in the loop, we want to look for what block
|
||||
// within the loop is the best one to layout at the top. However, if the loop
|
||||
@ -557,11 +621,11 @@ MachineBlockPlacement::findBestLoopTop(MachineFunction &F,
|
||||
// header and only rotate if safe.
|
||||
BlockChain &HeaderChain = *BlockToChain[L.getHeader()];
|
||||
if (!LoopBlockSet.count(*HeaderChain.begin()))
|
||||
return L.getHeader();
|
||||
return 0;
|
||||
|
||||
BlockFrequency BestExitEdgeFreq;
|
||||
unsigned BestExitLoopDepth = 0;
|
||||
MachineBasicBlock *ExitingBB = 0;
|
||||
MachineBasicBlock *LoopingBB = 0;
|
||||
// If there are exits to outer loops, loop rotation can severely limit
|
||||
// fallthrough opportunites unless it selects such an exit. Keep a set of
|
||||
// blocks where rotating to exit with that block will reach an outer loop.
|
||||
@ -584,15 +648,10 @@ MachineBlockPlacement::findBestLoopTop(MachineFunction &F,
|
||||
// successor isn't found.
|
||||
MachineBasicBlock *OldExitingBB = ExitingBB;
|
||||
BlockFrequency OldBestExitEdgeFreq = BestExitEdgeFreq;
|
||||
// We also compute and store the best looping successor for use in layout.
|
||||
MachineBasicBlock *BestLoopSucc = 0;
|
||||
bool HasLoopingSucc = false;
|
||||
// FIXME: Due to the performance of the probability and weight routines in
|
||||
// the MBPI analysis, we use the internal weights. This is only valid
|
||||
// because it is purely a ranking function, we don't care about anything
|
||||
// but the relative values.
|
||||
uint32_t BestLoopSuccWeight = 0;
|
||||
// FIXME: We also manually compute the probabilities to avoid quadratic
|
||||
// behavior.
|
||||
// the MBPI analysis, we use the internal weights and manually compute the
|
||||
// probabilities to avoid quadratic behavior.
|
||||
uint32_t WeightScale = 0;
|
||||
uint32_t SumWeight = MBPI->getSumForBlock(*I, WeightScale);
|
||||
for (MachineBasicBlock::succ_iterator SI = (*I)->succ_begin(),
|
||||
@ -604,10 +663,8 @@ MachineBlockPlacement::findBestLoopTop(MachineFunction &F,
|
||||
continue;
|
||||
BlockChain &SuccChain = *BlockToChain[*SI];
|
||||
// Don't split chains, either this chain or the successor's chain.
|
||||
if (&Chain == &SuccChain || *SI != *SuccChain.begin()) {
|
||||
DEBUG(dbgs() << " " << (LoopBlockSet.count(*SI) ? "looping: "
|
||||
: "exiting: ")
|
||||
<< getBlockName(*I) << " -> "
|
||||
if (&Chain == &SuccChain) {
|
||||
DEBUG(dbgs() << " exiting: " << getBlockName(*I) << " -> "
|
||||
<< getBlockName(*SI) << " (chain conflict)\n");
|
||||
continue;
|
||||
}
|
||||
@ -616,60 +673,103 @@ MachineBlockPlacement::findBestLoopTop(MachineFunction &F,
|
||||
if (LoopBlockSet.count(*SI)) {
|
||||
DEBUG(dbgs() << " looping: " << getBlockName(*I) << " -> "
|
||||
<< getBlockName(*SI) << " (" << SuccWeight << ")\n");
|
||||
if (BestLoopSucc && BestLoopSuccWeight >= SuccWeight)
|
||||
continue;
|
||||
|
||||
BestLoopSucc = *SI;
|
||||
BestLoopSuccWeight = SuccWeight;
|
||||
HasLoopingSucc = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned SuccLoopDepth = 0;
|
||||
if (MachineLoop *ExitLoop = MLI->getLoopFor(*SI)) {
|
||||
SuccLoopDepth = ExitLoop->getLoopDepth();
|
||||
if (ExitLoop->contains(&L))
|
||||
BlocksExitingToOuterLoop.insert(*I);
|
||||
}
|
||||
|
||||
BranchProbability SuccProb(SuccWeight / WeightScale, SumWeight);
|
||||
BlockFrequency ExitEdgeFreq = MBFI->getBlockFreq(*I) * SuccProb;
|
||||
DEBUG(dbgs() << " exiting: " << getBlockName(*I) << " -> "
|
||||
<< getBlockName(*SI) << " (" << ExitEdgeFreq << ")\n");
|
||||
<< getBlockName(*SI) << " [L:" << SuccLoopDepth
|
||||
<< "] (" << ExitEdgeFreq << ")\n");
|
||||
// Note that we slightly bias this toward an existing layout successor to
|
||||
// retain incoming order in the absence of better information.
|
||||
// FIXME: Should we bias this more strongly? It's pretty weak.
|
||||
if (!ExitingBB || ExitEdgeFreq > BestExitEdgeFreq ||
|
||||
if (!ExitingBB || BestExitLoopDepth < SuccLoopDepth ||
|
||||
ExitEdgeFreq > BestExitEdgeFreq ||
|
||||
((*I)->isLayoutSuccessor(*SI) &&
|
||||
!(ExitEdgeFreq < BestExitEdgeFreq))) {
|
||||
BestExitEdgeFreq = ExitEdgeFreq;
|
||||
ExitingBB = *I;
|
||||
}
|
||||
|
||||
if (MachineLoop *ExitLoop = MLI->getLoopFor(*SI))
|
||||
if (ExitLoop->contains(&L))
|
||||
BlocksExitingToOuterLoop.insert(*I);
|
||||
}
|
||||
|
||||
// Restore the old exiting state, no viable looping successor was found.
|
||||
if (!BestLoopSucc) {
|
||||
if (!HasLoopingSucc) {
|
||||
ExitingBB = OldExitingBB;
|
||||
BestExitEdgeFreq = OldBestExitEdgeFreq;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this was best exiting block thus far, also record the looping block.
|
||||
if (ExitingBB == *I)
|
||||
LoopingBB = BestLoopSucc;
|
||||
}
|
||||
// Without a candidate exitting block or with only a single block in the
|
||||
// Without a candidate exiting block or with only a single block in the
|
||||
// loop, just use the loop header to layout the loop.
|
||||
if (!ExitingBB || L.getNumBlocks() == 1)
|
||||
return L.getHeader();
|
||||
return 0;
|
||||
|
||||
// Also, if we have exit blocks which lead to outer loops but didn't select
|
||||
// one of them as the exiting block we are rotating toward, disable loop
|
||||
// rotation altogether.
|
||||
if (!BlocksExitingToOuterLoop.empty() &&
|
||||
!BlocksExitingToOuterLoop.count(ExitingBB))
|
||||
return L.getHeader();
|
||||
return 0;
|
||||
|
||||
assert(LoopingBB && "All successors of a loop block are exit blocks!");
|
||||
DEBUG(dbgs() << " Best exiting block: " << getBlockName(ExitingBB) << "\n");
|
||||
DEBUG(dbgs() << " Best top block: " << getBlockName(LoopingBB) << "\n");
|
||||
return LoopingBB;
|
||||
return ExitingBB;
|
||||
}
|
||||
|
||||
/// \brief Attempt to rotate an exiting block to the bottom of the loop.
|
||||
///
|
||||
/// Once we have built a chain, try to rotate it to line up the hot exit block
|
||||
/// with fallthrough out of the loop if doing so doesn't introduce unnecessary
|
||||
/// branches. For example, if the loop has fallthrough into its header and out
|
||||
/// of its bottom already, don't rotate it.
|
||||
void MachineBlockPlacement::rotateLoop(BlockChain &LoopChain,
|
||||
MachineBasicBlock *ExitingBB,
|
||||
const BlockFilterSet &LoopBlockSet) {
|
||||
if (!ExitingBB)
|
||||
return;
|
||||
|
||||
MachineBasicBlock *Top = *LoopChain.begin();
|
||||
bool ViableTopFallthrough = false;
|
||||
for (MachineBasicBlock::pred_iterator PI = Top->pred_begin(),
|
||||
PE = Top->pred_end();
|
||||
PI != PE; ++PI) {
|
||||
BlockChain *PredChain = BlockToChain[*PI];
|
||||
if (!LoopBlockSet.count(*PI) &&
|
||||
(!PredChain || *PI == *llvm::prior(PredChain->end()))) {
|
||||
ViableTopFallthrough = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the header has viable fallthrough, check whether the current loop
|
||||
// bottom is a viable exiting block. If so, bail out as rotating will
|
||||
// introduce an unnecessary branch.
|
||||
if (ViableTopFallthrough) {
|
||||
MachineBasicBlock *Bottom = *llvm::prior(LoopChain.end());
|
||||
for (MachineBasicBlock::succ_iterator SI = Bottom->succ_begin(),
|
||||
SE = Bottom->succ_end();
|
||||
SI != SE; ++SI) {
|
||||
BlockChain *SuccChain = BlockToChain[*SI];
|
||||
if (!LoopBlockSet.count(*SI) &&
|
||||
(!SuccChain || *SI == *SuccChain->begin()))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BlockChain::iterator ExitIt = std::find(LoopChain.begin(), LoopChain.end(),
|
||||
ExitingBB);
|
||||
if (ExitIt == LoopChain.end())
|
||||
return;
|
||||
|
||||
std::rotate(LoopChain.begin(), llvm::next(ExitIt), LoopChain.end());
|
||||
}
|
||||
|
||||
/// \brief Forms basic block chains from the natural loop structures.
|
||||
@ -688,8 +788,20 @@ void MachineBlockPlacement::buildLoopChains(MachineFunction &F,
|
||||
SmallVector<MachineBasicBlock *, 16> BlockWorkList;
|
||||
BlockFilterSet LoopBlockSet(L.block_begin(), L.block_end());
|
||||
|
||||
MachineBasicBlock *LayoutTop = findBestLoopTop(F, L, LoopBlockSet);
|
||||
BlockChain &LoopChain = *BlockToChain[LayoutTop];
|
||||
// First check to see if there is an obviously preferable top block for the
|
||||
// loop. This will default to the header, but may end up as one of the
|
||||
// predecessors to the header if there is one which will result in strictly
|
||||
// fewer branches in the loop body.
|
||||
MachineBasicBlock *LoopTop = findBestLoopTop(L, LoopBlockSet);
|
||||
|
||||
// If we selected just the header for the loop top, look for a potentially
|
||||
// profitable exit block in the event that rotating the loop can eliminate
|
||||
// branches by placing an exit edge at the bottom.
|
||||
MachineBasicBlock *ExitingBB = 0;
|
||||
if (LoopTop == L.getHeader())
|
||||
ExitingBB = findBestLoopExit(F, L, LoopBlockSet);
|
||||
|
||||
BlockChain &LoopChain = *BlockToChain[LoopTop];
|
||||
|
||||
// FIXME: This is a really lame way of walking the chains in the loop: we
|
||||
// walk the blocks, and use a set to prevent visiting a particular chain
|
||||
@ -721,7 +833,8 @@ void MachineBlockPlacement::buildLoopChains(MachineFunction &F,
|
||||
BlockWorkList.push_back(*Chain.begin());
|
||||
}
|
||||
|
||||
buildChain(LayoutTop, LoopChain, BlockWorkList, &LoopBlockSet);
|
||||
buildChain(LoopTop, LoopChain, BlockWorkList, &LoopBlockSet);
|
||||
rotateLoop(LoopChain, ExitingBB, LoopBlockSet);
|
||||
|
||||
DEBUG({
|
||||
// Crash at the end so we get all of the debugging output first.
|
||||
@ -733,7 +846,8 @@ void MachineBlockPlacement::buildLoopChains(MachineFunction &F,
|
||||
<< " Chain header: " << getBlockName(*LoopChain.begin()) << "\n";
|
||||
}
|
||||
for (BlockChain::iterator BCI = LoopChain.begin(), BCE = LoopChain.end();
|
||||
BCI != BCE; ++BCI)
|
||||
BCI != BCE; ++BCI) {
|
||||
dbgs() << " ... " << getBlockName(*BCI) << "\n";
|
||||
if (!LoopBlockSet.erase(*BCI)) {
|
||||
// We don't mark the loop as bad here because there are real situations
|
||||
// where this can occur. For example, with an unanalyzable fallthrough
|
||||
@ -743,6 +857,7 @@ void MachineBlockPlacement::buildLoopChains(MachineFunction &F,
|
||||
<< " Chain header: " << getBlockName(*LoopChain.begin()) << "\n"
|
||||
<< " Bad block: " << getBlockName(*BCI) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!LoopBlockSet.empty()) {
|
||||
BadLoop = true;
|
||||
@ -882,28 +997,33 @@ void MachineBlockPlacement::buildCFGChains(MachineFunction &F) {
|
||||
MachineBasicBlock *TBB = 0, *FBB = 0; // For AnalyzeBranch.
|
||||
if (!TII->AnalyzeBranch(F.back(), TBB, FBB, Cond))
|
||||
F.back().updateTerminator();
|
||||
}
|
||||
|
||||
/// \brief Recursive helper to align a loop and any nested loops.
|
||||
static void AlignLoop(MachineFunction &F, MachineLoop *L, unsigned Align) {
|
||||
// Recurse through nested loops.
|
||||
for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I)
|
||||
AlignLoop(F, *I, Align);
|
||||
|
||||
L->getTopBlock()->setAlignment(Align);
|
||||
}
|
||||
|
||||
/// \brief Align loop headers to target preferred alignments.
|
||||
void MachineBlockPlacement::AlignLoops(MachineFunction &F) {
|
||||
// Walk through the backedges of the function now that we have fully laid out
|
||||
// the basic blocks and align the destination of each backedge. We don't rely
|
||||
// on the loop info here so that we can align backedges in unnatural CFGs and
|
||||
// backedges that were introduced purely because of the loop rotations done
|
||||
// during this layout pass.
|
||||
// FIXME: This isn't quite right, we shouldn't align backedges that result
|
||||
// from blocks being sunken below the exit block for the function.
|
||||
if (F.getFunction()->hasFnAttr(Attribute::OptimizeForSize))
|
||||
return;
|
||||
|
||||
unsigned Align = TLI->getPrefLoopAlignment();
|
||||
if (!Align)
|
||||
return; // Don't care about loop alignment.
|
||||
|
||||
for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); I != E; ++I)
|
||||
AlignLoop(F, *I, Align);
|
||||
SmallPtrSet<MachineBasicBlock *, 16> PreviousBlocks;
|
||||
for (BlockChain::iterator BI = FunctionChain.begin(),
|
||||
BE = FunctionChain.end();
|
||||
BI != BE; ++BI) {
|
||||
PreviousBlocks.insert(*BI);
|
||||
// Set alignment on the destination of all the back edges in the new
|
||||
// ordering.
|
||||
for (MachineBasicBlock::succ_iterator SI = (*BI)->succ_begin(),
|
||||
SE = (*BI)->succ_end();
|
||||
SI != SE; ++SI)
|
||||
if (PreviousBlocks.count(*SI))
|
||||
(*SI)->setAlignment(Align);
|
||||
}
|
||||
}
|
||||
|
||||
bool MachineBlockPlacement::runOnMachineFunction(MachineFunction &F) {
|
||||
@ -919,7 +1039,6 @@ bool MachineBlockPlacement::runOnMachineFunction(MachineFunction &F) {
|
||||
assert(BlockToChain.empty());
|
||||
|
||||
buildCFGChains(F);
|
||||
AlignLoops(F);
|
||||
|
||||
BlockToChain.clear();
|
||||
ChainAllocator.DestroyAll();
|
||||
|
@ -37,8 +37,9 @@ static cl::opt<bool> DisableTailDuplicate("disable-tail-duplicate", cl::Hidden,
|
||||
cl::desc("Disable tail duplication"));
|
||||
static cl::opt<bool> DisableEarlyTailDup("disable-early-taildup", cl::Hidden,
|
||||
cl::desc("Disable pre-register allocation tail duplication"));
|
||||
static cl::opt<bool> EnableBlockPlacement("enable-block-placement",
|
||||
cl::Hidden, cl::desc("Enable probability-driven block placement"));
|
||||
static cl::opt<bool> DisableBlockPlacement("disable-block-placement",
|
||||
cl::Hidden, cl::desc("Disable the probability-driven block placement, and "
|
||||
"re-enable the old code placement pass"));
|
||||
static cl::opt<bool> EnableBlockPlacementStats("enable-block-placement-stats",
|
||||
cl::Hidden, cl::desc("Collect probability-driven block placement stats"));
|
||||
static cl::opt<bool> DisableCodePlace("disable-code-place", cl::Hidden,
|
||||
@ -206,7 +207,7 @@ TargetPassConfig::~TargetPassConfig() {
|
||||
// Out of line constructor provides default values for pass options and
|
||||
// registers all common codegen passes.
|
||||
TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm)
|
||||
: ImmutablePass(ID), TM(tm), PM(pm), Impl(0), Initialized(false),
|
||||
: ImmutablePass(ID), TM(tm), PM(&pm), Impl(0), Initialized(false),
|
||||
DisableVerify(false),
|
||||
EnableTailMerge(true) {
|
||||
|
||||
@ -233,7 +234,7 @@ TargetPassConfig *LLVMTargetMachine::createPassConfig(PassManagerBase &PM) {
|
||||
}
|
||||
|
||||
TargetPassConfig::TargetPassConfig()
|
||||
: ImmutablePass(ID), PM(*(PassManagerBase*)0) {
|
||||
: ImmutablePass(ID), PM(0) {
|
||||
llvm_unreachable("TargetPassConfig should not be constructed on-the-fly");
|
||||
}
|
||||
|
||||
@ -268,16 +269,16 @@ AnalysisID TargetPassConfig::addPass(char &ID) {
|
||||
Pass *P = Pass::createPass(FinalID);
|
||||
if (!P)
|
||||
llvm_unreachable("Pass ID not registered");
|
||||
PM.add(P);
|
||||
PM->add(P);
|
||||
return FinalID;
|
||||
}
|
||||
|
||||
void TargetPassConfig::printAndVerify(const char *Banner) const {
|
||||
if (TM->shouldPrintMachineCode())
|
||||
PM.add(createMachineFunctionPrinterPass(dbgs(), Banner));
|
||||
PM->add(createMachineFunctionPrinterPass(dbgs(), Banner));
|
||||
|
||||
if (VerifyMachineCode)
|
||||
PM.add(createMachineVerifierPass(Banner));
|
||||
PM->add(createMachineVerifierPass(Banner));
|
||||
}
|
||||
|
||||
/// Add common target configurable passes that perform LLVM IR to IR transforms
|
||||
@ -287,46 +288,46 @@ void TargetPassConfig::addIRPasses() {
|
||||
// Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
|
||||
// BasicAliasAnalysis wins if they disagree. This is intended to help
|
||||
// support "obvious" type-punning idioms.
|
||||
PM.add(createTypeBasedAliasAnalysisPass());
|
||||
PM.add(createBasicAliasAnalysisPass());
|
||||
PM->add(createTypeBasedAliasAnalysisPass());
|
||||
PM->add(createBasicAliasAnalysisPass());
|
||||
|
||||
// Before running any passes, run the verifier to determine if the input
|
||||
// coming from the front-end and/or optimizer is valid.
|
||||
if (!DisableVerify)
|
||||
PM.add(createVerifierPass());
|
||||
PM->add(createVerifierPass());
|
||||
|
||||
// Run loop strength reduction before anything else.
|
||||
if (getOptLevel() != CodeGenOpt::None && !DisableLSR) {
|
||||
PM.add(createLoopStrengthReducePass(getTargetLowering()));
|
||||
PM->add(createLoopStrengthReducePass(getTargetLowering()));
|
||||
if (PrintLSR)
|
||||
PM.add(createPrintFunctionPass("\n\n*** Code after LSR ***\n", &dbgs()));
|
||||
PM->add(createPrintFunctionPass("\n\n*** Code after LSR ***\n", &dbgs()));
|
||||
}
|
||||
|
||||
PM.add(createGCLoweringPass());
|
||||
PM->add(createGCLoweringPass());
|
||||
|
||||
// Make sure that no unreachable blocks are instruction selected.
|
||||
PM.add(createUnreachableBlockEliminationPass());
|
||||
PM->add(createUnreachableBlockEliminationPass());
|
||||
}
|
||||
|
||||
/// Add common passes that perform LLVM IR to IR transforms in preparation for
|
||||
/// instruction selection.
|
||||
void TargetPassConfig::addISelPrepare() {
|
||||
if (getOptLevel() != CodeGenOpt::None && !DisableCGP)
|
||||
PM.add(createCodeGenPreparePass(getTargetLowering()));
|
||||
PM->add(createCodeGenPreparePass(getTargetLowering()));
|
||||
|
||||
PM.add(createStackProtectorPass(getTargetLowering()));
|
||||
PM->add(createStackProtectorPass(getTargetLowering()));
|
||||
|
||||
addPreISel();
|
||||
|
||||
if (PrintISelInput)
|
||||
PM.add(createPrintFunctionPass("\n\n"
|
||||
"*** Final LLVM Code input to ISel ***\n",
|
||||
&dbgs()));
|
||||
PM->add(createPrintFunctionPass("\n\n"
|
||||
"*** Final LLVM Code input to ISel ***\n",
|
||||
&dbgs()));
|
||||
|
||||
// All passes which modify the LLVM IR are now complete; run the verifier
|
||||
// to ensure that the IR is valid.
|
||||
if (!DisableVerify)
|
||||
PM.add(createVerifierPass());
|
||||
PM->add(createVerifierPass());
|
||||
}
|
||||
|
||||
/// Add the complete set of target-independent postISel code generator passes.
|
||||
@ -404,7 +405,7 @@ void TargetPassConfig::addMachinePasses() {
|
||||
// GC
|
||||
addPass(GCMachineCodeAnalysisID);
|
||||
if (PrintGCInfo)
|
||||
PM.add(createGCInfoPrinter(dbgs()));
|
||||
PM->add(createGCInfoPrinter(dbgs()));
|
||||
|
||||
// Basic block placement.
|
||||
if (getOptLevel() != CodeGenOpt::None)
|
||||
@ -521,7 +522,7 @@ void TargetPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) {
|
||||
addPass(PHIEliminationID);
|
||||
addPass(TwoAddressInstructionPassID);
|
||||
|
||||
PM.add(RegAllocPass);
|
||||
PM->add(RegAllocPass);
|
||||
printAndVerify("After Register Allocation");
|
||||
}
|
||||
|
||||
@ -563,7 +564,7 @@ void TargetPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
|
||||
printAndVerify("After Machine Scheduling");
|
||||
|
||||
// Add the selected register allocation pass.
|
||||
PM.add(RegAllocPass);
|
||||
PM->add(RegAllocPass);
|
||||
printAndVerify("After Register Allocation");
|
||||
|
||||
// FinalizeRegAlloc is convenient until MachineInstrBundles is more mature,
|
||||
@ -610,10 +611,10 @@ void TargetPassConfig::addMachineLateOptimization() {
|
||||
/// Add standard basic block placement passes.
|
||||
void TargetPassConfig::addBlockPlacement() {
|
||||
AnalysisID ID = &NoPassID;
|
||||
if (EnableBlockPlacement) {
|
||||
// MachineBlockPlacement is an experimental pass which is disabled by
|
||||
// default currently. Eventually it should subsume CodePlacementOpt, so
|
||||
// when enabled, the other is disabled.
|
||||
if (!DisableBlockPlacement) {
|
||||
// MachineBlockPlacement is a new pass which subsumes the functionality of
|
||||
// CodPlacementOpt. The old code placement pass can be restored by
|
||||
// disabling block placement, but eventually it will be removed.
|
||||
ID = addPass(MachineBlockPlacementID);
|
||||
} else {
|
||||
ID = addPass(CodePlacementOptID);
|
||||
|
@ -39,8 +39,8 @@ ScheduleDAGInstrs::ScheduleDAGInstrs(MachineFunction &mf,
|
||||
LiveIntervals *lis)
|
||||
: ScheduleDAG(mf), MLI(mli), MDT(mdt), MFI(mf.getFrameInfo()),
|
||||
InstrItins(mf.getTarget().getInstrItineraryData()), LIS(lis),
|
||||
IsPostRA(IsPostRAFlag), UnitLatencies(false), LoopRegs(MLI, MDT),
|
||||
FirstDbgValue(0) {
|
||||
IsPostRA(IsPostRAFlag), UnitLatencies(false), CanHandleTerminators(false),
|
||||
LoopRegs(MLI, MDT), FirstDbgValue(0) {
|
||||
assert((IsPostRA || LIS) && "PreRA scheduling requires LiveIntervals");
|
||||
DbgValues.clear();
|
||||
assert(!(IsPostRA && MRI.getNumVirtRegs()) &&
|
||||
@ -554,7 +554,7 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA) {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(!MI->isTerminator() && !MI->isLabel() &&
|
||||
assert((!MI->isTerminator() || CanHandleTerminators) && !MI->isLabel() &&
|
||||
"Cannot schedule terminators or labels!");
|
||||
|
||||
SUnit *SU = MISUnitMap[MI];
|
||||
|
@ -1080,6 +1080,7 @@ void DAGCombiner::Run(CombineLevel AtLevel) {
|
||||
|
||||
// If the root changed (e.g. it was a dead load, update the root).
|
||||
DAG.setRoot(Dummy.getValue());
|
||||
DAG.RemoveDeadNodes();
|
||||
}
|
||||
|
||||
SDValue DAGCombiner::visit(SDNode *N) {
|
||||
|
@ -417,7 +417,8 @@ SDValue VectorLegalizer::ExpandVSELECT(SDValue Op) {
|
||||
|
||||
Op1 = DAG.getNode(ISD::AND, DL, VT, Op1, Mask);
|
||||
Op2 = DAG.getNode(ISD::AND, DL, VT, Op2, NotMask);
|
||||
return DAG.getNode(ISD::OR, DL, VT, Op1, Op2);
|
||||
SDValue Val = DAG.getNode(ISD::OR, DL, VT, Op1, Op2);
|
||||
return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Val);
|
||||
}
|
||||
|
||||
SDValue VectorLegalizer::ExpandUINT_TO_FLOAT(SDValue Op) {
|
||||
|
@ -138,9 +138,11 @@ static void AddGlue(SDNode *N, SDValue Glue, bool AddGlue, SelectionDAG *DAG) {
|
||||
// Don't add glue from a node to itself.
|
||||
if (GlueDestNode == N) return;
|
||||
|
||||
// Don't add glue to something which already has glue.
|
||||
if (N->getValueType(N->getNumValues() - 1) == MVT::Glue) return;
|
||||
|
||||
// Don't add glue to something that already has it, either as a use or value.
|
||||
if (N->getOperand(N->getNumOperands()-1).getValueType() == MVT::Glue ||
|
||||
N->getValueType(N->getNumValues() - 1) == MVT::Glue) {
|
||||
return;
|
||||
}
|
||||
for (unsigned I = 0, E = N->getNumValues(); I != E; ++I)
|
||||
VTs.push_back(N->getValueType(I));
|
||||
|
||||
|
@ -5050,7 +5050,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
||||
}
|
||||
case Intrinsic::gcroot:
|
||||
if (GFI) {
|
||||
const Value *Alloca = I.getArgOperand(0);
|
||||
const Value *Alloca = I.getArgOperand(0)->stripPointerCasts();
|
||||
const Constant *TypeMap = cast<Constant>(I.getArgOperand(1));
|
||||
|
||||
FrameIndexSDNode *FI = cast<FrameIndexSDNode>(getValue(Alloca).getNode());
|
||||
|
@ -1367,8 +1367,9 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
|
||||
// bits on that side are also known to be set on the other side, turn this
|
||||
// into an AND, as we know the bits will be cleared.
|
||||
// e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2
|
||||
if ((NewMask & (KnownZero|KnownOne)) == NewMask) { // all known
|
||||
if ((KnownOne & KnownOne2) == KnownOne) {
|
||||
// NB: it is okay if more bits are known than are requested
|
||||
if ((NewMask & (KnownZero|KnownOne)) == NewMask) { // all known on one side
|
||||
if (KnownOne == KnownOne2) { // set bits are the same on both sides
|
||||
EVT VT = Op.getValueType();
|
||||
SDValue ANDC = TLO.DAG.getConstant(~KnownOne & NewMask, VT);
|
||||
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::AND, dl, VT,
|
||||
|
@ -34,7 +34,8 @@ void SlotIndexes::releaseMemory() {
|
||||
mi2iMap.clear();
|
||||
MBBRanges.clear();
|
||||
idx2MBBMap.clear();
|
||||
clearList();
|
||||
indexList.clear();
|
||||
ileAllocator.Reset();
|
||||
}
|
||||
|
||||
bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) {
|
||||
@ -45,17 +46,15 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) {
|
||||
// iterator in lock-step (though skipping it over indexes which have
|
||||
// null pointers in the instruction field).
|
||||
// At each iteration assert that the instruction pointed to in the index
|
||||
// is the same one pointed to by the MI iterator. This
|
||||
// is the same one pointed to by the MI iterator. This
|
||||
|
||||
// FIXME: This can be simplified. The mi2iMap_, Idx2MBBMap, etc. should
|
||||
// only need to be set up once after the first numbering is computed.
|
||||
|
||||
mf = &fn;
|
||||
initList();
|
||||
|
||||
// Check that the list contains only the sentinal.
|
||||
assert(indexListHead->getNext() == 0 &&
|
||||
"Index list non-empty at initial numbering?");
|
||||
assert(indexList.empty() && "Index list non-empty at initial numbering?");
|
||||
assert(idx2MBBMap.empty() &&
|
||||
"Index -> MBB mapping non-empty at initial numbering?");
|
||||
assert(MBBRanges.empty() &&
|
||||
@ -68,7 +67,7 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) {
|
||||
MBBRanges.resize(mf->getNumBlockIDs());
|
||||
idx2MBBMap.reserve(mf->size());
|
||||
|
||||
push_back(createEntry(0, index));
|
||||
indexList.push_back(createEntry(0, index));
|
||||
|
||||
// Iterate over the function.
|
||||
for (MachineFunction::iterator mbbItr = mf->begin(), mbbEnd = mf->end();
|
||||
@ -76,7 +75,7 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) {
|
||||
MachineBasicBlock *mbb = &*mbbItr;
|
||||
|
||||
// Insert an index for the MBB start.
|
||||
SlotIndex blockStartIndex(back(), SlotIndex::Slot_Block);
|
||||
SlotIndex blockStartIndex(&indexList.back(), SlotIndex::Slot_Block);
|
||||
|
||||
for (MachineBasicBlock::iterator miItr = mbb->begin(), miEnd = mbb->end();
|
||||
miItr != miEnd; ++miItr) {
|
||||
@ -85,20 +84,20 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) {
|
||||
continue;
|
||||
|
||||
// Insert a store index for the instr.
|
||||
push_back(createEntry(mi, index += SlotIndex::InstrDist));
|
||||
indexList.push_back(createEntry(mi, index += SlotIndex::InstrDist));
|
||||
|
||||
// Save this base index in the maps.
|
||||
mi2iMap.insert(std::make_pair(mi, SlotIndex(back(),
|
||||
mi2iMap.insert(std::make_pair(mi, SlotIndex(&indexList.back(),
|
||||
SlotIndex::Slot_Block)));
|
||||
|
||||
|
||||
++functionSize;
|
||||
}
|
||||
|
||||
// We insert one blank instructions between basic blocks.
|
||||
push_back(createEntry(0, index += SlotIndex::InstrDist));
|
||||
indexList.push_back(createEntry(0, index += SlotIndex::InstrDist));
|
||||
|
||||
MBBRanges[mbb->getNumber()].first = blockStartIndex;
|
||||
MBBRanges[mbb->getNumber()].second = SlotIndex(back(),
|
||||
MBBRanges[mbb->getNumber()].second = SlotIndex(&indexList.back(),
|
||||
SlotIndex::Slot_Block);
|
||||
idx2MBBMap.push_back(IdxMBBPair(blockStartIndex, mbb));
|
||||
}
|
||||
@ -119,38 +118,37 @@ void SlotIndexes::renumberIndexes() {
|
||||
|
||||
unsigned index = 0;
|
||||
|
||||
for (IndexListEntry *curEntry = front(); curEntry != getTail();
|
||||
curEntry = curEntry->getNext()) {
|
||||
curEntry->setIndex(index);
|
||||
for (IndexList::iterator I = indexList.begin(), E = indexList.end();
|
||||
I != E; ++I) {
|
||||
I->setIndex(index);
|
||||
index += SlotIndex::InstrDist;
|
||||
}
|
||||
}
|
||||
|
||||
// Renumber indexes locally after curEntry was inserted, but failed to get a new
|
||||
// Renumber indexes locally after curItr was inserted, but failed to get a new
|
||||
// index.
|
||||
void SlotIndexes::renumberIndexes(IndexListEntry *curEntry) {
|
||||
void SlotIndexes::renumberIndexes(IndexList::iterator curItr) {
|
||||
// Number indexes with half the default spacing so we can catch up quickly.
|
||||
const unsigned Space = SlotIndex::InstrDist/2;
|
||||
assert((Space & 3) == 0 && "InstrDist must be a multiple of 2*NUM");
|
||||
|
||||
IndexListEntry *start = curEntry->getPrev();
|
||||
unsigned index = start->getIndex();
|
||||
IndexListEntry *tail = getTail();
|
||||
IndexList::iterator startItr = prior(curItr);
|
||||
unsigned index = startItr->getIndex();
|
||||
do {
|
||||
curEntry->setIndex(index += Space);
|
||||
curEntry = curEntry->getNext();
|
||||
curItr->setIndex(index += Space);
|
||||
++curItr;
|
||||
// If the next index is bigger, we have caught up.
|
||||
} while (curEntry != tail && curEntry->getIndex() <= index);
|
||||
} while (curItr != indexList.end() && curItr->getIndex() <= index);
|
||||
|
||||
DEBUG(dbgs() << "\n*** Renumbered SlotIndexes " << start->getIndex() << '-'
|
||||
DEBUG(dbgs() << "\n*** Renumbered SlotIndexes " << startItr->getIndex() << '-'
|
||||
<< index << " ***\n");
|
||||
++NumLocalRenum;
|
||||
}
|
||||
|
||||
|
||||
void SlotIndexes::dump() const {
|
||||
for (const IndexListEntry *itr = front(); itr != getTail();
|
||||
itr = itr->getNext()) {
|
||||
for (IndexList::const_iterator itr = indexList.begin();
|
||||
itr != indexList.end(); ++itr) {
|
||||
dbgs() << itr->getIndex() << " ";
|
||||
|
||||
if (itr->getInstr() != 0) {
|
||||
@ -168,7 +166,7 @@ void SlotIndexes::dump() const {
|
||||
// Print a SlotIndex to a raw_ostream.
|
||||
void SlotIndex::print(raw_ostream &os) const {
|
||||
if (isValid())
|
||||
os << entry().getIndex() << "Berd"[getSlot()];
|
||||
os << listEntry()->getIndex() << "Berd"[getSlot()];
|
||||
else
|
||||
os << "invalid";
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
add_llvm_library(LLVMRuntimeDyld
|
||||
GDBRegistrar.cpp
|
||||
RuntimeDyld.cpp
|
||||
RuntimeDyldMachO.cpp
|
||||
RuntimeDyldELF.cpp
|
||||
RuntimeDyldMachO.cpp
|
||||
)
|
||||
|
214
lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp
Normal file
214
lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
//===-- GDBRegistrar.cpp - Registers objects with GDB ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "JITRegistrar.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/MutexGuard.h"
|
||||
#include "llvm/Support/Mutex.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// This must be kept in sync with gdb/gdb/jit.h .
|
||||
extern "C" {
|
||||
|
||||
typedef enum {
|
||||
JIT_NOACTION = 0,
|
||||
JIT_REGISTER_FN,
|
||||
JIT_UNREGISTER_FN
|
||||
} jit_actions_t;
|
||||
|
||||
struct jit_code_entry {
|
||||
struct jit_code_entry *next_entry;
|
||||
struct jit_code_entry *prev_entry;
|
||||
const char *symfile_addr;
|
||||
uint64_t symfile_size;
|
||||
};
|
||||
|
||||
struct jit_descriptor {
|
||||
uint32_t version;
|
||||
// This should be jit_actions_t, but we want to be specific about the
|
||||
// bit-width.
|
||||
uint32_t action_flag;
|
||||
struct jit_code_entry *relevant_entry;
|
||||
struct jit_code_entry *first_entry;
|
||||
};
|
||||
|
||||
// We put information about the JITed function in this global, which the
|
||||
// debugger reads. Make sure to specify the version statically, because the
|
||||
// debugger checks the version before we can set it during runtime.
|
||||
static struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
|
||||
|
||||
// Debuggers puts a breakpoint in this function.
|
||||
LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { }
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Buffer for an in-memory object file in executable memory
|
||||
typedef llvm::DenseMap< const char*,
|
||||
std::pair<std::size_t, jit_code_entry*> >
|
||||
RegisteredObjectBufferMap;
|
||||
|
||||
/// Global access point for the JIT debugging interface designed for use with a
|
||||
/// singleton toolbox. Handles thread-safe registration and deregistration of
|
||||
/// object files that are in executable memory managed by the client of this
|
||||
/// class.
|
||||
class GDBJITRegistrar : public JITRegistrar {
|
||||
/// A map of in-memory object files that have been registered with the
|
||||
/// JIT interface.
|
||||
RegisteredObjectBufferMap ObjectBufferMap;
|
||||
|
||||
public:
|
||||
/// Instantiates the JIT service.
|
||||
GDBJITRegistrar() : ObjectBufferMap() {}
|
||||
|
||||
/// Unregisters each object that was previously registered and releases all
|
||||
/// internal resources.
|
||||
virtual ~GDBJITRegistrar();
|
||||
|
||||
/// Creates an entry in the JIT registry for the buffer @p Object,
|
||||
/// which must contain an object file in executable memory with any
|
||||
/// debug information for the debugger.
|
||||
void registerObject(const MemoryBuffer &Object);
|
||||
|
||||
/// Removes the internal registration of @p Object, and
|
||||
/// frees associated resources.
|
||||
/// Returns true if @p Object was found in ObjectBufferMap.
|
||||
bool deregisterObject(const MemoryBuffer &Object);
|
||||
|
||||
private:
|
||||
/// Deregister the debug info for the given object file from the debugger
|
||||
/// and delete any temporary copies. This private method does not remove
|
||||
/// the function from Map so that it can be called while iterating over Map.
|
||||
void deregisterObjectInternal(RegisteredObjectBufferMap::iterator I);
|
||||
};
|
||||
|
||||
/// Lock used to serialize all jit registration events, since they
|
||||
/// modify global variables.
|
||||
llvm::sys::Mutex JITDebugLock;
|
||||
|
||||
/// Acquire the lock and do the registration.
|
||||
void NotifyDebugger(jit_code_entry* JITCodeEntry) {
|
||||
llvm::MutexGuard locked(JITDebugLock);
|
||||
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
|
||||
|
||||
// Insert this entry at the head of the list.
|
||||
JITCodeEntry->prev_entry = NULL;
|
||||
jit_code_entry* NextEntry = __jit_debug_descriptor.first_entry;
|
||||
JITCodeEntry->next_entry = NextEntry;
|
||||
if (NextEntry != NULL) {
|
||||
NextEntry->prev_entry = JITCodeEntry;
|
||||
}
|
||||
__jit_debug_descriptor.first_entry = JITCodeEntry;
|
||||
__jit_debug_descriptor.relevant_entry = JITCodeEntry;
|
||||
__jit_debug_register_code();
|
||||
}
|
||||
|
||||
GDBJITRegistrar::~GDBJITRegistrar() {
|
||||
// Free all registered object files.
|
||||
for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end();
|
||||
I != E; ++I) {
|
||||
// Call the private method that doesn't update the map so our iterator
|
||||
// doesn't break.
|
||||
deregisterObjectInternal(I);
|
||||
}
|
||||
ObjectBufferMap.clear();
|
||||
}
|
||||
|
||||
void GDBJITRegistrar::registerObject(const MemoryBuffer &Object) {
|
||||
|
||||
const char *Buffer = Object.getBufferStart();
|
||||
size_t Size = Object.getBufferSize();
|
||||
|
||||
assert(Buffer && "Attempt to register a null object with a debugger.");
|
||||
assert(ObjectBufferMap.find(Buffer) == ObjectBufferMap.end() &&
|
||||
"Second attempt to perform debug registration.");
|
||||
jit_code_entry* JITCodeEntry = new jit_code_entry();
|
||||
|
||||
if (JITCodeEntry == 0) {
|
||||
llvm::report_fatal_error(
|
||||
"Allocation failed when registering a JIT entry!\n");
|
||||
}
|
||||
else {
|
||||
JITCodeEntry->symfile_addr = Buffer;
|
||||
JITCodeEntry->symfile_size = Size;
|
||||
|
||||
ObjectBufferMap[Buffer] = std::make_pair(Size, JITCodeEntry);
|
||||
NotifyDebugger(JITCodeEntry);
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBJITRegistrar::deregisterObject(const MemoryBuffer& Object) {
|
||||
const char *Buffer = Object.getBufferStart();
|
||||
RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer);
|
||||
|
||||
if (I != ObjectBufferMap.end()) {
|
||||
deregisterObjectInternal(I);
|
||||
ObjectBufferMap.erase(I);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GDBJITRegistrar::deregisterObjectInternal(
|
||||
RegisteredObjectBufferMap::iterator I) {
|
||||
|
||||
jit_code_entry*& JITCodeEntry = I->second.second;
|
||||
|
||||
// Acquire the lock and do the unregistration.
|
||||
{
|
||||
llvm::MutexGuard locked(JITDebugLock);
|
||||
__jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
|
||||
|
||||
// Remove the jit_code_entry from the linked list.
|
||||
jit_code_entry* PrevEntry = JITCodeEntry->prev_entry;
|
||||
jit_code_entry* NextEntry = JITCodeEntry->next_entry;
|
||||
|
||||
if (NextEntry) {
|
||||
NextEntry->prev_entry = PrevEntry;
|
||||
}
|
||||
if (PrevEntry) {
|
||||
PrevEntry->next_entry = NextEntry;
|
||||
}
|
||||
else {
|
||||
assert(__jit_debug_descriptor.first_entry == JITCodeEntry);
|
||||
__jit_debug_descriptor.first_entry = NextEntry;
|
||||
}
|
||||
|
||||
// Tell the debugger which entry we removed, and unregister the code.
|
||||
__jit_debug_descriptor.relevant_entry = JITCodeEntry;
|
||||
__jit_debug_register_code();
|
||||
}
|
||||
|
||||
delete JITCodeEntry;
|
||||
JITCodeEntry = NULL;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
namespace llvm {
|
||||
|
||||
JITRegistrar& JITRegistrar::getGDBRegistrar() {
|
||||
static GDBJITRegistrar* sRegistrar = NULL;
|
||||
if (sRegistrar == NULL) {
|
||||
// The mutex is here so that it won't slow down access once the registrar
|
||||
// is instantiated
|
||||
llvm::MutexGuard locked(JITDebugLock);
|
||||
// Check again to be sure another thread didn't create this while we waited
|
||||
if (sRegistrar == NULL) {
|
||||
sRegistrar = new GDBJITRegistrar;
|
||||
}
|
||||
}
|
||||
return *sRegistrar;
|
||||
}
|
||||
|
||||
} // namespace llvm
|
43
lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h
Normal file
43
lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h
Normal file
@ -0,0 +1,43 @@
|
||||
//===-- JITRegistrar.h - Registers objects with a debugger ----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H
|
||||
#define LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H
|
||||
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Global access point for the JIT debugging interface.
|
||||
class JITRegistrar {
|
||||
public:
|
||||
/// Instantiates the JIT service.
|
||||
JITRegistrar() {}
|
||||
|
||||
/// Unregisters each object that was previously registered and releases all
|
||||
/// internal resources.
|
||||
virtual ~JITRegistrar() {}
|
||||
|
||||
/// Creates an entry in the JIT registry for the buffer @p Object,
|
||||
/// which must contain an object file in executable memory with any
|
||||
/// debug information for the debugger.
|
||||
virtual void registerObject(const MemoryBuffer &Object) = 0;
|
||||
|
||||
/// Removes the internal registration of @p Object, and
|
||||
/// frees associated resources.
|
||||
/// Returns true if @p Object was previously registered.
|
||||
virtual bool deregisterObject(const MemoryBuffer &Object) = 0;
|
||||
|
||||
/// Returns a reference to a GDB JIT registrar singleton
|
||||
static JITRegistrar& getGDBRegistrar();
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_EXECUTION_ENGINE_JIT_REGISTRAR_H
|
59
lib/ExecutionEngine/RuntimeDyld/ObjectImage.h
Normal file
59
lib/ExecutionEngine/RuntimeDyld/ObjectImage.h
Normal file
@ -0,0 +1,59 @@
|
||||
//===---- ObjectImage.h - Format independent executuable object image -----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares a file format independent ObjectImage class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H
|
||||
#define LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H
|
||||
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ObjectImage {
|
||||
ObjectImage(); // = delete
|
||||
ObjectImage(const ObjectImage &other); // = delete
|
||||
protected:
|
||||
object::ObjectFile *ObjFile;
|
||||
|
||||
public:
|
||||
ObjectImage(object::ObjectFile *Obj) { ObjFile = Obj; }
|
||||
virtual ~ObjectImage() {}
|
||||
|
||||
virtual object::symbol_iterator begin_symbols() const
|
||||
{ return ObjFile->begin_symbols(); }
|
||||
virtual object::symbol_iterator end_symbols() const
|
||||
{ return ObjFile->end_symbols(); }
|
||||
|
||||
virtual object::section_iterator begin_sections() const
|
||||
{ return ObjFile->begin_sections(); }
|
||||
virtual object::section_iterator end_sections() const
|
||||
{ return ObjFile->end_sections(); }
|
||||
|
||||
virtual /* Triple::ArchType */ unsigned getArch() const
|
||||
{ return ObjFile->getArch(); }
|
||||
|
||||
// Subclasses can override these methods to update the image with loaded
|
||||
// addresses for sections and common symbols
|
||||
virtual void updateSectionAddress(const object::SectionRef &Sec,
|
||||
uint64_t Addr) {}
|
||||
virtual void updateSymbolAddress(const object::SymbolRef &Sym, uint64_t Addr)
|
||||
{}
|
||||
|
||||
// Subclasses can override this method to provide JIT debugging support
|
||||
virtual void registerWithDebugger() {}
|
||||
virtual void deregisterWithDebugger() {}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H
|
||||
|
@ -59,11 +59,17 @@ void RuntimeDyldImpl::mapSectionAddress(void *LocalAddress,
|
||||
llvm_unreachable("Attempting to remap address of unknown section!");
|
||||
}
|
||||
|
||||
// Subclasses can implement this method to create specialized image instances
|
||||
// The caller owns the the pointer that is returned.
|
||||
ObjectImage *RuntimeDyldImpl::createObjectImage(const MemoryBuffer *InputBuffer) {
|
||||
ObjectFile *ObjFile = ObjectFile::createObjectFile(const_cast<MemoryBuffer*>
|
||||
(InputBuffer));
|
||||
ObjectImage *Obj = new ObjectImage(ObjFile);
|
||||
return Obj;
|
||||
}
|
||||
|
||||
bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
|
||||
// FIXME: ObjectFile don't modify MemoryBuffer.
|
||||
// It should use const MemoryBuffer as parameter.
|
||||
OwningPtr<ObjectFile> obj(ObjectFile::createObjectFile(
|
||||
const_cast<MemoryBuffer*>(InputBuffer)));
|
||||
OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer));
|
||||
if (!obj)
|
||||
report_fatal_error("Unable to create object image from memory buffer!");
|
||||
|
||||
@ -110,7 +116,8 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
|
||||
(uintptr_t)FileOffset;
|
||||
uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)sData.begin());
|
||||
unsigned SectionID =
|
||||
findOrEmitSection(*si,
|
||||
findOrEmitSection(*obj,
|
||||
*si,
|
||||
SymType == object::SymbolRef::ST_Function,
|
||||
LocalSections);
|
||||
bool isGlobal = flags & SymbolRef::SF_Global;
|
||||
@ -128,7 +135,7 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
|
||||
|
||||
// Allocate common symbols
|
||||
if (CommonSize != 0)
|
||||
emitCommonSymbols(CommonSymbols, CommonSize, LocalSymbols);
|
||||
emitCommonSymbols(*obj, CommonSymbols, CommonSize, LocalSymbols);
|
||||
|
||||
// Parse and proccess relocations
|
||||
DEBUG(dbgs() << "Parse relocations:\n");
|
||||
@ -145,7 +152,7 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
|
||||
|
||||
// If it's first relocation in this section, find its SectionID
|
||||
if (isFirstRelocation) {
|
||||
SectionID = findOrEmitSection(*si, true, LocalSections);
|
||||
SectionID = findOrEmitSection(*obj, *si, true, LocalSections);
|
||||
DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
|
||||
isFirstRelocation = false;
|
||||
}
|
||||
@ -164,10 +171,14 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
|
||||
processRelocationRef(RI, *obj, LocalSections, LocalSymbols, Stubs);
|
||||
}
|
||||
}
|
||||
|
||||
handleObjectLoaded(obj.take());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned RuntimeDyldImpl::emitCommonSymbols(const CommonSymbolMap &Map,
|
||||
unsigned RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
|
||||
const CommonSymbolMap &Map,
|
||||
uint64_t TotalSize,
|
||||
LocalSymbolMap &LocalSymbols) {
|
||||
// Allocate memory for the section
|
||||
@ -191,6 +202,7 @@ unsigned RuntimeDyldImpl::emitCommonSymbols(const CommonSymbolMap &Map,
|
||||
uint64_t Size = it->second;
|
||||
StringRef Name;
|
||||
it->first.getName(Name);
|
||||
Obj.updateSymbolAddress(it->first, (uint64_t)Addr);
|
||||
LocalSymbols[Name.data()] = SymbolLoc(SectionID, Offset);
|
||||
Offset += Size;
|
||||
Addr += Size;
|
||||
@ -199,7 +211,8 @@ unsigned RuntimeDyldImpl::emitCommonSymbols(const CommonSymbolMap &Map,
|
||||
return SectionID;
|
||||
}
|
||||
|
||||
unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section,
|
||||
unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
||||
const SectionRef &Section,
|
||||
bool IsCode) {
|
||||
|
||||
unsigned StubBufSize = 0,
|
||||
@ -257,6 +270,7 @@ unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section,
|
||||
<< " StubBufSize: " << StubBufSize
|
||||
<< " Allocate: " << Allocate
|
||||
<< "\n");
|
||||
Obj.updateSectionAddress(Section, (uint64_t)Addr);
|
||||
}
|
||||
else {
|
||||
// Even if we didn't load the section, we need to record an entry for it
|
||||
@ -277,7 +291,8 @@ unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section,
|
||||
return SectionID;
|
||||
}
|
||||
|
||||
unsigned RuntimeDyldImpl::findOrEmitSection(const SectionRef &Section,
|
||||
unsigned RuntimeDyldImpl::findOrEmitSection(ObjectImage &Obj,
|
||||
const SectionRef &Section,
|
||||
bool IsCode,
|
||||
ObjSectionToIDMap &LocalSections) {
|
||||
|
||||
@ -286,7 +301,7 @@ unsigned RuntimeDyldImpl::findOrEmitSection(const SectionRef &Section,
|
||||
if (i != LocalSections.end())
|
||||
SectionID = i->second;
|
||||
else {
|
||||
SectionID = emitSection(Section, IsCode);
|
||||
SectionID = emitSection(Obj, Section, IsCode);
|
||||
LocalSections[Section] = SectionID;
|
||||
}
|
||||
return SectionID;
|
||||
|
@ -20,11 +20,176 @@
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "JITRegistrar.h"
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
namespace {
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> {
|
||||
LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
|
||||
|
||||
typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
|
||||
typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
|
||||
typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel;
|
||||
typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela;
|
||||
|
||||
typedef typename ELFObjectFile<target_endianness, is64Bits>::
|
||||
Elf_Ehdr Elf_Ehdr;
|
||||
|
||||
typedef typename ELFDataTypeTypedefHelper<
|
||||
target_endianness, is64Bits>::value_type addr_type;
|
||||
|
||||
protected:
|
||||
// This duplicates the 'Data' member in the 'Binary' base class
|
||||
// but it is necessary to workaround a bug in gcc 4.2
|
||||
MemoryBuffer *InputData;
|
||||
|
||||
public:
|
||||
DyldELFObject(MemoryBuffer *Object, error_code &ec);
|
||||
|
||||
void updateSectionAddress(const SectionRef &Sec, uint64_t Addr);
|
||||
void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr);
|
||||
|
||||
const MemoryBuffer& getBuffer() const { return *InputData; }
|
||||
|
||||
// Methods for type inquiry through isa, cast, and dyn_cast
|
||||
static inline bool classof(const Binary *v) {
|
||||
return (isa<ELFObjectFile<target_endianness, is64Bits> >(v)
|
||||
&& classof(cast<ELFObjectFile<target_endianness, is64Bits> >(v)));
|
||||
}
|
||||
static inline bool classof(
|
||||
const ELFObjectFile<target_endianness, is64Bits> *v) {
|
||||
return v->isDyldType();
|
||||
}
|
||||
static inline bool classof(const DyldELFObject *v) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
class ELFObjectImage : public ObjectImage {
|
||||
protected:
|
||||
DyldELFObject<target_endianness, is64Bits> *DyldObj;
|
||||
bool Registered;
|
||||
|
||||
public:
|
||||
ELFObjectImage(DyldELFObject<target_endianness, is64Bits> *Obj)
|
||||
: ObjectImage(Obj),
|
||||
DyldObj(Obj),
|
||||
Registered(false) {}
|
||||
|
||||
virtual ~ELFObjectImage() {
|
||||
if (Registered)
|
||||
deregisterWithDebugger();
|
||||
}
|
||||
|
||||
// Subclasses can override these methods to update the image with loaded
|
||||
// addresses for sections and common symbols
|
||||
virtual void updateSectionAddress(const SectionRef &Sec, uint64_t Addr)
|
||||
{
|
||||
DyldObj->updateSectionAddress(Sec, Addr);
|
||||
}
|
||||
|
||||
virtual void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr)
|
||||
{
|
||||
DyldObj->updateSymbolAddress(Sym, Addr);
|
||||
}
|
||||
|
||||
virtual void registerWithDebugger()
|
||||
{
|
||||
JITRegistrar::getGDBRegistrar().registerObject(DyldObj->getBuffer());
|
||||
Registered = true;
|
||||
}
|
||||
virtual void deregisterWithDebugger()
|
||||
{
|
||||
JITRegistrar::getGDBRegistrar().deregisterObject(DyldObj->getBuffer());
|
||||
}
|
||||
};
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
DyldELFObject<target_endianness, is64Bits>::DyldELFObject(MemoryBuffer *Object,
|
||||
error_code &ec)
|
||||
: ELFObjectFile<target_endianness, is64Bits>(Object, ec),
|
||||
InputData(Object) {
|
||||
this->isDyldELFObject = true;
|
||||
}
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
void DyldELFObject<target_endianness, is64Bits>::updateSectionAddress(
|
||||
const SectionRef &Sec,
|
||||
uint64_t Addr) {
|
||||
DataRefImpl ShdrRef = Sec.getRawDataRefImpl();
|
||||
Elf_Shdr *shdr = const_cast<Elf_Shdr*>(
|
||||
reinterpret_cast<const Elf_Shdr *>(ShdrRef.p));
|
||||
|
||||
// This assumes the address passed in matches the target address bitness
|
||||
// The template-based type cast handles everything else.
|
||||
shdr->sh_addr = static_cast<addr_type>(Addr);
|
||||
}
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
void DyldELFObject<target_endianness, is64Bits>::updateSymbolAddress(
|
||||
const SymbolRef &SymRef,
|
||||
uint64_t Addr) {
|
||||
|
||||
Elf_Sym *sym = const_cast<Elf_Sym*>(
|
||||
ELFObjectFile<target_endianness, is64Bits>::
|
||||
getSymbol(SymRef.getRawDataRefImpl()));
|
||||
|
||||
// This assumes the address passed in matches the target address bitness
|
||||
// The template-based type cast handles everything else.
|
||||
sym->st_value = static_cast<addr_type>(Addr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace llvm {
|
||||
|
||||
ObjectImage *RuntimeDyldELF::createObjectImage(
|
||||
const MemoryBuffer *ConstInputBuffer) {
|
||||
MemoryBuffer *InputBuffer = const_cast<MemoryBuffer*>(ConstInputBuffer);
|
||||
std::pair<unsigned char, unsigned char> Ident = getElfArchType(InputBuffer);
|
||||
error_code ec;
|
||||
|
||||
if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) {
|
||||
DyldELFObject<support::little, false> *Obj =
|
||||
new DyldELFObject<support::little, false>(InputBuffer, ec);
|
||||
return new ELFObjectImage<support::little, false>(Obj);
|
||||
}
|
||||
else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) {
|
||||
DyldELFObject<support::big, false> *Obj =
|
||||
new DyldELFObject<support::big, false>(InputBuffer, ec);
|
||||
return new ELFObjectImage<support::big, false>(Obj);
|
||||
}
|
||||
else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) {
|
||||
DyldELFObject<support::big, true> *Obj =
|
||||
new DyldELFObject<support::big, true>(InputBuffer, ec);
|
||||
return new ELFObjectImage<support::big, true>(Obj);
|
||||
}
|
||||
else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
|
||||
DyldELFObject<support::little, true> *Obj =
|
||||
new DyldELFObject<support::little, true>(InputBuffer, ec);
|
||||
return new ELFObjectImage<support::little, true>(Obj);
|
||||
}
|
||||
else
|
||||
llvm_unreachable("Unexpected ELF format");
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::handleObjectLoaded(ObjectImage *Obj)
|
||||
{
|
||||
Obj->registerWithDebugger();
|
||||
// Save the loaded object. It will deregister itself when deleted
|
||||
LoadedObject = Obj;
|
||||
}
|
||||
|
||||
RuntimeDyldELF::~RuntimeDyldELF() {
|
||||
if (LoadedObject)
|
||||
delete LoadedObject;
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
@ -167,7 +332,7 @@ void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress,
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
const ObjectFile &Obj,
|
||||
ObjectImage &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
LocalSymbolMap &Symbols,
|
||||
StubMap &Stubs) {
|
||||
@ -206,7 +371,7 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
if (si == Obj.end_sections())
|
||||
llvm_unreachable("Symbol section not found, bad object file format!");
|
||||
DEBUG(dbgs() << "\t\tThis is section symbol\n");
|
||||
Value.SectionID = findOrEmitSection((*si), true, ObjSectionToID);
|
||||
Value.SectionID = findOrEmitSection(Obj, (*si), true, ObjSectionToID);
|
||||
Value.Addend = Addend;
|
||||
break;
|
||||
}
|
||||
@ -236,7 +401,7 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
// Look up for existing stub.
|
||||
StubMap::const_iterator i = Stubs.find(Value);
|
||||
if (i != Stubs.end()) {
|
||||
resolveRelocation(Target, Section.LoadAddress, (uint64_t)Section.Address +
|
||||
resolveRelocation(Target, (uint64_t)Target, (uint64_t)Section.Address +
|
||||
i->second, RelType, 0);
|
||||
DEBUG(dbgs() << " Stub function found\n");
|
||||
} else {
|
||||
@ -247,7 +412,7 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
Section.StubOffset);
|
||||
AddRelocation(Value, Rel.SectionID,
|
||||
StubTargetAddr - Section.Address, ELF::R_ARM_ABS32);
|
||||
resolveRelocation(Target, Section.LoadAddress, (uint64_t)Section.Address +
|
||||
resolveRelocation(Target, (uint64_t)Target, (uint64_t)Section.Address +
|
||||
Section.StubOffset, RelType, 0);
|
||||
Section.StubOffset += getMaxStubSize();
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ using namespace llvm;
|
||||
namespace llvm {
|
||||
class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||
protected:
|
||||
ObjectImage *LoadedObject;
|
||||
|
||||
void resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
uint64_t Value,
|
||||
@ -47,12 +49,18 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||
int64_t Addend);
|
||||
|
||||
virtual void processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
const ObjectFile &Obj,
|
||||
ObjectImage &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
LocalSymbolMap &Symbols, StubMap &Stubs);
|
||||
|
||||
virtual ObjectImage *createObjectImage(const MemoryBuffer *InputBuffer);
|
||||
virtual void handleObjectLoaded(ObjectImage *Obj);
|
||||
|
||||
public:
|
||||
RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
|
||||
RuntimeDyldELF(RTDyldMemoryManager *mm)
|
||||
: RuntimeDyldImpl(mm), LoadedObject(0) {}
|
||||
|
||||
virtual ~RuntimeDyldELF();
|
||||
|
||||
bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const;
|
||||
};
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include <map>
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "ObjectImage.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
@ -154,7 +155,8 @@ class RuntimeDyldImpl {
|
||||
|
||||
/// \brief Emits a section containing common symbols.
|
||||
/// \return SectionID.
|
||||
unsigned emitCommonSymbols(const CommonSymbolMap &Map,
|
||||
unsigned emitCommonSymbols(ObjectImage &Obj,
|
||||
const CommonSymbolMap &Map,
|
||||
uint64_t TotalSize,
|
||||
LocalSymbolMap &Symbols);
|
||||
|
||||
@ -162,14 +164,18 @@ class RuntimeDyldImpl {
|
||||
/// \param IsCode if it's true then allocateCodeSection() will be
|
||||
/// used for emmits, else allocateDataSection() will be used.
|
||||
/// \return SectionID.
|
||||
unsigned emitSection(const SectionRef &Section, bool IsCode);
|
||||
unsigned emitSection(ObjectImage &Obj,
|
||||
const SectionRef &Section,
|
||||
bool IsCode);
|
||||
|
||||
/// \brief Find Section in LocalSections. If the secton is not found - emit
|
||||
/// it and store in LocalSections.
|
||||
/// \param IsCode if it's true then allocateCodeSection() will be
|
||||
/// used for emmits, else allocateDataSection() will be used.
|
||||
/// \return SectionID.
|
||||
unsigned findOrEmitSection(const SectionRef &Section, bool IsCode,
|
||||
unsigned findOrEmitSection(ObjectImage &Obj,
|
||||
const SectionRef &Section,
|
||||
bool IsCode,
|
||||
ObjSectionToIDMap &LocalSections);
|
||||
|
||||
/// \brief If Value.SymbolName is NULL then store relocation to the
|
||||
@ -200,11 +206,18 @@ class RuntimeDyldImpl {
|
||||
/// \brief Parses the object file relocation and store it to Relocations
|
||||
/// or SymbolRelocations. Its depend from object file type.
|
||||
virtual void processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
const ObjectFile &Obj,
|
||||
ObjectImage &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
LocalSymbolMap &Symbols, StubMap &Stubs) = 0;
|
||||
|
||||
void resolveSymbols();
|
||||
virtual ObjectImage *createObjectImage(const MemoryBuffer *InputBuffer);
|
||||
virtual void handleObjectLoaded(ObjectImage *Obj)
|
||||
{
|
||||
// Subclasses may choose to retain this image if they have a use for it
|
||||
delete Obj;
|
||||
}
|
||||
|
||||
public:
|
||||
RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
|
||||
|
||||
|
@ -205,7 +205,7 @@ resolveARMRelocation(uint8_t *LocalAddress,
|
||||
}
|
||||
|
||||
void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
const ObjectFile &Obj,
|
||||
ObjectImage &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
LocalSymbolMap &Symbols,
|
||||
StubMap &Stubs) {
|
||||
@ -246,7 +246,7 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
break;
|
||||
}
|
||||
assert(si != se && "No section containing relocation!");
|
||||
Value.SectionID = findOrEmitSection(*si, true, ObjSectionToID);
|
||||
Value.SectionID = findOrEmitSection(Obj, *si, true, ObjSectionToID);
|
||||
Value.Addend = *(const intptr_t *)Target;
|
||||
if (Value.Addend) {
|
||||
// The MachO addend is offset from the current section, we need set it
|
||||
|
@ -49,7 +49,7 @@ class RuntimeDyldMachO : public RuntimeDyldImpl {
|
||||
int64_t Addend);
|
||||
|
||||
virtual void processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
const ObjectFile &Obj,
|
||||
ObjectImage &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
LocalSymbolMap &Symbols, StubMap &Stubs);
|
||||
|
||||
@ -59,7 +59,7 @@ class RuntimeDyldMachO : public RuntimeDyldImpl {
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend);
|
||||
|
||||
|
||||
RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
|
||||
|
||||
bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const;
|
||||
|
@ -1527,11 +1527,11 @@ bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc,
|
||||
}
|
||||
Lex();
|
||||
}
|
||||
// If there weren't any arguments, erase the token vector so everything
|
||||
// else knows that. Leaving around the vestigal empty token list confuses
|
||||
// things.
|
||||
if (MacroArguments.size() == 1 && MacroArguments.back().empty())
|
||||
MacroArguments.clear();
|
||||
// If the last argument didn't end up with any tokens, it's not a real
|
||||
// argument and we should remove it from the list. This happens with either
|
||||
// a tailing comma or an empty argument list.
|
||||
if (MacroArguments.back().empty())
|
||||
MacroArguments.pop_back();
|
||||
|
||||
// Macro instantiation is lexical, unfortunately. We construct a new buffer
|
||||
// to hold the macro body with substitutions.
|
||||
|
@ -17,16 +17,6 @@ namespace llvm {
|
||||
|
||||
using namespace object;
|
||||
|
||||
namespace {
|
||||
std::pair<unsigned char, unsigned char>
|
||||
getElfArchType(MemoryBuffer *Object) {
|
||||
if (Object->getBufferSize() < ELF::EI_NIDENT)
|
||||
return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE);
|
||||
return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS]
|
||||
, (uint8_t)Object->getBufferStart()[ELF::EI_DATA]);
|
||||
}
|
||||
}
|
||||
|
||||
// Creates an in-memory object-file by default: createELFObjectFile(Buffer)
|
||||
ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) {
|
||||
std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object);
|
||||
|
@ -32,7 +32,7 @@ add_llvm_library(LLVMSupport
|
||||
IntrusiveRefCntPtr.cpp
|
||||
IsInf.cpp
|
||||
IsNAN.cpp
|
||||
JSONParser.cpp
|
||||
Locale.cpp
|
||||
LockFileManager.cpp
|
||||
ManagedStatic.cpp
|
||||
MemoryBuffer.cpp
|
||||
|
@ -1,302 +0,0 @@
|
||||
//===--- JSONParser.cpp - Simple JSON parser ------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a JSON parser.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/JSONParser.h"
|
||||
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
JSONParser::JSONParser(StringRef Input, SourceMgr *SM)
|
||||
: SM(SM), Failed(false) {
|
||||
InputBuffer = MemoryBuffer::getMemBuffer(Input, "JSON");
|
||||
SM->AddNewSourceBuffer(InputBuffer, SMLoc());
|
||||
End = InputBuffer->getBuffer().end();
|
||||
Position = InputBuffer->getBuffer().begin();
|
||||
}
|
||||
|
||||
JSONValue *JSONParser::parseRoot() {
|
||||
if (Position != InputBuffer->getBuffer().begin())
|
||||
report_fatal_error("Cannot reuse JSONParser.");
|
||||
if (isWhitespace())
|
||||
nextNonWhitespace();
|
||||
if (errorIfAtEndOfFile("'[' or '{' at start of JSON text"))
|
||||
return 0;
|
||||
switch (*Position) {
|
||||
case '[':
|
||||
return new (ValueAllocator.Allocate<JSONArray>(1)) JSONArray(this);
|
||||
case '{':
|
||||
return new (ValueAllocator.Allocate<JSONObject>(1)) JSONObject(this);
|
||||
default:
|
||||
setExpectedError("'[' or '{' at start of JSON text", *Position);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool JSONParser::validate() {
|
||||
JSONValue *Root = parseRoot();
|
||||
if (Root == NULL) {
|
||||
return false;
|
||||
}
|
||||
return skip(*Root);
|
||||
}
|
||||
|
||||
bool JSONParser::skip(const JSONAtom &Atom) {
|
||||
switch(Atom.getKind()) {
|
||||
case JSONAtom::JK_Array:
|
||||
case JSONAtom::JK_Object:
|
||||
return skipContainer(*cast<JSONContainer>(&Atom));
|
||||
case JSONAtom::JK_String:
|
||||
return true;
|
||||
case JSONAtom::JK_KeyValuePair:
|
||||
return skip(*cast<JSONKeyValuePair>(&Atom)->Value);
|
||||
}
|
||||
llvm_unreachable("Impossible enum value.");
|
||||
}
|
||||
|
||||
// Sets the current error to:
|
||||
// "expected <Expected>, but found <Found>".
|
||||
void JSONParser::setExpectedError(StringRef Expected, StringRef Found) {
|
||||
SM->PrintMessage(SMLoc::getFromPointer(Position), SourceMgr::DK_Error,
|
||||
"expected " + Expected + ", but found " + Found + ".", ArrayRef<SMRange>());
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
// Sets the current error to:
|
||||
// "expected <Expected>, but found <Found>".
|
||||
void JSONParser::setExpectedError(StringRef Expected, char Found) {
|
||||
setExpectedError(Expected, ("'" + StringRef(&Found, 1) + "'").str());
|
||||
}
|
||||
|
||||
// If there is no character available, returns true and sets the current error
|
||||
// to: "expected <Expected>, but found EOF.".
|
||||
bool JSONParser::errorIfAtEndOfFile(StringRef Expected) {
|
||||
if (Position == End) {
|
||||
setExpectedError(Expected, "EOF");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sets the current error if the current character is not C to:
|
||||
// "expected 'C', but got <current character>".
|
||||
bool JSONParser::errorIfNotAt(char C, StringRef Message) {
|
||||
if (*Position != C) {
|
||||
std::string Expected =
|
||||
("'" + StringRef(&C, 1) + "' " + Message).str();
|
||||
if (Position == End)
|
||||
setExpectedError(Expected, "EOF");
|
||||
else
|
||||
setExpectedError(Expected, *Position);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Forbidding inlining improves performance by roughly 20%.
|
||||
// FIXME: Remove once llvm optimizes this to the faster version without hints.
|
||||
LLVM_ATTRIBUTE_NOINLINE static bool
|
||||
wasEscaped(StringRef::iterator First, StringRef::iterator Position);
|
||||
|
||||
// Returns whether a character at 'Position' was escaped with a leading '\'.
|
||||
// 'First' specifies the position of the first character in the string.
|
||||
static bool wasEscaped(StringRef::iterator First,
|
||||
StringRef::iterator Position) {
|
||||
assert(Position - 1 >= First);
|
||||
StringRef::iterator I = Position - 1;
|
||||
// We calulate the number of consecutive '\'s before the current position
|
||||
// by iterating backwards through our string.
|
||||
while (I >= First && *I == '\\') --I;
|
||||
// (Position - 1 - I) now contains the number of '\'s before the current
|
||||
// position. If it is odd, the character at 'Positon' was escaped.
|
||||
return (Position - 1 - I) % 2 == 1;
|
||||
}
|
||||
|
||||
// Parses a JSONString, assuming that the current position is on a quote.
|
||||
JSONString *JSONParser::parseString() {
|
||||
assert(Position != End);
|
||||
assert(!isWhitespace());
|
||||
if (errorIfNotAt('"', "at start of string"))
|
||||
return 0;
|
||||
StringRef::iterator First = Position + 1;
|
||||
|
||||
// Benchmarking shows that this loop is the hot path of the application with
|
||||
// about 2/3rd of the runtime cycles. Since escaped quotes are not the common
|
||||
// case, and multiple escaped backslashes before escaped quotes are very rare,
|
||||
// we pessimize this case to achieve a smaller inner loop in the common case.
|
||||
// We're doing that by having a quick inner loop that just scans for the next
|
||||
// quote. Once we find the quote we check the last character to see whether
|
||||
// the quote might have been escaped. If the last character is not a '\', we
|
||||
// know the quote was not escaped and have thus found the end of the string.
|
||||
// If the immediately preceding character was a '\', we have to scan backwards
|
||||
// to see whether the previous character was actually an escaped backslash, or
|
||||
// an escape character for the quote. If we find that the current quote was
|
||||
// escaped, we continue parsing for the next quote and repeat.
|
||||
// This optimization brings around 30% performance improvements.
|
||||
do {
|
||||
// Step over the current quote.
|
||||
++Position;
|
||||
// Find the next quote.
|
||||
while (Position != End && *Position != '"')
|
||||
++Position;
|
||||
if (errorIfAtEndOfFile("'\"' at end of string"))
|
||||
return 0;
|
||||
// Repeat until the previous character was not a '\' or was an escaped
|
||||
// backslash.
|
||||
} while (*(Position - 1) == '\\' && wasEscaped(First, Position));
|
||||
|
||||
return new (ValueAllocator.Allocate<JSONString>())
|
||||
JSONString(StringRef(First, Position - First));
|
||||
}
|
||||
|
||||
|
||||
// Advances the position to the next non-whitespace position.
|
||||
void JSONParser::nextNonWhitespace() {
|
||||
do {
|
||||
++Position;
|
||||
} while (isWhitespace());
|
||||
}
|
||||
|
||||
// Checks if there is a whitespace character at the current position.
|
||||
bool JSONParser::isWhitespace() {
|
||||
return *Position == ' ' || *Position == '\t' ||
|
||||
*Position == '\n' || *Position == '\r';
|
||||
}
|
||||
|
||||
bool JSONParser::failed() const {
|
||||
return Failed;
|
||||
}
|
||||
|
||||
// Parses a JSONValue, assuming that the current position is at the first
|
||||
// character of the value.
|
||||
JSONValue *JSONParser::parseValue() {
|
||||
assert(Position != End);
|
||||
assert(!isWhitespace());
|
||||
switch (*Position) {
|
||||
case '[':
|
||||
return new (ValueAllocator.Allocate<JSONArray>(1)) JSONArray(this);
|
||||
case '{':
|
||||
return new (ValueAllocator.Allocate<JSONObject>(1)) JSONObject(this);
|
||||
case '"':
|
||||
return parseString();
|
||||
default:
|
||||
setExpectedError("'[', '{' or '\"' at start of value", *Position);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Parses a JSONKeyValuePair, assuming that the current position is at the first
|
||||
// character of the key, value pair.
|
||||
JSONKeyValuePair *JSONParser::parseKeyValuePair() {
|
||||
assert(Position != End);
|
||||
assert(!isWhitespace());
|
||||
|
||||
JSONString *Key = parseString();
|
||||
if (Key == 0)
|
||||
return 0;
|
||||
|
||||
nextNonWhitespace();
|
||||
if (errorIfNotAt(':', "between key and value"))
|
||||
return 0;
|
||||
|
||||
nextNonWhitespace();
|
||||
const JSONValue *Value = parseValue();
|
||||
if (Value == 0)
|
||||
return 0;
|
||||
|
||||
return new (ValueAllocator.Allocate<JSONKeyValuePair>(1))
|
||||
JSONKeyValuePair(Key, Value);
|
||||
}
|
||||
|
||||
/// \brief Parses the first element of a JSON array or object, or closes the
|
||||
/// array.
|
||||
///
|
||||
/// The method assumes that the current position is before the first character
|
||||
/// of the element, with possible white space in between. When successful, it
|
||||
/// returns the new position after parsing the element. Otherwise, if there is
|
||||
/// no next value, it returns a default constructed StringRef::iterator.
|
||||
StringRef::iterator JSONParser::parseFirstElement(JSONAtom::Kind ContainerKind,
|
||||
char StartChar, char EndChar,
|
||||
const JSONAtom *&Element) {
|
||||
assert(*Position == StartChar);
|
||||
Element = 0;
|
||||
nextNonWhitespace();
|
||||
if (errorIfAtEndOfFile("value or end of container at start of container"))
|
||||
return StringRef::iterator();
|
||||
|
||||
if (*Position == EndChar)
|
||||
return StringRef::iterator();
|
||||
|
||||
Element = parseElement(ContainerKind);
|
||||
if (Element == 0)
|
||||
return StringRef::iterator();
|
||||
|
||||
return Position;
|
||||
}
|
||||
|
||||
/// \brief Parses the next element of a JSON array or object, or closes the
|
||||
/// array.
|
||||
///
|
||||
/// The method assumes that the current position is before the ',' which
|
||||
/// separates the next element from the current element. When successful, it
|
||||
/// returns the new position after parsing the element. Otherwise, if there is
|
||||
/// no next value, it returns a default constructed StringRef::iterator.
|
||||
StringRef::iterator JSONParser::parseNextElement(JSONAtom::Kind ContainerKind,
|
||||
char EndChar,
|
||||
const JSONAtom *&Element) {
|
||||
Element = 0;
|
||||
nextNonWhitespace();
|
||||
if (errorIfAtEndOfFile("',' or end of container for next element"))
|
||||
return 0;
|
||||
|
||||
if (*Position == ',') {
|
||||
nextNonWhitespace();
|
||||
if (errorIfAtEndOfFile("element in container"))
|
||||
return StringRef::iterator();
|
||||
|
||||
Element = parseElement(ContainerKind);
|
||||
if (Element == 0)
|
||||
return StringRef::iterator();
|
||||
|
||||
return Position;
|
||||
} else if (*Position == EndChar) {
|
||||
return StringRef::iterator();
|
||||
} else {
|
||||
setExpectedError("',' or end of container for next element", *Position);
|
||||
return StringRef::iterator();
|
||||
}
|
||||
}
|
||||
|
||||
const JSONAtom *JSONParser::parseElement(JSONAtom::Kind ContainerKind) {
|
||||
switch (ContainerKind) {
|
||||
case JSONAtom::JK_Array:
|
||||
return parseValue();
|
||||
case JSONAtom::JK_Object:
|
||||
return parseKeyValuePair();
|
||||
default:
|
||||
llvm_unreachable("Impossible code path");
|
||||
}
|
||||
}
|
||||
|
||||
bool JSONParser::skipContainer(const JSONContainer &Container) {
|
||||
for (JSONContainer::AtomIterator I = Container.atom_current(),
|
||||
E = Container.atom_end();
|
||||
I != E; ++I) {
|
||||
assert(*I != 0);
|
||||
if (!skip(**I))
|
||||
return false;
|
||||
}
|
||||
return !failed();
|
||||
}
|
10
lib/Support/Locale.cpp
Normal file
10
lib/Support/Locale.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "llvm/Support/Locale.h"
|
||||
#include "llvm/Config/config.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "LocaleXlocale.inc"
|
||||
#elif LLVM_ON_WIN32
|
||||
#include "LocaleWindows.inc"
|
||||
#else
|
||||
#include "LocaleGeneric.inc"
|
||||
#endif
|
17
lib/Support/LocaleGeneric.inc
Normal file
17
lib/Support/LocaleGeneric.inc
Normal file
@ -0,0 +1,17 @@
|
||||
#include <cwctype>
|
||||
|
||||
namespace llvm {
|
||||
namespace sys {
|
||||
namespace locale {
|
||||
|
||||
int columnWidth(StringRef s) {
|
||||
return s.size();
|
||||
}
|
||||
|
||||
bool isPrint(int c) {
|
||||
return iswprint(c);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
15
lib/Support/LocaleWindows.inc
Normal file
15
lib/Support/LocaleWindows.inc
Normal file
@ -0,0 +1,15 @@
|
||||
namespace llvm {
|
||||
namespace sys {
|
||||
namespace locale {
|
||||
|
||||
int columnWidth(StringRef s) {
|
||||
return s.size();
|
||||
}
|
||||
|
||||
bool isPrint(int c) {
|
||||
return ' ' <= c && c <= '~';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
61
lib/Support/LocaleXlocale.inc
Normal file
61
lib/Support/LocaleXlocale.inc
Normal file
@ -0,0 +1,61 @@
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include <cassert>
|
||||
#include <xlocale.h>
|
||||
|
||||
|
||||
namespace {
|
||||
struct locale_holder {
|
||||
locale_holder()
|
||||
: l(newlocale(LC_CTYPE_MASK,"en_US.UTF-8",LC_GLOBAL_LOCALE))
|
||||
{
|
||||
assert(NULL!=l);
|
||||
}
|
||||
~locale_holder() {
|
||||
freelocale(l);
|
||||
}
|
||||
|
||||
int mbswidth(llvm::SmallString<16> s) const {
|
||||
// this implementation assumes no '\0' in s
|
||||
assert(s.size()==strlen(s.c_str()));
|
||||
|
||||
size_t size = mbstowcs_l(NULL,s.c_str(),0,l);
|
||||
assert(size!=(size_t)-1);
|
||||
if (size==0)
|
||||
return 0;
|
||||
llvm::SmallVector<wchar_t,200> ws(size);
|
||||
size = mbstowcs_l(&ws[0],s.c_str(),ws.size(),l);
|
||||
assert(ws.size()==size);
|
||||
return wcswidth_l(&ws[0],ws.size(),l);
|
||||
}
|
||||
|
||||
int isprint(int c) const {
|
||||
return iswprint_l(c,l);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
locale_t l;
|
||||
};
|
||||
|
||||
llvm::ManagedStatic<locale_holder> l;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
namespace sys {
|
||||
namespace locale {
|
||||
|
||||
int columnWidth(StringRef s) {
|
||||
int width = l->mbswidth(s);
|
||||
assert(width>=0);
|
||||
return width;
|
||||
}
|
||||
|
||||
bool isPrint(int c) {
|
||||
return l->isprint(c);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
@ -102,7 +103,7 @@ bool SmallPtrSetImpl::erase_imp(const void * Ptr) {
|
||||
}
|
||||
|
||||
const void * const *SmallPtrSetImpl::FindBucketFor(const void *Ptr) const {
|
||||
unsigned Bucket = Hash(Ptr);
|
||||
unsigned Bucket = DenseMapInfo<void *>::getHashValue(Ptr) & (CurArraySize-1);
|
||||
unsigned ArraySize = CurArraySize;
|
||||
unsigned ProbeAmt = 1;
|
||||
const void *const *Array = CurArray;
|
||||
|
@ -193,7 +193,8 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
|
||||
}
|
||||
|
||||
void SourceMgr::PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
|
||||
const Twine &Msg, ArrayRef<SMRange> Ranges) const {
|
||||
const Twine &Msg, ArrayRef<SMRange> Ranges,
|
||||
bool ShowColors) const {
|
||||
SMDiagnostic Diagnostic = GetMessage(Loc, Kind, Msg, Ranges);
|
||||
|
||||
// Report the message with the diagnostic handler if present.
|
||||
@ -208,7 +209,7 @@ void SourceMgr::PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
|
||||
assert(CurBuf != -1 && "Invalid or unspecified location!");
|
||||
PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS);
|
||||
|
||||
Diagnostic.print(0, OS);
|
||||
Diagnostic.print(0, OS, ShowColors);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -225,7 +226,14 @@ SMDiagnostic::SMDiagnostic(const SourceMgr &sm, SMLoc L, const std::string &FN,
|
||||
}
|
||||
|
||||
|
||||
void SMDiagnostic::print(const char *ProgName, raw_ostream &S) const {
|
||||
void SMDiagnostic::print(const char *ProgName, raw_ostream &S,
|
||||
bool ShowColors) const {
|
||||
// Display colors only if OS goes to a tty.
|
||||
ShowColors &= S.is_displayed();
|
||||
|
||||
if (ShowColors)
|
||||
S.changeColor(raw_ostream::SAVEDCOLOR, true);
|
||||
|
||||
if (ProgName && ProgName[0])
|
||||
S << ProgName << ": ";
|
||||
|
||||
@ -244,13 +252,33 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S) const {
|
||||
}
|
||||
|
||||
switch (Kind) {
|
||||
case SourceMgr::DK_Error: S << "error: "; break;
|
||||
case SourceMgr::DK_Warning: S << "warning: "; break;
|
||||
case SourceMgr::DK_Note: S << "note: "; break;
|
||||
case SourceMgr::DK_Error:
|
||||
if (ShowColors)
|
||||
S.changeColor(raw_ostream::RED, true);
|
||||
S << "error: ";
|
||||
break;
|
||||
case SourceMgr::DK_Warning:
|
||||
if (ShowColors)
|
||||
S.changeColor(raw_ostream::MAGENTA, true);
|
||||
S << "warning: ";
|
||||
break;
|
||||
case SourceMgr::DK_Note:
|
||||
if (ShowColors)
|
||||
S.changeColor(raw_ostream::BLACK, true);
|
||||
S << "note: ";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (ShowColors) {
|
||||
S.resetColor();
|
||||
S.changeColor(raw_ostream::SAVEDCOLOR, true);
|
||||
}
|
||||
|
||||
S << Message << '\n';
|
||||
|
||||
if (ShowColors)
|
||||
S.resetColor();
|
||||
|
||||
if (LineNo == -1 || ColumnNo == -1)
|
||||
return;
|
||||
|
||||
@ -292,6 +320,9 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S) const {
|
||||
}
|
||||
S << '\n';
|
||||
|
||||
if (ShowColors)
|
||||
S.changeColor(raw_ostream::GREEN, true);
|
||||
|
||||
// Print out the caret line, matching tabs in the source line.
|
||||
for (unsigned i = 0, e = CaretLine.size(), OutCol = 0; i != e; ++i) {
|
||||
if (i >= LineContents.size() || LineContents[i] != '\t') {
|
||||
@ -306,6 +337,9 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S) const {
|
||||
++OutCol;
|
||||
} while (OutCol & 7);
|
||||
}
|
||||
|
||||
if (ShowColors)
|
||||
S.resetColor();
|
||||
|
||||
S << '\n';
|
||||
}
|
||||
|
@ -290,6 +290,10 @@ const char *Process::OutputBold(bool bg) {
|
||||
return "\033[1m";
|
||||
}
|
||||
|
||||
const char *Process::OutputReverse() {
|
||||
return "\033[7m";
|
||||
}
|
||||
|
||||
const char *Process::ResetColor() {
|
||||
return "\033[0m";
|
||||
}
|
||||
|
@ -215,6 +215,38 @@ const char *Process::OutputColor(char code, bool bold, bool bg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
|
||||
return info.wAttributes;
|
||||
}
|
||||
|
||||
const char *Process::OutputReverse() {
|
||||
const WORD attributes
|
||||
= GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE));
|
||||
|
||||
const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
|
||||
FOREGROUND_RED | FOREGROUND_INTENSITY;
|
||||
const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
|
||||
BACKGROUND_RED | BACKGROUND_INTENSITY;
|
||||
const WORD color_mask = foreground_mask | background_mask;
|
||||
|
||||
WORD new_attributes =
|
||||
((attributes & FOREGROUND_BLUE )?BACKGROUND_BLUE :0) |
|
||||
((attributes & FOREGROUND_GREEN )?BACKGROUND_GREEN :0) |
|
||||
((attributes & FOREGROUND_RED )?BACKGROUND_RED :0) |
|
||||
((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) |
|
||||
((attributes & BACKGROUND_BLUE )?FOREGROUND_BLUE :0) |
|
||||
((attributes & BACKGROUND_GREEN )?FOREGROUND_GREEN :0) |
|
||||
((attributes & BACKGROUND_RED )?FOREGROUND_RED :0) |
|
||||
((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) |
|
||||
0;
|
||||
new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask);
|
||||
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *Process::ResetColor() {
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
|
||||
return 0;
|
||||
|
@ -1732,7 +1732,7 @@ StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
|
||||
if (UnquotedValue.size() < 3)
|
||||
// TODO: Report error.
|
||||
break;
|
||||
unsigned int UnicodeScalarValue;
|
||||
unsigned int UnicodeScalarValue = 0;
|
||||
UnquotedValue.substr(1, 2).getAsInteger(16, UnicodeScalarValue);
|
||||
encodeUTF8(UnicodeScalarValue, Storage);
|
||||
UnquotedValue = UnquotedValue.substr(2);
|
||||
@ -1742,7 +1742,7 @@ StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
|
||||
if (UnquotedValue.size() < 5)
|
||||
// TODO: Report error.
|
||||
break;
|
||||
unsigned int UnicodeScalarValue;
|
||||
unsigned int UnicodeScalarValue = 0;
|
||||
UnquotedValue.substr(1, 4).getAsInteger(16, UnicodeScalarValue);
|
||||
encodeUTF8(UnicodeScalarValue, Storage);
|
||||
UnquotedValue = UnquotedValue.substr(4);
|
||||
@ -1752,7 +1752,7 @@ StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
|
||||
if (UnquotedValue.size() < 9)
|
||||
// TODO: Report error.
|
||||
break;
|
||||
unsigned int UnicodeScalarValue;
|
||||
unsigned int UnicodeScalarValue = 0;
|
||||
UnquotedValue.substr(1, 8).getAsInteger(16, UnicodeScalarValue);
|
||||
encodeUTF8(UnicodeScalarValue, Storage);
|
||||
UnquotedValue = UnquotedValue.substr(8);
|
||||
|
@ -633,6 +633,19 @@ raw_ostream &raw_fd_ostream::resetColor() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
raw_ostream &raw_fd_ostream::reverseColor() {
|
||||
if (sys::Process::ColorNeedsFlush())
|
||||
flush();
|
||||
const char *colorcode = sys::Process::OutputReverse();
|
||||
if (colorcode) {
|
||||
size_t len = strlen(colorcode);
|
||||
write(colorcode, len);
|
||||
// don't account colors towards output characters
|
||||
pos -= len;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool raw_fd_ostream::is_displayed() const {
|
||||
return sys::Process::FileDescriptorIsDisplayed(FD);
|
||||
}
|
||||
|
@ -20,6 +20,22 @@ namespace llvm {
|
||||
|
||||
SourceMgr SrcMgr;
|
||||
|
||||
void PrintWarning(SMLoc WarningLoc, const Twine &Msg) {
|
||||
SrcMgr.PrintMessage(WarningLoc, SourceMgr::DK_Warning, Msg);
|
||||
}
|
||||
|
||||
void PrintWarning(const char *Loc, const Twine &Msg) {
|
||||
SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Warning, Msg);
|
||||
}
|
||||
|
||||
void PrintWarning(const Twine &Msg) {
|
||||
errs() << "warning:" << Msg << "\n";
|
||||
}
|
||||
|
||||
void PrintWarning(const TGError &Warning) {
|
||||
PrintWarning(Warning.getLoc(), Warning.getMessage());
|
||||
}
|
||||
|
||||
void PrintError(SMLoc ErrorLoc, const Twine &Msg) {
|
||||
SrcMgr.PrintMessage(ErrorLoc, SourceMgr::DK_Error, Msg);
|
||||
}
|
||||
|
@ -9,10 +9,6 @@
|
||||
// This describes the calling conventions for ARM architecture.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// CCIfSubtarget - Match if the current subtarget has a feature F.
|
||||
class CCIfSubtarget<string F, CCAction A>:
|
||||
CCIf<!strconcat("State.getTarget().getSubtarget<ARMSubtarget>().", F), A>;
|
||||
|
||||
/// CCIfAlign - Match of the original alignment of the arg
|
||||
class CCIfAlign<string Align, CCAction A>:
|
||||
CCIf<!strconcat("ArgFlags.getOrigAlign() == ", Align), A>;
|
||||
|
@ -532,6 +532,7 @@ class AIswp<bit b, dag oops, dag iops, string opc, list<dag> pattern>
|
||||
let Inst{11-4} = 0b00001001;
|
||||
let Inst{3-0} = Rt2;
|
||||
|
||||
let Unpredictable{11-8} = 0b1111;
|
||||
let DecoderMethod = "DecodeSwap";
|
||||
}
|
||||
|
||||
|
@ -219,8 +219,11 @@ def UseFPVMLx : Predicate<"Subtarget->useFPVMLx()">;
|
||||
|
||||
// Prefer fused MAC for fp mul + add over fp VMLA / VMLS if they are available.
|
||||
// But only select them if more precision in FP computation is allowed.
|
||||
def UseFusedMAC : Predicate<"!TM.Options.NoExcessFPPrecision">;
|
||||
def DontUseFusedMAC : Predicate<"!Subtarget->hasVFP4()">;
|
||||
// Do not use them for Darwin platforms.
|
||||
def UseFusedMAC : Predicate<"!TM.Options.NoExcessFPPrecision && "
|
||||
"!Subtarget->isTargetDarwin()">;
|
||||
def DontUseFusedMAC : Predicate<"!Subtarget->hasVFP4() || "
|
||||
"Subtarget->isTargetDarwin()">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ARM Flag Definitions.
|
||||
@ -905,6 +908,11 @@ def p_imm : Operand<i32> {
|
||||
let DecoderMethod = "DecodeCoprocessor";
|
||||
}
|
||||
|
||||
def pf_imm : Operand<i32> {
|
||||
let PrintMethod = "printPImmediate";
|
||||
let ParserMatchClass = CoprocNumAsmOperand;
|
||||
}
|
||||
|
||||
def CoprocRegAsmOperand : AsmOperandClass {
|
||||
let Name = "CoprocReg";
|
||||
let ParserMethod = "parseCoprocRegOperand";
|
||||
@ -1184,6 +1192,8 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = 0b0000;
|
||||
let Inst{11-0} = imm;
|
||||
|
||||
let Unpredictable{15-12} = 0b1111;
|
||||
}
|
||||
def rr : AI1<opcod, (outs), (ins GPR:$Rn, GPR:$Rm), DPFrm, iir,
|
||||
opc, "\t$Rn, $Rm",
|
||||
@ -1197,6 +1207,8 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,
|
||||
let Inst{15-12} = 0b0000;
|
||||
let Inst{11-4} = 0b00000000;
|
||||
let Inst{3-0} = Rm;
|
||||
|
||||
let Unpredictable{15-12} = 0b1111;
|
||||
}
|
||||
def rsi : AI1<opcod, (outs),
|
||||
(ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm, iis,
|
||||
@ -1211,11 +1223,13 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,
|
||||
let Inst{11-5} = shift{11-5};
|
||||
let Inst{4} = 0;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
|
||||
let Unpredictable{15-12} = 0b1111;
|
||||
}
|
||||
def rsr : AI1<opcod, (outs),
|
||||
(ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, iis,
|
||||
(ins GPRnopc:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, iis,
|
||||
opc, "\t$Rn, $shift",
|
||||
[(opnode GPR:$Rn, so_reg_reg:$shift)]> {
|
||||
[(opnode GPRnopc:$Rn, so_reg_reg:$shift)]> {
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
@ -1227,6 +1241,8 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,
|
||||
let Inst{6-5} = shift{6-5};
|
||||
let Inst{4} = 1;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
|
||||
let Unpredictable{15-12} = 0b1111;
|
||||
}
|
||||
|
||||
}
|
||||
@ -4103,7 +4119,7 @@ def ISB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
|
||||
let Inst{3-0} = opt;
|
||||
}
|
||||
|
||||
// Pseudo isntruction that combines movs + predicated rsbmi
|
||||
// Pseudo instruction that combines movs + predicated rsbmi
|
||||
// to implement integer ABS
|
||||
let usesCustomInserter = 1, Defs = [CPSR] in {
|
||||
def ABS : ARMPseudoInst<
|
||||
@ -4264,9 +4280,9 @@ def CLREX : AXI<(outs), (ins), MiscFrm, NoItinerary, "clrex", []>,
|
||||
|
||||
// SWP/SWPB are deprecated in V6/V7.
|
||||
let mayLoad = 1, mayStore = 1 in {
|
||||
def SWP : AIswp<0, (outs GPR:$Rt), (ins GPR:$Rt2, addr_offset_none:$addr),
|
||||
def SWP : AIswp<0, (outs GPRnopc:$Rt), (ins GPRnopc:$Rt2, addr_offset_none:$addr),
|
||||
"swp", []>;
|
||||
def SWPB: AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, addr_offset_none:$addr),
|
||||
def SWPB: AIswp<1, (outs GPRnopc:$Rt), (ins GPRnopc:$Rt2, addr_offset_none:$addr),
|
||||
"swpb", []>;
|
||||
}
|
||||
|
||||
@ -4295,7 +4311,7 @@ def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
|
||||
let Inst{23-20} = opc1;
|
||||
}
|
||||
|
||||
def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
|
||||
def CDP2 : ABXI<0b1110, (outs), (ins pf_imm:$cop, imm0_15:$opc1,
|
||||
c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2),
|
||||
NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
|
||||
[(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
|
||||
@ -4574,7 +4590,7 @@ def : ARMV5TPat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn,
|
||||
|
||||
class MovRRCopro<string opc, bit direction, list<dag> pattern = []>
|
||||
: ABI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1,
|
||||
GPR:$Rt, GPR:$Rt2, c_imm:$CRm),
|
||||
GPRnopc:$Rt, GPRnopc:$Rt2, c_imm:$CRm),
|
||||
NoItinerary, opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm", pattern> {
|
||||
let Inst{23-21} = 0b010;
|
||||
let Inst{20} = direction;
|
||||
@ -4593,13 +4609,13 @@ class MovRRCopro<string opc, bit direction, list<dag> pattern = []>
|
||||
}
|
||||
|
||||
def MCRR : MovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */,
|
||||
[(int_arm_mcrr imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2,
|
||||
[(int_arm_mcrr imm:$cop, imm:$opc1, GPRnopc:$Rt, GPRnopc:$Rt2,
|
||||
imm:$CRm)]>;
|
||||
def MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>;
|
||||
|
||||
class MovRRCopro2<string opc, bit direction, list<dag> pattern = []>
|
||||
: ABXI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1,
|
||||
GPR:$Rt, GPR:$Rt2, c_imm:$CRm), NoItinerary,
|
||||
GPRnopc:$Rt, GPRnopc:$Rt2, c_imm:$CRm), NoItinerary,
|
||||
!strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern> {
|
||||
let Inst{31-28} = 0b1111;
|
||||
let Inst{23-21} = 0b010;
|
||||
@ -4616,10 +4632,12 @@ class MovRRCopro2<string opc, bit direction, list<dag> pattern = []>
|
||||
let Inst{11-8} = cop;
|
||||
let Inst{7-4} = opc1;
|
||||
let Inst{3-0} = CRm;
|
||||
|
||||
let DecoderMethod = "DecodeMRRC2";
|
||||
}
|
||||
|
||||
def MCRR2 : MovRRCopro2<"mcrr2", 0 /* from ARM core register to coprocessor */,
|
||||
[(int_arm_mcrr2 imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2,
|
||||
[(int_arm_mcrr2 imm:$cop, imm:$opc1, GPRnopc:$Rt, GPRnopc:$Rt2,
|
||||
imm:$CRm)]>;
|
||||
def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>;
|
||||
|
||||
@ -4628,22 +4646,32 @@ def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>;
|
||||
//
|
||||
|
||||
// Move to ARM core register from Special Register
|
||||
def MRS : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary,
|
||||
def MRS : ABI<0b0001, (outs GPRnopc:$Rd), (ins), NoItinerary,
|
||||
"mrs", "\t$Rd, apsr", []> {
|
||||
bits<4> Rd;
|
||||
let Inst{23-16} = 0b00001111;
|
||||
let Unpredictable{19-17} = 0b111;
|
||||
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{7-4} = 0b0000;
|
||||
|
||||
let Inst{11-0} = 0b000000000000;
|
||||
let Unpredictable{11-0} = 0b110100001111;
|
||||
}
|
||||
|
||||
def : InstAlias<"mrs${p} $Rd, cpsr", (MRS GPR:$Rd, pred:$p)>, Requires<[IsARM]>;
|
||||
def : InstAlias<"mrs${p} $Rd, cpsr", (MRS GPRnopc:$Rd, pred:$p)>, Requires<[IsARM]>;
|
||||
|
||||
def MRSsys : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary,
|
||||
// The MRSsys instruction is the MRS instruction from the ARM ARM,
|
||||
// section B9.3.9, with the R bit set to 1.
|
||||
def MRSsys : ABI<0b0001, (outs GPRnopc:$Rd), (ins), NoItinerary,
|
||||
"mrs", "\t$Rd, spsr", []> {
|
||||
bits<4> Rd;
|
||||
let Inst{23-16} = 0b01001111;
|
||||
let Unpredictable{19-16} = 0b1111;
|
||||
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{7-4} = 0b0000;
|
||||
|
||||
let Inst{11-0} = 0b000000000000;
|
||||
let Unpredictable{11-0} = 0b110100001111;
|
||||
}
|
||||
|
||||
// Move from ARM core register to Special Register
|
||||
|
@ -5634,6 +5634,7 @@ multiclass Lengthen_HalfSingle<string DestLanes, string DestTy, string SrcTy,
|
||||
|
||||
// extload, zextload and sextload for a lengthening load followed by another
|
||||
// lengthening load, to quadruple the initial length.
|
||||
//
|
||||
// Lengthen_Double<"4", "i32", "i8", "8", "i16", "4", "i32", qsub_0> =
|
||||
// Pat<(v4i32 (extloadvi8 addrmode5:$addr))
|
||||
// (EXTRACT_SUBREG (VMOVLuv4i32
|
||||
@ -5644,28 +5645,63 @@ multiclass Lengthen_HalfSingle<string DestLanes, string DestTy, string SrcTy,
|
||||
// qsub_0)>;
|
||||
multiclass Lengthen_Double<string DestLanes, string DestTy, string SrcTy,
|
||||
string Insn1Lanes, string Insn1Ty, string Insn2Lanes,
|
||||
string Insn2Ty, SubRegIndex RegType> {
|
||||
string Insn2Ty> {
|
||||
def _Any : Pat<(!cast<ValueType>("v" # DestLanes # DestTy)
|
||||
(!cast<PatFrag>("extloadv" # SrcTy) addrmode5:$addr)),
|
||||
(!cast<Instruction>("VMOVLuv" # Insn2Lanes # Insn2Ty)
|
||||
(EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn1Lanes # Insn1Ty)
|
||||
(INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr),
|
||||
ssub_0)), dsub_0))>;
|
||||
def _Z : Pat<(!cast<ValueType>("v" # DestLanes # DestTy)
|
||||
(!cast<PatFrag>("zextloadv" # SrcTy) addrmode5:$addr)),
|
||||
(!cast<Instruction>("VMOVLuv" # Insn2Lanes # Insn2Ty)
|
||||
(EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn1Lanes # Insn1Ty)
|
||||
(INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr),
|
||||
ssub_0)), dsub_0))>;
|
||||
def _S : Pat<(!cast<ValueType>("v" # DestLanes # DestTy)
|
||||
(!cast<PatFrag>("sextloadv" # SrcTy) addrmode5:$addr)),
|
||||
(!cast<Instruction>("VMOVLsv" # Insn2Lanes # Insn2Ty)
|
||||
(EXTRACT_SUBREG (!cast<Instruction>("VMOVLsv" # Insn1Lanes # Insn1Ty)
|
||||
(INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr),
|
||||
ssub_0)), dsub_0))>;
|
||||
}
|
||||
|
||||
// extload, zextload and sextload for a lengthening load followed by another
|
||||
// lengthening load, to quadruple the initial length, but which ends up only
|
||||
// requiring half the available lanes (a 64-bit outcome instead of a 128-bit).
|
||||
//
|
||||
// Lengthen_HalfDouble<"2", "i32", "i8", "8", "i16", "4", "i32"> =
|
||||
// Pat<(v4i32 (extloadvi8 addrmode5:$addr))
|
||||
// (EXTRACT_SUBREG (VMOVLuv4i32
|
||||
// (EXTRACT_SUBREG (VMOVLuv8i16 (INSERT_SUBREG (f64 (IMPLICIT_DEF)),
|
||||
// (VLDRS addrmode5:$addr),
|
||||
// ssub_0)),
|
||||
// dsub_0)),
|
||||
// dsub_0)>;
|
||||
multiclass Lengthen_HalfDouble<string DestLanes, string DestTy, string SrcTy,
|
||||
string Insn1Lanes, string Insn1Ty, string Insn2Lanes,
|
||||
string Insn2Ty> {
|
||||
def _Any : Pat<(!cast<ValueType>("v" # DestLanes # DestTy)
|
||||
(!cast<PatFrag>("extloadv" # SrcTy) addrmode5:$addr)),
|
||||
(EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn2Lanes # Insn2Ty)
|
||||
(EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn1Lanes # Insn1Ty)
|
||||
(INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr),
|
||||
ssub_0)), dsub_0)),
|
||||
RegType)>;
|
||||
dsub_0)>;
|
||||
def _Z : Pat<(!cast<ValueType>("v" # DestLanes # DestTy)
|
||||
(!cast<PatFrag>("zextloadv" # SrcTy) addrmode5:$addr)),
|
||||
(EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn2Lanes # Insn2Ty)
|
||||
(EXTRACT_SUBREG (!cast<Instruction>("VMOVLuv" # Insn1Lanes # Insn1Ty)
|
||||
(INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr),
|
||||
ssub_0)), dsub_0)),
|
||||
RegType)>;
|
||||
dsub_0)>;
|
||||
def _S : Pat<(!cast<ValueType>("v" # DestLanes # DestTy)
|
||||
(!cast<PatFrag>("sextloadv" # SrcTy) addrmode5:$addr)),
|
||||
(EXTRACT_SUBREG (!cast<Instruction>("VMOVLsv" # Insn2Lanes # Insn2Ty)
|
||||
(EXTRACT_SUBREG (!cast<Instruction>("VMOVLsv" # Insn1Lanes # Insn1Ty)
|
||||
(INSERT_SUBREG (f64 (IMPLICIT_DEF)), (VLDRS addrmode5:$addr),
|
||||
ssub_0)), dsub_0)),
|
||||
RegType)>;
|
||||
dsub_0)>;
|
||||
}
|
||||
|
||||
defm : Lengthen_Single<"8", "i16", "i8">; // v8i8 -> v8i16
|
||||
@ -5676,12 +5712,12 @@ defm : Lengthen_HalfSingle<"4", "i16", "i8", "8", "i16">; // v4i8 -> v4i16
|
||||
defm : Lengthen_HalfSingle<"2", "i16", "i8", "8", "i16">; // v2i8 -> v2i16
|
||||
defm : Lengthen_HalfSingle<"2", "i32", "i16", "4", "i32">; // v2i16 -> v2i32
|
||||
|
||||
// Double lengthening - v4i8 -> v4i16 -> v4i32
|
||||
defm : Lengthen_Double<"4", "i32", "i8", "8", "i16", "4", "i32", qsub_0>;
|
||||
// Double lengthening - v4i8 -> v4i16 -> v4i32
|
||||
defm : Lengthen_Double<"4", "i32", "i8", "8", "i16", "4", "i32">;
|
||||
// v2i8 -> v2i16 -> v2i32
|
||||
defm : Lengthen_Double<"2", "i32", "i8", "8", "i16", "4", "i32", dsub_0>;
|
||||
defm : Lengthen_HalfDouble<"2", "i32", "i8", "8", "i16", "4", "i32">;
|
||||
// v2i16 -> v2i32 -> v2i64
|
||||
defm : Lengthen_Double<"2", "i64", "i16", "4", "i32", "2", "i64", qsub_0>;
|
||||
defm : Lengthen_Double<"2", "i64", "i16", "4", "i32", "2", "i64">;
|
||||
|
||||
// Triple lengthening - v2i8 -> v2i16 -> v2i32 -> v2i64
|
||||
def : Pat<(v2i64 (extloadvi8 addrmode5:$addr)),
|
||||
@ -5951,7 +5987,7 @@ def : NEONInstAlias<"vshl${p}.u32 $Vdn, $Vm",
|
||||
def : NEONInstAlias<"vshl${p}.u64 $Vdn, $Vm",
|
||||
(VSHLuv2i64 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
|
||||
// VSHL (immediate) two-operand aliases.
|
||||
// VSHR (immediate) two-operand aliases.
|
||||
def : NEONInstAlias<"vshr${p}.s8 $Vdn, $imm",
|
||||
(VSHRsv8i8 DPR:$Vdn, DPR:$Vdn, shr_imm8:$imm, pred:$p)>;
|
||||
def : NEONInstAlias<"vshr${p}.s16 $Vdn, $imm",
|
||||
@ -5988,6 +6024,41 @@ def : NEONInstAlias<"vshr${p}.u32 $Vdn, $imm",
|
||||
def : NEONInstAlias<"vshr${p}.u64 $Vdn, $imm",
|
||||
(VSHRuv2i64 QPR:$Vdn, QPR:$Vdn, shr_imm64:$imm, pred:$p)>;
|
||||
|
||||
// VRSHL two-operand aliases.
|
||||
def : NEONInstAlias<"vrshl${p}.s8 $Vdn, $Vm",
|
||||
(VRSHLsv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.s16 $Vdn, $Vm",
|
||||
(VRSHLsv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.s32 $Vdn, $Vm",
|
||||
(VRSHLsv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.s64 $Vdn, $Vm",
|
||||
(VRSHLsv1i64 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.u8 $Vdn, $Vm",
|
||||
(VRSHLuv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.u16 $Vdn, $Vm",
|
||||
(VRSHLuv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.u32 $Vdn, $Vm",
|
||||
(VRSHLuv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.u64 $Vdn, $Vm",
|
||||
(VRSHLuv1i64 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
|
||||
def : NEONInstAlias<"vrshl${p}.s8 $Vdn, $Vm",
|
||||
(VRSHLsv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.s16 $Vdn, $Vm",
|
||||
(VRSHLsv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.s32 $Vdn, $Vm",
|
||||
(VRSHLsv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.s64 $Vdn, $Vm",
|
||||
(VRSHLsv2i64 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.u8 $Vdn, $Vm",
|
||||
(VRSHLuv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.u16 $Vdn, $Vm",
|
||||
(VRSHLuv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.u32 $Vdn, $Vm",
|
||||
(VRSHLuv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrshl${p}.u64 $Vdn, $Vm",
|
||||
(VRSHLuv2i64 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
|
||||
// VLD1 single-lane pseudo-instructions. These need special handling for
|
||||
// the lane index that an InstAlias can't handle, so we use these instead.
|
||||
def VLD1LNdAsm_8 : NEONDataTypeAsmPseudoInst<"vld1${p}", ".8", "$list, $addr",
|
||||
@ -6951,6 +7022,100 @@ def : NEONInstAlias<"vsli${p}.32 $Vdm, $imm",
|
||||
def : NEONInstAlias<"vsli${p}.64 $Vdm, $imm",
|
||||
(VSLIv2i64 QPR:$Vdm, QPR:$Vdm, shr_imm64:$imm, pred:$p)>;
|
||||
|
||||
// Two-operand variants for VHSUB.
|
||||
// Signed.
|
||||
def : NEONInstAlias<"vhsub${p}.s8 $Vdn, $Vm",
|
||||
(VHSUBsv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhsub${p}.s16 $Vdn, $Vm",
|
||||
(VHSUBsv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhsub${p}.s32 $Vdn, $Vm",
|
||||
(VHSUBsv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
|
||||
def : NEONInstAlias<"vhsub${p}.s8 $Vdn, $Vm",
|
||||
(VHSUBsv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhsub${p}.s16 $Vdn, $Vm",
|
||||
(VHSUBsv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhsub${p}.s32 $Vdn, $Vm",
|
||||
(VHSUBsv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
|
||||
// Unsigned.
|
||||
def : NEONInstAlias<"vhsub${p}.u8 $Vdn, $Vm",
|
||||
(VHSUBuv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhsub${p}.u16 $Vdn, $Vm",
|
||||
(VHSUBuv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhsub${p}.u32 $Vdn, $Vm",
|
||||
(VHSUBuv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
|
||||
def : NEONInstAlias<"vhsub${p}.u8 $Vdn, $Vm",
|
||||
(VHSUBuv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhsub${p}.u16 $Vdn, $Vm",
|
||||
(VHSUBuv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhsub${p}.u32 $Vdn, $Vm",
|
||||
(VHSUBuv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
|
||||
|
||||
// Two-operand variants for VHADD.
|
||||
// Signed.
|
||||
def : NEONInstAlias<"vhadd${p}.s8 $Vdn, $Vm",
|
||||
(VHADDsv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhadd${p}.s16 $Vdn, $Vm",
|
||||
(VHADDsv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhadd${p}.s32 $Vdn, $Vm",
|
||||
(VHADDsv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
|
||||
def : NEONInstAlias<"vhadd${p}.s8 $Vdn, $Vm",
|
||||
(VHADDsv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhadd${p}.s16 $Vdn, $Vm",
|
||||
(VHADDsv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhadd${p}.s32 $Vdn, $Vm",
|
||||
(VHADDsv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
|
||||
// Unsigned.
|
||||
def : NEONInstAlias<"vhadd${p}.u8 $Vdn, $Vm",
|
||||
(VHADDuv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhadd${p}.u16 $Vdn, $Vm",
|
||||
(VHADDuv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhadd${p}.u32 $Vdn, $Vm",
|
||||
(VHADDuv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>;
|
||||
|
||||
def : NEONInstAlias<"vhadd${p}.u8 $Vdn, $Vm",
|
||||
(VHADDuv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhadd${p}.u16 $Vdn, $Vm",
|
||||
(VHADDuv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
def : NEONInstAlias<"vhadd${p}.u32 $Vdn, $Vm",
|
||||
(VHADDuv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>;
|
||||
|
||||
// Two-operand variants for VRHADD.
|
||||
// Signed.
|
||||
def : NEONInstAlias<"vrhadd${p}.s8 $Vdn, $Rm",
|
||||
(VRHADDsv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrhadd${p}.s16 $Vdn, $Rm",
|
||||
(VRHADDsv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrhadd${p}.s32 $Vdn, $Rm",
|
||||
(VRHADDsv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>;
|
||||
|
||||
def : NEONInstAlias<"vrhadd${p}.s8 $Vdn, $Rm",
|
||||
(VRHADDsv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrhadd${p}.s16 $Vdn, $Rm",
|
||||
(VRHADDsv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrhadd${p}.s32 $Vdn, $Rm",
|
||||
(VRHADDsv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>;
|
||||
|
||||
// Unsigned.
|
||||
def : NEONInstAlias<"vrhadd${p}.u8 $Vdn, $Rm",
|
||||
(VRHADDuv8i8 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrhadd${p}.u16 $Vdn, $Rm",
|
||||
(VRHADDuv4i16 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrhadd${p}.u32 $Vdn, $Rm",
|
||||
(VRHADDuv2i32 DPR:$Vdn, DPR:$Vdn, DPR:$Rm, pred:$p)>;
|
||||
|
||||
def : NEONInstAlias<"vrhadd${p}.u8 $Vdn, $Rm",
|
||||
(VRHADDuv16i8 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrhadd${p}.u16 $Vdn, $Rm",
|
||||
(VRHADDuv8i16 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>;
|
||||
def : NEONInstAlias<"vrhadd${p}.u32 $Vdn, $Rm",
|
||||
(VRHADDuv4i32 QPR:$Vdn, QPR:$Vdn, QPR:$Rm, pred:$p)>;
|
||||
|
||||
// VSWP allows, but does not require, a type suffix.
|
||||
defm : NEONDTAnyInstAlias<"vswp${p}", "$Vd, $Vm",
|
||||
(VSWPd DPR:$Vd, DPR:$Vm, pred:$p)>;
|
||||
|
@ -136,22 +136,22 @@ TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
|
||||
|
||||
bool ARMPassConfig::addPreISel() {
|
||||
if (TM->getOptLevel() != CodeGenOpt::None && EnableGlobalMerge)
|
||||
PM.add(createGlobalMergePass(TM->getTargetLowering()));
|
||||
PM->add(createGlobalMergePass(TM->getTargetLowering()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMPassConfig::addInstSelector() {
|
||||
PM.add(createARMISelDag(getARMTargetMachine(), getOptLevel()));
|
||||
PM->add(createARMISelDag(getARMTargetMachine(), getOptLevel()));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMPassConfig::addPreRegAlloc() {
|
||||
// FIXME: temporarily disabling load / store optimization pass for Thumb1.
|
||||
if (getOptLevel() != CodeGenOpt::None && !getARMSubtarget().isThumb1Only())
|
||||
PM.add(createARMLoadStoreOptimizationPass(true));
|
||||
PM->add(createARMLoadStoreOptimizationPass(true));
|
||||
if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9())
|
||||
PM.add(createMLxExpansionPass());
|
||||
PM->add(createMLxExpansionPass());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -159,23 +159,23 @@ bool ARMPassConfig::addPreSched2() {
|
||||
// FIXME: temporarily disabling load / store optimization pass for Thumb1.
|
||||
if (getOptLevel() != CodeGenOpt::None) {
|
||||
if (!getARMSubtarget().isThumb1Only()) {
|
||||
PM.add(createARMLoadStoreOptimizationPass());
|
||||
PM->add(createARMLoadStoreOptimizationPass());
|
||||
printAndVerify("After ARM load / store optimizer");
|
||||
}
|
||||
if (getARMSubtarget().hasNEON())
|
||||
PM.add(createExecutionDependencyFixPass(&ARM::DPRRegClass));
|
||||
PM->add(createExecutionDependencyFixPass(&ARM::DPRRegClass));
|
||||
}
|
||||
|
||||
// Expand some pseudo instructions into multiple instructions to allow
|
||||
// proper scheduling.
|
||||
PM.add(createARMExpandPseudoPass());
|
||||
PM->add(createARMExpandPseudoPass());
|
||||
|
||||
if (getOptLevel() != CodeGenOpt::None) {
|
||||
if (!getARMSubtarget().isThumb1Only())
|
||||
addPass(IfConverterID);
|
||||
}
|
||||
if (getARMSubtarget().isThumb2())
|
||||
PM.add(createThumb2ITBlockPass());
|
||||
PM->add(createThumb2ITBlockPass());
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -183,13 +183,13 @@ bool ARMPassConfig::addPreSched2() {
|
||||
bool ARMPassConfig::addPreEmitPass() {
|
||||
if (getARMSubtarget().isThumb2()) {
|
||||
if (!getARMSubtarget().prefers32BitThumb())
|
||||
PM.add(createThumb2SizeReductionPass());
|
||||
PM->add(createThumb2SizeReductionPass());
|
||||
|
||||
// Constant island pass work on unbundled instructions.
|
||||
addPass(UnpackMachineBundlesID);
|
||||
}
|
||||
|
||||
PM.add(createARMConstantIslandPass());
|
||||
PM->add(createARMConstantIslandPass());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -82,8 +82,14 @@ class ARMAsmParser : public MCTargetAsmParser {
|
||||
MCAsmParser &getParser() const { return Parser; }
|
||||
MCAsmLexer &getLexer() const { return Parser.getLexer(); }
|
||||
|
||||
void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
|
||||
bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
|
||||
bool Warning(SMLoc L, const Twine &Msg,
|
||||
ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
|
||||
return Parser.Warning(L, Msg, Ranges);
|
||||
}
|
||||
bool Error(SMLoc L, const Twine &Msg,
|
||||
ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
|
||||
return Parser.Error(L, Msg, Ranges);
|
||||
}
|
||||
|
||||
int tryParseRegister();
|
||||
bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||
@ -478,6 +484,8 @@ class ARMOperand : public MCParsedAsmOperand {
|
||||
/// getEndLoc - Get the location of the last token of this operand.
|
||||
SMLoc getEndLoc() const { return EndLoc; }
|
||||
|
||||
SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
|
||||
|
||||
ARMCC::CondCodes getCondCode() const {
|
||||
assert(Kind == k_CondCode && "Invalid access!");
|
||||
return CC.Val;
|
||||
@ -4518,22 +4526,26 @@ bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
case AsmToken::Dollar:
|
||||
case AsmToken::Hash: {
|
||||
// #42 -> immediate.
|
||||
// TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
|
||||
S = Parser.getTok().getLoc();
|
||||
Parser.Lex();
|
||||
bool isNegative = Parser.getTok().is(AsmToken::Minus);
|
||||
const MCExpr *ImmVal;
|
||||
if (getParser().ParseExpression(ImmVal))
|
||||
return true;
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
|
||||
if (CE) {
|
||||
int32_t Val = CE->getValue();
|
||||
if (isNegative && Val == 0)
|
||||
ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
|
||||
|
||||
if (Parser.getTok().isNot(AsmToken::Colon)) {
|
||||
bool isNegative = Parser.getTok().is(AsmToken::Minus);
|
||||
const MCExpr *ImmVal;
|
||||
if (getParser().ParseExpression(ImmVal))
|
||||
return true;
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
|
||||
if (CE) {
|
||||
int32_t Val = CE->getValue();
|
||||
if (isNegative && Val == 0)
|
||||
ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
|
||||
}
|
||||
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||
Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
|
||||
return false;
|
||||
}
|
||||
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||
Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
|
||||
return false;
|
||||
// w/ a ':' after the '#', it's just like a plain ':'.
|
||||
// FALLTHROUGH
|
||||
}
|
||||
case AsmToken::Colon: {
|
||||
// ":lower16:" and ":upper16:" expression prefixes
|
||||
@ -7321,7 +7333,8 @@ MatchAndEmitInstruction(SMLoc IDLoc,
|
||||
return Error(ErrorLoc, "invalid operand for instruction");
|
||||
}
|
||||
case Match_MnemonicFail:
|
||||
return Error(IDLoc, "invalid instruction");
|
||||
return Error(IDLoc, "invalid instruction",
|
||||
((ARMOperand*)Operands[0])->getLocRange());
|
||||
case Match_ConversionFail:
|
||||
// The converter function will have already emited a diagnostic.
|
||||
return true;
|
||||
|
@ -326,6 +326,8 @@ static DecodeStatus DecodeT2ShifterImmOperand(MCInst &Inst, unsigned Val,
|
||||
|
||||
static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeMRRC2(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
#include "ARMGenDisassemblerTables.inc"
|
||||
#include "ARMGenInstrInfo.inc"
|
||||
#include "ARMGenEDInfo.inc"
|
||||
@ -2690,7 +2692,6 @@ static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Insn,
|
||||
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
|
||||
unsigned align = fieldFromInstruction32(Insn, 4, 1);
|
||||
unsigned size = 1 << fieldFromInstruction32(Insn, 6, 2);
|
||||
unsigned pred = fieldFromInstruction32(Insn, 22, 4);
|
||||
align *= 2*size;
|
||||
|
||||
switch (Inst.getOpcode()) {
|
||||
@ -2721,16 +2722,11 @@ static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Insn,
|
||||
return MCDisassembler::Fail;
|
||||
Inst.addOperand(MCOperand::CreateImm(align));
|
||||
|
||||
if (Rm == 0xD)
|
||||
Inst.addOperand(MCOperand::CreateReg(0));
|
||||
else if (Rm != 0xF) {
|
||||
if (Rm != 0xD && Rm != 0xF) {
|
||||
if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
|
||||
if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
@ -4314,6 +4310,10 @@ static DecodeStatus DecodeSwap(MCInst &Inst, unsigned Insn,
|
||||
return DecodeCPSInstruction(Inst, Insn, Address, Decoder);
|
||||
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
if (Rt == Rn || Rn == Rt2)
|
||||
S = MCDisassembler::SoftFail;
|
||||
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt2, Address, Decoder)))
|
||||
@ -4409,3 +4409,31 @@ static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val,
|
||||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeMRRC2(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
unsigned CRm = fieldFromInstruction32(Val, 0, 4);
|
||||
unsigned opc1 = fieldFromInstruction32(Val, 4, 4);
|
||||
unsigned cop = fieldFromInstruction32(Val, 8, 4);
|
||||
unsigned Rt = fieldFromInstruction32(Val, 12, 4);
|
||||
unsigned Rt2 = fieldFromInstruction32(Val, 16, 4);
|
||||
|
||||
if ((cop & ~0x1) == 0xa)
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
if (Rt == Rt2)
|
||||
S = MCDisassembler::SoftFail;
|
||||
|
||||
Inst.addOperand(MCOperand::CreateImm(cop));
|
||||
Inst.addOperand(MCOperand::CreateImm(opc1));
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt2, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
Inst.addOperand(MCOperand::CreateImm(CRm));
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
|
@ -209,12 +209,12 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
} else {
|
||||
assert(Op.isExpr() && "unknown operand kind in printOperand");
|
||||
// If a symbolic branch target was added as a constant expression then print
|
||||
// that address in hex.
|
||||
// that address in hex. And only print 32 unsigned bits for the address.
|
||||
const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr());
|
||||
int64_t Address;
|
||||
if (BranchTarget && BranchTarget->EvaluateAsAbsolute(Address)) {
|
||||
O << "0x";
|
||||
O.write_hex(Address);
|
||||
O.write_hex((uint32_t)Address);
|
||||
}
|
||||
else {
|
||||
// Otherwise, just print the expression.
|
||||
|
@ -11,10 +11,6 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// CCIfSubtarget - Match if the current subtarget has a feature F.
|
||||
class CCIfSubtarget<string F, CCAction A>
|
||||
: CCIf<!strconcat("State.getTarget().getSubtarget<PPCSubtarget>().", F), A>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Return Value Calling Convention
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -72,7 +72,7 @@ TargetPassConfig *SPUTargetMachine::createPassConfig(PassManagerBase &PM) {
|
||||
|
||||
bool SPUPassConfig::addInstSelector() {
|
||||
// Install an instruction selector.
|
||||
PM.add(createSPUISelDag(getSPUTargetMachine()));
|
||||
PM->add(createSPUISelDag(getSPUTargetMachine()));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -85,9 +85,9 @@ bool SPUPassConfig::addPreEmitPass() {
|
||||
(BuilderFunc)(intptr_t)sys::DynamicLibrary::SearchForAddressOfSymbol(
|
||||
"createTCESchedulerPass");
|
||||
if (schedulerCreator != NULL)
|
||||
PM.add(schedulerCreator("cellspu"));
|
||||
PM->add(schedulerCreator("cellspu"));
|
||||
|
||||
//align instructions with nops/lnops for dual issue
|
||||
PM.add(createSPUNopFillerPass(getSPUTargetMachine()));
|
||||
PM->add(createSPUNopFillerPass(getSPUTargetMachine()));
|
||||
return true;
|
||||
}
|
||||
|
@ -11,15 +11,15 @@ add_public_tablegen_target(HexagonCommonTableGen)
|
||||
|
||||
add_llvm_target(HexagonCodeGen
|
||||
HexagonAsmPrinter.cpp
|
||||
HexagonCFGOptimizer.cpp
|
||||
HexagonCallingConvLower.cpp
|
||||
HexagonCFGOptimizer.cpp
|
||||
HexagonExpandPredSpillCode.cpp
|
||||
HexagonFrameLowering.cpp
|
||||
HexagonHardwareLoops.cpp
|
||||
HexagonMCInstLower.cpp
|
||||
HexagonInstrInfo.cpp
|
||||
HexagonISelDAGToDAG.cpp
|
||||
HexagonISelLowering.cpp
|
||||
HexagonInstrInfo.cpp
|
||||
HexagonMCInstLower.cpp
|
||||
HexagonPeephole.cpp
|
||||
HexagonRegisterInfo.cpp
|
||||
HexagonRemoveSZExtArgs.cpp
|
||||
@ -28,7 +28,6 @@ add_llvm_target(HexagonCodeGen
|
||||
HexagonSubtarget.cpp
|
||||
HexagonTargetMachine.cpp
|
||||
HexagonTargetObjectFile.cpp
|
||||
HexagonVLIWPacketizer.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(TargetInfo)
|
||||
|
@ -40,7 +40,6 @@ namespace llvm {
|
||||
FunctionPass *createHexagonHardwareLoops();
|
||||
FunctionPass *createHexagonPeephole();
|
||||
FunctionPass *createHexagonFixupHwLoops();
|
||||
FunctionPass *createHexagonPacketizer();
|
||||
|
||||
/* TODO: object output.
|
||||
MCCodeEmitter *createHexagonMCCodeEmitter(const Target &,
|
||||
|
@ -13,11 +13,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#define DEBUG_TYPE "asm-printer"
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonAsmPrinter.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include "HexagonMCInst.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "InstPrinter/HexagonInstPrinter.h"
|
||||
@ -54,7 +54,6 @@
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include <map>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -78,7 +77,8 @@ void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
|
||||
switch (MO.getType()) {
|
||||
default: llvm_unreachable("<unknown operand type>");
|
||||
default:
|
||||
assert(0 && "<unknown operand type>");
|
||||
case MachineOperand::MO_Register:
|
||||
O << HexagonInstPrinter::getRegisterName(MO.getReg());
|
||||
return;
|
||||
@ -196,45 +196,10 @@ void HexagonAsmPrinter::printPredicateOperand(const MachineInstr *MI,
|
||||
/// the current output stream.
|
||||
///
|
||||
void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
if (MI->isBundle()) {
|
||||
std::vector<const MachineInstr*> BundleMIs;
|
||||
MCInst MCI;
|
||||
|
||||
const MachineBasicBlock *MBB = MI->getParent();
|
||||
MachineBasicBlock::const_instr_iterator MII = MI;
|
||||
++MII;
|
||||
unsigned int IgnoreCount = 0;
|
||||
while (MII != MBB->end() && MII->isInsideBundle()) {
|
||||
const MachineInstr *MInst = MII;
|
||||
if (MInst->getOpcode() == TargetOpcode::DBG_VALUE ||
|
||||
MInst->getOpcode() == TargetOpcode::IMPLICIT_DEF) {
|
||||
IgnoreCount++;
|
||||
++MII;
|
||||
continue;
|
||||
}
|
||||
//BundleMIs.push_back(&*MII);
|
||||
BundleMIs.push_back(MInst);
|
||||
++MII;
|
||||
}
|
||||
unsigned Size = BundleMIs.size();
|
||||
assert((Size+IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!");
|
||||
for (unsigned Index = 0; Index < Size; Index++) {
|
||||
HexagonMCInst MCI;
|
||||
MCI.setStartPacket(Index == 0);
|
||||
MCI.setEndPacket(Index == (Size-1));
|
||||
|
||||
HexagonLowerToMC(BundleMIs[Index], MCI, *this);
|
||||
OutStreamer.EmitInstruction(MCI);
|
||||
}
|
||||
}
|
||||
else {
|
||||
HexagonMCInst MCI;
|
||||
if (MI->getOpcode() == Hexagon::ENDLOOP0) {
|
||||
MCI.setStartPacket(true);
|
||||
MCI.setEndPacket(true);
|
||||
}
|
||||
HexagonLowerToMC(MI, MCI, *this);
|
||||
OutStreamer.EmitInstruction(MCI);
|
||||
}
|
||||
HexagonLowerToMC(MI, MCI, *this);
|
||||
OutStreamer.EmitInstruction(MCI);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -277,17 +242,17 @@ void HexagonAsmPrinter::printJumpTable(const MachineInstr *MI, int OpNo,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
assert( (MO.getType() == MachineOperand::MO_JumpTableIndex) &&
|
||||
"Expecting jump table index");
|
||||
"Expecting jump table index");
|
||||
|
||||
// Hexagon_TODO: Do we need name mangling?
|
||||
O << *GetJTISymbol(MO.getIndex());
|
||||
}
|
||||
|
||||
void HexagonAsmPrinter::printConstantPool(const MachineInstr *MI, int OpNo,
|
||||
raw_ostream &O) {
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
assert( (MO.getType() == MachineOperand::MO_ConstantPoolIndex) &&
|
||||
"Expecting constant pool index");
|
||||
"Expecting constant pool index");
|
||||
|
||||
// Hexagon_TODO: Do we need name mangling?
|
||||
O << *GetCPISymbol(MO.getIndex());
|
||||
|
@ -32,9 +32,11 @@
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||
#include "llvm/CodeGen/ValueTypes.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
const unsigned Hexagon_MAX_RET_SIZE = 64;
|
||||
|
@ -13,26 +13,13 @@
|
||||
// *** Must match HexagonBaseInfo.h ***
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class Type<bits<5> t> {
|
||||
bits<5> Value = t;
|
||||
}
|
||||
def TypePSEUDO : Type<0>;
|
||||
def TypeALU32 : Type<1>;
|
||||
def TypeCR : Type<2>;
|
||||
def TypeJR : Type<3>;
|
||||
def TypeJ : Type<4>;
|
||||
def TypeLD : Type<5>;
|
||||
def TypeST : Type<6>;
|
||||
def TypeSYSTEM : Type<7>;
|
||||
def TypeXTYPE : Type<8>;
|
||||
def TypeMARKER : Type<31>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Intruction Class Declaration +
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr, InstrItinClass itin, Type type> : Instruction {
|
||||
string cstr, InstrItinClass itin> : Instruction {
|
||||
field bits<32> Inst;
|
||||
|
||||
let Namespace = "Hexagon";
|
||||
@ -44,15 +31,11 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
let Constraints = cstr;
|
||||
let Itinerary = itin;
|
||||
|
||||
// *** Must match HexagonBaseInfo.h ***
|
||||
Type HexagonType = type;
|
||||
let TSFlags{4-0} = HexagonType.Value;
|
||||
bits<1> isHexagonSolo = 0;
|
||||
let TSFlags{5} = isHexagonSolo;
|
||||
// *** The code below must match HexagonBaseInfo.h ***
|
||||
|
||||
// Predicated instructions.
|
||||
bits<1> isPredicated = 0;
|
||||
let TSFlags{6} = isPredicated;
|
||||
let TSFlags{1} = isPredicated;
|
||||
|
||||
// *** The code above must match HexagonBaseInfo.h ***
|
||||
}
|
||||
@ -64,40 +47,28 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
// LD Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class LDInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", LD, TypeLD> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", LD> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<13> imm13;
|
||||
let mayLoad = 1;
|
||||
}
|
||||
|
||||
// LD Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class LDInstPost<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, LD, TypeLD> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, LD> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
bits<13> imm13;
|
||||
let mayLoad = 1;
|
||||
}
|
||||
|
||||
// ST Instruction Class in V2/V3 can take SLOT0 only.
|
||||
// ST Instruction Class in V4 can take SLOT0 & SLOT1.
|
||||
// Definition of the instruction class CHANGED from V2/V3 to V4.
|
||||
class STInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", ST, TypeST> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<13> imm13;
|
||||
let mayStore = 1;
|
||||
}
|
||||
|
||||
// SYSTEM Instruction Class in V4 can take SLOT0 only
|
||||
// In V2/V3 we used ST for this but in v4 ST can take SLOT0 or SLOT1.
|
||||
class SYSInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", SYS, TypeSYSTEM> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", ST> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<13> imm13;
|
||||
@ -108,18 +79,17 @@ class SYSInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
// Definition of the instruction class CHANGED from V2/V3 to V4.
|
||||
class STInstPost<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, ST, TypeST> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, ST> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
bits<13> imm13;
|
||||
let mayStore = 1;
|
||||
}
|
||||
|
||||
// ALU32 Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class ALU32Type<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", ALU32, TypeALU32> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", ALU32> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
@ -132,17 +102,7 @@ class ALU32Type<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
// Name of the Instruction Class changed from ALU64 to XTYPE from V2/V3 to V4.
|
||||
class ALU64Type<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", ALU64, TypeXTYPE> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
bits<16> imm16;
|
||||
bits<16> imm16_2;
|
||||
}
|
||||
|
||||
class ALU64_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, ALU64, TypeXTYPE> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", ALU64> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
@ -155,7 +115,7 @@ class ALU64_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
// Name of the Instruction Class changed from M to XTYPE from V2/V3 to V4.
|
||||
class MInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", M, TypeXTYPE> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", M> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
@ -166,8 +126,8 @@ class MInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
// Name of the Instruction Class changed from M to XTYPE from V2/V3 to V4.
|
||||
class MInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, M, TypeXTYPE> {
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, M> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
@ -178,7 +138,9 @@ class MInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
// Name of the Instruction Class changed from S to XTYPE from V2/V3 to V4.
|
||||
class SInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", S, TypeXTYPE> {
|
||||
//: InstHexagon<outs, ins, asmstr, pattern, cstr, !if(V4T, XTYPE_V4, M)> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", S> {
|
||||
// : InstHexagon<outs, ins, asmstr, pattern, "", S> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
@ -189,8 +151,8 @@ class SInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
// Name of the Instruction Class changed from S to XTYPE from V2/V3 to V4.
|
||||
class SInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, S, TypeXTYPE> {
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, S> {
|
||||
// : InstHexagon<outs, ins, asmstr, pattern, cstr, S> {
|
||||
// : InstHexagon<outs, ins, asmstr, pattern, cstr, !if(V4T, XTYPE_V4, S)> {
|
||||
bits<5> rd;
|
||||
@ -201,14 +163,14 @@ class SInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
// J Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class JType<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", J, TypeJ> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", J> {
|
||||
bits<16> imm16;
|
||||
}
|
||||
|
||||
// JR Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class JRType<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", JR, TypeJR> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", JR> {
|
||||
bits<5> rs;
|
||||
bits<5> pu; // Predicate register
|
||||
}
|
||||
@ -216,22 +178,15 @@ class JRType<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
// CR Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class CRInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", CR, TypeCR> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", CR> {
|
||||
bits<5> rs;
|
||||
bits<10> imm10;
|
||||
}
|
||||
|
||||
class Marker<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", MARKER, TypeMARKER> {
|
||||
let isCodeGenOnly = 1;
|
||||
let isPseudo = 1;
|
||||
}
|
||||
|
||||
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", PSEUDO, TypePSEUDO> {
|
||||
let isCodeGenOnly = 1;
|
||||
let isPseudo = 1;
|
||||
}
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", PSEUDO>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Intruction Classes Definitions -
|
||||
@ -267,11 +222,6 @@ class ALU64_rr<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: ALU64Type<outs, ins, asmstr, pattern> {
|
||||
}
|
||||
|
||||
class ALU64_ri<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: ALU64Type<outs, ins, asmstr, pattern> {
|
||||
let rt{0-4} = 0;
|
||||
}
|
||||
|
||||
// J Type Instructions.
|
||||
class JInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: JType<outs, ins, asmstr, pattern> {
|
||||
@ -287,14 +237,12 @@ class JRInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
class STInstPI<dag outs, dag ins, string asmstr, list<dag> pattern, string cstr>
|
||||
: STInstPost<outs, ins, asmstr, pattern, cstr> {
|
||||
let rt{0-4} = 0;
|
||||
let mayStore = 1;
|
||||
}
|
||||
|
||||
// Post increment LD Instruction.
|
||||
class LDInstPI<dag outs, dag ins, string asmstr, list<dag> pattern, string cstr>
|
||||
: LDInstPost<outs, ins, asmstr, pattern, cstr> {
|
||||
let rt{0-4} = 0;
|
||||
let mayLoad = 1;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user