[llvm-branch-commits] [llvm-branch] r136234 - in /llvm/branches/exception-handling-rewrite: ./ docs/ include/llvm-c/ include/llvm-c/Transforms/ include/llvm/ include/llvm/ADT/ include/llvm/Analysis/ include/llvm/MC/ include/llvm/Support/ include/llvm/Transforms/ lib/Analysis/ lib/CodeGen/ lib/CodeGen/AsmPrinter/ lib/CodeGen/SelectionDAG/ lib/MC/ lib/MC/MCParser/ lib/Support/ lib/Target/ARM/ lib/Target/ARM/AsmParser/ lib/Target/ARM/Disassembler/ lib/Target/ARM/InstPrinter/ lib/Target/ARM/MCTargetDesc/ lib/Target/CppBackend/ li...
Bill Wendling
isanbard at gmail.com
Wed Jul 27 11:40:49 PDT 2011
Author: void
Date: Wed Jul 27 13:40:48 2011
New Revision: 136234
URL: http://llvm.org/viewvc/llvm-project?rev=136234&view=rev
Log:
Merge with ToT in prep for merging to trunk.
Added:
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/avx-256-movdup.ll
- copied unchanged from r136231, llvm/trunk/test/CodeGen/X86/avx-256-movdup.ll
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/avx-256-unpack.ll
- copied unchanged from r136231, llvm/trunk/test/CodeGen/X86/avx-256-unpack.ll
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/avx-vpermil.ll
- copied unchanged from r136231, llvm/trunk/test/CodeGen/X86/avx-vpermil.ll
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/crash-nosse.ll
- copied unchanged from r136231, llvm/trunk/test/CodeGen/X86/crash-nosse.ll
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/dbg-inline.ll
- copied unchanged from r136231, llvm/trunk/test/CodeGen/X86/dbg-inline.ll
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/split-vector-bitcast.ll
- copied unchanged from r136231, llvm/trunk/test/CodeGen/X86/split-vector-bitcast.ll
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/sub.ll
- copied unchanged from r136231, llvm/trunk/test/CodeGen/X86/sub.ll
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-printers.cc
- copied unchanged from r136231, llvm/trunk/utils/unittest/googletest/gtest-printers.cc
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-printers.h
- copied unchanged from r136231, llvm/trunk/utils/unittest/googletest/include/gtest/gtest-printers.h
Removed:
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/dg.exp
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/notvunpcklpd.ll
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/notvunpcklps.ll
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/vunpcklpd.ll
llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/vunpcklps.ll
llvm/branches/exception-handling-rewrite/test/FrontendAda/
llvm/branches/exception-handling-rewrite/test/FrontendC/
llvm/branches/exception-handling-rewrite/test/FrontendFortran/
Modified:
llvm/branches/exception-handling-rewrite/ (props changed)
llvm/branches/exception-handling-rewrite/docs/CodeGenerator.html
llvm/branches/exception-handling-rewrite/docs/LangRef.html
llvm/branches/exception-handling-rewrite/docs/SourceLevelDebugging.html
llvm/branches/exception-handling-rewrite/include/llvm-c/Core.h
llvm/branches/exception-handling-rewrite/include/llvm-c/Transforms/IPO.h
llvm/branches/exception-handling-rewrite/include/llvm/ADT/SCCIterator.h
llvm/branches/exception-handling-rewrite/include/llvm/ADT/Triple.h
llvm/branches/exception-handling-rewrite/include/llvm/Analysis/AliasAnalysis.h
llvm/branches/exception-handling-rewrite/include/llvm/Analysis/AliasSetTracker.h
llvm/branches/exception-handling-rewrite/include/llvm/Analysis/BlockFrequencyImpl.h
llvm/branches/exception-handling-rewrite/include/llvm/Analysis/ScalarEvolution.h
llvm/branches/exception-handling-rewrite/include/llvm/Instruction.h
llvm/branches/exception-handling-rewrite/include/llvm/MC/MCAsmInfo.h
llvm/branches/exception-handling-rewrite/include/llvm/MC/MCAsmInfoDarwin.h
llvm/branches/exception-handling-rewrite/include/llvm/MC/MCDirectives.h
llvm/branches/exception-handling-rewrite/include/llvm/Support/BlockFrequency.h
llvm/branches/exception-handling-rewrite/include/llvm/Transforms/IPO.h
llvm/branches/exception-handling-rewrite/lib/Analysis/AliasSetTracker.cpp
llvm/branches/exception-handling-rewrite/lib/Analysis/BasicAliasAnalysis.cpp
llvm/branches/exception-handling-rewrite/lib/Analysis/InstructionSimplify.cpp
llvm/branches/exception-handling-rewrite/lib/Analysis/ScalarEvolution.cpp
llvm/branches/exception-handling-rewrite/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
llvm/branches/exception-handling-rewrite/lib/CodeGen/PeepholeOptimizer.cpp
llvm/branches/exception-handling-rewrite/lib/CodeGen/RegAllocBasic.cpp
llvm/branches/exception-handling-rewrite/lib/CodeGen/RegAllocGreedy.cpp
llvm/branches/exception-handling-rewrite/lib/CodeGen/RegisterCoalescer.cpp
llvm/branches/exception-handling-rewrite/lib/CodeGen/RegisterCoalescer.h
llvm/branches/exception-handling-rewrite/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
llvm/branches/exception-handling-rewrite/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
llvm/branches/exception-handling-rewrite/lib/MC/MCAsmInfo.cpp
llvm/branches/exception-handling-rewrite/lib/MC/MCAsmStreamer.cpp
llvm/branches/exception-handling-rewrite/lib/MC/MCELFStreamer.cpp
llvm/branches/exception-handling-rewrite/lib/MC/MCMachOStreamer.cpp
llvm/branches/exception-handling-rewrite/lib/MC/MCParser/AsmParser.cpp
llvm/branches/exception-handling-rewrite/lib/Support/BlockFrequency.cpp
llvm/branches/exception-handling-rewrite/lib/Support/ConstantRange.cpp
llvm/branches/exception-handling-rewrite/lib/Support/Triple.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMAsmPrinter.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMCodeEmitter.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMFastISel.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMFrameLowering.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMISelDAGToDAG.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMISelLowering.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrFormats.td
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrInfo.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrInfo.td
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrThumb.td
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrThumb2.td
llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
llvm/branches/exception-handling-rewrite/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
llvm/branches/exception-handling-rewrite/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
llvm/branches/exception-handling-rewrite/lib/Target/ARM/Thumb2SizeReduction.cpp
llvm/branches/exception-handling-rewrite/lib/Target/CppBackend/CPPBackend.cpp
llvm/branches/exception-handling-rewrite/lib/Target/X86/AsmParser/X86AsmParser.cpp
llvm/branches/exception-handling-rewrite/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
llvm/branches/exception-handling-rewrite/lib/Target/X86/README.txt
llvm/branches/exception-handling-rewrite/lib/Target/X86/Utils/X86ShuffleDecode.cpp
llvm/branches/exception-handling-rewrite/lib/Target/X86/X86CodeEmitter.cpp
llvm/branches/exception-handling-rewrite/lib/Target/X86/X86FrameLowering.cpp
llvm/branches/exception-handling-rewrite/lib/Target/X86/X86ISelLowering.cpp
llvm/branches/exception-handling-rewrite/lib/Target/X86/X86ISelLowering.h
llvm/branches/exception-handling-rewrite/lib/Target/X86/X86InstrFragmentsSIMD.td
llvm/branches/exception-handling-rewrite/lib/Target/X86/X86InstrSSE.td
llvm/branches/exception-handling-rewrite/lib/Transforms/IPO/IPO.cpp
llvm/branches/exception-handling-rewrite/lib/Transforms/Instrumentation/GCOVProfiling.cpp
llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/DeadStoreElimination.cpp
llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/LowerAtomic.cpp
llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/SCCP.cpp
llvm/branches/exception-handling-rewrite/lib/VMCore/Instruction.cpp
llvm/branches/exception-handling-rewrite/test/CodeGen/ARM/sxt_rot.ll
llvm/branches/exception-handling-rewrite/test/MC/ARM/arm_instructions.s
llvm/branches/exception-handling-rewrite/test/MC/ARM/basic-arm-instructions.s
llvm/branches/exception-handling-rewrite/test/MC/ARM/diagnostics.s
llvm/branches/exception-handling-rewrite/tools/gold/gold-plugin.cpp
llvm/branches/exception-handling-rewrite/tools/llvm-mc/llvm-mc.cpp
llvm/branches/exception-handling-rewrite/unittests/ADT/DAGDeltaAlgorithmTest.cpp
llvm/branches/exception-handling-rewrite/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp
llvm/branches/exception-handling-rewrite/utils/TableGen/EDEmitter.cpp
llvm/branches/exception-handling-rewrite/utils/unittest/CMakeLists.txt
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/README.LLVM
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-death-test.cc
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-filepath.cc
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-port.cc
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-test-part.cc
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-typed-test.cc
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest.cc
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-death-test.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-message.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-param-test.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-spi.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-test-part.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-typed-test.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest_pred_impl.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-port.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-string.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h
llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h
Propchange: llvm/branches/exception-handling-rewrite/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Jul 27 13:40:48 2011
@@ -1,3 +1,3 @@
/llvm/branches/Apple/Pertwee:110850,110961
/llvm/branches/type-system-rewrite:133420-134817
-/llvm/trunk:135898-136038
+/llvm/trunk:135898-136231
Modified: llvm/branches/exception-handling-rewrite/docs/CodeGenerator.html
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/docs/CodeGenerator.html?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/docs/CodeGenerator.html (original)
+++ llvm/branches/exception-handling-rewrite/docs/CodeGenerator.html Wed Jul 27 13:40:48 2011
@@ -1768,22 +1768,28 @@
different register allocators:</p>
<ul>
- <li><i>Linear Scan</i> — <i>The default allocator</i>. This is the
- well-know linear scan register allocator. Whereas the
- <i>Simple</i> and <i>Local</i> algorithms use a direct mapping
- implementation technique, the <i>Linear Scan</i> implementation
- uses a spiller in order to place load and stores.</li>
-
<li><i>Fast</i> — This register allocator is the default for debug
builds. It allocates registers on a basic block level, attempting to keep
values in registers and reusing registers as appropriate.</li>
+ <li><i>Basic</i> — This is an incremental approach to register
+ allocation. Live ranges are assigned to registers one at a time in
+ an order that is driven by heuristics. Since code can be rewritten
+ on-the-fly during allocation, this framework allows interesting
+ allocators to be developed as extensions. It is not itself a
+ production register allocator but is a potentially useful
+ stand-alone mode for triaging bugs and as a performance baseline.
+
+ <li><i>Greedy</i> — <i>The default allocator</i>. This is a
+ highly tuned implementation of the <i>Basic</i> allocator that
+ incorporates global live range splitting. This allocator works hard
+ to minimize the cost of spill code.
+
<li><i>PBQP</i> — A Partitioned Boolean Quadratic Programming (PBQP)
based register allocator. This allocator works by constructing a PBQP
problem representing the register allocation problem under consideration,
solving this using a PBQP solver, and mapping the solution back to a
register assignment.</li>
-
</ul>
<p>The type of register allocator used in <tt>llc</tt> can be chosen with the
@@ -1813,12 +1819,14 @@
<div>
-<p>Unwinding out of a function is done virually via DWARF encodings. These
- encodings exist in two forms: a Common Information Entry (CIE) and a Frame
- Description Entry (FDE). These two tables contain the information necessary
- for the unwinder to restore the state of the computer to before the function
- was called. However, the tables themselves are rather large. LLVM can use a
- "compact unwind" encoding to represent the virtual unwinding.</p>
+<p>Throwing an exception requires <em>unwinding</em> out of a function. The
+ information on how to unwind a given function is traditionally expressed in
+ DWARF unwind (a.k.a. frame) info. But that format was originally developed
+ for debuggers to backtrace, and each Frame Description Entry (FDE) requires
+ ~20-30 bytes per function. There is also the cost of mapping from an address
+ in a function to the corresponding FDE at runtime. An alternative unwind
+ encoding is called <em>compact unwind</em> and requires just 4-bytes per
+ function.</p>
<p>The compact unwind encoding is a 32-bit value, which is encoded in an
architecture-specific way. It specifies which registers to restore and from
@@ -1834,7 +1842,7 @@
<p>For X86, there are three modes for the compact unwind encoding:</p>
-<ul>
+<dl>
<dt><i>Function with a Frame Pointer (<code>EBP</code> or <code>RBP</code>)</i></dt>
<dd><p><code>EBP/RBP</code>-based frame, where <code>EBP/RBP</code> is pushed
onto the stack immediately after the return address,
@@ -1845,10 +1853,11 @@
more into the PC. All non-volatile registers that need to be restored must
have been saved in a small range on the stack that
starts <code>EBP-4</code> to <code>EBP-1020</code> (<code>RBP-8</code>
- to <code>RBP-1020</code>). The offset (divided by 4) is encoded in bits
- 16-23 (mask: <code>0x00FF0000</code>). The registers saved are encoded in
- bits 0-14 (mask: <code>0x00007FFF</code>) as five 3-bit entries from the
- following table:</p>
+ to <code>RBP-1020</code>). The offset (divided by 4 in 32-bit mode and 8
+ in 64-bit mode) is encoded in bits 16-23 (mask: <code>0x00FF0000</code>).
+ The registers saved are encoded in bits 0-14
+ (mask: <code>0x00007FFF</code>) as five 3-bit entries from the following
+ table:</p>
<table border="1" cellspacing="0">
<tr>
<th>Compact Number</th>
@@ -1895,13 +1904,14 @@
to the <code>ESP/RSP</code>. Then the return is done by popping the stack
into the PC. All non-volatile registers that need to be restored must have
been saved on the stack immediately after the return address. The stack
- size (divided by 4) is encoded in bits 16-23
- (mask: <code>0x00FF0000</code>). There is a maximum stack size of 1024
- bytes. The number of registers saved is encoded in bits 9-12
- (mask: <code>0x00001C00</code>). Bits 0-9 (mask:
- <code>0x000003FF</code>) contain which registers were saved and their
- order. (See the <code>encodeCompactUnwindRegistersWithoutFrame()</code>
- function in <code>lib/Target/X86FrameLowering.cpp</code> for the encoding
+ size (divided by 4 in 32-bit mode and 8 in 64-bit mode) is encoded in bits
+ 16-23 (mask: <code>0x00FF0000</code>). There is a maximum stack size of
+ 1024 bytes in 32-bit mode and 2048 in 64-bit mode. The number of registers
+ saved is encoded in bits 9-12 (mask: <code>0x00001C00</code>). Bits 0-9
+ (mask: <code>0x000003FF</code>) contain which registers were saved and
+ their order. (See
+ the <code>encodeCompactUnwindRegistersWithoutFrame()</code> function
+ in <code>lib/Target/X86FrameLowering.cpp</code> for the encoding
algorithm.)</p></dd>
<dt><i>Frameless with a Large Constant Stack Size (<code>EBP</code>
@@ -1912,7 +1922,7 @@
$nnnnnn, %esp</code>" in its prolog. The compact encoding contains the
offset to the <code>$nnnnnn</code> value in the function in bits 9-12
(mask: <code>0x00001C00</code>).</p></dd>
-</ul>
+</dl>
</div>
Modified: llvm/branches/exception-handling-rewrite/docs/LangRef.html
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/docs/LangRef.html?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/docs/LangRef.html (original)
+++ llvm/branches/exception-handling-rewrite/docs/LangRef.html Wed Jul 27 13:40:48 2011
@@ -3012,7 +3012,8 @@
<h5>Syntax:</h5>
<pre>
- br i1 <cond>, label <iftrue>, label <iffalse><br> br label <dest> <i>; Unconditional branch</i>
+ br i1 <cond>, label <iftrue>, label <iffalse>
+ br label <dest> <i>; Unconditional branch</i>
</pre>
<h5>Overview:</h5>
@@ -4366,7 +4367,7 @@
<h5>Syntax:</h5>
<pre>
- <result> = insertvalue <aggregate type> <val>, <ty> <elt>, <idx>{, <idx>}* <i>; yields <aggregate type></i>
+ <result> = insertvalue <aggregate type> <val>, <ty> <elt>, <idx>{, <idx>}* <i>; yields <aggregate type></i>
</pre>
<h5>Overview:</h5>
Modified: llvm/branches/exception-handling-rewrite/docs/SourceLevelDebugging.html
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/docs/SourceLevelDebugging.html?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/docs/SourceLevelDebugging.html (original)
+++ llvm/branches/exception-handling-rewrite/docs/SourceLevelDebugging.html Wed Jul 27 13:40:48 2011
@@ -750,7 +750,9 @@
metadata, ;; Reference to file where defined
i32, ;; 24 bit - Line number where defined
;; 8 bit - Argument number. 1 indicates 1st argument.
- metadata ;; Type descriptor
+ metadata, ;; Type descriptor
+ i32, ;; flags
+ metadata ;; (optional) Reference to inline location
}
</pre>
</div>
Modified: llvm/branches/exception-handling-rewrite/include/llvm-c/Core.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm-c/Core.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm-c/Core.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm-c/Core.h Wed Jul 27 13:40:48 2011
@@ -159,34 +159,34 @@
LLVMFence = 31,
/* Cast Operators */
- LLVMTrunc = 32,
- LLVMZExt = 33,
- LLVMSExt = 34,
- LLVMFPToUI = 35,
- LLVMFPToSI = 36,
- LLVMUIToFP = 37,
- LLVMSIToFP = 38,
- LLVMFPTrunc = 39,
- LLVMFPExt = 40,
- LLVMPtrToInt = 41,
- LLVMIntToPtr = 42,
- LLVMBitCast = 43,
+ LLVMTrunc = 33,
+ LLVMZExt = 34,
+ LLVMSExt = 35,
+ LLVMFPToUI = 36,
+ LLVMFPToSI = 37,
+ LLVMUIToFP = 38,
+ LLVMSIToFP = 39,
+ LLVMFPTrunc = 40,
+ LLVMFPExt = 41,
+ LLVMPtrToInt = 42,
+ LLVMIntToPtr = 43,
+ LLVMBitCast = 44,
/* Other Operators */
- LLVMICmp = 44,
- LLVMFCmp = 45,
- LLVMPHI = 46,
- LLVMCall = 47,
- LLVMSelect = 48,
+ LLVMICmp = 45,
+ LLVMFCmp = 46,
+ LLVMPHI = 47,
+ LLVMCall = 48,
+ LLVMSelect = 49,
/* UserOp1 */
/* UserOp2 */
- LLVMVAArg = 51,
- LLVMExtractElement = 52,
- LLVMInsertElement = 53,
- LLVMShuffleVector = 54,
- LLVMExtractValue = 55,
- LLVMInsertValue = 56,
- LLVMLandingPad = 57
+ LLVMVAArg = 52,
+ LLVMExtractElement = 53,
+ LLVMInsertElement = 54,
+ LLVMShuffleVector = 55,
+ LLVMExtractValue = 56,
+ LLVMInsertValue = 57,
+ LLVMLandingPad = 58
} LLVMOpcode;
typedef enum {
Modified: llvm/branches/exception-handling-rewrite/include/llvm-c/Transforms/IPO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm-c/Transforms/IPO.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm-c/Transforms/IPO.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm-c/Transforms/IPO.h Wed Jul 27 13:40:48 2011
@@ -36,6 +36,9 @@
/** See llvm::createFunctionInliningPass function. */
void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM);
+/** See llvm::createAlwaysInlinerPass function. */
+void LLVMAddAlwaysInlinerPass(LLVMPassManagerRef PM);
+
/** See llvm::createGlobalDCEPass function. */
void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM);
@@ -57,9 +60,6 @@
/** See llvm::createInternalizePass function. */
void LLVMAddInternalizePass(LLVMPassManagerRef, unsigned AllButMain);
-// FIXME: Remove in LLVM 3.0.
-void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM);
-
/** See llvm::createStripDeadPrototypesPass function. */
void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM);
Modified: llvm/branches/exception-handling-rewrite/include/llvm/ADT/SCCIterator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/ADT/SCCIterator.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/ADT/SCCIterator.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/ADT/SCCIterator.h Wed Jul 27 13:40:48 2011
@@ -87,7 +87,7 @@
DFSVisitOne(childN);
continue;
}
-
+
unsigned childNum = nodeVisitNumbers[childN];
if (MinVisitNumStack.back() > childNum)
MinVisitNumStack.back() = childNum;
@@ -114,7 +114,7 @@
if (minVisitNum != nodeVisitNumbers[visitingN])
continue;
-
+
// A full SCC is on the SCCNodeStack! It includes all nodes below
// visitingN on the stack. Copy those nodes to CurrentSCC,
// reset their minVisit values, and return (this suspends
@@ -183,7 +183,7 @@
return true;
return false;
}
-
+
/// ReplaceNode - This informs the scc_iterator that the specified Old node
/// has been deleted, and New is to be used in its place.
void ReplaceNode(NodeType *Old, NodeType *New) {
Modified: llvm/branches/exception-handling-rewrite/include/llvm/ADT/Triple.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/ADT/Triple.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/ADT/Triple.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/ADT/Triple.h Wed Jul 27 13:40:48 2011
@@ -82,6 +82,7 @@
DragonFly,
FreeBSD,
IOS,
+ KFreeBSD,
Linux,
Lv2, // PS3
MacOSX,
Modified: llvm/branches/exception-handling-rewrite/include/llvm/Analysis/AliasAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/Analysis/AliasAnalysis.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/Analysis/AliasAnalysis.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/Analysis/AliasAnalysis.h Wed Jul 27 13:40:48 2011
@@ -341,6 +341,7 @@
case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc);
case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc);
case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc);
+ case Instruction::Fence: return getModRefInfo((const FenceInst*)I, Loc);
case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc);
case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc);
default: return NoModRef;
@@ -406,6 +407,19 @@
return getModRefInfo(S, Location(P, Size));
}
+ /// getModRefInfo (for fences) - Return whether information about whether
+ /// a particular store modifies or reads the specified memory location.
+ ModRefResult getModRefInfo(const FenceInst *S, const Location &Loc) {
+ // Conservatively correct. (We could possibly be a bit smarter if
+ // Loc is a alloca that doesn't escape.)
+ return ModRef;
+ }
+
+ /// getModRefInfo (for fences) - A convenience wrapper.
+ ModRefResult getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size){
+ return getModRefInfo(S, Location(P, Size));
+ }
+
/// getModRefInfo (for va_args) - Return whether information about whether
/// a particular va_arg modifies or reads the specified memory location.
ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc);
Modified: llvm/branches/exception-handling-rewrite/include/llvm/Analysis/AliasSetTracker.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/Analysis/AliasSetTracker.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/Analysis/AliasSetTracker.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/Analysis/AliasSetTracker.h Wed Jul 27 13:40:48 2011
@@ -111,8 +111,8 @@
AliasSet *Forward; // Forwarding pointer.
AliasSet *Next, *Prev; // Doubly linked list of AliasSets.
- // All calls & invokes in this alias set.
- std::vector<AssertingVH<Instruction> > CallSites;
+ // All instructions without a specific address in this alias set.
+ std::vector<AssertingVH<Instruction> > UnknownInsts;
// RefCount - Number of nodes pointing to this AliasSet plus the number of
// AliasSets forwarding to it.
@@ -147,9 +147,9 @@
removeFromTracker(AST);
}
- CallSite getCallSite(unsigned i) const {
- assert(i < CallSites.size());
- return CallSite(CallSites[i]);
+ Instruction *getUnknownInst(unsigned i) const {
+ assert(i < UnknownInsts.size());
+ return UnknownInsts[i];
}
public:
@@ -253,12 +253,12 @@
void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size,
const MDNode *TBAAInfo,
bool KnownMustAlias = false);
- void addCallSite(CallSite CS, AliasAnalysis &AA);
- void removeCallSite(CallSite CS) {
- for (size_t i = 0, e = CallSites.size(); i != e; ++i)
- if (CallSites[i] == CS.getInstruction()) {
- CallSites[i] = CallSites.back();
- CallSites.pop_back();
+ void addUnknownInst(Instruction *I, AliasAnalysis &AA);
+ void removeUnknownInst(Instruction *I) {
+ for (size_t i = 0, e = UnknownInsts.size(); i != e; ++i)
+ if (UnknownInsts[i] == I) {
+ UnknownInsts[i] = UnknownInsts.back();
+ UnknownInsts.pop_back();
--i; --e; // Revisit the moved entry.
}
}
@@ -269,7 +269,7 @@
///
bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo,
AliasAnalysis &AA) const;
- bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const;
+ bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const;
};
inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) {
@@ -326,12 +326,10 @@
bool add(LoadInst *LI);
bool add(StoreInst *SI);
bool add(VAArgInst *VAAI);
- bool add(CallSite CS); // Call/Invoke instructions
- bool add(CallInst *CI) { return add(CallSite(CI)); }
- bool add(InvokeInst *II) { return add(CallSite(II)); }
bool add(Instruction *I); // Dispatch to one of the other add methods...
void add(BasicBlock &BB); // Add all instructions in basic block
void add(const AliasSetTracker &AST); // Add alias relations from another AST
+ bool addUnknown(Instruction *I);
/// remove methods - These methods are used to remove all entries that might
/// be aliased by the specified instruction. These methods return true if any
@@ -341,11 +339,9 @@
bool remove(LoadInst *LI);
bool remove(StoreInst *SI);
bool remove(VAArgInst *VAAI);
- bool remove(CallSite CS);
- bool remove(CallInst *CI) { return remove(CallSite(CI)); }
- bool remove(InvokeInst *II) { return remove(CallSite(II)); }
bool remove(Instruction *I);
void remove(AliasSet &AS);
+ bool removeUnknown(Instruction *I);
void clear();
@@ -429,7 +425,7 @@
AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size,
const MDNode *TBAAInfo);
- AliasSet *findAliasSetForCallSite(CallSite CS);
+ AliasSet *findAliasSetForUnknownInst(Instruction *Inst);
};
inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) {
Modified: llvm/branches/exception-handling-rewrite/include/llvm/Analysis/BlockFrequencyImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/Analysis/BlockFrequencyImpl.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/Analysis/BlockFrequencyImpl.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/Analysis/BlockFrequencyImpl.h Wed Jul 27 13:40:48 2011
@@ -160,7 +160,7 @@
unsigned a = RPO[Src];
unsigned b = RPO[Dst];
- return a > b;
+ return a >= b;
}
/// getSingleBlockPred - return single BB block predecessor or NULL if
Modified: llvm/branches/exception-handling-rewrite/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/Analysis/ScalarEvolution.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/Analysis/ScalarEvolution.h Wed Jul 27 13:40:48 2011
@@ -241,31 +241,93 @@
///
ValueExprMapType ValueExprMap;
+ /// ExitLimit - Information about the number of loop iterations for
+ /// which a loop exit's branch condition evaluates to the not-taken path.
+ /// This is a temporary pair of exact and max expressions that are
+ /// eventually summarized in ExitNotTakenInfo and BackedgeTakenInfo.
+ struct ExitLimit {
+ const SCEV *Exact;
+ const SCEV *Max;
+
+ /*implicit*/ ExitLimit(const SCEV *E) : Exact(E), Max(E) {}
+
+ ExitLimit(const SCEV *E, const SCEV *M) : Exact(E), Max(M) {}
+
+ /// hasAnyInfo - Test whether this ExitLimit contains any computed
+ /// information, or whether it's all SCEVCouldNotCompute values.
+ bool hasAnyInfo() const {
+ return !isa<SCEVCouldNotCompute>(Exact) ||
+ !isa<SCEVCouldNotCompute>(Max);
+ }
+ };
+
+ /// ExitNotTakenInfo - Information about the number of times a particular
+ /// loop exit may be reached before exiting the loop.
+ struct ExitNotTakenInfo {
+ BasicBlock *ExitBlock;
+ const SCEV *ExactNotTaken;
+ PointerIntPair<ExitNotTakenInfo*, 1> NextExit;
+
+ ExitNotTakenInfo() : ExitBlock(0), ExactNotTaken(0) {}
+
+ /// isCompleteList - Return true if all loop exits are computable.
+ bool isCompleteList() const {
+ return NextExit.getInt() == 0;
+ }
+
+ void setIncomplete() { NextExit.setInt(1); }
+
+ /// getNextExit - Return a pointer to the next exit's not-taken info.
+ ExitNotTakenInfo *getNextExit() const {
+ return NextExit.getPointer();
+ }
+
+ void setNextExit(ExitNotTakenInfo *ENT) { NextExit.setPointer(ENT); }
+ };
+
/// BackedgeTakenInfo - Information about the backedge-taken count
/// of a loop. This currently includes an exact count and a maximum count.
///
- struct BackedgeTakenInfo {
- /// Exact - An expression indicating the exact backedge-taken count of
- /// the loop if it is known, or a SCEVCouldNotCompute otherwise.
- const SCEV *Exact;
+ class BackedgeTakenInfo {
+ /// ExitNotTaken - A list of computable exits and their not-taken counts.
+ /// Loops almost never have more than one computable exit.
+ ExitNotTakenInfo ExitNotTaken;
/// Max - An expression indicating the least maximum backedge-taken
/// count of the loop that is known, or a SCEVCouldNotCompute.
const SCEV *Max;
- /*implicit*/ BackedgeTakenInfo(const SCEV *exact) :
- Exact(exact), Max(exact) {}
+ public:
+ BackedgeTakenInfo() : Max(0) {}
- BackedgeTakenInfo(const SCEV *exact, const SCEV *max) :
- Exact(exact), Max(max) {}
+ /// Initialize BackedgeTakenInfo from a list of exact exit counts.
+ BackedgeTakenInfo(
+ SmallVectorImpl< std::pair<BasicBlock *, const SCEV *> > &ExitCounts,
+ bool Complete, const SCEV *MaxCount);
/// hasAnyInfo - Test whether this BackedgeTakenInfo contains any
/// computed information, or whether it's all SCEVCouldNotCompute
/// values.
bool hasAnyInfo() const {
- return !isa<SCEVCouldNotCompute>(Exact) ||
- !isa<SCEVCouldNotCompute>(Max);
+ return ExitNotTaken.ExitBlock || !isa<SCEVCouldNotCompute>(Max);
}
+
+ /// getExact - Return an expression indicating the exact backedge-taken
+ /// count of the loop if it is known, or SCEVCouldNotCompute
+ /// otherwise. This is the number of times the loop header can be
+ /// guaranteed to execute, minus one.
+ const SCEV *getExact(ScalarEvolution *SE) const;
+
+ /// getExact - Return the number of times this loop exit may fall through
+ /// to the back edge. The loop is guaranteed not to exit via this block
+ /// before this number of iterations, but may exit via another block.
+ const SCEV *getExact(BasicBlock *ExitBlock, ScalarEvolution *SE) const;
+
+ /// getMax - Get the max backedge taken count for the loop.
+ const SCEV *getMax(ScalarEvolution *SE) const;
+
+ /// clear - Invalidate this result and free associated memory.
+ void clear();
};
/// BackedgeTakenCounts - Cache the backedge-taken count of the loops for
@@ -365,64 +427,59 @@
/// loop will iterate.
BackedgeTakenInfo ComputeBackedgeTakenCount(const Loop *L);
- /// ComputeBackedgeTakenCountFromExit - Compute the number of times the
- /// backedge of the specified loop will execute if it exits via the
- /// specified block.
- BackedgeTakenInfo ComputeBackedgeTakenCountFromExit(const Loop *L,
- BasicBlock *ExitingBlock);
-
- /// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the
- /// backedge of the specified loop will execute if its exit condition
- /// were a conditional branch of ExitCond, TBB, and FBB.
- BackedgeTakenInfo
- ComputeBackedgeTakenCountFromExitCond(const Loop *L,
- Value *ExitCond,
- BasicBlock *TBB,
- BasicBlock *FBB);
-
- /// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of
- /// times the backedge of the specified loop will execute if its exit
- /// condition were a conditional branch of the ICmpInst ExitCond, TBB,
- /// and FBB.
- BackedgeTakenInfo
- ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L,
- ICmpInst *ExitCond,
- BasicBlock *TBB,
- BasicBlock *FBB);
+ /// ComputeExitLimit - Compute the number of times the backedge of the
+ /// specified loop will execute if it exits via the specified block.
+ ExitLimit ComputeExitLimit(const Loop *L, BasicBlock *ExitingBlock);
+
+ /// ComputeExitLimitFromCond - Compute the number of times the backedge of
+ /// the specified loop will execute if its exit condition were a conditional
+ /// branch of ExitCond, TBB, and FBB.
+ ExitLimit ComputeExitLimitFromCond(const Loop *L,
+ Value *ExitCond,
+ BasicBlock *TBB,
+ BasicBlock *FBB);
+
+ /// ComputeExitLimitFromICmp - Compute the number of times the backedge of
+ /// the specified loop will execute if its exit condition were a conditional
+ /// branch of the ICmpInst ExitCond, TBB, and FBB.
+ ExitLimit ComputeExitLimitFromICmp(const Loop *L,
+ ICmpInst *ExitCond,
+ BasicBlock *TBB,
+ BasicBlock *FBB);
- /// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition
+ /// ComputeLoadConstantCompareExitLimit - Given an exit condition
/// of 'icmp op load X, cst', try to see if we can compute the
/// backedge-taken count.
- BackedgeTakenInfo
- ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI,
- Constant *RHS,
- const Loop *L,
- ICmpInst::Predicate p);
+ ExitLimit ComputeLoadConstantCompareExitLimit(LoadInst *LI,
+ Constant *RHS,
+ const Loop *L,
+ ICmpInst::Predicate p);
- /// ComputeBackedgeTakenCountExhaustively - If the loop is known to execute
- /// a constant number of times (the condition evolves only from constants),
+ /// ComputeExitCountExhaustively - If the loop is known to execute a
+ /// constant number of times (the condition evolves only from constants),
/// try to evaluate a few iterations of the loop until we get the exit
/// condition gets a value of ExitWhen (true or false). If we cannot
- /// evaluate the backedge-taken count of the loop, return CouldNotCompute.
- const SCEV *ComputeBackedgeTakenCountExhaustively(const Loop *L,
- Value *Cond,
- bool ExitWhen);
+ /// evaluate the exit count of the loop, return CouldNotCompute.
+ const SCEV *ComputeExitCountExhaustively(const Loop *L,
+ Value *Cond,
+ bool ExitWhen);
- /// HowFarToZero - Return the number of times a backedge comparing the
- /// specified value to zero will execute. If not computable, return
+ /// HowFarToZero - Return the number of times an exit condition comparing
+ /// the specified value to zero will execute. If not computable, return
/// CouldNotCompute.
- BackedgeTakenInfo HowFarToZero(const SCEV *V, const Loop *L);
+ ExitLimit HowFarToZero(const SCEV *V, const Loop *L);
- /// HowFarToNonZero - Return the number of times a backedge checking the
- /// specified value for nonzero will execute. If not computable, return
+ /// HowFarToNonZero - Return the number of times an exit condition checking
+ /// the specified value for nonzero will execute. If not computable, return
/// CouldNotCompute.
- BackedgeTakenInfo HowFarToNonZero(const SCEV *V, const Loop *L);
+ ExitLimit HowFarToNonZero(const SCEV *V, const Loop *L);
- /// HowManyLessThans - Return the number of times a backedge containing the
- /// specified less-than comparison will execute. If not computable, return
- /// CouldNotCompute. isSigned specifies whether the less-than is signed.
- BackedgeTakenInfo HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
- const Loop *L, bool isSigned);
+ /// HowManyLessThans - Return the number of times an exit condition
+ /// containing the specified less-than comparison will execute. If not
+ /// computable, return CouldNotCompute. isSigned specifies whether the
+ /// less-than is signed.
+ ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
+ const Loop *L, bool isSigned);
/// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB
/// (which may not be an immediate predecessor) which has exactly one
@@ -653,6 +710,11 @@
bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
+ // getExitCount - Get the expression for the number of loop iterations for
+ // which this loop is guaranteed not to exit via ExitBlock. Otherwise return
+ // SCEVCouldNotCompute.
+ const SCEV *getExitCount(Loop *L, BasicBlock *ExitBlock);
+
/// getBackedgeTakenCount - If the specified loop has a predictable
/// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute
/// object. The backedge-taken count is the number of times the loop header
Modified: llvm/branches/exception-handling-rewrite/include/llvm/Instruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/Instruction.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/Instruction.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/Instruction.h Wed Jul 27 13:40:48 2011
@@ -223,6 +223,13 @@
///
bool mayReadFromMemory() const;
+ /// mayReadOrWriteMemory - Return true if this instruction may read or
+ /// write memory.
+ ///
+ bool mayReadOrWriteMemory() const {
+ return mayReadFromMemory() || mayWriteToMemory();
+ }
+
/// mayThrow - Return true if this instruction may throw an exception.
///
bool mayThrow() const;
Modified: llvm/branches/exception-handling-rewrite/include/llvm/MC/MCAsmInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/MC/MCAsmInfo.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/MC/MCAsmInfo.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/MC/MCAsmInfo.h Wed Jul 27 13:40:48 2011
@@ -117,6 +117,13 @@
const char *InlineAsmStart; // Defaults to "#APP\n"
const char *InlineAsmEnd; // Defaults to "#NO_APP\n"
+ /// Code16Directive, Code32Directive, Code64Directive - These are assembly
+ /// directives that tells the assembler to interpret the following
+ /// instructions differently.
+ const char *Code16Directive; // Defaults to ".code16"
+ const char *Code32Directive; // Defaults to ".code32"
+ const char *Code64Directive; // Defaults to ".code64"
+
/// AssemblerDialect - Which dialect of an assembler variant to use.
unsigned AssemblerDialect; // Defaults to 0
@@ -423,6 +430,15 @@
const char *getInlineAsmEnd() const {
return InlineAsmEnd;
}
+ const char *getCode16Directive() const {
+ return Code16Directive;
+ }
+ const char *getCode32Directive() const {
+ return Code32Directive;
+ }
+ const char *getCode64Directive() const {
+ return Code64Directive;
+ }
unsigned getAssemblerDialect() const {
return AssemblerDialect;
}
Modified: llvm/branches/exception-handling-rewrite/include/llvm/MC/MCAsmInfoDarwin.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/MC/MCAsmInfoDarwin.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/MC/MCAsmInfoDarwin.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/MC/MCAsmInfoDarwin.h Wed Jul 27 13:40:48 2011
@@ -18,11 +18,6 @@
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
- class GlobalValue;
- class GlobalVariable;
- class Type;
- class Mangler;
-
struct MCAsmInfoDarwin : public MCAsmInfo {
explicit MCAsmInfoDarwin();
};
Modified: llvm/branches/exception-handling-rewrite/include/llvm/MC/MCDirectives.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/MC/MCDirectives.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/MC/MCDirectives.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/MC/MCDirectives.h Wed Jul 27 13:40:48 2011
@@ -47,8 +47,9 @@
enum MCAssemblerFlag {
MCAF_SyntaxUnified, ///< .syntax (ARM/ELF)
MCAF_SubsectionsViaSymbols, ///< .subsections_via_symbols (MachO)
- MCAF_Code16, ///< .code 16
- MCAF_Code32 ///< .code 32
+ MCAF_Code16, ///< .code16 (X86) / .code 16 (ARM)
+ MCAF_Code32, ///< .code32 (X86) / .code 32 (ARM)
+ MCAF_Code64 ///< .code64 (X86)
};
} // end namespace llvm
Modified: llvm/branches/exception-handling-rewrite/include/llvm/Support/BlockFrequency.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/Support/BlockFrequency.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/Support/BlockFrequency.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/Support/BlockFrequency.h Wed Jul 27 13:40:48 2011
@@ -24,9 +24,6 @@
uint64_t Frequency;
- static void mult96bit(uint64_t freq, uint32_t N, uint64_t W[2]);
- static uint64_t div96bit(uint64_t W[2], uint32_t D);
-
public:
BlockFrequency(uint64_t Freq = 0) : Frequency(Freq) { }
Modified: llvm/branches/exception-handling-rewrite/include/llvm/Transforms/IPO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/include/llvm/Transforms/IPO.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/include/llvm/Transforms/IPO.h (original)
+++ llvm/branches/exception-handling-rewrite/include/llvm/Transforms/IPO.h Wed Jul 27 13:40:48 2011
@@ -81,7 +81,7 @@
//===----------------------------------------------------------------------===//
-/// createGVExtractionPass - If deleteFn is true, this pass deletes as
+/// createGVExtractionPass - If deleteFn is true, this pass deletes
/// the specified global values. Otherwise, it deletes as much of the module as
/// possible, except for the global values specified.
///
Modified: llvm/branches/exception-handling-rewrite/lib/Analysis/AliasSetTracker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Analysis/AliasSetTracker.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Analysis/AliasSetTracker.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Analysis/AliasSetTracker.cpp Wed Jul 27 13:40:48 2011
@@ -56,12 +56,12 @@
AliasTy = MayAlias;
}
- if (CallSites.empty()) { // Merge call sites...
- if (!AS.CallSites.empty())
- std::swap(CallSites, AS.CallSites);
- } else if (!AS.CallSites.empty()) {
- CallSites.insert(CallSites.end(), AS.CallSites.begin(), AS.CallSites.end());
- AS.CallSites.clear();
+ if (UnknownInsts.empty()) { // Merge call sites...
+ if (!AS.UnknownInsts.empty())
+ std::swap(UnknownInsts, AS.UnknownInsts);
+ } else if (!AS.UnknownInsts.empty()) {
+ UnknownInsts.insert(UnknownInsts.end(), AS.UnknownInsts.begin(), AS.UnknownInsts.end());
+ AS.UnknownInsts.clear();
}
AS.Forward = this; // Forward across AS now...
@@ -123,13 +123,12 @@
addRef(); // Entry points to alias set.
}
-void AliasSet::addCallSite(CallSite CS, AliasAnalysis &AA) {
- CallSites.push_back(CS.getInstruction());
+void AliasSet::addUnknownInst(Instruction *I, AliasAnalysis &AA) {
+ UnknownInsts.push_back(I);
- AliasAnalysis::ModRefBehavior Behavior = AA.getModRefBehavior(CS);
- if (Behavior == AliasAnalysis::DoesNotAccessMemory)
+ if (!I->mayReadOrWriteMemory())
return;
- if (AliasAnalysis::onlyReadsMemory(Behavior)) {
+ if (!I->mayWriteToMemory()) {
AliasTy = MayAlias;
AccessTy |= Refs;
return;
@@ -147,7 +146,7 @@
const MDNode *TBAAInfo,
AliasAnalysis &AA) const {
if (AliasTy == MustAlias) {
- assert(CallSites.empty() && "Illegal must alias set!");
+ assert(UnknownInsts.empty() && "Illegal must alias set!");
// If this is a set of MustAliases, only check to see if the pointer aliases
// SOME value in the set.
@@ -167,10 +166,10 @@
I.getTBAAInfo())))
return true;
- // Check the call sites list and invoke list...
- if (!CallSites.empty()) {
- for (unsigned i = 0, e = CallSites.size(); i != e; ++i)
- if (AA.getModRefInfo(CallSites[i],
+ // Check the unknown instructions...
+ if (!UnknownInsts.empty()) {
+ for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i)
+ if (AA.getModRefInfo(UnknownInsts[i],
AliasAnalysis::Location(Ptr, Size, TBAAInfo)) !=
AliasAnalysis::NoModRef)
return true;
@@ -179,18 +178,20 @@
return false;
}
-bool AliasSet::aliasesCallSite(CallSite CS, AliasAnalysis &AA) const {
- if (AA.doesNotAccessMemory(CS))
+bool AliasSet::aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const {
+ if (!Inst->mayReadOrWriteMemory())
return false;
- for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
- if (AA.getModRefInfo(getCallSite(i), CS) != AliasAnalysis::NoModRef ||
- AA.getModRefInfo(CS, getCallSite(i)) != AliasAnalysis::NoModRef)
+ for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) {
+ CallSite C1 = getUnknownInst(i), C2 = Inst;
+ if (!C1 || !C2 ||
+ AA.getModRefInfo(C1, C2) != AliasAnalysis::NoModRef ||
+ AA.getModRefInfo(C2, C1) != AliasAnalysis::NoModRef)
return true;
}
for (iterator I = begin(), E = end(); I != E; ++I)
- if (AA.getModRefInfo(CS, I.getPointer(), I.getSize()) !=
+ if (AA.getModRefInfo(Inst, I.getPointer(), I.getSize()) !=
AliasAnalysis::NoModRef)
return true;
@@ -244,10 +245,10 @@
-AliasSet *AliasSetTracker::findAliasSetForCallSite(CallSite CS) {
+AliasSet *AliasSetTracker::findAliasSetForUnknownInst(Instruction *Inst) {
AliasSet *FoundSet = 0;
for (iterator I = begin(), E = end(); I != E; ++I) {
- if (I->Forward || !I->aliasesCallSite(CS, AA))
+ if (I->Forward || !I->aliasesUnknownInst(Inst, AA))
continue;
if (FoundSet == 0) // If this is the first alias set ptr can go into.
@@ -325,20 +326,20 @@
}
-bool AliasSetTracker::add(CallSite CS) {
- if (isa<DbgInfoIntrinsic>(CS.getInstruction()))
+bool AliasSetTracker::addUnknown(Instruction *Inst) {
+ if (isa<DbgInfoIntrinsic>(Inst))
return true; // Ignore DbgInfo Intrinsics.
- if (AA.doesNotAccessMemory(CS))
+ if (!Inst->mayReadOrWriteMemory())
return true; // doesn't alias anything
- AliasSet *AS = findAliasSetForCallSite(CS);
+ AliasSet *AS = findAliasSetForUnknownInst(Inst);
if (AS) {
- AS->addCallSite(CS, AA);
+ AS->addUnknownInst(Inst, AA);
return false;
}
AliasSets.push_back(new AliasSet());
AS = &AliasSets.back();
- AS->addCallSite(CS, AA);
+ AS->addUnknownInst(Inst, AA);
return true;
}
@@ -348,13 +349,9 @@
return add(LI);
if (StoreInst *SI = dyn_cast<StoreInst>(I))
return add(SI);
- if (CallInst *CI = dyn_cast<CallInst>(I))
- return add(CI);
- if (InvokeInst *II = dyn_cast<InvokeInst>(I))
- return add(II);
if (VAArgInst *VAAI = dyn_cast<VAArgInst>(I))
return add(VAAI);
- return true;
+ return addUnknown(I);
}
void AliasSetTracker::add(BasicBlock &BB) {
@@ -375,8 +372,8 @@
AliasSet &AS = const_cast<AliasSet&>(*I);
// If there are any call sites in the alias set, add them to this AST.
- for (unsigned i = 0, e = AS.CallSites.size(); i != e; ++i)
- add(AS.CallSites[i]);
+ for (unsigned i = 0, e = AS.UnknownInsts.size(); i != e; ++i)
+ add(AS.UnknownInsts[i]);
// Loop over all of the pointers in this alias set.
bool X;
@@ -393,7 +390,7 @@
/// tracker.
void AliasSetTracker::remove(AliasSet &AS) {
// Drop all call sites.
- AS.CallSites.clear();
+ AS.UnknownInsts.clear();
// Clear the alias set.
unsigned NumRefs = 0;
@@ -453,11 +450,11 @@
return true;
}
-bool AliasSetTracker::remove(CallSite CS) {
- if (AA.doesNotAccessMemory(CS))
+bool AliasSetTracker::removeUnknown(Instruction *I) {
+ if (!I->mayReadOrWriteMemory())
return false; // doesn't alias anything
- AliasSet *AS = findAliasSetForCallSite(CS);
+ AliasSet *AS = findAliasSetForUnknownInst(I);
if (!AS) return false;
remove(*AS);
return true;
@@ -469,11 +466,9 @@
return remove(LI);
if (StoreInst *SI = dyn_cast<StoreInst>(I))
return remove(SI);
- if (CallInst *CI = dyn_cast<CallInst>(I))
- return remove(CI);
if (VAArgInst *VAAI = dyn_cast<VAArgInst>(I))
return remove(VAAI);
- return true;
+ return removeUnknown(I);
}
@@ -488,13 +483,13 @@
// If this is a call instruction, remove the callsite from the appropriate
// AliasSet (if present).
- if (CallSite CS = PtrVal) {
- if (!AA.doesNotAccessMemory(CS)) {
+ if (Instruction *Inst = dyn_cast<Instruction>(PtrVal)) {
+ if (Inst->mayReadOrWriteMemory()) {
// Scan all the alias sets to see if this call site is contained.
for (iterator I = begin(), E = end(); I != E; ++I) {
if (I->Forward) continue;
- I->removeCallSite(CS);
+ I->removeUnknownInst(Inst);
}
}
}
@@ -571,11 +566,11 @@
OS << ", " << I.getSize() << ")";
}
}
- if (!CallSites.empty()) {
- OS << "\n " << CallSites.size() << " Call Sites: ";
- for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
+ if (!UnknownInsts.empty()) {
+ OS << "\n " << UnknownInsts.size() << " Unknown instructions: ";
+ for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) {
if (i) OS << ", ";
- WriteAsOperand(OS, CallSites[i]);
+ WriteAsOperand(OS, UnknownInsts[i]);
}
}
OS << "\n";
Modified: llvm/branches/exception-handling-rewrite/lib/Analysis/BasicAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Analysis/BasicAliasAnalysis.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Analysis/BasicAliasAnalysis.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Analysis/BasicAliasAnalysis.cpp Wed Jul 27 13:40:48 2011
@@ -374,7 +374,8 @@
}
if (Scale) {
- VariableGEPIndex Entry = {Index, Extension, Scale};
+ VariableGEPIndex Entry = {Index, Extension,
+ static_cast<int64_t>(Scale)};
VarIndices.push_back(Entry);
}
}
Modified: llvm/branches/exception-handling-rewrite/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Analysis/InstructionSimplify.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Analysis/InstructionSimplify.cpp Wed Jul 27 13:40:48 2011
@@ -48,6 +48,26 @@
static Value *SimplifyXorInst(Value *, Value *, const TargetData *,
const DominatorTree *, unsigned);
+/// getFalse - For a boolean type, or a vector of boolean type, return false, or
+/// a vector with every element false, as appropriate for the type.
+static Constant *getFalse(Type *Ty) {
+ assert((Ty->isIntegerTy(1) ||
+ (Ty->isVectorTy() &&
+ cast<VectorType>(Ty)->getElementType()->isIntegerTy(1))) &&
+ "Expected i1 type or a vector of i1!");
+ return Constant::getNullValue(Ty);
+}
+
+/// getTrue - For a boolean type, or a vector of boolean type, return true, or
+/// a vector with every element true, as appropriate for the type.
+static Constant *getTrue(Type *Ty) {
+ assert((Ty->isIntegerTy(1) ||
+ (Ty->isVectorTy() &&
+ cast<VectorType>(Ty)->getElementType()->isIntegerTy(1))) &&
+ "Expected i1 type or a vector of i1!");
+ return Constant::getAllOnesValue(Ty);
+}
+
/// ValueDominatesPHI - Does the given value dominate the specified phi node?
static bool ValueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) {
Instruction *I = dyn_cast<Instruction>(V);
@@ -1478,48 +1498,46 @@
default:
assert(false && "Unknown ICmp predicate!");
case ICmpInst::ICMP_ULT:
- // getNullValue also works for vectors, unlike getFalse.
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
case ICmpInst::ICMP_UGE:
- // getAllOnesValue also works for vectors, unlike getTrue.
- return ConstantInt::getAllOnesValue(ITy);
+ return getTrue(ITy);
case ICmpInst::ICMP_EQ:
case ICmpInst::ICMP_ULE:
if (isKnownNonZero(LHS, TD))
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
break;
case ICmpInst::ICMP_NE:
case ICmpInst::ICMP_UGT:
if (isKnownNonZero(LHS, TD))
- return ConstantInt::getAllOnesValue(ITy);
+ return getTrue(ITy);
break;
case ICmpInst::ICMP_SLT:
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);
if (LHSKnownNegative)
- return ConstantInt::getAllOnesValue(ITy);
+ return getTrue(ITy);
if (LHSKnownNonNegative)
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
break;
case ICmpInst::ICMP_SLE:
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);
if (LHSKnownNegative)
- return ConstantInt::getAllOnesValue(ITy);
+ return getTrue(ITy);
if (LHSKnownNonNegative && isKnownNonZero(LHS, TD))
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
break;
case ICmpInst::ICMP_SGE:
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);
if (LHSKnownNegative)
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
if (LHSKnownNonNegative)
- return ConstantInt::getAllOnesValue(ITy);
+ return getTrue(ITy);
break;
case ICmpInst::ICMP_SGT:
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD);
if (LHSKnownNegative)
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
if (LHSKnownNonNegative && isKnownNonZero(LHS, TD))
- return ConstantInt::getAllOnesValue(ITy);
+ return getTrue(ITy);
break;
}
}
@@ -1811,8 +1829,7 @@
case ICmpInst::ICMP_EQ:
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_UGE:
- // getNullValue also works for vectors, unlike getFalse.
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
case ICmpInst::ICMP_SLT:
case ICmpInst::ICMP_SLE:
ComputeSignBit(LHS, KnownNonNegative, KnownNegative, TD);
@@ -1822,8 +1839,7 @@
case ICmpInst::ICMP_NE:
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_ULE:
- // getAllOnesValue also works for vectors, unlike getTrue.
- return Constant::getAllOnesValue(ITy);
+ return getTrue(ITy);
}
}
if (RBO && match(RBO, m_URem(m_Value(), m_Specific(LHS)))) {
@@ -1840,8 +1856,7 @@
case ICmpInst::ICMP_NE:
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_UGE:
- // getAllOnesValue also works for vectors, unlike getTrue.
- return Constant::getAllOnesValue(ITy);
+ return getTrue(ITy);
case ICmpInst::ICMP_SLT:
case ICmpInst::ICMP_SLE:
ComputeSignBit(RHS, KnownNonNegative, KnownNegative, TD);
@@ -1851,8 +1866,7 @@
case ICmpInst::ICMP_EQ:
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_ULE:
- // getNullValue also works for vectors, unlike getFalse.
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
}
}
@@ -1955,10 +1969,10 @@
}
case CmpInst::ICMP_SGE:
// Always true.
- return Constant::getAllOnesValue(ITy);
+ return getTrue(ITy);
case CmpInst::ICMP_SLT:
// Always false.
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
}
}
@@ -2025,10 +2039,10 @@
}
case CmpInst::ICMP_UGE:
// Always true.
- return Constant::getAllOnesValue(ITy);
+ return getTrue(ITy);
case CmpInst::ICMP_ULT:
// Always false.
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
}
}
@@ -2040,40 +2054,40 @@
// max(x, ?) pred min(x, ?).
if (Pred == CmpInst::ICMP_SGE)
// Always true.
- return Constant::getAllOnesValue(ITy);
+ return getTrue(ITy);
if (Pred == CmpInst::ICMP_SLT)
// Always false.
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
} else if (match(LHS, m_SMin(m_Value(A), m_Value(B))) &&
match(RHS, m_SMax(m_Value(C), m_Value(D))) &&
(A == C || A == D || B == C || B == D)) {
// min(x, ?) pred max(x, ?).
if (Pred == CmpInst::ICMP_SLE)
// Always true.
- return Constant::getAllOnesValue(ITy);
+ return getTrue(ITy);
if (Pred == CmpInst::ICMP_SGT)
// Always false.
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
} else if (match(LHS, m_UMax(m_Value(A), m_Value(B))) &&
match(RHS, m_UMin(m_Value(C), m_Value(D))) &&
(A == C || A == D || B == C || B == D)) {
// max(x, ?) pred min(x, ?).
if (Pred == CmpInst::ICMP_UGE)
// Always true.
- return Constant::getAllOnesValue(ITy);
+ return getTrue(ITy);
if (Pred == CmpInst::ICMP_ULT)
// Always false.
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
} else if (match(LHS, m_UMin(m_Value(A), m_Value(B))) &&
match(RHS, m_UMax(m_Value(C), m_Value(D))) &&
(A == C || A == D || B == C || B == D)) {
// min(x, ?) pred max(x, ?).
if (Pred == CmpInst::ICMP_ULE)
// Always true.
- return Constant::getAllOnesValue(ITy);
+ return getTrue(ITy);
if (Pred == CmpInst::ICMP_UGT)
// Always false.
- return Constant::getNullValue(ITy);
+ return getFalse(ITy);
}
// If the comparison is with the result of a select instruction, check whether
Modified: llvm/branches/exception-handling-rewrite/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Analysis/ScalarEvolution.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Analysis/ScalarEvolution.cpp Wed Jul 27 13:40:48 2011
@@ -3813,6 +3813,13 @@
// Iteration Count Computation Code
//
+// getExitCount - Get the expression for the number of loop iterations for which
+// this loop is guaranteed not to exit via ExitBlock. Otherwise return
+// SCEVCouldNotCompute.
+const SCEV *ScalarEvolution::getExitCount(Loop *L, BasicBlock *ExitBlock) {
+ return getBackedgeTakenInfo(L).getExact(ExitBlock, this);
+}
+
/// getBackedgeTakenCount - If the specified loop has a predictable
/// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute
/// object. The backedge-taken count is the number of times the loop header
@@ -3825,14 +3832,14 @@
/// hasLoopInvariantBackedgeTakenCount).
///
const SCEV *ScalarEvolution::getBackedgeTakenCount(const Loop *L) {
- return getBackedgeTakenInfo(L).Exact;
+ return getBackedgeTakenInfo(L).getExact(this);
}
/// getMaxBackedgeTakenCount - Similar to getBackedgeTakenCount, except
/// return the least SCEV value that is known never to be less than the
/// actual backedge taken count.
const SCEV *ScalarEvolution::getMaxBackedgeTakenCount(const Loop *L) {
- return getBackedgeTakenInfo(L).Max;
+ return getBackedgeTakenInfo(L).getMax(this);
}
/// PushLoopPHIs - Push PHI nodes in the header of the given loop
@@ -3849,33 +3856,31 @@
const ScalarEvolution::BackedgeTakenInfo &
ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
- // Initially insert a CouldNotCompute for this loop. If the insertion
+ // Initially insert an invalid entry for this loop. If the insertion
// succeeds, proceed to actually compute a backedge-taken count and
// update the value. The temporary CouldNotCompute value tells SCEV
// code elsewhere that it shouldn't attempt to request a new
// backedge-taken count, which could result in infinite recursion.
std::pair<DenseMap<const Loop *, BackedgeTakenInfo>::iterator, bool> Pair =
- BackedgeTakenCounts.insert(std::make_pair(L, getCouldNotCompute()));
+ BackedgeTakenCounts.insert(std::make_pair(L, BackedgeTakenInfo()));
if (!Pair.second)
return Pair.first->second;
- BackedgeTakenInfo Result = getCouldNotCompute();
- BackedgeTakenInfo Computed = ComputeBackedgeTakenCount(L);
- if (Computed.Exact != getCouldNotCompute()) {
- assert(isLoopInvariant(Computed.Exact, L) &&
- isLoopInvariant(Computed.Max, L) &&
+ // ComputeBackedgeTakenCount may allocate memory for its result. Inserting it
+ // into the BackedgeTakenCounts map transfers ownership. Otherwise, the result
+ // must be cleared in this scope.
+ BackedgeTakenInfo Result = ComputeBackedgeTakenCount(L);
+
+ if (Result.getExact(this) != getCouldNotCompute()) {
+ assert(isLoopInvariant(Result.getExact(this), L) &&
+ isLoopInvariant(Result.getMax(this), L) &&
"Computed backedge-taken count isn't loop invariant for loop!");
++NumTripCountsComputed;
-
- // Update the value in the map.
- Result = Computed;
- } else {
- if (Computed.Max != getCouldNotCompute())
- // Update the value in the map.
- Result = Computed;
- if (isa<PHINode>(L->getHeader()->begin()))
- // Only count loops that have phi nodes as not being computable.
- ++NumTripCountsNotComputed;
+ }
+ else if (Result.getMax(this) == getCouldNotCompute() &&
+ isa<PHINode>(L->getHeader()->begin())) {
+ // Only count loops that have phi nodes as not being computable.
+ ++NumTripCountsNotComputed;
}
// Now that we know more about the trip count for this loop, forget any
@@ -3883,7 +3888,7 @@
// conservative estimates made without the benefit of trip count
// information. This is similar to the code in forgetLoop, except that
// it handles SCEVUnknown PHI nodes specially.
- if (Computed.hasAnyInfo()) {
+ if (Result.hasAnyInfo()) {
SmallVector<Instruction *, 16> Worklist;
PushLoopPHIs(L, Worklist);
@@ -3928,7 +3933,12 @@
/// compute a trip count, or if the loop is deleted.
void ScalarEvolution::forgetLoop(const Loop *L) {
// Drop any stored trip count value.
- BackedgeTakenCounts.erase(L);
+ DenseMap<const Loop*, BackedgeTakenInfo>::iterator BTCPos =
+ BackedgeTakenCounts.find(L);
+ if (BTCPos != BackedgeTakenCounts.end()) {
+ BTCPos->second.clear();
+ BackedgeTakenCounts.erase(BTCPos);
+ }
// Drop information about expressions based on loop-header PHIs.
SmallVector<Instruction *, 16> Worklist;
@@ -3984,6 +3994,84 @@
}
}
+/// getExact - Get the exact loop backedge taken count considering all loop
+/// exits. If all exits are computable, this is the minimum computed count.
+const SCEV *
+ScalarEvolution::BackedgeTakenInfo::getExact(ScalarEvolution *SE) const {
+ // If any exits were not computable, the loop is not computable.
+ if (!ExitNotTaken.isCompleteList()) return SE->getCouldNotCompute();
+
+ // We need at least one computable exit.
+ if (!ExitNotTaken.ExitBlock) return SE->getCouldNotCompute();
+ assert(ExitNotTaken.ExactNotTaken && "uninitialized not-taken info");
+
+ const SCEV *BECount = 0;
+ for (const ExitNotTakenInfo *ENT = &ExitNotTaken;
+ ENT != 0; ENT = ENT->getNextExit()) {
+
+ assert(ENT->ExactNotTaken != SE->getCouldNotCompute() && "bad exit SCEV");
+
+ if (!BECount)
+ BECount = ENT->ExactNotTaken;
+ else
+ BECount = SE->getUMinFromMismatchedTypes(BECount, ENT->ExactNotTaken);
+ }
+ return BECount;
+}
+
+/// getExact - Get the exact not taken count for this loop exit.
+const SCEV *
+ScalarEvolution::BackedgeTakenInfo::getExact(BasicBlock *ExitBlock,
+ ScalarEvolution *SE) const {
+ for (const ExitNotTakenInfo *ENT = &ExitNotTaken;
+ ENT != 0; ENT = ENT->getNextExit()) {
+
+ if (ENT->ExitBlock == ExitBlock)
+ return ENT->ExactNotTaken;
+ }
+ return SE->getCouldNotCompute();
+}
+
+/// getMax - Get the max backedge taken count for the loop.
+const SCEV *
+ScalarEvolution::BackedgeTakenInfo::getMax(ScalarEvolution *SE) const {
+ return Max ? Max : SE->getCouldNotCompute();
+}
+
+/// Allocate memory for BackedgeTakenInfo and copy the not-taken count of each
+/// computable exit into a persistent ExitNotTakenInfo array.
+ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo(
+ SmallVectorImpl< std::pair<BasicBlock *, const SCEV *> > &ExitCounts,
+ bool Complete, const SCEV *MaxCount) : Max(MaxCount) {
+
+ if (!Complete)
+ ExitNotTaken.setIncomplete();
+
+ unsigned NumExits = ExitCounts.size();
+ if (NumExits == 0) return;
+
+ ExitNotTaken.ExitBlock = ExitCounts[0].first;
+ ExitNotTaken.ExactNotTaken = ExitCounts[0].second;
+ if (NumExits == 1) return;
+
+ // Handle the rare case of multiple computable exits.
+ ExitNotTakenInfo *ENT = new ExitNotTakenInfo[NumExits-1];
+
+ ExitNotTakenInfo *PrevENT = &ExitNotTaken;
+ for (unsigned i = 1; i < NumExits; ++i, PrevENT = ENT, ++ENT) {
+ PrevENT->setNextExit(ENT);
+ ENT->ExitBlock = ExitCounts[i].first;
+ ENT->ExactNotTaken = ExitCounts[i].second;
+ }
+}
+
+/// clear - Invalidate this result and free the ExitNotTakenInfo array.
+void ScalarEvolution::BackedgeTakenInfo::clear() {
+ ExitNotTaken.ExitBlock = 0;
+ ExitNotTaken.ExactNotTaken = 0;
+ delete[] ExitNotTaken.getNextExit();
+}
+
/// ComputeBackedgeTakenCount - Compute the number of times the backedge
/// of the specified loop will execute.
ScalarEvolution::BackedgeTakenInfo
@@ -3992,38 +4080,31 @@
L->getExitingBlocks(ExitingBlocks);
// Examine all exits and pick the most conservative values.
- const SCEV *BECount = getCouldNotCompute();
const SCEV *MaxBECount = getCouldNotCompute();
- bool CouldNotComputeBECount = false;
+ bool CouldComputeBECount = true;
+ SmallVector<std::pair<BasicBlock *, const SCEV *>, 4> ExitCounts;
for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
- BackedgeTakenInfo NewBTI =
- ComputeBackedgeTakenCountFromExit(L, ExitingBlocks[i]);
-
- if (NewBTI.Exact == getCouldNotCompute()) {
+ ExitLimit EL = ComputeExitLimit(L, ExitingBlocks[i]);
+ if (EL.Exact == getCouldNotCompute())
// We couldn't compute an exact value for this exit, so
// we won't be able to compute an exact value for the loop.
- CouldNotComputeBECount = true;
- BECount = getCouldNotCompute();
- } else if (!CouldNotComputeBECount) {
- if (BECount == getCouldNotCompute())
- BECount = NewBTI.Exact;
- else
- BECount = getUMinFromMismatchedTypes(BECount, NewBTI.Exact);
- }
+ CouldComputeBECount = false;
+ else
+ ExitCounts.push_back(std::make_pair(ExitingBlocks[i], EL.Exact));
+
if (MaxBECount == getCouldNotCompute())
- MaxBECount = NewBTI.Max;
- else if (NewBTI.Max != getCouldNotCompute())
- MaxBECount = getUMinFromMismatchedTypes(MaxBECount, NewBTI.Max);
+ MaxBECount = EL.Max;
+ else if (EL.Max != getCouldNotCompute())
+ MaxBECount = getUMinFromMismatchedTypes(MaxBECount, EL.Max);
}
- return BackedgeTakenInfo(BECount, MaxBECount);
+ return BackedgeTakenInfo(ExitCounts, CouldComputeBECount, MaxBECount);
}
-/// ComputeBackedgeTakenCountFromExit - Compute the number of times the backedge
-/// of the specified loop will execute if it exits via the specified block.
-ScalarEvolution::BackedgeTakenInfo
-ScalarEvolution::ComputeBackedgeTakenCountFromExit(const Loop *L,
- BasicBlock *ExitingBlock) {
+/// ComputeExitLimit - Compute the number of times the backedge of the specified
+/// loop will execute if it exits via the specified block.
+ScalarEvolution::ExitLimit
+ScalarEvolution::ComputeExitLimit(const Loop *L, BasicBlock *ExitingBlock) {
// Okay, we've chosen an exiting block. See what condition causes us to
// exit at this block.
@@ -4081,95 +4162,91 @@
}
// Proceed to the next level to examine the exit condition expression.
- return ComputeBackedgeTakenCountFromExitCond(L, ExitBr->getCondition(),
- ExitBr->getSuccessor(0),
- ExitBr->getSuccessor(1));
+ return ComputeExitLimitFromCond(L, ExitBr->getCondition(),
+ ExitBr->getSuccessor(0),
+ ExitBr->getSuccessor(1));
}
-/// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the
+/// ComputeExitLimitFromCond - Compute the number of times the
/// backedge of the specified loop will execute if its exit condition
/// were a conditional branch of ExitCond, TBB, and FBB.
-ScalarEvolution::BackedgeTakenInfo
-ScalarEvolution::ComputeBackedgeTakenCountFromExitCond(const Loop *L,
- Value *ExitCond,
- BasicBlock *TBB,
- BasicBlock *FBB) {
+ScalarEvolution::ExitLimit
+ScalarEvolution::ComputeExitLimitFromCond(const Loop *L,
+ Value *ExitCond,
+ BasicBlock *TBB,
+ BasicBlock *FBB) {
// Check if the controlling expression for this loop is an And or Or.
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(ExitCond)) {
if (BO->getOpcode() == Instruction::And) {
// Recurse on the operands of the and.
- BackedgeTakenInfo BTI0 =
- ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(0), TBB, FBB);
- BackedgeTakenInfo BTI1 =
- ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(1), TBB, FBB);
+ ExitLimit EL0 = ComputeExitLimitFromCond(L, BO->getOperand(0), TBB, FBB);
+ ExitLimit EL1 = ComputeExitLimitFromCond(L, BO->getOperand(1), TBB, FBB);
const SCEV *BECount = getCouldNotCompute();
const SCEV *MaxBECount = getCouldNotCompute();
if (L->contains(TBB)) {
// Both conditions must be true for the loop to continue executing.
// Choose the less conservative count.
- if (BTI0.Exact == getCouldNotCompute() ||
- BTI1.Exact == getCouldNotCompute())
+ if (EL0.Exact == getCouldNotCompute() ||
+ EL1.Exact == getCouldNotCompute())
BECount = getCouldNotCompute();
else
- BECount = getUMinFromMismatchedTypes(BTI0.Exact, BTI1.Exact);
- if (BTI0.Max == getCouldNotCompute())
- MaxBECount = BTI1.Max;
- else if (BTI1.Max == getCouldNotCompute())
- MaxBECount = BTI0.Max;
+ BECount = getUMinFromMismatchedTypes(EL0.Exact, EL1.Exact);
+ if (EL0.Max == getCouldNotCompute())
+ MaxBECount = EL1.Max;
+ else if (EL1.Max == getCouldNotCompute())
+ MaxBECount = EL0.Max;
else
- MaxBECount = getUMinFromMismatchedTypes(BTI0.Max, BTI1.Max);
+ MaxBECount = getUMinFromMismatchedTypes(EL0.Max, EL1.Max);
} else {
// Both conditions must be true at the same time for the loop to exit.
// For now, be conservative.
assert(L->contains(FBB) && "Loop block has no successor in loop!");
- if (BTI0.Max == BTI1.Max)
- MaxBECount = BTI0.Max;
- if (BTI0.Exact == BTI1.Exact)
- BECount = BTI0.Exact;
+ if (EL0.Max == EL1.Max)
+ MaxBECount = EL0.Max;
+ if (EL0.Exact == EL1.Exact)
+ BECount = EL0.Exact;
}
- return BackedgeTakenInfo(BECount, MaxBECount);
+ return ExitLimit(BECount, MaxBECount);
}
if (BO->getOpcode() == Instruction::Or) {
// Recurse on the operands of the or.
- BackedgeTakenInfo BTI0 =
- ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(0), TBB, FBB);
- BackedgeTakenInfo BTI1 =
- ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(1), TBB, FBB);
+ ExitLimit EL0 = ComputeExitLimitFromCond(L, BO->getOperand(0), TBB, FBB);
+ ExitLimit EL1 = ComputeExitLimitFromCond(L, BO->getOperand(1), TBB, FBB);
const SCEV *BECount = getCouldNotCompute();
const SCEV *MaxBECount = getCouldNotCompute();
if (L->contains(FBB)) {
// Both conditions must be false for the loop to continue executing.
// Choose the less conservative count.
- if (BTI0.Exact == getCouldNotCompute() ||
- BTI1.Exact == getCouldNotCompute())
+ if (EL0.Exact == getCouldNotCompute() ||
+ EL1.Exact == getCouldNotCompute())
BECount = getCouldNotCompute();
else
- BECount = getUMinFromMismatchedTypes(BTI0.Exact, BTI1.Exact);
- if (BTI0.Max == getCouldNotCompute())
- MaxBECount = BTI1.Max;
- else if (BTI1.Max == getCouldNotCompute())
- MaxBECount = BTI0.Max;
+ BECount = getUMinFromMismatchedTypes(EL0.Exact, EL1.Exact);
+ if (EL0.Max == getCouldNotCompute())
+ MaxBECount = EL1.Max;
+ else if (EL1.Max == getCouldNotCompute())
+ MaxBECount = EL0.Max;
else
- MaxBECount = getUMinFromMismatchedTypes(BTI0.Max, BTI1.Max);
+ MaxBECount = getUMinFromMismatchedTypes(EL0.Max, EL1.Max);
} else {
// Both conditions must be false at the same time for the loop to exit.
// For now, be conservative.
assert(L->contains(TBB) && "Loop block has no successor in loop!");
- if (BTI0.Max == BTI1.Max)
- MaxBECount = BTI0.Max;
- if (BTI0.Exact == BTI1.Exact)
- BECount = BTI0.Exact;
+ if (EL0.Max == EL1.Max)
+ MaxBECount = EL0.Max;
+ if (EL0.Exact == EL1.Exact)
+ BECount = EL0.Exact;
}
- return BackedgeTakenInfo(BECount, MaxBECount);
+ return ExitLimit(BECount, MaxBECount);
}
}
// With an icmp, it may be feasible to compute an exact backedge-taken count.
// Proceed to the next level to examine the icmp.
if (ICmpInst *ExitCondICmp = dyn_cast<ICmpInst>(ExitCond))
- return ComputeBackedgeTakenCountFromExitCondICmp(L, ExitCondICmp, TBB, FBB);
+ return ComputeExitLimitFromICmp(L, ExitCondICmp, TBB, FBB);
// Check for a constant condition. These are normally stripped out by
// SimplifyCFG, but ScalarEvolution may be used by a pass which wishes to
@@ -4185,17 +4262,17 @@
}
// If it's not an integer or pointer comparison then compute it the hard way.
- return ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB));
+ return ComputeExitCountExhaustively(L, ExitCond, !L->contains(TBB));
}
-/// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of times the
+/// ComputeExitLimitFromICmp - Compute the number of times the
/// backedge of the specified loop will execute if its exit condition
/// were a conditional branch of the ICmpInst ExitCond, TBB, and FBB.
-ScalarEvolution::BackedgeTakenInfo
-ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L,
- ICmpInst *ExitCond,
- BasicBlock *TBB,
- BasicBlock *FBB) {
+ScalarEvolution::ExitLimit
+ScalarEvolution::ComputeExitLimitFromICmp(const Loop *L,
+ ICmpInst *ExitCond,
+ BasicBlock *TBB,
+ BasicBlock *FBB) {
// If the condition was exit on true, convert the condition to exit on false
ICmpInst::Predicate Cond;
@@ -4207,8 +4284,8 @@
// Handle common loops like: for (X = "string"; *X; ++X)
if (LoadInst *LI = dyn_cast<LoadInst>(ExitCond->getOperand(0)))
if (Constant *RHS = dyn_cast<Constant>(ExitCond->getOperand(1))) {
- BackedgeTakenInfo ItCnt =
- ComputeLoadConstantCompareBackedgeTakenCount(LI, RHS, L, Cond);
+ ExitLimit ItCnt =
+ ComputeLoadConstantCompareExitLimit(LI, RHS, L, Cond);
if (ItCnt.hasAnyInfo())
return ItCnt;
}
@@ -4247,36 +4324,36 @@
switch (Cond) {
case ICmpInst::ICMP_NE: { // while (X != Y)
// Convert to: while (X-Y != 0)
- BackedgeTakenInfo BTI = HowFarToZero(getMinusSCEV(LHS, RHS), L);
- if (BTI.hasAnyInfo()) return BTI;
+ ExitLimit EL = HowFarToZero(getMinusSCEV(LHS, RHS), L);
+ if (EL.hasAnyInfo()) return EL;
break;
}
case ICmpInst::ICMP_EQ: { // while (X == Y)
// Convert to: while (X-Y == 0)
- BackedgeTakenInfo BTI = HowFarToNonZero(getMinusSCEV(LHS, RHS), L);
- if (BTI.hasAnyInfo()) return BTI;
+ ExitLimit EL = HowFarToNonZero(getMinusSCEV(LHS, RHS), L);
+ if (EL.hasAnyInfo()) return EL;
break;
}
case ICmpInst::ICMP_SLT: {
- BackedgeTakenInfo BTI = HowManyLessThans(LHS, RHS, L, true);
- if (BTI.hasAnyInfo()) return BTI;
+ ExitLimit EL = HowManyLessThans(LHS, RHS, L, true);
+ if (EL.hasAnyInfo()) return EL;
break;
}
case ICmpInst::ICMP_SGT: {
- BackedgeTakenInfo BTI = HowManyLessThans(getNotSCEV(LHS),
+ ExitLimit EL = HowManyLessThans(getNotSCEV(LHS),
getNotSCEV(RHS), L, true);
- if (BTI.hasAnyInfo()) return BTI;
+ if (EL.hasAnyInfo()) return EL;
break;
}
case ICmpInst::ICMP_ULT: {
- BackedgeTakenInfo BTI = HowManyLessThans(LHS, RHS, L, false);
- if (BTI.hasAnyInfo()) return BTI;
+ ExitLimit EL = HowManyLessThans(LHS, RHS, L, false);
+ if (EL.hasAnyInfo()) return EL;
break;
}
case ICmpInst::ICMP_UGT: {
- BackedgeTakenInfo BTI = HowManyLessThans(getNotSCEV(LHS),
+ ExitLimit EL = HowManyLessThans(getNotSCEV(LHS),
getNotSCEV(RHS), L, false);
- if (BTI.hasAnyInfo()) return BTI;
+ if (EL.hasAnyInfo()) return EL;
break;
}
default:
@@ -4290,8 +4367,7 @@
#endif
break;
}
- return
- ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB));
+ return ComputeExitCountExhaustively(L, ExitCond, !L->contains(TBB));
}
static ConstantInt *
@@ -4338,15 +4414,16 @@
return Init;
}
-/// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition of
+/// ComputeLoadConstantCompareExitLimit - Given an exit condition of
/// 'icmp op load X, cst', try to see if we can compute the backedge
/// execution count.
-ScalarEvolution::BackedgeTakenInfo
-ScalarEvolution::ComputeLoadConstantCompareBackedgeTakenCount(
- LoadInst *LI,
- Constant *RHS,
- const Loop *L,
- ICmpInst::Predicate predicate) {
+ScalarEvolution::ExitLimit
+ScalarEvolution::ComputeLoadConstantCompareExitLimit(
+ LoadInst *LI,
+ Constant *RHS,
+ const Loop *L,
+ ICmpInst::Predicate predicate) {
+
if (LI->isVolatile()) return getCouldNotCompute();
// Check to see if the loaded pointer is a getelementptr of a global.
@@ -4547,15 +4624,14 @@
}
}
-/// ComputeBackedgeTakenCountExhaustively - If the loop is known to execute a
+/// ComputeExitCountExhaustively - If the loop is known to execute a
/// constant number of times (the condition evolves only from constants),
/// try to evaluate a few iterations of the loop until we get the exit
/// condition gets a value of ExitWhen (true or false). If we cannot
/// evaluate the trip count of the loop, return getCouldNotCompute().
-const SCEV *
-ScalarEvolution::ComputeBackedgeTakenCountExhaustively(const Loop *L,
- Value *Cond,
- bool ExitWhen) {
+const SCEV * ScalarEvolution::ComputeExitCountExhaustively(const Loop *L,
+ Value *Cond,
+ bool ExitWhen) {
PHINode *PN = getConstantEvolvingPHI(Cond, L);
if (PN == 0) return getCouldNotCompute();
@@ -4949,7 +5025,7 @@
/// now expressed as a single expression, V = x-y. So the exit test is
/// effectively V != 0. We know and take advantage of the fact that this
/// expression only being used in a comparison by zero context.
-ScalarEvolution::BackedgeTakenInfo
+ScalarEvolution::ExitLimit
ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) {
// If the value is a constant
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(V)) {
@@ -5061,7 +5137,7 @@
/// HowFarToNonZero - Return the number of times a backedge checking the
/// specified value for nonzero will execute. If not computable, return
/// CouldNotCompute
-ScalarEvolution::BackedgeTakenInfo
+ScalarEvolution::ExitLimit
ScalarEvolution::HowFarToNonZero(const SCEV *V, const Loop *L) {
// Loops that look like: while (X == 0) are very strange indeed. We don't
// handle them yet except for the trivial case. This could be expanded in the
@@ -5774,7 +5850,7 @@
/// HowManyLessThans - Return the number of times a backedge containing the
/// specified less-than comparison will execute. If not computable, return
/// CouldNotCompute.
-ScalarEvolution::BackedgeTakenInfo
+ScalarEvolution::ExitLimit
ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
const Loop *L, bool isSigned) {
// Only handle: "ADDREC < LoopInvariant".
@@ -5881,7 +5957,7 @@
if (isa<SCEVCouldNotCompute>(MaxBECount))
MaxBECount = BECount;
- return BackedgeTakenInfo(BECount, MaxBECount);
+ return ExitLimit(BECount, MaxBECount);
}
return getCouldNotCompute();
@@ -6089,6 +6165,15 @@
FirstUnknown = 0;
ValueExprMap.clear();
+
+ // Free any extra memory created for ExitNotTakenInfo in the unlikely event
+ // that a loop had multiple computable exits.
+ for (DenseMap<const Loop*, BackedgeTakenInfo>::iterator I =
+ BackedgeTakenCounts.begin(), E = BackedgeTakenCounts.end();
+ I != E; ++I) {
+ I->second.clear();
+ }
+
BackedgeTakenCounts.clear();
ConstantEvolutionLoopExitValue.clear();
ValuesAtScopes.clear();
Modified: llvm/branches/exception-handling-rewrite/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Wed Jul 27 13:40:48 2011
@@ -565,10 +565,17 @@
assert (Ranges.empty() == false
&& "DbgScope does not have instruction markers!");
- // FIXME : .debug_inlined section specification does not clearly state how
- // to emit inlined scope that is split into multiple instruction ranges.
- // For now, use first instruction range and emit low_pc/high_pc pair and
- // corresponding .debug_inlined section entry for this pair.
+ if (!Scope->getScopeNode())
+ return NULL;
+ DIScope DS(Scope->getScopeNode());
+ DISubprogram InlinedSP = getDISubprogram(DS);
+ CompileUnit *TheCU = getCompileUnit(InlinedSP);
+ DIE *OriginDIE = TheCU->getDIE(InlinedSP);
+ if (!OriginDIE) {
+ DEBUG(dbgs() << "Unable to find original DIE for inlined subprogram.");
+ return NULL;
+ }
+
SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin();
const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
const MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
@@ -582,26 +589,35 @@
assert(EndLabel->isDefined() &&
"Invalid end label for an inlined scope!");
- if (!Scope->getScopeNode())
- return NULL;
- DIScope DS(Scope->getScopeNode());
- DISubprogram InlinedSP = getDISubprogram(DS);
- CompileUnit *TheCU = getCompileUnit(InlinedSP);
- DIE *OriginDIE = TheCU->getDIE(InlinedSP);
- if (!OriginDIE) {
- DEBUG(dbgs() << "Unable to find original DIE for inlined subprogram.");
- return NULL;
- }
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
dwarf::DW_FORM_ref4, OriginDIE);
- TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel);
- TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel);
+ if (Ranges.size() > 1) {
+ // .debug_range section has not been laid out yet. Emit offset in
+ // .debug_range as a uint, size 4, for now. emitDIE will handle
+ // DW_AT_ranges appropriately.
+ TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
+ DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize());
+ for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(),
+ RE = Ranges.end(); RI != RE; ++RI) {
+ DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
+ DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
+ }
+ DebugRangeSymbols.push_back(NULL);
+ DebugRangeSymbols.push_back(NULL);
+ } else {
+ TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel);
+ TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel);
+ }
InlinedSubprogramDIEs.insert(OriginDIE);
// Track the start label for this inlined function.
+ //.debug_inlined section specification does not clearly state how
+ // to emit inlined scope that is split into multiple instruction ranges.
+ // For now, use first instruction range and emit low_pc/high_pc pair and
+ // corresponding .debug_inlined section entry for this pair.
DenseMap<const MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
I = InlineInfo.find(InlinedSP);
@@ -1641,12 +1657,21 @@
WorkStack.push_back(ChildScope);
visitedChildren = true;
ChildScope->setDFSIn(++Counter);
+#ifndef NDEBUG
+ if (PrintDbgScope)
+ dbgs() << "calculate dbgscope dom: In " << Counter << "\n";
+#endif
break;
}
}
if (!visitedChildren) {
WorkStack.pop_back();
WS->setDFSOut(++Counter);
+#ifndef NDEBUG
+ if (PrintDbgScope)
+ dbgs() << "calculate dbgscope dom: In " << WS->getDFSIn()
+ << " Out " << Counter << "\n";
+#endif
}
}
}
@@ -1702,11 +1727,11 @@
// Scan each instruction and create scopes. First build working set of scopes.
SmallVector<DbgRange, 4> MIRanges;
DenseMap<const MachineInstr *, DbgScope *> MI2ScopeMap;
- DebugLoc PrevDL;
- const MachineInstr *RangeBeginMI = NULL;
- const MachineInstr *PrevMI = NULL;
for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end();
I != E; ++I) {
+ const MachineInstr *RangeBeginMI = NULL;
+ const MachineInstr *PrevMI = NULL;
+ DebugLoc PrevDL;
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
@@ -1749,13 +1774,13 @@
PrevMI = MInsn;
PrevDL = MIDL;
}
- }
- // Create last instruction range.
- if (RangeBeginMI && PrevMI && !PrevDL.isUnknown()) {
- DbgRange R(RangeBeginMI, PrevMI);
- MIRanges.push_back(R);
- MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevDL);
+ // Create last instruction range.
+ if (RangeBeginMI && PrevMI && !PrevDL.isUnknown()) {
+ DbgRange R(RangeBeginMI, PrevMI);
+ MIRanges.push_back(R);
+ MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevDL);
+ }
}
if (!CurrentFnDbgScope)
Modified: llvm/branches/exception-handling-rewrite/lib/CodeGen/PeepholeOptimizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/CodeGen/PeepholeOptimizer.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/CodeGen/PeepholeOptimizer.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/CodeGen/PeepholeOptimizer.cpp Wed Jul 27 13:40:48 2011
@@ -295,7 +295,6 @@
if (!DefMI || !DefMI->getDesc().isBitcast())
return false;
- unsigned SrcDef = 0;
unsigned SrcSrc = 0;
NumDefs = DefMI->getDesc().getNumDefs();
NumSrcs = DefMI->getDesc().getNumOperands() - NumDefs;
@@ -308,13 +307,13 @@
unsigned Reg = MO.getReg();
if (!Reg)
continue;
- if (MO.isDef())
- SrcDef = Reg;
- else if (SrcSrc)
- // Multiple sources?
- return false;
- else
- SrcSrc = Reg;
+ if (!MO.isDef()) {
+ if (SrcSrc)
+ // Multiple sources?
+ return false;
+ else
+ SrcSrc = Reg;
+ }
}
if (MRI->getRegClass(SrcSrc) != MRI->getRegClass(Def))
Modified: llvm/branches/exception-handling-rewrite/lib/CodeGen/RegAllocBasic.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/CodeGen/RegAllocBasic.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/CodeGen/RegAllocBasic.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/CodeGen/RegAllocBasic.cpp Wed Jul 27 13:40:48 2011
@@ -439,6 +439,7 @@
LiveIntervalUnion &LiveUnion = PhysReg2LiveUnion[PhysReg];
if (LiveUnion.empty())
continue;
+ DEBUG(dbgs() << PrintReg(PhysReg, TRI) << " live-in:");
MachineFunction::iterator MBB = llvm::next(MF->begin());
MachineFunction::iterator MFE = MF->end();
SlotIndex Start, Stop;
@@ -449,6 +450,8 @@
if (SI.start() <= Start) {
if (!MBB->isLiveIn(PhysReg))
MBB->addLiveIn(PhysReg);
+ DEBUG(dbgs() << "\tBB#" << MBB->getNumber() << ':'
+ << PrintReg(SI.value()->reg, TRI));
} else if (SI.start() > Stop)
MBB = Indexes->getMBBFromIndex(SI.start().getPrevIndex());
if (++MBB == MFE)
@@ -456,6 +459,7 @@
tie(Start, Stop) = Indexes->getMBBRange(MBB);
SI.advanceTo(Start);
}
+ DEBUG(dbgs() << '\n');
}
}
Modified: llvm/branches/exception-handling-rewrite/lib/CodeGen/RegAllocGreedy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/CodeGen/RegAllocGreedy.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/CodeGen/RegAllocGreedy.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/CodeGen/RegAllocGreedy.cpp Wed Jul 27 13:40:48 2011
@@ -38,6 +38,7 @@
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/Target/TargetOptions.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -51,6 +52,8 @@
STATISTIC(NumLocalSplits, "Number of split local live ranges");
STATISTIC(NumEvicted, "Number of interferences evicted");
+cl::opt<bool> CompactRegions("compact-regions");
+
static RegisterRegAlloc greedyRegAlloc("greedy", "greedy register allocator",
createGreedyRegisterAllocator);
@@ -171,17 +174,38 @@
/// Global live range splitting candidate info.
struct GlobalSplitCandidate {
+ // Register intended for assignment, or 0.
unsigned PhysReg;
+
+ // SplitKit interval index for this candidate.
+ unsigned IntvIdx;
+
+ // Interference for PhysReg.
InterferenceCache::Cursor Intf;
+
+ // Bundles where this candidate should be live.
BitVector LiveBundles;
SmallVector<unsigned, 8> ActiveBlocks;
void reset(InterferenceCache &Cache, unsigned Reg) {
PhysReg = Reg;
+ IntvIdx = 0;
Intf.setPhysReg(Cache, Reg);
LiveBundles.clear();
ActiveBlocks.clear();
}
+
+ // Set B[i] = C for every live bundle where B[i] was NoCand.
+ unsigned getBundles(SmallVectorImpl<unsigned> &B, unsigned C) {
+ unsigned Count = 0;
+ for (int i = LiveBundles.find_first(); i >= 0;
+ i = LiveBundles.find_next(i))
+ if (B[i] == NoCand) {
+ B[i] = C;
+ Count++;
+ }
+ return Count;
+ }
};
/// Candidate info for for each PhysReg in AllocationOrder.
@@ -189,6 +213,12 @@
/// class.
SmallVector<GlobalSplitCandidate, 32> GlobalCand;
+ enum { NoCand = ~0u };
+
+ /// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to
+ /// NoCand which indicates the stack interval.
+ SmallVector<unsigned, 32> BundleCand;
+
public:
RAGreedy();
@@ -223,8 +253,7 @@
void growRegion(GlobalSplitCandidate &Cand);
float calcGlobalSplitCost(GlobalSplitCandidate&);
bool calcCompactRegion(GlobalSplitCandidate&);
- void splitAroundRegion(LiveInterval&, GlobalSplitCandidate&,
- SmallVectorImpl<LiveInterval*>&);
+ void splitAroundRegion(LiveRangeEdit&, ArrayRef<unsigned>);
void calcGapWeights(unsigned, SmallVectorImpl<float>&);
bool shouldEvict(LiveInterval &A, bool, LiveInterval &B, bool);
bool canEvictInterference(LiveInterval&, unsigned, bool, EvictionCost&);
@@ -896,81 +925,109 @@
return GlobalCost;
}
-/// splitAroundRegion - Split VirtReg around the region determined by
-/// LiveBundles. Make an effort to avoid interference from PhysReg.
+/// splitAroundRegion - Split the current live range around the regions
+/// determined by BundleCand and GlobalCand.
///
-/// The 'register' interval is going to contain as many uses as possible while
-/// avoiding interference. The 'stack' interval is the complement constructed by
-/// SplitEditor. It will contain the rest.
+/// Before calling this function, GlobalCand and BundleCand must be initialized
+/// so each bundle is assigned to a valid candidate, or NoCand for the
+/// stack-bound bundles. The shared SA/SE SplitAnalysis and SplitEditor
+/// objects must be initialized for the current live range, and intervals
+/// created for the used candidates.
///
-void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,
- GlobalSplitCandidate &Cand,
- SmallVectorImpl<LiveInterval*> &NewVRegs) {
- const BitVector &LiveBundles = Cand.LiveBundles;
-
- DEBUG({
- dbgs() << "Splitting around region for " << PrintReg(Cand.PhysReg, TRI)
- << " with bundles";
- for (int i = LiveBundles.find_first(); i>=0; i = LiveBundles.find_next(i))
- dbgs() << " EB#" << i;
- dbgs() << ".\n";
- });
-
- InterferenceCache::Cursor &Intf = Cand.Intf;
- LiveRangeEdit LREdit(VirtReg, NewVRegs, this);
- SE->reset(LREdit);
-
- // Create the main cross-block interval.
- const unsigned MainIntv = SE->openIntv();
+/// @param LREdit The LiveRangeEdit object handling the current split.
+/// @param UsedCands List of used GlobalCand entries. Every BundleCand value
+/// must appear in this list.
+void RAGreedy::splitAroundRegion(LiveRangeEdit &LREdit,
+ ArrayRef<unsigned> UsedCands) {
+ // These are the intervals created for new global ranges. We may create more
+ // intervals for local ranges.
+ const unsigned NumGlobalIntvs = LREdit.size();
+ DEBUG(dbgs() << "splitAroundRegion with " << NumGlobalIntvs << " globals.\n");
+ assert(NumGlobalIntvs && "No global intervals configured");
// First handle all the blocks with uses.
ArrayRef<SplitAnalysis::BlockInfo> UseBlocks = SA->getUseBlocks();
for (unsigned i = 0; i != UseBlocks.size(); ++i) {
const SplitAnalysis::BlockInfo &BI = UseBlocks[i];
- bool RegIn = BI.LiveIn &&
- LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)];
- bool RegOut = BI.LiveOut &&
- LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)];
+ unsigned Number = BI.MBB->getNumber();
+ unsigned IntvIn = 0, IntvOut = 0;
+ SlotIndex IntfIn, IntfOut;
+ if (BI.LiveIn) {
+ unsigned CandIn = BundleCand[Bundles->getBundle(Number, 0)];
+ if (CandIn != NoCand) {
+ GlobalSplitCandidate &Cand = GlobalCand[CandIn];
+ IntvIn = Cand.IntvIdx;
+ Cand.Intf.moveToBlock(Number);
+ IntfIn = Cand.Intf.first();
+ }
+ }
+ if (BI.LiveOut) {
+ unsigned CandOut = BundleCand[Bundles->getBundle(Number, 1)];
+ if (CandOut != NoCand) {
+ GlobalSplitCandidate &Cand = GlobalCand[CandOut];
+ IntvOut = Cand.IntvIdx;
+ Cand.Intf.moveToBlock(Number);
+ IntfOut = Cand.Intf.last();
+ }
+ }
// Create separate intervals for isolated blocks with multiple uses.
- if (!RegIn && !RegOut) {
+ if (!IntvIn && !IntvOut) {
DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " isolated.\n");
- if (!BI.isOneInstr()) {
+ if (!BI.isOneInstr())
SE->splitSingleBlock(BI);
- SE->selectIntv(MainIntv);
- }
continue;
}
- Intf.moveToBlock(BI.MBB->getNumber());
-
- if (RegIn && RegOut)
- SE->splitLiveThroughBlock(BI.MBB->getNumber(),
- MainIntv, Intf.first(),
- MainIntv, Intf.last());
- else if (RegIn)
- SE->splitRegInBlock(BI, MainIntv, Intf.first());
+ if (IntvIn && IntvOut)
+ SE->splitLiveThroughBlock(Number, IntvIn, IntfIn, IntvOut, IntfOut);
+ else if (IntvIn)
+ SE->splitRegInBlock(BI, IntvIn, IntfIn);
else
- SE->splitRegOutBlock(BI, MainIntv, Intf.last());
+ SE->splitRegOutBlock(BI, IntvOut, IntfOut);
}
- // Handle live-through blocks.
- for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) {
- unsigned Number = Cand.ActiveBlocks[i];
- bool RegIn = LiveBundles[Bundles->getBundle(Number, 0)];
- bool RegOut = LiveBundles[Bundles->getBundle(Number, 1)];
- if (!RegIn && !RegOut)
- continue;
- Intf.moveToBlock(Number);
- SE->splitLiveThroughBlock(Number, RegIn ? MainIntv : 0, Intf.first(),
- RegOut ? MainIntv : 0, Intf.last());
+ // Handle live-through blocks. The relevant live-through blocks are stored in
+ // the ActiveBlocks list with each candidate. We need to filter out
+ // duplicates.
+ BitVector Todo = SA->getThroughBlocks();
+ for (unsigned c = 0; c != UsedCands.size(); ++c) {
+ ArrayRef<unsigned> Blocks = GlobalCand[UsedCands[c]].ActiveBlocks;
+ for (unsigned i = 0, e = Blocks.size(); i != e; ++i) {
+ unsigned Number = Blocks[i];
+ if (!Todo.test(Number))
+ continue;
+ Todo.reset(Number);
+
+ unsigned IntvIn = 0, IntvOut = 0;
+ SlotIndex IntfIn, IntfOut;
+
+ unsigned CandIn = BundleCand[Bundles->getBundle(Number, 0)];
+ if (CandIn != NoCand) {
+ GlobalSplitCandidate &Cand = GlobalCand[CandIn];
+ IntvIn = Cand.IntvIdx;
+ Cand.Intf.moveToBlock(Number);
+ IntfIn = Cand.Intf.first();
+ }
+
+ unsigned CandOut = BundleCand[Bundles->getBundle(Number, 1)];
+ if (CandOut != NoCand) {
+ GlobalSplitCandidate &Cand = GlobalCand[CandOut];
+ IntvOut = Cand.IntvIdx;
+ Cand.Intf.moveToBlock(Number);
+ IntfOut = Cand.Intf.last();
+ }
+ if (!IntvIn && !IntvOut)
+ continue;
+ SE->splitLiveThroughBlock(Number, IntvIn, IntfIn, IntvOut, IntfOut);
+ }
}
++NumGlobalSplits;
SmallVector<unsigned, 8> IntvMap;
SE->finish(&IntvMap);
- DebugVars->splitRegister(VirtReg.reg, LREdit.regs());
+ DebugVars->splitRegister(SA->getParent().reg, LREdit.regs());
ExtraRegInfo.resize(MRI->getNumVirtRegs());
unsigned OrigBlocks = SA->getNumLiveBlocks();
@@ -994,9 +1051,9 @@
continue;
}
- // Main interval. Allow repeated splitting as long as the number of live
- // blocks is strictly decreasing. Otherwise force per-block splitting.
- if (IntvMap[i] == MainIntv) {
+ // Global intervals. Allow repeated splitting as long as the number of live
+ // blocks is strictly decreasing.
+ if (IntvMap[i] < NumGlobalIntvs) {
if (SA->countLiveBlocks(&Reg) >= OrigBlocks) {
DEBUG(dbgs() << "Main interval covers the same " << OrigBlocks
<< " blocks as original.\n");
@@ -1016,11 +1073,23 @@
unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
SmallVectorImpl<LiveInterval*> &NewVRegs) {
- float BestCost = Hysteresis * calcSpillCost();
- DEBUG(dbgs() << "Cost of isolating all blocks = " << BestCost << '\n');
- const unsigned NoCand = ~0u;
- unsigned BestCand = NoCand;
unsigned NumCands = 0;
+ unsigned BestCand = NoCand;
+ float BestCost;
+ SmallVector<unsigned, 8> UsedCands;
+
+ // Check if we can split this live range around a compact region.
+ bool HasCompact = CompactRegions && calcCompactRegion(GlobalCand.front());
+ if (HasCompact) {
+ // Yes, keep GlobalCand[0] as the compact region candidate.
+ NumCands = 1;
+ BestCost = HUGE_VALF;
+ } else {
+ // No benefit from the compact region, our fallback will be per-block
+ // splitting. Make sure we find a solution that is cheaper than spilling.
+ BestCost = Hysteresis * calcSpillCost();
+ DEBUG(dbgs() << "Cost of isolating all blocks = " << BestCost << '\n');
+ }
Order.rewind();
while (unsigned PhysReg = Order.next()) {
@@ -1030,7 +1099,7 @@
unsigned WorstCount = ~0u;
unsigned Worst = 0;
for (unsigned i = 0; i != NumCands; ++i) {
- if (i == BestCand)
+ if (i == BestCand || !GlobalCand[i].PhysReg)
continue;
unsigned Count = GlobalCand[i].LiveBundles.count();
if (Count < WorstCount)
@@ -1087,10 +1156,41 @@
++NumCands;
}
- if (BestCand == NoCand)
+ // No solutions found, fall back to single block splitting.
+ if (!HasCompact && BestCand == NoCand)
return 0;
- splitAroundRegion(VirtReg, GlobalCand[BestCand], NewVRegs);
+ // Prepare split editor.
+ LiveRangeEdit LREdit(VirtReg, NewVRegs, this);
+ SE->reset(LREdit);
+
+ // Assign all edge bundles to the preferred candidate, or NoCand.
+ BundleCand.assign(Bundles->getNumBundles(), NoCand);
+
+ // Assign bundles for the best candidate region.
+ if (BestCand != NoCand) {
+ GlobalSplitCandidate &Cand = GlobalCand[BestCand];
+ if (unsigned B = Cand.getBundles(BundleCand, BestCand)) {
+ UsedCands.push_back(BestCand);
+ Cand.IntvIdx = SE->openIntv();
+ DEBUG(dbgs() << "Split for " << PrintReg(Cand.PhysReg, TRI) << " in "
+ << B << " bundles, intv " << Cand.IntvIdx << ".\n");
+ }
+ }
+
+ // Assign bundles for the compact region.
+ if (HasCompact) {
+ GlobalSplitCandidate &Cand = GlobalCand.front();
+ assert(!Cand.PhysReg && "Compact region has no physreg");
+ if (unsigned B = Cand.getBundles(BundleCand, 0)) {
+ UsedCands.push_back(0);
+ Cand.IntvIdx = SE->openIntv();
+ DEBUG(dbgs() << "Split for compact region in " << B << " bundles, intv "
+ << Cand.IntvIdx << ".\n");
+ }
+ }
+
+ splitAroundRegion(LREdit, UsedCands);
return 0;
}
@@ -1479,6 +1579,7 @@
ExtraRegInfo.resize(MRI->getNumVirtRegs());
NextCascade = 1;
IntfCache.init(MF, &PhysReg2LiveUnion[0], Indexes, TRI);
+ GlobalCand.resize(32); // This will grow as needed.
allocatePhysRegs();
addMBBLiveIns(MF);
Modified: llvm/branches/exception-handling-rewrite/lib/CodeGen/RegisterCoalescer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/CodeGen/RegisterCoalescer.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/CodeGen/RegisterCoalescer.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/CodeGen/RegisterCoalescer.cpp Wed Jul 27 13:40:48 2011
@@ -760,6 +760,49 @@
return true;
}
+/// eliminateUndefCopy - ProcessImpicitDefs may leave some copies of <undef>
+/// values, it only removes local variables. When we have a copy like:
+///
+/// %vreg1 = COPY %vreg2<undef>
+///
+/// We delete the copy and remove the corresponding value number from %vreg1.
+/// Any uses of that value number are marked as <undef>.
+bool RegisterCoalescer::eliminateUndefCopy(MachineInstr *CopyMI,
+ const CoalescerPair &CP) {
+ SlotIndex Idx = li_->getInstructionIndex(CopyMI);
+ LiveInterval *SrcInt = &li_->getInterval(CP.getSrcReg());
+ if (SrcInt->liveAt(Idx))
+ return false;
+ LiveInterval *DstInt = &li_->getInterval(CP.getDstReg());
+ if (DstInt->liveAt(Idx))
+ return false;
+
+ // No intervals are live-in to CopyMI - it is undef.
+ if (CP.isFlipped())
+ DstInt = SrcInt;
+ SrcInt = 0;
+
+ VNInfo *DeadVNI = DstInt->getVNInfoAt(Idx.getDefIndex());
+ assert(DeadVNI && "No value defined in DstInt");
+ DstInt->removeValNo(DeadVNI);
+
+ // Find new undef uses.
+ for (MachineRegisterInfo::reg_nodbg_iterator
+ I = mri_->reg_nodbg_begin(DstInt->reg), E = mri_->reg_nodbg_end();
+ I != E; ++I) {
+ MachineOperand &MO = I.getOperand();
+ if (MO.isDef() || MO.isUndef())
+ continue;
+ MachineInstr *MI = MO.getParent();
+ SlotIndex Idx = li_->getInstructionIndex(MI);
+ if (DstInt->liveAt(Idx))
+ continue;
+ MO.setIsUndef(true);
+ DEBUG(dbgs() << "\tnew undef: " << Idx << '\t' << *MI);
+ }
+ return true;
+}
+
/// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and
/// update the subregister number if it is not zero. If DstReg is a
/// physical register and the existing subregister number of the def / use
@@ -1018,6 +1061,13 @@
return false; // Not coalescable.
}
+ // Eliminate undefs.
+ if (!CP.isPhys() && eliminateUndefCopy(CopyMI, CP)) {
+ markAsJoined(CopyMI);
+ DEBUG(dbgs() << "\tEliminated copy of <undef> value.\n");
+ return false; // Not coalescable.
+ }
+
DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), tri_)
<< " with " << PrintReg(CP.getDstReg(), tri_, CP.getSubIdx())
<< "\n");
Modified: llvm/branches/exception-handling-rewrite/lib/CodeGen/RegisterCoalescer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/CodeGen/RegisterCoalescer.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/CodeGen/RegisterCoalescer.h (original)
+++ llvm/branches/exception-handling-rewrite/lib/CodeGen/RegisterCoalescer.h Wed Jul 27 13:40:48 2011
@@ -136,6 +136,9 @@
/// markAsJoined - Remember that CopyMI has already been joined.
void markAsJoined(MachineInstr *CopyMI);
+ /// eliminateUndefCopy - Handle copies of undef values.
+ bool eliminateUndefCopy(MachineInstr *CopyMI, const CoalescerPair &CP);
+
public:
static char ID; // Class identification, replacement for typeinfo
RegisterCoalescer() : MachineFunctionPass(ID) {
Modified: llvm/branches/exception-handling-rewrite/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Wed Jul 27 13:40:48 2011
@@ -524,12 +524,11 @@
// Handle some special cases efficiently.
switch (getTypeAction(InVT)) {
- default:
- assert(false && "Unknown type action!");
case TargetLowering::TypeLegal:
case TargetLowering::TypePromoteInteger:
case TargetLowering::TypeSoftenFloat:
case TargetLowering::TypeScalarizeVector:
+ case TargetLowering::TypeWidenVector:
break;
case TargetLowering::TypeExpandInteger:
case TargetLowering::TypeExpandFloat:
Modified: llvm/branches/exception-handling-rewrite/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed Jul 27 13:40:48 2011
@@ -2787,7 +2787,8 @@
// Analyze the access pattern of the vector to see if we can extract
// two subvectors and do the shuffle. The analysis is done by calculating
// the range of elements the mask access on both vectors.
- int MinRange[2] = { SrcNumElts+1, SrcNumElts+1};
+ int MinRange[2] = { static_cast<int>(SrcNumElts+1),
+ static_cast<int>(SrcNumElts+1)};
int MaxRange[2] = {-1, -1};
for (unsigned i = 0; i != MaskNumElts; ++i) {
Modified: llvm/branches/exception-handling-rewrite/lib/MC/MCAsmInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/MC/MCAsmInfo.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/MC/MCAsmInfo.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/MC/MCAsmInfo.cpp Wed Jul 27 13:40:48 2011
@@ -42,6 +42,9 @@
LinkerPrivateGlobalPrefix = "";
InlineAsmStart = "APP";
InlineAsmEnd = "NO_APP";
+ Code16Directive = ".code16";
+ Code32Directive = ".code32";
+ Code64Directive = ".code64";
AssemblerDialect = 0;
AllowQuotesInName = false;
AllowNameToStartWithDigit = false;
Modified: llvm/branches/exception-handling-rewrite/lib/MC/MCAsmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/MC/MCAsmStreamer.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/MC/MCAsmStreamer.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/MC/MCAsmStreamer.cpp Wed Jul 27 13:40:48 2011
@@ -15,6 +15,7 @@
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionMachO.h"
@@ -28,7 +29,6 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Target/TargetLoweringObjectFile.h"
#include <cctype>
using namespace llvm;
@@ -335,8 +335,9 @@
default: assert(0 && "Invalid flag!");
case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;
case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
- case MCAF_Code16: OS << "\t.code\t16"; break;
- case MCAF_Code32: OS << "\t.code\t32"; break;
+ case MCAF_Code16: OS << '\t'<< MAI.getCode16Directive(); break;
+ case MCAF_Code32: OS << '\t'<< MAI.getCode32Directive(); break;
+ case MCAF_Code64: OS << '\t'<< MAI.getCode64Directive(); break;
}
EmitEOL();
}
Modified: llvm/branches/exception-handling-rewrite/lib/MC/MCELFStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/MC/MCELFStreamer.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/MC/MCELFStreamer.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/MC/MCELFStreamer.cpp Wed Jul 27 13:40:48 2011
@@ -53,8 +53,9 @@
void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
switch (Flag) {
case MCAF_SyntaxUnified: return; // no-op here.
- case MCAF_Code16: return; // no-op here.
- case MCAF_Code32: return; // no-op here.
+ case MCAF_Code16: return; // Change parsing mode; no-op here.
+ case MCAF_Code32: return; // Change parsing mode; no-op here.
+ case MCAF_Code64: return; // Change parsing mode; no-op here.
case MCAF_SubsectionsViaSymbols:
getAssembler().setSubsectionsViaSymbols(true);
return;
Modified: llvm/branches/exception-handling-rewrite/lib/MC/MCMachOStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/MC/MCMachOStreamer.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/MC/MCMachOStreamer.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/MC/MCMachOStreamer.cpp Wed Jul 27 13:40:48 2011
@@ -143,8 +143,9 @@
// Do any generic stuff we need to do.
switch (Flag) {
case MCAF_SyntaxUnified: return; // no-op here.
- case MCAF_Code16: return; // no-op here.
- case MCAF_Code32: return; // no-op here.
+ case MCAF_Code16: return; // Change parsing mode; no-op here.
+ case MCAF_Code32: return; // Change parsing mode; no-op here.
+ case MCAF_Code64: return; // Change parsing mode; no-op here.
case MCAF_SubsectionsViaSymbols:
getAssembler().setSubsectionsViaSymbols(true);
return;
Modified: llvm/branches/exception-handling-rewrite/lib/MC/MCParser/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/MC/MCParser/AsmParser.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/MC/MCParser/AsmParser.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/MC/MCParser/AsmParser.cpp Wed Jul 27 13:40:48 2011
@@ -1146,7 +1146,7 @@
if (IDVal == ".include")
return ParseDirectiveInclude();
- if (IDVal == ".code16" || IDVal == ".code32" || IDVal == ".code64")
+ if (IDVal == ".code16")
return TokError(Twine(IDVal) + " not supported yet");
// Look up the handler in the handler table.
Modified: llvm/branches/exception-handling-rewrite/lib/Support/BlockFrequency.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Support/BlockFrequency.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Support/BlockFrequency.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Support/BlockFrequency.cpp Wed Jul 27 13:40:48 2011
@@ -18,8 +18,10 @@
using namespace llvm;
+namespace {
+
/// mult96bit - Multiply FREQ by N and store result in W array.
-void BlockFrequency::mult96bit(uint64_t freq, uint32_t N, uint64_t W[2]) {
+void mult96bit(uint64_t freq, uint32_t N, uint64_t W[2]) {
uint64_t u0 = freq & UINT32_MAX;
uint64_t u1 = freq >> 32;
@@ -41,11 +43,12 @@
/// div96bit - Divide 96-bit value stored in W array by D. Return 64-bit frequency.
-uint64_t BlockFrequency::div96bit(uint64_t W[2], uint32_t D) {
+uint64_t div96bit(uint64_t W[2], uint32_t D) {
uint64_t y = W[0];
uint64_t x = W[1];
+ int i;
- for (int i = 1; i <= 64; ++i) {
+ for (i = 1; i <= 64 && x; ++i) {
uint32_t t = (int)x >> 31;
x = (x << 1) | (y >> 63);
y = y << 1;
@@ -55,9 +58,12 @@
}
}
- return y;
+ return y << (64 - i + 1);
+}
+
}
+
BlockFrequency &BlockFrequency::operator*=(const BranchProbability &Prob) {
uint32_t n = Prob.getNumerator();
uint32_t d = Prob.getDenominator();
Modified: llvm/branches/exception-handling-rewrite/lib/Support/ConstantRange.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Support/ConstantRange.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Support/ConstantRange.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Support/ConstantRange.cpp Wed Jul 27 13:40:48 2011
@@ -21,11 +21,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Constants.h"
+#include "llvm/InstrTypes.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Instructions.h"
using namespace llvm;
/// Initialize a full (the default) or empty set for the specified type.
@@ -57,55 +56,55 @@
uint32_t W = CR.getBitWidth();
switch (Pred) {
default: assert(!"Invalid ICmp predicate to makeICmpRegion()");
- case ICmpInst::ICMP_EQ:
+ case CmpInst::ICMP_EQ:
return CR;
- case ICmpInst::ICMP_NE:
+ case CmpInst::ICMP_NE:
if (CR.isSingleElement())
return ConstantRange(CR.getUpper(), CR.getLower());
return ConstantRange(W);
- case ICmpInst::ICMP_ULT: {
+ case CmpInst::ICMP_ULT: {
APInt UMax(CR.getUnsignedMax());
if (UMax.isMinValue())
return ConstantRange(W, /* empty */ false);
return ConstantRange(APInt::getMinValue(W), UMax);
}
- case ICmpInst::ICMP_SLT: {
+ case CmpInst::ICMP_SLT: {
APInt SMax(CR.getSignedMax());
if (SMax.isMinSignedValue())
return ConstantRange(W, /* empty */ false);
return ConstantRange(APInt::getSignedMinValue(W), SMax);
}
- case ICmpInst::ICMP_ULE: {
+ case CmpInst::ICMP_ULE: {
APInt UMax(CR.getUnsignedMax());
if (UMax.isMaxValue())
return ConstantRange(W);
return ConstantRange(APInt::getMinValue(W), UMax + 1);
}
- case ICmpInst::ICMP_SLE: {
+ case CmpInst::ICMP_SLE: {
APInt SMax(CR.getSignedMax());
if (SMax.isMaxSignedValue())
return ConstantRange(W);
return ConstantRange(APInt::getSignedMinValue(W), SMax + 1);
}
- case ICmpInst::ICMP_UGT: {
+ case CmpInst::ICMP_UGT: {
APInt UMin(CR.getUnsignedMin());
if (UMin.isMaxValue())
return ConstantRange(W, /* empty */ false);
return ConstantRange(UMin + 1, APInt::getNullValue(W));
}
- case ICmpInst::ICMP_SGT: {
+ case CmpInst::ICMP_SGT: {
APInt SMin(CR.getSignedMin());
if (SMin.isMaxSignedValue())
return ConstantRange(W, /* empty */ false);
return ConstantRange(SMin + 1, APInt::getSignedMinValue(W));
}
- case ICmpInst::ICMP_UGE: {
+ case CmpInst::ICMP_UGE: {
APInt UMin(CR.getUnsignedMin());
if (UMin.isMinValue())
return ConstantRange(W);
return ConstantRange(UMin, APInt::getNullValue(W));
}
- case ICmpInst::ICMP_SGE: {
+ case CmpInst::ICMP_SGE: {
APInt SMin(CR.getSignedMin());
if (SMin.isMinSignedValue())
return ConstantRange(W);
Modified: llvm/branches/exception-handling-rewrite/lib/Support/Triple.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Support/Triple.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Support/Triple.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Support/Triple.cpp Wed Jul 27 13:40:48 2011
@@ -97,6 +97,7 @@
case DragonFly: return "dragonfly";
case FreeBSD: return "freebsd";
case IOS: return "ios";
+ case KFreeBSD: return "kfreebsd";
case Linux: return "linux";
case Lv2: return "lv2";
case MacOSX: return "macosx";
@@ -327,6 +328,8 @@
return FreeBSD;
else if (OSName.startswith("ios"))
return IOS;
+ else if (OSName.startswith("kfreebsd"))
+ return KFreeBSD;
else if (OSName.startswith("linux"))
return Linux;
else if (OSName.startswith("lv2"))
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMAsmPrinter.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMAsmPrinter.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMAsmPrinter.cpp Wed Jul 27 13:40:48 2011
@@ -994,7 +994,8 @@
i != NumOps; ++i)
RegList.push_back(MI->getOperand(i).getReg());
break;
- case ARM::STR_PRE:
+ case ARM::STR_PRE_IMM:
+ case ARM::STR_PRE_REG:
assert(MI->getOperand(2).getReg() == ARM::SP &&
"Only stack pointer as a source reg is supported");
RegList.push_back(SrcReg);
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMCodeEmitter.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMCodeEmitter.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMCodeEmitter.cpp Wed Jul 27 13:40:48 2011
@@ -215,8 +215,6 @@
const { return 0; }
unsigned getT2SORegOpValue(const MachineInstr &MI, unsigned Op)
const { return 0; }
- unsigned getRotImmOpValue(const MachineInstr &MI, unsigned Op)
- const { return 0; }
unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op)
const { return 0; }
unsigned getT2AdrLabelOpValue(const MachineInstr &MI, unsigned Op)
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMFastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMFastISel.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMFastISel.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMFastISel.cpp Wed Jul 27 13:40:48 2011
@@ -2003,15 +2003,15 @@
default: return false;
case MVT::i16:
if (isZext)
- Opc = isThumb ? ARM::t2UXTHr : ARM::UXTHr;
+ Opc = isThumb ? ARM::t2UXTH : ARM::UXTH;
else
- Opc = isThumb ? ARM::t2SXTHr : ARM::SXTHr;
+ Opc = isThumb ? ARM::t2SXTH : ARM::SXTH;
break;
case MVT::i8:
if (isZext)
- Opc = isThumb ? ARM::t2UXTBr : ARM::UXTBr;
+ Opc = isThumb ? ARM::t2UXTB : ARM::UXTB;
else
- Opc = isThumb ? ARM::t2SXTBr : ARM::SXTBr;
+ Opc = isThumb ? ARM::t2SXTB : ARM::SXTB;
break;
case MVT::i1:
if (isZext) {
@@ -2033,6 +2033,8 @@
.addReg(SrcReg);
if (isBoolZext)
MIB.addImm(1);
+ else
+ MIB.addImm(0);
AddOptionalDefs(MIB);
UpdateValueMap(I, DestReg);
return true;
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMFrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMFrameLowering.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMFrameLowering.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMFrameLowering.cpp Wed Jul 27 13:40:48 2011
@@ -93,7 +93,8 @@
return false;
return true;
}
- if ((MI->getOpcode() == ARM::LDR_POST ||
+ if ((MI->getOpcode() == ARM::LDR_POST_IMM ||
+ MI->getOpcode() == ARM::LDR_POST_REG ||
MI->getOpcode() == ARM::t2LDR_POST) &&
isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs) &&
MI->getOperand(1).getReg() == ARM::SP)
@@ -590,7 +591,7 @@
.addReg(ARM::SP).setMIFlags(MIFlags);
// ARM mode needs an extra reg0 here due to addrmode2. Will go away once
// that refactoring is complete (eventually).
- if (StrOpc == ARM::STR_PRE) {
+ if (StrOpc == ARM::STR_PRE_REG || StrOpc == ARM::STR_PRE_IMM) {
MIB.addReg(0);
MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::sub, 4, ARM_AM::no_shift));
} else
@@ -665,7 +666,7 @@
.addReg(ARM::SP);
// ARM mode needs an extra reg0 here due to addrmode2. Will go away once
// that refactoring is complete (eventually).
- if (LdrOpc == ARM::LDR_POST) {
+ if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
MIB.addReg(0);
MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::add, 4, ARM_AM::no_shift));
} else
@@ -687,7 +688,7 @@
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
- unsigned PushOneOpc = AFI->isThumbFunction() ? ARM::t2STR_PRE : ARM::STR_PRE;
+ unsigned PushOneOpc = AFI->isThumbFunction() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM;
unsigned FltOpc = ARM::VSTMDDB_UPD;
emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register,
MachineInstr::FrameSetup);
@@ -711,7 +712,7 @@
bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
- unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST;
+ unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
unsigned FltOpc = ARM::VLDMDIA_UPD;
emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register);
emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false,
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMISelDAGToDAG.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMISelDAGToDAG.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMISelDAGToDAG.cpp Wed Jul 27 13:40:48 2011
@@ -129,7 +129,9 @@
return true;
}
- bool SelectAddrMode2Offset(SDNode *Op, SDValue N,
+ bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
+ SDValue &Offset, SDValue &Opc);
+ bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc);
bool SelectAddrMode3(SDValue N, SDValue &Base,
SDValue &Offset, SDValue &Opc);
@@ -714,7 +716,7 @@
return AM2_SHOP;
}
-bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N,
+bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc) {
unsigned Opcode = Op->getOpcode();
ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
@@ -723,13 +725,8 @@
ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
? ARM_AM::add : ARM_AM::sub;
int Val;
- if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
- Offset = CurDAG->getRegister(0, MVT::i32);
- Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
- ARM_AM::no_shift),
- MVT::i32);
- return true;
- }
+ if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
+ return false;
Offset = N;
ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
@@ -755,6 +752,28 @@
return true;
}
+bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
+ SDValue &Offset, SDValue &Opc) {
+ unsigned Opcode = Op->getOpcode();
+ ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
+ ? cast<LoadSDNode>(Op)->getAddressingMode()
+ : cast<StoreSDNode>(Op)->getAddressingMode();
+ ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
+ ? ARM_AM::add : ARM_AM::sub;
+ int Val;
+ if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
+ Offset = CurDAG->getRegister(0, MVT::i32);
+ Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
+ ARM_AM::no_shift),
+ MVT::i32);
+ return true;
+ }
+
+ return false;
+}
+
+
+
bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
SDValue &Base, SDValue &Offset,
@@ -1298,9 +1317,14 @@
unsigned Opcode = 0;
bool Match = false;
if (LoadedVT == MVT::i32 &&
- SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) {
- Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST;
+ SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
+ Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST_IMM;
+ Match = true;
+ } else if (LoadedVT == MVT::i32 &&
+ SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
+ Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST_REG;
Match = true;
+
} else if (LoadedVT == MVT::i16 &&
SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Match = true;
@@ -1314,9 +1338,12 @@
Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
}
} else {
- if (SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) {
+ if (SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
+ Match = true;
+ Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST_IMM;
+ } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Match = true;
- Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST;
+ Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST_REG;
}
}
}
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMISelLowering.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMISelLowering.cpp Wed Jul 27 13:40:48 2011
@@ -5125,12 +5125,12 @@
case 1:
ldrOpc = isThumb2 ? ARM::t2LDREXB : ARM::LDREXB;
strOpc = isThumb2 ? ARM::t2STREXB : ARM::STREXB;
- extendOpc = isThumb2 ? ARM::t2SXTBr : ARM::SXTBr;
+ extendOpc = isThumb2 ? ARM::t2SXTB : ARM::SXTB;
break;
case 2:
ldrOpc = isThumb2 ? ARM::t2LDREXH : ARM::LDREXH;
strOpc = isThumb2 ? ARM::t2STREXH : ARM::STREXH;
- extendOpc = isThumb2 ? ARM::t2SXTHr : ARM::SXTHr;
+ extendOpc = isThumb2 ? ARM::t2SXTH : ARM::SXTH;
break;
case 4:
ldrOpc = isThumb2 ? ARM::t2LDREX : ARM::LDREX;
@@ -5175,7 +5175,9 @@
// Sign extend the value, if necessary.
if (signExtend && extendOpc) {
oldval = MRI.createVirtualRegister(ARM::GPRRegisterClass);
- AddDefaultPred(BuildMI(BB, dl, TII->get(extendOpc), oldval).addReg(dest));
+ AddDefaultPred(BuildMI(BB, dl, TII->get(extendOpc), oldval)
+ .addReg(dest)
+ .addImm(0));
}
// Build compare and cmov instructions.
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrFormats.td?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrFormats.td (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrFormats.td Wed Jul 27 13:40:48 2011
@@ -418,11 +418,11 @@
: I<oops, iops, AddrModeNone, 4, IndexModeNone, LdStExFrm, itin,
opc, asm, "", pattern> {
bits<4> Rt;
- bits<4> Rn;
+ bits<4> addr;
let Inst{27-23} = 0b00011;
let Inst{22-21} = opcod;
let Inst{20} = 1;
- let Inst{19-16} = Rn;
+ let Inst{19-16} = addr;
let Inst{15-12} = Rt;
let Inst{11-0} = 0b111110011111;
}
@@ -442,14 +442,14 @@
let Inst{3-0} = Rt;
}
class AIswp<bit b, dag oops, dag iops, string opc, list<dag> pattern>
- : AI<oops, iops, MiscFrm, NoItinerary, opc, "\t$Rt, $Rt2, [$Rn]", pattern> {
+ : AI<oops, iops, MiscFrm, NoItinerary, opc, "\t$Rt, $Rt2, $addr", pattern> {
bits<4> Rt;
bits<4> Rt2;
- bits<4> Rn;
+ bits<4> addr;
let Inst{27-23} = 0b00010;
let Inst{22} = b;
let Inst{21-20} = 0b00;
- let Inst{19-16} = Rn;
+ let Inst{19-16} = addr;
let Inst{15-12} = Rt;
let Inst{11-4} = 0b00001001;
let Inst{3-0} = Rt2;
@@ -507,22 +507,41 @@
let Inst{20} = isLd; // L bit
let Inst{15-12} = Rt;
}
-class AI2stridx<bit isByte, bit isPre, dag oops, dag iops,
+class AI2stridx_reg<bit isByte, bit isPre, dag oops, dag iops,
+ IndexMode im, Format f, InstrItinClass itin, string opc,
+ string asm, string cstr, list<dag> pattern>
+ : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr,
+ pattern> {
+ // AM2 store w/ two operands: (GPR, am2offset)
+ // {12} isAdd
+ // {11-0} imm12/Rm
+ bits<14> offset;
+ bits<4> Rn;
+ let Inst{25} = 1;
+ let Inst{23} = offset{12};
+ let Inst{19-16} = Rn;
+ let Inst{11-5} = offset{11-5};
+ let Inst{4} = 0;
+ let Inst{3-0} = offset{3-0};
+}
+
+class AI2stridx_imm<bit isByte, bit isPre, dag oops, dag iops,
IndexMode im, Format f, InstrItinClass itin, string opc,
string asm, string cstr, list<dag> pattern>
: AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr,
pattern> {
// AM2 store w/ two operands: (GPR, am2offset)
- // {13} 1 == Rm, 0 == imm12
// {12} isAdd
// {11-0} imm12/Rm
bits<14> offset;
bits<4> Rn;
- let Inst{25} = offset{13};
+ let Inst{25} = 0;
let Inst{23} = offset{12};
let Inst{19-16} = Rn;
let Inst{11-0} = offset{11-0};
}
+
+
// FIXME: Merge with the above class when addrmode2 gets used for STR, STRB
// but for now use this class for STRT and STRBT.
class AI2stridxT<bit isByte, bit isPre, dag oops, dag iops,
@@ -600,7 +619,7 @@
let Inst{11-8} = addr{7-4}; // imm7_4/zero
let Inst{7-4} = op;
let Inst{3-0} = addr{3-0}; // imm3_0/Rm
- let AsmMatchConverter = "CvtLdWriteBackRegAddrMode3";
+ let AsmMatchConverter = "cvtLdWriteBackRegAddrMode3";
}
class AI3stridx<bits<4> op, bit isByte, bit isPre, dag oops, dag iops,
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrInfo.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrInfo.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrInfo.cpp Wed Jul 27 13:40:48 2011
@@ -31,13 +31,15 @@
switch (Opc) {
default: break;
case ARM::LDR_PRE:
- case ARM::LDR_POST:
+ case ARM::LDR_POST_IMM:
+ case ARM::LDR_POST_REG:
return ARM::LDRi12;
case ARM::LDRH_PRE:
case ARM::LDRH_POST:
return ARM::LDRH;
case ARM::LDRB_PRE:
- case ARM::LDRB_POST:
+ case ARM::LDRB_POST_IMM:
+ case ARM::LDRB_POST_REG:
return ARM::LDRBi12;
case ARM::LDRSH_PRE:
case ARM::LDRSH_POST:
@@ -45,14 +47,18 @@
case ARM::LDRSB_PRE:
case ARM::LDRSB_POST:
return ARM::LDRSB;
- case ARM::STR_PRE:
- case ARM::STR_POST:
+ case ARM::STR_PRE_IMM:
+ case ARM::STR_PRE_REG:
+ case ARM::STR_POST_IMM:
+ case ARM::STR_POST_REG:
return ARM::STRi12;
case ARM::STRH_PRE:
case ARM::STRH_POST:
return ARM::STRH;
- case ARM::STRB_PRE:
- case ARM::STRB_POST:
+ case ARM::STRB_PRE_IMM:
+ case ARM::STRB_PRE_REG:
+ case ARM::STRB_POST_IMM:
+ case ARM::STRB_POST_REG:
return ARM::STRBi12;
}
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrInfo.td?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrInfo.td Wed Jul 27 13:40:48 2011
@@ -388,10 +388,20 @@
}
// rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24.
-def rot_imm : Operand<i32>, ImmLeaf<i32, [{
- int32_t v = (int32_t)Imm;
- return v == 8 || v == 16 || v == 24; }]> {
- let EncoderMethod = "getRotImmOpValue";
+def rot_imm_XFORM: SDNodeXForm<imm, [{
+ switch (N->getZExtValue()){
+ default: assert(0);
+ case 0: return CurDAG->getTargetConstant(0, MVT::i32);
+ case 8: return CurDAG->getTargetConstant(1, MVT::i32);
+ case 16: return CurDAG->getTargetConstant(2, MVT::i32);
+ case 24: return CurDAG->getTargetConstant(3, MVT::i32);
+ }
+}]>;
+def rot_imm : Operand<i32>, PatLeaf<(i32 imm), [{
+ int32_t v = N->getZExtValue();
+ return v == 8 || v == 16 || v == 24; }],
+ rot_imm_XFORM> {
+ let PrintMethod = "printRotImmOperand";
}
// shift_imm: An integer that encodes a shift amount and the type of shift
@@ -494,13 +504,16 @@
def Imm0_31AsmOperand: AsmOperandClass { let Name = "Imm0_31"; }
def imm0_31 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 32;
-}]>;
+}]> {
+ let ParserMatchClass = Imm0_31AsmOperand;
+}
/// imm0_31_m1 - Matches and prints like imm0_31, but encodes as 'value - 1'.
def imm0_31_m1 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 32;
}]> {
let EncoderMethod = "getImmMinusOneOpValue";
+ let DecoderMethod = "DecodeImmMinusOneOperand";
}
// imm0_65535_expr - For movt/movw - 16-bit immediate that can also reference
@@ -515,6 +528,15 @@
let ParserMatchClass = Imm0_65535ExprAsmOperand;
}
+/// imm24b - True if the 32-bit immediate is encodable in 24 bits.
+def Imm24bitAsmOperand: AsmOperandClass { let Name = "Imm24bit"; }
+def imm24b : Operand<i32>, ImmLeaf<i32, [{
+ return Imm >= 0 && Imm <= 0xffffff;
+}]> {
+ let ParserMatchClass = Imm24bitAsmOperand;
+}
+
+
/// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield
/// e.g., 0xf000ffff
def bf_inv_mask_imm : Operand<i32>,
@@ -595,14 +617,23 @@
let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}
-def am2offset : Operand<i32>,
- ComplexPattern<i32, 2, "SelectAddrMode2Offset",
+def am2offset_reg : Operand<i32>,
+ ComplexPattern<i32, 2, "SelectAddrMode2OffsetReg",
[], [SDNPWantRoot]> {
let EncoderMethod = "getAddrMode2OffsetOpValue";
let PrintMethod = "printAddrMode2OffsetOperand";
let MIOperandInfo = (ops GPR, i32imm);
}
+def am2offset_imm : Operand<i32>,
+ ComplexPattern<i32, 2, "SelectAddrMode2OffsetImm",
+ [], [SDNPWantRoot]> {
+ let EncoderMethod = "getAddrMode2OffsetOpValue";
+ let PrintMethod = "printAddrMode2OffsetOperand";
+ let MIOperandInfo = (ops GPR, i32imm);
+}
+
+
// addrmode3 := reg +/- reg
// addrmode3 := reg +/- imm8
//
@@ -955,102 +986,55 @@
/// AI_ext_rrot - A unary operation with two forms: one whose operand is a
/// register and one whose operand is a register rotated by 8/16/24.
/// FIXME: Remove the 'r' variant. Its rot_imm is zero.
-multiclass AI_ext_rrot<bits<8> opcod, string opc, PatFrag opnode> {
- def r : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm),
- IIC_iEXTr, opc, "\t$Rd, $Rm",
- [(set GPR:$Rd, (opnode GPR:$Rm))]>,
- Requires<[IsARM, HasV6]> {
- bits<4> Rd;
- bits<4> Rm;
- let Inst{19-16} = 0b1111;
- let Inst{15-12} = Rd;
- let Inst{11-10} = 0b00;
- let Inst{3-0} = Rm;
- }
- def r_rot : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm, rot_imm:$rot),
- IIC_iEXTr, opc, "\t$Rd, $Rm, ror $rot",
- [(set GPR:$Rd, (opnode (rotr GPR:$Rm, rot_imm:$rot)))]>,
- Requires<[IsARM, HasV6]> {
- bits<4> Rd;
- bits<4> Rm;
- bits<2> rot;
- let Inst{19-16} = 0b1111;
- let Inst{15-12} = Rd;
- let Inst{11-10} = rot;
- let Inst{3-0} = Rm;
- }
+class AI_ext_rrot<bits<8> opcod, string opc, PatFrag opnode>
+ : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm, rot_imm:$rot),
+ IIC_iEXTr, opc, "\t$Rd, $Rm$rot",
+ [(set GPR:$Rd, (opnode (rotr GPR:$Rm, rot_imm:$rot)))]>,
+ Requires<[IsARM, HasV6]> {
+ bits<4> Rd;
+ bits<4> Rm;
+ bits<2> rot;
+ let Inst{19-16} = 0b1111;
+ let Inst{15-12} = Rd;
+ let Inst{11-10} = rot;
+ let Inst{3-0} = Rm;
}
-multiclass AI_ext_rrot_np<bits<8> opcod, string opc> {
- def r : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm),
- IIC_iEXTr, opc, "\t$Rd, $Rm",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM, HasV6]> {
- let Inst{19-16} = 0b1111;
- let Inst{11-10} = 0b00;
- }
- def r_rot : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm, rot_imm:$rot),
- IIC_iEXTr, opc, "\t$Rd, $Rm, ror $rot",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM, HasV6]> {
- bits<2> rot;
- let Inst{19-16} = 0b1111;
- let Inst{11-10} = rot;
- }
+class AI_ext_rrot_np<bits<8> opcod, string opc>
+ : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm, rot_imm:$rot),
+ IIC_iEXTr, opc, "\t$Rd, $Rm$rot", []>,
+ Requires<[IsARM, HasV6]> {
+ bits<2> rot;
+ let Inst{19-16} = 0b1111;
+ let Inst{11-10} = rot;
}
/// AI_exta_rrot - A binary operation with two forms: one whose operand is a
/// register and one whose operand is a register rotated by 8/16/24.
-multiclass AI_exta_rrot<bits<8> opcod, string opc, PatFrag opnode> {
- def rr : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
- IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm",
- [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]>,
- Requires<[IsARM, HasV6]> {
- bits<4> Rd;
- bits<4> Rm;
- bits<4> Rn;
- let Inst{19-16} = Rn;
- let Inst{15-12} = Rd;
- let Inst{11-10} = 0b00;
- let Inst{9-4} = 0b000111;
- let Inst{3-0} = Rm;
- }
- def rr_rot : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm,
- rot_imm:$rot),
- IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm, ror $rot",
- [(set GPR:$Rd, (opnode GPR:$Rn,
- (rotr GPR:$Rm, rot_imm:$rot)))]>,
- Requires<[IsARM, HasV6]> {
- bits<4> Rd;
- bits<4> Rm;
- bits<4> Rn;
- bits<2> rot;
- let Inst{19-16} = Rn;
- let Inst{15-12} = Rd;
- let Inst{11-10} = rot;
- let Inst{9-4} = 0b000111;
- let Inst{3-0} = Rm;
- }
+class AI_exta_rrot<bits<8> opcod, string opc, PatFrag opnode>
+ : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, rot_imm:$rot),
+ IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm$rot",
+ [(set GPR:$Rd, (opnode GPR:$Rn, (rotr GPR:$Rm, rot_imm:$rot)))]>,
+ Requires<[IsARM, HasV6]> {
+ bits<4> Rd;
+ bits<4> Rm;
+ bits<4> Rn;
+ bits<2> rot;
+ let Inst{19-16} = Rn;
+ let Inst{15-12} = Rd;
+ let Inst{11-10} = rot;
+ let Inst{9-4} = 0b000111;
+ let Inst{3-0} = Rm;
}
-// For disassembly only.
-multiclass AI_exta_rrot_np<bits<8> opcod, string opc> {
- def rr : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
- IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM, HasV6]> {
- let Inst{11-10} = 0b00;
- }
- def rr_rot : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm,
- rot_imm:$rot),
- IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm, ror $rot",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM, HasV6]> {
- bits<4> Rn;
- bits<2> rot;
- let Inst{19-16} = Rn;
- let Inst{11-10} = rot;
- }
+class AI_exta_rrot_np<bits<8> opcod, string opc>
+ : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, rot_imm:$rot),
+ IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm$rot", []>,
+ Requires<[IsARM, HasV6]> {
+ bits<4> Rn;
+ bits<2> rot;
+ let Inst{19-16} = Rn;
+ let Inst{11-10} = rot;
}
/// AI1_adde_sube_irs - Define instructions and patterns for adde and sube.
@@ -1730,10 +1714,9 @@
let Inst{3-0} = opt;
}
-// Supervisor Call (Software Interrupt) -- for disassembly only
+// Supervisor Call (Software Interrupt)
let isCall = 1, Uses = [SP] in {
-def SVC : ABI<0b1111, (outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc",
- [/* For disassembly only; pattern left blank */]> {
+def SVC : ABI<0b1111, (outs), (ins imm24b:$svc), IIC_Br, "svc", "\t$svc", []> {
bits<24> svc;
let Inst{23-0} = svc;
}
@@ -1835,7 +1818,7 @@
(ins addrmode2:$addr), IndexModePre, LdFrm, itin,
opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
// {17-14} Rn
- // {13} 1 == Rm, 0 == imm12
+ // {13} reg vs. imm
// {12} isAdd
// {11-0} imm12/Rm
bits<18> addr;
@@ -1843,21 +1826,37 @@
let Inst{23} = addr{12};
let Inst{19-16} = addr{17-14};
let Inst{11-0} = addr{11-0};
- let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
+ let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
}
- def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
- (ins GPR:$Rn, am2offset:$offset),
+
+ def _POST_REG : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
+ (ins GPR:$Rn, am2offset_reg:$offset),
+ IndexModePost, LdFrm, itin,
+ opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> {
+ // {12} isAdd
+ // {11-0} imm12/Rm
+ bits<14> offset;
+ bits<4> Rn;
+ let Inst{25} = 1;
+ let Inst{23} = offset{12};
+ let Inst{19-16} = Rn;
+ let Inst{11-0} = offset{11-0};
+ let DecoderMethod = "DecodeAddrMode2IdxInstruction";
+ }
+
+ def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
+ (ins GPR:$Rn, am2offset_imm:$offset),
IndexModePost, LdFrm, itin,
opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> {
- // {13} 1 == Rm, 0 == imm12
// {12} isAdd
// {11-0} imm12/Rm
bits<14> offset;
bits<4> Rn;
- let Inst{25} = offset{13};
+ let Inst{25} = 0;
let Inst{23} = offset{12};
let Inst{19-16} = Rn;
let Inst{11-0} = offset{11-0};
+ let DecoderMethod = "DecodeAddrMode2IdxInstruction";
}
}
@@ -1940,7 +1939,7 @@
let Inst{21} = 1; // overwrite
let Inst{19-16} = addr{17-14};
let Inst{11-0} = addr{11-0};
- let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
+ let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
}
def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
(ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_bh_ru,
@@ -1955,7 +1954,7 @@
let Inst{21} = 1; // overwrite
let Inst{19-16} = addr{17-14};
let Inst{11-0} = addr{11-0};
- let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
+ let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
}
def LDRSBT : AI3ldstidxT<0b1101, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
(ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru,
@@ -1988,36 +1987,69 @@
"strd", "\t$Rt, $src2, $addr", []>, Requires<[IsARM, HasV5TE]>;
// Indexed stores
-def STR_PRE : AI2stridx<0, 1, (outs GPR:$Rn_wb),
- (ins GPR:$Rt, GPR:$Rn, am2offset:$offset),
+def STR_PRE_REG : AI2stridx_reg<0, 1, (outs GPR:$Rn_wb),
+ (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset),
+ IndexModePre, StFrm, IIC_iStore_ru,
+ "str", "\t$Rt, [$Rn, $offset]!",
+ "$Rn = $Rn_wb, at earlyclobber $Rn_wb",
+ [(set GPR:$Rn_wb,
+ (pre_store GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>;
+def STR_PRE_IMM : AI2stridx_imm<0, 1, (outs GPR:$Rn_wb),
+ (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset),
IndexModePre, StFrm, IIC_iStore_ru,
"str", "\t$Rt, [$Rn, $offset]!",
"$Rn = $Rn_wb, at earlyclobber $Rn_wb",
[(set GPR:$Rn_wb,
- (pre_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]>;
+ (pre_store GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>;
+
-def STR_POST : AI2stridx<0, 0, (outs GPR:$Rn_wb),
- (ins GPR:$Rt, GPR:$Rn, am2offset:$offset),
+
+def STR_POST_REG : AI2stridx_reg<0, 0, (outs GPR:$Rn_wb),
+ (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset),
+ IndexModePost, StFrm, IIC_iStore_ru,
+ "str", "\t$Rt, [$Rn], $offset",
+ "$Rn = $Rn_wb, at earlyclobber $Rn_wb",
+ [(set GPR:$Rn_wb,
+ (post_store GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>;
+def STR_POST_IMM : AI2stridx_imm<0, 0, (outs GPR:$Rn_wb),
+ (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset),
IndexModePost, StFrm, IIC_iStore_ru,
"str", "\t$Rt, [$Rn], $offset",
"$Rn = $Rn_wb, at earlyclobber $Rn_wb",
[(set GPR:$Rn_wb,
- (post_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]>;
+ (post_store GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>;
-def STRB_PRE : AI2stridx<1, 1, (outs GPR:$Rn_wb),
- (ins GPR:$Rt, GPR:$Rn, am2offset:$offset),
+
+def STRB_PRE_REG : AI2stridx_reg<1, 1, (outs GPR:$Rn_wb),
+ (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset),
IndexModePre, StFrm, IIC_iStore_bh_ru,
"strb", "\t$Rt, [$Rn, $offset]!",
"$Rn = $Rn_wb, at earlyclobber $Rn_wb",
[(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt,
- GPR:$Rn, am2offset:$offset))]>;
-def STRB_POST: AI2stridx<1, 0, (outs GPR:$Rn_wb),
- (ins GPR:$Rt, GPR:$Rn, am2offset:$offset),
+ GPR:$Rn, am2offset_reg:$offset))]>;
+def STRB_PRE_IMM : AI2stridx_imm<1, 1, (outs GPR:$Rn_wb),
+ (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset),
+ IndexModePre, StFrm, IIC_iStore_bh_ru,
+ "strb", "\t$Rt, [$Rn, $offset]!",
+ "$Rn = $Rn_wb, at earlyclobber $Rn_wb",
+ [(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt,
+ GPR:$Rn, am2offset_imm:$offset))]>;
+
+def STRB_POST_REG: AI2stridx_reg<1, 0, (outs GPR:$Rn_wb),
+ (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset),
IndexModePost, StFrm, IIC_iStore_bh_ru,
"strb", "\t$Rt, [$Rn], $offset",
"$Rn = $Rn_wb, at earlyclobber $Rn_wb",
[(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt,
- GPR:$Rn, am2offset:$offset))]>;
+ GPR:$Rn, am2offset_reg:$offset))]>;
+def STRB_POST_IMM: AI2stridx_imm<1, 0, (outs GPR:$Rn_wb),
+ (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset),
+ IndexModePost, StFrm, IIC_iStore_bh_ru,
+ "strb", "\t$Rt, [$Rn], $offset",
+ "$Rn = $Rn_wb, at earlyclobber $Rn_wb",
+ [(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt,
+ GPR:$Rn, am2offset_imm:$offset))]>;
+
def STRH_PRE : AI3stridx<0b1011, 0, 1, (outs GPR:$Rn_wb),
(ins GPR:$Rt, GPR:$Rn, am3offset:$offset),
@@ -2058,7 +2090,7 @@
"strt", "\t$Rt, $addr", "$addr.base = $Rn_wb",
[/* For disassembly only; pattern left blank */]> {
let Inst{21} = 1; // overwrite
- let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";
+ let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
}
def STRBT : AI2stridxT<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),
@@ -2066,7 +2098,7 @@
"strbt", "\t$Rt, $addr", "$addr.base = $Rn_wb",
[/* For disassembly only; pattern left blank */]> {
let Inst{21} = 1; // overwrite
- let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";
+ let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
}
def STRHT: AI3sthpo<(outs GPR:$base_wb), (ins GPR:$Rt, addrmode3:$addr),
@@ -2074,7 +2106,7 @@
"strht", "\t$Rt, $addr", "$addr.base = $base_wb",
[/* For disassembly only; pattern left blank */]> {
let Inst{21} = 1; // overwrite
- let AsmMatchConverter = "CvtStWriteBackRegAddrMode3";
+ let AsmMatchConverter = "cvtStWriteBackRegAddrMode3";
}
//===----------------------------------------------------------------------===//
@@ -2314,30 +2346,28 @@
// Sign extenders
-defm SXTB : AI_ext_rrot<0b01101010,
+def SXTB : AI_ext_rrot<0b01101010,
"sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>;
-defm SXTH : AI_ext_rrot<0b01101011,
+def SXTH : AI_ext_rrot<0b01101011,
"sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>;
-defm SXTAB : AI_exta_rrot<0b01101010,
+def SXTAB : AI_exta_rrot<0b01101010,
"sxtab", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
-defm SXTAH : AI_exta_rrot<0b01101011,
+def SXTAH : AI_exta_rrot<0b01101011,
"sxtah", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
-// For disassembly only
-defm SXTB16 : AI_ext_rrot_np<0b01101000, "sxtb16">;
+def SXTB16 : AI_ext_rrot_np<0b01101000, "sxtb16">;
-// For disassembly only
-defm SXTAB16 : AI_exta_rrot_np<0b01101000, "sxtab16">;
+def SXTAB16 : AI_exta_rrot_np<0b01101000, "sxtab16">;
// Zero extenders
let AddedComplexity = 16 in {
-defm UXTB : AI_ext_rrot<0b01101110,
+def UXTB : AI_ext_rrot<0b01101110,
"uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>;
-defm UXTH : AI_ext_rrot<0b01101111,
+def UXTH : AI_ext_rrot<0b01101111,
"uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
-defm UXTB16 : AI_ext_rrot<0b01101100,
+def UXTB16 : AI_ext_rrot<0b01101100,
"uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
// FIXME: This pattern incorrectly assumes the shl operator is a rotate.
@@ -2345,19 +2375,18 @@
// instead so we can include a check for masking back in the upper
// eight bits of the source into the lower eight bits of the result.
//def : ARMV6Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF),
-// (UXTB16r_rot GPR:$Src, 24)>;
+// (UXTB16r_rot GPR:$Src, 3)>;
def : ARMV6Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF),
- (UXTB16r_rot GPR:$Src, 8)>;
+ (UXTB16 GPR:$Src, 1)>;
-defm UXTAB : AI_exta_rrot<0b01101110, "uxtab",
+def UXTAB : AI_exta_rrot<0b01101110, "uxtab",
BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
-defm UXTAH : AI_exta_rrot<0b01101111, "uxtah",
+def UXTAH : AI_exta_rrot<0b01101111, "uxtah",
BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>;
}
// This isn't safe in general, the add is two 16-bit units, not a 32-bit add.
-// For disassembly only
-defm UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">;
+def UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">;
def SBFX : I<(outs GPR:$Rd),
@@ -3649,12 +3678,10 @@
let Inst{31-0} = 0b11110101011111111111000000011111;
}
-// SWP/SWPB are deprecated in V6/V7 and for disassembly only.
-let mayLoad = 1 in {
-def SWP : AIswp<0, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swp",
- [/* For disassembly only; pattern left blank */]>;
-def SWPB : AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swpb",
- [/* For disassembly only; pattern left blank */]>;
+// SWP/SWPB are deprecated in V6/V7.
+let mayLoad = 1, mayStore = 1 in {
+def SWP : AIswp<0, (outs GPR:$Rt), (ins GPR:$Rt2, addrmode7:$addr), "swp", []>;
+def SWPB: AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, addrmode7:$addr), "swpb", []>;
}
//===----------------------------------------------------------------------===//
@@ -4210,6 +4237,24 @@
def : ARMPat<(ARMMemBarrierMCR GPR:$zero), (MCR 15, 0, GPR:$zero, 7, 10, 5)>,
Requires<[IsARM, HasV6]>;
+// SXT/UXT with no rotate
+let AddedComplexity = 16 in {
+def : ARMV6Pat<(and GPR:$Src, 0x000000FF), (UXTB GPR:$Src, 0)>;
+def : ARMV6Pat<(and GPR:$Src, 0x0000FFFF), (UXTH GPR:$Src, 0)>;
+def : ARMV6Pat<(and GPR:$Src, 0x00FF00FF), (UXTB16 GPR:$Src, 0)>;
+def : ARMV6Pat<(add GPR:$Rn, (and GPR:$Rm, 0x00FF)),
+ (UXTAB GPR:$Rn, GPR:$Rm, 0)>;
+def : ARMV6Pat<(add GPR:$Rn, (and GPR:$Rm, 0xFFFF)),
+ (UXTAH GPR:$Rn, GPR:$Rm, 0)>;
+}
+
+def : ARMV6Pat<(sext_inreg GPR:$Src, i8), (SXTB GPR:$Src, 0)>;
+def : ARMV6Pat<(sext_inreg GPR:$Src, i16), (SXTH GPR:$Src, 0)>;
+
+def : ARMV6Pat<(add GPR:$Rn, (sext_inreg GPR:$Rm, i8)),
+ (SXTAB GPR:$Rn, GPR:$Rm, 0)>;
+def : ARMV6Pat<(add GPR:$Rn, (sext_inreg GPR:$Rm, i16)),
+ (SXTAH GPR:$Rn, GPR:$Rm, 0)>;
//===----------------------------------------------------------------------===//
// Thumb Support
@@ -4297,3 +4342,25 @@
// SSAT optional shift operand.
def : InstAlias<"ssat${p} $Rd, $sat_imm, $Rn",
(SSAT GPR:$Rd, imm1_32:$sat_imm, GPR:$Rn, 0, pred:$p)>;
+
+
+// Extend instruction optional rotate operand.
+def : InstAlias<"sxtab${p} $Rd, $Rn, $Rm",
+ (SXTAB GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
+def : InstAlias<"sxtah${p} $Rd, $Rn, $Rm",
+ (SXTAH GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
+def : InstAlias<"sxtab16${p} $Rd, $Rn, $Rm",
+ (SXTAB16 GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
+def : InstAlias<"sxtb${p} $Rd, $Rm", (SXTB GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
+def : InstAlias<"sxtb16${p} $Rd, $Rm", (SXTB16 GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
+def : InstAlias<"sxth${p} $Rd, $Rm", (SXTH GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
+
+def : InstAlias<"uxtab${p} $Rd, $Rn, $Rm",
+ (UXTAB GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
+def : InstAlias<"uxtah${p} $Rd, $Rn, $Rm",
+ (UXTAH GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
+def : InstAlias<"uxtab16${p} $Rd, $Rn, $Rm",
+ (UXTAB16 GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
+def : InstAlias<"uxtb${p} $Rd, $Rm", (UXTB GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
+def : InstAlias<"uxtb16${p} $Rd, $Rm", (UXTB16 GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
+def : InstAlias<"uxth${p} $Rd, $Rm", (UXTH GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrThumb.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrThumb.td?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrThumb.td (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrThumb.td Wed Jul 27 13:40:48 2011
@@ -547,7 +547,7 @@
// A8.6.16 B: Encoding T1
// If Inst{11-8} == 0b1111 then SEE SVC
let isCall = 1, Uses = [SP] in
-def tSVC : T1pI<(outs), (ins i32imm:$imm), IIC_Br,
+def tSVC : T1pI<(outs), (ins imm0_255:$imm), IIC_Br,
"svc", "\t$imm", []>, Encoding16 {
bits<8> imm;
let Inst{15-12} = 0b1101;
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrThumb2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrThumb2.td?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMInstrThumb2.td Wed Jul 27 13:40:48 2011
@@ -977,146 +977,80 @@
/// T2I_ext_rrot - A unary operation with two forms: one whose operand is a
/// register and one whose operand is a register rotated by 8/16/24.
-multiclass T2I_ext_rrot<bits<3> opcod, string opc, PatFrag opnode> {
- def r : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iEXTr,
- opc, ".w\t$Rd, $Rm",
- [(set rGPR:$Rd, (opnode rGPR:$Rm))]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
- let Inst{5-4} = 0b00; // rotate
- }
- def r_rot : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr,
- opc, ".w\t$Rd, $Rm, ror $rot",
- [(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
-
- bits<2> rot;
- let Inst{5-4} = rot{1-0}; // rotate
- }
+class T2I_ext_rrot<bits<3> opcod, string opc, PatFrag opnode>
+ : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr,
+ opc, ".w\t$Rd, $Rm$rot",
+ [(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]> {
+ let Inst{31-27} = 0b11111;
+ let Inst{26-23} = 0b0100;
+ let Inst{22-20} = opcod;
+ let Inst{19-16} = 0b1111; // Rn
+ let Inst{15-12} = 0b1111;
+ let Inst{7} = 1;
+
+ bits<2> rot;
+ let Inst{5-4} = rot{1-0}; // rotate
}
// UXTB16 - Requres T2ExtractPack, does not need the .w qualifier.
-multiclass T2I_ext_rrot_uxtb16<bits<3> opcod, string opc, PatFrag opnode> {
- def r : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iEXTr,
- opc, "\t$Rd, $Rm",
- [(set rGPR:$Rd, (opnode rGPR:$Rm))]>,
- Requires<[HasT2ExtractPack, IsThumb2]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
- let Inst{5-4} = 0b00; // rotate
- }
- def r_rot : T2TwoReg<(outs rGPR:$dst), (ins rGPR:$Rm, rot_imm:$rot),
- IIC_iEXTr, opc, "\t$dst, $Rm, ror $rot",
- [(set rGPR:$dst, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>,
- Requires<[HasT2ExtractPack, IsThumb2]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
-
- bits<2> rot;
- let Inst{5-4} = rot{1-0}; // rotate
- }
+class T2I_ext_rrot_uxtb16<bits<3> opcod, string opc, PatFrag opnode>
+ : T2TwoReg<(outs rGPR:$dst), (ins rGPR:$Rm, rot_imm:$rot),
+ IIC_iEXTr, opc, "\t$dst, $Rm$rot",
+ [(set rGPR:$dst, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>,
+ Requires<[HasT2ExtractPack, IsThumb2]> {
+ bits<2> rot;
+ let Inst{31-27} = 0b11111;
+ let Inst{26-23} = 0b0100;
+ let Inst{22-20} = opcod;
+ let Inst{19-16} = 0b1111; // Rn
+ let Inst{15-12} = 0b1111;
+ let Inst{7} = 1;
+ let Inst{5-4} = rot;
}
// SXTB16 - Requres T2ExtractPack, does not need the .w qualifier, no pattern
// supported yet.
-multiclass T2I_ext_rrot_sxtb16<bits<3> opcod, string opc> {
- def r : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iEXTr,
- opc, "\t$Rd, $Rm", []>,
- Requires<[IsThumb2, HasT2ExtractPack]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
- let Inst{5-4} = 0b00; // rotate
- }
- def r_rot : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, i32imm:$rot), IIC_iEXTr,
- opc, "\t$Rd, $Rm, ror $rot", []>,
+class T2I_ext_rrot_sxtb16<bits<3> opcod, string opc>
+ : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr,
+ opc, "\t$Rd, $Rm$rot", []>,
Requires<[IsThumb2, HasT2ExtractPack]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
-
- bits<2> rot;
- let Inst{5-4} = rot{1-0}; // rotate
- }
+ bits<2> rot;
+ let Inst{31-27} = 0b11111;
+ let Inst{26-23} = 0b0100;
+ let Inst{22-20} = opcod;
+ let Inst{19-16} = 0b1111; // Rn
+ let Inst{15-12} = 0b1111;
+ let Inst{7} = 1;
+ let Inst{5-4} = rot;
}
/// T2I_exta_rrot - A binary operation with two forms: one whose operand is a
/// register and one whose operand is a register rotated by 8/16/24.
-multiclass T2I_exta_rrot<bits<3> opcod, string opc, PatFrag opnode> {
- def rr : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iEXTAr,
- opc, "\t$Rd, $Rn, $Rm",
- [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>,
- Requires<[HasT2ExtractPack, IsThumb2]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
- let Inst{5-4} = 0b00; // rotate
- }
- def rr_rot : T2ThreeReg<(outs rGPR:$Rd),
- (ins rGPR:$Rn, rGPR:$Rm, rot_imm:$rot),
- IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm, ror $rot",
- [(set rGPR:$Rd, (opnode rGPR:$Rn,
- (rotr rGPR:$Rm, rot_imm:$rot)))]>,
- Requires<[HasT2ExtractPack, IsThumb2]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
-
- bits<2> rot;
- let Inst{5-4} = rot{1-0}; // rotate
- }
-}
-
-// DO variant - disassembly only, no pattern
-
-multiclass T2I_exta_rrot_DO<bits<3> opcod, string opc> {
- def rr : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iEXTAr,
- opc, "\t$Rd, $Rn, $Rm", []> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
- let Inst{5-4} = 0b00; // rotate
- }
- def rr_rot :T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, i32imm:$rot),
- IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm, ror $rot", []> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
-
- bits<2> rot;
- let Inst{5-4} = rot{1-0}; // rotate
- }
+class T2I_exta_rrot<bits<3> opcod, string opc, PatFrag opnode>
+ : T2ThreeReg<(outs rGPR:$Rd),
+ (ins rGPR:$Rn, rGPR:$Rm, rot_imm:$rot),
+ IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm$rot",
+ [(set rGPR:$Rd, (opnode rGPR:$Rn, (rotr rGPR:$Rm,rot_imm:$rot)))]>,
+ Requires<[HasT2ExtractPack, IsThumb2]> {
+ bits<2> rot;
+ let Inst{31-27} = 0b11111;
+ let Inst{26-23} = 0b0100;
+ let Inst{22-20} = opcod;
+ let Inst{15-12} = 0b1111;
+ let Inst{7} = 1;
+ let Inst{5-4} = rot;
+}
+
+class T2I_exta_rrot_np<bits<3> opcod, string opc>
+ : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm,rot_imm:$rot),
+ IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm$rot", []> {
+ bits<2> rot;
+ let Inst{31-27} = 0b11111;
+ let Inst{26-23} = 0b0100;
+ let Inst{22-20} = opcod;
+ let Inst{15-12} = 0b1111;
+ let Inst{7} = 1;
+ let Inst{5-4} = rot;
}
//===----------------------------------------------------------------------===//
@@ -1671,28 +1605,28 @@
// Sign extenders
-defm t2SXTB : T2I_ext_rrot<0b100, "sxtb",
+def t2SXTB : T2I_ext_rrot<0b100, "sxtb",
UnOpFrag<(sext_inreg node:$Src, i8)>>;
-defm t2SXTH : T2I_ext_rrot<0b000, "sxth",
+def t2SXTH : T2I_ext_rrot<0b000, "sxth",
UnOpFrag<(sext_inreg node:$Src, i16)>>;
-defm t2SXTB16 : T2I_ext_rrot_sxtb16<0b010, "sxtb16">;
+def t2SXTB16 : T2I_ext_rrot_sxtb16<0b010, "sxtb16">;
-defm t2SXTAB : T2I_exta_rrot<0b100, "sxtab",
+def t2SXTAB : T2I_exta_rrot<0b100, "sxtab",
BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
-defm t2SXTAH : T2I_exta_rrot<0b000, "sxtah",
+def t2SXTAH : T2I_exta_rrot<0b000, "sxtah",
BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
-defm t2SXTAB16 : T2I_exta_rrot_DO<0b010, "sxtab16">;
+def t2SXTAB16 : T2I_exta_rrot_np<0b010, "sxtab16">;
-// TODO: SXT(A){B|H}16 - done for disassembly only
+// TODO: SXT(A){B|H}16
// Zero extenders
let AddedComplexity = 16 in {
-defm t2UXTB : T2I_ext_rrot<0b101, "uxtb",
+def t2UXTB : T2I_ext_rrot<0b101, "uxtb",
UnOpFrag<(and node:$Src, 0x000000FF)>>;
-defm t2UXTH : T2I_ext_rrot<0b001, "uxth",
+def t2UXTH : T2I_ext_rrot<0b001, "uxth",
UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
-defm t2UXTB16 : T2I_ext_rrot_uxtb16<0b011, "uxtb16",
+def t2UXTB16 : T2I_ext_rrot_uxtb16<0b011, "uxtb16",
UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
// FIXME: This pattern incorrectly assumes the shl operator is a rotate.
@@ -1700,17 +1634,17 @@
// instead so we can include a check for masking back in the upper
// eight bits of the source into the lower eight bits of the result.
//def : T2Pat<(and (shl rGPR:$Src, (i32 8)), 0xFF00FF),
-// (t2UXTB16r_rot rGPR:$Src, 24)>,
+// (t2UXTB16 rGPR:$Src, 3)>,
// Requires<[HasT2ExtractPack, IsThumb2]>;
def : T2Pat<(and (srl rGPR:$Src, (i32 8)), 0xFF00FF),
- (t2UXTB16r_rot rGPR:$Src, 8)>,
+ (t2UXTB16 rGPR:$Src, 1)>,
Requires<[HasT2ExtractPack, IsThumb2]>;
-defm t2UXTAB : T2I_exta_rrot<0b101, "uxtab",
+def t2UXTAB : T2I_exta_rrot<0b101, "uxtab",
BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
-defm t2UXTAH : T2I_exta_rrot<0b001, "uxtah",
+def t2UXTAH : T2I_exta_rrot<0b001, "uxtah",
BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>;
-defm t2UXTAB16 : T2I_exta_rrot_DO<0b011, "uxtab16">;
+def t2UXTAB16 : T2I_exta_rrot_np<0b011, "uxtab16">;
}
//===----------------------------------------------------------------------===//
@@ -3464,3 +3398,36 @@
let Inst{19-16} = CRn;
let Inst{23-20} = opc1;
}
+
+
+
+//===----------------------------------------------------------------------===//
+// Non-Instruction Patterns
+//
+
+// SXT/UXT with no rotate
+let AddedComplexity = 16 in {
+def : T2Pat<(and rGPR:$Rm, 0x000000FF), (t2UXTB rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : T2Pat<(and rGPR:$Rm, 0x0000FFFF), (t2UXTH rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : T2Pat<(and rGPR:$Rm, 0x00FF00FF), (t2UXTB16 rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : T2Pat<(add rGPR:$Rn, (and rGPR:$Rm, 0x00FF)),
+ (t2UXTAB rGPR:$Rn, rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : T2Pat<(add rGPR:$Rn, (and rGPR:$Rm, 0xFFFF)),
+ (t2UXTAH rGPR:$Rn, rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+}
+
+def : T2Pat<(sext_inreg rGPR:$Src, i8), (t2SXTB rGPR:$Src, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : T2Pat<(sext_inreg rGPR:$Src, i16), (t2SXTH rGPR:$Src, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : T2Pat<(add rGPR:$Rn, (sext_inreg rGPR:$Rm, i8)),
+ (t2SXTAB rGPR:$Rn, rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : T2Pat<(add rGPR:$Rn, (sext_inreg rGPR:$Rm, i16)),
+ (t2SXTAH rGPR:$Rn, rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMLoadStoreOptimizer.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMLoadStoreOptimizer.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/ARMLoadStoreOptimizer.cpp Wed Jul 27 13:40:48 2011
@@ -766,7 +766,7 @@
case ARM::LDRi12:
return ARM::LDR_PRE;
case ARM::STRi12:
- return ARM::STR_PRE;
+ return ARM::STR_PRE_IMM;
case ARM::VLDRS:
return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
case ARM::VLDRD:
@@ -790,9 +790,9 @@
ARM_AM::AddrOpc Mode) {
switch (Opc) {
case ARM::LDRi12:
- return ARM::LDR_POST;
+ return ARM::LDR_POST_IMM;
case ARM::STRi12:
- return ARM::STR_POST;
+ return ARM::STR_POST_IMM;
case ARM::VLDRS:
return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
case ARM::VLDRD:
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Wed Jul 27 13:40:48 2011
@@ -47,20 +47,19 @@
void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
- int TryParseRegister();
- virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
- bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
- int TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
- bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
- bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &,
+ int tryParseRegister();
+ bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
+ int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &,
ARMII::AddrMode AddrMode);
- bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
- bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);
- const MCExpr *ApplyPrefixToExpr(const MCExpr *E,
+ bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
+ bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
+ const MCExpr *applyPrefixToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind Variant);
- bool ParseMemoryOffsetReg(bool &Negative,
+ bool parseMemoryOffsetReg(bool &Negative,
bool &OffsetRegShifted,
enum ARM_AM::ShiftOpc &ShiftType,
const MCExpr *&ShiftAmount,
@@ -68,20 +67,17 @@
bool &OffsetIsReg,
int &OffsetRegNum,
SMLoc &E);
- bool ParseShift(enum ARM_AM::ShiftOpc &St,
+ bool parseShift(enum ARM_AM::ShiftOpc &St,
const MCExpr *&ShiftAmount, SMLoc &E);
- bool ParseDirectiveWord(unsigned Size, SMLoc L);
- bool ParseDirectiveThumb(SMLoc L);
- bool ParseDirectiveThumbFunc(SMLoc L);
- bool ParseDirectiveCode(SMLoc L);
- bool ParseDirectiveSyntax(SMLoc L);
+ bool parseDirectiveWord(unsigned Size, SMLoc L);
+ bool parseDirectiveThumb(SMLoc L);
+ bool parseDirectiveThumbFunc(SMLoc L);
+ bool parseDirectiveCode(SMLoc L);
+ bool parseDirectiveSyntax(SMLoc L);
- bool MatchAndEmitInstruction(SMLoc IDLoc,
- SmallVectorImpl<MCParsedAsmOperand*> &Operands,
- MCStreamer &Out);
- StringRef SplitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
+ StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
bool &CarrySetting, unsigned &ProcessorIMod);
- void GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
+ void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
bool &CanAcceptPredicationCode);
bool isThumb() const {
@@ -130,15 +126,19 @@
OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
// Asm Match Converter Methods
- bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
+ bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
- bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
+ bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
- bool CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
- bool CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
+
+ bool validateInstruction(MCInst &Inst,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
+
public:
ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
: MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
@@ -148,9 +148,15 @@
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
}
- virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
- SmallVectorImpl<MCParsedAsmOperand*> &Operands);
- virtual bool ParseDirective(AsmToken DirectiveID);
+ // Implementation of the MCTargetAsmParser interface:
+ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
+ bool ParseInstruction(StringRef Name, SMLoc NameLoc,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands);
+ bool ParseDirective(AsmToken DirectiveID);
+
+ bool MatchAndEmitInstruction(SMLoc IDLoc,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+ MCStreamer &Out);
};
} // end anonymous namespace
@@ -467,6 +473,14 @@
int64_t Value = CE->getValue();
return Value >= 0 && Value < 65536;
}
+ bool isImm24bit() const {
+ if (Kind != Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value >= 0 && Value <= 0xffffff;
+ }
bool isPKHLSLImm() const {
if (Kind != Immediate)
return false;
@@ -738,6 +752,11 @@
addExpr(Inst, getImm());
}
+ void addImm24bitOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
@@ -1194,7 +1213,7 @@
bool ARMAsmParser::ParseRegister(unsigned &RegNo,
SMLoc &StartLoc, SMLoc &EndLoc) {
- RegNo = TryParseRegister();
+ RegNo = tryParseRegister();
return (RegNo == (unsigned)-1);
}
@@ -1203,7 +1222,7 @@
/// and if it is a register name the token is eaten and the register number is
/// returned. Otherwise return -1.
///
-int ARMAsmParser::TryParseRegister() {
+int ARMAsmParser::tryParseRegister() {
const AsmToken &Tok = Parser.getTok();
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
@@ -1231,7 +1250,7 @@
// occurs, return -1. An irrecoverable error is one where tokens have been
// consumed in the process of trying to parse the shifter (i.e., when it is
// indeed a shifter operand, but malformed).
-int ARMAsmParser::TryParseShiftRegister(
+int ARMAsmParser::tryParseShiftRegister(
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
@@ -1293,7 +1312,7 @@
return -1;
}
} else if (Parser.getTok().is(AsmToken::Identifier)) {
- ShiftReg = TryParseRegister();
+ ShiftReg = tryParseRegister();
SMLoc L = Parser.getTok().getLoc();
if (ShiftReg == -1) {
Error (L, "expected immediate or register in shift operand");
@@ -1325,9 +1344,9 @@
/// TODO this is likely to change to allow different register types and or to
/// parse for a specific register type.
bool ARMAsmParser::
-TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
- int RegNo = TryParseRegister();
+ int RegNo = tryParseRegister();
if (RegNo == -1)
return true;
@@ -1425,7 +1444,7 @@
/// Parse a register list, return it if successful else return null. The first
/// token must be a '{' when called.
bool ARMAsmParser::
-ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
assert(Parser.getTok().is(AsmToken::LCurly) &&
"Token is not a Left Curly Brace");
SMLoc S = Parser.getTok().getLoc();
@@ -1445,7 +1464,7 @@
return true;
}
- int RegNum = TryParseRegister();
+ int RegNum = tryParseRegister();
if (RegNum == -1) {
Error(RegLoc, "register expected");
return true;
@@ -1637,7 +1656,7 @@
parseMemMode2Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\"");
- if (ParseMemory(Operands, ARMII::AddrMode2))
+ if (parseMemory(Operands, ARMII::AddrMode2))
return MatchOperand_NoMatch;
return MatchOperand_Success;
@@ -1648,7 +1667,7 @@
parseMemMode3Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\"");
- if (ParseMemory(Operands, ARMII::AddrMode3))
+ if (parseMemory(Operands, ARMII::AddrMode3))
return MatchOperand_NoMatch;
return MatchOperand_Success;
@@ -1791,11 +1810,11 @@
return MatchOperand_Success;
}
-/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
+/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.
bool ARMAsmParser::
-CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
+cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
@@ -1807,11 +1826,11 @@
return true;
}
-/// CvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
+/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.
bool ARMAsmParser::
-CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
+cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// Create a writeback register dummy placeholder.
Inst.addOperand(MCOperand::CreateImm(0));
@@ -1821,11 +1840,11 @@
return true;
}
-/// CvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
+/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.
bool ARMAsmParser::
-CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
@@ -1837,11 +1856,11 @@
return true;
}
-/// CvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
+/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.
bool ARMAsmParser::
-CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// Create a writeback register dummy placeholder.
Inst.addOperand(MCOperand::CreateImm(0));
@@ -1857,7 +1876,7 @@
/// TODO Only preindexing and postindexing addressing are started, unindexed
/// with option, etc are still to do.
bool ARMAsmParser::
-ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
ARMII::AddrMode AddrMode = ARMII::AddrModeNone) {
SMLoc S, E;
assert(Parser.getTok().is(AsmToken::LBrac) &&
@@ -1870,7 +1889,7 @@
Error(BaseRegTok.getLoc(), "register expected");
return true;
}
- int BaseRegNum = TryParseRegister();
+ int BaseRegNum = tryParseRegister();
if (BaseRegNum == -1) {
Error(BaseRegTok.getLoc(), "register expected");
return true;
@@ -1899,7 +1918,7 @@
Preindexed = true;
Parser.Lex(); // Eat comma token.
- if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
+ if (parseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
Offset, OffsetIsReg, OffsetRegNum, E))
return true;
const AsmToken &RBracTok = Parser.getTok();
@@ -1945,7 +1964,7 @@
Parser.Lex(); // Eat comma token.
- if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
+ if (parseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
E))
return true;
@@ -1980,7 +1999,7 @@
/// +/-Rm, shift
/// #offset
/// we return false on success or an error otherwise.
-bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
+bool ARMAsmParser::parseMemoryOffsetReg(bool &Negative,
bool &OffsetRegShifted,
enum ARM_AM::ShiftOpc &ShiftType,
const MCExpr *&ShiftAmount,
@@ -2004,7 +2023,7 @@
const AsmToken &OffsetRegTok = Parser.getTok();
if (OffsetRegTok.is(AsmToken::Identifier)) {
SMLoc CurLoc = OffsetRegTok.getLoc();
- OffsetRegNum = TryParseRegister();
+ OffsetRegNum = tryParseRegister();
if (OffsetRegNum != -1) {
OffsetIsReg = true;
E = CurLoc;
@@ -2019,7 +2038,7 @@
Parser.Lex(); // Eat comma token.
const AsmToken &Tok = Parser.getTok();
- if (ParseShift(ShiftType, ShiftAmount, E))
+ if (parseShift(ShiftType, ShiftAmount, E))
return Error(Tok.getLoc(), "shift expected");
OffsetRegShifted = true;
}
@@ -2039,11 +2058,11 @@
return false;
}
-/// ParseShift as one of these two:
+/// parseShift as one of these two:
/// ( lsl | lsr | asr | ror ) , # shift_amount
/// rrx
/// and returns true if it parses a shift otherwise it returns false.
-bool ARMAsmParser::ParseShift(ARM_AM::ShiftOpc &St,
+bool ARMAsmParser::parseShift(ARM_AM::ShiftOpc &St,
const MCExpr *&ShiftAmount, SMLoc &E) {
const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier))
@@ -2081,7 +2100,7 @@
/// Parse a arm instruction operand. For now this parses the operand regardless
/// of the mnemonic.
-bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
StringRef Mnemonic) {
SMLoc S, E;
@@ -2101,9 +2120,9 @@
Error(Parser.getTok().getLoc(), "unexpected token in operand");
return true;
case AsmToken::Identifier: {
- if (!TryParseRegisterWithWriteBack(Operands))
+ if (!tryParseRegisterWithWriteBack(Operands))
return false;
- int Res = TryParseShiftRegister(Operands);
+ int Res = tryParseShiftRegister(Operands);
if (Res == 0) // success
return false;
else if (Res == -1) // irrecoverable error
@@ -2125,9 +2144,9 @@
return false;
}
case AsmToken::LBrac:
- return ParseMemory(Operands);
+ return parseMemory(Operands);
case AsmToken::LCurly:
- return ParseRegisterList(Operands);
+ return parseRegisterList(Operands);
case AsmToken::Hash:
// #42 -> immediate.
// TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
@@ -2144,7 +2163,7 @@
// FIXME: Check it's an expression prefix,
// e.g. (FOO - :lower16:BAR) isn't legal.
ARMMCExpr::VariantKind RefKind;
- if (ParsePrefix(RefKind))
+ if (parsePrefix(RefKind))
return true;
const MCExpr *SubExprVal;
@@ -2160,9 +2179,9 @@
}
}
-// ParsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
+// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
// :lower16: and :upper16:.
-bool ARMAsmParser::ParsePrefix(ARMMCExpr::VariantKind &RefKind) {
+bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
RefKind = ARMMCExpr::VK_ARM_None;
// :lower16: and :upper16: modifiers
@@ -2194,7 +2213,7 @@
}
const MCExpr *
-ARMAsmParser::ApplyPrefixToExpr(const MCExpr *E,
+ARMAsmParser::applyPrefixToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind Variant) {
// Recurse over the given expression, rebuilding it to apply the given variant
// to the leftmost symbol.
@@ -2221,7 +2240,7 @@
case MCExpr::Binary: {
const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
- const MCExpr *LHS = ApplyPrefixToExpr(BE->getLHS(), Variant);
+ const MCExpr *LHS = applyPrefixToExpr(BE->getLHS(), Variant);
const MCExpr *RHS = BE->getRHS();
if (!LHS)
return 0;
@@ -2238,7 +2257,7 @@
/// setting letters to form a canonical mnemonic and flags.
//
// FIXME: Would be nice to autogen this.
-StringRef ARMAsmParser::SplitMnemonic(StringRef Mnemonic,
+StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
unsigned &PredicationCode,
bool &CarrySetting,
unsigned &ProcessorIMod) {
@@ -2323,7 +2342,7 @@
//
// FIXME: It would be nice to autogen this.
void ARMAsmParser::
-GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
+getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
bool &CanAcceptPredicationCode) {
if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
@@ -2368,7 +2387,7 @@
unsigned PredicationCode;
unsigned ProcessorIMod;
bool CarrySetting;
- Mnemonic = SplitMnemonic(Mnemonic, PredicationCode, CarrySetting,
+ Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
ProcessorIMod);
Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
@@ -2384,7 +2403,7 @@
// the matcher deal with finding the right instruction or generating an
// appropriate error.
bool CanAcceptCarrySet, CanAcceptPredicationCode;
- GetMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
+ getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
// If we had a carry-set on an instruction that can't do that, issue an
// error.
@@ -2440,7 +2459,7 @@
// Read the remaining operands.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
// Read the first operand.
- if (ParseOperand(Operands, Mnemonic)) {
+ if (parseOperand(Operands, Mnemonic)) {
Parser.EatToEndOfStatement();
return true;
}
@@ -2449,7 +2468,7 @@
Parser.Lex(); // Eat the comma.
// Parse and remember the operand.
- if (ParseOperand(Operands, Mnemonic)) {
+ if (parseOperand(Operands, Mnemonic)) {
Parser.EatToEndOfStatement();
return true;
}
@@ -2484,6 +2503,35 @@
return false;
}
+// Validate context-sensitive operand constraints.
+// FIXME: We would really like to be able to tablegen'erate this.
+bool ARMAsmParser::
+validateInstruction(MCInst &Inst,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ switch (Inst.getOpcode()) {
+ case ARM::LDREXD: {
+ // Rt2 must be Rt + 1.
+ unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
+ unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
+ if (Rt2 != Rt + 1)
+ return Error(Operands[3]->getStartLoc(),
+ "destination operands must be sequential");
+ return false;
+ }
+ case ARM::STREXD: {
+ // Rt2 must be Rt + 1.
+ unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
+ unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
+ if (Rt2 != Rt + 1)
+ return Error(Operands[4]->getStartLoc(),
+ "source operands must be sequential");
+ return false;
+ }
+ }
+
+ return false;
+}
+
bool ARMAsmParser::
MatchAndEmitInstruction(SMLoc IDLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
@@ -2494,6 +2542,11 @@
MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
switch (MatchResult) {
case Match_Success:
+ // Context sensitive operand constraints aren't handled by the matcher,
+ // so check them here.
+ if (validateInstruction(Inst, Operands))
+ return true;
+
Out.EmitInstruction(Inst);
return false;
case Match_MissingFeature:
@@ -2521,25 +2574,25 @@
return true;
}
-/// ParseDirective parses the arm specific directives
+/// parseDirective parses the arm specific directives
bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getIdentifier();
if (IDVal == ".word")
- return ParseDirectiveWord(4, DirectiveID.getLoc());
+ return parseDirectiveWord(4, DirectiveID.getLoc());
else if (IDVal == ".thumb")
- return ParseDirectiveThumb(DirectiveID.getLoc());
+ return parseDirectiveThumb(DirectiveID.getLoc());
else if (IDVal == ".thumb_func")
- return ParseDirectiveThumbFunc(DirectiveID.getLoc());
+ return parseDirectiveThumbFunc(DirectiveID.getLoc());
else if (IDVal == ".code")
- return ParseDirectiveCode(DirectiveID.getLoc());
+ return parseDirectiveCode(DirectiveID.getLoc());
else if (IDVal == ".syntax")
- return ParseDirectiveSyntax(DirectiveID.getLoc());
+ return parseDirectiveSyntax(DirectiveID.getLoc());
return true;
}
-/// ParseDirectiveWord
+/// parseDirectiveWord
/// ::= .word [ expression (, expression)* ]
-bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
+bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
if (getLexer().isNot(AsmToken::EndOfStatement)) {
for (;;) {
const MCExpr *Value;
@@ -2562,9 +2615,9 @@
return false;
}
-/// ParseDirectiveThumb
+/// parseDirectiveThumb
/// ::= .thumb
-bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
+bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(L, "unexpected token in directive");
Parser.Lex();
@@ -2575,9 +2628,9 @@
return false;
}
-/// ParseDirectiveThumbFunc
+/// parseDirectiveThumbFunc
/// ::= .thumbfunc symbol_name
-bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
+bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
bool isMachO = MAI.hasSubsectionsViaSymbols();
StringRef Name;
@@ -2607,9 +2660,9 @@
return false;
}
-/// ParseDirectiveSyntax
+/// parseDirectiveSyntax
/// ::= .syntax unified | divided
-bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
+bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier))
return Error(L, "unexpected token in .syntax directive");
@@ -2630,9 +2683,9 @@
return false;
}
-/// ParseDirectiveCode
+/// parseDirectiveCode
/// ::= .code 16 | 32
-bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
+bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Integer))
return Error(L, "unexpected token in .code directive");
@@ -2649,13 +2702,15 @@
Parser.Lex();
if (Val == 16) {
- if (!isThumb())
+ if (!isThumb()) {
SwitchMode();
- getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
+ getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
+ }
} else {
- if (isThumb())
+ if (isThumb()) {
SwitchMode();
- getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
+ getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
+ }
}
return false;
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp Wed Jul 27 13:40:48 2011
@@ -1785,8 +1785,7 @@
&& !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
// Extract the 2-bit rotate field Inst{11-10}.
unsigned rot = (insn >> ARMII::ExtRotImmShift) & 3;
- // Rotation by 8, 16, or 24 bits.
- MI.addOperand(MCOperand::CreateImm(rot << 3));
+ MI.addOperand(MCOperand::CreateImm(rot));
++OpIdx;
}
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Wed Jul 27 13:40:48 2011
@@ -323,12 +323,6 @@
return SignExtend32<25>(Imm25);
}
-// See, for example, A8.6.221 SXTAB16.
-static inline unsigned decodeRotate(uint32_t insn) {
- unsigned rotate = slice(insn, 5, 4);
- return rotate << 3;
-}
-
///////////////////////////////////////////////
// //
// Thumb1 instruction disassembly functions. //
@@ -2195,7 +2189,7 @@
if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
&& !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
// Add the rotation amount immediate.
- MI.addOperand(MCOperand::CreateImm(decodeRotate(insn)));
+ MI.addOperand(MCOperand::CreateImm(slice(insn, 5, 4)));
++OpIdx;
}
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp Wed Jul 27 13:40:48 2011
@@ -835,3 +835,17 @@
unsigned Imm = MI->getOperand(OpNum).getImm();
O << "#" << Imm + 1;
}
+
+void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ unsigned Imm = MI->getOperand(OpNum).getImm();
+ if (Imm == 0)
+ return;
+ O << ", ror #";
+ switch (Imm) {
+ default: assert (0 && "illegal ror immediate!");
+ case 1: O << "8\n"; break;
+ case 2: O << "16\n"; break;
+ case 3: O << "24\n"; break;
+ }
+}
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/InstPrinter/ARMInstPrinter.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/InstPrinter/ARMInstPrinter.h (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/InstPrinter/ARMInstPrinter.h Wed Jul 27 13:40:48 2011
@@ -115,6 +115,7 @@
void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printRotImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printPCLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O);
};
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp Wed Jul 27 13:40:48 2011
@@ -52,6 +52,9 @@
AsmTransCBE = arm_asm_table;
Data64bitsDirective = 0;
CommentString = "@";
+ Code16Directive = ".code\t16";
+ Code32Directive = ".code\t32";
+
SupportsDebugInformation = true;
// Exceptions handling
@@ -64,12 +67,14 @@
Data64bitsDirective = 0;
CommentString = "@";
-
- HasLEB128 = true;
PrivateGlobalPrefix = ".L";
+ Code16Directive = ".code\t16";
+ Code32Directive = ".code\t32";
+
WeakRefDirective = "\t.weak\t";
HasLCOMMDirective = true;
+ HasLEB128 = true;
SupportsDebugInformation = true;
// Exceptions handling
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp Wed Jul 27 13:40:48 2011
@@ -259,17 +259,6 @@
unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op,
SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getRotImmOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- switch (MI.getOperand(Op).getImm()) {
- default: assert (0 && "Not a valid rot_imm value!");
- case 0: return 0;
- case 8: return 1;
- case 16: return 2;
- case 24: return 3;
- }
- }
-
unsigned getImmMinusOneOpValue(const MCInst &MI, unsigned Op,
SmallVectorImpl<MCFixup> &Fixups) const {
return MI.getOperand(Op).getImm() - 1;
Modified: llvm/branches/exception-handling-rewrite/lib/Target/ARM/Thumb2SizeReduction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/ARM/Thumb2SizeReduction.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/ARM/Thumb2SizeReduction.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/ARM/Thumb2SizeReduction.cpp Wed Jul 27 13:40:48 2011
@@ -97,11 +97,11 @@
{ ARM::t2SUBrr, ARM::tSUBrr, 0, 0, 0, 1, 0, 0,0, 0,0 },
{ ARM::t2SUBSri,ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 2,2, 0,0 },
{ ARM::t2SUBSrr,ARM::tSUBrr, 0, 0, 0, 1, 0, 2,0, 0,0 },
- { ARM::t2SXTBr, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0,0 },
- { ARM::t2SXTHr, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0,0 },
+ { ARM::t2SXTB, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0,1 },
+ { ARM::t2SXTH, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0,1 },
{ ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0,0 },
- { ARM::t2UXTBr, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0,0 },
- { ARM::t2UXTHr, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0,0 },
+ { ARM::t2UXTB, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0,1 },
+ { ARM::t2UXTH, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0,1 },
// FIXME: Clean this up after splitting each Thumb load / store opcode
// into multiple ones.
@@ -546,6 +546,10 @@
}
case ARM::t2RSBri:
case ARM::t2RSBSri:
+ case ARM::t2SXTB:
+ case ARM::t2SXTH:
+ case ARM::t2UXTB:
+ case ARM::t2UXTH:
if (MI->getOperand(2).getImm() == 0)
return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef);
break;
@@ -742,7 +746,11 @@
if (i < NumOps && MCID.OpInfo[i].isOptionalDef())
continue;
if ((MCID.getOpcode() == ARM::t2RSBSri ||
- MCID.getOpcode() == ARM::t2RSBri) && i == 2)
+ MCID.getOpcode() == ARM::t2RSBri ||
+ MCID.getOpcode() == ARM::t2SXTB ||
+ MCID.getOpcode() == ARM::t2SXTH ||
+ MCID.getOpcode() == ARM::t2UXTB ||
+ MCID.getOpcode() == ARM::t2UXTH) && i == 2)
// Skip the zero immediate operand, it's now implicit.
continue;
bool isPred = (i < NumOps && MCID.OpInfo[i].isPredicate());
Modified: llvm/branches/exception-handling-rewrite/lib/Target/CppBackend/CPPBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/CppBackend/CPPBackend.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/CppBackend/CPPBackend.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/CppBackend/CPPBackend.cpp Wed Jul 27 13:40:48 2011
@@ -1245,8 +1245,7 @@
nl(Out);
}
Out << "Instruction* " << iName << " = GetElementPtrInst::Create("
- << opNames[0] << ", " << iName << "_indices.begin(), "
- << iName << "_indices.end()";
+ << opNames[0] << ", " << iName << "_indices";
}
Out << ", \"";
printEscapedString(gep->getName());
Modified: llvm/branches/exception-handling-rewrite/lib/Target/X86/AsmParser/X86AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/X86/AsmParser/X86AsmParser.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/X86/AsmParser/X86AsmParser.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/X86/AsmParser/X86AsmParser.cpp Wed Jul 27 13:40:48 2011
@@ -46,6 +46,7 @@
X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
bool ParseDirectiveWord(unsigned Size, SMLoc L);
+ bool ParseDirectiveCode(StringRef IDVal, SMLoc L);
bool MatchAndEmitInstruction(SMLoc IDLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
@@ -63,6 +64,10 @@
// FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
}
+ void SwitchMode() {
+ unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(X86::Mode64Bit));
+ setAvailableFeatures(FB);
+ }
/// @name Auto-generated Matcher Functions
/// {
@@ -1094,6 +1099,8 @@
StringRef IDVal = DirectiveID.getIdentifier();
if (IDVal == ".word")
return ParseDirectiveWord(2, DirectiveID.getLoc());
+ else if (IDVal.startswith(".code"))
+ return ParseDirectiveCode(IDVal, DirectiveID.getLoc());
return true;
}
@@ -1122,7 +1129,27 @@
return false;
}
+/// ParseDirectiveCode
+/// ::= .code32 | .code64
+bool X86ATTAsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
+ if (IDVal == ".code32") {
+ Parser.Lex();
+ if (is64BitMode()) {
+ SwitchMode();
+ getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
+ }
+ } else if (IDVal == ".code64") {
+ Parser.Lex();
+ if (!is64BitMode()) {
+ SwitchMode();
+ getParser().getStreamer().EmitAssemblerFlag(MCAF_Code64);
+ }
+ } else {
+ return Error(L, "unexpected directive " + IDVal);
+ }
+ return false;
+}
extern "C" void LLVMInitializeX86AsmLexer();
Modified: llvm/branches/exception-handling-rewrite/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp Wed Jul 27 13:40:48 2011
@@ -357,7 +357,7 @@
}
// Calculate what the SS field value should be...
- static const unsigned SSTable[] = { ~0, 0, 1, ~0, 2, ~0, ~0, ~0, 3 };
+ static const unsigned SSTable[] = { ~0U, 0, 1, ~0U, 2, ~0U, ~0U, ~0U, 3 };
unsigned SS = SSTable[Scale.getImm()];
if (BaseReg == 0) {
Modified: llvm/branches/exception-handling-rewrite/lib/Target/X86/README.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/X86/README.txt?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/X86/README.txt (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/X86/README.txt Wed Jul 27 13:40:48 2011
@@ -2076,12 +2076,11 @@
jb LBB0_2
## BB#1:
decl %edi
- movl $63, %eax
- bsrl %edi, %ecx
- cmovel %eax, %ecx
- xorl $31, %ecx
- movl $32, %eax
- subl %ecx, %eax
+ movl $63, %ecx
+ bsrl %edi, %eax
+ cmovel %ecx, %eax
+ xorl $-32, %eax
+ addl $33, %eax
LBB0_2:
ret
@@ -2091,26 +2090,10 @@
jb LBB0_2
## BB#1:
decl %edi
- bsrl %edi, %ecx
- xorl $31, %ecx
- movl $32, %eax
- subl %ecx, %eax
+ bsrl %edi, %eax
+ xorl $-32, %eax
+ addl $33, %eax
LBB0_2:
ret
-If we want to get really fancy we could use some two's complement magic:
- xorl %eax, %eax
- cmpl $2, %edi
- jb LBB0_2
-## BB#1:
- decl %edi
- bsrl %edi, %ecx
- xorl $-32, %ecx
- leal 33(%ecx), %eax
-LBB0_2:
- ret
-
-This is only useful on targets that can't encode the first operand of a sub
-directly. The rule is C1 - (X^C2) -> (C1+1) + (X^~C2).
-
//===---------------------------------------------------------------------===//
Modified: llvm/branches/exception-handling-rewrite/lib/Target/X86/Utils/X86ShuffleDecode.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/X86/Utils/X86ShuffleDecode.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/X86/Utils/X86ShuffleDecode.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/X86/Utils/X86ShuffleDecode.cpp Wed Jul 27 13:40:48 2011
@@ -167,23 +167,22 @@
SmallVectorImpl<unsigned> &ShuffleMask) {
unsigned NumElts = VT.getVectorNumElements();
- // Handle vector lengths > 128 bits. Define a "section" as a set of
- // 128 bits. AVX defines UNPCK* to operate independently on 128-bit
- // sections.
- unsigned NumSections = VT.getSizeInBits() / 128;
- if (NumSections == 0 ) NumSections = 1; // Handle MMX
- unsigned NumSectionElts = NumElts / NumSections;
+ // Handle 128 and 256-bit vector lengths. AVX defines UNPCK* to operate
+ // independently on 128-bit lanes.
+ unsigned NumLanes = VT.getSizeInBits() / 128;
+ if (NumLanes == 0 ) NumLanes = 1; // Handle MMX
+ unsigned NumLaneElts = NumElts / NumLanes;
unsigned Start = 0;
- unsigned End = NumSectionElts / 2;
- for (unsigned s = 0; s < NumSections; ++s) {
+ unsigned End = NumLaneElts / 2;
+ for (unsigned s = 0; s < NumLanes; ++s) {
for (unsigned i = Start; i != End; ++i) {
ShuffleMask.push_back(i); // Reads from dest/src1
- ShuffleMask.push_back(i+NumSectionElts); // Reads from src/src2
+ ShuffleMask.push_back(i+NumLaneElts); // Reads from src/src2
}
// Process the next 128 bits.
- Start += NumSectionElts;
- End += NumSectionElts;
+ Start += NumLaneElts;
+ End += NumLaneElts;
}
}
Modified: llvm/branches/exception-handling-rewrite/lib/Target/X86/X86CodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/X86/X86CodeEmitter.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/X86/X86CodeEmitter.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/X86/X86CodeEmitter.cpp Wed Jul 27 13:40:48 2011
@@ -559,7 +559,7 @@
}
// Calculate what the SS field value should be...
- static const unsigned SSTable[] = { ~0, 0, 1, ~0, 2, ~0, ~0, ~0, 3 };
+ static const unsigned SSTable[] = { ~0U, 0, 1, ~0U, 2, ~0U, ~0U, ~0U, 3 };
unsigned SS = SSTable[Scale.getImm()];
if (BaseReg == 0) {
Modified: llvm/branches/exception-handling-rewrite/lib/Target/X86/X86FrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/X86/X86FrameLowering.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/X86/X86FrameLowering.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/X86/X86FrameLowering.cpp Wed Jul 27 13:40:48 2011
@@ -490,6 +490,8 @@
unsigned SubtractInstr = getSUBriOpcode(Is64Bit, -TailCallReturnAddrDelta);
unsigned SubtractInstrIdx = (Is64Bit ? 3 : 2);
+ unsigned StackDivide = (Is64Bit ? 8 : 4);
+
unsigned InstrOffset = 0;
unsigned CFAOffset = 0;
unsigned StackAdjust = 0;
@@ -536,7 +538,7 @@
// %RSP<def> = SUB64ri8 %RSP, 48
return 0;
- StackAdjust = MI.getOperand(2).getImm() / 4;
+ StackAdjust = MI.getOperand(2).getImm() / StackDivide;
SubtractInstrIdx += InstrOffset;
ExpectEnd = true;
}
@@ -544,7 +546,7 @@
// Encode that we are using EBP/RBP as the frame pointer.
uint32_t CompactUnwindEncoding = 0;
- CFAOffset /= 4;
+ CFAOffset /= StackDivide;
if (HasFP) {
if ((CFAOffset & 0xFF) != CFAOffset)
// Offset was too big for compact encoding.
Modified: llvm/branches/exception-handling-rewrite/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/X86/X86ISelLowering.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/X86/X86ISelLowering.cpp Wed Jul 27 13:40:48 2011
@@ -2711,11 +2711,16 @@
case X86ISD::PUNPCKLQDQ:
case X86ISD::UNPCKHPS:
case X86ISD::UNPCKHPD:
+ case X86ISD::VUNPCKHPSY:
+ case X86ISD::VUNPCKHPDY:
case X86ISD::PUNPCKHWD:
case X86ISD::PUNPCKHBW:
case X86ISD::PUNPCKHDQ:
case X86ISD::PUNPCKHQDQ:
- case X86ISD::VPERMIL:
+ case X86ISD::VPERMILPS:
+ case X86ISD::VPERMILPSY:
+ case X86ISD::VPERMILPD:
+ case X86ISD::VPERMILPDY:
return true;
}
return false;
@@ -2741,7 +2746,10 @@
case X86ISD::PSHUFD:
case X86ISD::PSHUFHW:
case X86ISD::PSHUFLW:
- case X86ISD::VPERMIL:
+ case X86ISD::VPERMILPS:
+ case X86ISD::VPERMILPSY:
+ case X86ISD::VPERMILPD:
+ case X86ISD::VPERMILPDY:
return DAG.getNode(Opc, dl, VT, V1, DAG.getConstant(TargetMask, MVT::i8));
}
@@ -2782,6 +2790,8 @@
case X86ISD::PUNPCKLQDQ:
case X86ISD::UNPCKHPS:
case X86ISD::UNPCKHPD:
+ case X86ISD::VUNPCKHPSY:
+ case X86ISD::VUNPCKHPDY:
case X86ISD::PUNPCKHWD:
case X86ISD::PUNPCKHBW:
case X86ISD::PUNPCKHDQ:
@@ -3219,20 +3229,22 @@
static bool isUNPCKLMask(const SmallVectorImpl<int> &Mask, EVT VT,
bool V2IsSplat = false) {
int NumElts = VT.getVectorNumElements();
- if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
+
+ assert((VT.is128BitVector() || VT.is256BitVector()) &&
+ "Unsupported vector type for unpckh");
+
+ if (VT.getSizeInBits() == 256 && NumElts != 4 && NumElts != 8)
return false;
- // Handle vector lengths > 128 bits. Define a "section" as a set of
- // 128 bits. AVX defines UNPCK* to operate independently on 128-bit
- // sections.
- unsigned NumSections = VT.getSizeInBits() / 128;
- if (NumSections == 0 ) NumSections = 1; // Handle MMX
- unsigned NumSectionElts = NumElts / NumSections;
+ // Handle 128 and 256-bit vector lengths. AVX defines UNPCK* to operate
+ // independently on 128-bit lanes.
+ unsigned NumLanes = VT.getSizeInBits()/128;
+ unsigned NumLaneElts = NumElts/NumLanes;
unsigned Start = 0;
- unsigned End = NumSectionElts;
- for (unsigned s = 0; s < NumSections; ++s) {
- for (unsigned i = Start, j = s * NumSectionElts;
+ unsigned End = NumLaneElts;
+ for (unsigned s = 0; s < NumLanes; ++s) {
+ for (unsigned i = Start, j = s * NumLaneElts;
i != End;
i += 2, ++j) {
int BitI = Mask[i];
@@ -3248,8 +3260,8 @@
}
}
// Process the next 128 bits.
- Start += NumSectionElts;
- End += NumSectionElts;
+ Start += NumLaneElts;
+ End += NumLaneElts;
}
return true;
@@ -3266,21 +3278,38 @@
static bool isUNPCKHMask(const SmallVectorImpl<int> &Mask, EVT VT,
bool V2IsSplat = false) {
int NumElts = VT.getVectorNumElements();
- if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
+
+ assert((VT.is128BitVector() || VT.is256BitVector()) &&
+ "Unsupported vector type for unpckh");
+
+ if (VT.getSizeInBits() == 256 && NumElts != 4 && NumElts != 8)
return false;
- for (int i = 0, j = 0; i != NumElts; i += 2, ++j) {
- int BitI = Mask[i];
- int BitI1 = Mask[i+1];
- if (!isUndefOrEqual(BitI, j + NumElts/2))
- return false;
- if (V2IsSplat) {
- if (isUndefOrEqual(BitI1, NumElts))
- return false;
- } else {
- if (!isUndefOrEqual(BitI1, j + NumElts/2 + NumElts))
+ // Handle 128 and 256-bit vector lengths. AVX defines UNPCK* to operate
+ // independently on 128-bit lanes.
+ unsigned NumLanes = VT.getSizeInBits()/128;
+ unsigned NumLaneElts = NumElts/NumLanes;
+
+ unsigned Start = 0;
+ unsigned End = NumLaneElts;
+ for (unsigned l = 0; l != NumLanes; ++l) {
+ for (unsigned i = Start, j = (l*NumLaneElts)+NumLaneElts/2;
+ i != End; i += 2, ++j) {
+ int BitI = Mask[i];
+ int BitI1 = Mask[i+1];
+ if (!isUndefOrEqual(BitI, j))
return false;
+ if (V2IsSplat) {
+ if (isUndefOrEqual(BitI1, NumElts))
+ return false;
+ } else {
+ if (!isUndefOrEqual(BitI1, j+NumElts))
+ return false;
+ }
}
+ // Process the next 128 bits.
+ Start += NumLaneElts;
+ End += NumLaneElts;
}
return true;
}
@@ -3299,16 +3328,14 @@
if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16)
return false;
- // Handle vector lengths > 128 bits. Define a "section" as a set of
- // 128 bits. AVX defines UNPCK* to operate independently on 128-bit
- // sections.
- unsigned NumSections = VT.getSizeInBits() / 128;
- if (NumSections == 0 ) NumSections = 1; // Handle MMX
- unsigned NumSectionElts = NumElems / NumSections;
-
- for (unsigned s = 0; s < NumSections; ++s) {
- for (unsigned i = s * NumSectionElts, j = s * NumSectionElts;
- i != NumSectionElts * (s + 1);
+ // Handle 128 and 256-bit vector lengths. AVX defines UNPCK* to operate
+ // independently on 128-bit lanes.
+ unsigned NumLanes = VT.getSizeInBits() / 128;
+ unsigned NumLaneElts = NumElems / NumLanes;
+
+ for (unsigned s = 0; s < NumLanes; ++s) {
+ for (unsigned i = s * NumLaneElts, j = s * NumLaneElts;
+ i != NumLaneElts * (s + 1);
i += 2, ++j) {
int BitI = Mask[i];
int BitI1 = Mask[i+1];
@@ -3379,21 +3406,63 @@
return ::isMOVLMask(M, N->getValueType(0));
}
-/// isVPERMILMask - Return true if the specified VECTOR_SHUFFLE operand
-/// specifies a shuffle of elements that is suitable for input to VPERMIL*.
-static bool isVPERMILMask(const SmallVectorImpl<int> &Mask, EVT VT) {
+/// isVPERMILPDMask - Return true if the specified VECTOR_SHUFFLE operand
+/// specifies a shuffle of elements that is suitable for input to VPERMILPD*.
+/// Note that VPERMIL mask matching is different depending whether theunderlying
+/// type is 32 or 64. In the VPERMILPS the high half of the mask should point
+/// to the same elements of the low, but to the higher half of the source.
+/// In VPERMILPD the two lanes could be shuffled independently of each other
+/// with the same restriction that lanes can't be crossed.
+static bool isVPERMILPDMask(const SmallVectorImpl<int> &Mask, EVT VT,
+ const X86Subtarget *Subtarget) {
+ int NumElts = VT.getVectorNumElements();
+ int NumLanes = VT.getSizeInBits()/128;
+
+ if (!Subtarget->hasAVX())
+ return false;
+
+ // Match any permutation of 128-bit vector with 64-bit types
+ if (NumLanes == 1 && NumElts != 2)
+ return false;
+
+ // Only match 256-bit with 32 types
+ if (VT.getSizeInBits() == 256 && NumElts != 4)
+ return false;
+
+ // The mask on the high lane is independent of the low. Both can match
+ // any element in inside its own lane, but can't cross.
+ int LaneSize = NumElts/NumLanes;
+ for (int l = 0; l < NumLanes; ++l)
+ for (int i = l*LaneSize; i < LaneSize*(l+1); ++i) {
+ int LaneStart = l*LaneSize;
+ if (!isUndefOrInRange(Mask[i], LaneStart, LaneStart+LaneSize))
+ return false;
+ }
+
+ return true;
+}
+
+/// isVPERMILPSMask - Return true if the specified VECTOR_SHUFFLE operand
+/// specifies a shuffle of elements that is suitable for input to VPERMILPS*.
+/// Note that VPERMIL mask matching is different depending whether theunderlying
+/// type is 32 or 64. In the VPERMILPS the high half of the mask should point
+/// to the same elements of the low, but to the higher half of the source.
+/// In VPERMILPD the two lanes could be shuffled independently of each other
+/// with the same restriction that lanes can't be crossed.
+static bool isVPERMILPSMask(const SmallVectorImpl<int> &Mask, EVT VT,
+ const X86Subtarget *Subtarget) {
unsigned NumElts = VT.getVectorNumElements();
unsigned NumLanes = VT.getSizeInBits()/128;
- // Match any permutation of 128-bit vector with 32/64-bit types
- if (NumLanes == 1) {
- if (NumElts == 4 || NumElts == 2)
- return true;
+ if (!Subtarget->hasAVX())
+ return false;
+
+ // Match any permutation of 128-bit vector with 32-bit types
+ if (NumLanes == 1 && NumElts != 4)
return false;
- }
- // Only match 256-bit with 32/64-bit types
- if (NumElts != 8 && NumElts != 4)
+ // Only match 256-bit with 32 types
+ if (VT.getSizeInBits() == 256 && NumElts != 8)
return false;
// The mask on the high lane should be the same as the low. Actually,
@@ -3403,7 +3472,6 @@
int HighElt = i+LaneSize;
if (Mask[i] < 0 || Mask[HighElt] < 0)
continue;
-
if (Mask[HighElt]-Mask[i] != LaneSize)
return false;
}
@@ -3411,9 +3479,9 @@
return true;
}
-/// getShuffleVPERMILImmediateediate - Return the appropriate immediate to shuffle
-/// the specified VECTOR_MASK mask with VPERMIL* instructions.
-static unsigned getShuffleVPERMILImmediate(SDNode *N) {
+/// getShuffleVPERMILPSImmediate - Return the appropriate immediate to shuffle
+/// the specified VECTOR_MASK mask with VPERMILPS* instructions.
+static unsigned getShuffleVPERMILPSImmediate(SDNode *N) {
ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
EVT VT = SVOp->getValueType(0);
@@ -3427,6 +3495,24 @@
return Mask;
}
+/// getShuffleVPERMILPDImmediate - Return the appropriate immediate to shuffle
+/// the specified VECTOR_MASK mask with VPERMILPD* instructions.
+static unsigned getShuffleVPERMILPDImmediate(SDNode *N) {
+ ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
+ EVT VT = SVOp->getValueType(0);
+
+ int NumElts = VT.getVectorNumElements();
+ int NumLanes = VT.getSizeInBits()/128;
+
+ unsigned Mask = 0;
+ int LaneSize = NumElts/NumLanes;
+ for (int l = 0; l < NumLanes; ++l)
+ for (int i = l*LaneSize; i < LaneSize*(l+1); ++i)
+ Mask |= (SVOp->getMaskElt(i)-l*LaneSize) << i;
+
+ return Mask;
+}
+
/// isCommutedMOVL - Returns true if the shuffle mask is except the reverse
/// of what x86 movss want. X86 movs requires the lowest element to be lowest
/// element of vector 2 and the other elements to come from vector 1 in order.
@@ -3457,51 +3543,58 @@
/// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSHDUP.
-bool X86::isMOVSHDUPMask(ShuffleVectorSDNode *N) {
- if (N->getValueType(0).getVectorNumElements() != 4)
+/// Masks to match: <1, 1, 3, 3> or <1, 1, 3, 3, 5, 5, 7, 7>
+bool X86::isMOVSHDUPMask(ShuffleVectorSDNode *N,
+ const X86Subtarget *Subtarget) {
+ if (!Subtarget->hasSSE3() && !Subtarget->hasAVX())
return false;
- // Expect 1, 1, 3, 3
- for (unsigned i = 0; i < 2; ++i) {
- int Elt = N->getMaskElt(i);
- if (Elt >= 0 && Elt != 1)
- return false;
- }
+ // The second vector must be undef
+ if (N->getOperand(1).getOpcode() != ISD::UNDEF)
+ return false;
+
+ EVT VT = N->getValueType(0);
+ unsigned NumElems = VT.getVectorNumElements();
- bool HasHi = false;
- for (unsigned i = 2; i < 4; ++i) {
- int Elt = N->getMaskElt(i);
- if (Elt >= 0 && Elt != 3)
+ if ((VT.getSizeInBits() == 128 && NumElems != 4) ||
+ (VT.getSizeInBits() == 256 && NumElems != 8))
+ return false;
+
+ // "i+1" is the value the indexed mask element must have
+ for (unsigned i = 0; i < NumElems; i += 2)
+ if (!isUndefOrEqual(N->getMaskElt(i), i+1) ||
+ !isUndefOrEqual(N->getMaskElt(i+1), i+1))
return false;
- if (Elt == 3)
- HasHi = true;
- }
- // Don't use movshdup if it can be done with a shufps.
- // FIXME: verify that matching u, u, 3, 3 is what we want.
- return HasHi;
+
+ return true;
}
/// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSLDUP.
-bool X86::isMOVSLDUPMask(ShuffleVectorSDNode *N) {
- if (N->getValueType(0).getVectorNumElements() != 4)
+/// Masks to match: <0, 0, 2, 2> or <0, 0, 2, 2, 4, 4, 6, 6>
+bool X86::isMOVSLDUPMask(ShuffleVectorSDNode *N,
+ const X86Subtarget *Subtarget) {
+ if (!Subtarget->hasSSE3() && !Subtarget->hasAVX())
return false;
- // Expect 0, 0, 2, 2
- for (unsigned i = 0; i < 2; ++i)
- if (N->getMaskElt(i) > 0)
- return false;
+ // The second vector must be undef
+ if (N->getOperand(1).getOpcode() != ISD::UNDEF)
+ return false;
- bool HasHi = false;
- for (unsigned i = 2; i < 4; ++i) {
- int Elt = N->getMaskElt(i);
- if (Elt >= 0 && Elt != 2)
+ EVT VT = N->getValueType(0);
+ unsigned NumElems = VT.getVectorNumElements();
+
+ if ((VT.getSizeInBits() == 128 && NumElems != 4) ||
+ (VT.getSizeInBits() == 256 && NumElems != 8))
+ return false;
+
+ // "i" is the value the indexed mask element must have
+ for (unsigned i = 0; i < NumElems; i += 2)
+ if (!isUndefOrEqual(N->getMaskElt(i), i) ||
+ !isUndefOrEqual(N->getMaskElt(i+1), i))
return false;
- if (Elt == 2)
- HasHi = true;
- }
- // Don't use movsldup if it can be done with a shufps.
- return HasHi;
+
+ return true;
}
/// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand
@@ -4088,6 +4181,8 @@
break;
case X86ISD::UNPCKHPS:
case X86ISD::UNPCKHPD:
+ case X86ISD::VUNPCKHPSY:
+ case X86ISD::VUNPCKHPDY:
DecodeUNPCKHPMask(NumElems, ShuffleMask);
break;
case X86ISD::PUNPCKLBW:
@@ -4133,7 +4228,9 @@
return getShuffleScalarElt(V.getOperand(OpNum).getNode(), Index, DAG,
Depth+1);
}
- case X86ISD::VPERMIL:
+ case X86ISD::VPERMILPS:
+ case X86ISD::VPERMILPSY:
+ // FIXME: Implement the other types
ImmN = N->getOperand(N->getNumOperands()-1);
DecodeVPERMILMask(VT, cast<ConstantSDNode>(ImmN)->getZExtValue(),
ShuffleMask);
@@ -4513,7 +4610,8 @@
LDBase->getPointerInfo(),
LDBase->isVolatile(), LDBase->isNonTemporal(),
LDBase->getAlignment());
- } else if (NumElems == 4 && LastLoadedElt == 1) {
+ } else if (NumElems == 4 && LastLoadedElt == 1 &&
+ DAG.getTargetLoweringInfo().isTypeLegal(MVT::v2i64)) {
SDVTList Tys = DAG.getVTList(MVT::v2i64, MVT::Other);
SDValue Ops[] = { LDBase->getChain(), LDBase->getBasePtr() };
SDValue ResNode = DAG.getMemIntrinsicNode(X86ISD::VZEXT_LOAD, DL, Tys,
@@ -5721,7 +5819,7 @@
X86::getShuffleSHUFImmediate(SVOp), DAG);
}
-static inline unsigned getUNPCKLOpcode(EVT VT, const X86Subtarget *Subtarget) {
+static inline unsigned getUNPCKLOpcode(EVT VT) {
switch(VT.getSimpleVT().SimpleTy) {
case MVT::v4i32: return X86ISD::PUNPCKLDQ;
case MVT::v2i64: return X86ISD::PUNPCKLQDQ;
@@ -5743,6 +5841,8 @@
case MVT::v2i64: return X86ISD::PUNPCKHQDQ;
case MVT::v4f32: return X86ISD::UNPCKHPS;
case MVT::v2f64: return X86ISD::UNPCKHPD;
+ case MVT::v8f32: return X86ISD::VUNPCKHPSY;
+ case MVT::v4f64: return X86ISD::VUNPCKHPDY;
case MVT::v16i8: return X86ISD::PUNPCKHBW;
case MVT::v8i16: return X86ISD::PUNPCKHWD;
default:
@@ -5751,6 +5851,22 @@
return 0;
}
+static inline unsigned getVPERMILOpcode(EVT VT) {
+ switch(VT.getSimpleVT().SimpleTy) {
+ case MVT::v4i32:
+ case MVT::v4f32: return X86ISD::VPERMILPS;
+ case MVT::v2i64:
+ case MVT::v2f64: return X86ISD::VPERMILPD;
+ case MVT::v8i32:
+ case MVT::v8f32: return X86ISD::VPERMILPSY;
+ case MVT::v4i64:
+ case MVT::v4f64: return X86ISD::VPERMILPDY;
+ default:
+ llvm_unreachable("Unknown type for vpermil");
+ }
+ return 0;
+}
+
static
SDValue NormalizeVectorShuffle(SDValue Op, SelectionDAG &DAG,
const TargetLowering &TLI,
@@ -5870,7 +5986,7 @@
// NOTE: isPSHUFDMask can also match both masks below (unpckl_undef and
// unpckh_undef). Only use pshufd if speed is more important than size.
if (OptForSize && X86::isUNPCKL_v_undef_Mask(SVOp))
- return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()), dl, VT, V1, V1, DAG);
+ return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V1, V1, DAG);
if (OptForSize && X86::isUNPCKH_v_undef_Mask(SVOp))
return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V1, DAG);
@@ -5942,10 +6058,10 @@
if (X86::isMOVHLPSMask(SVOp))
return getMOVHighToLow(Op, dl, DAG);
- if (X86::isMOVSHDUPMask(SVOp) && HasSSE3 && V2IsUndef && NumElems == 4)
+ if (X86::isMOVSHDUPMask(SVOp, Subtarget))
return getTargetShuffleNode(X86ISD::MOVSHDUP, dl, VT, V1, DAG);
- if (X86::isMOVSLDUPMask(SVOp) && HasSSE3 && V2IsUndef && NumElems == 4)
+ if (X86::isMOVSLDUPMask(SVOp, Subtarget))
return getTargetShuffleNode(X86ISD::MOVSLDUP, dl, VT, V1, DAG);
if (X86::isMOVLPMask(SVOp))
@@ -5990,8 +6106,7 @@
}
if (X86::isUNPCKLMask(SVOp))
- return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()),
- dl, VT, V1, V2, DAG);
+ return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V1, V2, DAG);
if (X86::isUNPCKHMask(SVOp))
return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V2, DAG);
@@ -6018,8 +6133,7 @@
ShuffleVectorSDNode *NewSVOp = cast<ShuffleVectorSDNode>(NewOp);
if (X86::isUNPCKLMask(NewSVOp))
- return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()),
- dl, VT, V2, V1, DAG);
+ return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V2, V1, DAG);
if (X86::isUNPCKHMask(NewSVOp))
return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V2, V1, DAG);
@@ -6069,11 +6183,31 @@
}
if (X86::isUNPCKL_v_undef_Mask(SVOp))
- return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()),
- dl, VT, V1, V1, DAG);
+ return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V1, V1, DAG);
if (X86::isUNPCKH_v_undef_Mask(SVOp))
return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V1, DAG);
+ //===--------------------------------------------------------------------===//
+ // Generate target specific nodes for 128 or 256-bit shuffles only
+ // supported in the AVX instruction set.
+ //
+
+ // Handle VPERMILPS* permutations
+ if (isVPERMILPSMask(M, VT, Subtarget))
+ return getTargetShuffleNode(getVPERMILOpcode(VT), dl, VT, V1,
+ getShuffleVPERMILPSImmediate(SVOp), DAG);
+
+ // Handle VPERMILPD* permutations
+ if (isVPERMILPDMask(M, VT, Subtarget))
+ return getTargetShuffleNode(getVPERMILOpcode(VT), dl, VT, V1,
+ getShuffleVPERMILPDImmediate(SVOp), DAG);
+
+ //===--------------------------------------------------------------------===//
+ // Since no target specific shuffle was selected for this generic one,
+ // lower it into other known shuffles. FIXME: this isn't true yet, but
+ // this is the plan.
+ //
+
// Handle v8i16 specifically since SSE can do byte extraction and insertion.
if (VT == MVT::v8i16) {
SDValue NewOp = LowerVECTOR_SHUFFLEv8i16(Op, DAG);
@@ -6092,16 +6226,6 @@
if (NumElems == 4 && VT.getSizeInBits() == 128)
return LowerVECTOR_SHUFFLE_128v4(SVOp, DAG);
- //===--------------------------------------------------------------------===//
- // Custom lower or generate target specific nodes for 256-bit shuffles.
-
- // Handle VPERMIL permutations
- if (isVPERMILMask(M, VT)) {
- unsigned TargetMask = getShuffleVPERMILImmediate(SVOp);
- if (VT == MVT::v8f32)
- return getTargetShuffleNode(X86ISD::VPERMIL, dl, VT, V1, TargetMask, DAG);
- }
-
// Handle general 256-bit shuffles
if (VT.is256BitVector())
return LowerVECTOR_SHUFFLE_256(SVOp, DAG);
@@ -6233,7 +6357,7 @@
return Op;
// SHUFPS the element to the lowest double word, then movss.
- int Mask[4] = { Idx, -1, -1, -1 };
+ int Mask[4] = { static_cast<int>(Idx), -1, -1, -1 };
EVT VVT = Op.getOperand(0).getValueType();
SDValue Vec = DAG.getVectorShuffle(VVT, dl, Op.getOperand(0),
DAG.getUNDEF(VVT), Mask);
@@ -9718,7 +9842,10 @@
case X86ISD::PUNPCKHWD: return "X86ISD::PUNPCKHWD";
case X86ISD::PUNPCKHDQ: return "X86ISD::PUNPCKHDQ";
case X86ISD::PUNPCKHQDQ: return "X86ISD::PUNPCKHQDQ";
- case X86ISD::VPERMIL: return "X86ISD::VPERMIL";
+ case X86ISD::VPERMILPS: return "X86ISD::VPERMILPS";
+ case X86ISD::VPERMILPSY: return "X86ISD::VPERMILPSY";
+ case X86ISD::VPERMILPD: return "X86ISD::VPERMILPD";
+ case X86ISD::VPERMILPDY: return "X86ISD::VPERMILPDY";
case X86ISD::VASTART_SAVE_XMM_REGS: return "X86ISD::VASTART_SAVE_XMM_REGS";
case X86ISD::VAARG_64: return "X86ISD::VAARG_64";
case X86ISD::WIN_ALLOCA: return "X86ISD::WIN_ALLOCA";
@@ -12520,7 +12647,7 @@
// (add Y, (setne X, 0)) -> sbb -1, Y
// (sub (sete X, 0), Y) -> sbb 0, Y
// (sub (setne X, 0), Y) -> adc -1, Y
-static SDValue OptimizeConditonalInDecrement(SDNode *N, SelectionDAG &DAG) {
+static SDValue OptimizeConditionalInDecrement(SDNode *N, SelectionDAG &DAG) {
DebugLoc DL = N->getDebugLoc();
// Look through ZExts.
@@ -12556,6 +12683,33 @@
DAG.getConstant(0, OtherVal.getValueType()), NewCmp);
}
+static SDValue PerformSubCombine(SDNode *N, SelectionDAG &DAG) {
+ SDValue Op0 = N->getOperand(0);
+ SDValue Op1 = N->getOperand(1);
+
+ // X86 can't encode an immediate LHS of a sub. See if we can push the
+ // negation into a preceding instruction.
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op0)) {
+ uint64_t Op0C = C->getSExtValue();
+
+ // If the RHS of the sub is a XOR with one use and a constant, invert the
+ // immediate. Then add one to the LHS of the sub so we can turn
+ // X-Y -> X+~Y+1, saving one register.
+ if (Op1->hasOneUse() && Op1.getOpcode() == ISD::XOR &&
+ isa<ConstantSDNode>(Op1.getOperand(1))) {
+ uint64_t XorC = cast<ConstantSDNode>(Op1.getOperand(1))->getSExtValue();
+ EVT VT = Op0.getValueType();
+ SDValue NewXor = DAG.getNode(ISD::XOR, Op1.getDebugLoc(), VT,
+ Op1.getOperand(0),
+ DAG.getConstant(~XorC, VT));
+ return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, NewXor,
+ DAG.getConstant(Op0C+1, VT));
+ }
+ }
+
+ return OptimizeConditionalInDecrement(N, DAG);
+}
+
SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
DAGCombinerInfo &DCI) const {
SelectionDAG &DAG = DCI.DAG;
@@ -12565,8 +12719,8 @@
return PerformEXTRACT_VECTOR_ELTCombine(N, DAG, *this);
case ISD::SELECT: return PerformSELECTCombine(N, DAG, Subtarget);
case X86ISD::CMOV: return PerformCMOVCombine(N, DAG, DCI);
- case ISD::ADD:
- case ISD::SUB: return OptimizeConditonalInDecrement(N, DAG);
+ case ISD::ADD: return OptimizeConditionalInDecrement(N, DAG);
+ case ISD::SUB: return PerformSubCombine(N, DAG);
case X86ISD::ADC: return PerformADCCombine(N, DAG, DCI);
case ISD::MUL: return PerformMulCombine(N, DAG, DCI);
case ISD::SHL:
@@ -12592,6 +12746,8 @@
case X86ISD::PUNPCKHQDQ:
case X86ISD::UNPCKHPS:
case X86ISD::UNPCKHPD:
+ case X86ISD::VUNPCKHPSY:
+ case X86ISD::VUNPCKHPDY:
case X86ISD::PUNPCKLBW:
case X86ISD::PUNPCKLWD:
case X86ISD::PUNPCKLDQ:
@@ -12607,7 +12763,10 @@
case X86ISD::PSHUFLW:
case X86ISD::MOVSS:
case X86ISD::MOVSD:
- case X86ISD::VPERMIL:
+ case X86ISD::VPERMILPS:
+ case X86ISD::VPERMILPSY:
+ case X86ISD::VPERMILPD:
+ case X86ISD::VPERMILPDY:
case ISD::VECTOR_SHUFFLE: return PerformShuffleCombine(N, DAG, DCI);
}
Modified: llvm/branches/exception-handling-rewrite/lib/Target/X86/X86ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/X86/X86ISelLowering.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/X86/X86ISelLowering.h (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/X86/X86ISelLowering.h Wed Jul 27 13:40:48 2011
@@ -261,6 +261,8 @@
VUNPCKLPDY,
UNPCKHPS,
UNPCKHPD,
+ VUNPCKHPSY,
+ VUNPCKHPDY,
PUNPCKLBW,
PUNPCKLWD,
PUNPCKLDQ,
@@ -269,7 +271,10 @@
PUNPCKHWD,
PUNPCKHDQ,
PUNPCKHQDQ,
- VPERMIL,
+ VPERMILPS,
+ VPERMILPSY,
+ VPERMILPD,
+ VPERMILPDY,
// VASTART_SAVE_XMM_REGS - Save xmm argument registers to the stack,
// according to %al. An operator is needed so that this can be expanded
@@ -406,11 +411,11 @@
/// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSHDUP.
- bool isMOVSHDUPMask(ShuffleVectorSDNode *N);
+ bool isMOVSHDUPMask(ShuffleVectorSDNode *N, const X86Subtarget *Subtarget);
/// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSLDUP.
- bool isMOVSLDUPMask(ShuffleVectorSDNode *N);
+ bool isMOVSLDUPMask(ShuffleVectorSDNode *N, const X86Subtarget *Subtarget);
/// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVDDUP.
Modified: llvm/branches/exception-handling-rewrite/lib/Target/X86/X86InstrFragmentsSIMD.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/X86/X86InstrFragmentsSIMD.td?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/X86/X86InstrFragmentsSIMD.td (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/X86/X86InstrFragmentsSIMD.td Wed Jul 27 13:40:48 2011
@@ -49,16 +49,16 @@
def X86andnp : SDNode<"X86ISD::ANDNP",
SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>]>>;
-def X86psignb : SDNode<"X86ISD::PSIGNB",
+def X86psignb : SDNode<"X86ISD::PSIGNB",
SDTypeProfile<1, 2, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>]>>;
-def X86psignw : SDNode<"X86ISD::PSIGNW",
+def X86psignw : SDNode<"X86ISD::PSIGNW",
SDTypeProfile<1, 2, [SDTCisVT<0, v8i16>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>]>>;
-def X86psignd : SDNode<"X86ISD::PSIGND",
+def X86psignd : SDNode<"X86ISD::PSIGND",
SDTypeProfile<1, 2, [SDTCisVT<0, v4i32>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>]>>;
-def X86pblendv : SDNode<"X86ISD::PBLENDVB",
+def X86pblendv : SDNode<"X86ISD::PBLENDVB",
SDTypeProfile<1, 3, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>, SDTCisSameAs<0,3>]>>;
def X86pextrb : SDNode<"X86ISD::PEXTRB",
@@ -133,12 +133,15 @@
def X86Movlps : SDNode<"X86ISD::MOVLPS", SDTShuff2Op>;
def X86Movlpd : SDNode<"X86ISD::MOVLPD", SDTShuff2Op>;
-def X86Unpcklps : SDNode<"X86ISD::UNPCKLPS", SDTShuff2Op>;
-def X86Unpcklpd : SDNode<"X86ISD::UNPCKLPD", SDTShuff2Op>;
+def X86Unpcklps : SDNode<"X86ISD::UNPCKLPS", SDTShuff2Op>;
+def X86Unpcklpd : SDNode<"X86ISD::UNPCKLPD", SDTShuff2Op>;
def X86Unpcklpsy : SDNode<"X86ISD::VUNPCKLPSY", SDTShuff2Op>;
def X86Unpcklpdy : SDNode<"X86ISD::VUNPCKLPDY", SDTShuff2Op>;
-def X86Unpckhps : SDNode<"X86ISD::UNPCKHPS", SDTShuff2Op>;
-def X86Unpckhpd : SDNode<"X86ISD::UNPCKHPD", SDTShuff2Op>;
+
+def X86Unpckhps : SDNode<"X86ISD::UNPCKHPS", SDTShuff2Op>;
+def X86Unpckhpd : SDNode<"X86ISD::UNPCKHPD", SDTShuff2Op>;
+def X86Unpckhpsy : SDNode<"X86ISD::VUNPCKHPSY", SDTShuff2Op>;
+def X86Unpckhpdy : SDNode<"X86ISD::VUNPCKHPDY", SDTShuff2Op>;
def X86Punpcklbw : SDNode<"X86ISD::PUNPCKLBW", SDTShuff2Op>;
def X86Punpcklwd : SDNode<"X86ISD::PUNPCKLWD", SDTShuff2Op>;
@@ -150,7 +153,10 @@
def X86Punpckhdq : SDNode<"X86ISD::PUNPCKHDQ", SDTShuff2Op>;
def X86Punpckhqdq : SDNode<"X86ISD::PUNPCKHQDQ", SDTShuff2Op>;
-def X86VPermil : SDNode<"X86ISD::VPERMIL", SDTShuff2OpI>;
+def X86VPermilps : SDNode<"X86ISD::VPERMILPS", SDTShuff2OpI>;
+def X86VPermilpsy : SDNode<"X86ISD::VPERMILPSY", SDTShuff2OpI>;
+def X86VPermilpd : SDNode<"X86ISD::VPERMILPD", SDTShuff2OpI>;
+def X86VPermilpdy : SDNode<"X86ISD::VPERMILPDY", SDTShuff2OpI>;
//===----------------------------------------------------------------------===//
// SSE Complex Patterns
@@ -358,7 +364,7 @@
return getI8Imm(X86::getExtractVEXTRACTF128Immediate(N));
}]>;
-// INSERT_get_vinsertf128_imm xform function: convert insert_subvector index to
+// INSERT_get_vinsertf128_imm xform function: convert insert_subvector index to
// VINSERTF128 imm.
def INSERT_get_vinsertf128_imm : SDNodeXForm<insert_subvector, [{
return getI8Imm(X86::getInsertVINSERTF128Immediate(N));
@@ -400,16 +406,6 @@
return X86::isMOVLMask(cast<ShuffleVectorSDNode>(N));
}]>;
-def movshdup : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
- return X86::isMOVSHDUPMask(cast<ShuffleVectorSDNode>(N));
-}]>;
-
-def movsldup : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
- return X86::isMOVSLDUPMask(cast<ShuffleVectorSDNode>(N));
-}]>;
-
def unpckl : PatFrag<(ops node:$lhs, node:$rhs),
(vector_shuffle node:$lhs, node:$rhs), [{
return X86::isUNPCKLMask(cast<ShuffleVectorSDNode>(N));
@@ -420,16 +416,6 @@
return X86::isUNPCKHMask(cast<ShuffleVectorSDNode>(N));
}]>;
-def unpckl_undef : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
- return X86::isUNPCKL_v_undef_Mask(cast<ShuffleVectorSDNode>(N));
-}]>;
-
-def unpckh_undef : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
- return X86::isUNPCKH_v_undef_Mask(cast<ShuffleVectorSDNode>(N));
-}]>;
-
def pshufd : PatFrag<(ops node:$lhs, node:$rhs),
(vector_shuffle node:$lhs, node:$rhs), [{
return X86::isPSHUFDMask(cast<ShuffleVectorSDNode>(N));
Modified: llvm/branches/exception-handling-rewrite/lib/Target/X86/X86InstrSSE.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Target/X86/X86InstrSSE.td?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Target/X86/X86InstrSSE.td (original)
+++ llvm/branches/exception-handling-rewrite/lib/Target/X86/X86InstrSSE.td Wed Jul 27 13:40:48 2011
@@ -2646,71 +2646,69 @@
let ExeDomain = SSEPackedInt in {
multiclass sse2_unpack<bits<8> opc, string OpcodeStr, ValueType vt,
- PatFrag unp_frag, PatFrag bc_frag, bit Is2Addr = 1> {
+ SDNode OpNode, PatFrag bc_frag, bit Is2Addr = 1> {
def rr : PDI<opc, MRMSrcReg,
(outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
!if(Is2Addr,
!strconcat(OpcodeStr,"\t{$src2, $dst|$dst, $src2}"),
!strconcat(OpcodeStr,"\t{$src2, $src1, $dst|$dst, $src1, $src2}")),
- [(set VR128:$dst, (vt (unp_frag VR128:$src1, VR128:$src2)))]>;
+ [(set VR128:$dst, (vt (OpNode VR128:$src1, VR128:$src2)))]>;
def rm : PDI<opc, MRMSrcMem,
(outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
!if(Is2Addr,
!strconcat(OpcodeStr,"\t{$src2, $dst|$dst, $src2}"),
!strconcat(OpcodeStr,"\t{$src2, $src1, $dst|$dst, $src1, $src2}")),
- [(set VR128:$dst, (unp_frag VR128:$src1,
+ [(set VR128:$dst, (OpNode VR128:$src1,
(bc_frag (memopv2i64
addr:$src2))))]>;
}
let Predicates = [HasAVX] in {
- defm VPUNPCKLBW : sse2_unpack<0x60, "vpunpcklbw", v16i8, unpckl, bc_v16i8,
- 0>, VEX_4V;
- defm VPUNPCKLWD : sse2_unpack<0x61, "vpunpcklwd", v8i16, unpckl, bc_v8i16,
- 0>, VEX_4V;
- defm VPUNPCKLDQ : sse2_unpack<0x62, "vpunpckldq", v4i32, unpckl, bc_v4i32,
- 0>, VEX_4V;
+ defm VPUNPCKLBW : sse2_unpack<0x60, "vpunpcklbw", v16i8, X86Punpcklbw,
+ bc_v16i8, 0>, VEX_4V;
+ defm VPUNPCKLWD : sse2_unpack<0x61, "vpunpcklwd", v8i16, X86Punpcklwd,
+ bc_v8i16, 0>, VEX_4V;
+ defm VPUNPCKLDQ : sse2_unpack<0x62, "vpunpckldq", v4i32, X86Punpckldq,
+ bc_v4i32, 0>, VEX_4V;
/// FIXME: we could eliminate this and use sse2_unpack instead if tblgen
/// knew to collapse (bitconvert VT to VT) into its operand.
def VPUNPCKLQDQrr : PDI<0x6C, MRMSrcReg,
- (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
- "vpunpcklqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set VR128:$dst,
- (v2i64 (unpckl VR128:$src1, VR128:$src2)))]>, VEX_4V;
+ (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
+ "vpunpcklqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set VR128:$dst, (v2i64 (X86Punpcklqdq VR128:$src1,
+ VR128:$src2)))]>, VEX_4V;
def VPUNPCKLQDQrm : PDI<0x6C, MRMSrcMem,
- (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
- "vpunpcklqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set VR128:$dst,
- (v2i64 (unpckl VR128:$src1,
- (memopv2i64 addr:$src2))))]>, VEX_4V;
-
- defm VPUNPCKHBW : sse2_unpack<0x68, "vpunpckhbw", v16i8, unpckh, bc_v16i8,
- 0>, VEX_4V;
- defm VPUNPCKHWD : sse2_unpack<0x69, "vpunpckhwd", v8i16, unpckh, bc_v8i16,
- 0>, VEX_4V;
- defm VPUNPCKHDQ : sse2_unpack<0x6A, "vpunpckhdq", v4i32, unpckh, bc_v4i32,
- 0>, VEX_4V;
+ (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
+ "vpunpcklqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set VR128:$dst, (v2i64 (X86Punpcklqdq VR128:$src1,
+ (memopv2i64 addr:$src2))))]>, VEX_4V;
+
+ defm VPUNPCKHBW : sse2_unpack<0x68, "vpunpckhbw", v16i8, X86Punpckhbw,
+ bc_v16i8, 0>, VEX_4V;
+ defm VPUNPCKHWD : sse2_unpack<0x69, "vpunpckhwd", v8i16, X86Punpckhwd,
+ bc_v8i16, 0>, VEX_4V;
+ defm VPUNPCKHDQ : sse2_unpack<0x6A, "vpunpckhdq", v4i32, X86Punpckhdq,
+ bc_v4i32, 0>, VEX_4V;
/// FIXME: we could eliminate this and use sse2_unpack instead if tblgen
/// knew to collapse (bitconvert VT to VT) into its operand.
def VPUNPCKHQDQrr : PDI<0x6D, MRMSrcReg,
- (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
- "vpunpckhqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set VR128:$dst,
- (v2i64 (unpckh VR128:$src1, VR128:$src2)))]>, VEX_4V;
+ (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
+ "vpunpckhqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set VR128:$dst, (v2i64 (X86Punpckhqdq VR128:$src1,
+ VR128:$src2)))]>, VEX_4V;
def VPUNPCKHQDQrm : PDI<0x6D, MRMSrcMem,
- (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
- "vpunpckhqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set VR128:$dst,
- (v2i64 (unpckh VR128:$src1,
- (memopv2i64 addr:$src2))))]>, VEX_4V;
+ (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
+ "vpunpckhqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set VR128:$dst, (v2i64 (X86Punpckhqdq VR128:$src1,
+ (memopv2i64 addr:$src2))))]>, VEX_4V;
}
let Constraints = "$src1 = $dst" in {
- defm PUNPCKLBW : sse2_unpack<0x60, "punpcklbw", v16i8, unpckl, bc_v16i8>;
- defm PUNPCKLWD : sse2_unpack<0x61, "punpcklwd", v8i16, unpckl, bc_v8i16>;
- defm PUNPCKLDQ : sse2_unpack<0x62, "punpckldq", v4i32, unpckl, bc_v4i32>;
+ defm PUNPCKLBW : sse2_unpack<0x60, "punpcklbw", v16i8, X86Punpcklbw, bc_v16i8>;
+ defm PUNPCKLWD : sse2_unpack<0x61, "punpcklwd", v8i16, X86Punpcklwd, bc_v8i16>;
+ defm PUNPCKLDQ : sse2_unpack<0x62, "punpckldq", v4i32, X86Punpckldq, bc_v4i32>;
/// FIXME: we could eliminate this and use sse2_unpack instead if tblgen
/// knew to collapse (bitconvert VT to VT) into its operand.
@@ -2718,17 +2716,17 @@
(outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
"punpcklqdq\t{$src2, $dst|$dst, $src2}",
[(set VR128:$dst,
- (v2i64 (unpckl VR128:$src1, VR128:$src2)))]>;
+ (v2i64 (X86Punpcklqdq VR128:$src1, VR128:$src2)))]>;
def PUNPCKLQDQrm : PDI<0x6C, MRMSrcMem,
(outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
"punpcklqdq\t{$src2, $dst|$dst, $src2}",
[(set VR128:$dst,
- (v2i64 (unpckl VR128:$src1,
+ (v2i64 (X86Punpcklqdq VR128:$src1,
(memopv2i64 addr:$src2))))]>;
- defm PUNPCKHBW : sse2_unpack<0x68, "punpckhbw", v16i8, unpckh, bc_v16i8>;
- defm PUNPCKHWD : sse2_unpack<0x69, "punpckhwd", v8i16, unpckh, bc_v8i16>;
- defm PUNPCKHDQ : sse2_unpack<0x6A, "punpckhdq", v4i32, unpckh, bc_v4i32>;
+ defm PUNPCKHBW : sse2_unpack<0x68, "punpckhbw", v16i8, X86Punpckhbw, bc_v16i8>;
+ defm PUNPCKHWD : sse2_unpack<0x69, "punpckhwd", v8i16, X86Punpckhwd, bc_v8i16>;
+ defm PUNPCKHDQ : sse2_unpack<0x6A, "punpckhdq", v4i32, X86Punpckhdq, bc_v4i32>;
/// FIXME: we could eliminate this and use sse2_unpack instead if tblgen
/// knew to collapse (bitconvert VT to VT) into its operand.
@@ -2736,12 +2734,12 @@
(outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
"punpckhqdq\t{$src2, $dst|$dst, $src2}",
[(set VR128:$dst,
- (v2i64 (unpckh VR128:$src1, VR128:$src2)))]>;
+ (v2i64 (X86Punpckhqdq VR128:$src1, VR128:$src2)))]>;
def PUNPCKHQDQrm : PDI<0x6D, MRMSrcMem,
(outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
"punpckhqdq\t{$src2, $dst|$dst, $src2}",
[(set VR128:$dst,
- (v2i64 (unpckh VR128:$src1,
+ (v2i64 (X86Punpckhqdq VR128:$src1,
(memopv2i64 addr:$src2))))]>;
}
@@ -3219,37 +3217,68 @@
// SSE3 - Move Instructions
//===---------------------------------------------------------------------===//
-// Replicate Single FP
-multiclass sse3_replicate_sfp<bits<8> op, PatFrag rep_frag, string OpcodeStr> {
-def rr : S3SI<op, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
+//===---------------------------------------------------------------------===//
+// Replicate Single FP - MOVSHDUP and MOVSLDUP
+//
+multiclass sse3_replicate_sfp<bits<8> op, SDNode OpNode, string OpcodeStr,
+ ValueType vt, RegisterClass RC, PatFrag mem_frag,
+ X86MemOperand x86memop> {
+def rr : S3SI<op, MRMSrcReg, (outs RC:$dst), (ins RC:$src),
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
- [(set VR128:$dst, (v4f32 (rep_frag
- VR128:$src, (undef))))]>;
-def rm : S3SI<op, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
+ [(set RC:$dst, (vt (OpNode RC:$src)))]>;
+def rm : S3SI<op, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src),
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
- [(set VR128:$dst, (rep_frag
- (memopv4f32 addr:$src), (undef)))]>;
+ [(set RC:$dst, (OpNode (mem_frag addr:$src)))]>;
}
-multiclass sse3_replicate_sfp_y<bits<8> op, PatFrag rep_frag,
- string OpcodeStr> {
-def rr : S3SI<op, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
- !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), []>;
-def rm : S3SI<op, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src),
- !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), []>;
+let Predicates = [HasAVX] in {
+ defm VMOVSHDUP : sse3_replicate_sfp<0x16, X86Movshdup, "vmovshdup",
+ v4f32, VR128, memopv4f32, f128mem>, VEX;
+ defm VMOVSLDUP : sse3_replicate_sfp<0x12, X86Movsldup, "vmovsldup",
+ v4f32, VR128, memopv4f32, f128mem>, VEX;
+ defm VMOVSHDUPY : sse3_replicate_sfp<0x16, X86Movshdup, "vmovshdup",
+ v8f32, VR256, memopv8f32, f256mem>, VEX;
+ defm VMOVSLDUPY : sse3_replicate_sfp<0x12, X86Movsldup, "vmovsldup",
+ v8f32, VR256, memopv8f32, f256mem>, VEX;
+}
+defm MOVSHDUP : sse3_replicate_sfp<0x16, X86Movshdup, "movshdup", v4f32, VR128,
+ memopv4f32, f128mem>;
+defm MOVSLDUP : sse3_replicate_sfp<0x12, X86Movsldup, "movsldup", v4f32, VR128,
+ memopv4f32, f128mem>;
+
+let Predicates = [HasSSE3] in {
+ def : Pat<(v4i32 (X86Movshdup VR128:$src)),
+ (MOVSHDUPrr VR128:$src)>;
+ def : Pat<(v4i32 (X86Movshdup (bc_v4i32 (memopv2i64 addr:$src)))),
+ (MOVSHDUPrm addr:$src)>;
+ def : Pat<(v4i32 (X86Movsldup VR128:$src)),
+ (MOVSLDUPrr VR128:$src)>;
+ def : Pat<(v4i32 (X86Movsldup (bc_v4i32 (memopv2i64 addr:$src)))),
+ (MOVSLDUPrm addr:$src)>;
}
let Predicates = [HasAVX] in {
- // FIXME: Merge above classes when we have patterns for the ymm version
- defm VMOVSHDUP : sse3_replicate_sfp<0x16, movshdup, "vmovshdup">, VEX;
- defm VMOVSLDUP : sse3_replicate_sfp<0x12, movsldup, "vmovsldup">, VEX;
- defm VMOVSHDUPY : sse3_replicate_sfp_y<0x16, movshdup, "vmovshdup">, VEX;
- defm VMOVSLDUPY : sse3_replicate_sfp_y<0x12, movsldup, "vmovsldup">, VEX;
+ def : Pat<(v4i32 (X86Movshdup VR128:$src)),
+ (VMOVSHDUPrr VR128:$src)>;
+ def : Pat<(v4i32 (X86Movshdup (bc_v4i32 (memopv2i64 addr:$src)))),
+ (VMOVSHDUPrm addr:$src)>;
+ def : Pat<(v4i32 (X86Movsldup VR128:$src)),
+ (VMOVSLDUPrr VR128:$src)>;
+ def : Pat<(v4i32 (X86Movsldup (bc_v4i32 (memopv2i64 addr:$src)))),
+ (VMOVSLDUPrm addr:$src)>;
+ def : Pat<(v8i32 (X86Movshdup VR256:$src)),
+ (VMOVSHDUPYrr VR256:$src)>;
+ def : Pat<(v8i32 (X86Movshdup (bc_v8i32 (memopv4i64 addr:$src)))),
+ (VMOVSHDUPYrm addr:$src)>;
+ def : Pat<(v8i32 (X86Movsldup VR256:$src)),
+ (VMOVSLDUPYrr VR256:$src)>;
+ def : Pat<(v8i32 (X86Movsldup (bc_v8i32 (memopv4i64 addr:$src)))),
+ (VMOVSLDUPYrm addr:$src)>;
}
-defm MOVSHDUP : sse3_replicate_sfp<0x16, movshdup, "movshdup">;
-defm MOVSLDUP : sse3_replicate_sfp<0x12, movsldup, "movsldup">;
-// Replicate Double FP
+//===---------------------------------------------------------------------===//
+// Replicate Double FP - MOVDDUP
+//
multiclass sse3_replicate_dfp<string OpcodeStr> {
def rr : S3DI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
@@ -3306,22 +3335,6 @@
(MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>;
}
-// vector_shuffle v1, <undef> <1, 1, 3, 3>
-let AddedComplexity = 15 in
-def : Pat<(v4i32 (movshdup VR128:$src, (undef))),
- (MOVSHDUPrr VR128:$src)>, Requires<[HasSSE3]>;
-let AddedComplexity = 20 in
-def : Pat<(v4i32 (movshdup (bc_v4i32 (memopv2i64 addr:$src)), (undef))),
- (MOVSHDUPrm addr:$src)>, Requires<[HasSSE3]>;
-
-// vector_shuffle v1, <undef> <0, 0, 2, 2>
-let AddedComplexity = 15 in
- def : Pat<(v4i32 (movsldup VR128:$src, (undef))),
- (MOVSLDUPrr VR128:$src)>, Requires<[HasSSE3]>;
-let AddedComplexity = 20 in
- def : Pat<(v4i32 (movsldup (bc_v4i32 (memopv2i64 addr:$src)), (undef))),
- (MOVSLDUPrm addr:$src)>, Requires<[HasSSE3]>;
-
//===---------------------------------------------------------------------===//
// SSE3 - Arithmetic
//===---------------------------------------------------------------------===//
@@ -3735,12 +3748,8 @@
let AddedComplexity = 10 in {
def : Pat<(splat_lo (v2f64 VR128:$src), (undef)),
(UNPCKLPDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>;
-def : Pat<(unpckh (v2f64 VR128:$src), (undef)),
- (UNPCKHPDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>;
def : Pat<(splat_lo (v2i64 VR128:$src), (undef)),
(PUNPCKLQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>;
-def : Pat<(unpckh (v2i64 VR128:$src), (undef)),
- (PUNPCKHQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>;
}
// Special unary SHUFPSrri case.
@@ -3781,46 +3790,6 @@
(SHUFFLE_get_shuf_imm VR128:$src3))>,
Requires<[HasSSE2]>;
-// vector_shuffle v1, <undef>, <0, 0, 1, 1, ...>
-let AddedComplexity = 15 in {
-def : Pat<(v4i32 (unpckl_undef:$src2 VR128:$src, (undef))),
- (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>,
- Requires<[OptForSpeed, HasSSE2]>;
-def : Pat<(v4f32 (unpckl_undef:$src2 VR128:$src, (undef))),
- (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>,
- Requires<[OptForSpeed, HasSSE2]>;
-}
-let AddedComplexity = 10 in {
-def : Pat<(v4f32 (unpckl_undef VR128:$src, (undef))),
- (UNPCKLPSrr VR128:$src, VR128:$src)>;
-def : Pat<(v16i8 (unpckl_undef VR128:$src, (undef))),
- (PUNPCKLBWrr VR128:$src, VR128:$src)>;
-def : Pat<(v8i16 (unpckl_undef VR128:$src, (undef))),
- (PUNPCKLWDrr VR128:$src, VR128:$src)>;
-def : Pat<(v4i32 (unpckl_undef VR128:$src, (undef))),
- (PUNPCKLDQrr VR128:$src, VR128:$src)>;
-}
-
-// vector_shuffle v1, <undef>, <2, 2, 3, 3, ...>
-let AddedComplexity = 15 in {
-def : Pat<(v4i32 (unpckh_undef:$src2 VR128:$src, (undef))),
- (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>,
- Requires<[OptForSpeed, HasSSE2]>;
-def : Pat<(v4f32 (unpckh_undef:$src2 VR128:$src, (undef))),
- (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>,
- Requires<[OptForSpeed, HasSSE2]>;
-}
-let AddedComplexity = 10 in {
-def : Pat<(v4f32 (unpckh_undef VR128:$src, (undef))),
- (UNPCKHPSrr VR128:$src, VR128:$src)>;
-def : Pat<(v16i8 (unpckh_undef VR128:$src, (undef))),
- (PUNPCKHBWrr VR128:$src, VR128:$src)>;
-def : Pat<(v8i16 (unpckh_undef VR128:$src, (undef))),
- (PUNPCKHWDrr VR128:$src, VR128:$src)>;
-def : Pat<(v4i32 (unpckh_undef VR128:$src, (undef))),
- (PUNPCKHDQrr VR128:$src, VR128:$src)>;
-}
-
let AddedComplexity = 20 in {
// vector_shuffle v1, v2 <0, 1, 4, 5> using MOVLHPS
def : Pat<(v4i32 (movlhps VR128:$src1, VR128:$src2)),
@@ -5553,6 +5522,12 @@
VR256:$src1, (memopv8i32 addr:$src2), imm:$src3),
(VPERM2F128rm VR256:$src1, addr:$src2, imm:$src3)>;
+// Shuffle with VPERMIL instructions
+def : Pat<(v8f32 (X86VPermilpsy VR256:$src1, (i8 imm:$imm))),
+ (VPERMILPSYri VR256:$src1, imm:$imm)>;
+def : Pat<(v4f64 (X86VPermilpdy VR256:$src1, (i8 imm:$imm))),
+ (VPERMILPDYri VR256:$src1, imm:$imm)>;
+
//===----------------------------------------------------------------------===//
// VZERO - Zero YMM registers
//
@@ -5574,10 +5549,6 @@
// The AVX version of some but not all of them are described here, and more
// should come in a near future.
-// Shuffle with VPERMIL instructions
-def : Pat<(v8f32 (X86VPermil VR256:$src1, (i8 imm:$imm))),
- (VPERMILPSYri VR256:$src1, imm:$imm)>;
-
// Shuffle with PSHUFD instruction folding loads. The first two patterns match
// SSE2 loads, which are always promoted to v2i64. The last one should match
// the SSE1 case, where the only legal load is v4f32, but there is no PSHUFD
@@ -5708,6 +5679,12 @@
def : Pat<(v4f32 (X86Unpckhps VR128:$src1, VR128:$src2)),
(UNPCKHPSrr VR128:$src1, VR128:$src2)>;
+// Shuffle with VUNPCKHPSY
+def : Pat<(v8f32 (X86Unpckhpsy VR256:$src1, (memopv8f32 addr:$src2))),
+ (VUNPCKHPSYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>;
+def : Pat<(v8f32 (X86Unpckhpsy VR256:$src1, VR256:$src2)),
+ (VUNPCKHPSYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>;
+
// Shuffle with UNPCKLPD
def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))),
(VUNPCKLPDrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>;
@@ -5734,59 +5711,11 @@
def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, VR128:$src2)),
(UNPCKHPDrr VR128:$src1, VR128:$src2)>;
-// Shuffle with PUNPCKLBW
-def : Pat<(v16i8 (X86Punpcklbw VR128:$src1,
- (bc_v16i8 (memopv2i64 addr:$src2)))),
- (PUNPCKLBWrm VR128:$src1, addr:$src2)>;
-def : Pat<(v16i8 (X86Punpcklbw VR128:$src1, VR128:$src2)),
- (PUNPCKLBWrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKLWD
-def : Pat<(v8i16 (X86Punpcklwd VR128:$src1,
- (bc_v8i16 (memopv2i64 addr:$src2)))),
- (PUNPCKLWDrm VR128:$src1, addr:$src2)>;
-def : Pat<(v8i16 (X86Punpcklwd VR128:$src1, VR128:$src2)),
- (PUNPCKLWDrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKLDQ
-def : Pat<(v4i32 (X86Punpckldq VR128:$src1,
- (bc_v4i32 (memopv2i64 addr:$src2)))),
- (PUNPCKLDQrm VR128:$src1, addr:$src2)>;
-def : Pat<(v4i32 (X86Punpckldq VR128:$src1, VR128:$src2)),
- (PUNPCKLDQrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKLQDQ
-def : Pat<(v2i64 (X86Punpcklqdq VR128:$src1, (memopv2i64 addr:$src2))),
- (PUNPCKLQDQrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2i64 (X86Punpcklqdq VR128:$src1, VR128:$src2)),
- (PUNPCKLQDQrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKHBW
-def : Pat<(v16i8 (X86Punpckhbw VR128:$src1,
- (bc_v16i8 (memopv2i64 addr:$src2)))),
- (PUNPCKHBWrm VR128:$src1, addr:$src2)>;
-def : Pat<(v16i8 (X86Punpckhbw VR128:$src1, VR128:$src2)),
- (PUNPCKHBWrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKHWD
-def : Pat<(v8i16 (X86Punpckhwd VR128:$src1,
- (bc_v8i16 (memopv2i64 addr:$src2)))),
- (PUNPCKHWDrm VR128:$src1, addr:$src2)>;
-def : Pat<(v8i16 (X86Punpckhwd VR128:$src1, VR128:$src2)),
- (PUNPCKHWDrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKHDQ
-def : Pat<(v4i32 (X86Punpckhdq VR128:$src1,
- (bc_v4i32 (memopv2i64 addr:$src2)))),
- (PUNPCKHDQrm VR128:$src1, addr:$src2)>;
-def : Pat<(v4i32 (X86Punpckhdq VR128:$src1, VR128:$src2)),
- (PUNPCKHDQrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKHQDQ
-def : Pat<(v2i64 (X86Punpckhqdq VR128:$src1, (memopv2i64 addr:$src2))),
- (PUNPCKHQDQrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2i64 (X86Punpckhqdq VR128:$src1, VR128:$src2)),
- (PUNPCKHQDQrr VR128:$src1, VR128:$src2)>;
+// Shuffle with VUNPCKHPDY
+def : Pat<(v4f64 (X86Unpckhpdy VR256:$src1, (memopv4f64 addr:$src2))),
+ (VUNPCKHPDYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>;
+def : Pat<(v4f64 (X86Unpckhpdy VR256:$src1, VR256:$src2)),
+ (VUNPCKHPDYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>;
// Shuffle with MOVLHPS
def : Pat<(X86Movlhps VR128:$src1,
@@ -5853,28 +5782,6 @@
def : Pat<(v4i32 (X86Movsd VR128:$src1, VR128:$src2)),
(MOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4i32 VR128:$src2), sub_sd))>;
-// Shuffle with MOVSHDUP
-def : Pat<(v4i32 (X86Movshdup VR128:$src)),
- (MOVSHDUPrr VR128:$src)>;
-def : Pat<(X86Movshdup (bc_v4i32 (memopv2i64 addr:$src))),
- (MOVSHDUPrm addr:$src)>;
-
-def : Pat<(v4f32 (X86Movshdup VR128:$src)),
- (MOVSHDUPrr VR128:$src)>;
-def : Pat<(X86Movshdup (memopv4f32 addr:$src)),
- (MOVSHDUPrm addr:$src)>;
-
-// Shuffle with MOVSLDUP
-def : Pat<(v4i32 (X86Movsldup VR128:$src)),
- (MOVSLDUPrr VR128:$src)>;
-def : Pat<(X86Movsldup (bc_v4i32 (memopv2i64 addr:$src))),
- (MOVSLDUPrm addr:$src)>;
-
-def : Pat<(v4f32 (X86Movsldup VR128:$src)),
- (MOVSLDUPrr VR128:$src)>;
-def : Pat<(X86Movsldup (memopv4f32 addr:$src)),
- (MOVSLDUPrm addr:$src)>;
-
// Shuffle with PSHUFHW
def : Pat<(v8i16 (X86PShufhw VR128:$src, (i8 imm:$imm))),
(PSHUFHWri VR128:$src, imm:$imm)>;
Modified: llvm/branches/exception-handling-rewrite/lib/Transforms/IPO/IPO.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Transforms/IPO/IPO.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Transforms/IPO/IPO.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Transforms/IPO/IPO.cpp Wed Jul 27 13:40:48 2011
@@ -70,6 +70,10 @@
unwrap(PM)->add(createFunctionInliningPass());
}
+void LLVMAddAlwaysInlinerPass(LLVMPassManagerRef PM) {
+ unwrap(PM)->add(llvm::createAlwaysInlinerPass());
+}
+
void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createGlobalDCEPass());
}
@@ -98,11 +102,6 @@
unwrap(PM)->add(createInternalizePass(AllButMain != 0));
}
-
-void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM) {
- // FIXME: Remove in LLVM 3.0.
-}
-
void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createStripDeadPrototypesPass());
}
Modified: llvm/branches/exception-handling-rewrite/lib/Transforms/Instrumentation/GCOVProfiling.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Transforms/Instrumentation/GCOVProfiling.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Transforms/Instrumentation/GCOVProfiling.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Transforms/Instrumentation/GCOVProfiling.cpp Wed Jul 27 13:40:48 2011
@@ -377,7 +377,7 @@
if (!Use402Format)
out->write("oncg*404MVLL", 12);
else
- out->write("oncg*402MVLL", 12);
+ out->write("oncg*204MVLL", 12);
}
for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(),
Modified: llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/DeadStoreElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/DeadStoreElimination.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/DeadStoreElimination.cpp Wed Jul 27 13:40:48 2011
@@ -665,7 +665,7 @@
continue;
}
-
+
AliasAnalysis::Location LoadedLoc;
// If we encounter a use of the pointer, it is no longer considered dead
@@ -675,9 +675,12 @@
LoadedLoc = AA->getLocation(V);
} else if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(BBI)) {
LoadedLoc = AA->getLocationForSource(MTI);
- } else {
- // Not a loading instruction.
+ } else if (!BBI->mayReadOrWriteMemory()) {
+ // Instruction doesn't touch memory.
continue;
+ } else {
+ // Unknown inst; assume it clobbers everything.
+ break;
}
// Remove any allocas from the DeadPointer set that are loaded, as this
Modified: llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/LowerAtomic.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/LowerAtomic.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/LowerAtomic.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/LowerAtomic.cpp Wed Jul 27 13:40:48 2011
@@ -115,6 +115,11 @@
return true;
}
+static bool LowerFenceInst(FenceInst *FI) {
+ FI->eraseFromParent();
+ return true;
+}
+
namespace {
struct LowerAtomic : public BasicBlockPass {
static char ID;
@@ -123,9 +128,13 @@
}
bool runOnBasicBlock(BasicBlock &BB) {
bool Changed = false;
- for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; )
- if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(DI++))
+ for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) {
+ Instruction *Inst = DI++;
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst))
Changed |= LowerAtomicIntrinsic(II);
+ if (FenceInst *FI = dyn_cast<FenceInst>(Inst))
+ Changed |= LowerFenceInst(FI);
+ }
return Changed;
}
};
Modified: llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/SCCP.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/SCCP.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/SCCP.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/Transforms/Scalar/SCCP.cpp Wed Jul 27 13:40:48 2011
@@ -532,6 +532,7 @@
void visitResumeInst (TerminatorInst &I) { /*returns void*/ }
void visitUnwindInst (TerminatorInst &I) { /*returns void*/ }
void visitUnreachableInst(TerminatorInst &I) { /*returns void*/ }
+ void visitFenceInst (FenceInst &I) { /*returns void*/ }
void visitAllocaInst (Instruction &I) { markOverdefined(&I); }
void visitVAArgInst (Instruction &I) { markAnythingOverdefined(&I); }
Modified: llvm/branches/exception-handling-rewrite/lib/VMCore/Instruction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/lib/VMCore/Instruction.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/lib/VMCore/Instruction.cpp (original)
+++ llvm/branches/exception-handling-rewrite/lib/VMCore/Instruction.cpp Wed Jul 27 13:40:48 2011
@@ -211,6 +211,9 @@
return IVI->getIndices() == cast<InsertValueInst>(I)->getIndices();
if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(this))
return EVI->getIndices() == cast<ExtractValueInst>(I)->getIndices();
+ if (const FenceInst *FI = dyn_cast<FenceInst>(this))
+ return FI->getOrdering() == cast<FenceInst>(FI)->getOrdering() &&
+ FI->getSynchScope() == cast<FenceInst>(FI)->getSynchScope();
return true;
}
@@ -251,6 +254,9 @@
return IVI->getIndices() == cast<InsertValueInst>(I)->getIndices();
if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(this))
return EVI->getIndices() == cast<ExtractValueInst>(I)->getIndices();
+ if (const FenceInst *FI = dyn_cast<FenceInst>(this))
+ return FI->getOrdering() == cast<FenceInst>(FI)->getOrdering() &&
+ FI->getSynchScope() == cast<FenceInst>(FI)->getSynchScope();
return true;
}
@@ -283,6 +289,7 @@
default: return false;
case Instruction::VAArg:
case Instruction::Load:
+ case Instruction::Fence: // FIXME: refine definition of mayReadFromMemory
return true;
case Instruction::Call:
return !cast<CallInst>(this)->doesNotAccessMemory();
@@ -298,6 +305,7 @@
bool Instruction::mayWriteToMemory() const {
switch (getOpcode()) {
default: return false;
+ case Instruction::Fence: // FIXME: refine definition of mayWriteToMemory
case Instruction::Store:
case Instruction::VAArg:
return true;
@@ -395,6 +403,7 @@
case Switch:
case Unwind:
case Unreachable:
+ case Fence:
return false; // Misc instructions which have effects
}
}
Modified: llvm/branches/exception-handling-rewrite/test/CodeGen/ARM/sxt_rot.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/test/CodeGen/ARM/sxt_rot.ll?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/test/CodeGen/ARM/sxt_rot.ll (original)
+++ llvm/branches/exception-handling-rewrite/test/CodeGen/ARM/sxt_rot.ll Wed Jul 27 13:40:48 2011
@@ -1,29 +1,30 @@
-; RUN: llc < %s -march=arm -mattr=+v6 | \
-; RUN: grep sxtb | count 2
-; RUN: llc < %s -march=arm -mattr=+v6 | \
-; RUN: grep sxtb | grep ror | count 1
-; RUN: llc < %s -march=arm -mattr=+v6 | \
-; RUN: grep sxtab | count 1
+; RUN: llc < %s -march=arm -mattr=+v6 | FileCheck %s
define i32 @test0(i8 %A) {
- %B = sext i8 %A to i32
- ret i32 %B
+; CHECK: test0
+; CHECK: sxtb r0, r0
+ %B = sext i8 %A to i32
+ ret i32 %B
}
define signext i8 @test1(i32 %A) {
- %B = lshr i32 %A, 8
- %C = shl i32 %A, 24
- %D = or i32 %B, %C
- %E = trunc i32 %D to i8
- ret i8 %E
+; CHECK: test1
+; CHECK: sxtb r0, r0, ror #8
+ %B = lshr i32 %A, 8
+ %C = shl i32 %A, 24
+ %D = or i32 %B, %C
+ %E = trunc i32 %D to i8
+ ret i8 %E
}
define signext i32 @test2(i32 %A, i32 %X) {
- %B = lshr i32 %A, 8
- %C = shl i32 %A, 24
- %D = or i32 %B, %C
- %E = trunc i32 %D to i8
- %F = sext i8 %E to i32
- %G = add i32 %F, %X
- ret i32 %G
+; CHECK: test2
+; CHECK: sxtab r0, r1, r0
+ %B = lshr i32 %A, 8
+ %C = shl i32 %A, 24
+ %D = or i32 %B, %C
+ %E = trunc i32 %D to i8
+ %F = sext i8 %E to i32
+ %G = add i32 %F, %X
+ ret i32 %G
}
Removed: llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/dg.exp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/dg.exp?rev=136233&view=auto
==============================================================================
--- llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/dg.exp (original)
+++ llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/dg.exp (removed)
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if { [llvm_supports_target X86] } {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
-}
Removed: llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/notvunpcklpd.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/notvunpcklpd.ll?rev=136233&view=auto
==============================================================================
--- llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/notvunpcklpd.ll (original)
+++ llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/notvunpcklpd.ll (removed)
@@ -1,20 +0,0 @@
-; RUN: llc < %s -mattr=+avx | FileCheck %s
-
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define void @try_([2 x <4 x double>]* noalias %incarray, [2 x <4 x double>]* noalias %incarrayb ) {
-entry:
- %incarray1 = alloca [2 x <4 x double>]*, align 8
- %incarrayb1 = alloca [2 x <4 x double>]*, align 8
- %carray = alloca [2 x <4 x double>], align 16
- %r = getelementptr [2 x <4 x double>]* %incarray, i32 0, i32 0
- %rb = getelementptr [2 x <4 x double>]* %incarrayb, i32 0, i32 0
- %r3 = load <4 x double>* %r, align 8
- %r4 = load <4 x double>* %rb, align 8
- %r11 = shufflevector <4 x double> %r3, <4 x double> %r4, <4 x i32> < i32 0, i32 4, i32 1, i32 5 > ; <<4 x double>> [#uses=1]
-; CHECK-NOT: vunpcklpd %ymm
- %r12 = getelementptr [2 x <4 x double>]* %carray, i32 0, i32 1
- store <4 x double> %r11, <4 x double>* %r12, align 4
- ret void
-}
Removed: llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/notvunpcklps.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/notvunpcklps.ll?rev=136233&view=auto
==============================================================================
--- llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/notvunpcklps.ll (original)
+++ llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/notvunpcklps.ll (removed)
@@ -1,20 +0,0 @@
-; RUN: llc < %s -mattr=+avx | FileCheck %s
-
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define void @try_([2 x <8 x float>]* noalias %incarray, [2 x <8 x float>]* noalias %incarrayb ) {
-enmtry:
- %incarray1 = alloca [2 x <8 x float>]*, align 8
- %incarrayb1 = alloca [2 x <8 x float>]*, align 8
- %carray = alloca [2 x <8 x float>], align 16
- %r = getelementptr [2 x <8 x float>]* %incarray, i32 0, i32 0
- %rb = getelementptr [2 x <8 x float>]* %incarrayb, i32 0, i32 0
- %r3 = load <8 x float>* %r, align 8
- %r4 = load <8 x float>* %rb, align 8
- %r8 = shufflevector <8 x float> %r3, <8 x float> %r4, <8 x i32> < i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11 > ; <<8 x float>> [#uses=1]
-; CHECK-NOT: vunpcklps %ymm
- %r9 = getelementptr [2 x <8 x float>]* %carray, i32 0, i32 0
- store <8 x float> %r8, <8 x float>* %r9, align 4
- ret void
-}
Removed: llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/vunpcklpd.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/vunpcklpd.ll?rev=136233&view=auto
==============================================================================
--- llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/vunpcklpd.ll (original)
+++ llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/vunpcklpd.ll (removed)
@@ -1,20 +0,0 @@
-; RUN: llc < %s -mattr=+avx | FileCheck %s
-
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define void @try_([2 x <4 x double>]* noalias %incarray, [2 x <4 x double>]* noalias %incarrayb ) {
-entry:
- %incarray1 = alloca [2 x <4 x double>]*, align 8
- %incarrayb1 = alloca [2 x <4 x double>]*, align 8
- %carray = alloca [2 x <4 x double>], align 16
- %r = getelementptr [2 x <4 x double>]* %incarray, i32 0, i32 0
- %rb = getelementptr [2 x <4 x double>]* %incarrayb, i32 0, i32 0
- %r3 = load <4 x double>* %r, align 8
- %r4 = load <4 x double>* %rb, align 8
- %r11 = shufflevector <4 x double> %r3, <4 x double> %r4, <4 x i32> < i32 0, i32 4, i32 2, i32 6 > ; <<4 x double>> [#uses=1]
-; CHECK: vunpcklpd
- %r12 = getelementptr [2 x <4 x double>]* %carray, i32 0, i32 1
- store <4 x double> %r11, <4 x double>* %r12, align 4
- ret void
-}
Removed: llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/vunpcklps.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/vunpcklps.ll?rev=136233&view=auto
==============================================================================
--- llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/vunpcklps.ll (original)
+++ llvm/branches/exception-handling-rewrite/test/CodeGen/X86/SIMD/vunpcklps.ll (removed)
@@ -1,20 +0,0 @@
-; RUN: llc < %s -mattr=+avx | FileCheck %s
-
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define void @try_([2 x <8 x float>]* noalias %incarray, [2 x <8 x float>]* noalias %incarrayb ) {
-entry:
- %incarray1 = alloca [2 x <8 x float>]*, align 8
- %incarrayb1 = alloca [2 x <8 x float>]*, align 8
- %carray = alloca [2 x <8 x float>], align 16
- %r = getelementptr [2 x <8 x float>]* %incarray, i32 0, i32 0
- %rb = getelementptr [2 x <8 x float>]* %incarrayb, i32 0, i32 0
- %r3 = load <8 x float>* %r, align 8
- %r4 = load <8 x float>* %rb, align 8
- %r11 = shufflevector <8 x float> %r3, <8 x float> %r4, <8 x i32> < i32 0, i32 8, i32 1, i32 9, i32 4, i32 12, i32 5, i32 13 > ; <<8 x float>> [#uses=1]
-; CHECK: vunpcklps
- %r12 = getelementptr [2 x <8 x float>]* %carray, i32 0, i32 1
- store <8 x float> %r11, <8 x float>* %r12, align 4
- ret void
-}
Modified: llvm/branches/exception-handling-rewrite/test/MC/ARM/arm_instructions.s
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/test/MC/ARM/arm_instructions.s?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/test/MC/ARM/arm_instructions.s (original)
+++ llvm/branches/exception-handling-rewrite/test/MC/ARM/arm_instructions.s Wed Jul 27 13:40:48 2011
@@ -86,30 +86,6 @@
@ CHECK: add r1, r2, r3, lsl r4 @ encoding: [0x13,0x14,0x82,0xe0]
add r1, r2, r3, lsl r4
-@ CHECK: strexb r0, r1, [r2] @ encoding: [0x91,0x0f,0xc2,0xe1]
- strexb r0, r1, [r2]
-
-@ CHECK: strexh r0, r1, [r2] @ encoding: [0x91,0x0f,0xe2,0xe1]
- strexh r0, r1, [r2]
-
-@ CHECK: strex r0, r1, [r2] @ encoding: [0x91,0x0f,0x82,0xe1]
- strex r0, r1, [r2]
-
-@ CHECK: strexd r0, r2, r3, [r1] @ encoding: [0x92,0x0f,0xa1,0xe1]
- strexd r0, r2, r3, [r1]
-
-@ CHECK: ldrexb r0, [r0] @ encoding: [0x9f,0x0f,0xd0,0xe1]
- ldrexb r0, [r0]
-
-@ CHECK: ldrexh r0, [r0] @ encoding: [0x9f,0x0f,0xf0,0xe1]
- ldrexh r0, [r0]
-
-@ CHECK: ldrex r0, [r0] @ encoding: [0x9f,0x0f,0x90,0xe1]
- ldrex r0, [r0]
-
-@ CHECK: ldrexd r0, r1, [r0] @ encoding: [0x9f,0x0f,0xb0,0xe1]
- ldrexd r0, r1, [r0]
-
@ CHECK: ssat16 r0, #7, r0 @ encoding: [0x30,0x0f,0xa6,0xe6]
ssat16 r0, #7, r0
Modified: llvm/branches/exception-handling-rewrite/test/MC/ARM/basic-arm-instructions.s
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/test/MC/ARM/basic-arm-instructions.s?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/test/MC/ARM/basic-arm-instructions.s (original)
+++ llvm/branches/exception-handling-rewrite/test/MC/ARM/basic-arm-instructions.s Wed Jul 27 13:40:48 2011
@@ -622,6 +622,21 @@
@------------------------------------------------------------------------------
@ FIXME: LDR*
@------------------------------------------------------------------------------
+
+ at ------------------------------------------------------------------------------
+@ LDREX/LDREXB/LDREXH/LDREXD
+ at ------------------------------------------------------------------------------
+ ldrexb r3, [r4]
+ ldrexh r2, [r5]
+ ldrex r1, [r7]
+ ldrexd r6, r7, [r8]
+
+@ CHECK: ldrexb r3, [r4] @ encoding: [0x9f,0x3f,0xd4,0xe1]
+@ CHECK: ldrexh r2, [r5] @ encoding: [0x9f,0x2f,0xf5,0xe1]
+@ CHECK: ldrex r1, [r7] @ encoding: [0x9f,0x1f,0x97,0xe1]
+@ CHECK: ldrexd r6, r7, [r8] @ encoding: [0x9f,0x6f,0xb8,0xe1]
+
+
@------------------------------------------------------------------------------
@ FIXME: LSL
@------------------------------------------------------------------------------
@@ -1669,25 +1684,121 @@
@ STM*
@------------------------------------------------------------------------------
stm r2, {r1,r3-r6,sp}
- stmia r2, {r1,r3-r6,sp}
- stmib r2, {r1,r3-r6,sp}
- stmda r2, {r1,r3-r6,sp}
- stmdb r2, {r1,r3-r6,sp}
- stmfd r2, {r1,r3-r6,sp}
+ stmia r3, {r1,r3-r6,lr}
+ stmib r4, {r1,r3-r6,sp}
+ stmda r5, {r1,r3-r6,sp}
+ stmdb r6, {r1,r3-r6,r8}
+ stmfd sp, {r1,r3-r6,sp}
@ with update
- stmia r2!, {r1,r3-r6,sp}
- stmib r2!, {r1,r3-r6,sp}
- stmda r2!, {r1,r3-r6,sp}
- stmdb r2!, {r1,r3-r6,sp}
-@ CHECK: stm r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe8]
-@ CHECK: stm r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe8]
-@ CHECK: stmib r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe9]
-@ CHECK: stmda r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x02,0xe8]
-@ CHECK: stmdb r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x02,0xe9]
-@ CHECK: stmdb r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x02,0xe9]
-
-@ CHECK: stm r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xa2,0xe8]
-@ CHECK: stmib r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xa2,0xe9]
-@ CHECK: stmda r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x22,0xe8]
-@ CHECK: stmdb r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x22,0xe9]
+ stm r8!, {r1,r3-r6,sp}
+ stmib r9!, {r1,r3-r6,sp}
+ stmda sp!, {r1,r3-r6}
+ stmdb r0!, {r1,r5,r7,sp}
+
+@ CHECK: stm r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe8]
+@ CHECK: stm r3, {lr, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x40,0x83,0xe8]
+@ CHECK: stmib r4, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x84,0xe9]
+@ CHECK: stmda r5, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x05,0xe8]
+@ CHECK: stmdb r6, {r1, r3, r4, r5, r6, r8} @ encoding: [0x7a,0x01,0x06,0xe9]
+@ CHECK: stmdb sp, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x0d,0xe9]
+
+@ CHECK: stm r8!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xa8,0xe8]
+@ CHECK: stmib r9!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xa9,0xe9]
+@ CHECK: stmda sp!, {r1, r3, r4, r5, r6} @ encoding: [0x7a,0x00,0x2d,0xe8]
+@ CHECK: stmdb r0!, {r1, r5, r7, sp} @ encoding: [0xa2,0x20,0x20,0xe9]
+
+
+ at ------------------------------------------------------------------------------
+@ FIXME:STR*
+ at ------------------------------------------------------------------------------
+ at ------------------------------------------------------------------------------
+@ STREX/STREXB/STREXH/STREXD
+ at ------------------------------------------------------------------------------
+ strexb r1, r3, [r4]
+ strexh r4, r2, [r5]
+ strex r2, r1, [r7]
+ strexd r6, r2, r3, [r8]
+
+@ CHECK: strexb r1, r3, [r4] @ encoding: [0x93,0x1f,0xc4,0xe1]
+@ CHECK: strexh r4, r2, [r5] @ encoding: [0x92,0x4f,0xe5,0xe1]
+@ CHECK: strex r2, r1, [r7] @ encoding: [0x91,0x2f,0x87,0xe1]
+@ CHECK: strexd r6, r2, r3, [r8] @ encoding: [0x92,0x6f,0xa8,0xe1]
+
+
+ at ------------------------------------------------------------------------------
+@ SUB
+ at ------------------------------------------------------------------------------
+ sub r4, r5, #0xf000
+ sub r4, r5, r6
+ sub r4, r5, r6, lsl #5
+ sub r4, r5, r6, lsr #5
+ sub r4, r5, r6, lsr #5
+ sub r4, r5, r6, asr #5
+ sub r4, r5, r6, ror #5
+ sub r6, r7, r8, lsl r9
+ sub r6, r7, r8, lsr r9
+ sub r6, r7, r8, asr r9
+ sub r6, r7, r8, ror r9
+
+ @ destination register is optional
+ sub r5, #0xf000
+ sub r4, r5
+ sub r4, r5, lsl #5
+ sub r4, r5, lsr #5
+ sub r4, r5, lsr #5
+ sub r4, r5, asr #5
+ sub r4, r5, ror #5
+ sub r6, r7, lsl r9
+ sub r6, r7, lsr r9
+ sub r6, r7, asr r9
+ sub r6, r7, ror r9
+
+@ CHECK: sub r4, r5, #61440 @ encoding: [0x0f,0x4a,0x45,0xe2]
+@ CHECK: sub r4, r5, r6 @ encoding: [0x06,0x40,0x45,0xe0]
+@ CHECK: sub r4, r5, r6, lsl #5 @ encoding: [0x86,0x42,0x45,0xe0]
+@ CHECK: sub r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0x45,0xe0]
+@ CHECK: sub r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0x45,0xe0]
+@ CHECK: sub r4, r5, r6, asr #5 @ encoding: [0xc6,0x42,0x45,0xe0]
+@ CHECK: sub r4, r5, r6, ror #5 @ encoding: [0xe6,0x42,0x45,0xe0]
+@ CHECK: sub r6, r7, r8, lsl r9 @ encoding: [0x18,0x69,0x47,0xe0]
+@ CHECK: sub r6, r7, r8, lsr r9 @ encoding: [0x38,0x69,0x47,0xe0]
+@ CHECK: sub r6, r7, r8, asr r9 @ encoding: [0x58,0x69,0x47,0xe0]
+@ CHECK: sub r6, r7, r8, ror r9 @ encoding: [0x78,0x69,0x47,0xe0]
+
+
+@ CHECK: sub r5, r5, #61440 @ encoding: [0x0f,0x5a,0x45,0xe2]
+@ CHECK: sub r4, r4, r5 @ encoding: [0x05,0x40,0x44,0xe0]
+@ CHECK: sub r4, r4, r5, lsl #5 @ encoding: [0x85,0x42,0x44,0xe0]
+@ CHECK: sub r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0x44,0xe0]
+@ CHECK: sub r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0x44,0xe0]
+@ CHECK: sub r4, r4, r5, asr #5 @ encoding: [0xc5,0x42,0x44,0xe0]
+@ CHECK: sub r4, r4, r5, ror #5 @ encoding: [0xe5,0x42,0x44,0xe0]
+@ CHECK: sub r6, r6, r7, lsl r9 @ encoding: [0x17,0x69,0x46,0xe0]
+@ CHECK: sub r6, r6, r7, lsr r9 @ encoding: [0x37,0x69,0x46,0xe0]
+@ CHECK: sub r6, r6, r7, asr r9 @ encoding: [0x57,0x69,0x46,0xe0]
+@ CHECK: sub r6, r6, r7, ror r9 @ encoding: [0x77,0x69,0x46,0xe0]
+
+
+ at ------------------------------------------------------------------------------
+@ SVC
+ at ------------------------------------------------------------------------------
+ svc #16
+ svc #0
+ svc #0xffffff
+
+@ CHECK: svc #16 @ encoding: [0x10,0x00,0x00,0xef]
+@ CHECK: svc #0 @ encoding: [0x00,0x00,0x00,0xef]
+@ CHECK: svc #16777215 @ encoding: [0xff,0xff,0xff,0xef]
+
+
+ at ------------------------------------------------------------------------------
+@ SWP/SWPB
+ at ------------------------------------------------------------------------------
+ swp r1, r2, [r3]
+ swp r4, r4, [r6]
+ swpb r5, r1, [r9]
+
+@ CHECK: swp r1, r2, [r3] @ encoding: [0x92,0x10,0x03,0xe1]
+@ CHECK: swp r4, r4, [r6] @ encoding: [0x94,0x40,0x06,0xe1]
+@ CHECK: swpb r5, r1, [r9] @ encoding: [0x91,0x50,0x49,0xe1]
Modified: llvm/branches/exception-handling-rewrite/test/MC/ARM/diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/test/MC/ARM/diagnostics.s?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/test/MC/ARM/diagnostics.s (original)
+++ llvm/branches/exception-handling-rewrite/test/MC/ARM/diagnostics.s Wed Jul 27 13:40:48 2011
@@ -126,24 +126,24 @@
pkhbt r2, r2, r3, asr #3
pkhtb r2, r2, r3, lsl #3
-@ CHECK: error: immediate value out of range
-@ CHECK: pkhbt r2, r2, r3, lsl #-1
-@ CHECK: ^
-@ CHECK: error: immediate value out of range
-@ CHECK: pkhbt r2, r2, r3, lsl #32
-@ CHECK: ^
-@ CHECK: error: immediate value out of range
-@ CHECK: pkhtb r2, r2, r3, asr #0
-@ CHECK: ^
-@ CHECK: error: immediate value out of range
-@ CHECK: pkhtb r2, r2, r3, asr #33
-@ CHECK: ^
-@ CHECK: error: lsl operand expected.
-@ CHECK: pkhbt r2, r2, r3, asr #3
-@ CHECK: ^
-@ CHECK: error: asr operand expected.
-@ CHECK: pkhtb r2, r2, r3, lsl #3
-@ CHECK: ^
+@ CHECK-ERRORS: error: immediate value out of range
+@ CHECK-ERRORS: pkhbt r2, r2, r3, lsl #-1
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: immediate value out of range
+@ CHECK-ERRORS: pkhbt r2, r2, r3, lsl #32
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: immediate value out of range
+@ CHECK-ERRORS: pkhtb r2, r2, r3, asr #0
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: immediate value out of range
+@ CHECK-ERRORS: pkhtb r2, r2, r3, asr #33
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: lsl operand expected.
+@ CHECK-ERRORS: pkhbt r2, r2, r3, asr #3
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: asr operand expected.
+@ CHECK-ERRORS: pkhtb r2, r2, r3, lsl #3
+@ CHECK-ERRORS: ^
@ bad values for SETEND
@@ -151,15 +151,15 @@
setend me
setend 1
-@ CHECK: error: instruction 'setend' is not predicable, but condition code specified
-@ CHECK: setendne be
-@ CHECK: ^
-@ CHECK: error: 'be' or 'le' operand expected
-@ CHECK: setend me
-@ CHECK: ^
-@ CHECK: error: 'be' or 'le' operand expected
-@ CHECK: setend 1
-@ CHECK: ^
+@ CHECK-ERRORS: error: instruction 'setend' is not predicable, but condition code specified
+@ CHECK-ERRORS: setendne be
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'be' or 'le' operand expected
+@ CHECK-ERRORS: setend me
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'be' or 'le' operand expected
+@ CHECK-ERRORS: setend 1
+@ CHECK-ERRORS: ^
@ Out of range immediates and bad shift types for SSAT
@@ -173,41 +173,68 @@
ssat r8, #1, r10, lsl fred
ssat r8, #1, r10, lsl #fred
-@ CHECK: error: invalid operand for instruction
-@ CHECK: ssat r8, #0, r10, lsl #8
-@ CHECK: ^
-@ CHECK: error: invalid operand for instruction
-@ CHECK: ssat r8, #33, r10, lsl #8
-@ CHECK: ^
-@ CHECK: error: 'lsr' shift amount must be in range [0,31]
-@ CHECK: ssat r8, #1, r10, lsl #-1
-@ CHECK: ^
-@ CHECK: error: 'lsr' shift amount must be in range [0,31]
-@ CHECK: ssat r8, #1, r10, lsl #32
-@ CHECK: ^
-@ CHECK: error: 'asr' shift amount must be in range [1,32]
-@ CHECK: ssat r8, #1, r10, asr #0
-@ CHECK: ^
-@ CHECK: error: 'asr' shift amount must be in range [1,32]
-@ CHECK: ssat r8, #1, r10, asr #33
-@ CHECK: ^
-@ CHECK: error: shift operator 'asr' or 'lsl' expected
-@ CHECK: ssat r8, #1, r10, lsr #5
-@ CHECK: ^
-@ CHECK: error: '#' expected
-@ CHECK: ssat r8, #1, r10, lsl fred
-@ CHECK: ^
-@ CHECK: error: shift amount must be an immediate
-@ CHECK: ssat r8, #1, r10, lsl #fred
-@ CHECK: ^
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: ssat r8, #0, r10, lsl #8
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: ssat r8, #33, r10, lsl #8
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'lsr' shift amount must be in range [0,31]
+@ CHECK-ERRORS: ssat r8, #1, r10, lsl #-1
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'lsr' shift amount must be in range [0,31]
+@ CHECK-ERRORS: ssat r8, #1, r10, lsl #32
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'asr' shift amount must be in range [1,32]
+@ CHECK-ERRORS: ssat r8, #1, r10, asr #0
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'asr' shift amount must be in range [1,32]
+@ CHECK-ERRORS: ssat r8, #1, r10, asr #33
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: shift operator 'asr' or 'lsl' expected
+@ CHECK-ERRORS: ssat r8, #1, r10, lsr #5
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: '#' expected
+@ CHECK-ERRORS: ssat r8, #1, r10, lsl fred
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: shift amount must be an immediate
+@ CHECK-ERRORS: ssat r8, #1, r10, lsl #fred
+@ CHECK-ERRORS: ^
@ Out of range immediates for SSAT16
ssat16 r2, #0, r7
ssat16 r3, #17, r5
-@ CHECK: error: invalid operand for instruction
-@ CHECK: ssat16 r2, #0, r7
-@ CHECK: ^
-@ CHECK: error: invalid operand for instruction
-@ CHECK: ssat16 r3, #17, r5
-@ CHECK: ^
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: ssat16 r2, #0, r7
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: ssat16 r3, #17, r5
+@ CHECK-ERRORS: ^
+
+
+ @ Out of order STM registers
+ stmda sp!, {r5, r2}
+
+@ CHECK-ERRORS: warning: register not in ascending order in register list
+@ CHECK-ERRORS: stmda sp!, {r5, r2}
+@ CHECK-ERRORS: ^
+
+
+ @ Out of range immediate on SVC
+ svc #0x1000000
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: svc #0x1000000
+@ CHECK-ERRORS: ^
+
+
+ @ Out of order Rt/Rt2 operands for ldrexd/strexd
+ ldrexd r4, r3, [r8]
+ strexd r6, r5, r3, [r8]
+
+@ CHECK-ERRORS: error: destination operands must be sequential
+@ CHECK-ERRORS: ldrexd r4, r3, [r8]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: source operands must be sequential
+@ CHECK-ERRORS: strexd r6, r5, r3, [r8]
+@ CHECK-ERRORS: ^
Modified: llvm/branches/exception-handling-rewrite/tools/gold/gold-plugin.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/tools/gold/gold-plugin.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/tools/gold/gold-plugin.cpp (original)
+++ llvm/branches/exception-handling-rewrite/tools/gold/gold-plugin.cpp Wed Jul 27 13:40:48 2011
@@ -360,6 +360,8 @@
bool anySymbolsPreserved = false;
for (std::list<claimed_file>::iterator I = Modules.begin(),
E = Modules.end(); I != E; ++I) {
+ if (I->syms.empty())
+ continue;
(*get_symbols)(I->handle, I->syms.size(), &I->syms[0]);
for (unsigned i = 0, e = I->syms.size(); i != e; i++) {
if (I->syms[i].resolution == LDPR_PREVAILING_DEF) {
Modified: llvm/branches/exception-handling-rewrite/tools/llvm-mc/llvm-mc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/tools/llvm-mc/llvm-mc.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/tools/llvm-mc/llvm-mc.cpp (original)
+++ llvm/branches/exception-handling-rewrite/tools/llvm-mc/llvm-mc.cpp Wed Jul 27 13:40:48 2011
@@ -170,21 +170,42 @@
// Figure out the target triple.
if (TripleName.empty())
TripleName = sys::getHostTriple();
+ Triple TheTriple(Triple::normalize(TripleName));
+
+ const Target *TheTarget = 0;
if (!ArchName.empty()) {
- llvm::Triple TT(TripleName);
- TT.setArchName(ArchName);
- TripleName = TT.str();
- }
+ for (TargetRegistry::iterator it = TargetRegistry::begin(),
+ ie = TargetRegistry::end(); it != ie; ++it) {
+ if (ArchName == it->getName()) {
+ TheTarget = &*it;
+ break;
+ }
+ }
- // Get the target specific parser.
- std::string Error;
- const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
- if (TheTarget)
- return TheTarget;
+ if (!TheTarget) {
+ errs() << ProgName << ": error: invalid target '" << ArchName << "'.\n";
+ return 0;
+ }
- errs() << ProgName << ": error: unable to get target for '" << TripleName
- << "', see --version and --triple.\n";
- return 0;
+ // Adjust the triple to match (if known), otherwise stick with the
+ // module/host triple.
+ Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
+ if (Type != Triple::UnknownArch)
+ TheTriple.setArch(Type);
+ } else {
+ // Get the target specific parser.
+ std::string Error;
+ TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
+ if (TheTarget == 0) {
+ errs() << ProgName << ": error: unable to get target for '"
+ << TheTriple.getTriple()
+ << "', see --version and --triple.\n";
+ return 0;
+ }
+ }
+
+ TripleName = TheTriple.getTriple();
+ return TheTarget;
}
static tool_output_file *GetOutputStream() {
Modified: llvm/branches/exception-handling-rewrite/unittests/ADT/DAGDeltaAlgorithmTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/unittests/ADT/DAGDeltaAlgorithmTest.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/unittests/ADT/DAGDeltaAlgorithmTest.cpp (original)
+++ llvm/branches/exception-handling-rewrite/unittests/ADT/DAGDeltaAlgorithmTest.cpp Wed Jul 27 13:40:48 2011
@@ -13,23 +13,6 @@
#include <cstdarg>
using namespace llvm;
-namespace std {
-
-static std::ostream &operator<<(std::ostream &OS,
- const std::set<unsigned> &S) {
- OS << "{";
- for (std::set<unsigned>::const_iterator it = S.begin(),
- ie = S.end(); it != ie; ++it) {
- if (it != S.begin())
- OS << ",";
- OS << *it;
- }
- OS << "}";
- return OS;
-}
-
-}
-
namespace {
typedef DAGDeltaAlgorithm::edge_ty edge_ty;
Modified: llvm/branches/exception-handling-rewrite/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp (original)
+++ llvm/branches/exception-handling-rewrite/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp Wed Jul 27 13:40:48 2011
@@ -45,7 +45,7 @@
std::vector<FunctionEmittedEvent> EmittedEvents;
std::vector<FunctionFreedEvent> FreedEvents;
- int NextIndex;
+ unsigned NextIndex;
RecordingJITEventListener() : NextIndex(0) {}
Modified: llvm/branches/exception-handling-rewrite/utils/TableGen/EDEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/TableGen/EDEmitter.cpp?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/TableGen/EDEmitter.cpp (original)
+++ llvm/branches/exception-handling-rewrite/utils/TableGen/EDEmitter.cpp Wed Jul 27 13:40:48 2011
@@ -596,6 +596,7 @@
IMM("imm0_4095");
IMM("imm0_65535");
IMM("imm0_65535_expr");
+ IMM("imm24b");
IMM("pkh_lsl_amt");
IMM("pkh_asr_amt");
IMM("jt2block_operand");
@@ -638,7 +639,8 @@
MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I
MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I
MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I
- MISC("am2offset", "kOperandTypeARMAddrMode2Offset"); // R, I
+ MISC("am2offset_reg", "kOperandTypeARMAddrMode2Offset"); // R, I
+ MISC("am2offset_imm", "kOperandTypeARMAddrMode2Offset"); // R, I
MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I
MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I
MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/CMakeLists.txt?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/CMakeLists.txt (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/CMakeLists.txt Wed Jul 27 13:40:48 2011
@@ -32,6 +32,7 @@
googletest/gtest-death-test.cc
googletest/gtest-filepath.cc
googletest/gtest-port.cc
+ googletest/gtest-printers.cc
googletest/gtest-test-part.cc
googletest/gtest-typed-test.cc
)
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/README.LLVM
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/README.LLVM?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/README.LLVM (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/README.LLVM Wed Jul 27 13:40:48 2011
@@ -1,14 +1,14 @@
LLVM notes
----------
-This directory contains Google Test 1.5.0, with all elements removed except for
+This directory contains Google Test 1.6.0, with all elements removed except for
the actual source code, to minimize the addition to the LLVM distribution.
Cleaned up as follows:
# Remove all the unnecessary files and directories
$ rm -f aclocal* CMakeLists.txt configure* Makefile* CHANGES CONTRIBUTORS README
-$ rm -rf build-aux codegear fused-src m4 make msvc samples scripts test xcode
+$ rm -rf build-aux cmake codegear fused-src m4 make msvc samples scripts test xcode
$ rm -f `find . -name \*\.pump`
# Move all the source files to the current directory
@@ -21,6 +21,8 @@
# Update paths to the included files
$ perl -pi -e 's|^#include "src/|#include "gtest/internal/|' *.cc
+$ rm -f gtest-all.cc gtest_main.cc
+
$ mv COPYING LICENSE.TXT
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-death-test.cc
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-death-test.cc?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-death-test.cc (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-death-test.cc Wed Jul 27 13:40:48 2011
@@ -31,31 +31,31 @@
//
// This file implements death tests.
-#include <gtest/gtest-death-test.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/gtest-death-test.h"
+#include "gtest/internal/gtest-port.h"
#if GTEST_HAS_DEATH_TEST
-#if GTEST_OS_MAC
-#include <crt_externs.h>
-#endif // GTEST_OS_MAC
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-
-#if GTEST_OS_WINDOWS
-#include <windows.h>
-#else
-#include <sys/mman.h>
-#include <sys/wait.h>
-#endif // GTEST_OS_WINDOWS
+# if GTEST_OS_MAC
+# include <crt_externs.h>
+# endif // GTEST_OS_MAC
+
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+# include <stdarg.h>
+
+# if GTEST_OS_WINDOWS
+# include <windows.h>
+# else
+# include <sys/mman.h>
+# include <sys/wait.h>
+# endif // GTEST_OS_WINDOWS
#endif // GTEST_HAS_DEATH_TEST
-#include <gtest/gtest-message.h>
-#include <gtest/internal/gtest-string.h>
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
@@ -113,14 +113,18 @@
// ExitedWithCode function-call operator.
bool ExitedWithCode::operator()(int exit_status) const {
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+
return exit_status == exit_code_;
-#else
+
+# else
+
return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
-#endif // GTEST_OS_WINDOWS
+
+# endif // GTEST_OS_WINDOWS
}
-#if !GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS
// KilledBySignal constructor.
KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
}
@@ -129,7 +133,7 @@
bool KilledBySignal::operator()(int exit_status) const {
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
}
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
namespace internal {
@@ -139,20 +143,25 @@
// specified by wait(2).
static String ExitSummary(int exit_code) {
Message m;
-#if GTEST_OS_WINDOWS
+
+# if GTEST_OS_WINDOWS
+
m << "Exited with exit status " << exit_code;
-#else
+
+# else
+
if (WIFEXITED(exit_code)) {
m << "Exited with exit status " << WEXITSTATUS(exit_code);
} else if (WIFSIGNALED(exit_code)) {
m << "Terminated by signal " << WTERMSIG(exit_code);
}
-#ifdef WCOREDUMP
+# ifdef WCOREDUMP
if (WCOREDUMP(exit_code)) {
m << " (core dumped)";
}
-#endif
-#endif // GTEST_OS_WINDOWS
+# endif
+# endif // GTEST_OS_WINDOWS
+
return m.GetString();
}
@@ -162,7 +171,7 @@
return !ExitedWithCode(0)(exit_status);
}
-#if !GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS
// Generates a textual failure message when a death test finds more than
// one thread running, or cannot determine the number of threads, prior
// to executing the given statement. It is the responsibility of the
@@ -177,20 +186,24 @@
msg << "detected " << thread_count << " threads.";
return msg.GetString();
}
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
// Flag characters for reporting a death test that did not die.
static const char kDeathTestLived = 'L';
static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
static const char kDeathTestInternalError = 'I';
-// An enumeration describing all of the possible ways that a death test
-// can conclude. DIED means that the process died while executing the
-// test code; LIVED means that process lived beyond the end of the test
-// code; and RETURNED means that the test statement attempted a "return,"
-// which is not allowed. IN_PROGRESS means the test has not yet
-// concluded.
-enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED };
+// An enumeration describing all of the possible ways that a death test can
+// conclude. DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception. IN_PROGRESS means the test
+// has not yet concluded.
+// TODO(vladl at google.com): Unify names and possibly values for
+// AbortReason, DeathTestOutcome, and flag characters above.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
// Routine for aborting the program which is safe to call from an
// exec-style death test child process, in which case the error
@@ -212,13 +225,13 @@
} else {
fprintf(stderr, "%s", message.c_str());
fflush(stderr);
- abort();
+ posix::Abort();
}
}
// A replacement for CHECK that calls DeathTestAbort if the assertion
// fails.
-#define GTEST_DEATH_TEST_CHECK_(expression) \
+# define GTEST_DEATH_TEST_CHECK_(expression) \
do { \
if (!::testing::internal::IsTrue(expression)) { \
DeathTestAbort(::testing::internal::String::Format( \
@@ -234,7 +247,7 @@
// evaluates the expression as long as it evaluates to -1 and sets
// errno to EINTR. If the expression evaluates to -1 but errno is
// something other than EINTR, DeathTestAbort is called.
-#define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
do { \
int gtest_retval; \
do { \
@@ -388,6 +401,9 @@
case kDeathTestReturned:
set_outcome(RETURNED);
break;
+ case kDeathTestThrew:
+ set_outcome(THREW);
+ break;
case kDeathTestLived:
set_outcome(LIVED);
break;
@@ -416,19 +432,46 @@
// it finds any data in our pipe. So, here we write a single flag byte
// to the pipe, then exit.
const char status_ch =
- reason == TEST_DID_NOT_DIE ? kDeathTestLived : kDeathTestReturned;
+ reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+ reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
- GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(write_fd()));
+ // We are leaking the descriptor here because on some platforms (i.e.,
+ // when built as Windows DLL), destructors of global objects will still
+ // run after calling _exit(). On such systems, write_fd_ will be
+ // indirectly closed from the destructor of UnitTestImpl, causing double
+ // close if it is also closed here. On debug configurations, double close
+ // may assert. As there are no in-process buffers to flush here, we are
+ // relying on the OS to close the descriptor after the process terminates
+ // when the destructors are not run.
_exit(1); // Exits w/o any normal exit hooks (we were supposed to crash)
}
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+ ::std::string ret;
+ for (size_t at = 0; ; ) {
+ const size_t line_end = output.find('\n', at);
+ ret += "[ DEATH ] ";
+ if (line_end == ::std::string::npos) {
+ ret += output.substr(at);
+ break;
+ }
+ ret += output.substr(at, line_end + 1 - at);
+ at = line_end + 1;
+ }
+ return ret;
+}
+
// Assesses the success or failure of a death test, using both private
// members which have previously been set, and one argument:
//
// Private data members:
// outcome: An enumeration describing how the death test
-// concluded: DIED, LIVED, or RETURNED. The death test fails
-// in the latter two cases.
+// concluded: DIED, LIVED, THREW, or RETURNED. The death test
+// fails in the latter three cases.
// status: The exit status of the child process. On *nix, it is in the
// in the format specified by wait(2). On Windows, this is the
// value supplied to the ExitProcess() API or a numeric code
@@ -457,11 +500,15 @@
switch (outcome()) {
case LIVED:
buffer << " Result: failed to die.\n"
- << " Error msg: " << error_message;
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
+ break;
+ case THREW:
+ buffer << " Result: threw an exception.\n"
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
break;
case RETURNED:
buffer << " Result: illegal return in test statement.\n"
- << " Error msg: " << error_message;
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
break;
case DIED:
if (status_ok) {
@@ -471,11 +518,12 @@
} else {
buffer << " Result: died but not with expected error.\n"
<< " Expected: " << regex()->pattern() << "\n"
- << "Actual msg: " << error_message;
+ << "Actual msg:\n" << FormatDeathTestOutput(error_message);
}
} else {
buffer << " Result: died but not with expected exit code:\n"
- << " " << ExitSummary(status()) << "\n";
+ << " " << ExitSummary(status()) << "\n"
+ << "Actual msg:\n" << FormatDeathTestOutput(error_message);
}
break;
case IN_PROGRESS:
@@ -488,7 +536,7 @@
return success;
}
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
// WindowsDeathTest implements death tests on Windows. Due to the
// specifics of starting new processes on Windows, death tests there are
// always threadsafe, and Google Test considers the
@@ -519,11 +567,11 @@
//
class WindowsDeathTest : public DeathTestImpl {
public:
- WindowsDeathTest(const char* statement,
- const RE* regex,
+ WindowsDeathTest(const char* a_statement,
+ const RE* a_regex,
const char* file,
int line)
- : DeathTestImpl(statement, regex), file_(file), line_(line) {}
+ : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
// All of these virtual functions are inherited from DeathTest.
virtual int Wait();
@@ -580,12 +628,12 @@
GTEST_DEATH_TEST_CHECK_(
WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
INFINITE));
- DWORD status;
- GTEST_DEATH_TEST_CHECK_(::GetExitCodeProcess(child_handle_.Get(), &status)
- != FALSE);
+ DWORD status_code;
+ GTEST_DEATH_TEST_CHECK_(
+ ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
child_handle_.Reset();
- set_status(static_cast<int>(status));
- return this->status();
+ set_status(static_cast<int>(status_code));
+ return status();
}
// The AssumeRole process for a Windows death test. It creates a child
@@ -684,7 +732,7 @@
set_spawned(true);
return OVERSEE_TEST;
}
-#else // We are not on Windows.
+# else // We are not on Windows.
// ForkingDeathTest provides implementations for most of the abstract
// methods of the DeathTest interface. Only the AssumeRole method is
@@ -832,19 +880,19 @@
int close_fd; // File descriptor to close; the read end of a pipe
};
-#if GTEST_OS_MAC
+# if GTEST_OS_MAC
inline char** GetEnviron() {
// When Google Test is built as a framework on MacOS X, the environ variable
// is unavailable. Apple's documentation (man environ) recommends using
// _NSGetEnviron() instead.
return *_NSGetEnviron();
}
-#else
+# else
// Some POSIX platforms expect you to declare environ. extern "C" makes
// it reside in the global namespace.
extern "C" char** environ;
inline char** GetEnviron() { return environ; }
-#endif // GTEST_OS_MAC
+# endif // GTEST_OS_MAC
// The main function for a threadsafe-style death test child process.
// This function is called in a clone()-ed process and thus must avoid
@@ -884,6 +932,11 @@
// This could be accomplished more elegantly by a single recursive
// function, but we want to guard against the unlikely possibility of
// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+bool StackLowerThanAddress(const void* ptr) GTEST_NO_INLINE_;
bool StackLowerThanAddress(const void* ptr) {
int dummy;
return &dummy < ptr;
@@ -901,7 +954,7 @@
ExecDeathTestArgs args = { argv, close_fd };
pid_t child_pid = -1;
-#if GTEST_HAS_CLONE
+# if GTEST_HAS_CLONE
const bool use_fork = GTEST_FLAG(death_test_use_fork);
if (!use_fork) {
@@ -918,9 +971,9 @@
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
}
-#else
+# else
const bool use_fork = true;
-#endif // GTEST_HAS_CLONE
+# endif // GTEST_HAS_CLONE
if (use_fork && (child_pid = fork()) == 0) {
ExecDeathTestChildMain(&args);
@@ -981,7 +1034,7 @@
return OVERSEE_TEST;
}
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
// Creates a concrete DeathTest-derived class that depends on the
// --gtest_death_test_style flag, and sets the pointer pointed to
@@ -1012,18 +1065,23 @@
}
}
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
GTEST_FLAG(death_test_style) == "fast") {
*test = new WindowsDeathTest(statement, regex, file, line);
}
-#else
+
+# else
+
if (GTEST_FLAG(death_test_style) == "threadsafe") {
*test = new ExecDeathTest(statement, regex, file, line);
} else if (GTEST_FLAG(death_test_style) == "fast") {
*test = new NoExecDeathTest(statement, regex);
}
-#endif // GTEST_OS_WINDOWS
+
+# endif // GTEST_OS_WINDOWS
+
else { // NOLINT - this is more readable than unbalanced brackets inside #if.
DeathTest::set_last_death_test_message(String::Format(
"Unknown death test style \"%s\" encountered",
@@ -1054,7 +1112,7 @@
dest->swap(parsed);
}
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
// Recreates the pipe and event handles from the provided parameters,
// signals the event, and returns a file descriptor wrapped around the pipe
// handle. This function is called in the child process only.
@@ -1118,7 +1176,7 @@
return write_fd;
}
-#endif // GTEST_OS_WINDOWS
+# endif // GTEST_OS_WINDOWS
// Returns a newly created InternalRunDeathTestFlag object with fields
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
@@ -1134,7 +1192,8 @@
SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
int write_fd = -1;
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+
unsigned int parent_process_id = 0;
size_t write_handle_as_size_t = 0;
size_t event_handle_as_size_t = 0;
@@ -1152,7 +1211,8 @@
write_fd = GetStatusFileDescriptor(parent_process_id,
write_handle_as_size_t,
event_handle_as_size_t);
-#else
+# else
+
if (fields.size() != 4
|| !ParseNaturalNumber(fields[1], &line)
|| !ParseNaturalNumber(fields[2], &index)
@@ -1161,7 +1221,9 @@
"Bad --gtest_internal_run_death_test flag: %s",
GTEST_FLAG(internal_run_death_test).c_str()));
}
-#endif // GTEST_OS_WINDOWS
+
+# endif // GTEST_OS_WINDOWS
+
return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
}
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-filepath.cc
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-filepath.cc?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-filepath.cc (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-filepath.cc Wed Jul 27 13:40:48 2011
@@ -29,35 +29,35 @@
//
// Authors: keith.ray at gmail.com (Keith Ray)
-#include <gtest/internal/gtest-filepath.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-port.h"
#include <stdlib.h>
#if GTEST_OS_WINDOWS_MOBILE
-#include <windows.h>
+# include <windows.h>
#elif GTEST_OS_WINDOWS
-#include <direct.h>
-#include <io.h>
-#elif GTEST_OS_SYMBIAN
-// Symbian OpenC has PATH_MAX in sys/syslimits.h
-#include <sys/syslimits.h>
+# include <direct.h>
+# include <io.h>
+#elif GTEST_OS_SYMBIAN || GTEST_OS_NACL
+// Symbian OpenC and NaCl have PATH_MAX in sys/syslimits.h
+# include <sys/syslimits.h>
#else
-#include <limits.h>
-#include <climits> // Some Linux distributions define PATH_MAX here.
+# include <limits.h>
+# include <climits> // Some Linux distributions define PATH_MAX here.
#endif // GTEST_OS_WINDOWS_MOBILE
#if GTEST_OS_WINDOWS
-#define GTEST_PATH_MAX_ _MAX_PATH
+# define GTEST_PATH_MAX_ _MAX_PATH
#elif defined(PATH_MAX)
-#define GTEST_PATH_MAX_ PATH_MAX
+# define GTEST_PATH_MAX_ PATH_MAX
#elif defined(_XOPEN_PATH_MAX)
-#define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
#else
-#define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
#endif // GTEST_OS_WINDOWS
-#include <gtest/internal/gtest-string.h>
+#include "gtest/internal/gtest-string.h"
namespace testing {
namespace internal {
@@ -71,16 +71,16 @@
const char kAlternatePathSeparator = '/';
const char kPathSeparatorString[] = "\\";
const char kAlternatePathSeparatorString[] = "/";
-#if GTEST_OS_WINDOWS_MOBILE
+# if GTEST_OS_WINDOWS_MOBILE
// Windows CE doesn't have a current directory. You should not use
// the current directory in tests on Windows CE, but this at least
// provides a reasonable fallback.
const char kCurrentDirectoryString[] = "\\";
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
const DWORD kInvalidFileAttributes = 0xffffffff;
-#else
+# else
const char kCurrentDirectoryString[] = ".\\";
-#endif // GTEST_OS_WINDOWS_MOBILE
+# endif // GTEST_OS_WINDOWS_MOBILE
#else
const char kPathSeparator = '/';
const char kPathSeparatorString[] = "/";
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-port.cc
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-port.cc?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-port.cc (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-port.cc Wed Jul 27 13:40:48 2011
@@ -29,30 +29,32 @@
//
// Author: wan at google.com (Zhanyong Wan)
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#if GTEST_OS_WINDOWS_MOBILE
-#include <windows.h> // For TerminateProcess()
+# include <windows.h> // For TerminateProcess()
#elif GTEST_OS_WINDOWS
-#include <io.h>
-#include <sys/stat.h>
+# include <io.h>
+# include <sys/stat.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif // GTEST_OS_WINDOWS_MOBILE
#if GTEST_OS_MAC
-#include <mach/mach_init.h>
-#include <mach/task.h>
-#include <mach/vm_map.h>
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
#endif // GTEST_OS_MAC
-#include <gtest/gtest-spi.h>
-#include <gtest/gtest-message.h>
-#include <gtest/internal/gtest-string.h>
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
@@ -180,20 +182,20 @@
// Returns true iff ch belongs to the given classification. Unlike
// similar functions in <ctype.h>, these aren't affected by the
// current locale.
-bool IsDigit(char ch) { return '0' <= ch && ch <= '9'; }
-bool IsPunct(char ch) {
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
}
bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
-bool IsWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
-bool IsWordChar(char ch) {
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
('0' <= ch && ch <= '9') || ch == '_';
}
// Returns true iff "\\c" is a supported escape sequence.
bool IsValidEscape(char c) {
- return (IsPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+ return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
}
// Returns true iff the given atom (specified by escaped and pattern)
@@ -201,19 +203,19 @@
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
if (escaped) { // "\\p" where p is pattern_char.
switch (pattern_char) {
- case 'd': return IsDigit(ch);
- case 'D': return !IsDigit(ch);
+ case 'd': return IsAsciiDigit(ch);
+ case 'D': return !IsAsciiDigit(ch);
case 'f': return ch == '\f';
case 'n': return ch == '\n';
case 'r': return ch == '\r';
- case 's': return IsWhiteSpace(ch);
- case 'S': return !IsWhiteSpace(ch);
+ case 's': return IsAsciiWhiteSpace(ch);
+ case 'S': return !IsAsciiWhiteSpace(ch);
case 't': return ch == '\t';
case 'v': return ch == '\v';
- case 'w': return IsWordChar(ch);
- case 'W': return !IsWordChar(ch);
+ case 'w': return IsAsciiWordChar(ch);
+ case 'W': return !IsAsciiWordChar(ch);
}
- return IsPunct(pattern_char) && pattern_char == ch;
+ return IsAsciiPunct(pattern_char) && pattern_char == ch;
}
return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
@@ -422,6 +424,38 @@
#endif // GTEST_USES_POSIX_RE
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+ const char* const file_name = file == NULL ? kUnknownFile : file;
+
+ if (line < 0) {
+ return String::Format("%s:", file_name).c_str();
+ }
+#ifdef _MSC_VER
+ return String::Format("%s(%d):", file_name, line).c_str();
+#else
+ return String::Format("%s:%d:", file_name, line).c_str();
+#endif // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+ const char* file, int line) {
+ const char* const file_name = file == NULL ? kUnknownFile : file;
+
+ if (line < 0)
+ return file_name;
+ else
+ return String::Format("%s:%d", file_name, line).c_str();
+}
+
GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
: severity_(severity) {
@@ -444,18 +478,19 @@
// Disable Microsoft deprecation warnings for POSIX functions called from
// this class (creat, dup, dup2, and close)
#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable: 4996)
+# pragma warning(push)
+# pragma warning(disable: 4996)
#endif // _MSC_VER
-#if GTEST_HAS_STREAM_REDIRECTION_
+#if GTEST_HAS_STREAM_REDIRECTION
// Object that captures an output stream (stdout/stderr).
class CapturedStream {
public:
// The ctor redirects the stream to a temporary file.
CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
-#if GTEST_OS_WINDOWS
+
+# if GTEST_OS_WINDOWS
char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
@@ -470,14 +505,14 @@
GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
<< temp_file_path;
filename_ = temp_file_path;
-#else
+# else
// There's no guarantee that a test has write access to the
// current directory, so we create the temporary file in the /tmp
// directory instead.
char name_template[] = "/tmp/captured_stream.XXXXXX";
const int captured_fd = mkstemp(name_template);
filename_ = name_template;
-#endif // GTEST_OS_WINDOWS
+# endif // GTEST_OS_WINDOWS
fflush(NULL);
dup2(captured_fd, fd_);
close(captured_fd);
@@ -546,9 +581,9 @@
return content;
}
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif // _MSC_VER
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif // _MSC_VER
static CapturedStream* g_captured_stderr = NULL;
static CapturedStream* g_captured_stdout = NULL;
@@ -588,7 +623,7 @@
// Stops capturing stderr and returns the captured string.
String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
-#endif // GTEST_HAS_STREAM_REDIRECTION_
+#endif // GTEST_HAS_STREAM_REDIRECTION
#if GTEST_HAS_DEATH_TEST
@@ -618,7 +653,7 @@
Message env_var;
for (size_t i = 0; i != full_flag.length(); i++) {
- env_var << static_cast<char>(toupper(full_flag.c_str()[i]));
+ env_var << ToUpper(full_flag.c_str()[i]);
}
return env_var.GetString();
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-test-part.cc
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-test-part.cc?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-test-part.cc (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-test-part.cc Wed Jul 27 13:40:48 2011
@@ -31,7 +31,7 @@
//
// The Google C++ Testing Framework (Google Test)
-#include <gtest/gtest-test-part.h>
+#include "gtest/gtest-test-part.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-typed-test.cc
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-typed-test.cc?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-typed-test.cc (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest-typed-test.cc Wed Jul 27 13:40:48 2011
@@ -29,8 +29,8 @@
//
// Author: wan at google.com (Zhanyong Wan)
-#include <gtest/gtest-typed-test.h>
-#include <gtest/gtest.h>
+#include "gtest/gtest-typed-test.h"
+#include "gtest/gtest.h"
namespace testing {
namespace internal {
@@ -40,7 +40,7 @@
// Skips to the first non-space char in str. Returns an empty string if str
// contains only whitespace characters.
static const char* SkipSpaces(const char* str) {
- while (isspace(*str))
+ while (IsSpace(*str))
str++;
return str;
}
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest.cc
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest.cc?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest.cc (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/gtest.cc Wed Jul 27 13:40:48 2011
@@ -31,8 +31,8 @@
//
// The Google C++ Testing Framework (Google Test)
-#include <gtest/gtest.h>
-#include <gtest/gtest-spi.h>
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
#include <ctype.h>
#include <math.h>
@@ -43,7 +43,7 @@
#include <wctype.h>
#include <algorithm>
-#include <ostream>
+#include <ostream> // NOLINT
#include <sstream>
#include <vector>
@@ -51,72 +51,76 @@
// TODO(kenton at google.com): Use autoconf to detect availability of
// gettimeofday().
-#define GTEST_HAS_GETTIMEOFDAY_ 1
+# define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <fcntl.h>
-#include <limits.h>
-#include <sched.h>
+# include <fcntl.h> // NOLINT
+# include <limits.h> // NOLINT
+# include <sched.h> // NOLINT
// Declares vsnprintf(). This header is not available on Windows.
-#include <strings.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <string>
-#include <vector>
+# include <strings.h> // NOLINT
+# include <sys/mman.h> // NOLINT
+# include <sys/time.h> // NOLINT
+# include <unistd.h> // NOLINT
+# include <string>
#elif GTEST_OS_SYMBIAN
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
#elif GTEST_OS_ZOS
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
// On z/OS we additionally need strings.h for strcasecmp.
-#include <strings.h> // NOLINT
+# include <strings.h> // NOLINT
#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE.
-#include <windows.h> // NOLINT
+# include <windows.h> // NOLINT
#elif GTEST_OS_WINDOWS // We are on Windows proper.
-#include <io.h> // NOLINT
-#include <sys/timeb.h> // NOLINT
-#include <sys/types.h> // NOLINT
-#include <sys/stat.h> // NOLINT
+# include <io.h> // NOLINT
+# include <sys/timeb.h> // NOLINT
+# include <sys/types.h> // NOLINT
+# include <sys/stat.h> // NOLINT
-#if GTEST_OS_WINDOWS_MINGW
+# if GTEST_OS_WINDOWS_MINGW
// MinGW has gettimeofday() but not _ftime64().
// TODO(kenton at google.com): Use autoconf to detect availability of
// gettimeofday().
// TODO(kenton at google.com): There are other ways to get the time on
// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW
// supports these. consider using them instead.
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
-#endif // GTEST_OS_WINDOWS_MINGW
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
+# endif // GTEST_OS_WINDOWS_MINGW
// cpplint thinks that the header is already included, so we want to
// silence it.
-#include <windows.h> // NOLINT
+# include <windows.h> // NOLINT
#else
// Assume other platforms have gettimeofday().
// TODO(kenton at google.com): Use autoconf to detect availability of
// gettimeofday().
-#define GTEST_HAS_GETTIMEOFDAY_ 1
+# define GTEST_HAS_GETTIMEOFDAY_ 1
// cpplint thinks that the header is already included, so we want to
// silence it.
-#include <sys/time.h> // NOLINT
-#include <unistd.h> // NOLINT
+# include <sys/time.h> // NOLINT
+# include <unistd.h> // NOLINT
#endif // GTEST_OS_LINUX
#if GTEST_HAS_EXCEPTIONS
-#include <stdexcept>
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h> // NOLINT
+# include <netdb.h> // NOLINT
#endif
// Indicates that this translation unit is part of Google Test's
@@ -129,7 +133,7 @@
#undef GTEST_IMPLEMENTATION_
#if GTEST_OS_WINDOWS
-#define vsnprintf _vsnprintf
+# define vsnprintf _vsnprintf
#endif // GTEST_OS_WINDOWS
namespace testing {
@@ -187,7 +191,7 @@
GTEST_DEFINE_bool_(
catch_exceptions,
- internal::BoolFromGTestEnv("catch_exceptions", false),
+ internal::BoolFromGTestEnv("catch_exceptions", true),
"True iff " GTEST_NAME_
" should catch exceptions and treat them as test failures.");
@@ -258,6 +262,13 @@
"The maximum number of stack frames to print when an "
"assertion fails. The valid range is 0 through 100, inclusive.");
+GTEST_DEFINE_string_(
+ stream_result_to,
+ internal::StringFromGTestEnv("stream_result_to", ""),
+ "This flag specifies the host name and the port number on which to stream "
+ "test results. Example: \"localhost:555\". The flag is effective only on "
+ "Linux.");
+
GTEST_DEFINE_bool_(
throw_on_failure,
internal::BoolFromGTestEnv("throw_on_failure", false),
@@ -490,20 +501,33 @@
!MatchesFilter(full_name, negative.c_str()));
}
-#if GTEST_OS_WINDOWS
+#if GTEST_HAS_SEH
// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
// This function is useful as an __except condition.
int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
- // Google Test should handle an exception if:
+ // Google Test should handle a SEH exception if:
// 1. the user wants it to, AND
- // 2. this is not a breakpoint exception.
- return (GTEST_FLAG(catch_exceptions) &&
- exception_code != EXCEPTION_BREAKPOINT) ?
- EXCEPTION_EXECUTE_HANDLER :
- EXCEPTION_CONTINUE_SEARCH;
+ // 2. this is not a breakpoint exception, AND
+ // 3. this is not a C++ exception (VC++ implements them via SEH,
+ // apparently).
+ //
+ // SEH exception code for C++ exceptions.
+ // (see http://support.microsoft.com/kb/185294 for more information).
+ const DWORD kCxxExceptionCode = 0xe06d7363;
+
+ bool should_handle = true;
+
+ if (!GTEST_FLAG(catch_exceptions))
+ should_handle = false;
+ else if (exception_code == EXCEPTION_BREAKPOINT)
+ should_handle = false;
+ else if (exception_code == kCxxExceptionCode)
+ should_handle = false;
+
+ return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
}
-#endif // GTEST_OS_WINDOWS
+#endif // GTEST_HAS_SEH
} // namespace internal
@@ -583,7 +607,7 @@
const char* /* substr_expr */,
const TestPartResultArray& results,
TestPartResult::Type type,
- const char* substr) {
+ const string& substr) {
const String expected(type == TestPartResult::kFatalFailure ?
"1 fatal failure" :
"1 non-fatal failure");
@@ -594,23 +618,21 @@
for (int i = 0; i < results.size(); i++) {
msg << "\n" << results.GetTestPartResult(i);
}
- return AssertionFailure(msg);
+ return AssertionFailure() << msg;
}
const TestPartResult& r = results.GetTestPartResult(0);
if (r.type() != type) {
- msg << "Expected: " << expected << "\n"
- << " Actual:\n"
- << r;
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: " << expected << "\n"
+ << " Actual:\n"
+ << r;
}
- if (strstr(r.message(), substr) == NULL) {
- msg << "Expected: " << expected << " containing \""
- << substr << "\"\n"
- << " Actual:\n"
- << r;
- return AssertionFailure(msg);
+ if (strstr(r.message(), substr.c_str()) == NULL) {
+ return AssertionFailure() << "Expected: " << expected << " containing \""
+ << substr << "\"\n"
+ << " Actual:\n"
+ << r;
}
return AssertionSuccess();
@@ -622,7 +644,7 @@
SingleFailureChecker:: SingleFailureChecker(
const TestPartResultArray* results,
TestPartResult::Type type,
- const char* substr)
+ const string& substr)
: results_(results),
type_(type),
substr_(substr) {}
@@ -632,7 +654,7 @@
// type and contains the given substring. If that's not the case, a
// non-fatal failure will be generated.
SingleFailureChecker::~SingleFailureChecker() {
- EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_.c_str());
+ EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
}
DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
@@ -764,25 +786,30 @@
return 0;
#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
__timeb64 now;
-#ifdef _MSC_VER
+
+# ifdef _MSC_VER
+
// MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
// (deprecated function) there.
// TODO(kenton at google.com): Use GetTickCount()? Or use
// SystemTimeToFileTime()
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4996) // Temporarily disables warning 4996.
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996.
_ftime64(&now);
-#pragma warning(pop) // Restores the warning state.
-#else
+# pragma warning(pop) // Restores the warning state.
+# else
+
_ftime64(&now);
-#endif // _MSC_VER
+
+# endif // _MSC_VER
+
return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
#elif GTEST_HAS_GETTIMEOFDAY_
struct timeval now;
gettimeofday(&now, NULL);
return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
#else
-#error "Don't know how to get the current time on your system."
+# error "Don't know how to get the current time on your system."
#endif
}
@@ -918,55 +945,13 @@
}
#endif // GTEST_HAS_GLOBAL_WSTRING
-namespace internal {
-
-// Formats a value to be used in a failure message.
-
-// For a char value, we print it as a C++ char literal and as an
-// unsigned integer (both in decimal and in hexadecimal).
-String FormatForFailureMessage(char ch) {
- const unsigned int ch_as_uint = ch;
- // A String object cannot contain '\0', so we print "\\0" when ch is
- // '\0'.
- return String::Format("'%s' (%u, 0x%X)",
- ch ? String::Format("%c", ch).c_str() : "\\0",
- ch_as_uint, ch_as_uint);
-}
-
-// For a wchar_t value, we print it as a C++ wchar_t literal and as an
-// unsigned integer (both in decimal and in hexidecimal).
-String FormatForFailureMessage(wchar_t wchar) {
- // The C++ standard doesn't specify the exact size of the wchar_t
- // type. It just says that it shall have the same size as another
- // integral type, called its underlying type.
- //
- // Therefore, in order to print a wchar_t value in the numeric form,
- // we first convert it to the largest integral type (UInt64) and
- // then print the converted value.
- //
- // We use streaming to print the value as "%llu" doesn't work
- // correctly with MSVC 7.1.
- const UInt64 wchar_as_uint64 = wchar;
- Message msg;
- // A String object cannot contain '\0', so we print "\\0" when wchar is
- // L'\0'.
- char buffer[32]; // CodePointToUtf8 requires a buffer that big.
- msg << "L'"
- << (wchar ? CodePointToUtf8(static_cast<UInt32>(wchar), buffer) : "\\0")
- << "' (" << wchar_as_uint64 << ", 0x" << ::std::setbase(16)
- << wchar_as_uint64 << ")";
- return msg.GetString();
-}
-
-} // namespace internal
-
// AssertionResult constructors.
// Used in EXPECT_TRUE/FALSE(assertion_result).
AssertionResult::AssertionResult(const AssertionResult& other)
: success_(other.success_),
message_(other.message_.get() != NULL ?
- new internal::String(*other.message_) :
- static_cast<internal::String*>(NULL)) {
+ new ::std::string(*other.message_) :
+ static_cast< ::std::string*>(NULL)) {
}
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
@@ -1029,7 +1014,7 @@
msg << "\nWhich is: " << expected_value;
}
- return AssertionFailure(msg);
+ return AssertionFailure() << msg;
}
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
@@ -1059,13 +1044,12 @@
// TODO(wan): do not print the value of an expression if it's
// already a literal.
- Message msg;
- msg << "The difference between " << expr1 << " and " << expr2
+ return AssertionFailure()
+ << "The difference between " << expr1 << " and " << expr2
<< " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
<< expr1 << " evaluates to " << val1 << ",\n"
<< expr2 << " evaluates to " << val2 << ", and\n"
<< abs_error_expr << " evaluates to " << abs_error << ".";
- return AssertionFailure(msg);
}
@@ -1090,20 +1074,18 @@
// val2 is NaN, as the IEEE floating-point standard requires that
// any predicate involving a NaN must return false.
- StrStream val1_ss;
+ ::std::stringstream val1_ss;
val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< val1;
- StrStream val2_ss;
+ ::std::stringstream val2_ss;
val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< val2;
- Message msg;
- msg << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
- << " Actual: " << StrStreamToString(&val1_ss) << " vs "
- << StrStreamToString(&val2_ss);
-
- return AssertionFailure(msg);
+ return AssertionFailure()
+ << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+ << " Actual: " << StringStreamToString(&val1_ss) << " vs "
+ << StringStreamToString(&val2_ss);
}
} // namespace internal
@@ -1150,11 +1132,10 @@
if (val1 op val2) {\
return AssertionSuccess();\
} else {\
- Message msg;\
- msg << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ return AssertionFailure() \
+ << "Expected: (" << expr1 << ") " #op " (" << expr2\
<< "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
<< " vs " << FormatForComparisonFailureMessage(val2, val1);\
- return AssertionFailure(msg);\
}\
}
@@ -1216,11 +1197,9 @@
if (!String::CStringEquals(s1, s2)) {
return AssertionSuccess();
} else {
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
- << s2_expression << "), actual: \""
- << s1 << "\" vs \"" << s2 << "\"";
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: \""
+ << s1 << "\" vs \"" << s2 << "\"";
}
}
@@ -1232,11 +1211,10 @@
if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
return AssertionSuccess();
} else {
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
+ return AssertionFailure()
+ << "Expected: (" << s1_expression << ") != ("
<< s2_expression << ") (ignoring case), actual: \""
<< s1 << "\" vs \"" << s2 << "\"";
- return AssertionFailure(msg);
}
}
@@ -1285,13 +1263,12 @@
const bool is_wide_string = sizeof(needle[0]) > 1;
const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
- return AssertionFailure(
- Message()
+ return AssertionFailure()
<< "Value of: " << needle_expr << "\n"
<< " Actual: " << begin_string_quote << needle << "\"\n"
<< "Expected: " << (expected_to_be_substring ? "" : "not ")
<< "a substring of " << haystack_expr << "\n"
- << "Which is: " << begin_string_quote << haystack << "\"");
+ << "Which is: " << begin_string_quote << haystack << "\"";
}
} // namespace
@@ -1360,10 +1337,13 @@
AssertionResult HRESULTFailureHelper(const char* expr,
const char* expected,
long hr) { // NOLINT
-#if GTEST_OS_WINDOWS_MOBILE
+# if GTEST_OS_WINDOWS_MOBILE
+
// Windows CE doesn't support FormatMessage.
const char error_text[] = "";
-#else
+
+# else
+
// Looks up the human-readable system message for the HRESULT code
// and since we're not passing any params to FormatMessage, we don't
// want inserts expanded.
@@ -1380,18 +1360,17 @@
kBufSize, // buf size
NULL); // no arguments for inserts
// Trims tailing white space (FormatMessage leaves a trailing cr-lf)
- for (; message_length && isspace(error_text[message_length - 1]);
+ for (; message_length && IsSpace(error_text[message_length - 1]);
--message_length) {
error_text[message_length - 1] = '\0';
}
-#endif // GTEST_OS_WINDOWS_MOBILE
+
+# endif // GTEST_OS_WINDOWS_MOBILE
const String error_hex(String::Format("0x%08X ", hr));
- Message msg;
- msg << "Expected: " << expr << " " << expected << ".\n"
+ return ::testing::AssertionFailure()
+ << "Expected: " << expr << " " << expected << ".\n"
<< " Actual: " << error_hex << error_text << "\n";
-
- return ::testing::AssertionFailure(msg);
}
} // namespace
@@ -1526,7 +1505,7 @@
if (num_chars == -1)
num_chars = static_cast<int>(wcslen(str));
- StrStream stream;
+ ::std::stringstream stream;
for (int i = 0; i < num_chars; ++i) {
UInt32 unicode_code_point;
@@ -1543,7 +1522,7 @@
char buffer[32]; // CodePointToUtf8 requires a buffer this big.
stream << CodePointToUtf8(unicode_code_point, buffer);
}
- return StrStreamToString(&stream);
+ return StringStreamToString(&stream);
}
// Converts a wide C string to a String using the UTF-8 encoding.
@@ -1602,12 +1581,10 @@
return AssertionSuccess();
}
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
- << s2_expression << "), actual: "
- << String::ShowWideCStringQuoted(s1)
- << " vs " << String::ShowWideCStringQuoted(s2);
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: "
+ << String::ShowWideCStringQuoted(s1)
+ << " vs " << String::ShowWideCStringQuoted(s2);
}
// Compares two C strings, ignoring case. Returns true iff they have
@@ -1638,17 +1615,17 @@
// current locale.
bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
const wchar_t* rhs) {
- if ( lhs == NULL ) return rhs == NULL;
+ if (lhs == NULL) return rhs == NULL;
- if ( rhs == NULL ) return false;
+ if (rhs == NULL) return false;
#if GTEST_OS_WINDOWS
return _wcsicmp(lhs, rhs) == 0;
-#elif GTEST_OS_LINUX
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
return wcscasecmp(lhs, rhs) == 0;
#else
- // Mac OS X and Cygwin don't define wcscasecmp. Other unknown OSes
- // may not define it either.
+ // Android, Mac OS X and Cygwin don't define wcscasecmp.
+ // Other unknown OSes may not define it either.
wint_t left, right;
do {
left = towlower(*lhs++);
@@ -1730,10 +1707,12 @@
// MSVC 8 deprecates vsnprintf(), so we want to suppress warning
// 4996 (deprecated function) there.
#ifdef _MSC_VER // We are using MSVC.
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4996) // Temporarily disables warning 4996.
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996.
+
const int size = vsnprintf(buffer, kBufferSize, format, args);
-#pragma warning(pop) // Restores the warning state.
+
+# pragma warning(pop) // Restores the warning state.
#else // We are not using MSVC.
const int size = vsnprintf(buffer, kBufferSize, format, args);
#endif // _MSC_VER
@@ -1751,16 +1730,16 @@
}
}
-// Converts the buffer in a StrStream to a String, converting NUL
+// Converts the buffer in a stringstream to a String, converting NUL
// bytes to "\\0" along the way.
-String StrStreamToString(StrStream* ss) {
+String StringStreamToString(::std::stringstream* ss) {
const ::std::string& str = ss->str();
const char* const start = str.c_str();
const char* const end = start + str.length();
- // We need to use a helper StrStream to do this transformation
+ // We need to use a helper stringstream to do this transformation
// because String doesn't support push_back().
- StrStream helper;
+ ::std::stringstream helper;
for (const char* ch = start; ch != end; ++ch) {
if (*ch == '\0') {
helper << "\\0"; // Replaces NUL with "\\0";
@@ -1964,22 +1943,6 @@
} // namespace internal
-#if GTEST_HAS_SEH
-// We are on Windows with SEH.
-
-// Adds an "exception thrown" fatal failure to the current test.
-static void AddExceptionThrownFailure(DWORD exception_code,
- const char* location) {
- Message message;
- message << "Exception thrown with code 0x" << std::setbase(16) <<
- exception_code << std::setbase(10) << " in " << location << ".";
-
- internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
- message.GetString());
-}
-
-#endif // GTEST_HAS_SEH
-
// Google Test requires all tests in the same test case to use the same test
// fixture class. This function checks if the current test has the
// same fixture class as the first test in the current test case. If
@@ -1990,15 +1953,13 @@
const TestCase* const test_case = impl->current_test_case();
// Info about the first test in the current test case.
- const internal::TestInfoImpl* const first_test_info =
- test_case->test_info_list()[0]->impl();
- const internal::TypeId first_fixture_id = first_test_info->fixture_class_id();
+ const TestInfo* const first_test_info = test_case->test_info_list()[0];
+ const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
const char* const first_test_name = first_test_info->name();
// Info about the current test.
- const internal::TestInfoImpl* const this_test_info =
- impl->current_test_info()->impl();
- const internal::TypeId this_fixture_id = this_test_info->fixture_class_id();
+ const TestInfo* const this_test_info = impl->current_test_info();
+ const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
const char* const this_test_name = this_test_info->name();
if (this_fixture_id != first_fixture_id) {
@@ -2048,62 +2009,167 @@
return true;
}
-// Runs the test and updates the test result.
-void Test::Run() {
- if (!HasSameFixtureClass()) return;
+#if GTEST_HAS_SEH
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+// Adds an "exception thrown" fatal failure to the current test. This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static internal::String* FormatSehExceptionMessage(DWORD exception_code,
+ const char* location) {
+ Message message;
+ message << "SEH exception with code 0x" << std::setbase(16) <<
+ exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+ return new internal::String(message.GetString());
+}
+
+#endif // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static internal::String FormatCxxExceptionMessage(const char* description,
+ const char* location) {
+ Message message;
+ if (description != NULL) {
+ message << "C++ exception with description \"" << description << "\"";
+ } else {
+ message << "Unknown C++ exception";
+ }
+ message << " thrown in " << location << ".";
+
+ return message.GetString();
+}
+
+static internal::String PrintTestPartResultToString(
+ const TestPartResult& test_part_result);
+
+// A failed Google Test assertion will throw an exception of this type when
+// GTEST_FLAG(throw_on_failure) is true (if exceptions are enabled). We
+// derive it from std::runtime_error, which is for errors presumably
+// detectable only at run time. Since std::runtime_error inherits from
+// std::exception, many testing frameworks know how to extract and print the
+// message inside it.
+class GoogleTestFailureException : public ::std::runtime_error {
+ public:
+ explicit GoogleTestFailureException(const TestPartResult& failure)
+ : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+};
+#endif // GTEST_HAS_EXCEPTIONS
+
+namespace internal {
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception. (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function. Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
- impl->os_stack_trace_getter()->UponLeavingGTest();
__try {
- SetUp();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
+ return (object->*method)();
+ } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT
GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "SetUp()");
+ // We create the exception message on the heap because VC++ prohibits
+ // creation of objects with destructors on stack in functions using __try
+ // (see error C2712).
+ internal::String* exception_message = FormatSehExceptionMessage(
+ GetExceptionCode(), location);
+ internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+ *exception_message);
+ delete exception_message;
+ return static_cast<Result>(0);
}
+#else
+ (void)location;
+ return (object->*method)();
+#endif // GTEST_HAS_SEH
+}
- // We will run the test only if SetUp() had no fatal failure.
- if (!HasFatalFailure()) {
- impl->os_stack_trace_getter()->UponLeavingGTest();
- __try {
- TestBody();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "the test body");
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
+ // NOTE: The user code can affect the way in which Google Test handles
+ // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+ // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+ // after the exception is caught and either report or re-throw the
+ // exception based on the flag's value:
+ //
+ // try {
+ // // Perform the test method.
+ // } catch (...) {
+ // if (GTEST_FLAG(catch_exceptions))
+ // // Report the exception as failure.
+ // else
+ // throw; // Re-throws the original exception.
+ // }
+ //
+ // However, the purpose of this flag is to allow the program to drop into
+ // the debugger when the exception is thrown. On most platforms, once the
+ // control enters the catch block, the exception origin information is
+ // lost and the debugger will stop the program at the point of the
+ // re-throw in this function -- instead of at the point of the original
+ // throw statement in the code under test. For this reason, we perform
+ // the check early, sacrificing the ability to affect Google Test's
+ // exception handling in the method where the exception is thrown.
+ if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+ try {
+ return HandleSehExceptionsInMethodIfSupported(object, method, location);
+ } catch (const GoogleTestFailureException&) { // NOLINT
+ // This exception doesn't originate in code under test. It makes no
+ // sense to report it as a test failure.
+ throw;
+ } catch (const std::exception& e) { // NOLINT
+ internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatCxxExceptionMessage(e.what(), location));
+ } catch (...) { // NOLINT
+ internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatCxxExceptionMessage(NULL, location));
}
+ return static_cast<Result>(0);
+#else
+ return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif // GTEST_HAS_EXCEPTIONS
+ } else {
+ return (object->*method)();
}
+}
- // However, we want to clean up as much as possible. Hence we will
- // always call TearDown(), even if SetUp() or the test body has
- // failed.
- impl->os_stack_trace_getter()->UponLeavingGTest();
- __try {
- TearDown();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "TearDown()");
- }
+} // namespace internal
-#else // We are on a compiler or platform that doesn't support SEH.
- impl->os_stack_trace_getter()->UponLeavingGTest();
- SetUp();
+// Runs the test and updates the test result.
+void Test::Run() {
+ if (!HasSameFixtureClass()) return;
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
// We will run the test only if SetUp() was successful.
if (!HasFatalFailure()) {
impl->os_stack_trace_getter()->UponLeavingGTest();
- TestBody();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &Test::TestBody, "the test body");
}
// However, we want to clean up as much as possible. Hence we will
// always call TearDown(), even if SetUp() or the test body has
// failed.
impl->os_stack_trace_getter()->UponLeavingGTest();
- TearDown();
-#endif // GTEST_HAS_SEH
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &Test::TearDown, "TearDown()");
}
-
// Returns true iff the current test has a fatal failure.
bool Test::HasFatalFailure() {
return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
@@ -2118,22 +2184,28 @@
// class TestInfo
// Constructs a TestInfo object. It assumes ownership of the test factory
-// object via impl_.
+// object.
+// TODO(vladl at google.com): Make a_test_case_name and a_name const string&'s
+// to signify they cannot be NULLs.
TestInfo::TestInfo(const char* a_test_case_name,
const char* a_name,
- const char* a_test_case_comment,
- const char* a_comment,
+ const char* a_type_param,
+ const char* a_value_param,
internal::TypeId fixture_class_id,
- internal::TestFactoryBase* factory) {
- impl_ = new internal::TestInfoImpl(this, a_test_case_name, a_name,
- a_test_case_comment, a_comment,
- fixture_class_id, factory);
-}
+ internal::TestFactoryBase* factory)
+ : test_case_name_(a_test_case_name),
+ name_(a_name),
+ type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+ value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+ fixture_class_id_(fixture_class_id),
+ should_run_(false),
+ is_disabled_(false),
+ matches_filter_(false),
+ factory_(factory),
+ result_() {}
// Destructs a TestInfo object.
-TestInfo::~TestInfo() {
- delete impl_;
-}
+TestInfo::~TestInfo() { delete factory_; }
namespace internal {
@@ -2144,10 +2216,10 @@
//
// test_case_name: name of the test case
// name: name of the test
-// test_case_comment: a comment on the test case that will be included in
-// the test output
-// comment: a comment on the test that will be included in the
-// test output
+// type_param: the name of the test's type parameter, or NULL if
+// this is not a typed or a type-parameterized test.
+// value_param: text representation of the test's value parameter,
+// or NULL if this is not a value-parameterized test.
// fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
@@ -2156,13 +2228,14 @@
// ownership of the factory object.
TestInfo* MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* type_param,
+ const char* value_param,
TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc,
TestFactoryBase* factory) {
TestInfo* const test_info =
- new TestInfo(test_case_name, name, test_case_comment, comment,
+ new TestInfo(test_case_name, name, type_param, value_param,
fixture_class_id, factory);
GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
return test_info;
@@ -2189,41 +2262,6 @@
} // namespace internal
-// Returns the test case name.
-const char* TestInfo::test_case_name() const {
- return impl_->test_case_name();
-}
-
-// Returns the test name.
-const char* TestInfo::name() const {
- return impl_->name();
-}
-
-// Returns the test case comment.
-const char* TestInfo::test_case_comment() const {
- return impl_->test_case_comment();
-}
-
-// Returns the test comment.
-const char* TestInfo::comment() const {
- return impl_->comment();
-}
-
-// Returns true if this test should run.
-bool TestInfo::should_run() const { return impl_->should_run(); }
-
-// Returns true if this test matches the user-specified filter.
-bool TestInfo::matches_filter() const { return impl_->matches_filter(); }
-
-// Returns the result of the test.
-const TestResult* TestInfo::result() const { return impl_->result(); }
-
-// Increments the number of death tests encountered in this test so
-// far.
-int TestInfo::increment_death_test_count() {
- return impl_->result()->increment_death_test_count();
-}
-
namespace internal {
// This method expands all parameterized tests registered with macros TEST_P
@@ -2238,70 +2276,54 @@
#endif
}
+} // namespace internal
+
// Creates the test object, runs it, records its result, and then
// deletes it.
-void TestInfoImpl::Run() {
+void TestInfo::Run() {
if (!should_run_) return;
// Tells UnitTest where to store test result.
- UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->set_current_test_info(parent_);
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->set_current_test_info(this);
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
// Notifies the unit test event listeners that a test is about to start.
- repeater->OnTestStart(*parent_);
+ repeater->OnTestStart(*this);
- const TimeInMillis start = GetTimeInMillis();
+ const TimeInMillis start = internal::GetTimeInMillis();
impl->os_stack_trace_getter()->UponLeavingGTest();
-#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
- Test* test = NULL;
-
- __try {
- // Creates the test object.
- test = factory_->CreateTest();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(),
- "the test fixture's constructor");
- return;
- }
-#else // We are on a compiler or platform that doesn't support SEH.
-
- // TODO(wan): If test->Run() throws, test won't be deleted. This is
- // not a problem now as we don't use exceptions. If we were to
- // enable exceptions, we should revise the following to be
- // exception-safe.
// Creates the test object.
- Test* test = factory_->CreateTest();
-#endif // GTEST_HAS_SEH
-
- // Runs the test only if the constructor of the test fixture didn't
- // generate a fatal failure.
- if (!Test::HasFatalFailure()) {
+ Test* const test = internal::HandleExceptionsInMethodIfSupported(
+ factory_, &internal::TestFactoryBase::CreateTest,
+ "the test fixture's constructor");
+
+ // Runs the test only if the test object was created and its
+ // constructor didn't generate a fatal failure.
+ if ((test != NULL) && !Test::HasFatalFailure()) {
+ // This doesn't throw as all user code that can throw are wrapped into
+ // exception handling code.
test->Run();
}
// Deletes the test object.
impl->os_stack_trace_getter()->UponLeavingGTest();
- delete test;
- test = NULL;
+ internal::HandleExceptionsInMethodIfSupported(
+ test, &Test::DeleteSelf_, "the test fixture's destructor");
- result_.set_elapsed_time(GetTimeInMillis() - start);
+ result_.set_elapsed_time(internal::GetTimeInMillis() - start);
// Notifies the unit test event listener that a test has just finished.
- repeater->OnTestEnd(*parent_);
+ repeater->OnTestEnd(*this);
// Tells UnitTest to stop associating assertion results to this
// test.
impl->set_current_test_info(NULL);
}
-} // namespace internal
-
// class TestCase
// Gets the number of successful tests in this test case.
@@ -2333,13 +2355,15 @@
// Arguments:
//
// name: name of the test case
+// a_type_param: the name of the test case's type parameter, or NULL if
+// this is not a typed or a type-parameterized test case.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
-TestCase::TestCase(const char* a_name, const char* a_comment,
+TestCase::TestCase(const char* a_name, const char* a_type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc)
: name_(a_name),
- comment_(a_comment),
+ type_param_(a_type_param ? new std::string(a_type_param) : NULL),
set_up_tc_(set_up_tc),
tear_down_tc_(tear_down_tc),
should_run_(false),
@@ -2384,45 +2408,26 @@
repeater->OnTestCaseStart(*this);
impl->os_stack_trace_getter()->UponLeavingGTest();
- set_up_tc_();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
const internal::TimeInMillis start = internal::GetTimeInMillis();
for (int i = 0; i < total_test_count(); i++) {
- GetMutableTestInfo(i)->impl()->Run();
+ GetMutableTestInfo(i)->Run();
}
elapsed_time_ = internal::GetTimeInMillis() - start;
impl->os_stack_trace_getter()->UponLeavingGTest();
- tear_down_tc_();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
repeater->OnTestCaseEnd(*this);
impl->set_current_test_case(NULL);
}
// Clears the results of all tests in this test case.
void TestCase::ClearResult() {
- ForEach(test_info_list_, internal::TestInfoImpl::ClearTestResult);
-}
-
-// Returns true iff test passed.
-bool TestCase::TestPassed(const TestInfo * test_info) {
- const internal::TestInfoImpl* const impl = test_info->impl();
- return impl->should_run() && impl->result()->Passed();
-}
-
-// Returns true iff test failed.
-bool TestCase::TestFailed(const TestInfo * test_info) {
- const internal::TestInfoImpl* const impl = test_info->impl();
- return impl->should_run() && impl->result()->Failed();
-}
-
-// Returns true iff test is disabled.
-bool TestCase::TestDisabled(const TestInfo * test_info) {
- return test_info->impl()->is_disabled();
-}
-
-// Returns true if the given test should run.
-bool TestCase::ShouldRunTest(const TestInfo *test_info) {
- return test_info->impl()->should_run();
+ ForEach(test_info_list_, TestInfo::ClearTestResult);
}
// Shuffles the tests in this test case.
@@ -2475,9 +2480,9 @@
#else
return "Failure\n";
#endif
+ default:
+ return "Unknown result type";
}
-
- return "Unknown result type";
}
// Prints a TestPartResult to a String.
@@ -2563,6 +2568,7 @@
String::CStringEquals(term, "xterm") ||
String::CStringEquals(term, "xterm-color") ||
String::CStringEquals(term, "xterm-256color") ||
+ String::CStringEquals(term, "screen") ||
String::CStringEquals(term, "linux") ||
String::CStringEquals(term, "cygwin");
return stdout_is_tty && term_supports_color;
@@ -2628,6 +2634,23 @@
va_end(args);
}
+void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+ const char* const type_param = test_info.type_param();
+ const char* const value_param = test_info.value_param();
+
+ if (type_param != NULL || value_param != NULL) {
+ printf(", where ");
+ if (type_param != NULL) {
+ printf("TypeParam = %s", type_param);
+ if (value_param != NULL)
+ printf(" and ");
+ }
+ if (value_param != NULL) {
+ printf("GetParam() = %s", value_param);
+ }
+ }
+}
+
// This class implements the TestEventListener interface.
//
// Class PrettyUnitTestResultPrinter is copyable.
@@ -2675,9 +2698,10 @@
}
if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+ const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
ColoredPrintf(COLOR_YELLOW,
- "Note: This is test shard %s of %s.\n",
- internal::posix::GetEnv(kTestShardIndex),
+ "Note: This is test shard %d of %s.\n",
+ static_cast<int>(shard_index) + 1,
internal::posix::GetEnv(kTestTotalShards));
}
@@ -2707,10 +2731,10 @@
FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
ColoredPrintf(COLOR_GREEN, "[----------] ");
printf("%s from %s", counts.c_str(), test_case_name_.c_str());
- if (test_case.comment()[0] == '\0') {
+ if (test_case.type_param() == NULL) {
printf("\n");
} else {
- printf(", where %s\n", test_case.comment());
+ printf(", where TypeParam = %s\n", test_case.type_param());
}
fflush(stdout);
}
@@ -2718,11 +2742,7 @@
void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
ColoredPrintf(COLOR_GREEN, "[ RUN ] ");
PrintTestName(test_case_name_.c_str(), test_info.name());
- if (test_info.comment()[0] == '\0') {
- printf("\n");
- } else {
- printf(", where %s\n", test_info.comment());
- }
+ printf("\n");
fflush(stdout);
}
@@ -2745,6 +2765,9 @@
ColoredPrintf(COLOR_RED, "[ FAILED ] ");
}
PrintTestName(test_case_name_.c_str(), test_info.name());
+ if (test_info.result()->Failed())
+ PrintFullTestCommentIfPresent(test_info);
+
if (GTEST_FLAG(print_time)) {
printf(" (%s ms)\n", internal::StreamableToString(
test_info.result()->elapsed_time()).c_str());
@@ -2793,21 +2816,14 @@
}
ColoredPrintf(COLOR_RED, "[ FAILED ] ");
printf("%s.%s", test_case.name(), test_info.name());
- if (test_case.comment()[0] != '\0' ||
- test_info.comment()[0] != '\0') {
- printf(", where %s", test_case.comment());
- if (test_case.comment()[0] != '\0' &&
- test_info.comment()[0] != '\0') {
- printf(" and ");
- }
- }
- printf("%s\n", test_info.comment());
+ PrintFullTestCommentIfPresent(test_info);
+ printf("\n");
}
}
}
- void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
- int /*iteration*/) {
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+ int /*iteration*/) {
ColoredPrintf(COLOR_GREEN, "[==========] ");
printf("%s from %s ran.",
FormatTestCount(unit_test.test_to_run_count()).c_str(),
@@ -2987,7 +3003,7 @@
static String EscapeXml(const char* str, bool is_attribute);
// Returns the given string with all characters invalid in XML removed.
- static String RemoveInvalidXmlCharacters(const char* str);
+ static string RemoveInvalidXmlCharacters(const string& str);
// Convenience wrapper around EscapeXml when str is an attribute value.
static String EscapeXmlAttribute(const char* str) {
@@ -3121,17 +3137,14 @@
// Returns the given string with all characters invalid in XML removed.
// Currently invalid characters are dropped from the string. An
// alternative is to replace them with certain characters such as . or ?.
-String XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const char* str) {
- char* const output = new char[strlen(str) + 1];
- char* appender = output;
- for (char ch = *str; ch != '\0'; ch = *++str)
- if (IsValidXmlCharacter(ch))
- *appender++ = ch;
- *appender = '\0';
-
- String ret_value(output);
- delete[] output;
- return ret_value;
+string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const string& str) {
+ string output;
+ output.reserve(str.size());
+ for (string::const_iterator it = str.begin(); it != str.end(); ++it)
+ if (IsValidXmlCharacter(*it))
+ output.push_back(*it);
+
+ return output;
}
// The following routines generate an XML representation of a UnitTest
@@ -3184,8 +3197,18 @@
const TestInfo& test_info) {
const TestResult& result = *test_info.result();
*stream << " <testcase name=\""
- << EscapeXmlAttribute(test_info.name()).c_str()
- << "\" status=\""
+ << EscapeXmlAttribute(test_info.name()).c_str() << "\"";
+
+ if (test_info.value_param() != NULL) {
+ *stream << " value_param=\"" << EscapeXmlAttribute(test_info.value_param())
+ << "\"";
+ }
+ if (test_info.type_param() != NULL) {
+ *stream << " type_param=\"" << EscapeXmlAttribute(test_info.type_param())
+ << "\"";
+ }
+
+ *stream << " status=\""
<< (test_info.should_run() ? "run" : "notrun")
<< "\" time=\""
<< FormatTimeInMillisAsSeconds(result.elapsed_time())
@@ -3201,11 +3224,11 @@
*stream << " <failure message=\""
<< EscapeXmlAttribute(part.summary()).c_str()
<< "\" type=\"\">";
- const String message = RemoveInvalidXmlCharacters(String::Format(
- "%s:%d\n%s",
- part.file_name(), part.line_number(),
- part.message()).c_str());
- OutputXmlCDataSection(stream, message.c_str());
+ const string location = internal::FormatCompilerIndependentFileLocation(
+ part.file_name(), part.line_number());
+ const string message = location + "\n" + part.message();
+ OutputXmlCDataSection(stream,
+ RemoveInvalidXmlCharacters(message).c_str());
*stream << "</failure>\n";
}
}
@@ -3230,9 +3253,9 @@
"errors=\"0\" time=\"%s\">\n",
FormatTimeInMillisAsSeconds(test_case.elapsed_time()).c_str());
for (int i = 0; i < test_case.total_test_count(); ++i) {
- StrStream stream;
+ ::std::stringstream stream;
OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i));
- fprintf(out, "%s", StrStreamToString(&stream).c_str());
+ fprintf(out, "%s", StringStreamToString(&stream).c_str());
}
fprintf(out, " </testsuite>\n");
}
@@ -3272,6 +3295,182 @@
// End XmlUnitTestResultPrinter
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+ // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+ static string UrlEncode(const char* str);
+
+ StreamingListener(const string& host, const string& port)
+ : sockfd_(-1), host_name_(host), port_num_(port) {
+ MakeConnection();
+ Send("gtest_streaming_protocol_version=1.0\n");
+ }
+
+ virtual ~StreamingListener() {
+ if (sockfd_ != -1)
+ CloseConnection();
+ }
+
+ void OnTestProgramStart(const UnitTest& /* unit_test */) {
+ Send("event=TestProgramStart\n");
+ }
+
+ void OnTestProgramEnd(const UnitTest& unit_test) {
+ // Note that Google Test current only report elapsed time for each
+ // test iteration, not for the entire test program.
+ Send(String::Format("event=TestProgramEnd&passed=%d\n",
+ unit_test.Passed()));
+
+ // Notify the streaming server to stop.
+ CloseConnection();
+ }
+
+ void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+ Send(String::Format("event=TestIterationStart&iteration=%d\n",
+ iteration));
+ }
+
+ void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+ Send(String::Format("event=TestIterationEnd&passed=%d&elapsed_time=%sms\n",
+ unit_test.Passed(),
+ StreamableToString(unit_test.elapsed_time()).c_str()));
+ }
+
+ void OnTestCaseStart(const TestCase& test_case) {
+ Send(String::Format("event=TestCaseStart&name=%s\n", test_case.name()));
+ }
+
+ void OnTestCaseEnd(const TestCase& test_case) {
+ Send(String::Format("event=TestCaseEnd&passed=%d&elapsed_time=%sms\n",
+ test_case.Passed(),
+ StreamableToString(test_case.elapsed_time()).c_str()));
+ }
+
+ void OnTestStart(const TestInfo& test_info) {
+ Send(String::Format("event=TestStart&name=%s\n", test_info.name()));
+ }
+
+ void OnTestEnd(const TestInfo& test_info) {
+ Send(String::Format(
+ "event=TestEnd&passed=%d&elapsed_time=%sms\n",
+ (test_info.result())->Passed(),
+ StreamableToString((test_info.result())->elapsed_time()).c_str()));
+ }
+
+ void OnTestPartResult(const TestPartResult& test_part_result) {
+ const char* file_name = test_part_result.file_name();
+ if (file_name == NULL)
+ file_name = "";
+ Send(String::Format("event=TestPartResult&file=%s&line=%d&message=",
+ UrlEncode(file_name).c_str(),
+ test_part_result.line_number()));
+ Send(UrlEncode(test_part_result.message()) + "\n");
+ }
+
+ private:
+ // Creates a client socket and connects to the server.
+ void MakeConnection();
+
+ // Closes the socket.
+ void CloseConnection() {
+ GTEST_CHECK_(sockfd_ != -1)
+ << "CloseConnection() can be called only when there is a connection.";
+
+ close(sockfd_);
+ sockfd_ = -1;
+ }
+
+ // Sends a string to the socket.
+ void Send(const string& message) {
+ GTEST_CHECK_(sockfd_ != -1)
+ << "Send() can be called only when there is a connection.";
+
+ const int len = static_cast<int>(message.length());
+ if (write(sockfd_, message.c_str(), len) != len) {
+ GTEST_LOG_(WARNING)
+ << "stream_result_to: failed to stream to "
+ << host_name_ << ":" << port_num_;
+ }
+ }
+
+ int sockfd_; // socket file descriptor
+ const string host_name_;
+ const string port_num_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+}; // class StreamingListener
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D". This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+string StreamingListener::UrlEncode(const char* str) {
+ string result;
+ result.reserve(strlen(str) + 1);
+ for (char ch = *str; ch != '\0'; ch = *++str) {
+ switch (ch) {
+ case '%':
+ case '=':
+ case '&':
+ case '\n':
+ result.append(String::Format("%%%02x", static_cast<unsigned char>(ch)));
+ break;
+ default:
+ result.push_back(ch);
+ break;
+ }
+ }
+ return result;
+}
+
+void StreamingListener::MakeConnection() {
+ GTEST_CHECK_(sockfd_ == -1)
+ << "MakeConnection() can't be called when there is already a connection.";
+
+ addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses.
+ hints.ai_socktype = SOCK_STREAM;
+ addrinfo* servinfo = NULL;
+
+ // Use the getaddrinfo() to get a linked list of IP addresses for
+ // the given host name.
+ const int error_num = getaddrinfo(
+ host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+ if (error_num != 0) {
+ GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+ << gai_strerror(error_num);
+ }
+
+ // Loop through all the results and connect to the first we can.
+ for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL;
+ cur_addr = cur_addr->ai_next) {
+ sockfd_ = socket(
+ cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+ if (sockfd_ != -1) {
+ // Connect the client socket to the server socket.
+ if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+ close(sockfd_);
+ sockfd_ = -1;
+ }
+ }
+ }
+
+ freeaddrinfo(servinfo); // all done with this structure
+
+ if (sockfd_ == -1) {
+ GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+ << host_name_ << ":" << port_num_;
+ }
+}
+
+// End of class Streaming Listener
+#endif // GTEST_CAN_STREAM_RESULTS__
+
// Class ScopedTrace
// Pushes the given source file location and message onto a per-thread
@@ -3512,19 +3711,6 @@
return env;
}
-#if GTEST_HAS_EXCEPTIONS
-// A failed Google Test assertion will throw an exception of this type
-// when exceptions are enabled. We derive it from std::runtime_error,
-// which is for errors presumably detectable only at run time. Since
-// std::runtime_error inherits from std::exception, many testing
-// frameworks know how to extract and print the message inside it.
-class GoogleTestFailureException : public ::std::runtime_error {
- public:
- explicit GoogleTestFailureException(const TestPartResult& failure)
- : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
-};
-#endif
-
// Adds a TestPartResult to the current TestResult object. All Google Test
// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
// this to report their results. The user code should use the
@@ -3601,31 +3787,34 @@
// We don't protect this under mutex_, as we only support calling it
// from the main thread.
int UnitTest::Run() {
-#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
+ // Captures the value of GTEST_FLAG(catch_exceptions). This value will be
+ // used for the duration of the program.
+ impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+#if GTEST_HAS_SEH
const bool in_death_test_child_process =
internal::GTEST_FLAG(internal_run_death_test).length() > 0;
// Either the user wants Google Test to catch exceptions thrown by the
// tests or this is executing in the context of death test child
// process. In either case the user does not want to see pop-up dialogs
- // about crashes - they are expected..
- if (GTEST_FLAG(catch_exceptions) || in_death_test_child_process) {
-#if !GTEST_OS_WINDOWS_MOBILE
+ // about crashes - they are expected.
+ if (impl()->catch_exceptions() || in_death_test_child_process) {
+
+# if !GTEST_OS_WINDOWS_MOBILE
// SetErrorMode doesn't exist on CE.
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
-#endif // !GTEST_OS_WINDOWS_MOBILE
+# endif // !GTEST_OS_WINDOWS_MOBILE
-#if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
// Death test children can be terminated with _abort(). On Windows,
// _abort() can show a dialog with a warning message. This forces the
// abort message to go to stderr instead.
_set_error_mode(_OUT_TO_STDERR);
-#endif
+# endif
-#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
// In the debug version, Visual Studio pops up a separate dialog
// offering a choice to debug the aborted program. We need to suppress
// this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
@@ -3641,22 +3830,15 @@
_set_abort_behavior(
0x0, // Clear the following flags:
_WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump.
-#endif
- }
+# endif
- __try {
- return impl_->RunAllTests();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- printf("Exception thrown with code 0x%x.\nFAIL\n", GetExceptionCode());
- fflush(stdout);
- return 1;
}
-
-#else // We are on a compiler or platform that doesn't support SEH.
-
- return impl_->RunAllTests();
#endif // GTEST_HAS_SEH
+
+ return internal::HandleExceptionsInMethodIfSupported(
+ impl(),
+ &internal::UnitTestImpl::RunAllTests,
+ "auxiliary test code (environments or event listeners)") ? 0 : 1;
}
// Returns the working directory when the first TEST() or TEST_F() was
@@ -3724,12 +3906,12 @@
UnitTestImpl::UnitTestImpl(UnitTest* parent)
: parent_(parent),
#ifdef _MSC_VER
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4355) // Temporarily disables warning 4355
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4355) // Temporarily disables warning 4355
// (using this in initializer).
default_global_test_part_result_reporter_(this),
default_per_thread_test_part_result_reporter_(this),
-#pragma warning(pop) // Restores the warning state again.
+# pragma warning(pop) // Restores the warning state again.
#else
default_global_test_part_result_reporter_(this),
default_per_thread_test_part_result_reporter_(this),
@@ -3750,13 +3932,13 @@
post_flag_parse_init_performed_(false),
random_seed_(0), // Will be overridden by the flag before first use.
random_(0), // Will be reseeded before first use.
-#if GTEST_HAS_DEATH_TEST
elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
internal_run_death_test_flag_(NULL),
- death_test_factory_(new DefaultDeathTestFactory) {
-#else
- elapsed_time_(0) {
-#endif // GTEST_HAS_DEATH_TEST
+ death_test_factory_(new DefaultDeathTestFactory),
+#endif
+ // Will be overridden by the flag before first use.
+ catch_exceptions_(false) {
listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
}
@@ -3793,6 +3975,25 @@
}
}
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in String form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+ const string& target = GTEST_FLAG(stream_result_to);
+ if (!target.empty()) {
+ const size_t pos = target.find(':');
+ if (pos != string::npos) {
+ listeners()->Append(new StreamingListener(target.substr(0, pos),
+ target.substr(pos+1)));
+ } else {
+ printf("WARNING: unrecognized streaming target \"%s\" ignored.\n",
+ target.c_str());
+ fflush(stdout);
+ }
+ }
+}
+#endif // GTEST_CAN_STREAM_RESULTS_
+
// Performs initialization dependent upon flag values obtained in
// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
@@ -3816,6 +4017,11 @@
// Configures listeners for XML output. This makes it possible for users
// to shut down the default XML output before invoking RUN_ALL_TESTS.
ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+ // Configures listeners for streaming test results to the specified server.
+ ConfigureStreamingOutput();
+#endif // GTEST_CAN_STREAM_RESULTS_
}
}
@@ -3850,10 +4056,12 @@
// Arguments:
//
// test_case_name: name of the test case
+// type_param: the name of the test case's type parameter, or NULL if
+// this is not a typed or a type-parameterized test case.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
- const char* comment,
+ const char* type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc) {
// Can we find a TestCase with the given name?
@@ -3866,7 +4074,7 @@
// No. Let's create one.
TestCase* const new_test_case =
- new TestCase(test_case_name, comment, set_up_tc, tear_down_tc);
+ new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc);
// Is this a death test case?
if (internal::UnitTestOptions::MatchesFilter(String(test_case_name),
@@ -3893,27 +4101,26 @@
static void TearDownEnvironment(Environment* env) { env->TearDown(); }
// Runs all tests in this UnitTest object, prints the result, and
-// returns 0 if all tests are successful, or 1 otherwise. If any
-// exception is thrown during a test on Windows, this test is
-// considered to be failed, but the rest of the tests will still be
-// run. (We disable exceptions on Linux and Mac OS X, so the issue
-// doesn't apply there.)
+// returns true if all tests are successful. If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
// When parameterized tests are enabled, it expands and registers
// parameterized tests first in RegisterParameterizedTests().
// All other functions called from RunAllTests() may safely assume that
// parameterized tests are ready to be counted and run.
-int UnitTestImpl::RunAllTests() {
+bool UnitTestImpl::RunAllTests() {
// Makes sure InitGoogleTest() was called.
if (!GTestIsInitialized()) {
printf("%s",
"\nThis test program did NOT call ::testing::InitGoogleTest "
"before calling RUN_ALL_TESTS(). Please fix it.\n");
- return 1;
+ return false;
}
// Do not run any test if the --help flag was specified.
if (g_help_flag)
- return 0;
+ return true;
// Repeats the call to the post-flag parsing initialization in case the
// user didn't call InitGoogleTest.
@@ -3945,7 +4152,7 @@
if (GTEST_FLAG(list_tests)) {
// This must be called *after* FilterTests() has been called.
ListTestsMatchingFilter();
- return 0;
+ return true;
}
random_seed_ = GTEST_FLAG(shuffle) ?
@@ -3964,7 +4171,9 @@
// Repeats forever if the repeat count is negative.
const bool forever = repeat < 0;
for (int i = 0; forever || i != repeat; i++) {
- ClearResult();
+ // We want to preserve failures generated by ad-hoc test
+ // assertions executed before RUN_ALL_TESTS().
+ ClearNonAdHocTestResult();
const TimeInMillis start = GetTimeInMillis();
@@ -4029,8 +4238,7 @@
repeater->OnTestProgramEnd(*parent_);
- // Returns 0 if all tests passed, or 1 other wise.
- return failed ? 1 : 0;
+ return !failed;
}
// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
@@ -4104,7 +4312,7 @@
// Parses the environment variable var as an Int32. If it is unset,
// returns default_val. If it is not an Int32, prints an error
// and aborts.
-Int32 Int32FromEnvOrDie(const char* const var, Int32 default_val) {
+Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
const char* str_val = posix::GetEnv(var);
if (str_val == NULL) {
return default_val;
@@ -4160,12 +4368,12 @@
kDisableTestFilter) ||
internal::UnitTestOptions::MatchesFilter(test_name,
kDisableTestFilter);
- test_info->impl()->set_is_disabled(is_disabled);
+ test_info->is_disabled_ = is_disabled;
const bool matches_filter =
internal::UnitTestOptions::FilterMatchesTest(test_case_name,
test_name);
- test_info->impl()->set_matches_filter(matches_filter);
+ test_info->matches_filter_ = matches_filter;
const bool is_runnable =
(GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
@@ -4179,7 +4387,7 @@
num_runnable_tests += is_runnable;
num_selected_tests += is_selected;
- test_info->impl()->set_should_run(is_selected);
+ test_info->should_run_ = is_selected;
test_case->set_should_run(test_case->should_run() || is_selected);
}
}
@@ -4195,7 +4403,7 @@
for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
const TestInfo* const test_info =
test_case->test_info_list()[j];
- if (test_info->matches_filter()) {
+ if (test_info->matches_filter_) {
if (!printed_test_case_name) {
printed_test_case_name = true;
printf("%s.\n", test_case->name());
@@ -4235,7 +4443,7 @@
// the TestResult for the ad hoc test if no test is running.
TestResult* UnitTestImpl::current_test_result() {
return current_test_info_ ?
- current_test_info_->impl()->result() : &ad_hoc_test_result_;
+ &(current_test_info_->result_) : &ad_hoc_test_result_;
}
// Shuffles all test cases, and the tests within each test case,
@@ -4264,32 +4472,6 @@
}
}
-// TestInfoImpl constructor. The new instance assumes ownership of the test
-// factory object.
-TestInfoImpl::TestInfoImpl(TestInfo* parent,
- const char* a_test_case_name,
- const char* a_name,
- const char* a_test_case_comment,
- const char* a_comment,
- TypeId a_fixture_class_id,
- internal::TestFactoryBase* factory) :
- parent_(parent),
- test_case_name_(String(a_test_case_name)),
- name_(String(a_name)),
- test_case_comment_(String(a_test_case_comment)),
- comment_(String(a_comment)),
- fixture_class_id_(a_fixture_class_id),
- should_run_(false),
- is_disabled_(false),
- matches_filter_(false),
- factory_(factory) {
-}
-
-// TestInfoImpl destructor.
-TestInfoImpl::~TestInfoImpl() {
- delete factory_;
-}
-
// Returns the current OS stack trace as a String.
//
// The maximum number of stack frames to be included is specified by
@@ -4307,8 +4489,8 @@
return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
}
-// Used by the GTEST_HIDE_UNREACHABLE_CODE_ macro to suppress unreachable
-// code warnings.
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
namespace {
class ClassUniqueToAlwaysTrue {};
}
@@ -4520,6 +4702,10 @@
GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
" Generate an XML report in the given directory or with the given file\n"
" name. @YFILE_PATH at D defaults to @Gtest_details.xml at D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST at G:@YPORT at D\n"
+" Stream test results to the given server.\n"
+#endif // GTEST_CAN_STREAM_RESULTS_
"\n"
"Assertion Behavior:\n"
#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
@@ -4530,10 +4716,9 @@
" Turn assertion failures into debugger break-points.\n"
" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure at D\n"
" Turn assertion failures into C++ exceptions.\n"
-#if GTEST_OS_WINDOWS
-" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions at D\n"
-" Suppress pop-ups caused by exceptions.\n"
-#endif // GTEST_OS_WINDOWS
+" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0 at D\n"
+" Do not report exceptions as test failures. Instead, allow them\n"
+" to crash the program or throw a pop-up (on Windows).\n"
"\n"
"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests at D, you can alternatively set "
"the corresponding\n"
@@ -4583,7 +4768,10 @@
ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) ||
ParseInt32Flag(arg, kStackTraceDepthFlag,
>EST_FLAG(stack_trace_depth)) ||
- ParseBoolFlag(arg, kThrowOnFailureFlag, >EST_FLAG(throw_on_failure))
+ ParseStringFlag(arg, kStreamResultToFlag,
+ >EST_FLAG(stream_result_to)) ||
+ ParseBoolFlag(arg, kThrowOnFailureFlag,
+ >EST_FLAG(throw_on_failure))
) {
// Yes. Shift the remainder of the argv list left by one. Note
// that argv has (*argc + 1) elements, the last one always being
@@ -4641,10 +4829,12 @@
internal::g_executable_path = internal::StreamableToString(argv[0]);
#if GTEST_HAS_DEATH_TEST
+
g_argvs.clear();
for (int i = 0; i != *argc; i++) {
g_argvs.push_back(StreamableToString(argv[i]));
}
+
#endif // GTEST_HAS_DEATH_TEST
ParseGoogleTestFlagsOnly(argc, argv);
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-death-test.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-death-test.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-death-test.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-death-test.h Wed Jul 27 13:40:48 2011
@@ -38,7 +38,7 @@
#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
-#include <gtest/internal/gtest-death-test-internal.h>
+#include "gtest/internal/gtest-death-test-internal.h"
namespace testing {
@@ -154,24 +154,24 @@
// Asserts that a given statement causes the program to exit, with an
// integer exit status that satisfies predicate, and emitting error output
// that matches regex.
-#define ASSERT_EXIT(statement, predicate, regex) \
- GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
+# define ASSERT_EXIT(statement, predicate, regex) \
+ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
// Like ASSERT_EXIT, but continues on to successive tests in the
// test case, if any:
-#define EXPECT_EXIT(statement, predicate, regex) \
- GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
+# define EXPECT_EXIT(statement, predicate, regex) \
+ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
// Asserts that a given statement causes the program to exit, either by
// explicitly exiting with a nonzero exit code or being killed by a
// signal, and emitting error output that matches regex.
-#define ASSERT_DEATH(statement, regex) \
- ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+# define ASSERT_DEATH(statement, regex) \
+ ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
// Like ASSERT_DEATH, but continues on to successive tests in the
// test case, if any:
-#define EXPECT_DEATH(statement, regex) \
- EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+# define EXPECT_DEATH(statement, regex) \
+ EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
@@ -187,7 +187,7 @@
const int exit_code_;
};
-#if !GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS
// Tests that an exit code describes an exit due to termination by a
// given signal.
class GTEST_API_ KilledBySignal {
@@ -197,7 +197,7 @@
private:
const int signum_;
};
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
// The death testing framework causes this to have interesting semantics,
@@ -242,23 +242,23 @@
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
// }, "death");
//
-#ifdef NDEBUG
+# ifdef NDEBUG
-#define EXPECT_DEBUG_DEATH(statement, regex) \
+# define EXPECT_DEBUG_DEATH(statement, regex) \
do { statement; } while (::testing::internal::AlwaysFalse())
-#define ASSERT_DEBUG_DEATH(statement, regex) \
+# define ASSERT_DEBUG_DEATH(statement, regex) \
do { statement; } while (::testing::internal::AlwaysFalse())
-#else
+# else
-#define EXPECT_DEBUG_DEATH(statement, regex) \
+# define EXPECT_DEBUG_DEATH(statement, regex) \
EXPECT_DEATH(statement, regex)
-#define ASSERT_DEBUG_DEATH(statement, regex) \
+# define ASSERT_DEBUG_DEATH(statement, regex) \
ASSERT_DEATH(statement, regex)
-#endif // NDEBUG for EXPECT_DEBUG_DEATH
+# endif // NDEBUG for EXPECT_DEBUG_DEATH
#endif // GTEST_HAS_DEATH_TEST
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
@@ -267,14 +267,14 @@
// useful when you are combining death test assertions with normal test
// assertions in one test.
#if GTEST_HAS_DEATH_TEST
-#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
EXPECT_DEATH(statement, regex)
-#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
ASSERT_DEATH(statement, regex)
#else
-#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
-#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
#endif
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-message.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-message.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-message.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-message.h Wed Jul 27 13:40:48 2011
@@ -48,8 +48,8 @@
#include <limits>
-#include <gtest/internal/gtest-string.h>
-#include <gtest/internal/gtest-internal.h>
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-internal.h"
namespace testing {
@@ -58,7 +58,7 @@
// Typical usage:
//
// 1. You stream a bunch of values to a Message object.
-// It will remember the text in a StrStream.
+// It will remember the text in a stringstream.
// 2. Then you stream the Message object to an ostream.
// This causes the text in the Message to be streamed
// to the ostream.
@@ -74,7 +74,7 @@
// Message is not intended to be inherited from. In particular, its
// destructor is not virtual.
//
-// Note that StrStream behaves differently in gcc and in MSVC. You
+// Note that stringstream behaves differently in gcc and in MSVC. You
// can stream a NULL char pointer to it in the former, but not in the
// latter (it causes an access violation if you do). The Message
// class hides this difference by treating a NULL char pointer as
@@ -87,27 +87,26 @@
public:
// Constructs an empty Message.
- // We allocate the StrStream separately because it otherwise each use of
+ // We allocate the stringstream separately because otherwise each use of
// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
// stack frame leading to huge stack frames in some cases; gcc does not reuse
// the stack space.
- Message() : ss_(new internal::StrStream) {
+ Message() : ss_(new ::std::stringstream) {
// By default, we want there to be enough precision when printing
// a double to a Message.
*ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
}
// Copy constructor.
- Message(const Message& msg) : ss_(new internal::StrStream) { // NOLINT
+ Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
*ss_ << msg.GetString();
}
// Constructs a Message from a C-string.
- explicit Message(const char* str) : ss_(new internal::StrStream) {
+ explicit Message(const char* str) : ss_(new ::std::stringstream) {
*ss_ << str;
}
- ~Message() { delete ss_; }
#if GTEST_OS_SYMBIAN
// Streams a value (either a pointer or not) to this object.
template <typename T>
@@ -119,7 +118,7 @@
// Streams a non-pointer value to this object.
template <typename T>
inline Message& operator <<(const T& val) {
- ::GTestStreamToHelper(ss_, val);
+ ::GTestStreamToHelper(ss_.get(), val);
return *this;
}
@@ -141,7 +140,7 @@
if (pointer == NULL) {
*ss_ << "(null)";
} else {
- ::GTestStreamToHelper(ss_, pointer);
+ ::GTestStreamToHelper(ss_.get(), pointer);
}
return *this;
}
@@ -189,10 +188,11 @@
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
internal::String GetString() const {
- return internal::StrStreamToString(ss_);
+ return internal::StringStreamToString(ss_.get());
}
private:
+
#if GTEST_OS_SYMBIAN
// These are needed as the Nokia Symbian Compiler cannot decide between
// const T& and const T* in a function template. The Nokia compiler _can_
@@ -203,17 +203,17 @@
if (pointer == NULL) {
*ss_ << "(null)";
} else {
- ::GTestStreamToHelper(ss_, pointer);
+ ::GTestStreamToHelper(ss_.get(), pointer);
}
}
template <typename T>
inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
- ::GTestStreamToHelper(ss_, value);
+ ::GTestStreamToHelper(ss_.get(), value);
}
#endif // GTEST_OS_SYMBIAN
// We'll hold the text streamed to this object here.
- internal::StrStream* const ss_;
+ const internal::scoped_ptr< ::std::stringstream> ss_;
// We declare (but don't implement) this to prevent the compiler
// from implementing the assignment operator.
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-param-test.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-param-test.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-param-test.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-param-test.h Wed Jul 27 13:40:48 2011
@@ -1,4 +1,6 @@
-// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+// This file was GENERATED by command:
+// pump.py gtest-param-test.h.pump
+// DO NOT EDIT BY HAND!!!
// Copyright 2008, Google Inc.
// All rights reserved.
@@ -48,10 +50,12 @@
#if 0
// To write value-parameterized tests, first you should define a fixture
-// class. It must be derived from testing::TestWithParam<T>, where T is
-// the type of your parameter values. TestWithParam<T> is itself derived
-// from testing::Test. T can be any copyable type. If it's a raw pointer,
-// you are responsible for managing the lifespan of the pointed values.
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
class FooTest : public ::testing::TestWithParam<const char*> {
// You can implement all the usual class fixture members here.
@@ -146,20 +150,46 @@
// In the future, we plan to publish the API for defining new parameter
// generators. But for now this interface remains part of the internal
// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+ // You can inherit all the usual members for a non-parameterized test
+ // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+ // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+ // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+ // GetParam works just the same here as if you inherit from TestWithParam.
+ EXPECT_TRUE(foo.Blah(GetParam()));
+}
#endif // 0
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#if !GTEST_OS_SYMBIAN
-#include <utility>
+# include <utility>
#endif
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-param-util.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
#if GTEST_HAS_PARAM_TEST
@@ -275,11 +305,10 @@
//
template <typename ForwardIterator>
internal::ParamGenerator<
- typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
- ForwardIterator begin,
- ForwardIterator end) {
- typedef typename ::std::iterator_traits<ForwardIterator>::value_type
- ParamType;
+ typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+ typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+ ::value_type ParamType;
return internal::ParamGenerator<ParamType>(
new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
}
@@ -1197,7 +1226,7 @@
return Values(false, true);
}
-#if GTEST_HAS_COMBINE
+# if GTEST_HAS_COMBINE
// Combine() allows the user to combine two or more sequences to produce
// values of a Cartesian product of those sequences' elements.
//
@@ -1349,11 +1378,11 @@
Generator10>(
g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
}
-#endif // GTEST_HAS_COMBINE
+# endif // GTEST_HAS_COMBINE
-#define TEST_P(test_case_name, test_name) \
+# define TEST_P(test_case_name, test_name) \
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
: public test_case_name { \
public: \
@@ -1379,7 +1408,7 @@
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
-#define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
::testing::internal::ParamGenerator<test_case_name::ParamType> \
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
int gtest_##prefix##test_case_name##_dummy_ = \
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-spi.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-spi.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-spi.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-spi.h Wed Jul 27 13:40:48 2011
@@ -35,7 +35,7 @@
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
namespace testing {
@@ -98,12 +98,12 @@
// The constructor remembers the arguments.
SingleFailureChecker(const TestPartResultArray* results,
TestPartResult::Type type,
- const char* substr);
+ const string& substr);
~SingleFailureChecker();
private:
const TestPartResultArray* const results_;
const TestPartResult::Type type_;
- const String substr_;
+ const string substr_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
};
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-test-part.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-test-part.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-test-part.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-test-part.h Wed Jul 27 13:40:48 2011
@@ -35,8 +35,8 @@
#include <iosfwd>
#include <vector>
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-string.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
namespace testing {
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-typed-test.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-typed-test.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-typed-test.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest-typed-test.h Wed Jul 27 13:40:48 2011
@@ -146,8 +146,8 @@
#endif // 0
-#include <gtest/internal/gtest-port.h>
-#include <gtest/internal/gtest-type-util.h>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-type-util.h"
// Implements typed tests.
@@ -157,16 +157,16 @@
//
// Expands to the name of the typedef for the type parameters of the
// given test case.
-#define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
+# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
// The 'Types' template argument below must have spaces around it
// since some compilers may choke on '>>' when passing a template
// instance (e.g. Types<int>)
-#define TYPED_TEST_CASE(CaseName, Types) \
+# define TYPED_TEST_CASE(CaseName, Types) \
typedef ::testing::internal::TypeList< Types >::type \
GTEST_TYPE_PARAMS_(CaseName)
-#define TYPED_TEST(CaseName, TestName) \
+# define TYPED_TEST(CaseName, TestName) \
template <typename gtest_TypeParam_> \
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
: public CaseName<gtest_TypeParam_> { \
@@ -175,7 +175,7 @@
typedef gtest_TypeParam_ TypeParam; \
virtual void TestBody(); \
}; \
- bool gtest_##CaseName##_##TestName##_registered_ = \
+ bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
::testing::internal::TypeParameterizedTest< \
CaseName, \
::testing::internal::TemplateSel< \
@@ -196,31 +196,31 @@
// Expands to the namespace name that the type-parameterized tests for
// the given type-parameterized test case are defined in. The exact
// name of the namespace is subject to change without notice.
-#define GTEST_CASE_NAMESPACE_(TestCaseName) \
+# define GTEST_CASE_NAMESPACE_(TestCaseName) \
gtest_case_##TestCaseName##_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Expands to the name of the variable used to remember the names of
// the defined tests in the given test case.
-#define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
+# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
gtest_typed_test_case_p_state_##TestCaseName##_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
//
// Expands to the name of the variable used to remember the names of
// the registered tests in the given test case.
-#define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
+# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
gtest_registered_test_names_##TestCaseName##_
// The variables defined in the type-parameterized test macros are
// static as typically these macros are used in a .h file that can be
// #included in multiple translation units linked together.
-#define TYPED_TEST_CASE_P(CaseName) \
+# define TYPED_TEST_CASE_P(CaseName) \
static ::testing::internal::TypedTestCasePState \
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
-#define TYPED_TEST_P(CaseName, TestName) \
+# define TYPED_TEST_P(CaseName, TestName) \
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
template <typename gtest_TypeParam_> \
class TestName : public CaseName<gtest_TypeParam_> { \
@@ -229,14 +229,14 @@
typedef gtest_TypeParam_ TypeParam; \
virtual void TestBody(); \
}; \
- static bool gtest_##TestName##_defined_ = \
+ static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
__FILE__, __LINE__, #CaseName, #TestName); \
} \
template <typename gtest_TypeParam_> \
void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
-#define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
} \
@@ -247,8 +247,8 @@
// The 'Types' template argument below must have spaces around it
// since some compilers may choke on '>>' when passing a template
// instance (e.g. Types<int>)
-#define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
- bool gtest_##Prefix##_##CaseName = \
+# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
+ bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
::testing::internal::TypeParameterizedTestCase<CaseName, \
GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
::testing::internal::TypeList< Types >::type>::Register(\
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest.h Wed Jul 27 13:40:48 2011
@@ -54,14 +54,15 @@
#include <limits>
#include <vector>
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-string.h>
-#include <gtest/gtest-death-test.h>
-#include <gtest/gtest-message.h>
-#include <gtest/gtest-param-test.h>
-#include <gtest/gtest_prod.h>
-#include <gtest/gtest-test-part.h>
-#include <gtest/gtest-typed-test.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest-message.h"
+#include "gtest/gtest-param-test.h"
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest_prod.h"
+#include "gtest/gtest-test-part.h"
+#include "gtest/gtest-typed-test.h"
// Depending on the platform, different string classes are available.
// On Linux, in addition to ::std::string, Google also makes use of
@@ -136,6 +137,11 @@
// non-zero code otherwise.
GTEST_DECLARE_bool_(throw_on_failure);
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
// The upper limit for valid stack trace depths.
const int kMaxStackTraceDepth = 100;
@@ -147,7 +153,6 @@
class NoExecDeathTest;
class FinalSuccessChecker;
class GTestFlagSaver;
-class TestInfoImpl;
class TestResultAccessor;
class TestEventListenersAccessor;
class TestEventRepeater;
@@ -155,8 +160,6 @@
class UnitTestImpl* GetUnitTestImpl();
void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
const String& message);
-class PrettyUnitTestResultPrinter;
-class XmlUnitTestResultPrinter;
// Converts a streamable value to a String. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
@@ -172,6 +175,14 @@
} // namespace internal
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestCase;
+class TestInfo;
+class UnitTest;
+
// A class for indicating whether an assertion was successful. When
// the assertion wasn't successful, the AssertionResult object
// remembers a non-empty message that describes how it failed.
@@ -270,20 +281,33 @@
// assertion's expectation). When nothing has been streamed into the
// object, returns an empty string.
const char* message() const {
- return message_.get() != NULL && message_->c_str() != NULL ?
- message_->c_str() : "";
+ return message_.get() != NULL ? message_->c_str() : "";
}
// TODO(vladl at google.com): Remove this after making sure no clients use it.
// Deprecated; please use message() instead.
const char* failure_message() const { return message(); }
// Streams a custom failure message into this object.
- template <typename T> AssertionResult& operator<<(const T& value);
+ template <typename T> AssertionResult& operator<<(const T& value) {
+ AppendMessage(Message() << value);
+ return *this;
+ }
+
+ // Allows streaming basic output manipulators such as endl or flush into
+ // this object.
+ AssertionResult& operator<<(
+ ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+ AppendMessage(Message() << basic_manipulator);
+ return *this;
+ }
private:
- // No implementation - we want AssertionResult to be
- // copy-constructible but not assignable.
- void operator=(const AssertionResult& other);
+ // Appends the contents of message to message_.
+ void AppendMessage(const Message& a_message) {
+ if (message_.get() == NULL)
+ message_.reset(new ::std::string);
+ message_->append(a_message.GetString().c_str());
+ }
// Stores result of the assertion predicate.
bool success_;
@@ -291,19 +315,10 @@
// construct is not satisfied with the predicate's outcome.
// Referenced via a pointer to avoid taking too much stack frame space
// with test assertions.
- internal::scoped_ptr<internal::String> message_;
-}; // class AssertionResult
+ internal::scoped_ptr< ::std::string> message_;
-// Streams a custom failure message into this object.
-template <typename T>
-AssertionResult& AssertionResult::operator<<(const T& value) {
- Message msg;
- if (message_.get() != NULL)
- msg << *message_;
- msg << value;
- message_.reset(new internal::String(msg.GetString()));
- return *this;
-}
+ GTEST_DISALLOW_ASSIGN_(AssertionResult);
+};
// Makes a successful assertion result.
GTEST_API_ AssertionResult AssertionSuccess();
@@ -340,7 +355,7 @@
// Test is not copyable.
class GTEST_API_ Test {
public:
- friend class internal::TestInfoImpl;
+ friend class TestInfo;
// Defines types for pointers to functions that set up and tear down
// a test case.
@@ -417,6 +432,10 @@
// Sets up, executes, and tears down the test.
void Run();
+ // Deletes self. We deliberately pick an unusual name for this
+ // internal method to avoid clashing with names used in user TESTs.
+ void DeleteSelf_() { delete this; }
+
// Uses a GTestFlagSaver to save and restore all Google Test flags.
const internal::GTestFlagSaver* const gtest_flag_saver_;
@@ -531,7 +550,6 @@
friend class UnitTest;
friend class internal::DefaultGlobalTestPartResultReporter;
friend class internal::ExecDeathTest;
- friend class internal::TestInfoImpl;
friend class internal::TestResultAccessor;
friend class internal::UnitTestImpl;
friend class internal::WindowsDeathTest;
@@ -611,16 +629,26 @@
~TestInfo();
// Returns the test case name.
- const char* test_case_name() const;
+ const char* test_case_name() const { return test_case_name_.c_str(); }
// Returns the test name.
- const char* name() const;
+ const char* name() const { return name_.c_str(); }
- // Returns the test case comment.
- const char* test_case_comment() const;
+ // Returns the name of the parameter type, or NULL if this is not a typed
+ // or a type-parameterized test.
+ const char* type_param() const {
+ if (type_param_.get() != NULL)
+ return type_param_->c_str();
+ return NULL;
+ }
- // Returns the test comment.
- const char* comment() const;
+ // Returns the text representation of the value parameter, or NULL if this
+ // is not a value-parameterized test.
+ const char* value_param() const {
+ if (value_param_.get() != NULL)
+ return value_param_->c_str();
+ return NULL;
+ }
// Returns true if this test should run, that is if the test is not disabled
// (or it is disabled but the also_run_disabled_tests flag has been specified)
@@ -638,47 +666,70 @@
//
// For example, *A*:Foo.* is a filter that matches any string that
// contains the character 'A' or starts with "Foo.".
- bool should_run() const;
+ bool should_run() const { return should_run_; }
// Returns the result of the test.
- const TestResult* result() const;
+ const TestResult* result() const { return &result_; }
private:
+
#if GTEST_HAS_DEATH_TEST
friend class internal::DefaultDeathTestFactory;
#endif // GTEST_HAS_DEATH_TEST
friend class Test;
friend class TestCase;
- friend class internal::TestInfoImpl;
friend class internal::UnitTestImpl;
friend TestInfo* internal::MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* type_param,
+ const char* value_param,
internal::TypeId fixture_class_id,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc,
internal::TestFactoryBase* factory);
- // Returns true if this test matches the user-specified filter.
- bool matches_filter() const;
-
- // Increments the number of death tests encountered in this test so
- // far.
- int increment_death_test_count();
-
- // Accessors for the implementation object.
- internal::TestInfoImpl* impl() { return impl_; }
- const internal::TestInfoImpl* impl() const { return impl_; }
-
// Constructs a TestInfo object. The newly constructed instance assumes
// ownership of the factory object.
TestInfo(const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* a_type_param,
+ const char* a_value_param,
internal::TypeId fixture_class_id,
internal::TestFactoryBase* factory);
- // An opaque implementation object.
- internal::TestInfoImpl* impl_;
+ // Increments the number of death tests encountered in this test so
+ // far.
+ int increment_death_test_count() {
+ return result_.increment_death_test_count();
+ }
+
+ // Creates the test object, runs it, records its result, and then
+ // deletes it.
+ void Run();
+
+ static void ClearTestResult(TestInfo* test_info) {
+ test_info->result_.Clear();
+ }
+
+ // These fields are immutable properties of the test.
+ const std::string test_case_name_; // Test case name
+ const std::string name_; // Test name
+ // Name of the parameter type, or NULL if this is not a typed or a
+ // type-parameterized test.
+ const internal::scoped_ptr<const ::std::string> type_param_;
+ // Text representation of the value parameter, or NULL if this is not a
+ // value-parameterized test.
+ const internal::scoped_ptr<const ::std::string> value_param_;
+ const internal::TypeId fixture_class_id_; // ID of the test fixture class
+ bool should_run_; // True iff this test should run
+ bool is_disabled_; // True iff this test is disabled
+ bool matches_filter_; // True if this test matches the
+ // user-specified filter.
+ internal::TestFactoryBase* const factory_; // The factory that creates
+ // the test object
+
+ // This field is mutable and needs to be reset before running the
+ // test for the second time.
+ TestResult result_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
};
@@ -696,9 +747,11 @@
// Arguments:
//
// name: name of the test case
+ // a_type_param: the name of the test's type parameter, or NULL if
+ // this is not a type-parameterized test.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
- TestCase(const char* name, const char* comment,
+ TestCase(const char* name, const char* a_type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc);
@@ -708,8 +761,13 @@
// Gets the name of the TestCase.
const char* name() const { return name_.c_str(); }
- // Returns the test case comment.
- const char* comment() const { return comment_.c_str(); }
+ // Returns the name of the parameter type, or NULL if this is not a
+ // type-parameterized test case.
+ const char* type_param() const {
+ if (type_param_.get() != NULL)
+ return type_param_->c_str();
+ return NULL;
+ }
// Returns true if any test in this test case should run.
bool should_run() const { return should_run_; }
@@ -776,17 +834,33 @@
// Runs every test in this TestCase.
void Run();
+ // Runs SetUpTestCase() for this TestCase. This wrapper is needed
+ // for catching exceptions thrown from SetUpTestCase().
+ void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+ // Runs TearDownTestCase() for this TestCase. This wrapper is
+ // needed for catching exceptions thrown from TearDownTestCase().
+ void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
// Returns true iff test passed.
- static bool TestPassed(const TestInfo * test_info);
+ static bool TestPassed(const TestInfo* test_info) {
+ return test_info->should_run() && test_info->result()->Passed();
+ }
// Returns true iff test failed.
- static bool TestFailed(const TestInfo * test_info);
+ static bool TestFailed(const TestInfo* test_info) {
+ return test_info->should_run() && test_info->result()->Failed();
+ }
// Returns true iff test is disabled.
- static bool TestDisabled(const TestInfo * test_info);
+ static bool TestDisabled(const TestInfo* test_info) {
+ return test_info->is_disabled_;
+ }
// Returns true if the given test should run.
- static bool ShouldRunTest(const TestInfo *test_info);
+ static bool ShouldRunTest(const TestInfo* test_info) {
+ return test_info->should_run();
+ }
// Shuffles the tests in this test case.
void ShuffleTests(internal::Random* random);
@@ -796,8 +870,9 @@
// Name of the test case.
internal::String name_;
- // Comment on the test case.
- internal::String comment_;
+ // Name of the parameter type, or NULL if this is not a typed or a
+ // type-parameterized test.
+ const internal::scoped_ptr<const ::std::string> type_param_;
// The vector of TestInfos in their original order. It owns the
// elements in the vector.
std::vector<TestInfo*> test_info_list_;
@@ -876,7 +951,7 @@
// Fired before the test starts.
virtual void OnTestStart(const TestInfo& test_info) = 0;
- // Fired after a failed assertion or a SUCCESS().
+ // Fired after a failed assertion or a SUCCEED() invocation.
virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
// Fired after the test ends.
@@ -961,10 +1036,10 @@
private:
friend class TestCase;
+ friend class TestInfo;
friend class internal::DefaultGlobalTestPartResultReporter;
friend class internal::NoExecDeathTest;
friend class internal::TestEventListenersAccessor;
- friend class internal::TestInfoImpl;
friend class internal::UnitTestImpl;
// Returns repeater that broadcasts the TestEventListener events to all
@@ -1206,30 +1281,6 @@
namespace internal {
-// These overloaded versions handle ::std::string and ::std::wstring.
-GTEST_API_ inline String FormatForFailureMessage(const ::std::string& str) {
- return (Message() << '"' << str << '"').GetString();
-}
-
-#if GTEST_HAS_STD_WSTRING
-GTEST_API_ inline String FormatForFailureMessage(const ::std::wstring& wstr) {
- return (Message() << "L\"" << wstr << '"').GetString();
-}
-#endif // GTEST_HAS_STD_WSTRING
-
-// These overloaded versions handle ::string and ::wstring.
-#if GTEST_HAS_GLOBAL_STRING
-GTEST_API_ inline String FormatForFailureMessage(const ::string& str) {
- return (Message() << '"' << str << '"').GetString();
-}
-#endif // GTEST_HAS_GLOBAL_STRING
-
-#if GTEST_HAS_GLOBAL_WSTRING
-GTEST_API_ inline String FormatForFailureMessage(const ::wstring& wstr) {
- return (Message() << "L\"" << wstr << '"').GetString();
-}
-#endif // GTEST_HAS_GLOBAL_WSTRING
-
// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
// operand to be used in a failure message. The type (but not value)
// of the other operand may affect the format. This allows us to
@@ -1245,7 +1296,9 @@
template <typename T1, typename T2>
String FormatForComparisonFailureMessage(const T1& value,
const T2& /* other_operand */) {
- return FormatForFailureMessage(value);
+ // C++Builder compiles this incorrectly if the namespace isn't explicitly
+ // given.
+ return ::testing::PrintToString(value);
}
// The helper function for {ASSERT|EXPECT}_EQ.
@@ -1255,8 +1308,8 @@
const T1& expected,
const T2& actual) {
#ifdef _MSC_VER
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4389) // Temporarily disables warning on
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4389) // Temporarily disables warning on
// signed/unsigned mismatch.
#pragma warning(disable:4805) // Temporarily disables warning on
// unsafe mix of types
@@ -1267,7 +1320,7 @@
}
#ifdef _MSC_VER
-#pragma warning(pop) // Restores the warning state.
+# pragma warning(pop) // Restores the warning state.
#endif
return EqFailure(expected_expression,
@@ -1318,7 +1371,7 @@
};
// This specialization is used when the first argument to ASSERT_EQ()
-// is a null pointer literal.
+// is a null pointer literal, like NULL, false, or 0.
template <>
class EqHelper<true> {
public:
@@ -1327,24 +1380,38 @@
// NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or
// EXPECT_EQ(false, a_bool).
template <typename T1, typename T2>
- static AssertionResult Compare(const char* expected_expression,
- const char* actual_expression,
- const T1& expected,
- const T2& actual) {
+ static AssertionResult Compare(
+ const char* expected_expression,
+ const char* actual_expression,
+ const T1& expected,
+ const T2& actual,
+ // The following line prevents this overload from being considered if T2
+ // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr)
+ // expands to Compare("", "", NULL, my_ptr), which requires a conversion
+ // to match the Secret* in the other overload, which would otherwise make
+ // this template match better.
+ typename EnableIf<!is_pointer<T2>::value>::type* = 0) {
return CmpHelperEQ(expected_expression, actual_expression, expected,
actual);
}
- // This version will be picked when the second argument to
- // ASSERT_EQ() is a pointer, e.g. ASSERT_EQ(NULL, a_pointer).
- template <typename T1, typename T2>
- static AssertionResult Compare(const char* expected_expression,
- const char* actual_expression,
- const T1& /* expected */,
- T2* actual) {
+ // This version will be picked when the second argument to ASSERT_EQ() is a
+ // pointer, e.g. ASSERT_EQ(NULL, a_pointer).
+ template <typename T>
+ static AssertionResult Compare(
+ const char* expected_expression,
+ const char* actual_expression,
+ // We used to have a second template parameter instead of Secret*. That
+ // template parameter would deduce to 'long', making this a better match
+ // than the first overload even without the first overload's EnableIf.
+ // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to
+ // non-pointer argument" (even a deduced integral argument), so the old
+ // implementation caused warnings in user code.
+ Secret* /* expected (NULL) */,
+ T* actual) {
// We already know that 'expected' is a null pointer.
return CmpHelperEQ(expected_expression, actual_expression,
- static_cast<T2*>(NULL), actual);
+ static_cast<T*>(NULL), actual);
}
};
@@ -1365,11 +1432,10 @@
if (val1 op val2) {\
return AssertionSuccess();\
} else {\
- Message msg;\
- msg << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ return AssertionFailure() \
+ << "Expected: (" << expr1 << ") " #op " (" << expr2\
<< "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
<< " vs " << FormatForComparisonFailureMessage(val2, val1);\
- return AssertionFailure(msg);\
}\
}\
GTEST_API_ AssertionResult CmpHelper##op_name(\
@@ -1497,18 +1563,18 @@
return AssertionSuccess();
}
- StrStream expected_ss;
+ ::std::stringstream expected_ss;
expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< expected;
- StrStream actual_ss;
+ ::std::stringstream actual_ss;
actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< actual;
return EqFailure(expected_expression,
actual_expression,
- StrStreamToString(&expected_ss),
- StrStreamToString(&actual_ss),
+ StringStreamToString(&expected_ss),
+ StringStreamToString(&actual_ss),
false);
}
@@ -1566,9 +1632,13 @@
} // namespace internal
#if GTEST_HAS_PARAM_TEST
-// The abstract base class that all value-parameterized tests inherit from.
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
//
-// This class adds support for accessing the test parameter value via
+// This interface has support for accessing the test parameter value via
// the GetParam() method.
//
// Use it with one of the parameter generator defining functions, like Range(),
@@ -1597,12 +1667,16 @@
// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
template <typename T>
-class TestWithParam : public Test {
+class WithParamInterface {
public:
typedef T ParamType;
+ virtual ~WithParamInterface() {}
// The current parameter value. Is also available in the test fixture's
- // constructor.
+ // constructor. This member function is non-static, even though it only
+ // references static data, to reduce the opportunity for incorrect uses
+ // like writing 'WithParamInterface<bool>::GetParam()' for a test that
+ // uses a fixture whose parameter type is int.
const ParamType& GetParam() const { return *parameter_; }
private:
@@ -1615,12 +1689,19 @@
// Static value used for accessing parameter during a test lifetime.
static const ParamType* parameter_;
- // TestClass must be a subclass of TestWithParam<T>.
+ // TestClass must be a subclass of WithParamInterface<T> and Test.
template <class TestClass> friend class internal::ParameterizedTestFactory;
};
template <typename T>
-const T* TestWithParam<T>::parameter_ = NULL;
+const T* WithParamInterface<T>::parameter_ = NULL;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
#endif // GTEST_HAS_PARAM_TEST
@@ -1652,13 +1733,19 @@
// Generates a nonfatal failure with a generic message.
#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+ GTEST_MESSAGE_AT_(file, line, "Failed", \
+ ::testing::TestPartResult::kNonFatalFailure)
+
// Generates a fatal failure with a generic message.
#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
// Define this macro to 1 to omit the definition of FAIL(), which is a
// generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_FAIL
-#define FAIL() GTEST_FAIL()
+# define FAIL() GTEST_FAIL()
#endif
// Generates a success with a generic message.
@@ -1667,7 +1754,7 @@
// Define this macro to 1 to omit the definition of SUCCEED(), which
// is a generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_SUCCEED
-#define SUCCEED() GTEST_SUCCEED()
+# define SUCCEED() GTEST_SUCCEED()
#endif
// Macros for testing exceptions.
@@ -1710,7 +1797,7 @@
// Includes the auto-generated header that implements a family of
// generic predicate assertion macros.
-#include <gtest/gtest_pred_impl.h>
+#include "gtest/gtest_pred_impl.h"
// Macros for testing equalities and inequalities.
//
@@ -1773,21 +1860,48 @@
#define EXPECT_GT(val1, val2) \
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
-#define ASSERT_EQ(expected, actual) \
+#define GTEST_ASSERT_EQ(expected, actual) \
ASSERT_PRED_FORMAT2(::testing::internal:: \
EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
expected, actual)
-#define ASSERT_NE(val1, val2) \
+#define GTEST_ASSERT_NE(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
-#define ASSERT_LE(val1, val2) \
+#define GTEST_ASSERT_LE(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
-#define ASSERT_LT(val1, val2) \
+#define GTEST_ASSERT_LT(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
-#define ASSERT_GE(val1, val2) \
+#define GTEST_ASSERT_GE(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
-#define ASSERT_GT(val1, val2) \
+#define GTEST_ASSERT_GT(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
// C String Comparisons. All tests treat NULL and any non-NULL string
// as different. Two NULLs are equal.
//
@@ -1884,16 +1998,16 @@
// expected result and the actual result with both a human-readable
// string representation of the error, if available, as well as the
// hex result code.
-#define EXPECT_HRESULT_SUCCEEDED(expr) \
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
-#define ASSERT_HRESULT_SUCCEEDED(expr) \
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
-#define EXPECT_HRESULT_FAILED(expr) \
+# define EXPECT_HRESULT_FAILED(expr) \
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
-#define ASSERT_HRESULT_FAILED(expr) \
+# define ASSERT_HRESULT_FAILED(expr) \
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
#endif // GTEST_OS_WINDOWS
@@ -1928,17 +2042,6 @@
::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
__FILE__, __LINE__, ::testing::Message() << (message))
-namespace internal {
-
-// This template is declared, but intentionally undefined.
-template <typename T1, typename T2>
-struct StaticAssertTypeEqHelper;
-
-template <typename T>
-struct StaticAssertTypeEqHelper<T, T> {};
-
-} // namespace internal
-
// Compile-time assertion for type equality.
// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
// the same type. The value it returns is not interesting.
@@ -1971,7 +2074,7 @@
// to cause a compiler error.
template <typename T1, typename T2>
bool StaticAssertTypeEq() {
- internal::StaticAssertTypeEqHelper<T1, T2>();
+ (void)internal::StaticAssertTypeEqHelper<T1, T2>();
return true;
}
@@ -2007,7 +2110,7 @@
// Define this macro to 1 to omit the definition of TEST(), which
// is a generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_TEST
-#define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
+# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
#endif
// Defines a test that uses a test fixture.
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest_pred_impl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest_pred_impl.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest_pred_impl.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/gtest_pred_impl.h Wed Jul 27 13:40:48 2011
@@ -27,7 +27,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// This file is AUTOMATICALLY GENERATED on 10/02/2008 by command
+// This file is AUTOMATICALLY GENERATED on 09/24/2010 by command
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
//
// Implements a family of generic predicate assertion macros.
@@ -37,7 +37,7 @@
// Makes sure this header is not included before gtest.h.
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
-#error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
+# error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
// This header implements a family of generic predicate assertion
@@ -90,11 +90,9 @@
const T1& v1) {
if (pred(v1)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
@@ -136,13 +134,11 @@
const T2& v2) {
if (pred(v1, v2)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
@@ -189,15 +185,13 @@
const T3& v3) {
if (pred(v1, v2, v3)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ", "
- << e3 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2
- << "\n" << e3 << " evaluates to " << v3;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
@@ -249,17 +243,15 @@
const T4& v4) {
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ", "
- << e3 << ", "
- << e4 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2
- << "\n" << e3 << " evaluates to " << v3
- << "\n" << e4 << " evaluates to " << v4;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ", "
+ << e4 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3
+ << "\n" << e4 << " evaluates to " << v4;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
@@ -316,19 +308,17 @@
const T5& v5) {
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ", "
- << e3 << ", "
- << e4 << ", "
- << e5 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2
- << "\n" << e3 << " evaluates to " << v3
- << "\n" << e4 << " evaluates to " << v4
- << "\n" << e5 << " evaluates to " << v5;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ", "
+ << e4 << ", "
+ << e5 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3
+ << "\n" << e4 << " evaluates to " << v4
+ << "\n" << e5 << " evaluates to " << v5;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h Wed Jul 27 13:40:48 2011
@@ -37,7 +37,9 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
-#include <gtest/internal/gtest-internal.h>
+#include "gtest/internal/gtest-internal.h"
+
+#include <stdio.h>
namespace testing {
namespace internal {
@@ -96,8 +98,12 @@
// test, then wait for it to complete.
enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
- // An enumeration of the two reasons that a test might be aborted.
- enum AbortReason { TEST_ENCOUNTERED_RETURN_STATEMENT, TEST_DID_NOT_DIE };
+ // An enumeration of the three reasons that a test might be aborted.
+ enum AbortReason {
+ TEST_ENCOUNTERED_RETURN_STATEMENT,
+ TEST_THREW_EXCEPTION,
+ TEST_DID_NOT_DIE
+ };
// Assumes one of the above roles.
virtual TestRole AssumeRole() = 0;
@@ -149,9 +155,34 @@
// by a signal, or exited normally with a nonzero exit code.
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } catch (const ::std::exception& gtest_exception) { \
+ fprintf(\
+ stderr, \
+ "\n%s: Caught std::exception-derived exception escaping the " \
+ "death test statement. Exception message: %s\n", \
+ ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+ gtest_exception.what()); \
+ fflush(stderr); \
+ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+ } catch (...) { \
+ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+ }
+
+# else
+# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
// ASSERT_EXIT*, and EXPECT_EXIT*.
-#define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
const ::testing::internal::RE& gtest_regex = (regex); \
@@ -172,10 +203,12 @@
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
::testing::internal::DeathTest::ReturnSentinel \
gtest_sentinel(gtest_dt); \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
break; \
} \
+ default: \
+ break; \
} \
} \
} else \
@@ -254,7 +287,7 @@
// statement unconditionally returns or throws. The Message constructor at
// the end allows the syntax of streaming additional messages into the
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
-#define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
+# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_LOG_(WARNING) \
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h Wed Jul 27 13:40:48 2011
@@ -40,7 +40,7 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
-#include <gtest/internal/gtest-string.h>
+#include "gtest/internal/gtest-string.h"
namespace testing {
namespace internal {
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h Wed Jul 27 13:40:48 2011
@@ -41,12 +41,12 @@
// part of Google Test's implementation; otherwise it's undefined.
#if !GTEST_IMPLEMENTATION_
// A user is trying to include this from his code - just say no.
-#error "gtest-internal-inl.h is part of Google Test's internal implementation."
-#error "It must not be included except by Google Test itself."
+# error "gtest-internal-inl.h is part of Google Test's internal implementation."
+# error "It must not be included except by Google Test itself."
#endif // GTEST_IMPLEMENTATION_
#ifndef _WIN32_WCE
-#include <errno.h>
+# include <errno.h>
#endif // !_WIN32_WCE
#include <stddef.h>
#include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
@@ -56,14 +56,14 @@
#include <string>
#include <vector>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#if GTEST_OS_WINDOWS
-#include <windows.h> // For DWORD.
+# include <windows.h> // NOLINT
#endif // GTEST_OS_WINDOWS
-#include <gtest/gtest.h> // NOLINT
-#include <gtest/gtest-spi.h>
+#include "gtest/gtest.h" // NOLINT
+#include "gtest/gtest-spi.h"
namespace testing {
@@ -93,6 +93,7 @@
const char kRepeatFlag[] = "repeat";
const char kShuffleFlag[] = "shuffle";
const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
const char kThrowOnFailureFlag[] = "throw_on_failure";
// A valid random seed must be in [1, kMaxRandomSeed].
@@ -165,6 +166,7 @@
repeat_ = GTEST_FLAG(repeat);
shuffle_ = GTEST_FLAG(shuffle);
stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+ stream_result_to_ = GTEST_FLAG(stream_result_to);
throw_on_failure_ = GTEST_FLAG(throw_on_failure);
}
@@ -185,6 +187,7 @@
GTEST_FLAG(repeat) = repeat_;
GTEST_FLAG(shuffle) = shuffle_;
GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+ GTEST_FLAG(stream_result_to) = stream_result_to_;
GTEST_FLAG(throw_on_failure) = throw_on_failure_;
}
private:
@@ -205,6 +208,7 @@
internal::Int32 repeat_;
bool shuffle_;
internal::Int32 stack_trace_depth_;
+ String stream_result_to_;
bool throw_on_failure_;
} GTEST_ATTRIBUTE_UNUSED_;
@@ -267,7 +271,14 @@
// the given predicate.
template <class Container, typename Predicate>
inline int CountIf(const Container& c, Predicate predicate) {
- return static_cast<int>(std::count_if(c.begin(), c.end(), predicate));
+ // Implemented as an explicit loop since std::count_if() in libCstd on
+ // Solaris has a non-standard signature.
+ int count = 0;
+ for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+ if (predicate(*it))
+ ++count;
+ }
+ return count;
}
// Applies a function/functor to each element in the container.
@@ -340,85 +351,6 @@
String key_;
};
-class TestInfoImpl {
- public:
- TestInfoImpl(TestInfo* parent, const char* test_case_name,
- const char* name, const char* test_case_comment,
- const char* comment, TypeId fixture_class_id,
- internal::TestFactoryBase* factory);
- ~TestInfoImpl();
-
- // Returns true if this test should run.
- bool should_run() const { return should_run_; }
-
- // Sets the should_run member.
- void set_should_run(bool should) { should_run_ = should; }
-
- // Returns true if this test is disabled. Disabled tests are not run.
- bool is_disabled() const { return is_disabled_; }
-
- // Sets the is_disabled member.
- void set_is_disabled(bool is) { is_disabled_ = is; }
-
- // Returns true if this test matches the filter specified by the user.
- bool matches_filter() const { return matches_filter_; }
-
- // Sets the matches_filter member.
- void set_matches_filter(bool matches) { matches_filter_ = matches; }
-
- // Returns the test case name.
- const char* test_case_name() const { return test_case_name_.c_str(); }
-
- // Returns the test name.
- const char* name() const { return name_.c_str(); }
-
- // Returns the test case comment.
- const char* test_case_comment() const { return test_case_comment_.c_str(); }
-
- // Returns the test comment.
- const char* comment() const { return comment_.c_str(); }
-
- // Returns the ID of the test fixture class.
- TypeId fixture_class_id() const { return fixture_class_id_; }
-
- // Returns the test result.
- TestResult* result() { return &result_; }
- const TestResult* result() const { return &result_; }
-
- // Creates the test object, runs it, records its result, and then
- // deletes it.
- void Run();
-
- // Clears the test result.
- void ClearResult() { result_.Clear(); }
-
- // Clears the test result in the given TestInfo object.
- static void ClearTestResult(TestInfo * test_info) {
- test_info->impl()->ClearResult();
- }
-
- private:
- // These fields are immutable properties of the test.
- TestInfo* const parent_; // The owner of this object
- const String test_case_name_; // Test case name
- const String name_; // Test name
- const String test_case_comment_; // Test case comment
- const String comment_; // Test comment
- const TypeId fixture_class_id_; // ID of the test fixture class
- bool should_run_; // True iff this test should run
- bool is_disabled_; // True iff this test is disabled
- bool matches_filter_; // True if this test matches the
- // user-specified filter.
- internal::TestFactoryBase* const factory_; // The factory that creates
- // the test object
-
- // This field is mutable and needs to be reset before running the
- // test for the second time.
- TestResult result_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfoImpl);
-};
-
// Class UnitTestOptions.
//
// This class contains functions for processing options the user
@@ -682,10 +614,12 @@
// Arguments:
//
// test_case_name: name of the test case
+ // type_param: the name of the test's type parameter, or NULL if
+ // this is not a typed or a type-parameterized test.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
TestCase* GetTestCase(const char* test_case_name,
- const char* comment,
+ const char* type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc);
@@ -698,7 +632,7 @@
// test_info: the TestInfo object
void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc,
- TestInfo * test_info) {
+ TestInfo* test_info) {
// In order to support thread-safe death tests, we need to
// remember the original working directory when the test program
// was first invoked. We cannot do this in RUN_ALL_TESTS(), as
@@ -713,7 +647,7 @@
}
GetTestCase(test_info->test_case_name(),
- test_info->test_case_comment(),
+ test_info->type_param(),
set_up_tc,
tear_down_tc)->AddTestInfo(test_info);
}
@@ -739,24 +673,26 @@
}
// Registers all parameterized tests defined using TEST_P and
- // INSTANTIATE_TEST_P, creating regular tests for each test/parameter
- // combination. This method can be called more then once; it has
- // guards protecting from registering the tests more then once.
- // If value-parameterized tests are disabled, RegisterParameterizedTests
- // is present but does nothing.
+ // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
+ // combination. This method can be called more then once; it has guards
+ // protecting from registering the tests more then once. If
+ // value-parameterized tests are disabled, RegisterParameterizedTests is
+ // present but does nothing.
void RegisterParameterizedTests();
// Runs all tests in this UnitTest object, prints the result, and
- // returns 0 if all tests are successful, or 1 otherwise. If any
- // exception is thrown during a test on Windows, this test is
- // considered to be failed, but the rest of the tests will still be
- // run. (We disable exceptions on Linux and Mac OS X, so the issue
- // doesn't apply there.)
- int RunAllTests();
+ // returns true if all tests are successful. If any exception is
+ // thrown during a test, this test is considered to be failed, but
+ // the rest of the tests will still be run.
+ bool RunAllTests();
- // Clears the results of all tests, including the ad hoc test.
- void ClearResult() {
+ // Clears the results of all tests, except the ad hoc tests.
+ void ClearNonAdHocTestResult() {
ForEach(test_cases_, TestCase::ClearTestCaseResult);
+ }
+
+ // Clears the results of ad-hoc test assertions.
+ void ClearAdHocTestResult() {
ad_hoc_test_result_.Clear();
}
@@ -818,6 +754,12 @@
// UnitTestOptions. Must not be called before InitGoogleTest.
void ConfigureXmlOutput();
+#if GTEST_CAN_STREAM_RESULTS_
+ // Initializes the event listener for streaming test results to a socket.
+ // Must not be called before InitGoogleTest.
+ void ConfigureStreamingOutput();
+#endif
+
// Performs initialization dependent upon flag values obtained in
// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
@@ -838,9 +780,17 @@
// Restores the test cases and tests to their order before the first shuffle.
void UnshuffleTests();
+ // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+ // UnitTest::Run() starts.
+ bool catch_exceptions() const { return catch_exceptions_; }
+
private:
friend class ::testing::UnitTest;
+ // Used by UnitTest::Run() to capture the state of
+ // GTEST_FLAG(catch_exceptions) at the moment it starts.
+ void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
// The UnitTest object that owns this implementation object.
UnitTest* const parent_;
@@ -943,6 +893,10 @@
// A per-thread stack of traces created by the SCOPED_TRACE() macro.
internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+ // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+ // starts.
+ bool catch_exceptions_;
+
GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
}; // class UnitTestImpl
@@ -952,14 +906,16 @@
return UnitTest::GetInstance()->impl();
}
+#if GTEST_USES_SIMPLE_RE
+
// Internal helper functions for implementing the simple regular
// expression matcher.
GTEST_API_ bool IsInSet(char ch, const char* str);
-GTEST_API_ bool IsDigit(char ch);
-GTEST_API_ bool IsPunct(char ch);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
GTEST_API_ bool IsRepeat(char ch);
-GTEST_API_ bool IsWhiteSpace(char ch);
-GTEST_API_ bool IsWordChar(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
GTEST_API_ bool IsValidEscape(char ch);
GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
GTEST_API_ bool ValidateRegex(const char* regex);
@@ -968,6 +924,8 @@
bool escaped, char ch, char repeat, const char* regex, const char* str);
GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+#endif // GTEST_USES_SIMPLE_RE
+
// Parses the command line for Google Test flags, without initializing
// other parts of Google Test.
GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
@@ -977,9 +935,9 @@
// Returns the message describing the last system error, regardless of the
// platform.
-String GetLastErrnoDescription();
+GTEST_API_ String GetLastErrnoDescription();
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
// Provides leak-safe Windows kernel handle ownership.
class AutoHandle {
public:
@@ -1003,7 +961,7 @@
GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
};
-#endif // GTEST_OS_WINDOWS
+# endif // GTEST_OS_WINDOWS
// Attempts to parse a string into a positive integer pointed to by the
// number parameter. Returns true if that is possible.
@@ -1014,7 +972,7 @@
// Fail fast if the given string does not begin with a digit;
// this bypasses strtoXXX's "optional leading whitespace and plus
// or minus sign" semantics, which are undesirable here.
- if (str.empty() || !isdigit(str[0])) {
+ if (str.empty() || !IsDigit(str[0])) {
return false;
}
errno = 0;
@@ -1022,14 +980,20 @@
char* end;
// BiggestConvertible is the largest integer type that system-provided
// string-to-number conversion routines can return.
-#if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+# if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
// MSVC and C++ Builder define __int64 instead of the standard long long.
typedef unsigned __int64 BiggestConvertible;
const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
-#else
+
+# else
+
typedef unsigned long long BiggestConvertible; // NOLINT
const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
-#endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+# endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
const bool parse_success = *end == '\0' && errno == 0;
// TODO(vladl at google.com): Convert this to compile time assertion when it is
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-internal.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-internal.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-internal.h Wed Jul 27 13:40:48 2011
@@ -37,13 +37,13 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#if GTEST_OS_LINUX
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
#endif // GTEST_OS_LINUX
#include <ctype.h>
@@ -52,9 +52,9 @@
#include <limits>
#include <set>
-#include <gtest/internal/gtest-string.h>
-#include <gtest/internal/gtest-filepath.h>
-#include <gtest/internal/gtest-type-util.h>
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-type-util.h"
#include "llvm/Support/raw_os_ostream.h"
@@ -117,9 +117,12 @@
cos << val;
}
+class ProtocolMessage;
+namespace proto2 { class Message; }
+
namespace testing {
-// Forward declaration of classes.
+// Forward declarations.
class AssertionResult; // Result of an assertion.
class Message; // Represents a failure message.
@@ -128,6 +131,9 @@
class TestPartResult; // Result of a test part.
class UnitTest; // A collection of test cases.
+template <typename T>
+::std::string PrintToString(const T& value);
+
namespace internal {
struct TraceInfo; // Information about a trace point.
@@ -170,9 +176,9 @@
#ifdef GTEST_ELLIPSIS_NEEDS_POD_
// We lose support for NULL detection where the compiler doesn't like
// passing non-POD classes through ellipsis (...).
-#define GTEST_IS_NULL_LITERAL_(x) false
+# define GTEST_IS_NULL_LITERAL_(x) false
#else
-#define GTEST_IS_NULL_LITERAL_(x) \
+# define GTEST_IS_NULL_LITERAL_(x) \
(sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
#endif // GTEST_ELLIPSIS_NEEDS_POD_
@@ -209,72 +215,32 @@
template <typename T>
String StreamableToString(const T& streamable);
-// Formats a value to be used in a failure message.
-
-#ifdef GTEST_NEEDS_IS_POINTER_
-
-// These are needed as the Nokia Symbian and IBM XL C/C++ compilers
-// cannot decide between const T& and const T* in a function template.
-// These compilers _can_ decide between class template specializations
-// for T and T*, so a tr1::type_traits-like is_pointer works, and we
-// can overload on that.
-
-// This overload makes sure that all pointers (including
-// those to char or wchar_t) are printed as raw pointers.
-template <typename T>
-inline String FormatValueForFailureMessage(internal::true_type /*dummy*/,
- T* pointer) {
- return StreamableToString(static_cast<const void*>(pointer));
-}
-
-template <typename T>
-inline String FormatValueForFailureMessage(internal::false_type /*dummy*/,
- const T& value) {
- return StreamableToString(value);
-}
-
-template <typename T>
-inline String FormatForFailureMessage(const T& value) {
- return FormatValueForFailureMessage(
- typename internal::is_pointer<T>::type(), value);
-}
-
+// The Symbian compiler has a bug that prevents it from selecting the
+// correct overload of FormatForComparisonFailureMessage (see below)
+// unless we pass the first argument by reference. If we do that,
+// however, Visual Age C++ 10.1 generates a compiler error. Therefore
+// we only apply the work-around for Symbian.
+#if defined(__SYMBIAN32__)
+# define GTEST_CREF_WORKAROUND_ const&
#else
+# define GTEST_CREF_WORKAROUND_
+#endif
-// These are needed as the above solution using is_pointer has the
-// limitation that T cannot be a type without external linkage, when
-// compiled using MSVC.
-
-template <typename T>
-inline String FormatForFailureMessage(const T& value) {
- return StreamableToString(value);
-}
-
-// This overload makes sure that all pointers (including
-// those to char or wchar_t) are printed as raw pointers.
-template <typename T>
-inline String FormatForFailureMessage(T* pointer) {
- return StreamableToString(static_cast<const void*>(pointer));
-}
-
-#endif // GTEST_NEEDS_IS_POINTER_
-
-// These overloaded versions handle narrow and wide characters.
-GTEST_API_ String FormatForFailureMessage(char ch);
-GTEST_API_ String FormatForFailureMessage(wchar_t wchar);
-
-// When this operand is a const char* or char*, and the other operand
+// When this operand is a const char* or char*, if the other operand
// is a ::std::string or ::string, we print this operand as a C string
-// rather than a pointer. We do the same for wide strings.
+// rather than a pointer (we do the same for wide strings); otherwise
+// we print it as a pointer to be safe.
// This internal macro is used to avoid duplicated code.
#define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\
inline String FormatForComparisonFailureMessage(\
- operand2_type::value_type* str, const operand2_type& /*operand2*/) {\
+ operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+ const operand2_type& /*operand2*/) {\
return operand1_printer(str);\
}\
inline String FormatForComparisonFailureMessage(\
- const operand2_type::value_type* str, const operand2_type& /*operand2*/) {\
+ const operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+ const operand2_type& /*operand2*/) {\
return operand1_printer(str);\
}
@@ -292,6 +258,24 @@
#undef GTEST_FORMAT_IMPL_
+// The next four overloads handle the case where the operand being
+// printed is a char/wchar_t pointer and the other operand is not a
+// string/wstring object. In such cases, we just print the operand as
+// a pointer to be safe.
+#define GTEST_FORMAT_CHAR_PTR_IMPL_(CharType) \
+ template <typename T> \
+ String FormatForComparisonFailureMessage(CharType* GTEST_CREF_WORKAROUND_ p, \
+ const T&) { \
+ return PrintToString(static_cast<const void*>(p)); \
+ }
+
+GTEST_FORMAT_CHAR_PTR_IMPL_(char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(wchar_t)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const wchar_t)
+
+#undef GTEST_FORMAT_CHAR_PTR_IMPL_
+
// Constructs and returns the message for an equality assertion
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
//
@@ -578,20 +562,6 @@
#endif // GTEST_OS_WINDOWS
-// Formats a source file path and a line number as they would appear
-// in a compiler error message.
-inline String FormatFileLocation(const char* file, int line) {
- const char* const file_name = file == NULL ? "unknown file" : file;
- if (line < 0) {
- return String::Format("%s:", file_name);
- }
-#ifdef _MSC_VER
- return String::Format("%s(%d):", file_name, line);
-#else
- return String::Format("%s:%d:", file_name, line);
-#endif // _MSC_VER
-}
-
// Types of SetUpTestCase() and TearDownTestCase() functions.
typedef void (*SetUpTestCaseFunc)();
typedef void (*TearDownTestCaseFunc)();
@@ -603,10 +573,10 @@
//
// test_case_name: name of the test case
// name: name of the test
-// test_case_comment: a comment on the test case that will be included in
-// the test output
-// comment: a comment on the test that will be included in the
-// test output
+// type_param the name of the test's type parameter, or NULL if
+// this is not a typed or a type-parameterized test.
+// value_param text representation of the test's value parameter,
+// or NULL if this is not a type-parameterized test.
// fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
@@ -615,7 +585,8 @@
// ownership of the factory object.
GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* type_param,
+ const char* value_param,
TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc,
@@ -624,7 +595,7 @@
// If *pstr starts with the given prefix, modifies *pstr to be right
// past the prefix and returns true; otherwise leaves *pstr unchanged
// and returns false. None of pstr, *pstr, and prefix can be NULL.
-bool SkipPrefix(const char* prefix, const char** pstr);
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
@@ -667,7 +638,7 @@
if (comma == NULL) {
return NULL;
}
- while (isspace(*(++comma))) {}
+ while (IsSpace(*(++comma))) {}
return comma;
}
@@ -704,8 +675,8 @@
String::Format("%s%s%s/%d", prefix, prefix[0] == '\0' ? "" : "/",
case_name, index).c_str(),
GetPrefixUntilComma(test_names).c_str(),
- String::Format("TypeParam = %s", GetTypeName<Type>().c_str()).c_str(),
- "",
+ GetTypeName<Type>().c_str(),
+ NULL, // No value parameter.
GetTypeId<FixtureClass>(),
TestClass::SetUpTestCase,
TestClass::TearDownTestCase,
@@ -782,6 +753,15 @@
// Always returns false.
inline bool AlwaysFalse() { return !AlwaysTrue(); }
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+ ConstCharPtr(const char* str) : value(str) {}
+ operator bool() const { return true; }
+ const char* value;
+};
+
// A simple Linear Congruential Generator for generating random
// numbers with a uniform distribution. Unlike rand() and srand(), it
// doesn't use global state (and therefore can't interfere with user
@@ -804,13 +784,338 @@
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
};
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+// Removes the reference from a type if it is a reference type,
+// otherwise leaves it unchanged. This is the same as
+// tr1::remove_reference, which is not widely available yet.
+template <typename T>
+struct RemoveReference { typedef T type; }; // NOLINT
+template <typename T>
+struct RemoveReference<T&> { typedef T type; }; // NOLINT
+
+// A handy wrapper around RemoveReference that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_REFERENCE_(T) \
+ typename ::testing::internal::RemoveReference<T>::type
+
+// Removes const from a type if it is a const type, otherwise leaves
+// it unchanged. This is the same as tr1::remove_const, which is not
+// widely available yet.
+template <typename T>
+struct RemoveConst { typedef T type; }; // NOLINT
+template <typename T>
+struct RemoveConst<const T> { typedef T type; }; // NOLINT
+
+// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
+// definition to fail to remove the const in 'const int[3]' and 'const
+// char[3][4]'. The following specialization works around the bug.
+// However, it causes trouble with GCC and thus needs to be
+// conditionally compiled.
+#if defined(_MSC_VER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+template <typename T, size_t N>
+struct RemoveConst<const T[N]> {
+ typedef typename RemoveConst<T>::type type[N];
+};
+#endif
+
+// A handy wrapper around RemoveConst that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_CONST_(T) \
+ typename ::testing::internal::RemoveConst<T>::type
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+ GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
+
+// Adds reference to a type if it is not a reference type,
+// otherwise leaves it unchanged. This is the same as
+// tr1::add_reference, which is not widely available yet.
+template <typename T>
+struct AddReference { typedef T& type; }; // NOLINT
+template <typename T>
+struct AddReference<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper around AddReference that works when the argument T
+// depends on template parameters.
+#define GTEST_ADD_REFERENCE_(T) \
+ typename ::testing::internal::AddReference<T>::type
+
+// Adds a reference to const on top of T as necessary. For example,
+// it transforms
+//
+// char ==> const char&
+// const char ==> const char&
+// char& ==> const char&
+// const char& ==> const char&
+//
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+ GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
+
+// ImplicitlyConvertible<From, To>::value is a compile-time bool
+// constant that's true iff type From can be implicitly converted to
+// type To.
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+ // We need the following helper functions only for their types.
+ // They have no implementations.
+
+ // MakeFrom() is an expression whose type is From. We cannot simply
+ // use From(), as the type From may not have a public default
+ // constructor.
+ static From MakeFrom();
+
+ // These two functions are overloaded. Given an expression
+ // Helper(x), the compiler will pick the first version if x can be
+ // implicitly converted to type To; otherwise it will pick the
+ // second version.
+ //
+ // The first version returns a value of size 1, and the second
+ // version returns a value of size 2. Therefore, by checking the
+ // size of Helper(x), which can be done at compile time, we can tell
+ // which version of Helper() is used, and hence whether x can be
+ // implicitly converted to type To.
+ static char Helper(To);
+ static char (&Helper(...))[2]; // NOLINT
+
+ // We have to put the 'public' section after the 'private' section,
+ // or MSVC refuses to compile the code.
+ public:
+ // MSVC warns about implicitly converting from double to int for
+ // possible loss of data, so we need to temporarily disable the
+ // warning.
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4244) // Temporarily disables warning 4244.
+
+ static const bool value =
+ sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+# pragma warning(pop) // Restores the warning state.
+#elif defined(__BORLANDC__)
+ // C++Builder cannot use member overload resolution during template
+ // instantiation. The simplest workaround is to use its C++0x type traits
+ // functions (C++Builder 2009 and above only).
+ static const bool value = __is_convertible(From, To);
+#else
+ static const bool value =
+ sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+#endif // _MSV_VER
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+
+// IsAProtocolMessage<T>::value is a compile-time bool constant that's
+// true iff T is type ProtocolMessage, proto2::Message, or a subclass
+// of those.
+template <typename T>
+struct IsAProtocolMessage
+ : public bool_constant<
+ ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
+ ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
+};
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them). It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0. If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked. Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator. The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator'). If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C>
+IsContainer IsContainerTest(int /* dummy */,
+ typename C::iterator* /* it */ = NULL,
+ typename C::const_iterator* /* const_it */ = NULL) {
+ return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// EnableIf<condition>::type is void when 'Cond' is true, and
+// undefined when 'Cond' is false. To use SFINAE to make a function
+// overload only apply when a particular expression is true, add
+// "typename EnableIf<expression>::type* = 0" as the last parameter.
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; }; // NOLINT
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0. When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+ return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat. If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+ for (size_t i = 0; i != size; i++) {
+ if (!internal::ArrayEq(lhs[i], rhs[i]))
+ return false;
+ }
+ return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem. Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+ for (Iter it = begin; it != end; ++it) {
+ if (internal::ArrayEq(*it, elem))
+ return it;
+ }
+ return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0. When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+ internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat. If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+ for (size_t i = 0; i != size; i++) {
+ internal::CopyArray(from[i], to + i);
+ }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+enum RelationToSource {
+ kReference, // The NativeArray references the native array.
+ kCopy // The NativeArray makes a copy of the native array and
+ // owns the copy.
+};
+
+// Adapts a native array to a read-only STL-style container. Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers. New members
+// should be added as needed. To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier). It's the client's responsibility to satisfy
+// this requirement. Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+ // STL-style container typedefs.
+ typedef Element value_type;
+ typedef Element* iterator;
+ typedef const Element* const_iterator;
+
+ // Constructs from a native array.
+ NativeArray(const Element* array, size_t count, RelationToSource relation) {
+ Init(array, count, relation);
+ }
+
+ // Copy constructor.
+ NativeArray(const NativeArray& rhs) {
+ Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
+ }
+
+ ~NativeArray() {
+ // Ensures that the user doesn't instantiate NativeArray with a
+ // const or reference type.
+ static_cast<void>(StaticAssertTypeEqHelper<Element,
+ GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
+ if (relation_to_source_ == kCopy)
+ delete[] array_;
+ }
+
+ // STL-style container methods.
+ size_t size() const { return size_; }
+ const_iterator begin() const { return array_; }
+ const_iterator end() const { return array_ + size_; }
+ bool operator==(const NativeArray& rhs) const {
+ return size() == rhs.size() &&
+ ArrayEq(begin(), size(), rhs.begin());
+ }
+
+ private:
+ // Initializes this object; makes a copy of the input array if
+ // 'relation' is kCopy.
+ void Init(const Element* array, size_t a_size, RelationToSource relation) {
+ if (relation == kReference) {
+ array_ = array;
+ } else {
+ Element* const copy = new Element[a_size];
+ CopyArray(array, a_size, copy);
+ array_ = copy;
+ }
+ size_ = a_size;
+ relation_to_source_ = relation;
+ }
+
+ const Element* array_;
+ size_t size_;
+ RelationToSource relation_to_source_;
+
+ GTEST_DISALLOW_ASSIGN_(NativeArray);
+};
+
} // namespace internal
} // namespace testing
-#define GTEST_MESSAGE_(message, result_type) \
- ::testing::internal::AssertHelper(result_type, __FILE__, __LINE__, message) \
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+ ::testing::internal::AssertHelper(result_type, file, line, message) \
= ::testing::Message()
+#define GTEST_MESSAGE_(message, result_type) \
+ GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
#define GTEST_FATAL_FAILURE_(message) \
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
@@ -828,7 +1133,7 @@
#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::ConstCharPtr gtest_msg = "") { \
bool gtest_caught_expected = false; \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
@@ -837,38 +1142,38 @@
gtest_caught_expected = true; \
} \
catch (...) { \
- gtest_msg = "Expected: " #statement " throws an exception of type " \
- #expected_exception ".\n Actual: it throws a different " \
- "type."; \
+ gtest_msg.value = \
+ "Expected: " #statement " throws an exception of type " \
+ #expected_exception ".\n Actual: it throws a different type."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
if (!gtest_caught_expected) { \
- gtest_msg = "Expected: " #statement " throws an exception of type " \
- #expected_exception ".\n Actual: it throws nothing."; \
+ gtest_msg.value = \
+ "Expected: " #statement " throws an exception of type " \
+ #expected_exception ".\n Actual: it throws nothing."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
- fail(gtest_msg)
+ fail(gtest_msg.value)
#define GTEST_TEST_NO_THROW_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::AlwaysTrue()) { \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} \
catch (...) { \
- gtest_msg = "Expected: " #statement " doesn't throw an exception.\n" \
- " Actual: it throws."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
- fail(gtest_msg)
+ fail("Expected: " #statement " doesn't throw an exception.\n" \
+ " Actual: it throws.")
#define GTEST_TEST_ANY_THROW_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::AlwaysTrue()) { \
bool gtest_caught_any = false; \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
@@ -877,13 +1182,12 @@
gtest_caught_any = true; \
} \
if (!gtest_caught_any) { \
- gtest_msg = "Expected: " #statement " throws an exception.\n" \
- " Actual: it doesn't."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
- fail(gtest_msg)
+ fail("Expected: " #statement " throws an exception.\n" \
+ " Actual: it doesn't.")
// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
@@ -900,18 +1204,17 @@
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::AlwaysTrue()) { \
::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
- gtest_msg = "Expected: " #statement " doesn't generate new fatal " \
- "failures in the current thread.\n" \
- " Actual: it does."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
- fail(gtest_msg)
+ fail("Expected: " #statement " doesn't generate new fatal " \
+ "failures in the current thread.\n" \
+ " Actual: it does.")
// Expands to the name of the class that implements the given test.
#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
@@ -924,7 +1227,7 @@
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
private:\
virtual void TestBody();\
- static ::testing::TestInfo* const test_info_;\
+ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
};\
@@ -932,7 +1235,7 @@
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
::test_info_ =\
::testing::internal::MakeAndRegisterTestInfo(\
- #test_case_name, #test_name, "", "", \
+ #test_case_name, #test_name, NULL, NULL, \
(parent_id), \
parent_class::SetUpTestCase, \
parent_class::TearDownTestCase, \
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h Wed Jul 27 13:40:48 2011
@@ -71,7 +71,7 @@
#include <stdlib.h>
#include <assert.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
namespace testing {
namespace internal {
@@ -172,16 +172,6 @@
T* get() const { return value_; }
T* operator->() const { return value_; }
T& operator*() const { return *value_; }
- // Release ownership of the pointed object and returns it.
- // Sole ownership by this linked_ptr object is required.
- T* release() {
- bool last = link_.depart();
- (void) last;
- assert(last);
- T* v = value_;
- value_ = NULL;
- return v;
- }
bool operator==(T* p) const { return value_ == p; }
bool operator!=(T* p) const { return value_ != p; }
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h Wed Jul 27 13:40:48 2011
@@ -1,4 +1,6 @@
-// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+// This file was GENERATED by command:
+// pump.py gtest-param-util-generated.h.pump
+// DO NOT EDIT BY HAND!!!
// Copyright 2008 Google Inc.
// All Rights Reserved.
@@ -47,8 +49,8 @@
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
-#include <gtest/internal/gtest-param-util.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
#if GTEST_HAS_PARAM_TEST
@@ -58,8 +60,8 @@
// include/gtest/gtest-param-test.h.
template <typename ForwardIterator>
internal::ParamGenerator<
- typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
- ForwardIterator begin, ForwardIterator end);
+ typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
template <typename T, size_t N>
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
@@ -2826,7 +2828,7 @@
const T50 v50_;
};
-#if GTEST_HAS_COMBINE
+# if GTEST_HAS_COMBINE
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Generates values from the Cartesian product of values produced
@@ -4810,7 +4812,7 @@
const Generator10 g10_;
}; // class CartesianProductHolder10
-#endif // GTEST_HAS_COMBINE
+# endif // GTEST_HAS_COMBINE
} // namespace internal
} // namespace testing
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h Wed Jul 27 13:40:48 2011
@@ -41,9 +41,10 @@
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-linked_ptr.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/gtest-printers.h"
#if GTEST_HAS_PARAM_TEST
@@ -171,7 +172,7 @@
iterator end() const { return iterator(impl_->End()); }
private:
- ::testing::internal::linked_ptr<const ParamGeneratorInterface<T> > impl_;
+ linked_ptr<const ParamGeneratorInterface<T> > impl_;
};
// Generates values from a range of two comparable values. Can be used to
@@ -285,7 +286,7 @@
public:
Iterator(const ParamGeneratorInterface<T>* base,
typename ContainerType::const_iterator iterator)
- : base_(base), iterator_(iterator) {}
+ : base_(base), iterator_(iterator) {}
virtual ~Iterator() {}
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
@@ -416,7 +417,7 @@
virtual ~ParameterizedTestCaseInfoBase() {}
// Base part of test case name for display purposes.
- virtual const String& GetTestCaseName() const = 0;
+ virtual const string& GetTestCaseName() const = 0;
// Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const = 0;
// UnitTest class invokes this method to register tests in this
@@ -453,7 +454,7 @@
: test_case_name_(name) {}
// Test case base name for display purposes.
- virtual const String& GetTestCaseName() const { return test_case_name_; }
+ virtual const string& GetTestCaseName() const { return test_case_name_; }
// Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
// TEST_P macro uses AddTestPattern() to record information
@@ -471,7 +472,7 @@
}
// INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
// about a generator.
- int AddTestCaseInstantiation(const char* instantiation_name,
+ int AddTestCaseInstantiation(const string& instantiation_name,
GeneratorCreationFunc* func,
const char* /* file */,
int /* line */) {
@@ -490,26 +491,25 @@
for (typename InstantiationContainer::iterator gen_it =
instantiations_.begin(); gen_it != instantiations_.end();
++gen_it) {
- const String& instantiation_name = gen_it->first;
+ const string& instantiation_name = gen_it->first;
ParamGenerator<ParamType> generator((*gen_it->second)());
Message test_case_name_stream;
if ( !instantiation_name.empty() )
- test_case_name_stream << instantiation_name.c_str() << "/";
- test_case_name_stream << test_info->test_case_base_name.c_str();
+ test_case_name_stream << instantiation_name << "/";
+ test_case_name_stream << test_info->test_case_base_name;
int i = 0;
for (typename ParamGenerator<ParamType>::iterator param_it =
generator.begin();
param_it != generator.end(); ++param_it, ++i) {
Message test_name_stream;
- test_name_stream << test_info->test_base_name.c_str() << "/" << i;
- ::testing::internal::MakeAndRegisterTestInfo(
+ test_name_stream << test_info->test_base_name << "/" << i;
+ MakeAndRegisterTestInfo(
test_case_name_stream.GetString().c_str(),
test_name_stream.GetString().c_str(),
- "", // test_case_comment
- "", // comment; TODO(vladl at google.com): provide parameter value
- // representation.
+ NULL, // No type parameter.
+ PrintToString(*param_it).c_str(),
GetTestCaseTypeId(),
TestCase::SetUpTestCase,
TestCase::TearDownTestCase,
@@ -530,17 +530,17 @@
test_base_name(a_test_base_name),
test_meta_factory(a_test_meta_factory) {}
- const String test_case_base_name;
- const String test_base_name;
+ const string test_case_base_name;
+ const string test_base_name;
const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
};
typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
// Keeps pairs of <Instantiation name, Sequence generator creation function>
// received from INSTANTIATE_TEST_CASE_P macros.
- typedef ::std::vector<std::pair<String, GeneratorCreationFunc*> >
+ typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
InstantiationContainer;
- const String test_case_name_;
+ const string test_case_name_;
TestInfoContainer tests_;
InstantiationContainer instantiations_;
@@ -579,7 +579,7 @@
// and terminate the program since we cannot guaranty correct
// test case setup and tear-down in this case.
ReportInvalidTestCaseType(test_case_name, file, line);
- abort();
+ posix::Abort();
} else {
// At this point we are sure that the object we found is of the same
// type we are looking for, so we downcast it to that type
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-port.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-port.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-port.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-port.h Wed Jul 27 13:40:48 2011
@@ -50,6 +50,8 @@
// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
// is/isn't available (some systems define
// ::wstring, which is different to std::wstring).
+// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular
+// expressions are/aren't available.
// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that <pthread.h>
// is/isn't available.
// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't
@@ -62,6 +64,10 @@
// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the
// compiler supports Microsoft's "Structured
// Exception Handling".
+// GTEST_HAS_STREAM_REDIRECTION
+// - Define it to 1/0 to indicate whether the
+// platform supports I/O stream redirection using
+// dup() and dup2().
// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google
// Test's own tr1 tuple implementation should be
// used. Unused when the user sets
@@ -81,8 +87,11 @@
// GTEST_OS_AIX - IBM AIX
// GTEST_OS_CYGWIN - Cygwin
// GTEST_OS_HAIKU - Haiku
+// GTEST_OS_HPUX - HP-UX
// GTEST_OS_LINUX - Linux
+// GTEST_OS_LINUX_ANDROID - Google Android
// GTEST_OS_MAC - Mac OS X
+// GTEST_OS_NACL - Google Native Client (NaCl)
// GTEST_OS_SOLARIS - Sun Solaris
// GTEST_OS_SYMBIAN - Symbian
// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile)
@@ -108,7 +117,9 @@
// GTEST_HAS_PARAM_TEST - value-parameterized tests
// GTEST_HAS_TYPED_TEST - typed tests
// GTEST_HAS_TYPED_TEST_P - type-parameterized tests
-// GTEST_USES_POSIX_RE - enhanced POSIX regex is used.
+// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with
+// GTEST_HAS_POSIX_RE (see above) which users can
+// define themselves.
// GTEST_USES_SIMPLE_RE - our own simple regex is used;
// the above two are mutually exclusive.
// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
@@ -130,14 +141,17 @@
//
// Template meta programming:
// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only.
+// IteratorTraits - partial implementation of std::iterator_traits, which
+// is not available in libCstd when compiled with Sun C++.
//
// Smart pointers:
// scoped_ptr - as in TR2.
//
// Regular expressions:
// RE - a simple regular expression class using the POSIX
-// Extended Regular Expression syntax. Not available on
-// Windows.
+// Extended Regular Expression syntax on UNIX-like
+// platforms, or a reduced regular exception syntax on
+// other platforms, including Windows.
//
// Logging:
// GTEST_LOG_() - logs messages at the specified severity level.
@@ -170,12 +184,14 @@
// Int32FromGTestEnv() - parses an Int32 environment variable.
// StringFromGTestEnv() - parses a string environment variable.
-#include <stddef.h> // For ptrdiff_t
+#include <ctype.h> // for isspace, etc
+#include <stddef.h> // for ptrdiff_t
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef _WIN32_WCE
-#include <sys/stat.h>
+# include <sys/types.h>
+# include <sys/stat.h>
#endif // !_WIN32_WCE
#include <iostream> // NOLINT
@@ -192,116 +208,140 @@
// Determines the version of gcc that is used to compile this.
#ifdef __GNUC__
// 40302 means version 4.3.2.
-#define GTEST_GCC_VER_ \
+# define GTEST_GCC_VER_ \
(__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
#endif // __GNUC__
// Determines the platform on which Google Test is compiled.
#ifdef __CYGWIN__
-#define GTEST_OS_CYGWIN 1
+# define GTEST_OS_CYGWIN 1
#elif defined __SYMBIAN32__
-#define GTEST_OS_SYMBIAN 1
+# define GTEST_OS_SYMBIAN 1
#elif defined _WIN32
-#define GTEST_OS_WINDOWS 1
-#ifdef _WIN32_WCE
-#define GTEST_OS_WINDOWS_MOBILE 1
-#elif defined(__MINGW__) || defined(__MINGW32__)
-#define GTEST_OS_WINDOWS_MINGW 1
-#else
-#define GTEST_OS_WINDOWS_DESKTOP 1
-#endif // _WIN32_WCE
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+# define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(__MINGW__) || defined(__MINGW32__)
+# define GTEST_OS_WINDOWS_MINGW 1
+# else
+# define GTEST_OS_WINDOWS_DESKTOP 1
+# endif // _WIN32_WCE
#elif defined __APPLE__
-#define GTEST_OS_MAC 1
+# define GTEST_OS_MAC 1
#elif defined __linux__
-#define GTEST_OS_LINUX 1
+# define GTEST_OS_LINUX 1
+# ifdef ANDROID
+# define GTEST_OS_LINUX_ANDROID 1
+# endif // ANDROID
#elif defined __MVS__
-#define GTEST_OS_ZOS 1
+# define GTEST_OS_ZOS 1
#elif defined(__sun) && defined(__SVR4)
-#define GTEST_OS_SOLARIS 1
+# define GTEST_OS_SOLARIS 1
#elif defined(_AIX)
-#define GTEST_OS_AIX 1
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
#elif defined(__HAIKU__)
-#define GTEST_OS_HAIKU 1
+# define GTEST_OS_HAIKU 1
#endif // __CYGWIN__
-#if GTEST_OS_CYGWIN || GTEST_OS_HAIKU || GTEST_OS_LINUX || GTEST_OS_MAC || \
- GTEST_OS_SYMBIAN || GTEST_OS_SOLARIS || GTEST_OS_AIX
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if !GTEST_OS_WINDOWS
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# if !GTEST_OS_NACL
+// TODO(vladl at google.com): Remove this condition when Native Client SDK adds
+// strings.h (tracked in
+// http://code.google.com/p/nativeclient/issues/detail?id=1175).
+# include <strings.h> // Native Client doesn't provide strings.h.
+# endif
+#elif !GTEST_OS_WINDOWS_MOBILE
+# include <direct.h>
+# include <io.h>
+#endif
+
+// Defines this to true iff Google Test can use POSIX regular expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
+#endif
+
+#if GTEST_HAS_POSIX_RE
// On some platforms, <regex.h> needs someone to define size_t, and
// won't compile otherwise. We can #include it here as we already
// included <stdlib.h>, which is guaranteed to define size_t through
// <stddef.h>.
-#include <regex.h> // NOLINT
-#include <strings.h> // NOLINT
-#include <sys/types.h> // NOLINT
-#include <time.h> // NOLINT
-#include <unistd.h> // NOLINT
+# include <regex.h> // NOLINT
-#define GTEST_USES_POSIX_RE 1
+# define GTEST_USES_POSIX_RE 1
#elif GTEST_OS_WINDOWS
-#if !GTEST_OS_WINDOWS_MOBILE
-#include <direct.h> // NOLINT
-#include <io.h> // NOLINT
-#endif
-
// <regex.h> is not available on Windows. Use our own simple regex
// implementation instead.
-#define GTEST_USES_SIMPLE_RE 1
+# define GTEST_USES_SIMPLE_RE 1
#else
// <regex.h> may not be available on this platform. Use our own
// simple regex implementation instead.
-#define GTEST_USES_SIMPLE_RE 1
+# define GTEST_USES_SIMPLE_RE 1
-#endif // GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC ||
- // GTEST_OS_SYMBIAN || GTEST_OS_SOLARIS || GTEST_OS_AIX
+#endif // GTEST_HAS_POSIX_RE
#ifndef GTEST_HAS_EXCEPTIONS
// The user didn't tell us whether exceptions are enabled, so we need
// to figure it out.
-#if defined(_MSC_VER) || defined(__BORLANDC__)
+# if defined(_MSC_VER) || defined(__BORLANDC__)
// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
// macro to enable exceptions, so we'll do the same.
// Assumes that exceptions are enabled by default.
-#ifndef _HAS_EXCEPTIONS
-#define _HAS_EXCEPTIONS 1
-#endif // _HAS_EXCEPTIONS
-#define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
-#elif defined(__GNUC__) && __EXCEPTIONS
+# ifndef _HAS_EXCEPTIONS
+# define _HAS_EXCEPTIONS 1
+# endif // _HAS_EXCEPTIONS
+# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__GNUC__) && __EXCEPTIONS
// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
-#define GTEST_HAS_EXCEPTIONS 1
-#elif defined(__SUNPRO_CC)
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
// Sun Pro CC supports exceptions. However, there is no compile-time way of
// detecting whether they are enabled or not. Therefore, we assume that
// they are enabled unless the user tells us otherwise.
-#define GTEST_HAS_EXCEPTIONS 1
-#elif defined(__IBMCPP__) && __EXCEPTIONS
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
-#define GTEST_HAS_EXCEPTIONS 1
-#else
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+# define GTEST_HAS_EXCEPTIONS 1
+# else
// For other compilers, we assume exceptions are disabled to be
// conservative.
-#define GTEST_HAS_EXCEPTIONS 0
-#endif // defined(_MSC_VER) || defined(__BORLANDC__)
+# define GTEST_HAS_EXCEPTIONS 0
+# endif // defined(_MSC_VER) || defined(__BORLANDC__)
#endif // GTEST_HAS_EXCEPTIONS
#if !defined(GTEST_HAS_STD_STRING)
// Even though we don't use this macro any longer, we keep it in case
// some clients still depend on it.
-#define GTEST_HAS_STD_STRING 1
+# define GTEST_HAS_STD_STRING 1
#elif !GTEST_HAS_STD_STRING
// The user told us that ::std::string isn't available.
-#error "Google Test cannot be used where ::std::string isn't available."
+# error "Google Test cannot be used where ::std::string isn't available."
#endif // !defined(GTEST_HAS_STD_STRING)
#ifndef GTEST_HAS_GLOBAL_STRING
// The user didn't tell us whether ::string is available, so we need
// to figure it out.
-#define GTEST_HAS_GLOBAL_STRING 0
+# define GTEST_HAS_GLOBAL_STRING 0
#endif // GTEST_HAS_GLOBAL_STRING
@@ -311,18 +351,19 @@
// TODO(wan at google.com): uses autoconf to detect whether ::std::wstring
// is available.
-// Cygwin 1.5 and below doesn't support ::std::wstring.
-// Cygwin 1.7 might add wstring support; this should be updated when clear.
-// Solaris' libc++ doesn't support it either.
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either. Android has
+// no support for it at least as recent as Froyo (2.2).
// Minix currently doesn't support it either.
-#define GTEST_HAS_STD_WSTRING (!(GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || GTEST_OS_HAIKU || defined(_MINIX)))
+# define GTEST_HAS_STD_WSTRING \
+ (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || GTEST_OS_HAIKU || defined(_MINIX)))
#endif // GTEST_HAS_STD_WSTRING
#ifndef GTEST_HAS_GLOBAL_WSTRING
// The user didn't tell us whether ::wstring is available, so we need
// to figure it out.
-#define GTEST_HAS_GLOBAL_WSTRING \
+# define GTEST_HAS_GLOBAL_WSTRING \
(GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
#endif // GTEST_HAS_GLOBAL_WSTRING
@@ -331,46 +372,46 @@
// The user didn't tell us whether RTTI is enabled, so we need to
// figure it out.
-#ifdef _MSC_VER
+# ifdef _MSC_VER
-#ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled.
-#define GTEST_HAS_RTTI 1
-#else
-#define GTEST_HAS_RTTI 0
-#endif
+# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled.
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif
// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
-#elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
-#ifdef __GXX_RTTI
-#define GTEST_HAS_RTTI 1
-#else
-#define GTEST_HAS_RTTI 0
-#endif // __GXX_RTTI
+# ifdef __GXX_RTTI
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif // __GXX_RTTI
// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
// both the typeid and dynamic_cast features are present.
-#elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
-#ifdef __RTTI_ALL__
-#define GTEST_HAS_RTTI 1
-#else
-#define GTEST_HAS_RTTI 0
-#endif
+# ifdef __RTTI_ALL__
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif
-#else
+# else
// For all other compilers, we assume RTTI is enabled.
-#define GTEST_HAS_RTTI 1
+# define GTEST_HAS_RTTI 1
-#endif // _MSC_VER
+# endif // _MSC_VER
#endif // GTEST_HAS_RTTI
// It's this header's responsibility to #include <typeinfo> when RTTI
// is enabled.
#if GTEST_HAS_RTTI
-#include <typeinfo>
+# include <typeinfo>
#endif
// Determines whether Google Test can use the pthreads library.
@@ -380,15 +421,24 @@
//
// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
// to your compiler flags.
-#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC)
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX)
#endif // GTEST_HAS_PTHREAD
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h> // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h> // NOLINT
+#endif
+
// Determines whether Google Test can use tr1/tuple. You can define
// this macro to 0 to prevent Google Test from using tuple (any
// feature depending on tuple with be disabled in this mode).
#ifndef GTEST_HAS_TR1_TUPLE
// The user didn't tell us not to do it, so we assume it's OK.
-#define GTEST_HAS_TR1_TUPLE 1
+# define GTEST_HAS_TR1_TUPLE 1
#endif // GTEST_HAS_TR1_TUPLE
// Determines whether Google Test's own tr1 tuple implementation
@@ -403,13 +453,13 @@
// defining __GNUC__ and friends, but cannot compile GCC's tuple
// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
// Feature Pack download, which we cannot assume the user has.
-#if (defined(__GNUC__) && !(defined(__CUDACC__) || defined(__clang__)) \
- && (GTEST_GCC_VER_ >= 40000)) \
+# if (defined(__GNUC__) && !(defined(__CUDACC__) || defined(__clang__)) \
+ && (GTEST_GCC_VER_ >= 40000)) \
|| _MSC_VER >= 1600
-#define GTEST_USE_OWN_TR1_TUPLE 0
-#else
-#define GTEST_USE_OWN_TR1_TUPLE 1
-#endif
+# define GTEST_USE_OWN_TR1_TUPLE 0
+# else
+# define GTEST_USE_OWN_TR1_TUPLE 1
+# endif
#endif // GTEST_USE_OWN_TR1_TUPLE
@@ -418,47 +468,47 @@
// tr1/tuple.
#if GTEST_HAS_TR1_TUPLE
-#if GTEST_USE_OWN_TR1_TUPLE
-#include <gtest/internal/gtest-tuple.h>
-#elif GTEST_OS_SYMBIAN
+# if GTEST_USE_OWN_TR1_TUPLE
+# include "gtest/internal/gtest-tuple.h"
+# elif GTEST_OS_SYMBIAN
// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
// use STLport's tuple implementation, which unfortunately doesn't
// work as the copy of STLport distributed with Symbian is incomplete.
// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to
// use its own tuple implementation.
-#ifdef BOOST_HAS_TR1_TUPLE
-#undef BOOST_HAS_TR1_TUPLE
-#endif // BOOST_HAS_TR1_TUPLE
+# ifdef BOOST_HAS_TR1_TUPLE
+# undef BOOST_HAS_TR1_TUPLE
+# endif // BOOST_HAS_TR1_TUPLE
// This prevents <boost/tr1/detail/config.hpp>, which defines
// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
-#define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
-#include <tuple>
+# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
+# include <tuple>
-#elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header. This does
// not conform to the TR1 spec, which requires the header to be <tuple>.
-#if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
// Until version 4.3.2, gcc has a bug that causes <tr1/functional>,
// which is #included by <tr1/tuple>, to not compile when RTTI is
// disabled. _TR1_FUNCTIONAL is the header guard for
// <tr1/functional>. Hence the following #define is a hack to prevent
// <tr1/functional> from being included.
-#define _TR1_FUNCTIONAL 1
-#include <tr1/tuple>
-#undef _TR1_FUNCTIONAL // Allows the user to #include
+# define _TR1_FUNCTIONAL 1
+# include <tr1/tuple>
+# undef _TR1_FUNCTIONAL // Allows the user to #include
// <tr1/functional> if he chooses to.
-#else
-#include <tr1/tuple> // NOLINT
-#endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+# else
+# include <tr1/tuple> // NOLINT
+# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
-#else
+# else
// If the compiler is not GCC 4.0+, we assume the user is using a
// spec-conforming TR1 implementation.
-#include <tuple> // NOLINT
-#endif // GTEST_USE_OWN_TR1_TUPLE
+# include <tuple> // NOLINT
+# endif // GTEST_USE_OWN_TR1_TUPLE
#endif // GTEST_HAS_TR1_TUPLE
@@ -469,19 +519,25 @@
#ifndef GTEST_HAS_CLONE
// The user didn't tell us, so we need to figure it out.
-#if GTEST_OS_LINUX && !defined(__ia64__)
-#define GTEST_HAS_CLONE 1
-#else
-#define GTEST_HAS_CLONE 0
-#endif // GTEST_OS_LINUX && !defined(__ia64__)
+# if GTEST_OS_LINUX && !defined(__ia64__)
+# define GTEST_HAS_CLONE 1
+# else
+# define GTEST_HAS_CLONE 0
+# endif // GTEST_OS_LINUX && !defined(__ia64__)
#endif // GTEST_HAS_CLONE
// Determines whether to support stream redirection. This is used to test
// output correctness and to implement death tests.
-#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
-#define GTEST_HAS_STREAM_REDIRECTION_ 1
-#endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN
+# define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+# define GTEST_HAS_STREAM_REDIRECTION 1
+# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#endif // GTEST_HAS_STREAM_REDIRECTION
// Determines whether to support death tests.
// Google Test does not support death tests for VC 7.1 and earlier as
@@ -489,9 +545,9 @@
// pops up a dialog window that cannot be suppressed programmatically.
#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
(GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
- GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX)
-#define GTEST_HAS_DEATH_TEST 1
-#include <vector> // NOLINT
+ GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX)
+# define GTEST_HAS_DEATH_TEST 1
+# include <vector> // NOLINT
#endif
// We don't support MSVC 7.1 with exceptions disabled now. Therefore
@@ -502,11 +558,11 @@
// Determines whether to support type-driven tests.
// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
-// Sun Pro CC, and IBM Visual Age support.
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
- defined(__IBMCPP__)
-#define GTEST_HAS_TYPED_TEST 1
-#define GTEST_HAS_TYPED_TEST_P 1
+ defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
#endif
// Determines whether to support Combine(). This only makes sense when
@@ -514,13 +570,18 @@
// work on Sun Studio since it doesn't understand templated conversion
// operators.
#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
-#define GTEST_HAS_COMBINE 1
+# define GTEST_HAS_COMBINE 1
#endif
// Determines whether the system compiler uses UTF-16 for encoding wide strings.
#define GTEST_WIDE_STRING_USES_UTF16_ \
(GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX)
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
// Defines some utility macros.
// The GNU compiler emits a warning if nested "if" statements are followed by
@@ -532,9 +593,9 @@
//
// The "switch (0) case 0:" idiom is used to suppress this.
#ifdef __INTEL_COMPILER
-#define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
#else
-#define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: // NOLINT
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT
#endif
// Use this annotation at the end of a struct/class definition to
@@ -549,9 +610,9 @@
// Also use it after a variable or parameter declaration to tell the
// compiler the variable/parameter does not have to be used.
#if defined(__GNUC__) && !defined(COMPILER_ICC)
-#define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
#else
-#define GTEST_ATTRIBUTE_UNUSED_
+# define GTEST_ATTRIBUTE_UNUSED_
#endif
// A macro to disallow operator=
@@ -571,9 +632,9 @@
//
// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC)
-#define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
#else
-#define GTEST_MUST_USE_RESULT_
+# define GTEST_MUST_USE_RESULT_
#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
// Determine whether the compiler supports Microsoft's Structured Exception
@@ -582,28 +643,35 @@
#ifndef GTEST_HAS_SEH
// The user didn't tell us, so we need to figure it out.
-#if defined(_MSC_VER) || defined(__BORLANDC__)
+# if defined(_MSC_VER) || defined(__BORLANDC__)
// These two compilers are known to support SEH.
-#define GTEST_HAS_SEH 1
-#else
+# define GTEST_HAS_SEH 1
+# else
// Assume no SEH.
-#define GTEST_HAS_SEH 0
-#endif
+# define GTEST_HAS_SEH 0
+# endif
#endif // GTEST_HAS_SEH
#ifdef _MSC_VER
-#if GTEST_LINKED_AS_SHARED_LIBRARY
-#define GTEST_API_ __declspec(dllimport)
-#elif GTEST_CREATE_SHARED_LIBRARY
-#define GTEST_API_ __declspec(dllexport)
-#endif
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+# define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+# define GTEST_API_ __declspec(dllexport)
+# endif
#endif // _MSC_VER
#ifndef GTEST_API_
-#define GTEST_API_
+# define GTEST_API_
+#endif
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
#endif
namespace testing {
@@ -614,7 +682,90 @@
class String;
-typedef ::std::stringstream StrStream;
+// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+// content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#define GTEST_COMPILE_ASSERT_(expr, msg) \
+ typedef ::testing::internal::CompileAssert<(bool(expr))> \
+ msg[bool(expr) ? 1 : -1]
+
+// Implementation details of GTEST_COMPILE_ASSERT_:
+//
+// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
+// elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+// does not work, as gcc supports variable-length arrays whose sizes
+// are determined at run-time (this is gcc's extension and not part
+// of the C++ standard). As a result, gcc fails to reject the
+// following code with the simple definition:
+//
+// int foo;
+// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
+// // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+// expr is a compile-time constant. (Template arguments must be
+// determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
+//
+// CompileAssert<bool(expr)>
+//
+// instead, these compilers will refuse to compile
+//
+// GTEST_COMPILE_ASSERT_(5 > 0, some_message);
+//
+// (They seem to think the ">" in "5 > 0" marks the end of the
+// template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+// ((expr) ? 1 : -1).
+//
+// This is to avoid running into a bug in MS VC 7.1, which
+// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
+//
+// This template is declared, but intentionally undefined.
+template <typename T1, typename T2>
+struct StaticAssertTypeEqHelper;
+
+template <typename T>
+struct StaticAssertTypeEqHelper<T, T> {};
+
+#if GTEST_HAS_GLOBAL_STRING
+typedef ::string string;
+#else
+typedef ::std::string string;
+#endif // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+typedef ::wstring wstring;
+#elif GTEST_HAS_STD_WSTRING
+typedef ::std::wstring wstring;
+#endif // GTEST_HAS_GLOBAL_WSTRING
// A helper for suppressing warnings on constant condition. It just
// returns 'condition'.
@@ -670,7 +821,9 @@
RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT
#if GTEST_HAS_GLOBAL_STRING
+
RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT
+
#endif // GTEST_HAS_GLOBAL_STRING
RE(const char* regex) { Init(regex); } // NOLINT
@@ -694,12 +847,14 @@
}
#if GTEST_HAS_GLOBAL_STRING
+
static bool FullMatch(const ::string& str, const RE& re) {
return FullMatch(str.c_str(), re);
}
static bool PartialMatch(const ::string& str, const RE& re) {
return PartialMatch(str.c_str(), re);
}
+
#endif // GTEST_HAS_GLOBAL_STRING
static bool FullMatch(const char* str, const RE& re);
@@ -714,16 +869,31 @@
// files.
const char* pattern_;
bool is_valid_;
+
#if GTEST_USES_POSIX_RE
+
regex_t full_regex_; // For FullMatch().
regex_t partial_regex_; // For PartialMatch().
+
#else // GTEST_USES_SIMPLE_RE
+
const char* full_pattern_; // For FullMatch();
+
#endif
GTEST_DISALLOW_ASSIGN_(RE);
};
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+ int line);
+
// Defines logging utilities:
// GTEST_LOG_(severity) - logs messages at the specified severity level. The
// message itself is streamed into the macro.
@@ -795,6 +965,66 @@
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*). When you use ImplicitCast_, the compiler checks that
+// the cast is safe. Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+// ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late. It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed. When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo? It
+// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
+// when you downcast, you should use this macro. In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not). In normal mode, we do the efficient static_cast<>
+// instead. Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+// This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From> // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) { // so we only accept pointers
+ // Ensures that To is a sub-type of From *. This test is here only
+ // for compile-time type checking, and has no overhead in an
+ // optimized build at run-time, as it will be optimized away
+ // completely.
+ if (false) {
+ const To to = NULL;
+ ::testing::internal::ImplicitCast_<From*>(to);
+ }
+
+#if GTEST_HAS_RTTI
+ // RTTI: debug mode only!
+ GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
+#endif
+ return static_cast<To>(f);
+}
+
// Downcasts the pointer of type Base to Derived.
// Derived must be a subclass of Base. The parameter MUST
// point to a class of type Derived, not any subclass of it.
@@ -810,7 +1040,7 @@
#endif
}
-#if GTEST_HAS_STREAM_REDIRECTION_
+#if GTEST_HAS_STREAM_REDIRECTION
// Defines the stderr capturer:
// CaptureStdout - starts capturing stdout.
@@ -823,7 +1053,7 @@
GTEST_API_ void CaptureStderr();
GTEST_API_ String GetCapturedStderr();
-#endif // GTEST_HAS_STREAM_REDIRECTION_
+#endif // GTEST_HAS_STREAM_REDIRECTION
#if GTEST_HAS_DEATH_TEST
@@ -957,10 +1187,6 @@
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
};
-// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
-// true.
-#include <pthread.h>
-
// MutexBase and Mutex implement mutex on pthreads-based platforms. They
// are used in conjunction with class MutexLock:
//
@@ -1015,11 +1241,11 @@
};
// Forward-declares a static mutex.
-#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
extern ::testing::internal::MutexBase mutex
// Defines and statically (i.e. at link time) initializes a static mutex.
-#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 }
// The Mutex class can only be used for mutexes created at runtime. It
@@ -1166,7 +1392,7 @@
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
};
-#define GTEST_IS_THREADSAFE 1
+# define GTEST_IS_THREADSAFE 1
#else // GTEST_HAS_PTHREAD
@@ -1181,10 +1407,10 @@
void AssertHeld() const {}
};
-#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
extern ::testing::internal::Mutex mutex
-#define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
class GTestMutexLock {
public:
@@ -1208,7 +1434,7 @@
// The above synchronization primitives have dummy implementations.
// Therefore Google Test is not thread-safe.
-#define GTEST_IS_THREADSAFE 0
+# define GTEST_IS_THREADSAFE 0
#endif // GTEST_HAS_PTHREAD
@@ -1225,9 +1451,9 @@
#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
// We lose support for NULL detection where the compiler doesn't like
// passing non-POD classes through ellipsis (...).
-#define GTEST_ELLIPSIS_NEEDS_POD_ 1
+# define GTEST_ELLIPSIS_NEEDS_POD_ 1
#else
-#define GTEST_CAN_COMPARE_NULL 1
+# define GTEST_CAN_COMPARE_NULL 1
#endif
// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between
@@ -1235,7 +1461,7 @@
// _can_ decide between class template specializations for T and T*,
// so a tr1::type_traits-like is_pointer works.
#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
-#define GTEST_NEEDS_IS_POINTER_ 1
+# define GTEST_NEEDS_IS_POINTER_ 1
#endif
template <bool bool_value>
@@ -1254,17 +1480,68 @@
template <typename T>
struct is_pointer<T*> : public true_type {};
+template <typename Iterator>
+struct IteratorTraits {
+ typedef typename Iterator::value_type value_type;
+};
+
+template <typename T>
+struct IteratorTraits<T*> {
+ typedef T value_type;
+};
+
+template <typename T>
+struct IteratorTraits<const T*> {
+ typedef T value_type;
+};
+
#if GTEST_OS_WINDOWS
-#define GTEST_PATH_SEP_ "\\"
-#define GTEST_HAS_ALT_PATH_SEP_ 1
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
// The biggest signed integer type the compiler supports.
typedef __int64 BiggestInt;
#else
-#define GTEST_PATH_SEP_ "/"
-#define GTEST_HAS_ALT_PATH_SEP_ 0
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
typedef long long BiggestInt; // NOLINT
#endif // GTEST_OS_WINDOWS
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF. char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+ return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+ return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+ return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+ return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+ return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+ return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+ return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+
+inline char ToLower(char ch) {
+ return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+ return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
// The testing::internal::posix namespace holds wrappers for common
// POSIX functions. These wrappers hide the differences between
// Windows/MSVC and POSIX systems. Since some compilers define these
@@ -1279,36 +1556,36 @@
typedef struct _stat StatStruct;
-#ifdef __BORLANDC__
+# ifdef __BORLANDC__
inline int IsATTY(int fd) { return isatty(fd); }
inline int StrCaseCmp(const char* s1, const char* s2) {
return stricmp(s1, s2);
}
inline char* StrDup(const char* src) { return strdup(src); }
-#else // !__BORLANDC__
-#if GTEST_OS_WINDOWS_MOBILE
+# else // !__BORLANDC__
+# if GTEST_OS_WINDOWS_MOBILE
inline int IsATTY(int /* fd */) { return 0; }
-#else
+# else
inline int IsATTY(int fd) { return _isatty(fd); }
-#endif // GTEST_OS_WINDOWS_MOBILE
+# endif // GTEST_OS_WINDOWS_MOBILE
inline int StrCaseCmp(const char* s1, const char* s2) {
return _stricmp(s1, s2);
}
inline char* StrDup(const char* src) { return _strdup(src); }
-#endif // __BORLANDC__
+# endif // __BORLANDC__
-#if GTEST_OS_WINDOWS_MOBILE
+# if GTEST_OS_WINDOWS_MOBILE
inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
// time and thus not defined there.
-#else
+# else
inline int FileNo(FILE* file) { return _fileno(file); }
inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
inline int RmDir(const char* dir) { return _rmdir(dir); }
inline bool IsDir(const StatStruct& st) {
return (_S_IFDIR & st.st_mode) != 0;
}
-#endif // GTEST_OS_WINDOWS_MOBILE
+# endif // GTEST_OS_WINDOWS_MOBILE
#else
@@ -1330,8 +1607,8 @@
#ifdef _MSC_VER
// Temporarily disable warning 4996 (deprecated function).
-#pragma warning(push)
-#pragma warning(disable:4996)
+# pragma warning(push)
+# pragma warning(disable:4996)
#endif
inline const char* StrNCpy(char* dest, const char* src, size_t n) {
@@ -1380,7 +1657,7 @@
}
#ifdef _MSC_VER
-#pragma warning(pop) // Restores the warning state.
+# pragma warning(pop) // Restores the warning state.
#endif
#if GTEST_OS_WINDOWS_MOBILE
@@ -1446,6 +1723,7 @@
template <>
class TypeWithSize<8> {
public:
+
#if GTEST_OS_WINDOWS
typedef __int64 Int;
typedef unsigned __int64 UInt;
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-string.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-string.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-string.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-string.h Wed Jul 27 13:40:48 2011
@@ -43,11 +43,11 @@
#ifdef __BORLANDC__
// string.h is not guaranteed to provide strcpy on C++ Builder.
-#include <mem.h>
+# include <mem.h>
#endif
#include <string.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#include <string>
@@ -296,7 +296,7 @@
private:
// Constructs a non-NULL String from the given content. This
- // function can only be called when data_ has not been allocated.
+ // function can only be called when c_str_ has not been allocated.
// ConstructNonNull(NULL, 0) results in an empty string ("").
// ConstructNonNull(NULL, non_zero) is undefined behavior.
void ConstructNonNull(const char* buffer, size_t a_length) {
@@ -329,9 +329,9 @@
return os;
}
-// Gets the content of the StrStream's buffer as a String. Each '\0'
+// Gets the content of the stringstream's buffer as a String. Each '\0'
// character in the buffer is replaced with "\\0".
-GTEST_API_ String StrStreamToString(StrStream* stream);
+GTEST_API_ String StringStreamToString(::std::stringstream* stream);
// Converts a streamable value to a String. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h Wed Jul 27 13:40:48 2011
@@ -44,9 +44,9 @@
// private as public.
// Sun Studio versions < 12 also have the above bug.
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
-#define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
#else
-#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
private:
#endif
Modified: llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h?rev=136234&r1=136233&r2=136234&view=diff
==============================================================================
--- llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h (original)
+++ llvm/branches/exception-handling-rewrite/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h Wed Jul 27 13:40:48 2011
@@ -44,55 +44,64 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
-#include <gtest/internal/gtest-port.h>
-#include <gtest/internal/gtest-string.h>
-
-#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-string.h"
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
// libstdc++ (which is where cxxabi.h comes from).
-#ifdef __GLIBCXX__
-#include <cxxabi.h>
-#endif // __GLIBCXX__
+# ifdef __GLIBCXX__
+# include <cxxabi.h>
+# elif defined(__HP_aCC)
+# include <acxx_demangle.h>
+# endif // __GLIBCXX__
namespace testing {
namespace internal {
-// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
-// type. This can be used as a compile-time assertion to ensure that
-// two types are equal.
-
-template <typename T1, typename T2>
-struct AssertTypeEq;
-
-template <typename T>
-struct AssertTypeEq<T, T> {
- typedef bool type;
-};
-
// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
template <typename T>
String GetTypeName() {
-#if GTEST_HAS_RTTI
+# if GTEST_HAS_RTTI
const char* const name = typeid(T).name();
-#ifdef __GLIBCXX__
+# if defined(__GLIBCXX__) || defined(__HP_aCC)
int status = 0;
// gcc's implementation of typeid(T).name() mangles the type name,
// so we have to demangle it.
- char* const readable_name = abi::__cxa_demangle(name, 0, 0, &status);
+# ifdef __GLIBCXX__
+ using abi::__cxa_demangle;
+# endif // __GLIBCXX__
+ char* const readable_name = __cxa_demangle(name, 0, 0, &status);
const String name_str(status == 0 ? readable_name : name);
free(readable_name);
return name_str;
-#else
+# else
return name;
-#endif // __GLIBCXX__
+# endif // __GLIBCXX__ || __HP_aCC
+
+# else
-#else
return "<type>";
-#endif // GTEST_HAS_RTTI
+
+# endif // GTEST_HAS_RTTI
}
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type. This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+ typedef bool type;
+};
+
// A unique type used as the default value for the arguments of class
// template Types. This allows us to simulate variadic templates
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
@@ -1611,7 +1620,7 @@
namespace internal {
-#define GTEST_TEMPLATE_ template <typename T> class
+# define GTEST_TEMPLATE_ template <typename T> class
// The template "selector" struct TemplateSel<Tmpl> is used to
// represent Tmpl, which must be a class template with one type
@@ -1629,7 +1638,7 @@
};
};
-#define GTEST_BIND_(TmplSel, T) \
+# define GTEST_BIND_(TmplSel, T) \
TmplSel::template Bind<T>::type
// A unique struct template used as the default value for the
@@ -3313,9 +3322,9 @@
T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
};
+#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
} // namespace internal
} // namespace testing
-#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
-
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
More information about the llvm-branch-commits
mailing list