summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/utils
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/utils')
-rwxr-xr-xcontrib/llvm/utils/DSAclean.py32
-rw-r--r--contrib/llvm/utils/DSAextract.py111
-rw-r--r--contrib/llvm/utils/FileCheck/CMakeLists.txt11
-rw-r--r--contrib/llvm/utils/FileCheck/FileCheck.cpp732
-rw-r--r--contrib/llvm/utils/FileCheck/Makefile21
-rw-r--r--contrib/llvm/utils/FileUpdate/CMakeLists.txt11
-rw-r--r--contrib/llvm/utils/FileUpdate/FileUpdate.cpp87
-rw-r--r--contrib/llvm/utils/FileUpdate/Makefile21
-rwxr-xr-xcontrib/llvm/utils/GenLibDeps.pl388
-rwxr-xr-xcontrib/llvm/utils/GetSourceVersion27
-rw-r--r--contrib/llvm/utils/Makefile22
-rwxr-xr-xcontrib/llvm/utils/Misc/zkill276
-rw-r--r--contrib/llvm/utils/NLT.schema8
-rwxr-xr-xcontrib/llvm/utils/NewNightlyTest.pl836
-rw-r--r--contrib/llvm/utils/NightlyTest.gnuplot214
-rw-r--r--contrib/llvm/utils/NightlyTestTemplate.html244
-rw-r--r--contrib/llvm/utils/OldenDataRecover.pl37
-rw-r--r--contrib/llvm/utils/PerfectShuffle/Makefile18
-rw-r--r--contrib/llvm/utils/PerfectShuffle/PerfectShuffle.cpp571
-rw-r--r--contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp1878
-rw-r--r--contrib/llvm/utils/TableGen/ARMDecoderEmitter.h50
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp1811
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.h33
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp548
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterEmitter.h54
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterInst.cpp265
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterInst.h113
-rw-r--r--contrib/llvm/utils/TableGen/CMakeLists.txt46
-rw-r--r--contrib/llvm/utils/TableGen/CallingConvEmitter.cpp212
-rw-r--r--contrib/llvm/utils/TableGen/CallingConvEmitter.h38
-rw-r--r--contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp165
-rw-r--r--contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h84
-rw-r--r--contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp638
-rw-r--r--contrib/llvm/utils/TableGen/ClangAttrEmitter.h88
-rw-r--r--contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp286
-rw-r--r--contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h46
-rw-r--r--contrib/llvm/utils/TableGen/CodeEmitterGen.cpp224
-rw-r--r--contrib/llvm/utils/TableGen/CodeEmitterGen.h43
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp3021
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h748
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.cpp306
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.h197
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenIntrinsics.h87
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenRegisters.h95
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.cpp568
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.h262
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelEmitter.cpp155
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelEmitter.h38
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcher.cpp401
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcher.h1114
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp795
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp910
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp514
-rw-r--r--contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp137
-rw-r--r--contrib/llvm/utils/TableGen/DisassemblerEmitter.h28
-rw-r--r--contrib/llvm/utils/TableGen/EDEmitter.cpp864
-rw-r--r--contrib/llvm/utils/TableGen/EDEmitter.h34
-rw-r--r--contrib/llvm/utils/TableGen/FastISelEmitter.cpp651
-rw-r--r--contrib/llvm/utils/TableGen/FastISelEmitter.h39
-rw-r--r--contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp48
-rw-r--r--contrib/llvm/utils/TableGen/InstrEnumEmitter.h33
-rw-r--r--contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp335
-rw-r--r--contrib/llvm/utils/TableGen/InstrInfoEmitter.h66
-rw-r--r--contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp751
-rw-r--r--contrib/llvm/utils/TableGen/IntrinsicEmitter.h63
-rw-r--r--contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp3110
-rw-r--r--contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.h32
-rw-r--r--contrib/llvm/utils/TableGen/Makefile20
-rw-r--r--contrib/llvm/utils/TableGen/NeonEmitter.cpp1207
-rw-r--r--contrib/llvm/utils/TableGen/NeonEmitter.h122
-rw-r--r--contrib/llvm/utils/TableGen/OptParserEmitter.cpp194
-rw-r--r--contrib/llvm/utils/TableGen/OptParserEmitter.h34
-rw-r--r--contrib/llvm/utils/TableGen/Record.cpp1588
-rw-r--r--contrib/llvm/utils/TableGen/Record.h1497
-rw-r--r--contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp1017
-rw-r--r--contrib/llvm/utils/TableGen/RegisterInfoEmitter.h40
-rw-r--r--contrib/llvm/utils/TableGen/StringToOffsetTable.h81
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetEmitter.cpp605
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetEmitter.h65
-rw-r--r--contrib/llvm/utils/TableGen/TGLexer.cpp450
-rw-r--r--contrib/llvm/utils/TableGen/TGLexer.h121
-rw-r--r--contrib/llvm/utils/TableGen/TGParser.cpp2123
-rw-r--r--contrib/llvm/utils/TableGen/TGParser.h112
-rw-r--r--contrib/llvm/utils/TableGen/TGValueTypes.cpp106
-rw-r--r--contrib/llvm/utils/TableGen/TableGen.cpp356
-rw-r--r--contrib/llvm/utils/TableGen/TableGenBackend.cpp25
-rw-r--r--contrib/llvm/utils/TableGen/TableGenBackend.h43
-rw-r--r--contrib/llvm/utils/TableGen/X86DisassemblerShared.h38
-rw-r--r--contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp603
-rw-r--r--contrib/llvm/utils/TableGen/X86DisassemblerTables.h291
-rw-r--r--contrib/llvm/utils/TableGen/X86ModRMFilters.h197
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp983
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.h239
-rwxr-xr-xcontrib/llvm/utils/UpdateCMakeLists.pl119
-rw-r--r--contrib/llvm/utils/bugpoint/RemoteRunSafely.sh105
-rw-r--r--contrib/llvm/utils/buildit/GNUmakefile131
-rwxr-xr-xcontrib/llvm/utils/buildit/build_llvm373
-rwxr-xr-xcontrib/llvm/utils/cgiplotNLT.pl68
-rwxr-xr-xcontrib/llvm/utils/check-each-file150
-rwxr-xr-xcontrib/llvm/utils/codegen-diff135
-rw-r--r--contrib/llvm/utils/count/CMakeLists.txt3
-rw-r--r--contrib/llvm/utils/count/Makefile20
-rw-r--r--contrib/llvm/utils/count/count.c50
-rwxr-xr-xcontrib/llvm/utils/countloc.sh40
-rw-r--r--contrib/llvm/utils/crosstool/ARM/README37
-rwxr-xr-xcontrib/llvm/utils/crosstool/ARM/build-install-linux.sh200
-rwxr-xr-xcontrib/llvm/utils/crosstool/create-snapshots.sh41
-rw-r--r--contrib/llvm/utils/emacs/README27
-rw-r--r--contrib/llvm/utils/emacs/emacs.el39
-rw-r--r--contrib/llvm/utils/emacs/llvm-mode.el128
-rw-r--r--contrib/llvm/utils/emacs/tablegen-mode.el124
-rwxr-xr-xcontrib/llvm/utils/findmisopt178
-rwxr-xr-xcontrib/llvm/utils/findoptdiff101
-rwxr-xr-xcontrib/llvm/utils/findsym.pl33
-rw-r--r--contrib/llvm/utils/fpcmp/Makefile16
-rw-r--r--contrib/llvm/utils/fpcmp/fpcmp.cpp43
-rwxr-xr-xcontrib/llvm/utils/getsrcs.sh34
-rwxr-xr-xcontrib/llvm/utils/git/find-rev50
-rw-r--r--contrib/llvm/utils/importNLT.pl86
-rw-r--r--contrib/llvm/utils/jedit/README14
-rw-r--r--contrib/llvm/utils/jedit/tablegen.xml39
-rw-r--r--contrib/llvm/utils/lint/common_lint.py97
-rwxr-xr-xcontrib/llvm/utils/lint/cpp_lint.py94
-rwxr-xr-xcontrib/llvm/utils/lint/generic_lint.py24
-rwxr-xr-xcontrib/llvm/utils/lint/remove_trailing_whitespace.sh6
-rw-r--r--contrib/llvm/utils/lit/TODO19
-rwxr-xr-xcontrib/llvm/utils/lit/lit.py5
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests.ObjDir/lit.site.cfg15
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/Clang/fsyntax-only.c4
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/Clang/lit.cfg47
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/bar-test.ll3
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/dg.exp6
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg151
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.site.cfg10
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp28
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/lit.local.cfg1
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/Foo/lit.local.cfg0
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg11
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp28
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/data.txt1
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/dg.exp6
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/pct-S.ll1
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/lit.cfg151
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/ShExternal/lit.local.cfg6
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/ShInternal/lit.local.cfg6
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg5
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/TclTest/stderr-pipe.ll1
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll7
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/fail.c2
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/lit.cfg26
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/pass.c1
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/required-and-missing.c4
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/required-and-present.c2
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/xfail.c2
-rw-r--r--contrib/llvm/utils/lit/lit/ExampleTests/xpass.c2
-rw-r--r--contrib/llvm/utils/lit/lit/LitConfig.py112
-rw-r--r--contrib/llvm/utils/lit/lit/LitFormats.py2
-rw-r--r--contrib/llvm/utils/lit/lit/LitTestCase.py30
-rw-r--r--contrib/llvm/utils/lit/lit/ProgressBar.py267
-rw-r--r--contrib/llvm/utils/lit/lit/ShCommands.py85
-rw-r--r--contrib/llvm/utils/lit/lit/ShUtil.py353
-rw-r--r--contrib/llvm/utils/lit/lit/TclUtil.py322
-rw-r--r--contrib/llvm/utils/lit/lit/Test.py79
-rw-r--r--contrib/llvm/utils/lit/lit/TestFormats.py221
-rw-r--r--contrib/llvm/utils/lit/lit/TestRunner.py586
-rw-r--r--contrib/llvm/utils/lit/lit/TestingConfig.py101
-rw-r--r--contrib/llvm/utils/lit/lit/Util.py125
-rw-r--r--contrib/llvm/utils/lit/lit/__init__.py10
-rwxr-xr-xcontrib/llvm/utils/lit/lit/lit.py648
-rw-r--r--contrib/llvm/utils/lit/setup.py69
-rw-r--r--contrib/llvm/utils/llvm-lit/Makefile21
-rw-r--r--contrib/llvm/utils/llvm-lit/llvm-lit.in21
-rwxr-xr-xcontrib/llvm/utils/llvm-native-gcc249
-rwxr-xr-xcontrib/llvm/utils/llvm-native-gxx249
-rw-r--r--contrib/llvm/utils/llvm.grm418
-rwxr-xr-xcontrib/llvm/utils/llvmdo184
-rwxr-xr-xcontrib/llvm/utils/llvmgrep39
-rwxr-xr-xcontrib/llvm/utils/makellvm145
-rw-r--r--contrib/llvm/utils/not/CMakeLists.txt11
-rw-r--r--contrib/llvm/utils/not/Makefile21
-rw-r--r--contrib/llvm/utils/not/not.cpp17
-rw-r--r--contrib/llvm/utils/parseNLT.pl34
-rw-r--r--contrib/llvm/utils/plotNLT.pl53
-rwxr-xr-xcontrib/llvm/utils/profile.pl74
-rw-r--r--contrib/llvm/utils/unittest/Makefile13
-rw-r--r--contrib/llvm/utils/unittest/UnitTestMain/Makefile30
-rw-r--r--contrib/llvm/utils/unittest/UnitTestMain/TestMain.cpp15
-rw-r--r--contrib/llvm/utils/unittest/googletest/LICENSE.TXT28
-rw-r--r--contrib/llvm/utils/unittest/googletest/Makefile39
-rw-r--r--contrib/llvm/utils/unittest/googletest/README.LLVM31
-rw-r--r--contrib/llvm/utils/unittest/googletest/gtest-death-test.cc1172
-rw-r--r--contrib/llvm/utils/unittest/googletest/gtest-filepath.cc380
-rw-r--r--contrib/llvm/utils/unittest/googletest/gtest-port.cc711
-rw-r--r--contrib/llvm/utils/unittest/googletest/gtest-test-part.cc110
-rw-r--r--contrib/llvm/utils/unittest/googletest/gtest-typed-test.cc110
-rw-r--r--contrib/llvm/utils/unittest/googletest/gtest.cc4704
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/gtest-death-test.h283
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/gtest-message.h230
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/gtest-param-test.h1397
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/gtest-spi.h232
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/gtest-test-part.h176
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/gtest-typed-test.h259
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/gtest.h2052
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/gtest_pred_impl.h368
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/gtest_prod.h58
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h275
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h210
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h1074
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-internal.h943
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h243
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h4820
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h619
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port.h1501
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-string.h350
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h968
-rw-r--r--contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h3321
-rw-r--r--contrib/llvm/utils/valgrind/i386-pc-linux-gnu.supp41
-rw-r--r--contrib/llvm/utils/valgrind/x86_64-pc-linux-gnu.supp46
-rw-r--r--contrib/llvm/utils/vim/README43
-rw-r--r--contrib/llvm/utils/vim/llvm.vim109
-rw-r--r--contrib/llvm/utils/vim/tablegen.vim54
-rw-r--r--contrib/llvm/utils/vim/vimrc220
-rwxr-xr-xcontrib/llvm/utils/webNLT.pl83
223 files changed, 72868 insertions, 0 deletions
diff --git a/contrib/llvm/utils/DSAclean.py b/contrib/llvm/utils/DSAclean.py
new file mode 100755
index 0000000..6c43357
--- /dev/null
+++ b/contrib/llvm/utils/DSAclean.py
@@ -0,0 +1,32 @@
+#! /usr/bin/python
+
+#changelog:
+#10/13/2005b: replaced the # in tmp(.#*)* with alphanumeric and _, this will then remove
+#nodes such as %tmp.1.i and %tmp._i.3
+#10/13/2005: exntended to remove variables of the form %tmp(.#)* rather than just
+#%tmp.#, i.e. it now will remove %tmp.12.3.15 etc, additionally fixed a spelling error in
+#the comments
+#10/12/2005: now it only removes nodes and edges for which the label is %tmp.# rather
+#than removing all lines for which the lable CONTAINS %tmp.#
+import re
+import sys
+if( len(sys.argv) < 3 ):
+ print 'usage is: ./DSAclean <dot_file_to_be_cleaned> <out_put_file>'
+ sys.exit(1)
+#get a file object
+input = open(sys.argv[1], 'r')
+output = open(sys.argv[2], 'w')
+#we'll get this one line at a time...while we could just put the whole thing in a string
+#it would kill old computers
+buffer = input.readline()
+while buffer != '':
+ if re.compile("label(\s*)=(\s*)\"\s%tmp(.\w*)*(\s*)\"").search(buffer):
+ #skip next line, write neither this line nor the next
+ buffer = input.readline()
+ else:
+ #this isn't a tmp Node, we can write it
+ output.write(buffer)
+ #prepare for the next iteration
+ buffer = input.readline()
+input.close()
+output.close()
diff --git a/contrib/llvm/utils/DSAextract.py b/contrib/llvm/utils/DSAextract.py
new file mode 100644
index 0000000..134e945
--- /dev/null
+++ b/contrib/llvm/utils/DSAextract.py
@@ -0,0 +1,111 @@
+#! /usr/bin/python
+
+#this is a script to extract given named nodes from a dot file, with
+#the associated edges. An edge is kept iff for edge x -> y
+# x and y are both nodes specified to be kept.
+
+#known issues: if a line contains '->' and is not an edge line
+#problems will occur. If node labels do not begin with
+#Node this also will not work. Since this is designed to work
+#on DSA dot output and not general dot files this is ok.
+#If you want to use this on other files rename the node labels
+#to Node[.*] with a script or something. This also relies on
+#the length of a node name being 13 characters (as it is in all
+#DSA dot output files)
+
+#Note that the name of the node can be any substring of the actual
+#name in the dot file. Thus if you say specify COLLAPSED
+#as a parameter this script will pull out all COLLAPSED
+#nodes in the file
+
+#Specifying escape characters in the name like \n also will not work,
+#as Python
+#will make it \\n, I'm not really sure how to fix this
+
+#currently the script prints the names it is searching for
+#to STDOUT, so you can check to see if they are what you intend
+
+import re
+import string
+import sys
+
+
+if len(sys.argv) < 3:
+ print 'usage is ./DSAextract <dot_file_to_modify> \
+ <output_file> [list of nodes to extract]'
+
+#open the input file
+input = open(sys.argv[1], 'r')
+
+#construct a set of node names
+node_name_set = set()
+for name in sys.argv[3:]:
+ node_name_set |= set([name])
+
+#construct a list of compiled regular expressions from the
+#node_name_set
+regexp_list = []
+for name in node_name_set:
+ regexp_list.append(re.compile(name))
+
+#used to see what kind of line we are on
+nodeexp = re.compile('Node')
+#used to check to see if the current line is an edge line
+arrowexp = re.compile('->')
+
+node_set = set()
+
+#read the file one line at a time
+buffer = input.readline()
+while buffer != '':
+ #filter out the unecessary checks on all the edge lines
+ if not arrowexp.search(buffer):
+ #check to see if this is a node we are looking for
+ for regexp in regexp_list:
+ #if this name is for the current node, add the dot variable name
+ #for the node (it will be Node(hex number)) to our set of nodes
+ if regexp.search(buffer):
+ node_set |= set([re.split('\s+',buffer,2)[1]])
+ break
+ buffer = input.readline()
+
+
+#test code
+#print '\n'
+
+print node_name_set
+
+#print node_set
+
+
+#open the output file
+output = open(sys.argv[2], 'w')
+#start the second pass over the file
+input = open(sys.argv[1], 'r')
+
+buffer = input.readline()
+while buffer != '':
+ #there are three types of lines we are looking for
+ #1) node lines, 2) edge lines 3) support lines (like page size, etc)
+
+ #is this an edge line?
+ #note that this is no completely robust, if a none edge line
+ #for some reason contains -> it will be missidentified
+ #hand edit the file if this happens
+ if arrowexp.search(buffer):
+ #check to make sure that both nodes are in the node list
+ #if they are print this to output
+ nodes = arrowexp.split(buffer)
+ nodes[0] = string.strip(nodes[0])
+ nodes[1] = string.strip(nodes[1])
+ if nodes[0][:13] in node_set and \
+ nodes[1][:13] in node_set:
+ output.write(buffer)
+ elif nodeexp.search(buffer): #this is a node line
+ node = re.split('\s+', buffer,2)[1]
+ if node in node_set:
+ output.write(buffer)
+ else: #this is a support line
+ output.write(buffer)
+ buffer = input.readline()
+
diff --git a/contrib/llvm/utils/FileCheck/CMakeLists.txt b/contrib/llvm/utils/FileCheck/CMakeLists.txt
new file mode 100644
index 0000000..8fee03f
--- /dev/null
+++ b/contrib/llvm/utils/FileCheck/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_executable(FileCheck
+ FileCheck.cpp
+ )
+
+target_link_libraries(FileCheck LLVMSupport LLVMSystem)
+if( MINGW )
+ target_link_libraries(FileCheck imagehlp psapi)
+endif( MINGW )
+if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD )
+ target_link_libraries(FileCheck pthread)
+endif()
diff --git a/contrib/llvm/utils/FileCheck/FileCheck.cpp b/contrib/llvm/utils/FileCheck/FileCheck.cpp
new file mode 100644
index 0000000..cd76d44
--- /dev/null
+++ b/contrib/llvm/utils/FileCheck/FileCheck.cpp
@@ -0,0 +1,732 @@
+//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// FileCheck does a line-by line check of a file that validates whether it
+// contains the expected content. This is useful for regression tests etc.
+//
+// This program exits with an error status of 2 on error, exit status of 0 if
+// the file matched the expected contents, and exit status of 1 if it did not
+// contain the expected contents.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Signals.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include <algorithm>
+using namespace llvm;
+
+static cl::opt<std::string>
+CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);
+
+static cl::opt<std::string>
+InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
+ cl::init("-"), cl::value_desc("filename"));
+
+static cl::opt<std::string>
+CheckPrefix("check-prefix", cl::init("CHECK"),
+ cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
+
+static cl::opt<bool>
+NoCanonicalizeWhiteSpace("strict-whitespace",
+ cl::desc("Do not treat all horizontal whitespace as equivalent"));
+
+//===----------------------------------------------------------------------===//
+// Pattern Handling Code.
+//===----------------------------------------------------------------------===//
+
+class Pattern {
+ SMLoc PatternLoc;
+
+ /// FixedStr - If non-empty, this pattern is a fixed string match with the
+ /// specified fixed string.
+ StringRef FixedStr;
+
+ /// RegEx - If non-empty, this is a regex pattern.
+ std::string RegExStr;
+
+ /// VariableUses - Entries in this vector map to uses of a variable in the
+ /// pattern, e.g. "foo[[bar]]baz". In this case, the RegExStr will contain
+ /// "foobaz" and we'll get an entry in this vector that tells us to insert the
+ /// value of bar at offset 3.
+ std::vector<std::pair<StringRef, unsigned> > VariableUses;
+
+ /// VariableDefs - Entries in this vector map to definitions of a variable in
+ /// the pattern, e.g. "foo[[bar:.*]]baz". In this case, the RegExStr will
+ /// contain "foo(.*)baz" and VariableDefs will contain the pair "bar",1. The
+ /// index indicates what parenthesized value captures the variable value.
+ std::vector<std::pair<StringRef, unsigned> > VariableDefs;
+
+public:
+
+ Pattern() { }
+
+ bool ParsePattern(StringRef PatternStr, SourceMgr &SM);
+
+ /// Match - Match the pattern string against the input buffer Buffer. This
+ /// returns the position that is matched or npos if there is no match. If
+ /// there is a match, the size of the matched string is returned in MatchLen.
+ ///
+ /// The VariableTable StringMap provides the current values of filecheck
+ /// variables and is updated if this match defines new values.
+ size_t Match(StringRef Buffer, size_t &MatchLen,
+ StringMap<StringRef> &VariableTable) const;
+
+ /// PrintFailureInfo - Print additional information about a failure to match
+ /// involving this pattern.
+ void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
+ const StringMap<StringRef> &VariableTable) const;
+
+private:
+ static void AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr);
+ bool AddRegExToRegEx(StringRef RegExStr, unsigned &CurParen, SourceMgr &SM);
+
+ /// ComputeMatchDistance - Compute an arbitrary estimate for the quality of
+ /// matching this pattern at the start of \arg Buffer; a distance of zero
+ /// should correspond to a perfect match.
+ unsigned ComputeMatchDistance(StringRef Buffer,
+ const StringMap<StringRef> &VariableTable) const;
+};
+
+
+bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
+ PatternLoc = SMLoc::getFromPointer(PatternStr.data());
+
+ // Ignore trailing whitespace.
+ while (!PatternStr.empty() &&
+ (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
+ PatternStr = PatternStr.substr(0, PatternStr.size()-1);
+
+ // Check that there is something on the line.
+ if (PatternStr.empty()) {
+ SM.PrintMessage(PatternLoc, "found empty check string with prefix '" +
+ CheckPrefix+":'", "error");
+ return true;
+ }
+
+ // Check to see if this is a fixed string, or if it has regex pieces.
+ if (PatternStr.size() < 2 ||
+ (PatternStr.find("{{") == StringRef::npos &&
+ PatternStr.find("[[") == StringRef::npos)) {
+ FixedStr = PatternStr;
+ return false;
+ }
+
+ // Paren value #0 is for the fully matched string. Any new parenthesized
+ // values add from their.
+ unsigned CurParen = 1;
+
+ // Otherwise, there is at least one regex piece. Build up the regex pattern
+ // by escaping scary characters in fixed strings, building up one big regex.
+ while (!PatternStr.empty()) {
+ // RegEx matches.
+ if (PatternStr.size() >= 2 &&
+ PatternStr[0] == '{' && PatternStr[1] == '{') {
+
+ // Otherwise, this is the start of a regex match. Scan for the }}.
+ size_t End = PatternStr.find("}}");
+ if (End == StringRef::npos) {
+ SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
+ "found start of regex string with no end '}}'", "error");
+ return true;
+ }
+
+ if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM))
+ return true;
+ PatternStr = PatternStr.substr(End+2);
+ continue;
+ }
+
+ // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .*
+ // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
+ // second form is [[foo]] which is a reference to foo. The variable name
+ // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
+ // it. This is to catch some common errors.
+ if (PatternStr.size() >= 2 &&
+ PatternStr[0] == '[' && PatternStr[1] == '[') {
+ // Verify that it is terminated properly.
+ size_t End = PatternStr.find("]]");
+ if (End == StringRef::npos) {
+ SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
+ "invalid named regex reference, no ]] found", "error");
+ return true;
+ }
+
+ StringRef MatchStr = PatternStr.substr(2, End-2);
+ PatternStr = PatternStr.substr(End+2);
+
+ // Get the regex name (e.g. "foo").
+ size_t NameEnd = MatchStr.find(':');
+ StringRef Name = MatchStr.substr(0, NameEnd);
+
+ if (Name.empty()) {
+ SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
+ "invalid name in named regex: empty name", "error");
+ return true;
+ }
+
+ // Verify that the name is well formed.
+ for (unsigned i = 0, e = Name.size(); i != e; ++i)
+ if (Name[i] != '_' &&
+ (Name[i] < 'a' || Name[i] > 'z') &&
+ (Name[i] < 'A' || Name[i] > 'Z') &&
+ (Name[i] < '0' || Name[i] > '9')) {
+ SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i),
+ "invalid name in named regex", "error");
+ return true;
+ }
+
+ // Name can't start with a digit.
+ if (isdigit(Name[0])) {
+ SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
+ "invalid name in named regex", "error");
+ return true;
+ }
+
+ // Handle [[foo]].
+ if (NameEnd == StringRef::npos) {
+ VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
+ continue;
+ }
+
+ // Handle [[foo:.*]].
+ VariableDefs.push_back(std::make_pair(Name, CurParen));
+ RegExStr += '(';
+ ++CurParen;
+
+ if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM))
+ return true;
+
+ RegExStr += ')';
+ }
+
+ // Handle fixed string matches.
+ // Find the end, which is the start of the next regex.
+ size_t FixedMatchEnd = PatternStr.find("{{");
+ FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
+ AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr);
+ PatternStr = PatternStr.substr(FixedMatchEnd);
+ continue;
+ }
+
+ return false;
+}
+
+void Pattern::AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr) {
+ // Add the characters from FixedStr to the regex, escaping as needed. This
+ // avoids "leaning toothpicks" in common patterns.
+ for (unsigned i = 0, e = FixedStr.size(); i != e; ++i) {
+ switch (FixedStr[i]) {
+ // These are the special characters matched in "p_ere_exp".
+ case '(':
+ case ')':
+ case '^':
+ case '$':
+ case '|':
+ case '*':
+ case '+':
+ case '?':
+ case '.':
+ case '[':
+ case '\\':
+ case '{':
+ TheStr += '\\';
+ // FALL THROUGH.
+ default:
+ TheStr += FixedStr[i];
+ break;
+ }
+ }
+}
+
+bool Pattern::AddRegExToRegEx(StringRef RegexStr, unsigned &CurParen,
+ SourceMgr &SM) {
+ Regex R(RegexStr);
+ std::string Error;
+ if (!R.isValid(Error)) {
+ SM.PrintMessage(SMLoc::getFromPointer(RegexStr.data()),
+ "invalid regex: " + Error, "error");
+ return true;
+ }
+
+ RegExStr += RegexStr.str();
+ CurParen += R.getNumMatches();
+ return false;
+}
+
+/// Match - Match the pattern string against the input buffer Buffer. This
+/// returns the position that is matched or npos if there is no match. If
+/// there is a match, the size of the matched string is returned in MatchLen.
+size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
+ StringMap<StringRef> &VariableTable) const {
+ // If this is a fixed string pattern, just match it now.
+ if (!FixedStr.empty()) {
+ MatchLen = FixedStr.size();
+ return Buffer.find(FixedStr);
+ }
+
+ // Regex match.
+
+ // If there are variable uses, we need to create a temporary string with the
+ // actual value.
+ StringRef RegExToMatch = RegExStr;
+ std::string TmpStr;
+ if (!VariableUses.empty()) {
+ TmpStr = RegExStr;
+
+ unsigned InsertOffset = 0;
+ for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
+ StringMap<StringRef>::iterator it =
+ VariableTable.find(VariableUses[i].first);
+ // If the variable is undefined, return an error.
+ if (it == VariableTable.end())
+ return StringRef::npos;
+
+ // Look up the value and escape it so that we can plop it into the regex.
+ std::string Value;
+ AddFixedStringToRegEx(it->second, Value);
+
+ // Plop it into the regex at the adjusted offset.
+ TmpStr.insert(TmpStr.begin()+VariableUses[i].second+InsertOffset,
+ Value.begin(), Value.end());
+ InsertOffset += Value.size();
+ }
+
+ // Match the newly constructed regex.
+ RegExToMatch = TmpStr;
+ }
+
+
+ SmallVector<StringRef, 4> MatchInfo;
+ if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
+ return StringRef::npos;
+
+ // Successful regex match.
+ assert(!MatchInfo.empty() && "Didn't get any match");
+ StringRef FullMatch = MatchInfo[0];
+
+ // If this defines any variables, remember their values.
+ for (unsigned i = 0, e = VariableDefs.size(); i != e; ++i) {
+ assert(VariableDefs[i].second < MatchInfo.size() &&
+ "Internal paren error");
+ VariableTable[VariableDefs[i].first] = MatchInfo[VariableDefs[i].second];
+ }
+
+ MatchLen = FullMatch.size();
+ return FullMatch.data()-Buffer.data();
+}
+
+unsigned Pattern::ComputeMatchDistance(StringRef Buffer,
+ const StringMap<StringRef> &VariableTable) const {
+ // Just compute the number of matching characters. For regular expressions, we
+ // just compare against the regex itself and hope for the best.
+ //
+ // FIXME: One easy improvement here is have the regex lib generate a single
+ // example regular expression which matches, and use that as the example
+ // string.
+ StringRef ExampleString(FixedStr);
+ if (ExampleString.empty())
+ ExampleString = RegExStr;
+
+ // Only compare up to the first line in the buffer, or the string size.
+ StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
+ BufferPrefix = BufferPrefix.split('\n').first;
+ return BufferPrefix.edit_distance(ExampleString);
+}
+
+void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
+ const StringMap<StringRef> &VariableTable) const{
+ // If this was a regular expression using variables, print the current
+ // variable values.
+ if (!VariableUses.empty()) {
+ for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
+ StringRef Var = VariableUses[i].first;
+ StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
+ SmallString<256> Msg;
+ raw_svector_ostream OS(Msg);
+
+ // Check for undefined variable references.
+ if (it == VariableTable.end()) {
+ OS << "uses undefined variable \"";
+ OS.write_escaped(Var) << "\"";;
+ } else {
+ OS << "with variable \"";
+ OS.write_escaped(Var) << "\" equal to \"";
+ OS.write_escaped(it->second) << "\"";
+ }
+
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), OS.str(), "note",
+ /*ShowLine=*/false);
+ }
+ }
+
+ // Attempt to find the closest/best fuzzy match. Usually an error happens
+ // because some string in the output didn't exactly match. In these cases, we
+ // would like to show the user a best guess at what "should have" matched, to
+ // save them having to actually check the input manually.
+ size_t NumLinesForward = 0;
+ size_t Best = StringRef::npos;
+ double BestQuality = 0;
+
+ // Use an arbitrary 4k limit on how far we will search.
+ for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
+ if (Buffer[i] == '\n')
+ ++NumLinesForward;
+
+ // Patterns have leading whitespace stripped, so skip whitespace when
+ // looking for something which looks like a pattern.
+ if (Buffer[i] == ' ' || Buffer[i] == '\t')
+ continue;
+
+ // Compute the "quality" of this match as an arbitrary combination of the
+ // match distance and the number of lines skipped to get to this match.
+ unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable);
+ double Quality = Distance + (NumLinesForward / 100.);
+
+ if (Quality < BestQuality || Best == StringRef::npos) {
+ Best = i;
+ BestQuality = Quality;
+ }
+ }
+
+ // Print the "possible intended match here" line if we found something
+ // reasonable and not equal to what we showed in the "scanning from here"
+ // line.
+ if (Best && Best != StringRef::npos && BestQuality < 50) {
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best),
+ "possible intended match here", "note");
+
+ // FIXME: If we wanted to be really friendly we would show why the match
+ // failed, as it can be hard to spot simple one character differences.
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Check Strings.
+//===----------------------------------------------------------------------===//
+
+/// CheckString - This is a check that we found in the input file.
+struct CheckString {
+ /// Pat - The pattern to match.
+ Pattern Pat;
+
+ /// Loc - The location in the match file that the check string was specified.
+ SMLoc Loc;
+
+ /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
+ /// to a CHECK: directive.
+ bool IsCheckNext;
+
+ /// NotStrings - These are all of the strings that are disallowed from
+ /// occurring between this match string and the previous one (or start of
+ /// file).
+ std::vector<std::pair<SMLoc, Pattern> > NotStrings;
+
+ CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
+ : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
+};
+
+/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
+/// memory buffer, free it, and return a new one.
+static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
+ SmallString<128> NewFile;
+ NewFile.reserve(MB->getBufferSize());
+
+ for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
+ Ptr != End; ++Ptr) {
+ // If C is not a horizontal whitespace, skip it.
+ if (*Ptr != ' ' && *Ptr != '\t') {
+ NewFile.push_back(*Ptr);
+ continue;
+ }
+
+ // Otherwise, add one space and advance over neighboring space.
+ NewFile.push_back(' ');
+ while (Ptr+1 != End &&
+ (Ptr[1] == ' ' || Ptr[1] == '\t'))
+ ++Ptr;
+ }
+
+ // Free the old buffer and return a new one.
+ MemoryBuffer *MB2 =
+ MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier());
+
+ delete MB;
+ return MB2;
+}
+
+
+/// ReadCheckFile - Read the check file, which specifies the sequence of
+/// expected strings. The strings are added to the CheckStrings vector.
+static bool ReadCheckFile(SourceMgr &SM,
+ std::vector<CheckString> &CheckStrings) {
+ // Open the check file, and tell SourceMgr about it.
+ std::string ErrorStr;
+ MemoryBuffer *F =
+ MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr);
+ if (F == 0) {
+ errs() << "Could not open check file '" << CheckFilename << "': "
+ << ErrorStr << '\n';
+ return true;
+ }
+
+ // If we want to canonicalize whitespace, strip excess whitespace from the
+ // buffer containing the CHECK lines.
+ if (!NoCanonicalizeWhiteSpace)
+ F = CanonicalizeInputFile(F);
+
+ SM.AddNewSourceBuffer(F, SMLoc());
+
+ // Find all instances of CheckPrefix followed by : in the file.
+ StringRef Buffer = F->getBuffer();
+
+ std::vector<std::pair<SMLoc, Pattern> > NotMatches;
+
+ while (1) {
+ // See if Prefix occurs in the memory buffer.
+ Buffer = Buffer.substr(Buffer.find(CheckPrefix));
+
+ // If we didn't find a match, we're done.
+ if (Buffer.empty())
+ break;
+
+ const char *CheckPrefixStart = Buffer.data();
+
+ // When we find a check prefix, keep track of whether we find CHECK: or
+ // CHECK-NEXT:
+ bool IsCheckNext = false, IsCheckNot = false;
+
+ // Verify that the : is present after the prefix.
+ if (Buffer[CheckPrefix.size()] == ':') {
+ Buffer = Buffer.substr(CheckPrefix.size()+1);
+ } else if (Buffer.size() > CheckPrefix.size()+6 &&
+ memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
+ Buffer = Buffer.substr(CheckPrefix.size()+7);
+ IsCheckNext = true;
+ } else if (Buffer.size() > CheckPrefix.size()+5 &&
+ memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
+ Buffer = Buffer.substr(CheckPrefix.size()+6);
+ IsCheckNot = true;
+ } else {
+ Buffer = Buffer.substr(1);
+ continue;
+ }
+
+ // Okay, we found the prefix, yay. Remember the rest of the line, but
+ // ignore leading and trailing whitespace.
+ Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
+
+ // Scan ahead to the end of line.
+ size_t EOL = Buffer.find_first_of("\n\r");
+
+ // Remember the location of the start of the pattern, for diagnostics.
+ SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
+
+ // Parse the pattern.
+ Pattern P;
+ if (P.ParsePattern(Buffer.substr(0, EOL), SM))
+ return true;
+
+ Buffer = Buffer.substr(EOL);
+
+
+ // Verify that CHECK-NEXT lines have at least one CHECK line before them.
+ if (IsCheckNext && CheckStrings.empty()) {
+ SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
+ "found '"+CheckPrefix+"-NEXT:' without previous '"+
+ CheckPrefix+ ": line", "error");
+ return true;
+ }
+
+ // Handle CHECK-NOT.
+ if (IsCheckNot) {
+ NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
+ P));
+ continue;
+ }
+
+
+ // Okay, add the string we captured to the output vector and move on.
+ CheckStrings.push_back(CheckString(P,
+ PatternLoc,
+ IsCheckNext));
+ std::swap(NotMatches, CheckStrings.back().NotStrings);
+ }
+
+ if (CheckStrings.empty()) {
+ errs() << "error: no check strings found with prefix '" << CheckPrefix
+ << ":'\n";
+ return true;
+ }
+
+ if (!NotMatches.empty()) {
+ errs() << "error: '" << CheckPrefix
+ << "-NOT:' not supported after last check line.\n";
+ return true;
+ }
+
+ return false;
+}
+
+static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
+ StringRef Buffer,
+ StringMap<StringRef> &VariableTable) {
+ // Otherwise, we have an error, emit an error message.
+ SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
+ "error");
+
+ // Print the "scanning from here" line. If the current position is at the
+ // end of a line, advance to the start of the next line.
+ Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
+
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
+ "note");
+
+ // Allow the pattern to print additional information if desired.
+ CheckStr.Pat.PrintFailureInfo(SM, Buffer, VariableTable);
+}
+
+/// CountNumNewlinesBetween - Count the number of newlines in the specified
+/// range.
+static unsigned CountNumNewlinesBetween(StringRef Range) {
+ unsigned NumNewLines = 0;
+ while (1) {
+ // Scan for newline.
+ Range = Range.substr(Range.find_first_of("\n\r"));
+ if (Range.empty()) return NumNewLines;
+
+ ++NumNewLines;
+
+ // Handle \n\r and \r\n as a single newline.
+ if (Range.size() > 1 &&
+ (Range[1] == '\n' || Range[1] == '\r') &&
+ (Range[0] != Range[1]))
+ Range = Range.substr(1);
+ Range = Range.substr(1);
+ }
+}
+
+int main(int argc, char **argv) {
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ cl::ParseCommandLineOptions(argc, argv);
+
+ SourceMgr SM;
+
+ // Read the expected strings from the check file.
+ std::vector<CheckString> CheckStrings;
+ if (ReadCheckFile(SM, CheckStrings))
+ return 2;
+
+ // Open the file to check and add it to SourceMgr.
+ std::string ErrorStr;
+ MemoryBuffer *F =
+ MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
+ if (F == 0) {
+ errs() << "Could not open input file '" << InputFilename << "': "
+ << ErrorStr << '\n';
+ return true;
+ }
+
+ // Remove duplicate spaces in the input file if requested.
+ if (!NoCanonicalizeWhiteSpace)
+ F = CanonicalizeInputFile(F);
+
+ SM.AddNewSourceBuffer(F, SMLoc());
+
+ /// VariableTable - This holds all the current filecheck variables.
+ StringMap<StringRef> VariableTable;
+
+ // Check that we have all of the expected strings, in order, in the input
+ // file.
+ StringRef Buffer = F->getBuffer();
+
+ const char *LastMatch = Buffer.data();
+
+ for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
+ const CheckString &CheckStr = CheckStrings[StrNo];
+
+ StringRef SearchFrom = Buffer;
+
+ // Find StrNo in the file.
+ size_t MatchLen = 0;
+ Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen, VariableTable));
+
+ // If we didn't find a match, reject the input.
+ if (Buffer.empty()) {
+ PrintCheckFailed(SM, CheckStr, SearchFrom, VariableTable);
+ return 1;
+ }
+
+ StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);
+
+ // If this check is a "CHECK-NEXT", verify that the previous match was on
+ // the previous line (i.e. that there is one newline between them).
+ if (CheckStr.IsCheckNext) {
+ // Count the number of newlines between the previous match and this one.
+ assert(LastMatch != F->getBufferStart() &&
+ "CHECK-NEXT can't be the first check in a file");
+
+ unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
+ if (NumNewLines == 0) {
+ SM.PrintMessage(CheckStr.Loc,
+ CheckPrefix+"-NEXT: is on the same line as previous match",
+ "error");
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
+ "'next' match was here", "note");
+ SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
+ "previous match was here", "note");
+ return 1;
+ }
+
+ if (NumNewLines != 1) {
+ SM.PrintMessage(CheckStr.Loc,
+ CheckPrefix+
+ "-NEXT: is not on the line after the previous match",
+ "error");
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
+ "'next' match was here", "note");
+ SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
+ "previous match was here", "note");
+ return 1;
+ }
+ }
+
+ // If this match had "not strings", verify that they don't exist in the
+ // skipped region.
+ for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size();
+ ChunkNo != e; ++ChunkNo) {
+ size_t MatchLen = 0;
+ size_t Pos = CheckStr.NotStrings[ChunkNo].second.Match(SkippedRegion,
+ MatchLen,
+ VariableTable);
+ if (Pos == StringRef::npos) continue;
+
+ SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
+ CheckPrefix+"-NOT: string occurred!", "error");
+ SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first,
+ CheckPrefix+"-NOT: pattern specified here", "note");
+ return 1;
+ }
+
+
+ // Otherwise, everything is good. Step over the matched text and remember
+ // the position after the match as the end of the last match.
+ Buffer = Buffer.substr(MatchLen);
+ LastMatch = Buffer.data();
+ }
+
+ return 0;
+}
diff --git a/contrib/llvm/utils/FileCheck/Makefile b/contrib/llvm/utils/FileCheck/Makefile
new file mode 100644
index 0000000..f1af5b6
--- /dev/null
+++ b/contrib/llvm/utils/FileCheck/Makefile
@@ -0,0 +1,21 @@
+##===- utils/FileCheck/Makefile ----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TOOLNAME = FileCheck
+USEDLIBS = LLVMSupport.a LLVMSystem.a
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+# Don't install this utility
+NO_INSTALL = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/contrib/llvm/utils/FileUpdate/CMakeLists.txt b/contrib/llvm/utils/FileUpdate/CMakeLists.txt
new file mode 100644
index 0000000..bacbd16
--- /dev/null
+++ b/contrib/llvm/utils/FileUpdate/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_executable(FileUpdate
+ FileUpdate.cpp
+ )
+
+target_link_libraries(FileUpdate LLVMSupport LLVMSystem)
+if( MINGW )
+ target_link_libraries(FileUpdate imagehlp psapi)
+endif( MINGW )
+if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD )
+ target_link_libraries(FileUpdate pthread)
+endif()
diff --git a/contrib/llvm/utils/FileUpdate/FileUpdate.cpp b/contrib/llvm/utils/FileUpdate/FileUpdate.cpp
new file mode 100644
index 0000000..2cf366f
--- /dev/null
+++ b/contrib/llvm/utils/FileUpdate/FileUpdate.cpp
@@ -0,0 +1,87 @@
+//===- FileUpdate.cpp - Conditionally update a file -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// FileUpdate is a utility for conditionally updating a file from its input
+// based on whether the input differs from the output. It is used to avoid
+// unnecessary modifications in a build system.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Signals.h"
+using namespace llvm;
+
+static cl::opt<bool>
+Quiet("quiet", cl::desc("Don't print unnecessary status information"),
+ cl::init(false));
+
+static cl::opt<std::string>
+InputFilename("input-file", cl::desc("Input file (defaults to stdin)"),
+ cl::init("-"), cl::value_desc("filename"));
+
+static cl::opt<std::string>
+OutputFilename(cl::Positional, cl::desc("<output-file>"), cl::Required);
+
+int main(int argc, char **argv) {
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ cl::ParseCommandLineOptions(argc, argv);
+
+ if (OutputFilename == "-") {
+ errs() << argv[0] << ": error: Can't update standard output\n";
+ return 1;
+ }
+
+ // Get the input data.
+ std::string ErrorStr;
+ MemoryBuffer *In =
+ MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
+ if (In == 0) {
+ errs() << argv[0] << ": error: Unable to get input '"
+ << InputFilename << "': " << ErrorStr << '\n';
+ return 1;
+ }
+
+ // Get the output data.
+ MemoryBuffer *Out = MemoryBuffer::getFile(OutputFilename.c_str(), &ErrorStr);
+
+ // If the output exists and the contents match, we are done.
+ if (Out && In->getBufferSize() == Out->getBufferSize() &&
+ memcmp(In->getBufferStart(), Out->getBufferStart(),
+ Out->getBufferSize()) == 0) {
+ if (!Quiet)
+ errs() << argv[0] << ": Not updating '" << OutputFilename
+ << "', contents match input.\n";
+ return 0;
+ }
+
+ delete Out;
+
+ // Otherwise, overwrite the output.
+ if (!Quiet)
+ errs() << argv[0] << ": Updating '" << OutputFilename
+ << "', contents changed.\n";
+ tool_output_file OutStream(OutputFilename.c_str(), ErrorStr,
+ raw_fd_ostream::F_Binary);
+ if (!ErrorStr.empty()) {
+ errs() << argv[0] << ": Unable to write output '"
+ << OutputFilename << "': " << ErrorStr << '\n';
+ return 1;
+ }
+
+ OutStream.os().write(In->getBufferStart(), In->getBufferSize());
+
+ // Declare success.
+ OutStream.keep();
+
+ return 0;
+}
diff --git a/contrib/llvm/utils/FileUpdate/Makefile b/contrib/llvm/utils/FileUpdate/Makefile
new file mode 100644
index 0000000..5b545c2
--- /dev/null
+++ b/contrib/llvm/utils/FileUpdate/Makefile
@@ -0,0 +1,21 @@
+##===- utils/FileUpdate/Makefile ---------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TOOLNAME = FileUpdate
+USEDLIBS = LLVMSupport.a LLVMSystem.a
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+# Don't install this utility
+NO_INSTALL = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/contrib/llvm/utils/GenLibDeps.pl b/contrib/llvm/utils/GenLibDeps.pl
new file mode 100755
index 0000000..f1f7e72
--- /dev/null
+++ b/contrib/llvm/utils/GenLibDeps.pl
@@ -0,0 +1,388 @@
+#!/usr/bin/perl -w
+#
+# Program: GenLibDeps.pl
+#
+# Synopsis: Generate HTML output that shows the dependencies between a set of
+# libraries. The output of this script should periodically replace
+# the similar content in the UsingLibraries.html document.
+#
+# Syntax: GenLibDeps.pl [-flat] <directory_with_libraries_in_it> [path_to_nm_binary]
+#
+use strict;
+use warnings;
+# Parse arguments...
+my $FLAT = 0;
+my $WHY = 0;
+my $PEROBJ = 0;
+my $PEROBJINCL = 0;
+while (scalar(@ARGV) and ($_ = $ARGV[0], /^[-+]/)) {
+ shift;
+ last if /^--$/; # Stop processing arguments on --
+
+ # List command line options here...
+ if (/^-flat$/) { $FLAT = 1; next; }
+ if (/^-why/) { $WHY = 1; $FLAT = 1; next; }
+ if (/^-perobj$/) { $PEROBJ = 1; next; }
+ if (/^-perobjincl/) { $PEROBJINCL = 1; next;}
+ print "Unknown option: $_ : ignoring!\n";
+}
+
+# Give first option a name.
+my $Directory = $ARGV[0];
+if (!defined($Directory) || ! -d "$Directory") {
+ die "First argument must specify the directory containing LLVM libs\n";
+}
+
+my $nmPath = $ARGV[1];
+
+# Find the "dot" program
+my $DotPath="";
+if (!$FLAT) {
+ chomp($DotPath = `which dot`);
+ die "Can't find 'dot'" if (! -x "$DotPath");
+}
+
+if (defined($ENV{NM})) {
+ chomp($nmPath=$ENV{NM});
+}
+
+if (!defined($nmPath) || $nmPath eq "") {
+ chomp($nmPath=`which nm`);
+ die "Can't find 'nm'" if (! -x "$nmPath");
+}
+
+my $ranlibPath;
+if ($PEROBJ) {
+ $ranlibPath = $ARGV[2];
+ if (defined($ENV{RANLIB})) {
+ chomp($ranlibPath=$ENV{RANLIB});
+ }
+
+ if (!defined($ranlibPath) || $ranlibPath eq "") {
+ chomp($ranlibPath=`which ranlib`);
+ die "Can't find 'ranlib'" if (! -x "$ranlibPath");
+ }
+}
+
+# Open the directory and read its contents, sorting by name and differentiating
+# by whether its a library (.a) or an object file (.o)
+opendir DIR,$Directory;
+my @files = readdir DIR;
+closedir DIR;
+my @libs = grep(/libLLVM.*\.(dylib|so|a)$/,sort(@files));
+# Omit the all-of-llvm shared library.
+@libs = grep(!/libLLVM-\d\.\d(svn)?\.(dylib|so)/, @libs);
+my @objs = grep(/LLVM.*\.o$/,sort(@files));
+
+# Declare the hashes we will use to keep track of the library and object file
+# symbol definitions.
+my %libdefs;
+my %objdefs;
+
+my %libobjs;
+my %objdeps=();
+# Gather library definitions at object file granularity (optional)
+if ($PEROBJ) {
+ foreach my $lib (@libs ) {
+ `$ranlibPath $Directory/$lib`;
+ my $libpath = $lib;
+ $libpath =~ s/^libLLVM(.*)\.a/$1/;
+ $libpath =~ s/(.+)CodeGen$/Target\/$1/;
+ $libpath =~ s/(.+)AsmPrinter$/Target\/$1\/AsmPrinter/;
+ $libpath =~ s/(.+)AsmParser$/Target\/$1\/AsmParser/;
+ $libpath =~ s/(.+)Info$/Target\/$1\/TargetInfo/;
+ $libpath =~ s/(.+)Disassembler$/Target\/$1\/Disassembler/;
+ $libpath =~ s/SelectionDAG/CodeGen\/SelectionDAG/;
+ $libpath =~ s/^AsmPrinter/CodeGen\/AsmPrinter/;
+ $libpath =~ s/^BitReader/Bitcode\/Reader/;
+ $libpath =~ s/^BitWriter/Bitcode\/Writer/;
+ $libpath =~ s/^CBackend/Target\/CBackend/;
+ $libpath =~ s/^CppBackend/Target\/CppBackend/;
+ $libpath =~ s/^MSIL/Target\/MSIL/;
+ $libpath =~ s/^Core/VMCore/;
+ $libpath =~ s/^Instrumentation/Transforms\/Instrumentation/;
+ $libpath =~ s/^Interpreter/ExecutionEngine\/Interpreter/;
+ $libpath =~ s/^JIT/ExecutionEngine\/JIT/;
+ $libpath =~ s/^ScalarOpts/Transforms\/Scalar/;
+ $libpath =~ s/^TransformUtils/Transforms\/Utils/;
+ $libpath =~ s/^ipa/Analysis\/IPA/;
+ $libpath =~ s/^ipo/Transforms\/IPO/;
+ $libpath =~ s/^pic16passes/Target\/PIC16\/PIC16Passes/;
+ $libpath = "lib/".$libpath."/";
+ open DEFS, "$nmPath -sg $Directory/$lib|";
+ while (<DEFS>) {
+ chomp;
+ if (/^([^ ]*) in ([^ ]*)/) {
+ my $objfile = $libpath.$2;
+ $objdefs{$1} = $objfile;
+ $objdeps{$objfile} = {};
+ $libobjs{$lib}{$objfile}=1;
+# my $p = "../llvm/".$objfile;
+# $p =~ s/Support\/reg(.*).o/Support\/reg$1.c/;
+# $p =~ s/.o$/.cpp/;
+# unless (-e $p) {
+# die "$p\n"
+# }
+ }
+ }
+ close DEFS or die "nm failed";
+ }
+ foreach my $lib (@libs ) {
+ my $libpath = $lib;
+ $libpath =~ s/^libLLVM(.*)\.a/$1/;
+ $libpath =~ s/(.+)CodeGen$/Target\/$1/;
+ $libpath =~ s/(.+)AsmPrinter$/Target\/$1\/AsmPrinter/;
+ $libpath =~ s/(.+)AsmParser$/Target\/$1\/AsmParser/;
+ $libpath =~ s/(.+)Info$/Target\/$1\/TargetInfo/;
+ $libpath =~ s/(.+)Disassembler$/Target\/$1\/Disassembler/;
+ $libpath =~ s/SelectionDAG/CodeGen\/SelectionDAG/;
+ $libpath =~ s/^AsmPrinter/CodeGen\/AsmPrinter/;
+ $libpath =~ s/^BitReader/Bitcode\/Reader/;
+ $libpath =~ s/^BitWriter/Bitcode\/Writer/;
+ $libpath =~ s/^CBackend/Target\/CBackend/;
+ $libpath =~ s/^CppBackend/Target\/CppBackend/;
+ $libpath =~ s/^MSIL/Target\/MSIL/;
+ $libpath =~ s/^Core/VMCore/;
+ $libpath =~ s/^Instrumentation/Transforms\/Instrumentation/;
+ $libpath =~ s/^Interpreter/ExecutionEngine\/Interpreter/;
+ $libpath =~ s/^JIT/ExecutionEngine\/JIT/;
+ $libpath =~ s/^ScalarOpts/Transforms\/Scalar/;
+ $libpath =~ s/^TransformUtils/Transforms\/Utils/;
+ $libpath =~ s/^ipa/Analysis\/IPA/;
+ $libpath =~ s/^ipo/Transforms\/IPO/;
+ $libpath =~ s/^pic16passes/Target\/PIC16\/PIC16Passes/;
+ $libpath = "lib/".$libpath."/";
+ open UDEFS, "$nmPath -Aup $Directory/$lib|";
+ while (<UDEFS>) {
+ chomp;
+ if (/:([^:]+):/) {
+ my $obj = $libpath.$1;
+ s/[^ ]+: *U //;
+ if (defined($objdefs{$_})) {
+ $objdeps{$obj}{$objdefs{$_}}=1;
+ }
+ }
+ }
+ close UDEFS or die "nm failed"
+ }
+} else {
+# Gather definitions from the libraries
+foreach my $lib (@libs ) {
+ open DEFS, "$nmPath -g $Directory/$lib|";
+ while (<DEFS>) {
+ next if (! / [ABCDGRST] /);
+ s/^[^ ]* [ABCDGRST] //;
+ s/\015?\012//; # not sure if <DEFS> is in binmode and uses LF or CRLF.
+ # this strips both LF and CRLF.
+ $libdefs{$_} = $lib;
+ }
+ close DEFS or die "nm failed";
+}
+}
+
+# Gather definitions from the object files.
+foreach my $obj (@objs ) {
+ open DEFS, "$nmPath -g $Directory/$obj |";
+ while (<DEFS>) {
+ next if (! / [ABCDGRST] /);
+ s/^[^ ]* [ABCDGRST] //;
+ s/\015?\012//; # not sure if <DEFS> is in binmode and uses LF or CRLF.
+ # this strips both LF and CRLF.
+ $objdefs{$_} = $obj;
+ }
+ close DEFS or die "nm failed";
+}
+
+# Generate one entry in the <dl> list. This generates the <dt> and <dd> elements
+# for one library or object file. The <dt> provides the name of the library or
+# object. The <dd> provides a list of the libraries/objects it depends on.
+sub gen_one_entry {
+ my $lib = $_[0];
+ my $lib_ns = $lib;
+ $lib_ns =~ s/(.*)\.[oa]/$1/;
+ if ($FLAT) {
+ print "$lib:";
+ if ($WHY) { print "\n"; }
+ } else {
+ print " <dt><b>$lib</b</dt><dd><ul>\n";
+ }
+ open UNDEFS,
+ "$nmPath -u $Directory/$lib | sed -e 's/^[ 0]* U //' | sort | uniq |";
+ my %DepLibs;
+ while (<UNDEFS>) {
+ chomp;
+ my $lib_printed = 0;
+ if (defined($libdefs{$_}) && $libdefs{$_} ne $lib) {
+ $DepLibs{$libdefs{$_}} = [] unless exists $DepLibs{$libdefs{$_}};
+ push(@{$DepLibs{$libdefs{$_}}}, $_);
+ } elsif (defined($objdefs{$_}) && $objdefs{$_} ne $lib) {
+ if ($PEROBJ && !$PEROBJINCL) {
+ # -perobjincl makes .a files depend on .o files they contain themselves
+ # default is don't depend on these.
+ next if defined $libobjs{$lib}{$objdefs{$_}};
+ }
+ my $libroot = $lib;
+ $libroot =~ s/lib(.*).a/$1/;
+ if ($objdefs{$_} ne "$libroot.o") {
+ $DepLibs{$objdefs{$_}} = [] unless exists $DepLibs{$objdefs{$_}};
+ push(@{$DepLibs{$objdefs{$_}}}, $_);
+ }
+ }
+ }
+ close UNDEFS or die "nm failed";
+ unless(keys %DepLibs) {
+ # above failed
+ open UNDEFS, "$nmPath -u $Directory/$lib |";
+ while (<UNDEFS>) {
+ # to bypass non-working sed
+ if (' ' eq substr($_,0,2) and index($_,'U ')) {
+ $_ = substr($_,index($_,'U ')+2)
+ };
+ $_ = substr($_,index($_,' *U ')+5) if -1!=index($_,' *U ');
+
+ chomp;
+ my $lib_printed = 0;
+ if (defined($libdefs{$_}) && $libdefs{$_} ne $lib) {
+ $DepLibs{$libdefs{$_}} = [] unless exists $DepLibs{$libdefs{$_}};
+ push(@{$DepLibs{$libdefs{$_}}}, $_);
+ } elsif (defined($objdefs{$_}) && $objdefs{$_} ne $lib) {
+ my $libroot = $lib;
+ $libroot =~ s/lib(.*).a/$1/;
+ if ($objdefs{$_} ne "$libroot.o") {
+ $DepLibs{$objdefs{$_}} = [] unless exists $DepLibs{$objdefs{$_}};
+ push(@{$DepLibs{$objdefs{$_}}}, $_);
+ }
+ }
+ }
+ close UNDEFS or die "nm failed";
+ }
+ if ($PEROBJINCL) {
+ # include the .a's objects
+ for my $obj (keys %{$libobjs{$lib}}) {
+ $DepLibs{$obj} = ["<.a object>"] unless exists $DepLibs{$obj};
+ }
+ my $madechange = 1;
+ while($madechange) {
+ $madechange = 0;
+ my %temp = %DepLibs;
+ foreach my $obj (keys %DepLibs) {
+ foreach my $objdeps (keys %{$objdeps{$obj}}) {
+ next if defined $temp{$objdeps};
+ push(@{$temp{$objdeps}}, $obj);
+ $madechange = 1;
+ }
+ }
+ %DepLibs = %temp;
+ }
+ }
+
+ for my $key (sort keys %DepLibs) {
+ if ($FLAT) {
+ print " $key";
+ if ($WHY) {
+ print "\n";
+ my @syms = @{$DepLibs{$key}};
+ foreach my $sym (@syms) {
+ print " $sym\n";
+ }
+ }
+ } else {
+ print " <li>$key</li>\n";
+ }
+ my $suffix = substr($key,length($key)-1,1);
+ $key =~ s/(.*)\.[oa]/$1/;
+ if ($suffix eq "a") {
+ if (!$FLAT) { print DOT "$lib_ns -> $key [ weight=0 ];\n" };
+ } else {
+ if (!$FLAT) { print DOT "$lib_ns -> $key [ weight=10];\n" };
+ }
+ }
+ if ($FLAT) {
+ if (!$WHY) {
+ print "\n";
+ }
+ } else {
+ print " </ul></dd>\n";
+ }
+}
+
+# Make sure we flush on write. This is slower but correct based on the way we
+# write I/O in gen_one_entry.
+$| = 1;
+
+# Print the definition list tag
+if (!$FLAT) {
+ print "<dl>\n";
+
+ open DOT, "| $DotPath -Tgif > libdeps.gif";
+
+ print DOT "digraph LibDeps {\n";
+ print DOT " size=\"40,15\"; \n";
+ print DOT " ratio=\"1.33333\"; \n";
+ print DOT " margin=\"0.25\"; \n";
+ print DOT " rankdir=\"LR\"; \n";
+ print DOT " mclimit=\"50.0\"; \n";
+ print DOT " ordering=\"out\"; \n";
+ print DOT " center=\"1\";\n";
+ print DOT "node [shape=\"box\",\n";
+ print DOT " color=\"#000088\",\n";
+ print DOT " fillcolor=\"#FFFACD\",\n";
+ print DOT " fontcolor=\"#3355BB\",\n";
+ print DOT " style=\"filled\",\n";
+ print DOT " fontname=\"sans\",\n";
+ print DOT " fontsize=\"24\"\n";
+ print DOT "];\n";
+ print DOT "edge [dir=\"forward\",style=\"solid\",color=\"#000088\"];\n";
+}
+
+# Print libraries first
+foreach my $lib (@libs) {
+ gen_one_entry($lib);
+}
+
+if ($PEROBJ) {
+ foreach my $obj (keys %objdeps) {
+ print "$obj:";
+ if (!$PEROBJINCL) {
+ foreach my $dep (keys %{$objdeps{$obj}}) {
+ print " $dep";
+ }
+ }
+ print "\n";
+ }
+}
+
+if (!$FLAT) {
+ print DOT "}\n";
+ close DOT;
+ open DOT, "| $DotPath -Tgif > objdeps.gif";
+ print DOT "digraph ObjDeps {\n";
+ print DOT " size=\"8,10\";\n";
+ print DOT " margin=\"0.25\";\n";
+ print DOT " rankdir=\"LR\";\n";
+ print DOT " mclimit=\"50.0\";\n";
+ print DOT " ordering=\"out\";\n";
+ print DOT " center=\"1\";\n";
+ print DOT "node [shape=\"box\",\n";
+ print DOT " color=\"#000088\",\n";
+ print DOT " fillcolor=\"#FFFACD\",\n";
+ print DOT " fontcolor=\"#3355BB\",\n";
+ print DOT " fontname=\"sans\",\n";
+ print DOT " style=\"filled\",\n";
+ print DOT " fontsize=\"24\"\n";
+ print DOT "];\n";
+ print DOT "edge [dir=\"forward\",style=\"solid\",color=\"#000088\"];\n";
+}
+
+# Print objects second
+foreach my $obj (@objs) {
+ gen_one_entry($obj);
+}
+
+if (!$FLAT) {
+ print DOT "}\n";
+ close DOT;
+
+# Print end tag of definition list element
+ print "</dl>\n";
+}
diff --git a/contrib/llvm/utils/GetSourceVersion b/contrib/llvm/utils/GetSourceVersion
new file mode 100755
index 0000000..b25f2f9
--- /dev/null
+++ b/contrib/llvm/utils/GetSourceVersion
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+usage() {
+ echo "usage: $0 <source root>"
+ echo " Prints the source control revision of the given source directory,"
+ echo " the exact format of the revision string depends on the source "
+ echo " control system. If the source control system isn't known, the output"
+ echo " is empty and the exit code is 1."
+ exit 1
+}
+
+if [ $# != 1 ] || [ ! -d $1 ]; then
+ usage;
+fi
+
+cd $1
+if [ -d .svn ]; then
+ svnversion
+elif [ -d .git/svn ]; then
+ git svn info | grep 'Revision:' | cut -d: -f2-
+elif [ -d .git ]; then
+ git log -1 --pretty=format:%H
+else
+ exit 1;
+fi
+
+exit 0
diff --git a/contrib/llvm/utils/Makefile b/contrib/llvm/utils/Makefile
new file mode 100644
index 0000000..1a4dcca
--- /dev/null
+++ b/contrib/llvm/utils/Makefile
@@ -0,0 +1,22 @@
+##===- utils/Makefile --------------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ..
+PARALLEL_DIRS := FileCheck FileUpdate TableGen PerfectShuffle \
+ count fpcmp llvm-lit not unittest
+
+EXTRA_DIST := cgiplotNLT.pl check-each-file codegen-diff countloc.sh \
+ DSAclean.py DSAextract.py emacs findsym.pl GenLibDeps.pl \
+ getsrcs.sh importNLT.pl llvmdo llvmgrep llvm-native-gcc \
+ llvm-native-gxx makellvm NightlyTest.gnuplot NightlyTest.pl \
+ NightlyTestTemplate.html NLT.schema OldenDataRecover.pl \
+ parseNLT.pl plotNLT.pl profile.pl \
+ webNLT.pl vim
+
+include $(LEVEL)/Makefile.common
diff --git a/contrib/llvm/utils/Misc/zkill b/contrib/llvm/utils/Misc/zkill
new file mode 100755
index 0000000..bc0bfd5
--- /dev/null
+++ b/contrib/llvm/utils/Misc/zkill
@@ -0,0 +1,276 @@
+#!/usr/bin/env python
+
+import os
+import re
+import sys
+
+def _write_message(kind, message):
+ import inspect, os, sys
+
+ # Get the file/line where this message was generated.
+ f = inspect.currentframe()
+ # Step out of _write_message, and then out of wrapper.
+ f = f.f_back.f_back
+ file,line,_,_,_ = inspect.getframeinfo(f)
+ location = '%s:%d' % (os.path.basename(file), line)
+
+ print >>sys.stderr, '%s: %s: %s' % (location, kind, message)
+
+note = lambda message: _write_message('note', message)
+warning = lambda message: _write_message('warning', message)
+error = lambda message: (_write_message('error', message), sys.exit(1))
+
+def re_full_match(pattern, str):
+ m = re.match(pattern, str)
+ if m and m.end() != len(str):
+ m = None
+ return m
+
+def parse_time(value):
+ minutes,value = value.split(':',1)
+ if '.' in value:
+ seconds,fseconds = value.split('.',1)
+ else:
+ seconds = value
+ return int(minutes) * 60 + int(seconds) + float('.'+fseconds)
+
+def extractExecutable(command):
+ """extractExecutable - Given a string representing a command line, attempt
+ to extract the executable path, even if it includes spaces."""
+
+ # Split into potential arguments.
+ args = command.split(' ')
+
+ # Scanning from the beginning, try to see if the first N args, when joined,
+ # exist. If so that's probably the executable.
+ for i in range(1,len(args)):
+ cmd = ' '.join(args[:i])
+ if os.path.exists(cmd):
+ return cmd
+
+ # Otherwise give up and return the first "argument".
+ return args[0]
+
+class Struct:
+ def __init__(self, **kwargs):
+ self.fields = kwargs.keys()
+ self.__dict__.update(kwargs)
+
+ def __repr__(self):
+ return 'Struct(%s)' % ', '.join(['%s=%r' % (k,getattr(self,k))
+ for k in self.fields])
+
+kExpectedPSFields = [('PID', int, 'pid'),
+ ('USER', str, 'user'),
+ ('COMMAND', str, 'command'),
+ ('%CPU', float, 'cpu_percent'),
+ ('TIME', parse_time, 'cpu_time'),
+ ('VSZ', int, 'vmem_size'),
+ ('RSS', int, 'rss')]
+def getProcessTable():
+ import subprocess
+ p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out,err = p.communicate()
+ res = p.wait()
+ if p.wait():
+ error('unable to get process table')
+ elif err.strip():
+ error('unable to get process table: %s' % err)
+
+ lns = out.split('\n')
+ it = iter(lns)
+ header = it.next().split()
+ numRows = len(header)
+
+ # Make sure we have the expected fields.
+ indexes = []
+ for field in kExpectedPSFields:
+ try:
+ indexes.append(header.index(field[0]))
+ except:
+ if opts.debug:
+ raise
+ error('unable to get process table, no %r field.' % field[0])
+
+ table = []
+ for i,ln in enumerate(it):
+ if not ln.strip():
+ continue
+
+ fields = ln.split(None, numRows - 1)
+ if len(fields) != numRows:
+ warning('unable to process row: %r' % ln)
+ continue
+
+ record = {}
+ for field,idx in zip(kExpectedPSFields, indexes):
+ value = fields[idx]
+ try:
+ record[field[2]] = field[1](value)
+ except:
+ if opts.debug:
+ raise
+ warning('unable to process %r in row: %r' % (field[0], ln))
+ break
+ else:
+ # Add our best guess at the executable.
+ record['executable'] = extractExecutable(record['command'])
+ table.append(Struct(**record))
+
+ return table
+
+def getSignalValue(name):
+ import signal
+ if name.startswith('SIG'):
+ value = getattr(signal, name)
+ if value and isinstance(value, int):
+ return value
+ error('unknown signal: %r' % name)
+
+import signal
+kSignals = {}
+for name in dir(signal):
+ if name.startswith('SIG') and name == name.upper() and name.isalpha():
+ kSignals[name[3:]] = getattr(signal, name)
+
+def main():
+ global opts
+ from optparse import OptionParser, OptionGroup
+ parser = OptionParser("usage: %prog [options] {pid}*")
+
+ # FIXME: Add -NNN and -SIGNAME options.
+
+ parser.add_option("-s", "", dest="signalName",
+ help="Name of the signal to use (default=%default)",
+ action="store", default='INT',
+ choices=kSignals.keys())
+ parser.add_option("-l", "", dest="listSignals",
+ help="List known signal names",
+ action="store_true", default=False)
+
+ parser.add_option("-n", "--dry-run", dest="dryRun",
+ help="Only print the actions that would be taken",
+ action="store_true", default=False)
+ parser.add_option("-v", "--verbose", dest="verbose",
+ help="Print more verbose output",
+ action="store_true", default=False)
+ parser.add_option("", "--debug", dest="debug",
+ help="Enable debugging output",
+ action="store_true", default=False)
+ parser.add_option("", "--force", dest="force",
+ help="Perform the specified commands, even if it seems like a bad idea",
+ action="store_true", default=False)
+
+ inf = float('inf')
+ group = OptionGroup(parser, "Process Filters")
+ group.add_option("", "--name", dest="execName", metavar="REGEX",
+ help="Kill processes whose name matches the given regexp",
+ action="store", default=None)
+ group.add_option("", "--exec", dest="execPath", metavar="REGEX",
+ help="Kill processes whose executable matches the given regexp",
+ action="store", default=None)
+ group.add_option("", "--user", dest="userName", metavar="REGEX",
+ help="Kill processes whose user matches the given regexp",
+ action="store", default=None)
+ group.add_option("", "--min-cpu", dest="minCPU", metavar="PCT",
+ help="Kill processes with CPU usage >= PCT",
+ action="store", type=float, default=None)
+ group.add_option("", "--max-cpu", dest="maxCPU", metavar="PCT",
+ help="Kill processes with CPU usage <= PCT",
+ action="store", type=float, default=inf)
+ group.add_option("", "--min-mem", dest="minMem", metavar="N",
+ help="Kill processes with virtual size >= N (MB)",
+ action="store", type=float, default=None)
+ group.add_option("", "--max-mem", dest="maxMem", metavar="N",
+ help="Kill processes with virtual size <= N (MB)",
+ action="store", type=float, default=inf)
+ group.add_option("", "--min-rss", dest="minRSS", metavar="N",
+ help="Kill processes with RSS >= N",
+ action="store", type=float, default=None)
+ group.add_option("", "--max-rss", dest="maxRSS", metavar="N",
+ help="Kill processes with RSS <= N",
+ action="store", type=float, default=inf)
+ group.add_option("", "--min-time", dest="minTime", metavar="N",
+ help="Kill processes with CPU time >= N (seconds)",
+ action="store", type=float, default=None)
+ group.add_option("", "--max-time", dest="maxTime", metavar="N",
+ help="Kill processes with CPU time <= N (seconds)",
+ action="store", type=float, default=inf)
+ parser.add_option_group(group)
+
+ (opts, args) = parser.parse_args()
+
+ if opts.listSignals:
+ items = [(v,k) for k,v in kSignals.items()]
+ items.sort()
+ for i in range(0, len(items), 4):
+ print '\t'.join(['%2d) SIG%s' % (k,v)
+ for k,v in items[i:i+4]])
+ sys.exit(0)
+
+ # Figure out the signal to use.
+ signal = kSignals[opts.signalName]
+ signalValueName = str(signal)
+ if opts.verbose:
+ name = dict((v,k) for k,v in kSignals.items()).get(signal,None)
+ if name:
+ signalValueName = name
+ note('using signal %d (SIG%s)' % (signal, name))
+ else:
+ note('using signal %d' % signal)
+
+ # Get the pid list to consider.
+ pids = set()
+ for arg in args:
+ try:
+ pids.add(int(arg))
+ except:
+ parser.error('invalid positional argument: %r' % arg)
+
+ filtered = ps = getProcessTable()
+
+ # Apply filters.
+ if pids:
+ filtered = [p for p in filtered
+ if p.pid in pids]
+ if opts.execName is not None:
+ filtered = [p for p in filtered
+ if re_full_match(opts.execName,
+ os.path.basename(p.executable))]
+ if opts.execPath is not None:
+ filtered = [p for p in filtered
+ if re_full_match(opts.execPath, p.executable)]
+ if opts.userName is not None:
+ filtered = [p for p in filtered
+ if re_full_match(opts.userName, p.user)]
+ filtered = [p for p in filtered
+ if opts.minCPU <= p.cpu_percent <= opts.maxCPU]
+ filtered = [p for p in filtered
+ if opts.minMem <= float(p.vmem_size) / (1<<20) <= opts.maxMem]
+ filtered = [p for p in filtered
+ if opts.minRSS <= p.rss <= opts.maxRSS]
+ filtered = [p for p in filtered
+ if opts.minTime <= p.cpu_time <= opts.maxTime]
+
+ if len(filtered) == len(ps):
+ if not opts.force and not opts.dryRun:
+ error('refusing to kill all processes without --force')
+
+ if not filtered:
+ warning('no processes selected')
+
+ for p in filtered:
+ if opts.verbose:
+ note('kill(%r, %s) # (user=%r, executable=%r, CPU=%2.2f%%, time=%r, vmem=%r, rss=%r)' %
+ (p.pid, signalValueName, p.user, p.executable, p.cpu_percent, p.cpu_time, p.vmem_size, p.rss))
+ if not opts.dryRun:
+ try:
+ os.kill(p.pid, signal)
+ except OSError:
+ if opts.debug:
+ raise
+ warning('unable to kill PID: %r' % p.pid)
+
+if __name__ == '__main__':
+ main()
diff --git a/contrib/llvm/utils/NLT.schema b/contrib/llvm/utils/NLT.schema
new file mode 100644
index 0000000..4bcddbc
--- /dev/null
+++ b/contrib/llvm/utils/NLT.schema
@@ -0,0 +1,8 @@
+CREATE TABLE `Tests` (
+ `NAME` varchar(255) NOT NULL default '',
+ `RUN` date NOT NULL default '0000-00-00',
+ `TEST` varchar(32) NOT NULL default '',
+ `VALUE` double NOT NULL default '0',
+ KEY `name_index` (`NAME`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
diff --git a/contrib/llvm/utils/NewNightlyTest.pl b/contrib/llvm/utils/NewNightlyTest.pl
new file mode 100755
index 0000000..1b48168
--- /dev/null
+++ b/contrib/llvm/utils/NewNightlyTest.pl
@@ -0,0 +1,836 @@
+#!/usr/bin/perl
+use POSIX qw(strftime);
+use File::Copy;
+use File::Find;
+use Socket;
+
+#
+# Program: NewNightlyTest.pl
+#
+# Synopsis: Perform a series of tests which are designed to be run nightly.
+# This is used to keep track of the status of the LLVM tree, tracking
+# regressions and performance changes. Submits this information
+# to llvm.org where it is placed into the nightlytestresults database.
+#
+# Syntax: NightlyTest.pl [OPTIONS] [CVSROOT BUILDDIR WEBDIR]
+# where
+# OPTIONS may include one or more of the following:
+#
+# MAIN OPTIONS:
+# -config LLVMPATH If specified, use an existing LLVM build and only run and
+# report the test information. The LLVMCONFIG argument should
+# be the path to the llvm-config executable in the LLVM build.
+# This should be the first argument if given. NOT YET
+# IMPLEMENTED.
+# -nickname NAME The NAME argument specifieds the nickname this script
+# will submit to the nightlytest results repository.
+# -nouname Don't include uname data (machine will be identified by nickname only).
+# -submit-server Specifies a server to submit the test results too. If this
+# option is not specified it defaults to
+# llvm.org. This is basically just the address of the
+# webserver
+# -submit-script Specifies which script to call on the submit server. If
+# this option is not specified it defaults to
+# /nightlytest/NightlyTestAccept.php. This is basically
+# everything after the www.yourserver.org.
+# -submit-aux If specified, an auxiliary script to run in addition to the
+# normal submit script. The script will be passed the path to
+# the "sentdata.txt" file as its sole argument.
+# -nosubmit Do not report the test results back to a submit server.
+#
+#
+# BUILD OPTIONS (not used with -config):
+# -nocheckout Do not create, checkout, update, or configure
+# the source tree.
+# -noremove Do not remove the BUILDDIR after it has been built.
+# -noremoveresults Do not remove the WEBDIR after it has been built.
+# -noclean Do not run 'make clean' before building.
+# -nobuild Do not build llvm. If tests are enabled perform them
+# on the llvm build specified in the build directory
+# -release Build an LLVM Release+Asserts version
+# -release-asserts Build an LLVM Release version
+# -disable-bindings Disable building LLVM bindings.
+# -with-clang Checkout Clang source into tools/clang.
+# -compileflags Next argument specifies extra options passed to make when
+# building LLVM.
+# -use-gmake Use gmake instead of the default make command to build
+# llvm and run tests.
+# -llvmgccdir Next argument specifies the llvm-gcc install prefix.
+#
+# TESTING OPTIONS:
+# -notest Do not even attempt to run the test programs.
+# -nodejagnu Do not run feature or regression tests
+# -enable-llcbeta Enable testing of beta features in llc.
+# -enable-lli Enable testing of lli (interpreter) features, default is off
+# -disable-pic Disable building with Position Independent Code.
+# -disable-llc Disable LLC tests in the nightly tester.
+# -disable-jit Disable JIT tests in the nightly tester.
+# -disable-cbe Disable C backend tests in the nightly tester.
+# -disable-lto Disable link time optimization.
+# -test-cflags Next argument specifies that C compilation options that
+# override the default when running the testsuite.
+# -test-cxxflags Next argument specifies that C++ compilation options that
+# override the default when running the testsuite.
+# -extraflags Next argument specifies extra options that are passed to
+# compile the tests.
+# -noexternals Do not run the external tests (for cases where povray
+# or SPEC are not installed)
+# -with-externals Specify a directory where the external tests are located.
+#
+# OTHER OPTIONS:
+# -parallel Run parallel jobs with GNU Make (see -parallel-jobs).
+# -parallel-jobs The number of parallel Make jobs to use (default is two).
+# -parallel-test Allow parallel execution of llvm-test
+# -verbose Turn on some debug output
+# -nice Checkout/Configure/Build with "nice" to reduce impact
+# on busy servers.
+# -f2c Next argument specifies path to F2C utility
+# -gccpath Path to gcc/g++ used to build LLVM
+# -target Specify the target triplet
+# -cflags Next argument specifies that C compilation options that
+# override the default.
+# -cxxflags Next argument specifies that C++ compilation options that
+# override the default.
+# -ldflags Next argument specifies that linker options that override
+# the default.
+#
+# CVSROOT is ignored, it is passed for backwards compatibility.
+# BUILDDIR is the directory where sources for this test run will be checked out
+# AND objects for this test run will be built. This directory MUST NOT
+# exist before the script is run; it will be created by the svn checkout
+# process and erased (unless -noremove is specified; see above.)
+# WEBDIR is the directory into which the test results web page will be written,
+# AND in which the "index.html" is assumed to be a symlink to the most recent
+# copy of the results. This directory will be created if it does not exist.
+# LLVMGCCDIR is the directory in which the LLVM GCC Front End is installed
+# to. This is the same as you would have for a normal LLVM build.
+#
+##############################################################
+#
+# Getting environment variables
+#
+##############################################################
+my $HOME = $ENV{'HOME'};
+my $SVNURL = $ENV{"SVNURL"};
+$SVNURL = 'http://llvm.org/svn/llvm-project' unless $SVNURL;
+my $TestSVNURL = $ENV{"TestSVNURL"};
+$TestSVNURL = 'http://llvm.org/svn/llvm-project' unless $TestSVNURL;
+my $BuildDir = $ENV{'BUILDDIR'};
+my $WebDir = $ENV{'WEBDIR'};
+
+##############################################################
+#
+# Calculate the date prefix...
+#
+##############################################################
+use POSIX;
+@TIME = localtime;
+my $DATE = strftime("%Y-%m-%d_%H-%M-%S", localtime());
+
+##############################################################
+#
+# Parse arguments...
+#
+##############################################################
+$CONFIG_PATH="";
+$CONFIGUREARGS="";
+$nickname="";
+$NOTEST=0;
+$MAKECMD="make";
+$SUBMITSERVER = "llvm.org";
+$SUBMITSCRIPT = "/nightlytest/NightlyTestAccept.php";
+$SUBMITAUX="";
+$SUBMIT = 1;
+$PARALLELJOBS = "2";
+my $TESTFLAGS="";
+
+if ($ENV{'LLVMGCCDIR'}) {
+ $CONFIGUREARGS .= " --with-llvmgccdir=" . $ENV{'LLVMGCCDIR'};
+ $LLVMGCCPATH = $ENV{'LLVMGCCDIR'} . '/bin';
+}
+else {
+ $LLVMGCCPATH = "";
+}
+
+while (scalar(@ARGV) and ($_ = $ARGV[0], /^[-+]/)) {
+ shift;
+ last if /^--$/; # Stop processing arguments on --
+
+ # List command line options here...
+ if (/^-config$/) { $CONFIG_PATH = "$ARGV[0]"; shift; next; }
+ if (/^-nocheckout$/) { $NOCHECKOUT = 1; next; }
+ if (/^-noclean$/) { $NOCLEAN = 1; next; }
+ if (/^-noremove$/) { $NOREMOVE = 1; next; }
+ if (/^-noremoveatend$/) { $NOREMOVEATEND = 1; next; }
+ if (/^-noremoveresults$/){ $NOREMOVERESULTS = 1; next; }
+ if (/^-notest$/) { $NOTEST = 1; next; }
+ if (/^-norunningtests$/) { next; } # Backward compatibility, ignored.
+ if (/^-parallel-jobs$/) { $PARALLELJOBS = "$ARGV[0]"; shift; next;}
+ if (/^-parallel$/) { $MAKEOPTS = "$MAKEOPTS -j$PARALLELJOBS"; next; }
+ if (/^-parallel-test$/) { $PROGTESTOPTS .= " ENABLE_PARALLEL_REPORT=1"; next; }
+ if (/^-with-clang$/) { $WITHCLANG = 1; next; }
+ if (/^-release$/) { $MAKEOPTS = "$MAKEOPTS ENABLE_OPTIMIZED=1 ".
+ "OPTIMIZE_OPTION=-O2"; next;}
+ if (/^-release-asserts$/){ $MAKEOPTS = "$MAKEOPTS ENABLE_OPTIMIZED=1 ".
+ "DISABLE_ASSERTIONS=1 ".
+ "OPTIMIZE_OPTION=-O2"; next;}
+ if (/^-enable-llcbeta$/) { $PROGTESTOPTS .= " ENABLE_LLCBETA=1"; next; }
+ if (/^-disable-pic$/) { $CONFIGUREARGS .= " --enable-pic=no"; next; }
+ if (/^-enable-lli$/) { $PROGTESTOPTS .= " ENABLE_LLI=1";
+ $CONFIGUREARGS .= " --enable-lli"; next; }
+ if (/^-disable-llc$/) { $PROGTESTOPTS .= " DISABLE_LLC=1";
+ $CONFIGUREARGS .= " --disable-llc_diffs"; next; }
+ if (/^-disable-jit$/) { $PROGTESTOPTS .= " DISABLE_JIT=1";
+ $CONFIGUREARGS .= " --disable-jit"; next; }
+ if (/^-disable-bindings$/) { $CONFIGUREARGS .= " --disable-bindings"; next; }
+ if (/^-disable-cbe$/) { $PROGTESTOPTS .= " DISABLE_CBE=1"; next; }
+ if (/^-disable-lto$/) { $PROGTESTOPTS .= " DISABLE_LTO=1"; next; }
+ if (/^-test-opts$/) { $PROGTESTOPTS .= " $ARGV[0]"; shift; next; }
+ if (/^-verbose$/) { $VERBOSE = 1; next; }
+ if (/^-teelogs$/) { $TEELOGS = 1; next; }
+ if (/^-nice$/) { $NICE = "nice "; next; }
+ if (/^-f2c$/) { $CONFIGUREARGS .= " --with-f2c=$ARGV[0]";
+ shift; next; }
+ if (/^-with-externals$/) { $CONFIGUREARGS .= " --with-externals=$ARGV[0]";
+ shift; next; }
+ if (/^-configure-args$/) { $CONFIGUREARGS .= " $ARGV[0]";
+ shift; next; }
+ if (/^-submit-server/) { $SUBMITSERVER = "$ARGV[0]"; shift; next; }
+ if (/^-submit-script/) { $SUBMITSCRIPT = "$ARGV[0]"; shift; next; }
+ if (/^-submit-aux/) { $SUBMITAUX = "$ARGV[0]"; shift; next; }
+ if (/^-nosubmit$/) { $SUBMIT = 0; next; }
+ if (/^-nickname$/) { $nickname = "$ARGV[0]"; shift; next; }
+ if (/^-gccpath/) { $CONFIGUREARGS .=
+ " CC=$ARGV[0]/gcc CXX=$ARGV[0]/g++";
+ $GCCPATH=$ARGV[0]; shift; next; }
+ else { $GCCPATH=""; }
+ if (/^-target/) { $CONFIGUREARGS .= " --target=$ARGV[0]";
+ shift; next; }
+ if (/^-cflags/) { $MAKEOPTS = "$MAKEOPTS C.Flags=\'$ARGV[0]\'";
+ shift; next; }
+ if (/^-cxxflags/) { $MAKEOPTS = "$MAKEOPTS CXX.Flags=\'$ARGV[0]\'";
+ shift; next; }
+ if (/^-ldflags/) { $MAKEOPTS = "$MAKEOPTS LD.Flags=\'$ARGV[0]\'";
+ shift; next; }
+ if (/^-test-cflags/) { $TESTFLAGS = "$TESTFLAGS CFLAGS=\'$ARGV[0]\'";
+ shift; next; }
+ if (/^-test-cxxflags/) { $TESTFLAGS = "$TESTFLAGS CXXFLAGS=\'$ARGV[0]\'";
+ shift; next; }
+ if (/^-compileflags/) { $MAKEOPTS = "$MAKEOPTS $ARGV[0]"; shift; next; }
+ if (/^-llvmgccdir/) { $CONFIGUREARGS .= " --with-llvmgccdir=\'$ARGV[0]\'";
+ $LLVMGCCPATH = $ARGV[0] . '/bin';
+ shift; next;}
+ if (/^-noexternals$/) { $NOEXTERNALS = 1; next; }
+ if (/^-nouname$/) { $NOUNAME = 1; next; }
+ if (/^-use-gmake/) { $MAKECMD = "gmake"; shift; next; }
+ if (/^-extraflags/) { $CONFIGUREARGS .=
+ " --with-extra-options=\'$ARGV[0]\'"; shift; next;}
+ if (/^-noexternals$/) { $NOEXTERNALS = 1; next; }
+ if (/^-nodejagnu$/) { next; }
+ if (/^-nobuild$/) { $NOBUILD = 1; next; }
+ print "Unknown option: $_ : ignoring!\n";
+}
+
+if ($CONFIGUREARGS !~ /--disable-jit/) {
+ $CONFIGUREARGS .= " --enable-jit";
+}
+
+if (@ARGV != 0 and @ARGV != 3) {
+ die "error: must specify 0 or 3 options!";
+}
+
+if (@ARGV == 3) {
+ if ($CONFIG_PATH ne "") {
+ die "error: arguments are unsupported in -config mode,";
+ }
+
+ # ARGV[0] used to be the CVS root, ignored for backward compatibility.
+ $BuildDir = $ARGV[1];
+ $WebDir = $ARGV[2];
+}
+
+if ($CONFIG_PATH ne "") {
+ $BuildDir = "";
+ $SVNURL = $TestSVNURL = "";
+ if ($WebDir eq "") {
+ die("please specify a web directory");
+ }
+} else {
+ if ($BuildDir eq "" or
+ $WebDir eq "") {
+ die("please specify a build directory, and a web directory");
+ }
+}
+
+if ($nickname eq "") {
+ die ("Please invoke NewNightlyTest.pl with command line option " .
+ "\"-nickname <nickname>\"");
+}
+
+my $LLVMSrcDir = $ENV{'LLVMSRCDIR'};
+$LLVMSrcDir = "$BuildDir/llvm" unless $LLVMSrcDir;
+my $LLVMObjDir = $ENV{'LLVMOBJDIR'};
+$LLVMObjDir = "$BuildDir/llvm" unless $LLVMObjDir;
+my $LLVMTestDir = $ENV{'LLVMTESTDIR'};
+$LLVMTestDir = "$BuildDir/llvm/projects/llvm-test" unless $LLVMTestDir;
+
+##############################################################
+#
+# Define the file names we'll use
+#
+##############################################################
+
+my $Prefix = "$WebDir/$DATE";
+my $SingleSourceLog = "$Prefix-SingleSource-ProgramTest.txt.gz";
+my $MultiSourceLog = "$Prefix-MultiSource-ProgramTest.txt.gz";
+my $ExternalLog = "$Prefix-External-ProgramTest.txt.gz";
+
+# These are only valid in non-config mode.
+my $ConfigureLog = "", $BuildLog = "", $COLog = "";
+my $DejagnuLog = "", $DejagnuSum = "", $DejagnuLog = "";
+
+# Are we in config mode?
+my $ConfigMode = 0;
+
+##############################################################
+#
+# Helper functions
+#
+##############################################################
+
+sub GetDir {
+ my $Suffix = shift;
+ opendir DH, $WebDir;
+ my @Result = reverse sort grep !/$DATE/, grep /[-0-9]+$Suffix/, readdir DH;
+ closedir DH;
+ return @Result;
+}
+
+sub RunLoggedCommand {
+ my $Command = shift;
+ my $Log = shift;
+ my $Title = shift;
+ if ($TEELOGS) {
+ if ($VERBOSE) {
+ print "$Title\n";
+ print "$Command 2>&1 | tee $Log\n";
+ }
+ system "$Command 2>&1 | tee $Log";
+ } else {
+ if ($VERBOSE) {
+ print "$Title\n";
+ print "$Command > $Log 2>&1\n";
+ }
+ system "$Command > $Log 2>&1";
+ }
+}
+
+sub RunAppendingLoggedCommand {
+ my $Command = shift;
+ my $Log = shift;
+ my $Title = shift;
+ if ($TEELOGS) {
+ if ($VERBOSE) {
+ print "$Title\n";
+ print "$Command 2>&1 | tee -a $Log\n";
+ }
+ system "$Command 2>&1 | tee -a $Log";
+ } else {
+ if ($VERBOSE) {
+ print "$Title\n";
+ print "$Command >> $Log 2>&1\n";
+ }
+ system "$Command >> $Log 2>&1";
+ }
+}
+
+sub GetRegex { # (Regex with ()'s, value)
+ if ($_[1] =~ /$_[0]/m) {
+ return $1;
+ }
+ return "0";
+}
+
+sub ChangeDir { # directory, logical name
+ my ($dir,$name) = @_;
+ chomp($dir);
+ if ( $VERBOSE ) { print "Changing To: $name ($dir)\n"; }
+ $result = chdir($dir);
+ if (!$result) {
+ print "ERROR!!! Cannot change directory to: $name ($dir) because $!\n";
+ return false;
+ }
+ return true;
+}
+
+sub ReadFile {
+ if (open (FILE, $_[0])) {
+ undef $/;
+ my $Ret = <FILE>;
+ close FILE;
+ $/ = '\n';
+ return $Ret;
+ } else {
+ print "Could not open file '$_[0]' for reading!\n";
+ return "";
+ }
+}
+
+sub WriteFile { # (filename, contents)
+ open (FILE, ">$_[0]") or die "Could not open file '$_[0]' for writing!\n";
+ print FILE $_[1];
+ close FILE;
+}
+
+sub CopyFile { #filename, newfile
+ my ($file, $newfile) = @_;
+ chomp($file);
+ if ($VERBOSE) { print "Copying $file to $newfile\n"; }
+ copy($file, $newfile);
+}
+
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+# This function acts as a mini web browswer submitting data
+# to our central server via the post method
+#
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+sub WriteSentData {
+ $variables = $_[0];
+
+ # Write out the "...-sentdata.txt" file.
+
+ my $sentdata="";
+ foreach $x (keys (%$variables)){
+ $value = $variables->{$x};
+ $sentdata.= "$x => $value\n";
+ }
+ WriteFile "$Prefix-sentdata.txt", $sentdata;
+}
+
+sub SendData {
+ $host = $_[0];
+ $file = $_[1];
+ $variables = $_[2];
+
+ if (!($SUBMITAUX eq "")) {
+ system "$SUBMITAUX \"$Prefix-sentdata.txt\"";
+ }
+
+ if (!$SUBMIT) {
+ return "Skipped standard submit.\n";
+ }
+
+ # Create the content to send to the server.
+
+ my $content;
+ foreach $key (keys (%$variables)){
+ $value = $variables->{$key};
+ $value =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
+ $content .= "$key=$value&";
+ }
+
+ # Send the data to the server.
+ #
+ # FIXME: This code should be more robust?
+
+ $port=80;
+ $socketaddr= sockaddr_in $port, inet_aton $host or die "Bad hostname\n";
+ socket SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp') or
+ die "Bad socket\n";
+ connect SOCK, $socketaddr or die "Bad connection\n";
+ select((select(SOCK), $| = 1)[0]);
+
+ $length = length($content);
+
+ my $send= "POST $file HTTP/1.0\n";
+ $send.= "Host: $host\n";
+ $send.= "Content-Type: application/x-www-form-urlencoded\n";
+ $send.= "Content-length: $length\n\n";
+ $send.= "$content";
+
+ print SOCK $send;
+ my $result;
+ while(<SOCK>){
+ $result .= $_;
+ }
+ close(SOCK);
+
+ return $result;
+}
+
+##############################################################
+#
+# Individual Build & Test Functions
+#
+##############################################################
+
+# Create the source repository directory.
+sub CheckoutSource {
+ die "Invalid call!" unless $ConfigMode == 0;
+ if (-d $BuildDir) {
+ if (!$NOREMOVE) {
+ if ( $VERBOSE ) {
+ print "Build directory exists! Removing it\n";
+ }
+ system "rm -rf $BuildDir";
+ mkdir $BuildDir or die "Could not create checkout directory $BuildDir!";
+ } else {
+ if ( $VERBOSE ) {
+ print "Build directory exists!\n";
+ }
+ }
+ } else {
+ mkdir $BuildDir or die "Could not create checkout directory $BuildDir!";
+ }
+
+ ChangeDir( $BuildDir, "checkout directory" );
+ my $SVNCMD = "$NICE svn co --non-interactive";
+ RunLoggedCommand("( time -p $SVNCMD $SVNURL/llvm/trunk llvm; cd llvm/projects ; " .
+ " $SVNCMD $TestSVNURL/test-suite/trunk llvm-test )", $COLog,
+ "CHECKOUT LLVM");
+ if ($WITHCLANG) {
+ RunLoggedCommand("( cd llvm/tools ; " .
+ " $SVNCMD $SVNURL/cfe/trunk clang )", $COLog,
+ "CHECKOUT CLANG");
+ }
+}
+
+# Build the entire tree, saving build messages to the build log. Returns false
+# on build failure.
+sub BuildLLVM {
+ die "Invalid call!" unless $ConfigMode == 0;
+ my $EXTRAFLAGS = "--enable-spec --with-objroot=.";
+ RunLoggedCommand("(time -p $NICE ./configure $CONFIGUREARGS $EXTRAFLAGS) ",
+ $ConfigureLog, "CONFIGURE");
+ # Build the entire tree, capturing the output into $BuildLog
+ if (!$NOCLEAN) {
+ RunAppendingLoggedCommand("($NICE $MAKECMD $MAKEOPTS clean)", $BuildLog, "BUILD CLEAN");
+ }
+ RunAppendingLoggedCommand("(time -p $NICE $MAKECMD $MAKEOPTS)", $BuildLog, "BUILD");
+
+ if (`grep -a '^$MAKECMD\[^:]*: .*Error' $BuildLog | wc -l` + 0 ||
+ `grep -a '^$MAKECMD: \*\*\*.*Stop.' $BuildLog | wc -l` + 0) {
+ return 0;
+ }
+
+ return 1;
+}
+
+# Run the named tests (i.e. "SingleSource" "MultiSource" "External")
+sub TestDirectory {
+ my $SubDir = shift;
+ ChangeDir( "$LLVMTestDir/$SubDir",
+ "Programs Test Subdirectory" ) || return ("", "");
+
+ my $ProgramTestLog = "$Prefix-$SubDir-ProgramTest.txt";
+
+ # Make sure to clean the test results.
+ RunLoggedCommand("$MAKECMD -k $MAKEOPTS $PROGTESTOPTS clean $TESTFLAGS",
+ $ProgramTestLog, "TEST DIRECTORY $SubDir");
+
+ # Run the programs tests... creating a report.nightly.csv file.
+ my $LLCBetaOpts = "";
+ RunLoggedCommand("$MAKECMD -k $MAKEOPTS $PROGTESTOPTS report.nightly.csv ".
+ "$TESTFLAGS TEST=nightly",
+ $ProgramTestLog, "TEST DIRECTORY $SubDir");
+ $LLCBetaOpts = `$MAKECMD print-llcbeta-option`;
+
+ my $ProgramsTable;
+ if (`grep -a '^$MAKECMD\[^:]: .*Error' $ProgramTestLog | wc -l` + 0) {
+ $ProgramsTable="Error running test $SubDir\n";
+ print "ERROR TESTING\n";
+ } elsif (`grep -a '^$MAKECMD\[^:]: .*No rule to make target' $ProgramTestLog | wc -l` + 0) {
+ $ProgramsTable="Makefile error running tests $SubDir!\n";
+ print "ERROR TESTING\n";
+ } else {
+ # Create a list of the tests which were run...
+ system "egrep -a 'TEST-(PASS|FAIL)' < $ProgramTestLog ".
+ "| sort > $Prefix-$SubDir-Tests.txt";
+ }
+ $ProgramsTable = ReadFile "report.nightly.csv";
+
+ ChangeDir( "../../..", "Programs Test Parent Directory" );
+ return ($ProgramsTable, $LLCBetaOpts);
+}
+
+# Run all the nightly tests and return the program tables and the list of tests,
+# passes, fails, and xfails.
+sub RunNightlyTest() {
+ ($SSProgs, $llcbeta_options) = TestDirectory("SingleSource");
+ WriteFile "$Prefix-SingleSource-Performance.txt", $SSProgs;
+ ($MSProgs, $llcbeta_options) = TestDirectory("MultiSource");
+ WriteFile "$Prefix-MultiSource-Performance.txt", $MSProgs;
+ if ( ! $NOEXTERNALS ) {
+ ($ExtProgs, $llcbeta_options) = TestDirectory("External");
+ WriteFile "$Prefix-External-Performance.txt", $ExtProgs;
+ system "cat $Prefix-SingleSource-Tests.txt " .
+ "$Prefix-MultiSource-Tests.txt ".
+ "$Prefix-External-Tests.txt | sort > $Prefix-Tests.txt";
+ system "cat $Prefix-SingleSource-Performance.txt " .
+ "$Prefix-MultiSource-Performance.txt ".
+ "$Prefix-External-Performance.txt | sort > $Prefix-Performance.txt";
+ } else {
+ $ExtProgs = "External TEST STAGE SKIPPED\n";
+ if ( $VERBOSE ) {
+ print "External TEST STAGE SKIPPED\n";
+ }
+ system "cat $Prefix-SingleSource-Tests.txt " .
+ "$Prefix-MultiSource-Tests.txt ".
+ " | sort > $Prefix-Tests.txt";
+ system "cat $Prefix-SingleSource-Performance.txt " .
+ "$Prefix-MultiSource-Performance.txt ".
+ " | sort > $Prefix-Performance.txt";
+ }
+
+ # Compile passes, fails, xfails.
+ my $All = (ReadFile "$Prefix-Tests.txt");
+ my @TestSuiteResultLines = split "\n", $All;
+ my ($Passes, $Fails, $XFails) = "";
+
+ for ($x=0; $x < @TestSuiteResultLines; $x++) {
+ if (@TestSuiteResultLines[$x] =~ m/^PASS:/) {
+ $Passes .= "$TestSuiteResultLines[$x]\n";
+ }
+ elsif (@TestSuiteResultLines[$x] =~ m/^FAIL:/) {
+ $Fails .= "$TestSuiteResultLines[$x]\n";
+ }
+ elsif (@TestSuiteResultLines[$x] =~ m/^XFAIL:/) {
+ $XFails .= "$TestSuiteResultLines[$x]\n";
+ }
+ }
+
+ return ($SSProgs, $MSProgs, $ExtProgs, $All, $Passes, $Fails, $XFails);
+}
+
+##############################################################
+#
+# Initialize filenames
+#
+##############################################################
+
+if (! -d $WebDir) {
+ mkdir $WebDir, 0777 or die "Unable to create web directory: '$WebDir'.";
+ if($VERBOSE){
+ warn "$WebDir did not exist; creating it.\n";
+ }
+}
+
+if ($CONFIG_PATH ne "") {
+ $ConfigMode = 1;
+ $LLVMSrcDir = GetRegex "^(.*)\\s+", `$CONFIG_PATH --src-root`;
+ $LLVMObjDir = GetRegex "^(.*)\\s+", `$CONFIG_PATH --obj-root`;
+ # FIXME: Add llvm-config hook for this?
+ $LLVMTestDir = $LLVMObjDir . "/projects/test-suite";
+} else {
+ $ConfigureLog = "$Prefix-Configure-Log.txt";
+ $BuildLog = "$Prefix-Build-Log.txt";
+ $COLog = "$Prefix-CVS-Log.txt";
+}
+
+if ($VERBOSE) {
+ if ($CONFIG_PATH ne "") {
+ print "INITIALIZED (config mode)\n";
+ print "WebDir = $WebDir\n";
+ print "Prefix = $Prefix\n";
+ print "LLVM Src = $LLVMSrcDir\n";
+ print "LLVM Obj = $LLVMObjDir\n";
+ print "LLVM Test = $LLVMTestDir\n";
+ } else {
+ print "INITIALIZED\n";
+ print "SVN URL = $SVNURL\n";
+ print "COLog = $COLog\n";
+ print "BuildDir = $BuildDir\n";
+ print "WebDir = $WebDir\n";
+ print "Prefix = $Prefix\n";
+ print "BuildLog = $BuildLog\n";
+ }
+}
+
+##############################################################
+#
+# The actual NewNightlyTest logic.
+#
+##############################################################
+
+$starttime = `date "+20%y-%m-%d %H:%M:%S"`;
+
+my $BuildError = 0, $BuildStatus = "OK";
+if ($ConfigMode == 0) {
+ if (!$NOCHECKOUT) {
+ CheckoutSource();
+ }
+
+ # Build LLVM.
+ ChangeDir( $LLVMSrcDir , "llvm source directory") ;
+ if ($NOCHECKOUT || $NOBUILD) {
+ $BuildStatus = "Skipped by user";
+ } else {
+ if (!BuildLLVM()) {
+ if( $VERBOSE) { print "\n***ERROR BUILDING TREE\n\n"; }
+ $BuildError = 1;
+ $BuildStatus = "Error: compilation aborted";
+ }
+ }
+}
+
+# Run the llvm-test tests.
+my ($SingleSourceProgramsTable, $MultiSourceProgramsTable, $ExternalProgramsTable,
+ $all_tests, $passes, $fails, $xfails) = "";
+if (!$NOTEST && !$BuildError) {
+ ($SingleSourceProgramsTable, $MultiSourceProgramsTable, $ExternalProgramsTable,
+ $all_tests, $passes, $fails, $xfails) = RunNightlyTest();
+}
+
+$endtime = `date "+20%y-%m-%d %H:%M:%S"`;
+
+# The last bit of logic is to remove the build and web dirs, after sending data
+# to the server.
+
+##############################################################
+#
+# Accumulate the information to send to the server.
+#
+##############################################################
+
+if ( $VERBOSE ) { print "PREPARING LOGS TO BE SENT TO SERVER\n"; }
+
+if ( ! $NOUNAME ) {
+ $machine_data = "uname: ".`uname -a`.
+ "hardware: ".`uname -m`.
+ "os: ".`uname -sr`.
+ "name: ".`uname -n`.
+ "date: ".`date \"+20%y-%m-%d\"`.
+ "time: ".`date +\"%H:%M:%S\"`;
+} else {
+ $machine_data = "uname: (excluded)\n".
+ "hardware: ".`uname -m`.
+ "os: ".`uname -sr`.
+ "name: $nickname\n".
+ "date: ".`date \"+20%y-%m-%d\"`.
+ "time: ".`date +\"%H:%M:%S\"`;
+}
+
+# Get gcc version.
+my $gcc_version_long = "";
+if ($GCCPATH ne "") {
+ $gcc_version_long = `$GCCPATH/gcc --version`;
+} elsif ($ENV{"CC"}) {
+ $gcc_version_long = `$ENV{"CC"} --version`;
+} else {
+ $gcc_version_long = `gcc --version`;
+}
+my $gcc_version = (split '\n', $gcc_version_long)[0];
+
+# Get llvm-gcc target triple.
+#
+# FIXME: This shouldn't be hardwired to llvm-gcc.
+my $llvmgcc_version_long = "";
+if ($LLVMGCCPATH ne "") {
+ $llvmgcc_version_long = `$LLVMGCCPATH/llvm-gcc -v 2>&1`;
+} else {
+ $llvmgcc_version_long = `llvm-gcc -v 2>&1`;
+}
+(split '\n', $llvmgcc_version_long)[1] =~ /Target: (.+)/;
+my $targetTriple = $1;
+
+# Logs.
+my ($ConfigureLogData, $BuildLogData, $CheckoutLogData) = "";
+if ($ConfigMode == 0) {
+ $ConfigureLogData = ReadFile $ConfigureLog;
+ $BuildLogData = ReadFile $BuildLog;
+ $CheckoutLogData = ReadFile $COLog;
+}
+
+# Checkout info.
+my $CheckoutTime_Wall = GetRegex "^real ([0-9.]+)", $CheckoutLogData;
+my $CheckoutTime_User = GetRegex "^user ([0-9.]+)", $CheckoutLogData;
+my $CheckoutTime_Sys = GetRegex "^sys ([0-9.]+)", $CheckoutLogData;
+my $CheckoutTime_CPU = $CVSCheckoutTime_User + $CVSCheckoutTime_Sys;
+
+# Configure info.
+my $ConfigTimeU = GetRegex "^user ([0-9.]+)", $ConfigureLogData;
+my $ConfigTimeS = GetRegex "^sys ([0-9.]+)", $ConfigureLogData;
+my $ConfigTime = $ConfigTimeU+$ConfigTimeS; # ConfigTime = User+System
+my $ConfigWallTime = GetRegex "^real ([0-9.]+)",$ConfigureLogData;
+$ConfigTime=-1 unless $ConfigTime;
+$ConfigWallTime=-1 unless $ConfigWallTime;
+
+# Build info.
+my $BuildTimeU = GetRegex "^user ([0-9.]+)", $BuildLogData;
+my $BuildTimeS = GetRegex "^sys ([0-9.]+)", $BuildLogData;
+my $BuildTime = $BuildTimeU+$BuildTimeS; # BuildTime = User+System
+my $BuildWallTime = GetRegex "^real ([0-9.]+)", $BuildLogData;
+$BuildTime=-1 unless $BuildTime;
+$BuildWallTime=-1 unless $BuildWallTime;
+
+if ( $VERBOSE ) { print "SEND THE DATA VIA THE POST REQUEST\n"; }
+
+my %hash_of_data = (
+ 'machine_data' => $machine_data,
+ 'build_data' => $ConfigureLogData . $BuildLogData,
+ 'gcc_version' => $gcc_version,
+ 'nickname' => $nickname,
+ 'dejagnutime_wall' => "0.0",
+ 'dejagnutime_cpu' => "0.0",
+ 'cvscheckouttime_wall' => $CheckoutTime_Wall,
+ 'cvscheckouttime_cpu' => $CheckoutTime_CPU,
+ 'configtime_wall' => $ConfigWallTime,
+ 'configtime_cpu'=> $ConfigTime,
+ 'buildtime_wall' => $BuildWallTime,
+ 'buildtime_cpu' => $BuildTime,
+ 'buildstatus' => $BuildStatus,
+ 'singlesource_programstable' => $SingleSourceProgramsTable,
+ 'multisource_programstable' => $MultiSourceProgramsTable,
+ 'externalsource_programstable' => $ExternalProgramsTable,
+ 'llcbeta_options' => $llcbeta_options,
+ 'passing_tests' => $passes,
+ 'expfail_tests' => $xfails,
+ 'unexpfail_tests' => $fails,
+ 'all_tests' => $all_tests,
+ 'dejagnutests_results' => "Dejagnu skipped by user choice.",
+ 'dejagnutests_log' => "",
+ 'starttime' => $starttime,
+ 'endtime' => $endtime,
+ 'target_triple' => $targetTriple,
+
+ # Unused, but left around for backwards compatability.
+ 'warnings' => "",
+ 'cvsusercommitlist' => "",
+ 'cvsuserupdatelist' => "",
+ 'cvsaddedfiles' => "",
+ 'cvsmodifiedfiles' => "",
+ 'cvsremovedfiles' => "",
+ 'lines_of_code' => "",
+ 'cvs_file_count' => 0,
+ 'cvs_dir_count' => 0,
+ 'warnings_removed' => "",
+ 'warnings_added' => "",
+ 'new_tests' => "",
+ 'removed_tests' => "",
+ 'o_file_sizes' => "",
+ 'a_file_sizes' => ""
+);
+
+# Write out the "...-sentdata.txt" file.
+WriteSentData \%hash_of_data;
+
+if ($SUBMIT || !($SUBMITAUX eq "")) {
+ my $response = SendData $SUBMITSERVER,$SUBMITSCRIPT,\%hash_of_data;
+ if( $VERBOSE) { print "============================\n$response"; }
+} else {
+ print "============================\n";
+ foreach $x(keys %hash_of_data){
+ print "$x => $hash_of_data{$x}\n";
+ }
+}
+
+##############################################################
+#
+# Remove the source tree...
+#
+##############################################################
+system ( "$NICE rm -rf $BuildDir")
+ if (!$NOCHECKOUT and !$NOREMOVE and !$NOREMOVEATEND);
+system ( "$NICE rm -rf $WebDir")
+ if (!$NOCHECKOUT and !$NOREMOVE and !$NOREMOVERESULTS);
diff --git a/contrib/llvm/utils/NightlyTest.gnuplot b/contrib/llvm/utils/NightlyTest.gnuplot
new file mode 100644
index 0000000..514b72a
--- /dev/null
+++ b/contrib/llvm/utils/NightlyTest.gnuplot
@@ -0,0 +1,214 @@
+set terminal png
+
+##------- Plot small Date vs LOC ----
+set output "running_loc.png"
+set xlabel "Date"
+set ylabel "Lines of Code"
+set xdata time
+set timefmt "%Y-%m-%d-%H:%M:%S:"
+set format x "%b %d, %Y"
+
+set size .75,.75
+set xtics rotate
+set xlabel 0,-1
+plot "running_loc.txt" using 1:2 title '' with lines, \
+ "running_loc.txt" using 1:2 title "Date vs. Lines of Code" with lines
+
+##------- Plot large Date vs LOC ----
+set size 1.5,1.5
+set xtics norotate
+set xlabel 0,0
+set output "running_loc_large.png"
+plot "running_loc.txt" using 1:2 title '', \
+ "running_loc.txt" using 1:2 title "Date vs. Lines of Code" with lines
+
+
+# Delete all labels...
+set nolabel
+
+##------- Olden CBE performance ----
+
+set size .75,.75
+set xtics rotate
+set xlabel 0,-1
+set output "running_Olden_cbe_time.png"
+set ylabel "CBE compiled execution time (s)"
+plot "running_Olden_cbe_time.txt" u 1:2 t '' with lines, \
+ "running_Olden_cbe_time.txt" u 1:2 t "bh" with lines, \
+ "running_Olden_cbe_time.txt" u 1:3 t "em3d" with lines, \
+ "running_Olden_cbe_time.txt" u 1:4 t "mst" with lines, \
+ "running_Olden_cbe_time.txt" u 1:5 t "power" with lines, \
+ "running_Olden_cbe_time.txt" u 1:6 t "tsp" with lines, \
+ "running_Olden_cbe_time.txt" u 1:7 t "bisort" with lines, \
+ "running_Olden_cbe_time.txt" u 1:8 t "health" with lines, \
+ "running_Olden_cbe_time.txt" u 1:9 t "perimeter" with lines, \
+ "running_Olden_cbe_time.txt" u 1:10 t "treeadd" with lines, \
+ "running_Olden_cbe_time.txt" u 1:11 t "voronoi" \
+ with lines
+
+set size 1.5,1.5
+set xtics norotate
+set xlabel 0,0
+set output "running_Olden_cbe_time_large.png"
+plot "running_Olden_cbe_time.txt" u 1:2 t '' with lines, \
+ "running_Olden_cbe_time.txt" u 1:2 t "bh" with lines, \
+ "running_Olden_cbe_time.txt" u 1:3 t "em3d" with lines, \
+ "running_Olden_cbe_time.txt" u 1:4 t "mst" with lines, \
+ "running_Olden_cbe_time.txt" u 1:5 t "power" with lines, \
+ "running_Olden_cbe_time.txt" u 1:6 t "tsp" with lines, \
+ "running_Olden_cbe_time.txt" u 1:7 t "bisort" with lines, \
+ "running_Olden_cbe_time.txt" u 1:8 t "health" with lines, \
+ "running_Olden_cbe_time.txt" u 1:9 t "perimeter" with lines, \
+ "running_Olden_cbe_time.txt" u 1:10 t "treeadd" with lines, \
+ "running_Olden_cbe_time.txt" u 1:11 t "voronoi" \
+ with lines
+
+##------- Olden JIT performance ----
+
+set size .75,.75
+set xtics rotate
+set xlabel 0,-1
+set output "running_Olden_jit_time.png"
+set ylabel "JIT execution time (s)"
+plot "running_Olden_jit_time.txt" u 1:2 t '' with lines, \
+ "running_Olden_jit_time.txt" u 1:2 t "bh" with lines, \
+ "running_Olden_jit_time.txt" u 1:3 t "em3d" with lines, \
+ "running_Olden_jit_time.txt" u 1:4 t "mst" with lines, \
+ "running_Olden_jit_time.txt" u 1:5 t "power" with lines, \
+ "running_Olden_jit_time.txt" u 1:6 t "tsp" with lines, \
+ "running_Olden_jit_time.txt" u 1:7 t "bisort" with lines, \
+ "running_Olden_jit_time.txt" u 1:8 t "health" with lines, \
+ "running_Olden_jit_time.txt" u 1:9 t "perimeter" with lines, \
+ "running_Olden_jit_time.txt" u 1:10 t "treeadd" with lines, \
+ "running_Olden_jit_time.txt" u 1:11 t "voronoi" \
+ with lines
+
+set size 1.5,1.5
+set xtics norotate
+set xlabel 0,0
+set output "running_Olden_jit_time_large.png"
+plot "running_Olden_jit_time.txt" u 1:2 t '' with lines, \
+ "running_Olden_jit_time.txt" u 1:2 t "bh" with lines, \
+ "running_Olden_jit_time.txt" u 1:3 t "em3d" with lines, \
+ "running_Olden_jit_time.txt" u 1:4 t "mst" with lines, \
+ "running_Olden_jit_time.txt" u 1:5 t "power" with lines, \
+ "running_Olden_jit_time.txt" u 1:6 t "tsp" with lines, \
+ "running_Olden_jit_time.txt" u 1:7 t "bisort" with lines, \
+ "running_Olden_jit_time.txt" u 1:8 t "health" with lines, \
+ "running_Olden_jit_time.txt" u 1:9 t "perimeter" with lines, \
+ "running_Olden_jit_time.txt" u 1:10 t "treeadd" with lines, \
+ "running_Olden_jit_time.txt" u 1:11 t "voronoi" \
+ with lines
+
+##------- Olden LLC performance ----
+
+set size .75,.75
+set xtics rotate
+set xlabel 0,-1
+set output "running_Olden_llc_time.png"
+set ylabel "LLC compiled execution time (s)"
+plot "running_Olden_llc_time.txt" u 1:2 t '' with lines, \
+ "running_Olden_llc_time.txt" u 1:2 t "bh" with lines, \
+ "running_Olden_llc_time.txt" u 1:3 t "em3d" with lines, \
+ "running_Olden_llc_time.txt" u 1:4 t "mst" with lines, \
+ "running_Olden_llc_time.txt" u 1:5 t "power" with lines, \
+ "running_Olden_llc_time.txt" u 1:6 t "tsp" with lines, \
+ "running_Olden_llc_time.txt" u 1:7 t "bisort" with lines, \
+ "running_Olden_llc_time.txt" u 1:8 t "health" with lines, \
+ "running_Olden_llc_time.txt" u 1:9 t "perimeter" with lines, \
+ "running_Olden_llc_time.txt" u 1:10 t "treeadd" with lines, \
+ "running_Olden_llc_time.txt" u 1:11 t "voronoi" \
+ with lines
+
+set size 1.5,1.5
+set xtics norotate
+set xlabel 0,0
+set output "running_Olden_llc_time_large.png"
+plot "running_Olden_llc_time.txt" u 1:2 t '' with lines, \
+ "running_Olden_llc_time.txt" u 1:2 t "bh" with lines, \
+ "running_Olden_llc_time.txt" u 1:3 t "em3d" with lines, \
+ "running_Olden_llc_time.txt" u 1:4 t "mst" with lines, \
+ "running_Olden_llc_time.txt" u 1:5 t "power" with lines, \
+ "running_Olden_llc_time.txt" u 1:6 t "tsp" with lines, \
+ "running_Olden_llc_time.txt" u 1:7 t "bisort" with lines, \
+ "running_Olden_llc_time.txt" u 1:8 t "health" with lines, \
+ "running_Olden_llc_time.txt" u 1:9 t "perimeter" with lines, \
+ "running_Olden_llc_time.txt" u 1:10 t "treeadd" with lines, \
+ "running_Olden_llc_time.txt" u 1:11 t "voronoi" \
+ with lines
+
+
+##------- Olden optimizer time ----
+
+set size .75,.75
+set xtics rotate
+set xlabel 0,-1
+set output "running_Olden_opt_time.png"
+set ylabel "Time to run the optimizer (s)"
+plot "running_Olden_opt_time.txt" u 1:2 t '' with lines, \
+ "running_Olden_opt_time.txt" u 1:2 t "bh" with lines, \
+ "running_Olden_opt_time.txt" u 1:3 t "em3d" with lines, \
+ "running_Olden_opt_time.txt" u 1:4 t "mst" with lines, \
+ "running_Olden_opt_time.txt" u 1:5 t "power" with lines, \
+ "running_Olden_opt_time.txt" u 1:6 t "tsp" with lines, \
+ "running_Olden_opt_time.txt" u 1:7 t "bisort" with lines, \
+ "running_Olden_opt_time.txt" u 1:8 t "health" with lines, \
+ "running_Olden_opt_time.txt" u 1:9 t "perimeter" with lines, \
+ "running_Olden_opt_time.txt" u 1:10 t "treeadd" with lines, \
+ "running_Olden_opt_time.txt" u 1:11 t "voronoi" \
+ with lines
+
+set size 1.5,1.5
+set xtics norotate
+set xlabel 0,0
+set output "running_Olden_opt_time_large.png"
+plot "running_Olden_opt_time.txt" u 1:2 t '' with lines, \
+ "running_Olden_opt_time.txt" u 1:2 t "bh" with lines, \
+ "running_Olden_opt_time.txt" u 1:3 t "em3d" with lines, \
+ "running_Olden_opt_time.txt" u 1:4 t "mst" with lines, \
+ "running_Olden_opt_time.txt" u 1:5 t "power" with lines, \
+ "running_Olden_opt_time.txt" u 1:6 t "tsp" with lines, \
+ "running_Olden_opt_time.txt" u 1:7 t "bisort" with lines, \
+ "running_Olden_opt_time.txt" u 1:8 t "health" with lines, \
+ "running_Olden_opt_time.txt" u 1:9 t "perimeter" with lines, \
+ "running_Olden_opt_time.txt" u 1:10 t "treeadd" with lines, \
+ "running_Olden_opt_time.txt" u 1:11 t "voronoi" \
+ with lines
+
+
+##------- Bytecode size ----
+
+set size .75,.75
+set xtics rotate
+set xlabel 0,-1
+set output "running_Olden_bytecode.png"
+set ylabel "Program bytecode size (bytes)"
+plot "running_Olden_bytecode.txt" u 1:2 t '' with lines, \
+ "running_Olden_bytecode.txt" u 1:2 t "bh" with lines, \
+ "running_Olden_bytecode.txt" u 1:3 t "em3d" with lines, \
+ "running_Olden_bytecode.txt" u 1:4 t "mst" with lines, \
+ "running_Olden_bytecode.txt" u 1:5 t "power" with lines, \
+ "running_Olden_bytecode.txt" u 1:6 t "tsp" with lines, \
+ "running_Olden_bytecode.txt" u 1:7 t "bisort" with lines, \
+ "running_Olden_bytecode.txt" u 1:8 t "health" with lines, \
+ "running_Olden_bytecode.txt" u 1:9 t "perimeter" with lines, \
+ "running_Olden_bytecode.txt" u 1:10 t "treeadd" with lines, \
+ "running_Olden_bytecode.txt" u 1:11 t "voronoi" \
+ with lines
+
+set size 1.5,1.5
+set xtics norotate
+set xlabel 0,0
+set output "running_Olden_bytecode_large.png"
+plot "running_Olden_bytecode.txt" u 1:2 t '' with lines, \
+ "running_Olden_bytecode.txt" u 1:2 t "bh" with lines, \
+ "running_Olden_bytecode.txt" u 1:3 t "em3d" with lines, \
+ "running_Olden_bytecode.txt" u 1:4 t "mst" with lines, \
+ "running_Olden_bytecode.txt" u 1:5 t "power" with lines, \
+ "running_Olden_bytecode.txt" u 1:6 t "tsp" with lines, \
+ "running_Olden_bytecode.txt" u 1:7 t "bisort" with lines, \
+ "running_Olden_bytecode.txt" u 1:8 t "health" with lines, \
+ "running_Olden_bytecode.txt" u 1:9 t "perimeter" with lines, \
+ "running_Olden_bytecode.txt" u 1:10 t "treeadd" with lines, \
+ "running_Olden_bytecode.txt" u 1:11 t "voronoi" \
+ with lines
diff --git a/contrib/llvm/utils/NightlyTestTemplate.html b/contrib/llvm/utils/NightlyTestTemplate.html
new file mode 100644
index 0000000..c38bb2e
--- /dev/null
+++ b/contrib/llvm/utils/NightlyTestTemplate.html
@@ -0,0 +1,244 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><title>LLVM Test Results for $DateString</title></head>
+
+<body bgcolor=white>
+<center><font size=+3 face=Verdana><b>LLVM Test Results for $DateString</b></font></center>
+<hr height=1>
+
+<table width=100%>
+<tr><td valign=top align=center>
+
+<table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#000000">
+<table border="0" cellpadding="5" cellspacing="0"><tr><td bgcolor="#DDAA77">
+<font size=+1><b>Sections:</b></font><br>
+</td></tr><tr><td bgcolor="#FFCC99" align=center>
+<a href="#Overview">Overview</a><br>
+<a href="#Changes">Changes</a><br>
+<a href="#Dejagnu">Dejagnu Tests</a><br>
+<a href="#Trends">Trends</a><br>
+<a href="#Programs">Programs</a><br>
+</td></tr></table></td></tr></table>
+
+<p>
+<table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#000000">
+<table border="0" cellpadding="5" cellspacing="0"><tr><td bgcolor="#DDAA77"
+<font size=+1><b>Previous:</b></font><br>
+</td></tr><tr><td bgcolor="#FFCC99">
+ $PrevDaysList
+</td></tr></table></td></tr></table>
+<p>
+
+<font size=+1><b>Back to:</b></font><br>
+<a href="http://llvm.org/testresults/">Test&nbsp;Results</a><br>
+<a href="http://llvm.org/">LLVM&nbsp;Page</a><p>
+
+</td><td valign=top>
+
+<center>
+<table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#000000">
+<table border="0" cellpadding="10" cellspacing="0"><tr><td bgcolor="#DDAA77"
+<font size=+2 face=Verdana><b><a name="Overview">Today's Test Results Overview</font></b>
+</td></tr></table></td></tr></table></center><p>
+
+<!-- Running LOC graph -->
+<table align=right>
+<tr><td>
+<a href="running_loc_large.png"
+ ><img border=0 width=480 height=360 src="running_loc.png"></a>
+</td></tr>
+<tr><td align=center>Lines Of Code over Time<br>
+<font size=-1><a href="running_loc_large.png">Click for larger view</a></font>
+</td></tr>
+</table>
+
+<h2>Nightly Test Overview:</h2>
+<ul>
+ <li>Start: <b>$TestStartTime</b></li>
+ <li>Finish: <b>$TestFinishTime</b></li>
+ <li>Platform: <b>$TestPlatform</b></li>
+</ul>
+<h2>CVS Tree Overview:</h2>
+<ul>
+<li><a href="$DATE-CVS-Log.txt">CVS Checkout Log</a>
+<ul>
+ <b>$NumDirsInCVS</b> dirs, <b>$NumFilesInCVS</b> files, <b>$LOC</b>
+ lines of code, checked out in <b>$CVSCheckoutTime</b> seconds<br></ul>
+<li><a href="$DATE-Build-Log.txt">Compilation Log</a>
+<table>
+<tr><td><b>Item</b></td><td><b>CPU Time</b></td><td><b>Wall Clock</b></td></tr>
+<tr><td>Configure CVS Tree</td><td>$ConfigTime</td><td>$ConfigWallTime</td></tr>
+<tr><td>Build CVS Tree</td><td>$BuildTime</td><td>$BuildWallTime</td></tr>
+<tr><td>Run Dejagnu Tests</td><td>$DejagnuTime</td><td>$DejagnuWallTime</td></tr>
+</table></li>
+<li>Number of object files compiled: <b>$NumObjects</b></li>
+<li>Number of libraries linked: <b>$NumLibraries</b></li>
+<li>Number of executables linked:<b> $NumExecutables</b></li>
+<li>Build Status: $BuildStatus</li>
+</ul>
+
+<h2>Warnings during the build:</h2>
+$WarningsList
+
+<br><br><center>
+<table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#000000">
+<table border="0" cellpadding="10" cellspacing="0"><tr><td bgcolor="#DDAA77"
+<font size=+2 face=Verdana><b><a name="Changes">Changes from Yesterday</font></b>
+</td></tr></table></td></tr></table></center><p>
+
+<h2>Changes to CVS:</h2>
+<ul>
+<li>Users who committed to CVS: <b>$UserCommitList</b>
+<li>Users who updated from CVS: <b>$UserUpdateList</b>
+<li>Added Files: $AddedFilesList
+<li>Modified Files: $ModifiedFilesList
+<li>Removed Files: $RemovedFilesList
+</ul><p>
+
+<h2>Changes to Warnings:</h2>
+<p>Warnings Added:</p>
+$WarningsAdded
+<p>Warnings Removed:</p>
+$WarningsRemoved
+
+<h2>Changes in the test suite:</h2>
+<ul>
+<li>New Tests: $TestsAdded
+<li>Removed Tests: $TestsRemoved
+<li>Newly passing tests: $TestsFixed
+<li>Newly failing tests: $TestsBroken
+</ul>
+</td></tr></tbody></table>
+
+
+<br/><br/><center>
+<table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#000000">
+<table border="0" cellpadding="10" cellspacing="0"><tr><td bgcolor="#DDAA77"
+<font size=+2 face=Verdana><b><a name="Dejagnu">Dejagnu Test Results</font></b>
+</td></tr></table></td></tr></table></center>
+<br/>
+$DejagnuTestResults
+<p>A complete log of testing <a href="$DATE-Dejagnu-testrun.log">Feature and Regression</a> is available for further analysis.</p>
+
+<br><br><center>
+<table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#000000">
+<table border="0" cellpadding="10" cellspacing="0"><tr><td bgcolor="#DDAA77"
+<font size=+2 face=Verdana><b><a name="Trends">Changes Over Time</font></b>
+</td></tr></table></td></tr></table></center><p>
+
+
+Here are some charts showing how the LLVM optimizer and code generators are
+changing over time. For now we use the Olden benchmark suite to measure this,
+but eventually we will switch to using SPEC CPU2000. All programs are run with
+"LARGE_PROBLEM_SIZE" enabled. Click on any of the charts to get a larger
+version.<p>
+
+<h2>Compilation Measurements:</h2>
+
+<table border="0" align=center>
+<tr>
+<td width=50% align=center>
+<a href="running_Olden_bytecode_large.png"><img width=480 height=360 border=0 src="running_Olden_bytecode.png"></a><br>
+Size of LLVM bytecode files
+</td>
+<td width=50% align=center>
+<a href="running_Olden_opt_time_large.png"><img width=480 height=360 border=0 src="running_Olden_opt_time.png"></a><br>
+Time to run the LLVM optimizer on each program
+</td></tr>
+</table>
+
+<h2>Program Execution Measurements:</h2>
+
+<table border="0" align=center>
+<tr>
+<td width=50% align=center>
+<a href="running_Olden_cbe_time_large.png"><img width=480 height=360 border=0 src="running_Olden_cbe_time.png"></a><br>
+Execution time for CBE generated executable
+</td>
+<td width=50% align=center>
+<a href="running_Olden_llc_time_large.png"><img width=480 height=360 border=0 src="running_Olden_llc_time.png"></a><br>
+Execution time for the LLC generated executable
+</td></tr>
+
+<tr>
+<td align=center>
+<a href="running_Olden_jit_time_large.png"><img width=480 height=360 border=0 src="running_Olden_jit_time.png"></a><br>
+Execution time for program in the JIT
+</td>
+<td></td></tr>
+</table>
+
+
+
+
+<br><br><center>
+<table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#000000">
+<table border="0" cellpadding="10" cellspacing="0"><tr><td bgcolor="#DDAA77"
+<font size=+2 face=Verdana><b><a name="Programs">Program Tests</font></b>
+</td></tr></table></td></tr></table></center><p>
+
+This section tests LLVM on a variety of programs in the test suite. This
+includes benchmark suites like the Olden, McCat, Ptrdist, and SPEC benchmarks as
+well as a few random programs with test inputs. This section is meant to track
+how stable LLVM is as a whole. A failure in the execution of any test is marked
+with an asterisk: `*'. The columns of the tables are:<p>
+
+<ol>
+<li><a name="Program">Program</a> - The name of the program for that row.</li>
+<li><a name="GCCAS">GCCAS</a> - Time to run LLVM optimizers on the program.</li>
+<li><a name="Bytecode">Bytecode</a> - The size of the bytecode for the
+ program</li>
+<li><a name="Instrs">Instrs</a> - The number of LLVM instructions in the
+ compiled bytecode</li>
+<li><a name="LLC<br>compile">LLC compile</a> - The time taken compile with
+ LLC (the static backend)</li>
+<li><a name="JIT<br>codegen">JIT codegen</a> - The amount of time spent in the
+ JIT itself, instead of executing the program.</li>
+<li><a name="Machine<br>code">Machine code</a> - The number of bytes of machine
+ code generated by the JIT.</li>
+<li><a name="GCC">GCC</a> - The time taken to execute the program when compiled
+ with GCC -O2.</li>
+<li><a name="CBE">CBE</a> - The time taken to execute the program after
+ compilation through the C backend, compiled with -O2.</li>
+<li><a name="LLC">LLC</a> - How long does the program generated by the static
+ backend LLC take to execute </li>
+<li><a name="JIT">JIT</a> - The amount of time spent running the
+ program with the JIT; this includes the code generation phase (listed above)
+ and actually running the program.</li>
+<li><a name="GCC/LLC">GCC/LLC</a> - The speed-up of the LLC output vs the native
+ GCC output: greater than 1 is a speedup, less than 1 is a slowdown.</li>
+<li><a name="GCC/CBE">GCC/CBE</a> - The speed-up of the CBE output vs the native
+ GCC output: greater than 1 is a speedup, less than 1 is a slowdown.</li>
+<li><a name="LLC-BETA">LLC-BETA</a> - How long does the program generated by the static
+ backend LLC take to execute the program, when compiled with new experimental
+ features. This is temporary, for tuning.</li>
+</ol><p>
+
+A complete log of testing
+<a href="$DATE-SingleSource-ProgramTest.txt.gz">SingleSource</a>,
+<a href="$DATE-MultiSource-ProgramTest.txt.gz">MultiSource</a>, and
+<a href="$DATE-External-ProgramTest.txt.gz">External</a> programs are
+available for further analysis.
+
+<h2>Programs/External</h2>
+
+<center>
+<table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#000000">
+$ExternalProgramsTable
+</td></tr></table></center>
+
+<h2>Programs/MultiSource</h2>
+
+<center>
+<table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#000000">
+$MultiSourceProgramsTable
+</td></tr></table></center>
+
+<h2>Programs/SingleSource</h2>
+
+<center>
+<table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#000000">
+$SingleSourceProgramsTable
+</td></tr></table></center>
+
+</td></tr></html>
+
diff --git a/contrib/llvm/utils/OldenDataRecover.pl b/contrib/llvm/utils/OldenDataRecover.pl
new file mode 100644
index 0000000..7678394
--- /dev/null
+++ b/contrib/llvm/utils/OldenDataRecover.pl
@@ -0,0 +1,37 @@
+#this script is intended to help recover the running graphs when
+#the nightly tester decides to eat them.
+
+#zgrep -E "(=========)|(TEST-RESULT-llc-time)" *-Olden-tests.txt* |perl this > file
+#zgrep -E "(=========)|(TEST-RESULT-compile.*bc)" *-Olden-tests.tx* |perl this >file
+
+while (<>) {
+ if (/(\d*-\d*-\d*)-.*=========.*\/(.*)\' Program/) {
+# print "$1 $2\n";
+ $curP = $2;
+ $curD = $1;
+ $dates{$1} = 1;
+ } elsif (/(\d*-\d*-\d*)-.*TEST-RESULT-.*: program (\d*\.\d*)/) {
+# print "$1 $2\n";
+ if ($curD eq $1) {
+ $$data{$curD}{$curP} = $2;
+ }
+ } elsif (/(\d*-\d*-\d*)-.*TEST-RESULT-.*: (\d*)/) {
+# print "$1 $2\n";
+ if ($curD eq $1) {
+ $$data{$curD}{$curP} = $2;
+ }
+ }
+}
+@progs = ("bh", "em3d", "mst", "power", "tsp", "bisort", "health", "perimeter", "treeadd", "voronoi");
+
+foreach $date (sort keys %dates) {
+ print "$date: ";
+ foreach $prog (@progs) {
+ if ($$data{$date}{$prog}) {
+ print " $$data{$date}{$prog}";
+ } else {
+ print " 0";
+ }
+ }
+ print "\n";
+}
diff --git a/contrib/llvm/utils/PerfectShuffle/Makefile b/contrib/llvm/utils/PerfectShuffle/Makefile
new file mode 100644
index 0000000..28709fe
--- /dev/null
+++ b/contrib/llvm/utils/PerfectShuffle/Makefile
@@ -0,0 +1,18 @@
+##===- utils/PerfectShuffle/Makefile -----------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TOOLNAME = llvm-PerfectShuffle
+NO_INSTALL = 1
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/contrib/llvm/utils/PerfectShuffle/PerfectShuffle.cpp b/contrib/llvm/utils/PerfectShuffle/PerfectShuffle.cpp
new file mode 100644
index 0000000..b94a7d3
--- /dev/null
+++ b/contrib/llvm/utils/PerfectShuffle/PerfectShuffle.cpp
@@ -0,0 +1,571 @@
+//===-- PerfectShuffle.cpp - Perfect Shuffle Generator --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file computes an optimal sequence of instructions for doing all shuffles
+// of two 4-element vectors. With a release build and when configured to emit
+// an altivec instruction table, this takes about 30s to run on a 2.7Ghz
+// PowerPC G5.
+//
+//===----------------------------------------------------------------------===//
+
+#include <iostream>
+#include <vector>
+#include <cassert>
+#include <cstdlib>
+struct Operator;
+
+// Masks are 4-nibble hex numbers. Values 0-7 in any nibble means that it takes
+// an element from that value of the input vectors. A value of 8 means the
+// entry is undefined.
+
+// Mask manipulation functions.
+static inline unsigned short MakeMask(unsigned V0, unsigned V1,
+ unsigned V2, unsigned V3) {
+ return (V0 << (3*4)) | (V1 << (2*4)) | (V2 << (1*4)) | (V3 << (0*4));
+}
+
+/// getMaskElt - Return element N of the specified mask.
+static unsigned getMaskElt(unsigned Mask, unsigned Elt) {
+ return (Mask >> ((3-Elt)*4)) & 0xF;
+}
+
+static unsigned setMaskElt(unsigned Mask, unsigned Elt, unsigned NewVal) {
+ unsigned FieldShift = ((3-Elt)*4);
+ return (Mask & ~(0xF << FieldShift)) | (NewVal << FieldShift);
+}
+
+// Reject elements where the values are 9-15.
+static bool isValidMask(unsigned short Mask) {
+ unsigned short UndefBits = Mask & 0x8888;
+ return (Mask & ((UndefBits >> 1)|(UndefBits>>2)|(UndefBits>>3))) == 0;
+}
+
+/// hasUndefElements - Return true if any of the elements in the mask are undefs
+///
+static bool hasUndefElements(unsigned short Mask) {
+ return (Mask & 0x8888) != 0;
+}
+
+/// isOnlyLHSMask - Return true if this mask only refers to its LHS, not
+/// including undef values..
+static bool isOnlyLHSMask(unsigned short Mask) {
+ return (Mask & 0x4444) == 0;
+}
+
+/// getLHSOnlyMask - Given a mask that refers to its LHS and RHS, modify it to
+/// refer to the LHS only (for when one argument value is passed into the same
+/// function twice).
+#if 0
+static unsigned short getLHSOnlyMask(unsigned short Mask) {
+ return Mask & 0xBBBB; // Keep only LHS and Undefs.
+}
+#endif
+
+/// getCompressedMask - Turn a 16-bit uncompressed mask (where each elt uses 4
+/// bits) into a compressed 13-bit mask, where each elt is multiplied by 9.
+static unsigned getCompressedMask(unsigned short Mask) {
+ return getMaskElt(Mask, 0)*9*9*9 + getMaskElt(Mask, 1)*9*9 +
+ getMaskElt(Mask, 2)*9 + getMaskElt(Mask, 3);
+}
+
+static void PrintMask(unsigned i, std::ostream &OS) {
+ OS << "<" << (char)(getMaskElt(i, 0) == 8 ? 'u' : ('0'+getMaskElt(i, 0)))
+ << "," << (char)(getMaskElt(i, 1) == 8 ? 'u' : ('0'+getMaskElt(i, 1)))
+ << "," << (char)(getMaskElt(i, 2) == 8 ? 'u' : ('0'+getMaskElt(i, 2)))
+ << "," << (char)(getMaskElt(i, 3) == 8 ? 'u' : ('0'+getMaskElt(i, 3)))
+ << ">";
+}
+
+/// ShuffleVal - This represents a shufflevector operation.
+struct ShuffleVal {
+ unsigned Cost; // Number of instrs used to generate this value.
+ Operator *Op; // The Operation used to generate this value.
+ unsigned short Arg0, Arg1; // Input operands for this value.
+
+ ShuffleVal() : Cost(1000000) {}
+};
+
+
+/// ShufTab - This is the actual shuffle table that we are trying to generate.
+///
+static ShuffleVal ShufTab[65536];
+
+/// TheOperators - All of the operators that this target supports.
+static std::vector<Operator*> TheOperators;
+
+/// Operator - This is a vector operation that is available for use.
+struct Operator {
+ unsigned short ShuffleMask;
+ unsigned short OpNum;
+ const char *Name;
+ unsigned Cost;
+
+ Operator(unsigned short shufflemask, const char *name, unsigned opnum,
+ unsigned cost = 1)
+ : ShuffleMask(shufflemask), OpNum(opnum), Name(name), Cost(cost) {
+ TheOperators.push_back(this);
+ }
+ ~Operator() {
+ assert(TheOperators.back() == this);
+ TheOperators.pop_back();
+ }
+
+ bool isOnlyLHSOperator() const {
+ return isOnlyLHSMask(ShuffleMask);
+ }
+
+ const char *getName() const { return Name; }
+ unsigned getCost() const { return Cost; }
+
+ unsigned short getTransformedMask(unsigned short LHSMask, unsigned RHSMask) {
+ // Extract the elements from LHSMask and RHSMask, as appropriate.
+ unsigned Result = 0;
+ for (unsigned i = 0; i != 4; ++i) {
+ unsigned SrcElt = (ShuffleMask >> (4*i)) & 0xF;
+ unsigned ResElt;
+ if (SrcElt < 4)
+ ResElt = getMaskElt(LHSMask, SrcElt);
+ else if (SrcElt < 8)
+ ResElt = getMaskElt(RHSMask, SrcElt-4);
+ else {
+ assert(SrcElt == 8 && "Bad src elt!");
+ ResElt = 8;
+ }
+ Result |= ResElt << (4*i);
+ }
+ return Result;
+ }
+};
+
+static const char *getZeroCostOpName(unsigned short Op) {
+ if (ShufTab[Op].Arg0 == 0x0123)
+ return "LHS";
+ else if (ShufTab[Op].Arg0 == 0x4567)
+ return "RHS";
+ else {
+ assert(0 && "bad zero cost operation");
+ abort();
+ }
+}
+
+static void PrintOperation(unsigned ValNo, unsigned short Vals[]) {
+ unsigned short ThisOp = Vals[ValNo];
+ std::cerr << "t" << ValNo;
+ PrintMask(ThisOp, std::cerr);
+ std::cerr << " = " << ShufTab[ThisOp].Op->getName() << "(";
+
+ if (ShufTab[ShufTab[ThisOp].Arg0].Cost == 0) {
+ std::cerr << getZeroCostOpName(ShufTab[ThisOp].Arg0);
+ PrintMask(ShufTab[ThisOp].Arg0, std::cerr);
+ } else {
+ // Figure out what tmp # it is.
+ for (unsigned i = 0; ; ++i)
+ if (Vals[i] == ShufTab[ThisOp].Arg0) {
+ std::cerr << "t" << i;
+ break;
+ }
+ }
+
+ if (!ShufTab[Vals[ValNo]].Op->isOnlyLHSOperator()) {
+ std::cerr << ", ";
+ if (ShufTab[ShufTab[ThisOp].Arg1].Cost == 0) {
+ std::cerr << getZeroCostOpName(ShufTab[ThisOp].Arg1);
+ PrintMask(ShufTab[ThisOp].Arg1, std::cerr);
+ } else {
+ // Figure out what tmp # it is.
+ for (unsigned i = 0; ; ++i)
+ if (Vals[i] == ShufTab[ThisOp].Arg1) {
+ std::cerr << "t" << i;
+ break;
+ }
+ }
+ }
+ std::cerr << ") ";
+}
+
+static unsigned getNumEntered() {
+ unsigned Count = 0;
+ for (unsigned i = 0; i != 65536; ++i)
+ Count += ShufTab[i].Cost < 100;
+ return Count;
+}
+
+static void EvaluateOps(unsigned short Elt, unsigned short Vals[],
+ unsigned &NumVals) {
+ if (ShufTab[Elt].Cost == 0) return;
+
+ // If this value has already been evaluated, it is free. FIXME: match undefs.
+ for (unsigned i = 0, e = NumVals; i != e; ++i)
+ if (Vals[i] == Elt) return;
+
+ // Otherwise, get the operands of the value, then add it.
+ unsigned Arg0 = ShufTab[Elt].Arg0, Arg1 = ShufTab[Elt].Arg1;
+ if (ShufTab[Arg0].Cost)
+ EvaluateOps(Arg0, Vals, NumVals);
+ if (Arg0 != Arg1 && ShufTab[Arg1].Cost)
+ EvaluateOps(Arg1, Vals, NumVals);
+
+ Vals[NumVals++] = Elt;
+}
+
+
+int main() {
+ // Seed the table with accesses to the LHS and RHS.
+ ShufTab[0x0123].Cost = 0;
+ ShufTab[0x0123].Op = 0;
+ ShufTab[0x0123].Arg0 = 0x0123;
+ ShufTab[0x4567].Cost = 0;
+ ShufTab[0x4567].Op = 0;
+ ShufTab[0x4567].Arg0 = 0x4567;
+
+ // Seed the first-level of shuffles, shuffles whose inputs are the input to
+ // the vectorshuffle operation.
+ bool MadeChange = true;
+ unsigned OpCount = 0;
+ while (MadeChange) {
+ MadeChange = false;
+ ++OpCount;
+ std::cerr << "Starting iteration #" << OpCount << " with "
+ << getNumEntered() << " entries established.\n";
+
+ // Scan the table for two reasons: First, compute the maximum cost of any
+ // operation left in the table. Second, make sure that values with undefs
+ // have the cheapest alternative that they match.
+ unsigned MaxCost = ShufTab[0].Cost;
+ for (unsigned i = 1; i != 0x8889; ++i) {
+ if (!isValidMask(i)) continue;
+ if (ShufTab[i].Cost > MaxCost)
+ MaxCost = ShufTab[i].Cost;
+
+ // If this value has an undef, make it be computed the cheapest possible
+ // way of any of the things that it matches.
+ if (hasUndefElements(i)) {
+ // This code is a little bit tricky, so here's the idea: consider some
+ // permutation, like 7u4u. To compute the lowest cost for 7u4u, we
+ // need to take the minimum cost of all of 7[0-8]4[0-8], 81 entries. If
+ // there are 3 undefs, the number rises to 729 entries we have to scan,
+ // and for the 4 undef case, we have to scan the whole table.
+ //
+ // Instead of doing this huge amount of scanning, we process the table
+ // entries *in order*, and use the fact that 'u' is 8, larger than any
+ // valid index. Given an entry like 7u4u then, we only need to scan
+ // 7[0-7]4u - 8 entries. We can get away with this, because we already
+ // know that each of 704u, 714u, 724u, etc contain the minimum value of
+ // all of the 704[0-8], 714[0-8] and 724[0-8] entries respectively.
+ unsigned UndefIdx;
+ if (i & 0x8000)
+ UndefIdx = 0;
+ else if (i & 0x0800)
+ UndefIdx = 1;
+ else if (i & 0x0080)
+ UndefIdx = 2;
+ else if (i & 0x0008)
+ UndefIdx = 3;
+ else
+ abort();
+
+ unsigned MinVal = i;
+ unsigned MinCost = ShufTab[i].Cost;
+
+ // Scan the 8 entries.
+ for (unsigned j = 0; j != 8; ++j) {
+ unsigned NewElt = setMaskElt(i, UndefIdx, j);
+ if (ShufTab[NewElt].Cost < MinCost) {
+ MinCost = ShufTab[NewElt].Cost;
+ MinVal = NewElt;
+ }
+ }
+
+ // If we found something cheaper than what was here before, use it.
+ if (i != MinVal) {
+ MadeChange = true;
+ ShufTab[i] = ShufTab[MinVal];
+ }
+ }
+ }
+
+ for (unsigned LHS = 0; LHS != 0x8889; ++LHS) {
+ if (!isValidMask(LHS)) continue;
+ if (ShufTab[LHS].Cost > 1000) continue;
+
+ // If nothing involving this operand could possibly be cheaper than what
+ // we already have, don't consider it.
+ if (ShufTab[LHS].Cost + 1 >= MaxCost)
+ continue;
+
+ for (unsigned opnum = 0, e = TheOperators.size(); opnum != e; ++opnum) {
+ Operator *Op = TheOperators[opnum];
+
+ // Evaluate op(LHS,LHS)
+ unsigned ResultMask = Op->getTransformedMask(LHS, LHS);
+
+ unsigned Cost = ShufTab[LHS].Cost + Op->getCost();
+ if (Cost < ShufTab[ResultMask].Cost) {
+ ShufTab[ResultMask].Cost = Cost;
+ ShufTab[ResultMask].Op = Op;
+ ShufTab[ResultMask].Arg0 = LHS;
+ ShufTab[ResultMask].Arg1 = LHS;
+ MadeChange = true;
+ }
+
+ // If this is a two input instruction, include the op(x,y) cases. If
+ // this is a one input instruction, skip this.
+ if (Op->isOnlyLHSOperator()) continue;
+
+ for (unsigned RHS = 0; RHS != 0x8889; ++RHS) {
+ if (!isValidMask(RHS)) continue;
+ if (ShufTab[RHS].Cost > 1000) continue;
+
+ // If nothing involving this operand could possibly be cheaper than
+ // what we already have, don't consider it.
+ if (ShufTab[RHS].Cost + 1 >= MaxCost)
+ continue;
+
+
+ // Evaluate op(LHS,RHS)
+ unsigned ResultMask = Op->getTransformedMask(LHS, RHS);
+
+ if (ShufTab[ResultMask].Cost <= OpCount ||
+ ShufTab[ResultMask].Cost <= ShufTab[LHS].Cost ||
+ ShufTab[ResultMask].Cost <= ShufTab[RHS].Cost)
+ continue;
+
+ // Figure out the cost to evaluate this, knowing that CSE's only need
+ // to be evaluated once.
+ unsigned short Vals[30];
+ unsigned NumVals = 0;
+ EvaluateOps(LHS, Vals, NumVals);
+ EvaluateOps(RHS, Vals, NumVals);
+
+ unsigned Cost = NumVals + Op->getCost();
+ if (Cost < ShufTab[ResultMask].Cost) {
+ ShufTab[ResultMask].Cost = Cost;
+ ShufTab[ResultMask].Op = Op;
+ ShufTab[ResultMask].Arg0 = LHS;
+ ShufTab[ResultMask].Arg1 = RHS;
+ MadeChange = true;
+ }
+ }
+ }
+ }
+ }
+
+ std::cerr << "Finished Table has " << getNumEntered()
+ << " entries established.\n";
+
+ unsigned CostArray[10] = { 0 };
+
+ // Compute a cost histogram.
+ for (unsigned i = 0; i != 65536; ++i) {
+ if (!isValidMask(i)) continue;
+ if (ShufTab[i].Cost > 9)
+ ++CostArray[9];
+ else
+ ++CostArray[ShufTab[i].Cost];
+ }
+
+ for (unsigned i = 0; i != 9; ++i)
+ if (CostArray[i])
+ std::cout << "// " << CostArray[i] << " entries have cost " << i << "\n";
+ if (CostArray[9])
+ std::cout << "// " << CostArray[9] << " entries have higher cost!\n";
+
+
+ // Build up the table to emit.
+ std::cout << "\n// This table is 6561*4 = 26244 bytes in size.\n";
+ std::cout << "static const unsigned PerfectShuffleTable[6561+1] = {\n";
+
+ for (unsigned i = 0; i != 0x8889; ++i) {
+ if (!isValidMask(i)) continue;
+
+ // CostSat - The cost of this operation saturated to two bits.
+ unsigned CostSat = ShufTab[i].Cost;
+ if (CostSat > 4) CostSat = 4;
+ if (CostSat == 0) CostSat = 1;
+ --CostSat; // Cost is now between 0-3.
+
+ unsigned OpNum = ShufTab[i].Op ? ShufTab[i].Op->OpNum : 0;
+ assert(OpNum < 16 && "Too few bits to encode operation!");
+
+ unsigned LHS = getCompressedMask(ShufTab[i].Arg0);
+ unsigned RHS = getCompressedMask(ShufTab[i].Arg1);
+
+ // Encode this as 2 bits of saturated cost, 4 bits of opcodes, 13 bits of
+ // LHS, and 13 bits of RHS = 32 bits.
+ unsigned Val = (CostSat << 30) | (OpNum << 26) | (LHS << 13) | RHS;
+
+ std::cout << " " << Val << "U,\t// ";
+ PrintMask(i, std::cout);
+ std::cout << ": Cost " << ShufTab[i].Cost;
+ std::cout << " " << (ShufTab[i].Op ? ShufTab[i].Op->getName() : "copy");
+ std::cout << " ";
+ if (ShufTab[ShufTab[i].Arg0].Cost == 0) {
+ std::cout << getZeroCostOpName(ShufTab[i].Arg0);
+ } else {
+ PrintMask(ShufTab[i].Arg0, std::cout);
+ }
+
+ if (ShufTab[i].Op && !ShufTab[i].Op->isOnlyLHSOperator()) {
+ std::cout << ", ";
+ if (ShufTab[ShufTab[i].Arg1].Cost == 0) {
+ std::cout << getZeroCostOpName(ShufTab[i].Arg1);
+ } else {
+ PrintMask(ShufTab[i].Arg1, std::cout);
+ }
+ }
+ std::cout << "\n";
+ }
+ std::cout << " 0\n};\n";
+
+ if (0) {
+ // Print out the table.
+ for (unsigned i = 0; i != 0x8889; ++i) {
+ if (!isValidMask(i)) continue;
+ if (ShufTab[i].Cost < 1000) {
+ PrintMask(i, std::cerr);
+ std::cerr << " - Cost " << ShufTab[i].Cost << " - ";
+
+ unsigned short Vals[30];
+ unsigned NumVals = 0;
+ EvaluateOps(i, Vals, NumVals);
+
+ for (unsigned j = 0, e = NumVals; j != e; ++j)
+ PrintOperation(j, Vals);
+ std::cerr << "\n";
+ }
+ }
+ }
+}
+
+
+#ifdef GENERATE_ALTIVEC
+
+///===---------------------------------------------------------------------===//
+/// The altivec instruction definitions. This is the altivec-specific part of
+/// this file.
+///===---------------------------------------------------------------------===//
+
+// Note that the opcode numbers here must match those in the PPC backend.
+enum {
+ OP_COPY = 0, // Copy, used for things like <u,u,u,3> to say it is <0,1,2,3>
+ OP_VMRGHW,
+ OP_VMRGLW,
+ OP_VSPLTISW0,
+ OP_VSPLTISW1,
+ OP_VSPLTISW2,
+ OP_VSPLTISW3,
+ OP_VSLDOI4,
+ OP_VSLDOI8,
+ OP_VSLDOI12
+};
+
+struct vmrghw : public Operator {
+ vmrghw() : Operator(0x0415, "vmrghw", OP_VMRGHW) {}
+} the_vmrghw;
+
+struct vmrglw : public Operator {
+ vmrglw() : Operator(0x2637, "vmrglw", OP_VMRGLW) {}
+} the_vmrglw;
+
+template<unsigned Elt>
+struct vspltisw : public Operator {
+ vspltisw(const char *N, unsigned Opc)
+ : Operator(MakeMask(Elt, Elt, Elt, Elt), N, Opc) {}
+};
+
+vspltisw<0> the_vspltisw0("vspltisw0", OP_VSPLTISW0);
+vspltisw<1> the_vspltisw1("vspltisw1", OP_VSPLTISW1);
+vspltisw<2> the_vspltisw2("vspltisw2", OP_VSPLTISW2);
+vspltisw<3> the_vspltisw3("vspltisw3", OP_VSPLTISW3);
+
+template<unsigned N>
+struct vsldoi : public Operator {
+ vsldoi(const char *Name, unsigned Opc)
+ : Operator(MakeMask(N&7, (N+1)&7, (N+2)&7, (N+3)&7), Name, Opc) {
+ }
+};
+
+vsldoi<1> the_vsldoi1("vsldoi4" , OP_VSLDOI4);
+vsldoi<2> the_vsldoi2("vsldoi8" , OP_VSLDOI8);
+vsldoi<3> the_vsldoi3("vsldoi12", OP_VSLDOI12);
+
+#endif
+
+#define GENERATE_NEON
+
+#ifdef GENERATE_NEON
+enum {
+ OP_COPY = 0, // Copy, used for things like <u,u,u,3> to say it is <0,1,2,3>
+ OP_VREV,
+ OP_VDUP0,
+ OP_VDUP1,
+ OP_VDUP2,
+ OP_VDUP3,
+ OP_VEXT1,
+ OP_VEXT2,
+ OP_VEXT3,
+ OP_VUZPL, // VUZP, left result
+ OP_VUZPR, // VUZP, right result
+ OP_VZIPL, // VZIP, left result
+ OP_VZIPR, // VZIP, right result
+ OP_VTRNL, // VTRN, left result
+ OP_VTRNR // VTRN, right result
+};
+
+struct vrev : public Operator {
+ vrev() : Operator(0x1032, "vrev", OP_VREV) {}
+} the_vrev;
+
+template<unsigned Elt>
+struct vdup : public Operator {
+ vdup(const char *N, unsigned Opc)
+ : Operator(MakeMask(Elt, Elt, Elt, Elt), N, Opc) {}
+};
+
+vdup<0> the_vdup0("vdup0", OP_VDUP0);
+vdup<1> the_vdup1("vdup1", OP_VDUP1);
+vdup<2> the_vdup2("vdup2", OP_VDUP2);
+vdup<3> the_vdup3("vdup3", OP_VDUP3);
+
+template<unsigned N>
+struct vext : public Operator {
+ vext(const char *Name, unsigned Opc)
+ : Operator(MakeMask(N&7, (N+1)&7, (N+2)&7, (N+3)&7), Name, Opc) {
+ }
+};
+
+vext<1> the_vext1("vext1", OP_VEXT1);
+vext<2> the_vext2("vext2", OP_VEXT2);
+vext<3> the_vext3("vext3", OP_VEXT3);
+
+struct vuzpl : public Operator {
+ vuzpl() : Operator(0x0246, "vuzpl", OP_VUZPL, 2) {}
+} the_vuzpl;
+
+struct vuzpr : public Operator {
+ vuzpr() : Operator(0x1357, "vuzpr", OP_VUZPR, 2) {}
+} the_vuzpr;
+
+struct vzipl : public Operator {
+ vzipl() : Operator(0x0415, "vzipl", OP_VZIPL, 2) {}
+} the_vzipl;
+
+struct vzipr : public Operator {
+ vzipr() : Operator(0x2637, "vzipr", OP_VZIPR, 2) {}
+} the_vzipr;
+
+struct vtrnl : public Operator {
+ vtrnl() : Operator(0x0426, "vtrnl", OP_VTRNL, 2) {}
+} the_vtrnl;
+
+struct vtrnr : public Operator {
+ vtrnr() : Operator(0x1537, "vtrnr", OP_VTRNR, 2) {}
+} the_vtrnr;
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp
new file mode 100644
index 0000000..03b01f6
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp
@@ -0,0 +1,1878 @@
+//===------------ ARMDecoderEmitter.cpp - Decoder Generator ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the ARM Disassembler.
+// It contains the tablegen backend that emits the decoder functions for ARM and
+// Thumb. The disassembler core includes the auto-generated file, invokes the
+// decoder functions, and builds up the MCInst based on the decoded Opcode.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "arm-decoder-emitter"
+
+#include "ARMDecoderEmitter.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <vector>
+#include <map>
+#include <string>
+
+using namespace llvm;
+
+/////////////////////////////////////////////////////
+// //
+// Enums and Utilities for ARM Instruction Format //
+// //
+/////////////////////////////////////////////////////
+
+#define ARM_FORMATS \
+ ENTRY(ARM_FORMAT_PSEUDO, 0) \
+ ENTRY(ARM_FORMAT_MULFRM, 1) \
+ ENTRY(ARM_FORMAT_BRFRM, 2) \
+ ENTRY(ARM_FORMAT_BRMISCFRM, 3) \
+ ENTRY(ARM_FORMAT_DPFRM, 4) \
+ ENTRY(ARM_FORMAT_DPSOREGFRM, 5) \
+ ENTRY(ARM_FORMAT_LDFRM, 6) \
+ ENTRY(ARM_FORMAT_STFRM, 7) \
+ ENTRY(ARM_FORMAT_LDMISCFRM, 8) \
+ ENTRY(ARM_FORMAT_STMISCFRM, 9) \
+ ENTRY(ARM_FORMAT_LDSTMULFRM, 10) \
+ ENTRY(ARM_FORMAT_LDSTEXFRM, 11) \
+ ENTRY(ARM_FORMAT_ARITHMISCFRM, 12) \
+ ENTRY(ARM_FORMAT_SATFRM, 13) \
+ ENTRY(ARM_FORMAT_EXTFRM, 14) \
+ ENTRY(ARM_FORMAT_VFPUNARYFRM, 15) \
+ ENTRY(ARM_FORMAT_VFPBINARYFRM, 16) \
+ ENTRY(ARM_FORMAT_VFPCONV1FRM, 17) \
+ ENTRY(ARM_FORMAT_VFPCONV2FRM, 18) \
+ ENTRY(ARM_FORMAT_VFPCONV3FRM, 19) \
+ ENTRY(ARM_FORMAT_VFPCONV4FRM, 20) \
+ ENTRY(ARM_FORMAT_VFPCONV5FRM, 21) \
+ ENTRY(ARM_FORMAT_VFPLDSTFRM, 22) \
+ ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 23) \
+ ENTRY(ARM_FORMAT_VFPMISCFRM, 24) \
+ ENTRY(ARM_FORMAT_THUMBFRM, 25) \
+ ENTRY(ARM_FORMAT_MISCFRM, 26) \
+ ENTRY(ARM_FORMAT_NEONGETLNFRM, 27) \
+ ENTRY(ARM_FORMAT_NEONSETLNFRM, 28) \
+ ENTRY(ARM_FORMAT_NEONDUPFRM, 29) \
+ ENTRY(ARM_FORMAT_NLdSt, 30) \
+ ENTRY(ARM_FORMAT_N1RegModImm, 31) \
+ ENTRY(ARM_FORMAT_N2Reg, 32) \
+ ENTRY(ARM_FORMAT_NVCVT, 33) \
+ ENTRY(ARM_FORMAT_NVecDupLn, 34) \
+ ENTRY(ARM_FORMAT_N2RegVecShL, 35) \
+ ENTRY(ARM_FORMAT_N2RegVecShR, 36) \
+ ENTRY(ARM_FORMAT_N3Reg, 37) \
+ ENTRY(ARM_FORMAT_N3RegVecSh, 38) \
+ ENTRY(ARM_FORMAT_NVecExtract, 39) \
+ ENTRY(ARM_FORMAT_NVecMulScalar, 40) \
+ ENTRY(ARM_FORMAT_NVTBL, 41)
+
+// ARM instruction format specifies the encoding used by the instruction.
+#define ENTRY(n, v) n = v,
+typedef enum {
+ ARM_FORMATS
+ ARM_FORMAT_NA
+} ARMFormat;
+#undef ENTRY
+
+// Converts enum to const char*.
+static const char *stringForARMFormat(ARMFormat form) {
+#define ENTRY(n, v) case n: return #n;
+ switch(form) {
+ ARM_FORMATS
+ case ARM_FORMAT_NA:
+ default:
+ return "";
+ }
+#undef ENTRY
+}
+
+enum {
+ IndexModeNone = 0,
+ IndexModePre = 1,
+ IndexModePost = 2,
+ IndexModeUpd = 3
+};
+
+/////////////////////////
+// //
+// Utility functions //
+// //
+/////////////////////////
+
+/// byteFromBitsInit - Return the byte value from a BitsInit.
+/// Called from getByteField().
+static uint8_t byteFromBitsInit(BitsInit &init) {
+ int width = init.getNumBits();
+
+ assert(width <= 8 && "Field is too large for uint8_t!");
+
+ int index;
+ uint8_t mask = 0x01;
+
+ uint8_t ret = 0;
+
+ for (index = 0; index < width; index++) {
+ if (static_cast<BitInit*>(init.getBit(index))->getValue())
+ ret |= mask;
+
+ mask <<= 1;
+ }
+
+ return ret;
+}
+
+static uint8_t getByteField(const Record &def, const char *str) {
+ BitsInit *bits = def.getValueAsBitsInit(str);
+ return byteFromBitsInit(*bits);
+}
+
+static BitsInit &getBitsField(const Record &def, const char *str) {
+ BitsInit *bits = def.getValueAsBitsInit(str);
+ return *bits;
+}
+
+/// sameStringExceptSuffix - Return true if the two strings differ only in RHS's
+/// suffix. ("VST4d8", "VST4d8_UPD", "_UPD") as input returns true.
+static
+bool sameStringExceptSuffix(const StringRef LHS, const StringRef RHS,
+ const StringRef Suffix) {
+
+ if (RHS.startswith(LHS) && RHS.endswith(Suffix))
+ return RHS.size() == LHS.size() + Suffix.size();
+
+ return false;
+}
+
+/// thumbInstruction - Determine whether we have a Thumb instruction.
+/// See also ARMInstrFormats.td.
+static bool thumbInstruction(uint8_t Form) {
+ return Form == ARM_FORMAT_THUMBFRM;
+}
+
+// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system
+// for a bit value.
+//
+// BIT_UNFILTERED is used as the init value for a filter position. It is used
+// only for filter processings.
+typedef enum {
+ BIT_TRUE, // '1'
+ BIT_FALSE, // '0'
+ BIT_UNSET, // '?'
+ BIT_UNFILTERED // unfiltered
+} bit_value_t;
+
+static bool ValueSet(bit_value_t V) {
+ return (V == BIT_TRUE || V == BIT_FALSE);
+}
+static bool ValueNotSet(bit_value_t V) {
+ return (V == BIT_UNSET);
+}
+static int Value(bit_value_t V) {
+ return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1);
+}
+static bit_value_t bitFromBits(BitsInit &bits, unsigned index) {
+ if (BitInit *bit = dynamic_cast<BitInit*>(bits.getBit(index)))
+ return bit->getValue() ? BIT_TRUE : BIT_FALSE;
+
+ // The bit is uninitialized.
+ return BIT_UNSET;
+}
+// Prints the bit value for each position.
+static void dumpBits(raw_ostream &o, BitsInit &bits) {
+ unsigned index;
+
+ for (index = bits.getNumBits(); index > 0; index--) {
+ switch (bitFromBits(bits, index - 1)) {
+ case BIT_TRUE:
+ o << "1";
+ break;
+ case BIT_FALSE:
+ o << "0";
+ break;
+ case BIT_UNSET:
+ o << "_";
+ break;
+ default:
+ assert(0 && "unexpected return value from bitFromBits");
+ }
+ }
+}
+
+// Enums for the available target names.
+typedef enum {
+ TARGET_ARM = 0,
+ TARGET_THUMB
+} TARGET_NAME_t;
+
+// FIXME: Possibly auto-detected?
+#define BIT_WIDTH 32
+
+// Forward declaration.
+class FilterChooser;
+
+// Representation of the instruction to work on.
+typedef bit_value_t insn_t[BIT_WIDTH];
+
+/// Filter - Filter works with FilterChooser to produce the decoding tree for
+/// the ISA.
+///
+/// It is useful to think of a Filter as governing the switch stmts of the
+/// decoding tree in a certain level. Each case stmt delegates to an inferior
+/// FilterChooser to decide what further decoding logic to employ, or in another
+/// words, what other remaining bits to look at. The FilterChooser eventually
+/// chooses a best Filter to do its job.
+///
+/// This recursive scheme ends when the number of Opcodes assigned to the
+/// FilterChooser becomes 1 or if there is a conflict. A conflict happens when
+/// the Filter/FilterChooser combo does not know how to distinguish among the
+/// Opcodes assigned.
+///
+/// An example of a conflcit is
+///
+/// Conflict:
+/// 111101000.00........00010000....
+/// 111101000.00........0001........
+/// 1111010...00........0001........
+/// 1111010...00....................
+/// 1111010.........................
+/// 1111............................
+/// ................................
+/// VST4q8a 111101000_00________00010000____
+/// VST4q8b 111101000_00________00010000____
+///
+/// The Debug output shows the path that the decoding tree follows to reach the
+/// the conclusion that there is a conflict. VST4q8a is a vst4 to double-spaced
+/// even registers, while VST4q8b is a vst4 to double-spaced odd regsisters.
+///
+/// The encoding info in the .td files does not specify this meta information,
+/// which could have been used by the decoder to resolve the conflict. The
+/// decoder could try to decode the even/odd register numbering and assign to
+/// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a"
+/// version and return the Opcode since the two have the same Asm format string.
+class Filter {
+protected:
+ FilterChooser *Owner; // points to the FilterChooser who owns this filter
+ unsigned StartBit; // the starting bit position
+ unsigned NumBits; // number of bits to filter
+ bool Mixed; // a mixed region contains both set and unset bits
+
+ // Map of well-known segment value to the set of uid's with that value.
+ std::map<uint64_t, std::vector<unsigned> > FilteredInstructions;
+
+ // Set of uid's with non-constant segment values.
+ std::vector<unsigned> VariableInstructions;
+
+ // Map of well-known segment value to its delegate.
+ std::map<unsigned, FilterChooser*> FilterChooserMap;
+
+ // Number of instructions which fall under FilteredInstructions category.
+ unsigned NumFiltered;
+
+ // Keeps track of the last opcode in the filtered bucket.
+ unsigned LastOpcFiltered;
+
+ // Number of instructions which fall under VariableInstructions category.
+ unsigned NumVariable;
+
+public:
+ unsigned getNumFiltered() { return NumFiltered; }
+ unsigned getNumVariable() { return NumVariable; }
+ unsigned getSingletonOpc() {
+ assert(NumFiltered == 1);
+ return LastOpcFiltered;
+ }
+ // Return the filter chooser for the group of instructions without constant
+ // segment values.
+ FilterChooser &getVariableFC() {
+ assert(NumFiltered == 1);
+ assert(FilterChooserMap.size() == 1);
+ return *(FilterChooserMap.find((unsigned)-1)->second);
+ }
+
+ Filter(const Filter &f);
+ Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed);
+
+ ~Filter();
+
+ // Divides the decoding task into sub tasks and delegates them to the
+ // inferior FilterChooser's.
+ //
+ // A special case arises when there's only one entry in the filtered
+ // instructions. In order to unambiguously decode the singleton, we need to
+ // match the remaining undecoded encoding bits against the singleton.
+ void recurse();
+
+ // Emit code to decode instructions given a segment or segments of bits.
+ void emit(raw_ostream &o, unsigned &Indentation);
+
+ // Returns the number of fanout produced by the filter. More fanout implies
+ // the filter distinguishes more categories of instructions.
+ unsigned usefulness() const;
+}; // End of class Filter
+
+// These are states of our finite state machines used in FilterChooser's
+// filterProcessor() which produces the filter candidates to use.
+typedef enum {
+ ATTR_NONE,
+ ATTR_FILTERED,
+ ATTR_ALL_SET,
+ ATTR_ALL_UNSET,
+ ATTR_MIXED
+} bitAttr_t;
+
+/// FilterChooser - FilterChooser chooses the best filter among a set of Filters
+/// in order to perform the decoding of instructions at the current level.
+///
+/// Decoding proceeds from the top down. Based on the well-known encoding bits
+/// of instructions available, FilterChooser builds up the possible Filters that
+/// can further the task of decoding by distinguishing among the remaining
+/// candidate instructions.
+///
+/// Once a filter has been chosen, it is called upon to divide the decoding task
+/// into sub-tasks and delegates them to its inferior FilterChoosers for further
+/// processings.
+///
+/// It is useful to think of a Filter as governing the switch stmts of the
+/// decoding tree. And each case is delegated to an inferior FilterChooser to
+/// decide what further remaining bits to look at.
+class FilterChooser {
+ static TARGET_NAME_t TargetName;
+
+protected:
+ friend class Filter;
+
+ // Vector of codegen instructions to choose our filter.
+ const std::vector<const CodeGenInstruction*> &AllInstructions;
+
+ // Vector of uid's for this filter chooser to work on.
+ const std::vector<unsigned> Opcodes;
+
+ // Vector of candidate filters.
+ std::vector<Filter> Filters;
+
+ // Array of bit values passed down from our parent.
+ // Set to all BIT_UNFILTERED's for Parent == NULL.
+ bit_value_t FilterBitValues[BIT_WIDTH];
+
+ // Links to the FilterChooser above us in the decoding tree.
+ FilterChooser *Parent;
+
+ // Index of the best filter from Filters.
+ int BestIndex;
+
+public:
+ static void setTargetName(TARGET_NAME_t tn) { TargetName = tn; }
+
+ FilterChooser(const FilterChooser &FC) :
+ AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
+ Filters(FC.Filters), Parent(FC.Parent), BestIndex(FC.BestIndex) {
+ memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues));
+ }
+
+ FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
+ const std::vector<unsigned> &IDs) :
+ AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(NULL),
+ BestIndex(-1) {
+ for (unsigned i = 0; i < BIT_WIDTH; ++i)
+ FilterBitValues[i] = BIT_UNFILTERED;
+
+ doFilter();
+ }
+
+ FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
+ const std::vector<unsigned> &IDs,
+ bit_value_t (&ParentFilterBitValues)[BIT_WIDTH],
+ FilterChooser &parent) :
+ AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(&parent),
+ BestIndex(-1) {
+ for (unsigned i = 0; i < BIT_WIDTH; ++i)
+ FilterBitValues[i] = ParentFilterBitValues[i];
+
+ doFilter();
+ }
+
+ // The top level filter chooser has NULL as its parent.
+ bool isTopLevel() { return Parent == NULL; }
+
+ // This provides an opportunity for target specific code emission.
+ void emitTopHook(raw_ostream &o);
+
+ // Emit the top level typedef and decodeInstruction() function.
+ void emitTop(raw_ostream &o, unsigned &Indentation);
+
+ // This provides an opportunity for target specific code emission after
+ // emitTop().
+ void emitBot(raw_ostream &o, unsigned &Indentation);
+
+protected:
+ // Populates the insn given the uid.
+ void insnWithID(insn_t &Insn, unsigned Opcode) const {
+ BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst");
+
+ for (unsigned i = 0; i < BIT_WIDTH; ++i)
+ Insn[i] = bitFromBits(Bits, i);
+
+ // Set Inst{21} to 1 (wback) when IndexModeBits == IndexModeUpd.
+ if (getByteField(*AllInstructions[Opcode]->TheDef, "IndexModeBits")
+ == IndexModeUpd)
+ Insn[21] = BIT_TRUE;
+ }
+
+ // Returns the record name.
+ const std::string &nameWithID(unsigned Opcode) const {
+ return AllInstructions[Opcode]->TheDef->getName();
+ }
+
+ // Populates the field of the insn given the start position and the number of
+ // consecutive bits to scan for.
+ //
+ // Returns false if there exists any uninitialized bit value in the range.
+ // Returns true, otherwise.
+ bool fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit,
+ unsigned NumBits) const;
+
+ /// dumpFilterArray - dumpFilterArray prints out debugging info for the given
+ /// filter array as a series of chars.
+ void dumpFilterArray(raw_ostream &o, bit_value_t (&filter)[BIT_WIDTH]);
+
+ /// dumpStack - dumpStack traverses the filter chooser chain and calls
+ /// dumpFilterArray on each filter chooser up to the top level one.
+ void dumpStack(raw_ostream &o, const char *prefix);
+
+ Filter &bestFilter() {
+ assert(BestIndex != -1 && "BestIndex not set");
+ return Filters[BestIndex];
+ }
+
+ // Called from Filter::recurse() when singleton exists. For debug purpose.
+ void SingletonExists(unsigned Opc);
+
+ bool PositionFiltered(unsigned i) {
+ return ValueSet(FilterBitValues[i]);
+ }
+
+ // Calculates the island(s) needed to decode the instruction.
+ // This returns a lit of undecoded bits of an instructions, for example,
+ // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
+ // decoded bits in order to verify that the instruction matches the Opcode.
+ unsigned getIslands(std::vector<unsigned> &StartBits,
+ std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
+ insn_t &Insn);
+
+ // The purpose of this function is for the API client to detect possible
+ // Load/Store Coprocessor instructions. If the coprocessor number is of
+ // the instruction is either 10 or 11, the decoder should not report the
+ // instruction as LDC/LDC2/STC/STC2, but should match against Advanced SIMD or
+ // VFP instructions.
+ bool LdStCopEncoding1(unsigned Opc) {
+ const std::string &Name = nameWithID(Opc);
+ if (Name == "LDC_OFFSET" || Name == "LDC_OPTION" ||
+ Name == "LDC_POST" || Name == "LDC_PRE" ||
+ Name == "LDCL_OFFSET" || Name == "LDCL_OPTION" ||
+ Name == "LDCL_POST" || Name == "LDCL_PRE" ||
+ Name == "STC_OFFSET" || Name == "STC_OPTION" ||
+ Name == "STC_POST" || Name == "STC_PRE" ||
+ Name == "STCL_OFFSET" || Name == "STCL_OPTION" ||
+ Name == "STCL_POST" || Name == "STCL_PRE")
+ return true;
+ else
+ return false;
+ }
+
+ // Emits code to decode the singleton. Return true if we have matched all the
+ // well-known bits.
+ bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc);
+
+ // Emits code to decode the singleton, and then to decode the rest.
+ void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,Filter &Best);
+
+ // Assign a single filter and run with it.
+ void runSingleFilter(FilterChooser &owner, unsigned startBit, unsigned numBit,
+ bool mixed);
+
+ // reportRegion is a helper function for filterProcessor to mark a region as
+ // eligible for use as a filter region.
+ void reportRegion(bitAttr_t RA, unsigned StartBit, unsigned BitIndex,
+ bool AllowMixed);
+
+ // FilterProcessor scans the well-known encoding bits of the instructions and
+ // builds up a list of candidate filters. It chooses the best filter and
+ // recursively descends down the decoding tree.
+ bool filterProcessor(bool AllowMixed, bool Greedy = true);
+
+ // Decides on the best configuration of filter(s) to use in order to decode
+ // the instructions. A conflict of instructions may occur, in which case we
+ // dump the conflict set to the standard error.
+ void doFilter();
+
+ // Emits code to decode our share of instructions. Returns true if the
+ // emitted code causes a return, which occurs if we know how to decode
+ // the instruction at this level or the instruction is not decodeable.
+ bool emit(raw_ostream &o, unsigned &Indentation);
+};
+
+///////////////////////////
+// //
+// Filter Implmenetation //
+// //
+///////////////////////////
+
+Filter::Filter(const Filter &f) :
+ Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed),
+ FilteredInstructions(f.FilteredInstructions),
+ VariableInstructions(f.VariableInstructions),
+ FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered),
+ LastOpcFiltered(f.LastOpcFiltered), NumVariable(f.NumVariable) {
+}
+
+Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
+ bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits),
+ Mixed(mixed) {
+ assert(StartBit + NumBits - 1 < BIT_WIDTH);
+
+ NumFiltered = 0;
+ LastOpcFiltered = 0;
+ NumVariable = 0;
+
+ for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) {
+ insn_t Insn;
+
+ // Populates the insn given the uid.
+ Owner->insnWithID(Insn, Owner->Opcodes[i]);
+
+ uint64_t Field;
+ // Scans the segment for possibly well-specified encoding bits.
+ bool ok = Owner->fieldFromInsn(Field, Insn, StartBit, NumBits);
+
+ if (ok) {
+ // The encoding bits are well-known. Lets add the uid of the
+ // instruction into the bucket keyed off the constant field value.
+ LastOpcFiltered = Owner->Opcodes[i];
+ FilteredInstructions[Field].push_back(LastOpcFiltered);
+ ++NumFiltered;
+ } else {
+ // Some of the encoding bit(s) are unspecfied. This contributes to
+ // one additional member of "Variable" instructions.
+ VariableInstructions.push_back(Owner->Opcodes[i]);
+ ++NumVariable;
+ }
+ }
+
+ assert((FilteredInstructions.size() + VariableInstructions.size() > 0)
+ && "Filter returns no instruction categories");
+}
+
+Filter::~Filter() {
+ std::map<unsigned, FilterChooser*>::iterator filterIterator;
+ for (filterIterator = FilterChooserMap.begin();
+ filterIterator != FilterChooserMap.end();
+ filterIterator++) {
+ delete filterIterator->second;
+ }
+}
+
+// Divides the decoding task into sub tasks and delegates them to the
+// inferior FilterChooser's.
+//
+// A special case arises when there's only one entry in the filtered
+// instructions. In order to unambiguously decode the singleton, we need to
+// match the remaining undecoded encoding bits against the singleton.
+void Filter::recurse() {
+ std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator;
+
+ bit_value_t BitValueArray[BIT_WIDTH];
+ // Starts by inheriting our parent filter chooser's filter bit values.
+ memcpy(BitValueArray, Owner->FilterBitValues, sizeof(BitValueArray));
+
+ unsigned bitIndex;
+
+ if (VariableInstructions.size()) {
+ // Conservatively marks each segment position as BIT_UNSET.
+ for (bitIndex = 0; bitIndex < NumBits; bitIndex++)
+ BitValueArray[StartBit + bitIndex] = BIT_UNSET;
+
+ // Delegates to an inferior filter chooser for futher processing on this
+ // group of instructions whose segment values are variable.
+ FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>(
+ (unsigned)-1,
+ new FilterChooser(Owner->AllInstructions,
+ VariableInstructions,
+ BitValueArray,
+ *Owner)
+ ));
+ }
+
+ // No need to recurse for a singleton filtered instruction.
+ // See also Filter::emit().
+ if (getNumFiltered() == 1) {
+ //Owner->SingletonExists(LastOpcFiltered);
+ assert(FilterChooserMap.size() == 1);
+ return;
+ }
+
+ // Otherwise, create sub choosers.
+ for (mapIterator = FilteredInstructions.begin();
+ mapIterator != FilteredInstructions.end();
+ mapIterator++) {
+
+ // Marks all the segment positions with either BIT_TRUE or BIT_FALSE.
+ for (bitIndex = 0; bitIndex < NumBits; bitIndex++) {
+ if (mapIterator->first & (1ULL << bitIndex))
+ BitValueArray[StartBit + bitIndex] = BIT_TRUE;
+ else
+ BitValueArray[StartBit + bitIndex] = BIT_FALSE;
+ }
+
+ // Delegates to an inferior filter chooser for futher processing on this
+ // category of instructions.
+ FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>(
+ mapIterator->first,
+ new FilterChooser(Owner->AllInstructions,
+ mapIterator->second,
+ BitValueArray,
+ *Owner)
+ ));
+ }
+}
+
+// Emit code to decode instructions given a segment or segments of bits.
+void Filter::emit(raw_ostream &o, unsigned &Indentation) {
+ o.indent(Indentation) << "// Check Inst{";
+
+ if (NumBits > 1)
+ o << (StartBit + NumBits - 1) << '-';
+
+ o << StartBit << "} ...\n";
+
+ o.indent(Indentation) << "switch (fieldFromInstruction(insn, "
+ << StartBit << ", " << NumBits << ")) {\n";
+
+ std::map<unsigned, FilterChooser*>::iterator filterIterator;
+
+ bool DefaultCase = false;
+ for (filterIterator = FilterChooserMap.begin();
+ filterIterator != FilterChooserMap.end();
+ filterIterator++) {
+
+ // Field value -1 implies a non-empty set of variable instructions.
+ // See also recurse().
+ if (filterIterator->first == (unsigned)-1) {
+ DefaultCase = true;
+
+ o.indent(Indentation) << "default:\n";
+ o.indent(Indentation) << " break; // fallthrough\n";
+
+ // Closing curly brace for the switch statement.
+ // This is unconventional because we want the default processing to be
+ // performed for the fallthrough cases as well, i.e., when the "cases"
+ // did not prove a decoded instruction.
+ o.indent(Indentation) << "}\n";
+
+ } else
+ o.indent(Indentation) << "case " << filterIterator->first << ":\n";
+
+ // We arrive at a category of instructions with the same segment value.
+ // Now delegate to the sub filter chooser for further decodings.
+ // The case may fallthrough, which happens if the remaining well-known
+ // encoding bits do not match exactly.
+ if (!DefaultCase) { ++Indentation; ++Indentation; }
+
+ bool finished = filterIterator->second->emit(o, Indentation);
+ // For top level default case, there's no need for a break statement.
+ if (Owner->isTopLevel() && DefaultCase)
+ break;
+ if (!finished)
+ o.indent(Indentation) << "break;\n";
+
+ if (!DefaultCase) { --Indentation; --Indentation; }
+ }
+
+ // If there is no default case, we still need to supply a closing brace.
+ if (!DefaultCase) {
+ // Closing curly brace for the switch statement.
+ o.indent(Indentation) << "}\n";
+ }
+}
+
+// Returns the number of fanout produced by the filter. More fanout implies
+// the filter distinguishes more categories of instructions.
+unsigned Filter::usefulness() const {
+ if (VariableInstructions.size())
+ return FilteredInstructions.size();
+ else
+ return FilteredInstructions.size() + 1;
+}
+
+//////////////////////////////////
+// //
+// Filterchooser Implementation //
+// //
+//////////////////////////////////
+
+// Define the symbol here.
+TARGET_NAME_t FilterChooser::TargetName;
+
+// This provides an opportunity for target specific code emission.
+void FilterChooser::emitTopHook(raw_ostream &o) {
+ if (TargetName == TARGET_ARM) {
+ // Emit code that references the ARMFormat data type.
+ o << "static const ARMFormat ARMFormats[] = {\n";
+ for (unsigned i = 0, e = AllInstructions.size(); i != e; ++i) {
+ const Record &Def = *(AllInstructions[i]->TheDef);
+ const std::string &Name = Def.getName();
+ if (Def.isSubClassOf("InstARM") || Def.isSubClassOf("InstThumb"))
+ o.indent(2) <<
+ stringForARMFormat((ARMFormat)getByteField(Def, "Form"));
+ else
+ o << " ARM_FORMAT_NA";
+
+ o << ",\t// Inst #" << i << " = " << Name << '\n';
+ }
+ o << " ARM_FORMAT_NA\t// Unreachable.\n";
+ o << "};\n\n";
+ }
+}
+
+// Emit the top level typedef and decodeInstruction() function.
+void FilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) {
+ // Run the target specific emit hook.
+ emitTopHook(o);
+
+ switch (BIT_WIDTH) {
+ case 8:
+ o.indent(Indentation) << "typedef uint8_t field_t;\n";
+ break;
+ case 16:
+ o.indent(Indentation) << "typedef uint16_t field_t;\n";
+ break;
+ case 32:
+ o.indent(Indentation) << "typedef uint32_t field_t;\n";
+ break;
+ case 64:
+ o.indent(Indentation) << "typedef uint64_t field_t;\n";
+ break;
+ default:
+ assert(0 && "Unexpected instruction size!");
+ }
+
+ o << '\n';
+
+ o.indent(Indentation) << "static field_t " <<
+ "fieldFromInstruction(field_t insn, unsigned startBit, unsigned numBits)\n";
+
+ o.indent(Indentation) << "{\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "assert(startBit + numBits <= " << BIT_WIDTH
+ << " && \"Instruction field out of bounds!\");\n";
+ o << '\n';
+ o.indent(Indentation) << "field_t fieldMask;\n";
+ o << '\n';
+ o.indent(Indentation) << "if (numBits == " << BIT_WIDTH << ")\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "fieldMask = (field_t)-1;\n";
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "else\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n";
+ --Indentation; --Indentation;
+
+ o << '\n';
+ o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n";
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "}\n";
+
+ o << '\n';
+
+ o.indent(Indentation) << "static uint16_t decodeInstruction(field_t insn) {\n";
+
+ ++Indentation; ++Indentation;
+ // Emits code to decode the instructions.
+ emit(o, Indentation);
+
+ o << '\n';
+ o.indent(Indentation) << "return 0;\n";
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "}\n";
+
+ o << '\n';
+}
+
+// This provides an opportunity for target specific code emission after
+// emitTop().
+void FilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) {
+ if (TargetName != TARGET_THUMB) return;
+
+ // Emit code that decodes the Thumb ISA.
+ o.indent(Indentation)
+ << "static uint16_t decodeThumbInstruction(field_t insn) {\n";
+
+ ++Indentation; ++Indentation;
+
+ // Emits code to decode the instructions.
+ emit(o, Indentation);
+
+ o << '\n';
+ o.indent(Indentation) << "return 0;\n";
+
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "}\n";
+}
+
+// Populates the field of the insn given the start position and the number of
+// consecutive bits to scan for.
+//
+// Returns false if and on the first uninitialized bit value encountered.
+// Returns true, otherwise.
+bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
+ unsigned StartBit, unsigned NumBits) const {
+ Field = 0;
+
+ for (unsigned i = 0; i < NumBits; ++i) {
+ if (Insn[StartBit + i] == BIT_UNSET)
+ return false;
+
+ if (Insn[StartBit + i] == BIT_TRUE)
+ Field = Field | (1ULL << i);
+ }
+
+ return true;
+}
+
+/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
+/// filter array as a series of chars.
+void FilterChooser::dumpFilterArray(raw_ostream &o,
+ bit_value_t (&filter)[BIT_WIDTH]) {
+ unsigned bitIndex;
+
+ for (bitIndex = BIT_WIDTH; bitIndex > 0; bitIndex--) {
+ switch (filter[bitIndex - 1]) {
+ case BIT_UNFILTERED:
+ o << ".";
+ break;
+ case BIT_UNSET:
+ o << "_";
+ break;
+ case BIT_TRUE:
+ o << "1";
+ break;
+ case BIT_FALSE:
+ o << "0";
+ break;
+ }
+ }
+}
+
+/// dumpStack - dumpStack traverses the filter chooser chain and calls
+/// dumpFilterArray on each filter chooser up to the top level one.
+void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) {
+ FilterChooser *current = this;
+
+ while (current) {
+ o << prefix;
+ dumpFilterArray(o, current->FilterBitValues);
+ o << '\n';
+ current = current->Parent;
+ }
+}
+
+// Called from Filter::recurse() when singleton exists. For debug purpose.
+void FilterChooser::SingletonExists(unsigned Opc) {
+ insn_t Insn0;
+ insnWithID(Insn0, Opc);
+
+ errs() << "Singleton exists: " << nameWithID(Opc)
+ << " with its decoding dominating ";
+ for (unsigned i = 0; i < Opcodes.size(); ++i) {
+ if (Opcodes[i] == Opc) continue;
+ errs() << nameWithID(Opcodes[i]) << ' ';
+ }
+ errs() << '\n';
+
+ dumpStack(errs(), "\t\t");
+ for (unsigned i = 0; i < Opcodes.size(); i++) {
+ const std::string &Name = nameWithID(Opcodes[i]);
+
+ errs() << '\t' << Name << " ";
+ dumpBits(errs(),
+ getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst"));
+ errs() << '\n';
+ }
+}
+
+// Calculates the island(s) needed to decode the instruction.
+// This returns a list of undecoded bits of an instructions, for example,
+// Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
+// decoded bits in order to verify that the instruction matches the Opcode.
+unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
+ std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
+ insn_t &Insn) {
+ unsigned Num, BitNo;
+ Num = BitNo = 0;
+
+ uint64_t FieldVal = 0;
+
+ // 0: Init
+ // 1: Water (the bit value does not affect decoding)
+ // 2: Island (well-known bit value needed for decoding)
+ int State = 0;
+ int Val = -1;
+
+ for (unsigned i = 0; i < BIT_WIDTH; ++i) {
+ Val = Value(Insn[i]);
+ bool Filtered = PositionFiltered(i);
+ switch (State) {
+ default:
+ assert(0 && "Unreachable code!");
+ break;
+ case 0:
+ case 1:
+ if (Filtered || Val == -1)
+ State = 1; // Still in Water
+ else {
+ State = 2; // Into the Island
+ BitNo = 0;
+ StartBits.push_back(i);
+ FieldVal = Val;
+ }
+ break;
+ case 2:
+ if (Filtered || Val == -1) {
+ State = 1; // Into the Water
+ EndBits.push_back(i - 1);
+ FieldVals.push_back(FieldVal);
+ ++Num;
+ } else {
+ State = 2; // Still in Island
+ ++BitNo;
+ FieldVal = FieldVal | Val << BitNo;
+ }
+ break;
+ }
+ }
+ // If we are still in Island after the loop, do some housekeeping.
+ if (State == 2) {
+ EndBits.push_back(BIT_WIDTH - 1);
+ FieldVals.push_back(FieldVal);
+ ++Num;
+ }
+
+ assert(StartBits.size() == Num && EndBits.size() == Num &&
+ FieldVals.size() == Num);
+ return Num;
+}
+
+// Emits code to decode the singleton. Return true if we have matched all the
+// well-known bits.
+bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
+ unsigned Opc) {
+ std::vector<unsigned> StartBits;
+ std::vector<unsigned> EndBits;
+ std::vector<uint64_t> FieldVals;
+ insn_t Insn;
+ insnWithID(Insn, Opc);
+
+ // This provides a good opportunity to check for possible Ld/St Coprocessor
+ // Opcode and escapes if the coproc # is either 10 or 11. It is a NEON/VFP
+ // instruction is disguise.
+ if (TargetName == TARGET_ARM && LdStCopEncoding1(Opc)) {
+ o.indent(Indentation);
+ // A8.6.51 & A8.6.188
+ // If coproc = 0b101?, i.e, slice(insn, 11, 8) = 10 or 11, escape.
+ o << "if (fieldFromInstruction(insn, 9, 3) == 5) break; // fallthrough\n";
+ }
+
+ // Look for islands of undecoded bits of the singleton.
+ getIslands(StartBits, EndBits, FieldVals, Insn);
+
+ unsigned Size = StartBits.size();
+ unsigned I, NumBits;
+
+ // If we have matched all the well-known bits, just issue a return.
+ if (Size == 0) {
+ o.indent(Indentation) << "return " << Opc << "; // " << nameWithID(Opc)
+ << '\n';
+ return true;
+ }
+
+ // Otherwise, there are more decodings to be done!
+
+ // Emit code to match the island(s) for the singleton.
+ o.indent(Indentation) << "// Check ";
+
+ for (I = Size; I != 0; --I) {
+ o << "Inst{" << EndBits[I-1] << '-' << StartBits[I-1] << "} ";
+ if (I > 1)
+ o << "&& ";
+ else
+ o << "for singleton decoding...\n";
+ }
+
+ o.indent(Indentation) << "if (";
+
+ for (I = Size; I != 0; --I) {
+ NumBits = EndBits[I-1] - StartBits[I-1] + 1;
+ o << "fieldFromInstruction(insn, " << StartBits[I-1] << ", " << NumBits
+ << ") == " << FieldVals[I-1];
+ if (I > 1)
+ o << " && ";
+ else
+ o << ")\n";
+ }
+
+ o.indent(Indentation) << " return " << Opc << "; // " << nameWithID(Opc)
+ << '\n';
+
+ return false;
+}
+
+// Emits code to decode the singleton, and then to decode the rest.
+void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
+ Filter &Best) {
+
+ unsigned Opc = Best.getSingletonOpc();
+
+ emitSingletonDecoder(o, Indentation, Opc);
+
+ // Emit code for the rest.
+ o.indent(Indentation) << "else\n";
+
+ Indentation += 2;
+ Best.getVariableFC().emit(o, Indentation);
+ Indentation -= 2;
+}
+
+// Assign a single filter and run with it. Top level API client can initialize
+// with a single filter to start the filtering process.
+void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit,
+ unsigned numBit, bool mixed) {
+ Filters.clear();
+ Filter F(*this, startBit, numBit, true);
+ Filters.push_back(F);
+ BestIndex = 0; // Sole Filter instance to choose from.
+ bestFilter().recurse();
+}
+
+// reportRegion is a helper function for filterProcessor to mark a region as
+// eligible for use as a filter region.
+void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit,
+ unsigned BitIndex, bool AllowMixed) {
+ if (RA == ATTR_MIXED && AllowMixed)
+ Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, true));
+ else if (RA == ATTR_ALL_SET && !AllowMixed)
+ Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, false));
+}
+
+// FilterProcessor scans the well-known encoding bits of the instructions and
+// builds up a list of candidate filters. It chooses the best filter and
+// recursively descends down the decoding tree.
+bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
+ Filters.clear();
+ BestIndex = -1;
+ unsigned numInstructions = Opcodes.size();
+
+ assert(numInstructions && "Filter created with no instructions");
+
+ // No further filtering is necessary.
+ if (numInstructions == 1)
+ return true;
+
+ // Heuristics. See also doFilter()'s "Heuristics" comment when num of
+ // instructions is 3.
+ if (AllowMixed && !Greedy) {
+ assert(numInstructions == 3);
+
+ for (unsigned i = 0; i < Opcodes.size(); ++i) {
+ std::vector<unsigned> StartBits;
+ std::vector<unsigned> EndBits;
+ std::vector<uint64_t> FieldVals;
+ insn_t Insn;
+
+ insnWithID(Insn, Opcodes[i]);
+
+ // Look for islands of undecoded bits of any instruction.
+ if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) {
+ // Found an instruction with island(s). Now just assign a filter.
+ runSingleFilter(*this, StartBits[0], EndBits[0] - StartBits[0] + 1,
+ true);
+ return true;
+ }
+ }
+ }
+
+ unsigned BitIndex, InsnIndex;
+
+ // We maintain BIT_WIDTH copies of the bitAttrs automaton.
+ // The automaton consumes the corresponding bit from each
+ // instruction.
+ //
+ // Input symbols: 0, 1, and _ (unset).
+ // States: NONE, FILTERED, ALL_SET, ALL_UNSET, and MIXED.
+ // Initial state: NONE.
+ //
+ // (NONE) ------- [01] -> (ALL_SET)
+ // (NONE) ------- _ ----> (ALL_UNSET)
+ // (ALL_SET) ---- [01] -> (ALL_SET)
+ // (ALL_SET) ---- _ ----> (MIXED)
+ // (ALL_UNSET) -- [01] -> (MIXED)
+ // (ALL_UNSET) -- _ ----> (ALL_UNSET)
+ // (MIXED) ------ . ----> (MIXED)
+ // (FILTERED)---- . ----> (FILTERED)
+
+ bitAttr_t bitAttrs[BIT_WIDTH];
+
+ // FILTERED bit positions provide no entropy and are not worthy of pursuing.
+ // Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
+ for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex)
+ if (FilterBitValues[BitIndex] == BIT_TRUE ||
+ FilterBitValues[BitIndex] == BIT_FALSE)
+ bitAttrs[BitIndex] = ATTR_FILTERED;
+ else
+ bitAttrs[BitIndex] = ATTR_NONE;
+
+ for (InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) {
+ insn_t insn;
+
+ insnWithID(insn, Opcodes[InsnIndex]);
+
+ for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex) {
+ switch (bitAttrs[BitIndex]) {
+ case ATTR_NONE:
+ if (insn[BitIndex] == BIT_UNSET)
+ bitAttrs[BitIndex] = ATTR_ALL_UNSET;
+ else
+ bitAttrs[BitIndex] = ATTR_ALL_SET;
+ break;
+ case ATTR_ALL_SET:
+ if (insn[BitIndex] == BIT_UNSET)
+ bitAttrs[BitIndex] = ATTR_MIXED;
+ break;
+ case ATTR_ALL_UNSET:
+ if (insn[BitIndex] != BIT_UNSET)
+ bitAttrs[BitIndex] = ATTR_MIXED;
+ break;
+ case ATTR_MIXED:
+ case ATTR_FILTERED:
+ break;
+ }
+ }
+ }
+
+ // The regionAttr automaton consumes the bitAttrs automatons' state,
+ // lowest-to-highest.
+ //
+ // Input symbols: F(iltered), (all_)S(et), (all_)U(nset), M(ixed)
+ // States: NONE, ALL_SET, MIXED
+ // Initial state: NONE
+ //
+ // (NONE) ----- F --> (NONE)
+ // (NONE) ----- S --> (ALL_SET) ; and set region start
+ // (NONE) ----- U --> (NONE)
+ // (NONE) ----- M --> (MIXED) ; and set region start
+ // (ALL_SET) -- F --> (NONE) ; and report an ALL_SET region
+ // (ALL_SET) -- S --> (ALL_SET)
+ // (ALL_SET) -- U --> (NONE) ; and report an ALL_SET region
+ // (ALL_SET) -- M --> (MIXED) ; and report an ALL_SET region
+ // (MIXED) ---- F --> (NONE) ; and report a MIXED region
+ // (MIXED) ---- S --> (ALL_SET) ; and report a MIXED region
+ // (MIXED) ---- U --> (NONE) ; and report a MIXED region
+ // (MIXED) ---- M --> (MIXED)
+
+ bitAttr_t RA = ATTR_NONE;
+ unsigned StartBit = 0;
+
+ for (BitIndex = 0; BitIndex < BIT_WIDTH; BitIndex++) {
+ bitAttr_t bitAttr = bitAttrs[BitIndex];
+
+ assert(bitAttr != ATTR_NONE && "Bit without attributes");
+
+ switch (RA) {
+ case ATTR_NONE:
+ switch (bitAttr) {
+ case ATTR_FILTERED:
+ break;
+ case ATTR_ALL_SET:
+ StartBit = BitIndex;
+ RA = ATTR_ALL_SET;
+ break;
+ case ATTR_ALL_UNSET:
+ break;
+ case ATTR_MIXED:
+ StartBit = BitIndex;
+ RA = ATTR_MIXED;
+ break;
+ default:
+ assert(0 && "Unexpected bitAttr!");
+ }
+ break;
+ case ATTR_ALL_SET:
+ switch (bitAttr) {
+ case ATTR_FILTERED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ RA = ATTR_NONE;
+ break;
+ case ATTR_ALL_SET:
+ break;
+ case ATTR_ALL_UNSET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ RA = ATTR_NONE;
+ break;
+ case ATTR_MIXED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ StartBit = BitIndex;
+ RA = ATTR_MIXED;
+ break;
+ default:
+ assert(0 && "Unexpected bitAttr!");
+ }
+ break;
+ case ATTR_MIXED:
+ switch (bitAttr) {
+ case ATTR_FILTERED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ StartBit = BitIndex;
+ RA = ATTR_NONE;
+ break;
+ case ATTR_ALL_SET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ StartBit = BitIndex;
+ RA = ATTR_ALL_SET;
+ break;
+ case ATTR_ALL_UNSET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ RA = ATTR_NONE;
+ break;
+ case ATTR_MIXED:
+ break;
+ default:
+ assert(0 && "Unexpected bitAttr!");
+ }
+ break;
+ case ATTR_ALL_UNSET:
+ assert(0 && "regionAttr state machine has no ATTR_UNSET state");
+ case ATTR_FILTERED:
+ assert(0 && "regionAttr state machine has no ATTR_FILTERED state");
+ }
+ }
+
+ // At the end, if we're still in ALL_SET or MIXED states, report a region
+ switch (RA) {
+ case ATTR_NONE:
+ break;
+ case ATTR_FILTERED:
+ break;
+ case ATTR_ALL_SET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ break;
+ case ATTR_ALL_UNSET:
+ break;
+ case ATTR_MIXED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ break;
+ }
+
+ // We have finished with the filter processings. Now it's time to choose
+ // the best performing filter.
+ BestIndex = 0;
+ bool AllUseless = true;
+ unsigned BestScore = 0;
+
+ for (unsigned i = 0, e = Filters.size(); i != e; ++i) {
+ unsigned Usefulness = Filters[i].usefulness();
+
+ if (Usefulness)
+ AllUseless = false;
+
+ if (Usefulness > BestScore) {
+ BestIndex = i;
+ BestScore = Usefulness;
+ }
+ }
+
+ if (!AllUseless)
+ bestFilter().recurse();
+
+ return !AllUseless;
+} // end of FilterChooser::filterProcessor(bool)
+
+// Decides on the best configuration of filter(s) to use in order to decode
+// the instructions. A conflict of instructions may occur, in which case we
+// dump the conflict set to the standard error.
+void FilterChooser::doFilter() {
+ unsigned Num = Opcodes.size();
+ assert(Num && "FilterChooser created with no instructions");
+
+ // Heuristics: Use Inst{31-28} as the top level filter for ARM ISA.
+ if (TargetName == TARGET_ARM && Parent == NULL) {
+ runSingleFilter(*this, 28, 4, false);
+ return;
+ }
+
+ // Try regions of consecutive known bit values first.
+ if (filterProcessor(false))
+ return;
+
+ // Then regions of mixed bits (both known and unitialized bit values allowed).
+ if (filterProcessor(true))
+ return;
+
+ // Heuristics to cope with conflict set {t2CMPrs, t2SUBSrr, t2SUBSrs} where
+ // no single instruction for the maximum ATTR_MIXED region Inst{14-4} has a
+ // well-known encoding pattern. In such case, we backtrack and scan for the
+ // the very first consecutive ATTR_ALL_SET region and assign a filter to it.
+ if (Num == 3 && filterProcessor(true, false))
+ return;
+
+ // If we come to here, the instruction decoding has failed.
+ // Set the BestIndex to -1 to indicate so.
+ BestIndex = -1;
+}
+
+// Emits code to decode our share of instructions. Returns true if the
+// emitted code causes a return, which occurs if we know how to decode
+// the instruction at this level or the instruction is not decodeable.
+bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) {
+ if (Opcodes.size() == 1)
+ // There is only one instruction in the set, which is great!
+ // Call emitSingletonDecoder() to see whether there are any remaining
+ // encodings bits.
+ return emitSingletonDecoder(o, Indentation, Opcodes[0]);
+
+ // Choose the best filter to do the decodings!
+ if (BestIndex != -1) {
+ Filter &Best = bestFilter();
+ if (Best.getNumFiltered() == 1)
+ emitSingletonDecoder(o, Indentation, Best);
+ else
+ bestFilter().emit(o, Indentation);
+ return false;
+ }
+
+ // If we reach here, there is a conflict in decoding. Let's resolve the known
+ // conflicts!
+ if ((TargetName == TARGET_ARM || TargetName == TARGET_THUMB) &&
+ Opcodes.size() == 2) {
+ // Resolve the known conflict sets:
+ //
+ // 1. source registers are identical => VMOVDneon; otherwise => VORRd
+ // 2. source registers are identical => VMOVQ; otherwise => VORRq
+ // 3. LDR, LDRcp => return LDR for now.
+ // FIXME: How can we distinguish between LDR and LDRcp? Do we need to?
+ // 4. tLDM, tLDM_UPD => Rn = Inst{10-8}, reglist = Inst{7-0},
+ // wback = registers<Rn> = 0
+ // NOTE: (tLDM, tLDM_UPD) resolution must come before Advanced SIMD
+ // addressing mode resolution!!!
+ // 5. VLD[234]LN*/VST[234]LN* vs. VLD[234]LN*_UPD/VST[234]LN*_UPD conflicts
+ // are resolved returning the non-UPD versions of the instructions if the
+ // Rm field, i.e., Inst{3-0} is 0b1111. This is specified in A7.7.1
+ // Advanced SIMD addressing mode.
+ const std::string &name1 = nameWithID(Opcodes[0]);
+ const std::string &name2 = nameWithID(Opcodes[1]);
+ if ((name1 == "VMOVDneon" && name2 == "VORRd") ||
+ (name1 == "VMOVQ" && name2 == "VORRq")) {
+ // Inserting the opening curly brace for this case block.
+ --Indentation; --Indentation;
+ o.indent(Indentation) << "{\n";
+ ++Indentation; ++Indentation;
+
+ o.indent(Indentation)
+ << "field_t N = fieldFromInstruction(insn, 7, 1), "
+ << "M = fieldFromInstruction(insn, 5, 1);\n";
+ o.indent(Indentation)
+ << "field_t Vn = fieldFromInstruction(insn, 16, 4), "
+ << "Vm = fieldFromInstruction(insn, 0, 4);\n";
+ o.indent(Indentation)
+ << "return (N == M && Vn == Vm) ? "
+ << Opcodes[0] << " /* " << name1 << " */ : "
+ << Opcodes[1] << " /* " << name2 << " */ ;\n";
+
+ // Inserting the closing curly brace for this case block.
+ --Indentation; --Indentation;
+ o.indent(Indentation) << "}\n";
+ ++Indentation; ++Indentation;
+
+ return true;
+ }
+ if (name1 == "LDR" && name2 == "LDRcp") {
+ o.indent(Indentation)
+ << "return " << Opcodes[0]
+ << "; // Returning LDR for {LDR, LDRcp}\n";
+ return true;
+ }
+ if (name1 == "tLDM" && name2 == "tLDM_UPD") {
+ // Inserting the opening curly brace for this case block.
+ --Indentation; --Indentation;
+ o.indent(Indentation) << "{\n";
+ ++Indentation; ++Indentation;
+
+ o.indent(Indentation)
+ << "unsigned Rn = fieldFromInstruction(insn, 8, 3), "
+ << "list = fieldFromInstruction(insn, 0, 8);\n";
+ o.indent(Indentation)
+ << "return ((list >> Rn) & 1) == 0 ? "
+ << Opcodes[1] << " /* " << name2 << " */ : "
+ << Opcodes[0] << " /* " << name1 << " */ ;\n";
+
+ // Inserting the closing curly brace for this case block.
+ --Indentation; --Indentation;
+ o.indent(Indentation) << "}\n";
+ ++Indentation; ++Indentation;
+
+ return true;
+ }
+ if (sameStringExceptSuffix(name1, name2, "_UPD")) {
+ o.indent(Indentation)
+ << "return fieldFromInstruction(insn, 0, 4) == 15 ? " << Opcodes[0]
+ << " /* " << name1 << " */ : " << Opcodes[1] << "/* " << name2
+ << " */ ; // Advanced SIMD addressing mode\n";
+ return true;
+ }
+
+ // Otherwise, it does not belong to the known conflict sets.
+ }
+
+ // We don't know how to decode these instructions! Return 0 and dump the
+ // conflict set!
+ o.indent(Indentation) << "return 0;" << " // Conflict set: ";
+ for (int i = 0, N = Opcodes.size(); i < N; ++i) {
+ o << nameWithID(Opcodes[i]);
+ if (i < (N - 1))
+ o << ", ";
+ else
+ o << '\n';
+ }
+
+ // Print out useful conflict information for postmortem analysis.
+ errs() << "Decoding Conflict:\n";
+
+ dumpStack(errs(), "\t\t");
+
+ for (unsigned i = 0; i < Opcodes.size(); i++) {
+ const std::string &Name = nameWithID(Opcodes[i]);
+
+ errs() << '\t' << Name << " ";
+ dumpBits(errs(),
+ getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst"));
+ errs() << '\n';
+ }
+
+ return true;
+}
+
+
+////////////////////////////////////////////
+// //
+// ARMDEBackend //
+// (Helper class for ARMDecoderEmitter) //
+// //
+////////////////////////////////////////////
+
+class ARMDecoderEmitter::ARMDEBackend {
+public:
+ ARMDEBackend(ARMDecoderEmitter &frontend) :
+ NumberedInstructions(),
+ Opcodes(),
+ Frontend(frontend),
+ Target(),
+ FC(NULL)
+ {
+ if (Target.getName() == "ARM")
+ TargetName = TARGET_ARM;
+ else {
+ errs() << "Target name " << Target.getName() << " not recognized\n";
+ assert(0 && "Unknown target");
+ }
+
+ // Populate the instructions for our TargetName.
+ populateInstructions();
+ }
+
+ ~ARMDEBackend() {
+ if (FC) {
+ delete FC;
+ FC = NULL;
+ }
+ }
+
+ void getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
+ &NumberedInstructions) {
+ // We must emit the PHI opcode first...
+ std::string Namespace = Target.getInstNamespace();
+ assert(!Namespace.empty() && "No instructions defined.");
+
+ NumberedInstructions = Target.getInstructionsByEnumValue();
+ }
+
+ bool populateInstruction(const CodeGenInstruction &CGI, TARGET_NAME_t TN);
+
+ void populateInstructions();
+
+ // Emits disassembler code for instruction decoding. This delegates to the
+ // FilterChooser instance to do the heavy lifting.
+ void emit(raw_ostream &o);
+
+protected:
+ std::vector<const CodeGenInstruction*> NumberedInstructions;
+ std::vector<unsigned> Opcodes;
+ // Special case for the ARM chip, which supports ARM and Thumb ISAs.
+ // Opcodes2 will be populated with the Thumb opcodes.
+ std::vector<unsigned> Opcodes2;
+ ARMDecoderEmitter &Frontend;
+ CodeGenTarget Target;
+ FilterChooser *FC;
+
+ TARGET_NAME_t TargetName;
+};
+
+bool ARMDecoderEmitter::ARMDEBackend::populateInstruction(
+ const CodeGenInstruction &CGI, TARGET_NAME_t TN) {
+ const Record &Def = *CGI.TheDef;
+ const StringRef Name = Def.getName();
+ uint8_t Form = getByteField(Def, "Form");
+
+ BitsInit &Bits = getBitsField(Def, "Inst");
+
+ // If all the bit positions are not specified; do not decode this instruction.
+ // We are bound to fail! For proper disassembly, the well-known encoding bits
+ // of the instruction must be fully specified.
+ //
+ // This also removes pseudo instructions from considerations of disassembly,
+ // which is a better design and less fragile than the name matchings.
+ if (Bits.allInComplete()) return false;
+
+ if (TN == TARGET_ARM) {
+ // FIXME: what about Int_MemBarrierV6 and Int_SyncBarrierV6?
+ if ((Name != "Int_MemBarrierV7" && Name != "Int_SyncBarrierV7") &&
+ Form == ARM_FORMAT_PSEUDO)
+ return false;
+ if (thumbInstruction(Form))
+ return false;
+ if (Name.find("CMPz") != std::string::npos /* ||
+ Name.find("CMNz") != std::string::npos */)
+ return false;
+
+ // Ignore pseudo instructions.
+ if (Name == "BXr9" || Name == "BMOVPCRX" || Name == "BMOVPCRXr9")
+ return false;
+
+ // Tail calls are other patterns that generate existing instructions.
+ if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" ||
+ Name == "TCRETURNri" || Name == "TCRETURNriND" ||
+ Name == "TAILJMPd" || Name == "TAILJMPdt" ||
+ Name == "TAILJMPdND" || Name == "TAILJMPdNDt" ||
+ Name == "TAILJMPr" || Name == "TAILJMPrND" ||
+ Name == "MOVr_TC")
+ return false;
+
+ // VLDMQ/VSTMQ can be handled with the more generic VLDMD/VSTMD.
+ if (Name == "VLDMQ" || Name == "VLDMQ_UPD" ||
+ Name == "VSTMQ" || Name == "VSTMQ_UPD")
+ return false;
+
+ //
+ // The following special cases are for conflict resolutions.
+ //
+
+ // NEON NLdStFrm conflict resolutions:
+ //
+ // 1. Ignore suffix "odd" and "odd_UPD", prefer the "even" register-
+ // numbered ones which have the same Asm format string.
+ // 2. Ignore VST2d64_UPD, which conflicts with VST1q64_UPD.
+ // 3. Ignore VLD2d64_UPD, which conflicts with VLD1q64_UPD.
+ // 4. Ignore VLD1q[_UPD], which conflicts with VLD1q64[_UPD].
+ // 5. Ignore VST1q[_UPD], which conflicts with VST1q64[_UPD].
+ if (Name.endswith("odd") || Name.endswith("odd_UPD") ||
+ Name == "VST2d64_UPD" || Name == "VLD2d64_UPD" ||
+ Name == "VLD1q" || Name == "VLD1q_UPD" ||
+ Name == "VST1q" || Name == "VST1q_UPD")
+ return false;
+
+ // RSCSri and RSCSrs set the 's' bit, but are not predicated. We are
+ // better off using the generic RSCri and RSCrs instructions.
+ if (Name == "RSCSri" || Name == "RSCSrs") return false;
+
+ // MOVCCr, MOVCCs, MOVCCi, FCYPScc, FCYPDcc, FNEGScc, and FNEGDcc are used
+ // in the compiler to implement conditional moves. We can ignore them in
+ // favor of their more generic versions of instructions.
+ // See also SDNode *ARMDAGToDAGISel::Select(SDValue Op).
+ if (Name == "MOVCCr" || Name == "MOVCCs" || Name == "MOVCCi" ||
+ Name == "FCPYScc" || Name == "FCPYDcc" ||
+ Name == "FNEGScc" || Name == "FNEGDcc")
+ return false;
+
+ // Ditto for VMOVDcc, VMOVScc, VNEGDcc, and VNEGScc.
+ if (Name == "VMOVDcc" || Name == "VMOVScc" || Name == "VNEGDcc" ||
+ Name == "VNEGScc")
+ return false;
+
+ // Ignore the *_sfp instructions when decoding. They are used by the
+ // compiler to implement scalar floating point operations using vector
+ // operations in order to work around some performance issues.
+ if (Name.find("_sfp") != std::string::npos) return false;
+
+ // LDM_RET is a special case of LDM (Load Multiple) where the registers
+ // loaded include the PC, causing a branch to a loaded address. Ignore
+ // the LDM_RET instruction when decoding.
+ if (Name == "LDM_RET") return false;
+
+ // Bcc is in a more generic form than B. Ignore B when decoding.
+ if (Name == "B") return false;
+
+ // Ignore the non-Darwin BL instructions and the TPsoft (TLS) instruction.
+ if (Name == "BL" || Name == "BL_pred" || Name == "BLX" || Name == "BX" ||
+ Name == "TPsoft")
+ return false;
+
+ // Ignore VDUPf[d|q] instructions known to conflict with VDUP32[d-q] for
+ // decoding. The instruction duplicates an element from an ARM core
+ // register into every element of the destination vector. There is no
+ // distinction between data types.
+ if (Name == "VDUPfd" || Name == "VDUPfq") return false;
+
+ // A8-598: VEXT
+ // Vector Extract extracts elements from the bottom end of the second
+ // operand vector and the top end of the first, concatenates them and
+ // places the result in the destination vector. The elements of the
+ // vectors are treated as being 8-bit bitfields. There is no distinction
+ // between data types. The size of the operation can be specified in
+ // assembler as vext.size. If the value is 16, 32, or 64, the syntax is
+ // a pseudo-instruction for a VEXT instruction specifying the equivalent
+ // number of bytes.
+ //
+ // Variants VEXTd16, VEXTd32, VEXTd8, and VEXTdf are reduced to VEXTd8;
+ // variants VEXTq16, VEXTq32, VEXTq8, and VEXTqf are reduced to VEXTq8.
+ if (Name == "VEXTd16" || Name == "VEXTd32" || Name == "VEXTdf" ||
+ Name == "VEXTq16" || Name == "VEXTq32" || Name == "VEXTqf")
+ return false;
+
+ // Vector Reverse is similar to Vector Extract. There is no distinction
+ // between data types, other than size.
+ //
+ // VREV64df is equivalent to VREV64d32.
+ // VREV64qf is equivalent to VREV64q32.
+ if (Name == "VREV64df" || Name == "VREV64qf") return false;
+
+ // VDUPLNfd is equivalent to VDUPLN32d; VDUPfdf is specialized VDUPLN32d.
+ // VDUPLNfq is equivalent to VDUPLN32q; VDUPfqf is specialized VDUPLN32q.
+ // VLD1df is equivalent to VLD1d32.
+ // VLD1qf is equivalent to VLD1q32.
+ // VLD2d64 is equivalent to VLD1q64.
+ // VST1df is equivalent to VST1d32.
+ // VST1qf is equivalent to VST1q32.
+ // VST2d64 is equivalent to VST1q64.
+ if (Name == "VDUPLNfd" || Name == "VDUPfdf" ||
+ Name == "VDUPLNfq" || Name == "VDUPfqf" ||
+ Name == "VLD1df" || Name == "VLD1qf" || Name == "VLD2d64" ||
+ Name == "VST1df" || Name == "VST1qf" || Name == "VST2d64")
+ return false;
+ } else if (TN == TARGET_THUMB) {
+ if (!thumbInstruction(Form))
+ return false;
+
+ // On Darwin R9 is call-clobbered. Ignore the non-Darwin counterparts.
+ if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr")
+ return false;
+
+ // Ignore the TPsoft (TLS) instructions, which conflict with tBLr9.
+ if (Name == "tTPsoft" || Name == "t2TPsoft")
+ return false;
+
+ // Ignore tLEApcrel and tLEApcrelJT, prefer tADDrPCi.
+ if (Name == "tLEApcrel" || Name == "tLEApcrelJT")
+ return false;
+
+ // Ignore t2LEApcrel, prefer the generic t2ADD* for disassembly printing.
+ if (Name == "t2LEApcrel")
+ return false;
+
+ // Ignore tADDrSP, tADDspr, and tPICADD, prefer the generic tADDhirr.
+ // Ignore t2SUBrSPs, prefer the t2SUB[S]r[r|s].
+ // Ignore t2ADDrSPs, prefer the t2ADD[S]r[r|s].
+ // Ignore t2ADDrSPi/t2SUBrSPi, which have more generic couterparts.
+ // Ignore t2ADDrSPi12/t2SUBrSPi12, which have more generic couterparts
+ if (Name == "tADDrSP" || Name == "tADDspr" || Name == "tPICADD" ||
+ Name == "t2SUBrSPs" || Name == "t2ADDrSPs" ||
+ Name == "t2ADDrSPi" || Name == "t2SUBrSPi" ||
+ Name == "t2ADDrSPi12" || Name == "t2SUBrSPi12")
+ return false;
+
+ // Ignore t2LDRDpci, prefer the generic t2LDRDi8, t2LDRD_PRE, t2LDRD_POST.
+ if (Name == "t2LDRDpci")
+ return false;
+
+ // Ignore t2TBB, t2TBH and prefer the generic t2TBBgen, t2TBHgen.
+ if (Name == "t2TBB" || Name == "t2TBH")
+ return false;
+
+ // Resolve conflicts:
+ //
+ // tBfar conflicts with tBLr9
+ // tCMNz conflicts with tCMN (with assembly format strings being equal)
+ // tPOP_RET/t2LDM_RET conflict with tPOP/t2LDM (ditto)
+ // tMOVCCi conflicts with tMOVi8
+ // tMOVCCr conflicts with tMOVgpr2gpr
+ // tBR_JTr conflicts with tBRIND
+ // tSpill conflicts with tSTRspi
+ // tLDRcp conflicts with tLDRspi
+ // tRestore conflicts with tLDRspi
+ // t2LEApcrelJT conflicts with t2LEApcrel
+ if (Name == "tBfar" ||
+ /* Name == "tCMNz" || */ Name == "tCMPzi8" || Name == "tCMPzr" ||
+ Name == "tCMPzhir" || /* Name == "t2CMNzrr" || Name == "t2CMNzrs" ||
+ Name == "t2CMNzri" || */ Name == "t2CMPzrr" || Name == "t2CMPzrs" ||
+ Name == "t2CMPzri" || Name == "tPOP_RET" || Name == "t2LDM_RET" ||
+ Name == "tMOVCCi" || Name == "tMOVCCr" || Name == "tBR_JTr" ||
+ Name == "tSpill" || Name == "tLDRcp" || Name == "tRestore" ||
+ Name == "t2LEApcrelJT")
+ return false;
+ }
+
+ // Dumps the instruction encoding format.
+ switch (TargetName) {
+ case TARGET_ARM:
+ case TARGET_THUMB:
+ DEBUG(errs() << Name << " " << stringForARMFormat((ARMFormat)Form));
+ break;
+ }
+
+ DEBUG({
+ errs() << " ";
+
+ // Dumps the instruction encoding bits.
+ dumpBits(errs(), Bits);
+
+ errs() << '\n';
+
+ // Dumps the list of operand info.
+ for (unsigned i = 0, e = CGI.OperandList.size(); i != e; ++i) {
+ CodeGenInstruction::OperandInfo Info = CGI.OperandList[i];
+ const std::string &OperandName = Info.Name;
+ const Record &OperandDef = *Info.Rec;
+
+ errs() << "\t" << OperandName << " (" << OperandDef.getName() << ")\n";
+ }
+ });
+
+ return true;
+}
+
+void ARMDecoderEmitter::ARMDEBackend::populateInstructions() {
+ getInstructionsByEnumValue(NumberedInstructions);
+
+ uint16_t numUIDs = NumberedInstructions.size();
+ uint16_t uid;
+
+ const char *instClass = NULL;
+
+ switch (TargetName) {
+ case TARGET_ARM:
+ instClass = "InstARM";
+ break;
+ default:
+ assert(0 && "Unreachable code!");
+ }
+
+ for (uid = 0; uid < numUIDs; uid++) {
+ // filter out intrinsics
+ if (!NumberedInstructions[uid]->TheDef->isSubClassOf(instClass))
+ continue;
+
+ if (populateInstruction(*NumberedInstructions[uid], TargetName))
+ Opcodes.push_back(uid);
+ }
+
+ // Special handling for the ARM chip, which supports two modes of execution.
+ // This branch handles the Thumb opcodes.
+ if (TargetName == TARGET_ARM) {
+ for (uid = 0; uid < numUIDs; uid++) {
+ // filter out intrinsics
+ if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM")
+ && !NumberedInstructions[uid]->TheDef->isSubClassOf("InstThumb"))
+ continue;
+
+ if (populateInstruction(*NumberedInstructions[uid], TARGET_THUMB))
+ Opcodes2.push_back(uid);
+ }
+ }
+}
+
+// Emits disassembler code for instruction decoding. This delegates to the
+// FilterChooser instance to do the heavy lifting.
+void ARMDecoderEmitter::ARMDEBackend::emit(raw_ostream &o) {
+ switch (TargetName) {
+ case TARGET_ARM:
+ Frontend.EmitSourceFileHeader("ARM/Thumb Decoders", o);
+ break;
+ default:
+ assert(0 && "Unreachable code!");
+ }
+
+ o << "#include \"llvm/System/DataTypes.h\"\n";
+ o << "#include <assert.h>\n";
+ o << '\n';
+ o << "namespace llvm {\n\n";
+
+ FilterChooser::setTargetName(TargetName);
+
+ switch (TargetName) {
+ case TARGET_ARM: {
+ // Emit common utility and ARM ISA decoder.
+ FC = new FilterChooser(NumberedInstructions, Opcodes);
+ // Reset indentation level.
+ unsigned Indentation = 0;
+ FC->emitTop(o, Indentation);
+ delete FC;
+
+ // Emit Thumb ISA decoder as well.
+ FilterChooser::setTargetName(TARGET_THUMB);
+ FC = new FilterChooser(NumberedInstructions, Opcodes2);
+ // Reset indentation level.
+ Indentation = 0;
+ FC->emitBot(o, Indentation);
+ break;
+ }
+ default:
+ assert(0 && "Unreachable code!");
+ }
+
+ o << "\n} // End llvm namespace \n";
+}
+
+/////////////////////////
+// Backend interface //
+/////////////////////////
+
+void ARMDecoderEmitter::initBackend()
+{
+ Backend = new ARMDEBackend(*this);
+}
+
+void ARMDecoderEmitter::run(raw_ostream &o)
+{
+ Backend->emit(o);
+}
+
+void ARMDecoderEmitter::shutdownBackend()
+{
+ delete Backend;
+ Backend = NULL;
+}
diff --git a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h
new file mode 100644
index 0000000..571a947
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h
@@ -0,0 +1,50 @@
+//===------------ ARMDecoderEmitter.h - Decoder Generator -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the ARM Disassembler.
+// It contains the tablegen backend declaration ARMDecoderEmitter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ARMDECODEREMITTER_H
+#define ARMDECODEREMITTER_H
+
+#include "TableGenBackend.h"
+
+#include "llvm/System/DataTypes.h"
+
+namespace llvm {
+
+class ARMDecoderEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ ARMDecoderEmitter(RecordKeeper &R) : Records(R) {
+ initBackend();
+ }
+
+ ~ARMDecoderEmitter() {
+ shutdownBackend();
+ }
+
+ // run - Output the code emitter
+ void run(raw_ostream &o);
+
+private:
+ // Helper class for ARMDecoderEmitter.
+ class ARMDEBackend;
+
+ ARMDEBackend *Backend;
+
+ void initBackend();
+ void shutdownBackend();
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
new file mode 100644
index 0000000..5583986
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -0,0 +1,1811 @@
+//===- AsmMatcherEmitter.cpp - Generate an assembly matcher ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits a target specifier matcher for converting parsed
+// assembly operands in the MCInst structures.
+//
+// The input to the target specific matcher is a list of literal tokens and
+// operands. The target specific parser should generally eliminate any syntax
+// which is not relevant for matching; for example, comma tokens should have
+// already been consumed and eliminated by the parser. Most instructions will
+// end up with a single literal token (the instruction name) and some number of
+// operands.
+//
+// Some example inputs, for X86:
+// 'addl' (immediate ...) (register ...)
+// 'add' (immediate ...) (memory ...)
+// 'call' '*' %epc
+//
+// The assembly matcher is responsible for converting this input into a precise
+// machine instruction (i.e., an instruction with a well defined encoding). This
+// mapping has several properties which complicate matching:
+//
+// - It may be ambiguous; many architectures can legally encode particular
+// variants of an instruction in different ways (for example, using a smaller
+// encoding for small immediates). Such ambiguities should never be
+// arbitrarily resolved by the assembler, the assembler is always responsible
+// for choosing the "best" available instruction.
+//
+// - It may depend on the subtarget or the assembler context. Instructions
+// which are invalid for the current mode, but otherwise unambiguous (e.g.,
+// an SSE instruction in a file being assembled for i486) should be accepted
+// and rejected by the assembler front end. However, if the proper encoding
+// for an instruction is dependent on the assembler context then the matcher
+// is responsible for selecting the correct machine instruction for the
+// current mode.
+//
+// The core matching algorithm attempts to exploit the regularity in most
+// instruction sets to quickly determine the set of possibly matching
+// instructions, and the simplify the generated code. Additionally, this helps
+// to ensure that the ambiguities are intentionally resolved by the user.
+//
+// The matching is divided into two distinct phases:
+//
+// 1. Classification: Each operand is mapped to the unique set which (a)
+// contains it, and (b) is the largest such subset for which a single
+// instruction could match all members.
+//
+// For register classes, we can generate these subgroups automatically. For
+// arbitrary operands, we expect the user to define the classes and their
+// relations to one another (for example, 8-bit signed immediates as a
+// subset of 32-bit immediates).
+//
+// By partitioning the operands in this way, we guarantee that for any
+// tuple of classes, any single instruction must match either all or none
+// of the sets of operands which could classify to that tuple.
+//
+// In addition, the subset relation amongst classes induces a partial order
+// on such tuples, which we use to resolve ambiguities.
+//
+// FIXME: What do we do if a crazy case shows up where this is the wrong
+// resolution?
+//
+// 2. The input can now be treated as a tuple of classes (static tokens are
+// simple singleton sets). Each such tuple should generally map to a single
+// instruction (we currently ignore cases where this isn't true, whee!!!),
+// which we can emit a simple matcher for.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AsmMatcherEmitter.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include <list>
+#include <map>
+#include <set>
+using namespace llvm;
+
+static cl::opt<std::string>
+MatchPrefix("match-prefix", cl::init(""),
+ cl::desc("Only match instructions with the given prefix"));
+
+/// FlattenVariants - Flatten an .td file assembly string by selecting the
+/// variant at index \arg N.
+static std::string FlattenVariants(const std::string &AsmString,
+ unsigned N) {
+ StringRef Cur = AsmString;
+ std::string Res = "";
+
+ for (;;) {
+ // Find the start of the next variant string.
+ size_t VariantsStart = 0;
+ for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart)
+ if (Cur[VariantsStart] == '{' &&
+ (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' &&
+ Cur[VariantsStart-1] != '\\')))
+ break;
+
+ // Add the prefix to the result.
+ Res += Cur.slice(0, VariantsStart);
+ if (VariantsStart == Cur.size())
+ break;
+
+ ++VariantsStart; // Skip the '{'.
+
+ // Scan to the end of the variants string.
+ size_t VariantsEnd = VariantsStart;
+ unsigned NestedBraces = 1;
+ for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) {
+ if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') {
+ if (--NestedBraces == 0)
+ break;
+ } else if (Cur[VariantsEnd] == '{')
+ ++NestedBraces;
+ }
+
+ // Select the Nth variant (or empty).
+ StringRef Selection = Cur.slice(VariantsStart, VariantsEnd);
+ for (unsigned i = 0; i != N; ++i)
+ Selection = Selection.split('|').second;
+ Res += Selection.split('|').first;
+
+ assert(VariantsEnd != Cur.size() &&
+ "Unterminated variants in assembly string!");
+ Cur = Cur.substr(VariantsEnd + 1);
+ }
+
+ return Res;
+}
+
+/// TokenizeAsmString - Tokenize a simplified assembly string.
+static void TokenizeAsmString(StringRef AsmString,
+ SmallVectorImpl<StringRef> &Tokens) {
+ unsigned Prev = 0;
+ bool InTok = true;
+ for (unsigned i = 0, e = AsmString.size(); i != e; ++i) {
+ switch (AsmString[i]) {
+ case '[':
+ case ']':
+ case '*':
+ case '!':
+ case ' ':
+ case '\t':
+ case ',':
+ if (InTok) {
+ Tokens.push_back(AsmString.slice(Prev, i));
+ InTok = false;
+ }
+ if (!isspace(AsmString[i]) && AsmString[i] != ',')
+ Tokens.push_back(AsmString.substr(i, 1));
+ Prev = i + 1;
+ break;
+
+ case '\\':
+ if (InTok) {
+ Tokens.push_back(AsmString.slice(Prev, i));
+ InTok = false;
+ }
+ ++i;
+ assert(i != AsmString.size() && "Invalid quoted character");
+ Tokens.push_back(AsmString.substr(i, 1));
+ Prev = i + 1;
+ break;
+
+ case '$': {
+ // If this isn't "${", treat like a normal token.
+ if (i + 1 == AsmString.size() || AsmString[i + 1] != '{') {
+ if (InTok) {
+ Tokens.push_back(AsmString.slice(Prev, i));
+ InTok = false;
+ }
+ Prev = i;
+ break;
+ }
+
+ if (InTok) {
+ Tokens.push_back(AsmString.slice(Prev, i));
+ InTok = false;
+ }
+
+ StringRef::iterator End =
+ std::find(AsmString.begin() + i, AsmString.end(), '}');
+ assert(End != AsmString.end() && "Missing brace in operand reference!");
+ size_t EndPos = End - AsmString.begin();
+ Tokens.push_back(AsmString.slice(i, EndPos+1));
+ Prev = EndPos + 1;
+ i = EndPos;
+ break;
+ }
+
+ case '.':
+ if (InTok) {
+ Tokens.push_back(AsmString.slice(Prev, i));
+ }
+ Prev = i;
+ InTok = true;
+ break;
+
+ default:
+ InTok = true;
+ }
+ }
+ if (InTok && Prev != AsmString.size())
+ Tokens.push_back(AsmString.substr(Prev));
+}
+
+static bool IsAssemblerInstruction(StringRef Name,
+ const CodeGenInstruction &CGI,
+ const SmallVectorImpl<StringRef> &Tokens) {
+ // Ignore "codegen only" instructions.
+ if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
+ return false;
+
+ // Ignore pseudo ops.
+ //
+ // FIXME: This is a hack; can we convert these instructions to set the
+ // "codegen only" bit instead?
+ if (const RecordVal *Form = CGI.TheDef->getValue("Form"))
+ if (Form->getValue()->getAsString() == "Pseudo")
+ return false;
+
+ // Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
+ //
+ // FIXME: This is a total hack.
+ if (StringRef(Name).startswith("Int_") || StringRef(Name).endswith("_Int"))
+ return false;
+
+ // Ignore instructions with no .s string.
+ //
+ // FIXME: What are these?
+ if (CGI.AsmString.empty())
+ return false;
+
+ // FIXME: Hack; ignore any instructions with a newline in them.
+ if (std::find(CGI.AsmString.begin(),
+ CGI.AsmString.end(), '\n') != CGI.AsmString.end())
+ return false;
+
+ // Ignore instructions with attributes, these are always fake instructions for
+ // simplifying codegen.
+ //
+ // FIXME: Is this true?
+ //
+ // Also, check for instructions which reference the operand multiple times;
+ // this implies a constraint we would not honor.
+ std::set<std::string> OperandNames;
+ for (unsigned i = 1, e = Tokens.size(); i < e; ++i) {
+ if (Tokens[i][0] == '$' &&
+ std::find(Tokens[i].begin(),
+ Tokens[i].end(), ':') != Tokens[i].end()) {
+ DEBUG({
+ errs() << "warning: '" << Name << "': "
+ << "ignoring instruction; operand with attribute '"
+ << Tokens[i] << "'\n";
+ });
+ return false;
+ }
+
+ if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) {
+ DEBUG({
+ errs() << "warning: '" << Name << "': "
+ << "ignoring instruction with tied operand '"
+ << Tokens[i].str() << "'\n";
+ });
+ return false;
+ }
+ }
+
+ return true;
+}
+
+namespace {
+
+struct SubtargetFeatureInfo;
+
+/// ClassInfo - Helper class for storing the information about a particular
+/// class of operands which can be matched.
+struct ClassInfo {
+ enum ClassInfoKind {
+ /// Invalid kind, for use as a sentinel value.
+ Invalid = 0,
+
+ /// The class for a particular token.
+ Token,
+
+ /// The (first) register class, subsequent register classes are
+ /// RegisterClass0+1, and so on.
+ RegisterClass0,
+
+ /// The (first) user defined class, subsequent user defined classes are
+ /// UserClass0+1, and so on.
+ UserClass0 = 1<<16
+ };
+
+ /// Kind - The class kind, which is either a predefined kind, or (UserClass0 +
+ /// N) for the Nth user defined class.
+ unsigned Kind;
+
+ /// SuperClasses - The super classes of this class. Note that for simplicities
+ /// sake user operands only record their immediate super class, while register
+ /// operands include all superclasses.
+ std::vector<ClassInfo*> SuperClasses;
+
+ /// Name - The full class name, suitable for use in an enum.
+ std::string Name;
+
+ /// ClassName - The unadorned generic name for this class (e.g., Token).
+ std::string ClassName;
+
+ /// ValueName - The name of the value this class represents; for a token this
+ /// is the literal token string, for an operand it is the TableGen class (or
+ /// empty if this is a derived class).
+ std::string ValueName;
+
+ /// PredicateMethod - The name of the operand method to test whether the
+ /// operand matches this class; this is not valid for Token or register kinds.
+ std::string PredicateMethod;
+
+ /// RenderMethod - The name of the operand method to add this operand to an
+ /// MCInst; this is not valid for Token or register kinds.
+ std::string RenderMethod;
+
+ /// For register classes, the records for all the registers in this class.
+ std::set<Record*> Registers;
+
+public:
+ /// isRegisterClass() - Check if this is a register class.
+ bool isRegisterClass() const {
+ return Kind >= RegisterClass0 && Kind < UserClass0;
+ }
+
+ /// isUserClass() - Check if this is a user defined class.
+ bool isUserClass() const {
+ return Kind >= UserClass0;
+ }
+
+ /// isRelatedTo - Check whether this class is "related" to \arg RHS. Classes
+ /// are related if they are in the same class hierarchy.
+ bool isRelatedTo(const ClassInfo &RHS) const {
+ // Tokens are only related to tokens.
+ if (Kind == Token || RHS.Kind == Token)
+ return Kind == Token && RHS.Kind == Token;
+
+ // Registers classes are only related to registers classes, and only if
+ // their intersection is non-empty.
+ if (isRegisterClass() || RHS.isRegisterClass()) {
+ if (!isRegisterClass() || !RHS.isRegisterClass())
+ return false;
+
+ std::set<Record*> Tmp;
+ std::insert_iterator< std::set<Record*> > II(Tmp, Tmp.begin());
+ std::set_intersection(Registers.begin(), Registers.end(),
+ RHS.Registers.begin(), RHS.Registers.end(),
+ II);
+
+ return !Tmp.empty();
+ }
+
+ // Otherwise we have two users operands; they are related if they are in the
+ // same class hierarchy.
+ //
+ // FIXME: This is an oversimplification, they should only be related if they
+ // intersect, however we don't have that information.
+ assert(isUserClass() && RHS.isUserClass() && "Unexpected class!");
+ const ClassInfo *Root = this;
+ while (!Root->SuperClasses.empty())
+ Root = Root->SuperClasses.front();
+
+ const ClassInfo *RHSRoot = &RHS;
+ while (!RHSRoot->SuperClasses.empty())
+ RHSRoot = RHSRoot->SuperClasses.front();
+
+ return Root == RHSRoot;
+ }
+
+ /// isSubsetOf - Test whether this class is a subset of \arg RHS;
+ bool isSubsetOf(const ClassInfo &RHS) const {
+ // This is a subset of RHS if it is the same class...
+ if (this == &RHS)
+ return true;
+
+ // ... or if any of its super classes are a subset of RHS.
+ for (std::vector<ClassInfo*>::const_iterator it = SuperClasses.begin(),
+ ie = SuperClasses.end(); it != ie; ++it)
+ if ((*it)->isSubsetOf(RHS))
+ return true;
+
+ return false;
+ }
+
+ /// operator< - Compare two classes.
+ bool operator<(const ClassInfo &RHS) const {
+ if (this == &RHS)
+ return false;
+
+ // Unrelated classes can be ordered by kind.
+ if (!isRelatedTo(RHS))
+ return Kind < RHS.Kind;
+
+ switch (Kind) {
+ case Invalid:
+ assert(0 && "Invalid kind!");
+ case Token:
+ // Tokens are comparable by value.
+ //
+ // FIXME: Compare by enum value.
+ return ValueName < RHS.ValueName;
+
+ default:
+ // This class preceeds the RHS if it is a proper subset of the RHS.
+ if (isSubsetOf(RHS))
+ return true;
+ if (RHS.isSubsetOf(*this))
+ return false;
+
+ // Otherwise, order by name to ensure we have a total ordering.
+ return ValueName < RHS.ValueName;
+ }
+ }
+};
+
+/// InstructionInfo - Helper class for storing the necessary information for an
+/// instruction which is capable of being matched.
+struct InstructionInfo {
+ struct Operand {
+ /// The unique class instance this operand should match.
+ ClassInfo *Class;
+
+ /// The original operand this corresponds to, if any.
+ const CodeGenInstruction::OperandInfo *OperandInfo;
+ };
+
+ /// InstrName - The target name for this instruction.
+ std::string InstrName;
+
+ /// Instr - The instruction this matches.
+ const CodeGenInstruction *Instr;
+
+ /// AsmString - The assembly string for this instruction (with variants
+ /// removed).
+ std::string AsmString;
+
+ /// Tokens - The tokenized assembly pattern that this instruction matches.
+ SmallVector<StringRef, 4> Tokens;
+
+ /// Operands - The operands that this instruction matches.
+ SmallVector<Operand, 4> Operands;
+
+ /// Predicates - The required subtarget features to match this instruction.
+ SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures;
+
+ /// ConversionFnKind - The enum value which is passed to the generated
+ /// ConvertToMCInst to convert parsed operands into an MCInst for this
+ /// function.
+ std::string ConversionFnKind;
+
+ /// operator< - Compare two instructions.
+ bool operator<(const InstructionInfo &RHS) const {
+ if (Operands.size() != RHS.Operands.size())
+ return Operands.size() < RHS.Operands.size();
+
+ // Compare lexicographically by operand. The matcher validates that other
+ // orderings wouldn't be ambiguous using \see CouldMatchAmiguouslyWith().
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (*Operands[i].Class < *RHS.Operands[i].Class)
+ return true;
+ if (*RHS.Operands[i].Class < *Operands[i].Class)
+ return false;
+ }
+
+ return false;
+ }
+
+ /// CouldMatchAmiguouslyWith - Check whether this instruction could
+ /// ambiguously match the same set of operands as \arg RHS (without being a
+ /// strictly superior match).
+ bool CouldMatchAmiguouslyWith(const InstructionInfo &RHS) {
+ // The number of operands is unambiguous.
+ if (Operands.size() != RHS.Operands.size())
+ return false;
+
+ // Otherwise, make sure the ordering of the two instructions is unambiguous
+ // by checking that either (a) a token or operand kind discriminates them,
+ // or (b) the ordering among equivalent kinds is consistent.
+
+ // Tokens and operand kinds are unambiguous (assuming a correct target
+ // specific parser).
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (Operands[i].Class->Kind != RHS.Operands[i].Class->Kind ||
+ Operands[i].Class->Kind == ClassInfo::Token)
+ if (*Operands[i].Class < *RHS.Operands[i].Class ||
+ *RHS.Operands[i].Class < *Operands[i].Class)
+ return false;
+
+ // Otherwise, this operand could commute if all operands are equivalent, or
+ // there is a pair of operands that compare less than and a pair that
+ // compare greater than.
+ bool HasLT = false, HasGT = false;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (*Operands[i].Class < *RHS.Operands[i].Class)
+ HasLT = true;
+ if (*RHS.Operands[i].Class < *Operands[i].Class)
+ HasGT = true;
+ }
+
+ return !(HasLT ^ HasGT);
+ }
+
+public:
+ void dump();
+};
+
+/// SubtargetFeatureInfo - Helper class for storing information on a subtarget
+/// feature which participates in instruction matching.
+struct SubtargetFeatureInfo {
+ /// \brief The predicate record for this feature.
+ Record *TheDef;
+
+ /// \brief An unique index assigned to represent this feature.
+ unsigned Index;
+
+ /// \brief The name of the enumerated constant identifying this feature.
+ std::string EnumName;
+};
+
+class AsmMatcherInfo {
+public:
+ /// The tablegen AsmParser record.
+ Record *AsmParser;
+
+ /// The AsmParser "CommentDelimiter" value.
+ std::string CommentDelimiter;
+
+ /// The AsmParser "RegisterPrefix" value.
+ std::string RegisterPrefix;
+
+ /// The classes which are needed for matching.
+ std::vector<ClassInfo*> Classes;
+
+ /// The information on the instruction to match.
+ std::vector<InstructionInfo*> Instructions;
+
+ /// Map of Register records to their class information.
+ std::map<Record*, ClassInfo*> RegisterClasses;
+
+ /// Map of Predicate records to their subtarget information.
+ std::map<Record*, SubtargetFeatureInfo*> SubtargetFeatures;
+
+private:
+ /// Map of token to class information which has already been constructed.
+ std::map<std::string, ClassInfo*> TokenClasses;
+
+ /// Map of RegisterClass records to their class information.
+ std::map<Record*, ClassInfo*> RegisterClassClasses;
+
+ /// Map of AsmOperandClass records to their class information.
+ std::map<Record*, ClassInfo*> AsmOperandClasses;
+
+private:
+ /// getTokenClass - Lookup or create the class for the given token.
+ ClassInfo *getTokenClass(StringRef Token);
+
+ /// getOperandClass - Lookup or create the class for the given operand.
+ ClassInfo *getOperandClass(StringRef Token,
+ const CodeGenInstruction::OperandInfo &OI);
+
+ /// getSubtargetFeature - Lookup or create the subtarget feature info for the
+ /// given operand.
+ SubtargetFeatureInfo *getSubtargetFeature(Record *Def) {
+ assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
+
+ SubtargetFeatureInfo *&Entry = SubtargetFeatures[Def];
+ if (!Entry) {
+ Entry = new SubtargetFeatureInfo;
+ Entry->TheDef = Def;
+ Entry->Index = SubtargetFeatures.size() - 1;
+ Entry->EnumName = "Feature_" + Def->getName();
+ assert(Entry->Index < 32 && "Too many subtarget features!");
+ }
+
+ return Entry;
+ }
+
+ /// BuildRegisterClasses - Build the ClassInfo* instances for register
+ /// classes.
+ void BuildRegisterClasses(CodeGenTarget &Target,
+ std::set<std::string> &SingletonRegisterNames);
+
+ /// BuildOperandClasses - Build the ClassInfo* instances for user defined
+ /// operand classes.
+ void BuildOperandClasses(CodeGenTarget &Target);
+
+public:
+ AsmMatcherInfo(Record *_AsmParser);
+
+ /// BuildInfo - Construct the various tables used during matching.
+ void BuildInfo(CodeGenTarget &Target);
+};
+
+}
+
+void InstructionInfo::dump() {
+ errs() << InstrName << " -- " << "flattened:\"" << AsmString << '\"'
+ << ", tokens:[";
+ for (unsigned i = 0, e = Tokens.size(); i != e; ++i) {
+ errs() << Tokens[i];
+ if (i + 1 != e)
+ errs() << ", ";
+ }
+ errs() << "]\n";
+
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ Operand &Op = Operands[i];
+ errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";
+ if (Op.Class->Kind == ClassInfo::Token) {
+ errs() << '\"' << Tokens[i] << "\"\n";
+ continue;
+ }
+
+ if (!Op.OperandInfo) {
+ errs() << "(singleton register)\n";
+ continue;
+ }
+
+ const CodeGenInstruction::OperandInfo &OI = *Op.OperandInfo;
+ errs() << OI.Name << " " << OI.Rec->getName()
+ << " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n";
+ }
+}
+
+static std::string getEnumNameForToken(StringRef Str) {
+ std::string Res;
+
+ for (StringRef::iterator it = Str.begin(), ie = Str.end(); it != ie; ++it) {
+ switch (*it) {
+ case '*': Res += "_STAR_"; break;
+ case '%': Res += "_PCT_"; break;
+ case ':': Res += "_COLON_"; break;
+
+ default:
+ if (isalnum(*it)) {
+ Res += *it;
+ } else {
+ Res += "_" + utostr((unsigned) *it) + "_";
+ }
+ }
+ }
+
+ return Res;
+}
+
+/// getRegisterRecord - Get the register record for \arg name, or 0.
+static Record *getRegisterRecord(CodeGenTarget &Target, StringRef Name) {
+ for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) {
+ const CodeGenRegister &Reg = Target.getRegisters()[i];
+ if (Name == Reg.TheDef->getValueAsString("AsmName"))
+ return Reg.TheDef;
+ }
+
+ return 0;
+}
+
+ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
+ ClassInfo *&Entry = TokenClasses[Token];
+
+ if (!Entry) {
+ Entry = new ClassInfo();
+ Entry->Kind = ClassInfo::Token;
+ Entry->ClassName = "Token";
+ Entry->Name = "MCK_" + getEnumNameForToken(Token);
+ Entry->ValueName = Token;
+ Entry->PredicateMethod = "<invalid>";
+ Entry->RenderMethod = "<invalid>";
+ Classes.push_back(Entry);
+ }
+
+ return Entry;
+}
+
+ClassInfo *
+AsmMatcherInfo::getOperandClass(StringRef Token,
+ const CodeGenInstruction::OperandInfo &OI) {
+ if (OI.Rec->isSubClassOf("RegisterClass")) {
+ ClassInfo *CI = RegisterClassClasses[OI.Rec];
+
+ if (!CI) {
+ PrintError(OI.Rec->getLoc(), "register class has no class info!");
+ throw std::string("ERROR: Missing register class!");
+ }
+
+ return CI;
+ }
+
+ assert(OI.Rec->isSubClassOf("Operand") && "Unexpected operand!");
+ Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass");
+ ClassInfo *CI = AsmOperandClasses[MatchClass];
+
+ if (!CI) {
+ PrintError(OI.Rec->getLoc(), "operand has no match class!");
+ throw std::string("ERROR: Missing match class!");
+ }
+
+ return CI;
+}
+
+void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target,
+ std::set<std::string>
+ &SingletonRegisterNames) {
+ std::vector<CodeGenRegisterClass> RegisterClasses;
+ std::vector<CodeGenRegister> Registers;
+
+ RegisterClasses = Target.getRegisterClasses();
+ Registers = Target.getRegisters();
+
+ // The register sets used for matching.
+ std::set< std::set<Record*> > RegisterSets;
+
+ // Gather the defined sets.
+ for (std::vector<CodeGenRegisterClass>::iterator it = RegisterClasses.begin(),
+ ie = RegisterClasses.end(); it != ie; ++it)
+ RegisterSets.insert(std::set<Record*>(it->Elements.begin(),
+ it->Elements.end()));
+
+ // Add any required singleton sets.
+ for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(),
+ ie = SingletonRegisterNames.end(); it != ie; ++it)
+ if (Record *Rec = getRegisterRecord(Target, *it))
+ RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1));
+
+ // Introduce derived sets where necessary (when a register does not determine
+ // a unique register set class), and build the mapping of registers to the set
+ // they should classify to.
+ std::map<Record*, std::set<Record*> > RegisterMap;
+ for (std::vector<CodeGenRegister>::iterator it = Registers.begin(),
+ ie = Registers.end(); it != ie; ++it) {
+ CodeGenRegister &CGR = *it;
+ // Compute the intersection of all sets containing this register.
+ std::set<Record*> ContainingSet;
+
+ for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(),
+ ie = RegisterSets.end(); it != ie; ++it) {
+ if (!it->count(CGR.TheDef))
+ continue;
+
+ if (ContainingSet.empty()) {
+ ContainingSet = *it;
+ } else {
+ std::set<Record*> Tmp;
+ std::swap(Tmp, ContainingSet);
+ std::insert_iterator< std::set<Record*> > II(ContainingSet,
+ ContainingSet.begin());
+ std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(),
+ II);
+ }
+ }
+
+ if (!ContainingSet.empty()) {
+ RegisterSets.insert(ContainingSet);
+ RegisterMap.insert(std::make_pair(CGR.TheDef, ContainingSet));
+ }
+ }
+
+ // Construct the register classes.
+ std::map<std::set<Record*>, ClassInfo*> RegisterSetClasses;
+ unsigned Index = 0;
+ for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(),
+ ie = RegisterSets.end(); it != ie; ++it, ++Index) {
+ ClassInfo *CI = new ClassInfo();
+ CI->Kind = ClassInfo::RegisterClass0 + Index;
+ CI->ClassName = "Reg" + utostr(Index);
+ CI->Name = "MCK_Reg" + utostr(Index);
+ CI->ValueName = "";
+ CI->PredicateMethod = ""; // unused
+ CI->RenderMethod = "addRegOperands";
+ CI->Registers = *it;
+ Classes.push_back(CI);
+ RegisterSetClasses.insert(std::make_pair(*it, CI));
+ }
+
+ // Find the superclasses; we could compute only the subgroup lattice edges,
+ // but there isn't really a point.
+ for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(),
+ ie = RegisterSets.end(); it != ie; ++it) {
+ ClassInfo *CI = RegisterSetClasses[*it];
+ for (std::set< std::set<Record*> >::iterator it2 = RegisterSets.begin(),
+ ie2 = RegisterSets.end(); it2 != ie2; ++it2)
+ if (*it != *it2 &&
+ std::includes(it2->begin(), it2->end(), it->begin(), it->end()))
+ CI->SuperClasses.push_back(RegisterSetClasses[*it2]);
+ }
+
+ // Name the register classes which correspond to a user defined RegisterClass.
+ for (std::vector<CodeGenRegisterClass>::iterator it = RegisterClasses.begin(),
+ ie = RegisterClasses.end(); it != ie; ++it) {
+ ClassInfo *CI = RegisterSetClasses[std::set<Record*>(it->Elements.begin(),
+ it->Elements.end())];
+ if (CI->ValueName.empty()) {
+ CI->ClassName = it->getName();
+ CI->Name = "MCK_" + it->getName();
+ CI->ValueName = it->getName();
+ } else
+ CI->ValueName = CI->ValueName + "," + it->getName();
+
+ RegisterClassClasses.insert(std::make_pair(it->TheDef, CI));
+ }
+
+ // Populate the map for individual registers.
+ for (std::map<Record*, std::set<Record*> >::iterator it = RegisterMap.begin(),
+ ie = RegisterMap.end(); it != ie; ++it)
+ this->RegisterClasses[it->first] = RegisterSetClasses[it->second];
+
+ // Name the register classes which correspond to singleton registers.
+ for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(),
+ ie = SingletonRegisterNames.end(); it != ie; ++it) {
+ if (Record *Rec = getRegisterRecord(Target, *it)) {
+ ClassInfo *CI = this->RegisterClasses[Rec];
+ assert(CI && "Missing singleton register class info!");
+
+ if (CI->ValueName.empty()) {
+ CI->ClassName = Rec->getName();
+ CI->Name = "MCK_" + Rec->getName();
+ CI->ValueName = Rec->getName();
+ } else
+ CI->ValueName = CI->ValueName + "," + Rec->getName();
+ }
+ }
+}
+
+void AsmMatcherInfo::BuildOperandClasses(CodeGenTarget &Target) {
+ std::vector<Record*> AsmOperands;
+ AsmOperands = Records.getAllDerivedDefinitions("AsmOperandClass");
+
+ // Pre-populate AsmOperandClasses map.
+ for (std::vector<Record*>::iterator it = AsmOperands.begin(),
+ ie = AsmOperands.end(); it != ie; ++it)
+ AsmOperandClasses[*it] = new ClassInfo();
+
+ unsigned Index = 0;
+ for (std::vector<Record*>::iterator it = AsmOperands.begin(),
+ ie = AsmOperands.end(); it != ie; ++it, ++Index) {
+ ClassInfo *CI = AsmOperandClasses[*it];
+ CI->Kind = ClassInfo::UserClass0 + Index;
+
+ ListInit *Supers = (*it)->getValueAsListInit("SuperClasses");
+ for (unsigned i = 0, e = Supers->getSize(); i != e; ++i) {
+ DefInit *DI = dynamic_cast<DefInit*>(Supers->getElement(i));
+ if (!DI) {
+ PrintError((*it)->getLoc(), "Invalid super class reference!");
+ continue;
+ }
+
+ ClassInfo *SC = AsmOperandClasses[DI->getDef()];
+ if (!SC)
+ PrintError((*it)->getLoc(), "Invalid super class reference!");
+ else
+ CI->SuperClasses.push_back(SC);
+ }
+ CI->ClassName = (*it)->getValueAsString("Name");
+ CI->Name = "MCK_" + CI->ClassName;
+ CI->ValueName = (*it)->getName();
+
+ // Get or construct the predicate method name.
+ Init *PMName = (*it)->getValueInit("PredicateMethod");
+ if (StringInit *SI = dynamic_cast<StringInit*>(PMName)) {
+ CI->PredicateMethod = SI->getValue();
+ } else {
+ assert(dynamic_cast<UnsetInit*>(PMName) &&
+ "Unexpected PredicateMethod field!");
+ CI->PredicateMethod = "is" + CI->ClassName;
+ }
+
+ // Get or construct the render method name.
+ Init *RMName = (*it)->getValueInit("RenderMethod");
+ if (StringInit *SI = dynamic_cast<StringInit*>(RMName)) {
+ CI->RenderMethod = SI->getValue();
+ } else {
+ assert(dynamic_cast<UnsetInit*>(RMName) &&
+ "Unexpected RenderMethod field!");
+ CI->RenderMethod = "add" + CI->ClassName + "Operands";
+ }
+
+ AsmOperandClasses[*it] = CI;
+ Classes.push_back(CI);
+ }
+}
+
+AsmMatcherInfo::AsmMatcherInfo(Record *_AsmParser)
+ : AsmParser(_AsmParser),
+ CommentDelimiter(AsmParser->getValueAsString("CommentDelimiter")),
+ RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix"))
+{
+}
+
+void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
+ // Parse the instructions; we need to do this first so that we can gather the
+ // singleton register classes.
+ std::set<std::string> SingletonRegisterNames;
+
+ const std::vector<const CodeGenInstruction*> &InstrList =
+ Target.getInstructionsByEnumValue();
+
+ for (unsigned i = 0, e = InstrList.size(); i != e; ++i) {
+ const CodeGenInstruction &CGI = *InstrList[i];
+
+ if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix))
+ continue;
+
+ OwningPtr<InstructionInfo> II(new InstructionInfo());
+
+ II->InstrName = CGI.TheDef->getName();
+ II->Instr = &CGI;
+ II->AsmString = FlattenVariants(CGI.AsmString, 0);
+
+ // Remove comments from the asm string.
+ if (!CommentDelimiter.empty()) {
+ size_t Idx = StringRef(II->AsmString).find(CommentDelimiter);
+ if (Idx != StringRef::npos)
+ II->AsmString = II->AsmString.substr(0, Idx);
+ }
+
+ TokenizeAsmString(II->AsmString, II->Tokens);
+
+ // Ignore instructions which shouldn't be matched.
+ if (!IsAssemblerInstruction(CGI.TheDef->getName(), CGI, II->Tokens))
+ continue;
+
+ // Collect singleton registers, if used.
+ if (!RegisterPrefix.empty()) {
+ for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
+ if (II->Tokens[i].startswith(RegisterPrefix)) {
+ StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size());
+ Record *Rec = getRegisterRecord(Target, RegName);
+
+ if (!Rec) {
+ std::string Err = "unable to find register for '" + RegName.str() +
+ "' (which matches register prefix)";
+ throw TGError(CGI.TheDef->getLoc(), Err);
+ }
+
+ SingletonRegisterNames.insert(RegName);
+ }
+ }
+ }
+
+ // Compute the require features.
+ ListInit *Predicates = CGI.TheDef->getValueAsListInit("Predicates");
+ for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
+ if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
+ // Ignore OptForSize and OptForSpeed, they aren't really requirements,
+ // rather they are hints to isel.
+ //
+ // FIXME: Find better way to model this.
+ if (Pred->getDef()->getName() == "OptForSize" ||
+ Pred->getDef()->getName() == "OptForSpeed")
+ continue;
+
+ // FIXME: Total hack; for now, we just limit ourselves to In32BitMode
+ // and In64BitMode, because we aren't going to have the right feature
+ // masks for SSE and friends. We need to decide what we are going to do
+ // about CPU subtypes to implement this the right way.
+ if (Pred->getDef()->getName() != "In32BitMode" &&
+ Pred->getDef()->getName() != "In64BitMode")
+ continue;
+
+ II->RequiredFeatures.push_back(getSubtargetFeature(Pred->getDef()));
+ }
+ }
+
+ Instructions.push_back(II.take());
+ }
+
+ // Build info for the register classes.
+ BuildRegisterClasses(Target, SingletonRegisterNames);
+
+ // Build info for the user defined assembly operand classes.
+ BuildOperandClasses(Target);
+
+ // Build the instruction information.
+ for (std::vector<InstructionInfo*>::iterator it = Instructions.begin(),
+ ie = Instructions.end(); it != ie; ++it) {
+ InstructionInfo *II = *it;
+
+ for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
+ StringRef Token = II->Tokens[i];
+
+ // Check for singleton registers.
+ if (!RegisterPrefix.empty() && Token.startswith(RegisterPrefix)) {
+ StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size());
+ InstructionInfo::Operand Op;
+ Op.Class = RegisterClasses[getRegisterRecord(Target, RegName)];
+ Op.OperandInfo = 0;
+ assert(Op.Class && Op.Class->Registers.size() == 1 &&
+ "Unexpected class for singleton register");
+ II->Operands.push_back(Op);
+ continue;
+ }
+
+ // Check for simple tokens.
+ if (Token[0] != '$') {
+ InstructionInfo::Operand Op;
+ Op.Class = getTokenClass(Token);
+ Op.OperandInfo = 0;
+ II->Operands.push_back(Op);
+ continue;
+ }
+
+ // Otherwise this is an operand reference.
+ StringRef OperandName;
+ if (Token[1] == '{')
+ OperandName = Token.substr(2, Token.size() - 3);
+ else
+ OperandName = Token.substr(1);
+
+ // Map this token to an operand. FIXME: Move elsewhere.
+ unsigned Idx;
+ try {
+ Idx = II->Instr->getOperandNamed(OperandName);
+ } catch(...) {
+ throw std::string("error: unable to find operand: '" +
+ OperandName.str() + "'");
+ }
+
+ // FIXME: This is annoying, the named operand may be tied (e.g.,
+ // XCHG8rm). What we want is the untied operand, which we now have to
+ // grovel for. Only worry about this for single entry operands, we have to
+ // clean this up anyway.
+ const CodeGenInstruction::OperandInfo *OI = &II->Instr->OperandList[Idx];
+ if (OI->Constraints[0].isTied()) {
+ unsigned TiedOp = OI->Constraints[0].getTiedOperand();
+
+ // The tied operand index is an MIOperand index, find the operand that
+ // contains it.
+ for (unsigned i = 0, e = II->Instr->OperandList.size(); i != e; ++i) {
+ if (II->Instr->OperandList[i].MIOperandNo == TiedOp) {
+ OI = &II->Instr->OperandList[i];
+ break;
+ }
+ }
+
+ assert(OI && "Unable to find tied operand target!");
+ }
+
+ InstructionInfo::Operand Op;
+ Op.Class = getOperandClass(Token, *OI);
+ Op.OperandInfo = OI;
+ II->Operands.push_back(Op);
+ }
+ }
+
+ // Reorder classes so that classes preceed super classes.
+ std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
+}
+
+static std::pair<unsigned, unsigned> *
+GetTiedOperandAtIndex(SmallVectorImpl<std::pair<unsigned, unsigned> > &List,
+ unsigned Index) {
+ for (unsigned i = 0, e = List.size(); i != e; ++i)
+ if (Index == List[i].first)
+ return &List[i];
+
+ return 0;
+}
+
+static void EmitConvertToMCInst(CodeGenTarget &Target,
+ std::vector<InstructionInfo*> &Infos,
+ raw_ostream &OS) {
+ // Write the convert function to a separate stream, so we can drop it after
+ // the enum.
+ std::string ConvertFnBody;
+ raw_string_ostream CvtOS(ConvertFnBody);
+
+ // Function we have already generated.
+ std::set<std::string> GeneratedFns;
+
+ // Start the unified conversion function.
+
+ CvtOS << "static void ConvertToMCInst(ConversionKind Kind, MCInst &Inst, "
+ << "unsigned Opcode,\n"
+ << " const SmallVectorImpl<MCParsedAsmOperand*"
+ << "> &Operands) {\n";
+ CvtOS << " Inst.setOpcode(Opcode);\n";
+ CvtOS << " switch (Kind) {\n";
+ CvtOS << " default:\n";
+
+ // Start the enum, which we will generate inline.
+
+ OS << "// Unified function for converting operants to MCInst instances.\n\n";
+ OS << "enum ConversionKind {\n";
+
+ // TargetOperandClass - This is the target's operand class, like X86Operand.
+ std::string TargetOperandClass = Target.getName() + "Operand";
+
+ for (std::vector<InstructionInfo*>::const_iterator it = Infos.begin(),
+ ie = Infos.end(); it != ie; ++it) {
+ InstructionInfo &II = **it;
+
+ // Order the (class) operands by the order to convert them into an MCInst.
+ SmallVector<std::pair<unsigned, unsigned>, 4> MIOperandList;
+ for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) {
+ InstructionInfo::Operand &Op = II.Operands[i];
+ if (Op.OperandInfo)
+ MIOperandList.push_back(std::make_pair(Op.OperandInfo->MIOperandNo, i));
+ }
+
+ // Find any tied operands.
+ SmallVector<std::pair<unsigned, unsigned>, 4> TiedOperands;
+ for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) {
+ const CodeGenInstruction::OperandInfo &OpInfo = II.Instr->OperandList[i];
+ for (unsigned j = 0, e = OpInfo.Constraints.size(); j != e; ++j) {
+ const CodeGenInstruction::ConstraintInfo &CI = OpInfo.Constraints[j];
+ if (CI.isTied())
+ TiedOperands.push_back(std::make_pair(OpInfo.MIOperandNo + j,
+ CI.getTiedOperand()));
+ }
+ }
+
+ std::sort(MIOperandList.begin(), MIOperandList.end());
+
+ // Compute the total number of operands.
+ unsigned NumMIOperands = 0;
+ for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) {
+ const CodeGenInstruction::OperandInfo &OI = II.Instr->OperandList[i];
+ NumMIOperands = std::max(NumMIOperands,
+ OI.MIOperandNo + OI.MINumOperands);
+ }
+
+ // Build the conversion function signature.
+ std::string Signature = "Convert";
+ unsigned CurIndex = 0;
+ for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) {
+ InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
+ assert(CurIndex <= Op.OperandInfo->MIOperandNo &&
+ "Duplicate match for instruction operand!");
+
+ // Skip operands which weren't matched by anything, this occurs when the
+ // .td file encodes "implicit" operands as explicit ones.
+ //
+ // FIXME: This should be removed from the MCInst structure.
+ for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) {
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+ if (!Tie)
+ Signature += "__Imp";
+ else
+ Signature += "__Tie" + utostr(Tie->second);
+ }
+
+ Signature += "__";
+
+ // Registers are always converted the same, don't duplicate the conversion
+ // function based on them.
+ //
+ // FIXME: We could generalize this based on the render method, if it
+ // mattered.
+ if (Op.Class->isRegisterClass())
+ Signature += "Reg";
+ else
+ Signature += Op.Class->ClassName;
+ Signature += utostr(Op.OperandInfo->MINumOperands);
+ Signature += "_" + utostr(MIOperandList[i].second);
+
+ CurIndex += Op.OperandInfo->MINumOperands;
+ }
+
+ // Add any trailing implicit operands.
+ for (; CurIndex != NumMIOperands; ++CurIndex) {
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+ if (!Tie)
+ Signature += "__Imp";
+ else
+ Signature += "__Tie" + utostr(Tie->second);
+ }
+
+ II.ConversionFnKind = Signature;
+
+ // Check if we have already generated this signature.
+ if (!GeneratedFns.insert(Signature).second)
+ continue;
+
+ // If not, emit it now.
+
+ // Add to the enum list.
+ OS << " " << Signature << ",\n";
+
+ // And to the convert function.
+ CvtOS << " case " << Signature << ":\n";
+ CurIndex = 0;
+ for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) {
+ InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
+
+ // Add the implicit operands.
+ for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) {
+ // See if this is a tied operand.
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+
+ if (!Tie) {
+ // If not, this is some implicit operand. Just assume it is a register
+ // for now.
+ CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+ } else {
+ // Copy the tied operand.
+ assert(Tie->first>Tie->second && "Tied operand preceeds its target!");
+ CvtOS << " Inst.addOperand(Inst.getOperand("
+ << Tie->second << "));\n";
+ }
+ }
+
+ CvtOS << " ((" << TargetOperandClass << "*)Operands["
+ << MIOperandList[i].second
+ << "])->" << Op.Class->RenderMethod
+ << "(Inst, " << Op.OperandInfo->MINumOperands << ");\n";
+ CurIndex += Op.OperandInfo->MINumOperands;
+ }
+
+ // And add trailing implicit operands.
+ for (; CurIndex != NumMIOperands; ++CurIndex) {
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+
+ if (!Tie) {
+ // If not, this is some implicit operand. Just assume it is a register
+ // for now.
+ CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+ } else {
+ // Copy the tied operand.
+ assert(Tie->first>Tie->second && "Tied operand preceeds its target!");
+ CvtOS << " Inst.addOperand(Inst.getOperand("
+ << Tie->second << "));\n";
+ }
+ }
+
+ CvtOS << " return;\n";
+ }
+
+ // Finish the convert function.
+
+ CvtOS << " }\n";
+ CvtOS << "}\n\n";
+
+ // Finish the enum, and drop the convert function after it.
+
+ OS << " NumConversionVariants\n";
+ OS << "};\n\n";
+
+ OS << CvtOS.str();
+}
+
+/// EmitMatchClassEnumeration - Emit the enumeration for match class kinds.
+static void EmitMatchClassEnumeration(CodeGenTarget &Target,
+ std::vector<ClassInfo*> &Infos,
+ raw_ostream &OS) {
+ OS << "namespace {\n\n";
+
+ OS << "/// MatchClassKind - The kinds of classes which participate in\n"
+ << "/// instruction matching.\n";
+ OS << "enum MatchClassKind {\n";
+ OS << " InvalidMatchClass = 0,\n";
+ for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
+ ie = Infos.end(); it != ie; ++it) {
+ ClassInfo &CI = **it;
+ OS << " " << CI.Name << ", // ";
+ if (CI.Kind == ClassInfo::Token) {
+ OS << "'" << CI.ValueName << "'\n";
+ } else if (CI.isRegisterClass()) {
+ if (!CI.ValueName.empty())
+ OS << "register class '" << CI.ValueName << "'\n";
+ else
+ OS << "derived register class\n";
+ } else {
+ OS << "user defined class '" << CI.ValueName << "'\n";
+ }
+ }
+ OS << " NumMatchClassKinds\n";
+ OS << "};\n\n";
+
+ OS << "}\n\n";
+}
+
+/// EmitClassifyOperand - Emit the function to classify an operand.
+static void EmitClassifyOperand(CodeGenTarget &Target,
+ AsmMatcherInfo &Info,
+ raw_ostream &OS) {
+ OS << "static MatchClassKind ClassifyOperand(MCParsedAsmOperand *GOp) {\n"
+ << " " << Target.getName() << "Operand &Operand = *("
+ << Target.getName() << "Operand*)GOp;\n";
+
+ // Classify tokens.
+ OS << " if (Operand.isToken())\n";
+ OS << " return MatchTokenString(Operand.getToken());\n\n";
+
+ // Classify registers.
+ //
+ // FIXME: Don't hardcode isReg, getReg.
+ OS << " if (Operand.isReg()) {\n";
+ OS << " switch (Operand.getReg()) {\n";
+ OS << " default: return InvalidMatchClass;\n";
+ for (std::map<Record*, ClassInfo*>::iterator
+ it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
+ it != ie; ++it)
+ OS << " case " << Target.getName() << "::"
+ << it->first->getName() << ": return " << it->second->Name << ";\n";
+ OS << " }\n";
+ OS << " }\n\n";
+
+ // Classify user defined operands.
+ for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(),
+ ie = Info.Classes.end(); it != ie; ++it) {
+ ClassInfo &CI = **it;
+
+ if (!CI.isUserClass())
+ continue;
+
+ OS << " // '" << CI.ClassName << "' class";
+ if (!CI.SuperClasses.empty()) {
+ OS << ", subclass of ";
+ for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i) {
+ if (i) OS << ", ";
+ OS << "'" << CI.SuperClasses[i]->ClassName << "'";
+ assert(CI < *CI.SuperClasses[i] && "Invalid class relation!");
+ }
+ }
+ OS << "\n";
+
+ OS << " if (Operand." << CI.PredicateMethod << "()) {\n";
+
+ // Validate subclass relationships.
+ if (!CI.SuperClasses.empty()) {
+ for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i)
+ OS << " assert(Operand." << CI.SuperClasses[i]->PredicateMethod
+ << "() && \"Invalid class relationship!\");\n";
+ }
+
+ OS << " return " << CI.Name << ";\n";
+ OS << " }\n\n";
+ }
+ OS << " return InvalidMatchClass;\n";
+ OS << "}\n\n";
+}
+
+/// EmitIsSubclass - Emit the subclass predicate function.
+static void EmitIsSubclass(CodeGenTarget &Target,
+ std::vector<ClassInfo*> &Infos,
+ raw_ostream &OS) {
+ OS << "/// IsSubclass - Compute whether \\arg A is a subclass of \\arg B.\n";
+ OS << "static bool IsSubclass(MatchClassKind A, MatchClassKind B) {\n";
+ OS << " if (A == B)\n";
+ OS << " return true;\n\n";
+
+ OS << " switch (A) {\n";
+ OS << " default:\n";
+ OS << " return false;\n";
+ for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
+ ie = Infos.end(); it != ie; ++it) {
+ ClassInfo &A = **it;
+
+ if (A.Kind != ClassInfo::Token) {
+ std::vector<StringRef> SuperClasses;
+ for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
+ ie = Infos.end(); it != ie; ++it) {
+ ClassInfo &B = **it;
+
+ if (&A != &B && A.isSubsetOf(B))
+ SuperClasses.push_back(B.Name);
+ }
+
+ if (SuperClasses.empty())
+ continue;
+
+ OS << "\n case " << A.Name << ":\n";
+
+ if (SuperClasses.size() == 1) {
+ OS << " return B == " << SuperClasses.back() << ";\n";
+ continue;
+ }
+
+ OS << " switch (B) {\n";
+ OS << " default: return false;\n";
+ for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+ OS << " case " << SuperClasses[i] << ": return true;\n";
+ OS << " }\n";
+ }
+ }
+ OS << " }\n";
+ OS << "}\n\n";
+}
+
+typedef std::pair<std::string, std::string> StringPair;
+
+/// FindFirstNonCommonLetter - Find the first character in the keys of the
+/// string pairs that is not shared across the whole set of strings. All
+/// strings are assumed to have the same length.
+static unsigned
+FindFirstNonCommonLetter(const std::vector<const StringPair*> &Matches) {
+ assert(!Matches.empty());
+ for (unsigned i = 0, e = Matches[0]->first.size(); i != e; ++i) {
+ // Check to see if letter i is the same across the set.
+ char Letter = Matches[0]->first[i];
+
+ for (unsigned str = 0, e = Matches.size(); str != e; ++str)
+ if (Matches[str]->first[i] != Letter)
+ return i;
+ }
+
+ return Matches[0]->first.size();
+}
+
+/// EmitStringMatcherForChar - Given a set of strings that are known to be the
+/// same length and whose characters leading up to CharNo are the same, emit
+/// code to verify that CharNo and later are the same.
+///
+/// \return - True if control can leave the emitted code fragment.
+static bool EmitStringMatcherForChar(const std::string &StrVariableName,
+ const std::vector<const StringPair*> &Matches,
+ unsigned CharNo, unsigned IndentCount,
+ raw_ostream &OS) {
+ assert(!Matches.empty() && "Must have at least one string to match!");
+ std::string Indent(IndentCount*2+4, ' ');
+
+ // If we have verified that the entire string matches, we're done: output the
+ // matching code.
+ if (CharNo == Matches[0]->first.size()) {
+ assert(Matches.size() == 1 && "Had duplicate keys to match on");
+
+ // FIXME: If Matches[0].first has embeded \n, this will be bad.
+ OS << Indent << Matches[0]->second << "\t // \"" << Matches[0]->first
+ << "\"\n";
+ return false;
+ }
+
+ // Bucket the matches by the character we are comparing.
+ std::map<char, std::vector<const StringPair*> > MatchesByLetter;
+
+ for (unsigned i = 0, e = Matches.size(); i != e; ++i)
+ MatchesByLetter[Matches[i]->first[CharNo]].push_back(Matches[i]);
+
+
+ // If we have exactly one bucket to match, see how many characters are common
+ // across the whole set and match all of them at once.
+ if (MatchesByLetter.size() == 1) {
+ unsigned FirstNonCommonLetter = FindFirstNonCommonLetter(Matches);
+ unsigned NumChars = FirstNonCommonLetter-CharNo;
+
+ // Emit code to break out if the prefix doesn't match.
+ if (NumChars == 1) {
+ // Do the comparison with if (Str[1] != 'f')
+ // FIXME: Need to escape general characters.
+ OS << Indent << "if (" << StrVariableName << "[" << CharNo << "] != '"
+ << Matches[0]->first[CharNo] << "')\n";
+ OS << Indent << " break;\n";
+ } else {
+ // Do the comparison with if (Str.substr(1,3) != "foo").
+ // FIXME: Need to escape general strings.
+ OS << Indent << "if (" << StrVariableName << ".substr(" << CharNo << ","
+ << NumChars << ") != \"";
+ OS << Matches[0]->first.substr(CharNo, NumChars) << "\")\n";
+ OS << Indent << " break;\n";
+ }
+
+ return EmitStringMatcherForChar(StrVariableName, Matches,
+ FirstNonCommonLetter, IndentCount, OS);
+ }
+
+ // Otherwise, we have multiple possible things, emit a switch on the
+ // character.
+ OS << Indent << "switch (" << StrVariableName << "[" << CharNo << "]) {\n";
+ OS << Indent << "default: break;\n";
+
+ for (std::map<char, std::vector<const StringPair*> >::iterator LI =
+ MatchesByLetter.begin(), E = MatchesByLetter.end(); LI != E; ++LI) {
+ // TODO: escape hard stuff (like \n) if we ever care about it.
+ OS << Indent << "case '" << LI->first << "':\t // "
+ << LI->second.size() << " strings to match.\n";
+ if (EmitStringMatcherForChar(StrVariableName, LI->second, CharNo+1,
+ IndentCount+1, OS))
+ OS << Indent << " break;\n";
+ }
+
+ OS << Indent << "}\n";
+ return true;
+}
+
+
+/// EmitStringMatcher - Given a list of strings and code to execute when they
+/// match, output a simple switch tree to classify the input string.
+///
+/// If a match is found, the code in Vals[i].second is executed; control must
+/// not exit this code fragment. If nothing matches, execution falls through.
+///
+/// \param StrVariableName - The name of the variable to test.
+static void EmitStringMatcher(const std::string &StrVariableName,
+ const std::vector<StringPair> &Matches,
+ raw_ostream &OS) {
+ // First level categorization: group strings by length.
+ std::map<unsigned, std::vector<const StringPair*> > MatchesByLength;
+
+ for (unsigned i = 0, e = Matches.size(); i != e; ++i)
+ MatchesByLength[Matches[i].first.size()].push_back(&Matches[i]);
+
+ // Output a switch statement on length and categorize the elements within each
+ // bin.
+ OS << " switch (" << StrVariableName << ".size()) {\n";
+ OS << " default: break;\n";
+
+ for (std::map<unsigned, std::vector<const StringPair*> >::iterator LI =
+ MatchesByLength.begin(), E = MatchesByLength.end(); LI != E; ++LI) {
+ OS << " case " << LI->first << ":\t // " << LI->second.size()
+ << " strings to match.\n";
+ if (EmitStringMatcherForChar(StrVariableName, LI->second, 0, 0, OS))
+ OS << " break;\n";
+ }
+
+ OS << " }\n";
+}
+
+
+/// EmitMatchTokenString - Emit the function to match a token string to the
+/// appropriate match class value.
+static void EmitMatchTokenString(CodeGenTarget &Target,
+ std::vector<ClassInfo*> &Infos,
+ raw_ostream &OS) {
+ // Construct the match list.
+ std::vector<StringPair> Matches;
+ for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
+ ie = Infos.end(); it != ie; ++it) {
+ ClassInfo &CI = **it;
+
+ if (CI.Kind == ClassInfo::Token)
+ Matches.push_back(StringPair(CI.ValueName, "return " + CI.Name + ";"));
+ }
+
+ OS << "static MatchClassKind MatchTokenString(StringRef Name) {\n";
+
+ EmitStringMatcher("Name", Matches, OS);
+
+ OS << " return InvalidMatchClass;\n";
+ OS << "}\n\n";
+}
+
+/// EmitMatchRegisterName - Emit the function to match a string to the target
+/// specific register enum.
+static void EmitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
+ raw_ostream &OS) {
+ // Construct the match list.
+ std::vector<StringPair> Matches;
+ for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) {
+ const CodeGenRegister &Reg = Target.getRegisters()[i];
+ if (Reg.TheDef->getValueAsString("AsmName").empty())
+ continue;
+
+ Matches.push_back(StringPair(Reg.TheDef->getValueAsString("AsmName"),
+ "return " + utostr(i + 1) + ";"));
+ }
+
+ OS << "static unsigned MatchRegisterName(StringRef Name) {\n";
+
+ EmitStringMatcher("Name", Matches, OS);
+
+ OS << " return 0;\n";
+ OS << "}\n\n";
+}
+
+/// EmitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag
+/// definitions.
+static void EmitSubtargetFeatureFlagEnumeration(CodeGenTarget &Target,
+ AsmMatcherInfo &Info,
+ raw_ostream &OS) {
+ OS << "// Flags for subtarget features that participate in "
+ << "instruction matching.\n";
+ OS << "enum SubtargetFeatureFlag {\n";
+ for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
+ it = Info.SubtargetFeatures.begin(),
+ ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
+ SubtargetFeatureInfo &SFI = *it->second;
+ OS << " " << SFI.EnumName << " = (1 << " << SFI.Index << "),\n";
+ }
+ OS << " Feature_None = 0\n";
+ OS << "};\n\n";
+}
+
+/// EmitComputeAvailableFeatures - Emit the function to compute the list of
+/// available features given a subtarget.
+static void EmitComputeAvailableFeatures(CodeGenTarget &Target,
+ AsmMatcherInfo &Info,
+ raw_ostream &OS) {
+ std::string ClassName =
+ Info.AsmParser->getValueAsString("AsmParserClassName");
+
+ OS << "unsigned " << Target.getName() << ClassName << "::\n"
+ << "ComputeAvailableFeatures(const " << Target.getName()
+ << "Subtarget *Subtarget) const {\n";
+ OS << " unsigned Features = 0;\n";
+ for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
+ it = Info.SubtargetFeatures.begin(),
+ ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
+ SubtargetFeatureInfo &SFI = *it->second;
+ OS << " if (" << SFI.TheDef->getValueAsString("CondString")
+ << ")\n";
+ OS << " Features |= " << SFI.EnumName << ";\n";
+ }
+ OS << " return Features;\n";
+ OS << "}\n\n";
+}
+
+void AsmMatcherEmitter::run(raw_ostream &OS) {
+ CodeGenTarget Target;
+ Record *AsmParser = Target.getAsmParser();
+ std::string ClassName = AsmParser->getValueAsString("AsmParserClassName");
+
+ // Compute the information on the instructions to match.
+ AsmMatcherInfo Info(AsmParser);
+ Info.BuildInfo(Target);
+
+ // Sort the instruction table using the partial order on classes. We use
+ // stable_sort to ensure that ambiguous instructions are still
+ // deterministically ordered.
+ std::stable_sort(Info.Instructions.begin(), Info.Instructions.end(),
+ less_ptr<InstructionInfo>());
+
+ DEBUG_WITH_TYPE("instruction_info", {
+ for (std::vector<InstructionInfo*>::iterator
+ it = Info.Instructions.begin(), ie = Info.Instructions.end();
+ it != ie; ++it)
+ (*it)->dump();
+ });
+
+ // Check for ambiguous instructions.
+ unsigned NumAmbiguous = 0;
+ for (unsigned i = 0, e = Info.Instructions.size(); i != e; ++i) {
+ for (unsigned j = i + 1; j != e; ++j) {
+ InstructionInfo &A = *Info.Instructions[i];
+ InstructionInfo &B = *Info.Instructions[j];
+
+ if (A.CouldMatchAmiguouslyWith(B)) {
+ DEBUG_WITH_TYPE("ambiguous_instrs", {
+ errs() << "warning: ambiguous instruction match:\n";
+ A.dump();
+ errs() << "\nis incomparable with:\n";
+ B.dump();
+ errs() << "\n\n";
+ });
+ ++NumAmbiguous;
+ }
+ }
+ }
+ if (NumAmbiguous)
+ DEBUG_WITH_TYPE("ambiguous_instrs", {
+ errs() << "warning: " << NumAmbiguous
+ << " ambiguous instructions!\n";
+ });
+
+ // Write the output.
+
+ EmitSourceFileHeader("Assembly Matcher Source Fragment", OS);
+
+ // Emit the subtarget feature enumeration.
+ EmitSubtargetFeatureFlagEnumeration(Target, Info, OS);
+
+ // Emit the function to match a register name to number.
+ EmitMatchRegisterName(Target, AsmParser, OS);
+
+ OS << "#ifndef REGISTERS_ONLY\n\n";
+
+ // Generate the unified function to convert operands into an MCInst.
+ EmitConvertToMCInst(Target, Info.Instructions, OS);
+
+ // Emit the enumeration for classes which participate in matching.
+ EmitMatchClassEnumeration(Target, Info.Classes, OS);
+
+ // Emit the routine to match token strings to their match class.
+ EmitMatchTokenString(Target, Info.Classes, OS);
+
+ // Emit the routine to classify an operand.
+ EmitClassifyOperand(Target, Info, OS);
+
+ // Emit the subclass predicate routine.
+ EmitIsSubclass(Target, Info.Classes, OS);
+
+ // Emit the available features compute function.
+ EmitComputeAvailableFeatures(Target, Info, OS);
+
+ // Finally, build the match function.
+
+ size_t MaxNumOperands = 0;
+ for (std::vector<InstructionInfo*>::const_iterator it =
+ Info.Instructions.begin(), ie = Info.Instructions.end();
+ it != ie; ++it)
+ MaxNumOperands = std::max(MaxNumOperands, (*it)->Operands.size());
+
+ OS << "bool " << Target.getName() << ClassName << "::\n"
+ << "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>"
+ << " &Operands,\n";
+ OS << " MCInst &Inst) {\n";
+
+ // Emit the static match table; unused classes get initalized to 0 which is
+ // guaranteed to be InvalidMatchClass.
+ //
+ // FIXME: We can reduce the size of this table very easily. First, we change
+ // it so that store the kinds in separate bit-fields for each index, which
+ // only needs to be the max width used for classes at that index (we also need
+ // to reject based on this during classification). If we then make sure to
+ // order the match kinds appropriately (putting mnemonics last), then we
+ // should only end up using a few bits for each class, especially the ones
+ // following the mnemonic.
+ OS << " static const struct MatchEntry {\n";
+ OS << " unsigned Opcode;\n";
+ OS << " ConversionKind ConvertFn;\n";
+ OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n";
+ OS << " unsigned RequiredFeatures;\n";
+ OS << " } MatchTable[" << Info.Instructions.size() << "] = {\n";
+
+ for (std::vector<InstructionInfo*>::const_iterator it =
+ Info.Instructions.begin(), ie = Info.Instructions.end();
+ it != ie; ++it) {
+ InstructionInfo &II = **it;
+
+ OS << " { " << Target.getName() << "::" << II.InstrName
+ << ", " << II.ConversionFnKind << ", { ";
+ for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) {
+ InstructionInfo::Operand &Op = II.Operands[i];
+
+ if (i) OS << ", ";
+ OS << Op.Class->Name;
+ }
+ OS << " }, ";
+
+ // Write the required features mask.
+ if (!II.RequiredFeatures.empty()) {
+ for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) {
+ if (i) OS << "|";
+ OS << II.RequiredFeatures[i]->EnumName;
+ }
+ } else
+ OS << "0";
+
+ OS << "},\n";
+ }
+
+ OS << " };\n\n";
+
+
+ // Emit code to get the available features.
+ OS << " // Get the current feature set.\n";
+ OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n";
+
+ // Emit code to compute the class list for this operand vector.
+ OS << " // Eliminate obvious mismatches.\n";
+ OS << " if (Operands.size() > " << MaxNumOperands << ")\n";
+ OS << " return true;\n\n";
+
+ OS << " // Compute the class list for this operand vector.\n";
+ OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n";
+ OS << " for (unsigned i = 0, e = Operands.size(); i != e; ++i) {\n";
+ OS << " Classes[i] = ClassifyOperand(Operands[i]);\n\n";
+
+ OS << " // Check for invalid operands before matching.\n";
+ OS << " if (Classes[i] == InvalidMatchClass)\n";
+ OS << " return true;\n";
+ OS << " }\n\n";
+
+ OS << " // Mark unused classes.\n";
+ OS << " for (unsigned i = Operands.size(), e = " << MaxNumOperands << "; "
+ << "i != e; ++i)\n";
+ OS << " Classes[i] = InvalidMatchClass;\n\n";
+
+ // Emit code to search the table.
+ OS << " // Search the table.\n";
+ OS << " for (const MatchEntry *it = MatchTable, "
+ << "*ie = MatchTable + " << Info.Instructions.size()
+ << "; it != ie; ++it) {\n";
+
+ // Emit check that the required features are available.
+ OS << " if ((AvailableFeatures & it->RequiredFeatures) "
+ << "!= it->RequiredFeatures)\n";
+ OS << " continue;\n";
+
+ // Emit check that the subclasses match.
+ for (unsigned i = 0; i != MaxNumOperands; ++i) {
+ OS << " if (!IsSubclass(Classes["
+ << i << "], it->Classes[" << i << "]))\n";
+ OS << " continue;\n";
+ }
+ OS << "\n";
+ OS << " ConvertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n";
+
+ // Call the post-processing function, if used.
+ std::string InsnCleanupFn =
+ AsmParser->getValueAsString("AsmParserInstCleanup");
+ if (!InsnCleanupFn.empty())
+ OS << " " << InsnCleanupFn << "(Inst);\n";
+
+ OS << " return false;\n";
+ OS << " }\n\n";
+
+ OS << " return true;\n";
+ OS << "}\n\n";
+
+ OS << "#endif // REGISTERS_ONLY\n";
+}
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h
new file mode 100644
index 0000000..729c938
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h
@@ -0,0 +1,33 @@
+//===- AsmMatcherEmitter.h - Generate an assembly matcher -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits a target specifier matcher for converting parsed
+// assembly operands in the MCInst structures.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ASMMATCHER_EMITTER_H
+#define ASMMATCHER_EMITTER_H
+
+#include "TableGenBackend.h"
+#include <map>
+#include <vector>
+#include <cassert>
+
+namespace llvm {
+ class AsmMatcherEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ public:
+ AsmMatcherEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the matcher, returning true on failure.
+ void run(raw_ostream &o);
+ };
+}
+#endif
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
new file mode 100644
index 0000000..23f13c2
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -0,0 +1,548 @@
+//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is emits an assembly printer for the current target.
+// Note that this is currently fairly skeletal, but will grow over time.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AsmWriterEmitter.h"
+#include "AsmWriterInst.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "StringToOffsetTable.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+using namespace llvm;
+
+static void PrintCases(std::vector<std::pair<std::string,
+ AsmWriterOperand> > &OpsToPrint, raw_ostream &O) {
+ O << " case " << OpsToPrint.back().first << ": ";
+ AsmWriterOperand TheOp = OpsToPrint.back().second;
+ OpsToPrint.pop_back();
+
+ // Check to see if any other operands are identical in this list, and if so,
+ // emit a case label for them.
+ for (unsigned i = OpsToPrint.size(); i != 0; --i)
+ if (OpsToPrint[i-1].second == TheOp) {
+ O << "\n case " << OpsToPrint[i-1].first << ": ";
+ OpsToPrint.erase(OpsToPrint.begin()+i-1);
+ }
+
+ // Finally, emit the code.
+ O << TheOp.getCode();
+ O << "break;\n";
+}
+
+
+/// EmitInstructions - Emit the last instruction in the vector and any other
+/// instructions that are suitably similar to it.
+static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
+ raw_ostream &O) {
+ AsmWriterInst FirstInst = Insts.back();
+ Insts.pop_back();
+
+ std::vector<AsmWriterInst> SimilarInsts;
+ unsigned DifferingOperand = ~0;
+ for (unsigned i = Insts.size(); i != 0; --i) {
+ unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst);
+ if (DiffOp != ~1U) {
+ if (DifferingOperand == ~0U) // First match!
+ DifferingOperand = DiffOp;
+
+ // If this differs in the same operand as the rest of the instructions in
+ // this class, move it to the SimilarInsts list.
+ if (DifferingOperand == DiffOp || DiffOp == ~0U) {
+ SimilarInsts.push_back(Insts[i-1]);
+ Insts.erase(Insts.begin()+i-1);
+ }
+ }
+ }
+
+ O << " case " << FirstInst.CGI->Namespace << "::"
+ << FirstInst.CGI->TheDef->getName() << ":\n";
+ for (unsigned i = 0, e = SimilarInsts.size(); i != e; ++i)
+ O << " case " << SimilarInsts[i].CGI->Namespace << "::"
+ << SimilarInsts[i].CGI->TheDef->getName() << ":\n";
+ for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) {
+ if (i != DifferingOperand) {
+ // If the operand is the same for all instructions, just print it.
+ O << " " << FirstInst.Operands[i].getCode();
+ } else {
+ // If this is the operand that varies between all of the instructions,
+ // emit a switch for just this operand now.
+ O << " switch (MI->getOpcode()) {\n";
+ std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint;
+ OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace + "::" +
+ FirstInst.CGI->TheDef->getName(),
+ FirstInst.Operands[i]));
+
+ for (unsigned si = 0, e = SimilarInsts.size(); si != e; ++si) {
+ AsmWriterInst &AWI = SimilarInsts[si];
+ OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::"+
+ AWI.CGI->TheDef->getName(),
+ AWI.Operands[i]));
+ }
+ std::reverse(OpsToPrint.begin(), OpsToPrint.end());
+ while (!OpsToPrint.empty())
+ PrintCases(OpsToPrint, O);
+ O << " }";
+ }
+ O << "\n";
+ }
+ O << " break;\n";
+}
+
+void AsmWriterEmitter::
+FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
+ std::vector<unsigned> &InstIdxs,
+ std::vector<unsigned> &InstOpsUsed) const {
+ InstIdxs.assign(NumberedInstructions.size(), ~0U);
+
+ // This vector parallels UniqueOperandCommands, keeping track of which
+ // instructions each case are used for. It is a comma separated string of
+ // enums.
+ std::vector<std::string> InstrsForCase;
+ InstrsForCase.resize(UniqueOperandCommands.size());
+ InstOpsUsed.assign(UniqueOperandCommands.size(), 0);
+
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ const AsmWriterInst *Inst = getAsmWriterInstByID(i);
+ if (Inst == 0) continue; // PHI, INLINEASM, PROLOG_LABEL, etc.
+
+ std::string Command;
+ if (Inst->Operands.empty())
+ continue; // Instruction already done.
+
+ Command = " " + Inst->Operands[0].getCode() + "\n";
+
+ // Check to see if we already have 'Command' in UniqueOperandCommands.
+ // If not, add it.
+ bool FoundIt = false;
+ for (unsigned idx = 0, e = UniqueOperandCommands.size(); idx != e; ++idx)
+ if (UniqueOperandCommands[idx] == Command) {
+ InstIdxs[i] = idx;
+ InstrsForCase[idx] += ", ";
+ InstrsForCase[idx] += Inst->CGI->TheDef->getName();
+ FoundIt = true;
+ break;
+ }
+ if (!FoundIt) {
+ InstIdxs[i] = UniqueOperandCommands.size();
+ UniqueOperandCommands.push_back(Command);
+ InstrsForCase.push_back(Inst->CGI->TheDef->getName());
+
+ // This command matches one operand so far.
+ InstOpsUsed.push_back(1);
+ }
+ }
+
+ // For each entry of UniqueOperandCommands, there is a set of instructions
+ // that uses it. If the next command of all instructions in the set are
+ // identical, fold it into the command.
+ for (unsigned CommandIdx = 0, e = UniqueOperandCommands.size();
+ CommandIdx != e; ++CommandIdx) {
+
+ for (unsigned Op = 1; ; ++Op) {
+ // Scan for the first instruction in the set.
+ std::vector<unsigned>::iterator NIT =
+ std::find(InstIdxs.begin(), InstIdxs.end(), CommandIdx);
+ if (NIT == InstIdxs.end()) break; // No commonality.
+
+ // If this instruction has no more operands, we isn't anything to merge
+ // into this command.
+ const AsmWriterInst *FirstInst =
+ getAsmWriterInstByID(NIT-InstIdxs.begin());
+ if (!FirstInst || FirstInst->Operands.size() == Op)
+ break;
+
+ // Otherwise, scan to see if all of the other instructions in this command
+ // set share the operand.
+ bool AllSame = true;
+ // Keep track of the maximum, number of operands or any
+ // instruction we see in the group.
+ size_t MaxSize = FirstInst->Operands.size();
+
+ for (NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx);
+ NIT != InstIdxs.end();
+ NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx)) {
+ // Okay, found another instruction in this command set. If the operand
+ // matches, we're ok, otherwise bail out.
+ const AsmWriterInst *OtherInst =
+ getAsmWriterInstByID(NIT-InstIdxs.begin());
+
+ if (OtherInst &&
+ OtherInst->Operands.size() > FirstInst->Operands.size())
+ MaxSize = std::max(MaxSize, OtherInst->Operands.size());
+
+ if (!OtherInst || OtherInst->Operands.size() == Op ||
+ OtherInst->Operands[Op] != FirstInst->Operands[Op]) {
+ AllSame = false;
+ break;
+ }
+ }
+ if (!AllSame) break;
+
+ // Okay, everything in this command set has the same next operand. Add it
+ // to UniqueOperandCommands and remember that it was consumed.
+ std::string Command = " " + FirstInst->Operands[Op].getCode() + "\n";
+
+ UniqueOperandCommands[CommandIdx] += Command;
+ InstOpsUsed[CommandIdx]++;
+ }
+ }
+
+ // Prepend some of the instructions each case is used for onto the case val.
+ for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) {
+ std::string Instrs = InstrsForCase[i];
+ if (Instrs.size() > 70) {
+ Instrs.erase(Instrs.begin()+70, Instrs.end());
+ Instrs += "...";
+ }
+
+ if (!Instrs.empty())
+ UniqueOperandCommands[i] = " // " + Instrs + "\n" +
+ UniqueOperandCommands[i];
+ }
+}
+
+
+static void UnescapeString(std::string &Str) {
+ for (unsigned i = 0; i != Str.size(); ++i) {
+ if (Str[i] == '\\' && i != Str.size()-1) {
+ switch (Str[i+1]) {
+ default: continue; // Don't execute the code after the switch.
+ case 'a': Str[i] = '\a'; break;
+ case 'b': Str[i] = '\b'; break;
+ case 'e': Str[i] = 27; break;
+ case 'f': Str[i] = '\f'; break;
+ case 'n': Str[i] = '\n'; break;
+ case 'r': Str[i] = '\r'; break;
+ case 't': Str[i] = '\t'; break;
+ case 'v': Str[i] = '\v'; break;
+ case '"': Str[i] = '\"'; break;
+ case '\'': Str[i] = '\''; break;
+ case '\\': Str[i] = '\\'; break;
+ }
+ // Nuke the second character.
+ Str.erase(Str.begin()+i+1);
+ }
+ }
+}
+
+/// EmitPrintInstruction - Generate the code for the "printInstruction" method
+/// implementation.
+void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
+ CodeGenTarget Target;
+ Record *AsmWriter = Target.getAsmWriter();
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+
+ O <<
+ "/// printInstruction - This method is automatically generated by tablegen\n"
+ "/// from the instruction set description.\n"
+ "void " << Target.getName() << ClassName
+ << "::printInstruction(const MachineInstr *MI, raw_ostream &O) {\n";
+
+ std::vector<AsmWriterInst> Instructions;
+
+ for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
+ E = Target.inst_end(); I != E; ++I)
+ if (!(*I)->AsmString.empty() &&
+ (*I)->TheDef->getName() != "PHI")
+ Instructions.push_back(
+ AsmWriterInst(**I,
+ AsmWriter->getValueAsInt("Variant"),
+ AsmWriter->getValueAsInt("FirstOperandColumn"),
+ AsmWriter->getValueAsInt("OperandSpacing")));
+
+ // Get the instruction numbering.
+ NumberedInstructions = Target.getInstructionsByEnumValue();
+
+ // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not
+ // all machine instructions are necessarily being printed, so there may be
+ // target instructions not in this map.
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
+ CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i]));
+
+ // Build an aggregate string, and build a table of offsets into it.
+ StringToOffsetTable StringTable;
+
+ /// OpcodeInfo - This encodes the index of the string to use for the first
+ /// chunk of the output as well as indices used for operand printing.
+ std::vector<unsigned> OpcodeInfo;
+
+ unsigned MaxStringIdx = 0;
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]];
+ unsigned Idx;
+ if (AWI == 0) {
+ // Something not handled by the asmwriter printer.
+ Idx = ~0U;
+ } else if (AWI->Operands[0].OperandType !=
+ AsmWriterOperand::isLiteralTextOperand ||
+ AWI->Operands[0].Str.empty()) {
+ // Something handled by the asmwriter printer, but with no leading string.
+ Idx = StringTable.GetOrAddStringOffset("");
+ } else {
+ std::string Str = AWI->Operands[0].Str;
+ UnescapeString(Str);
+ Idx = StringTable.GetOrAddStringOffset(Str);
+ MaxStringIdx = std::max(MaxStringIdx, Idx);
+
+ // Nuke the string from the operand list. It is now handled!
+ AWI->Operands.erase(AWI->Operands.begin());
+ }
+
+ // Bias offset by one since we want 0 as a sentinel.
+ OpcodeInfo.push_back(Idx+1);
+ }
+
+ // Figure out how many bits we used for the string index.
+ unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+2);
+
+ // To reduce code size, we compactify common instructions into a few bits
+ // in the opcode-indexed table.
+ unsigned BitsLeft = 32-AsmStrBits;
+
+ std::vector<std::vector<std::string> > TableDrivenOperandPrinters;
+
+ while (1) {
+ std::vector<std::string> UniqueOperandCommands;
+ std::vector<unsigned> InstIdxs;
+ std::vector<unsigned> NumInstOpsHandled;
+ FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs,
+ NumInstOpsHandled);
+
+ // If we ran out of operands to print, we're done.
+ if (UniqueOperandCommands.empty()) break;
+
+ // Compute the number of bits we need to represent these cases, this is
+ // ceil(log2(numentries)).
+ unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size());
+
+ // If we don't have enough bits for this operand, don't include it.
+ if (NumBits > BitsLeft) {
+ DEBUG(errs() << "Not enough bits to densely encode " << NumBits
+ << " more bits\n");
+ break;
+ }
+
+ // Otherwise, we can include this in the initial lookup table. Add it in.
+ BitsLeft -= NumBits;
+ for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i)
+ if (InstIdxs[i] != ~0U)
+ OpcodeInfo[i] |= InstIdxs[i] << (BitsLeft+AsmStrBits);
+
+ // Remove the info about this operand.
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ if (AsmWriterInst *Inst = getAsmWriterInstByID(i))
+ if (!Inst->Operands.empty()) {
+ unsigned NumOps = NumInstOpsHandled[InstIdxs[i]];
+ assert(NumOps <= Inst->Operands.size() &&
+ "Can't remove this many ops!");
+ Inst->Operands.erase(Inst->Operands.begin(),
+ Inst->Operands.begin()+NumOps);
+ }
+ }
+
+ // Remember the handlers for this set of operands.
+ TableDrivenOperandPrinters.push_back(UniqueOperandCommands);
+ }
+
+
+
+ O<<" static const unsigned OpInfo[] = {\n";
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ O << " " << OpcodeInfo[i] << "U,\t// "
+ << NumberedInstructions[i]->TheDef->getName() << "\n";
+ }
+ // Add a dummy entry so the array init doesn't end with a comma.
+ O << " 0U\n";
+ O << " };\n\n";
+
+ // Emit the string itself.
+ O << " const char *AsmStrs = \n";
+ StringTable.EmitString(O);
+ O << ";\n\n";
+
+ O << " O << \"\\t\";\n\n";
+
+ O << " // Emit the opcode for the instruction.\n"
+ << " unsigned Bits = OpInfo[MI->getOpcode()];\n"
+ << " assert(Bits != 0 && \"Cannot print this instruction.\");\n"
+ << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1;\n\n";
+
+ // Output the table driven operand information.
+ BitsLeft = 32-AsmStrBits;
+ for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) {
+ std::vector<std::string> &Commands = TableDrivenOperandPrinters[i];
+
+ // Compute the number of bits we need to represent these cases, this is
+ // ceil(log2(numentries)).
+ unsigned NumBits = Log2_32_Ceil(Commands.size());
+ assert(NumBits <= BitsLeft && "consistency error");
+
+ // Emit code to extract this field from Bits.
+ BitsLeft -= NumBits;
+
+ O << "\n // Fragment " << i << " encoded into " << NumBits
+ << " bits for " << Commands.size() << " unique commands.\n";
+
+ if (Commands.size() == 2) {
+ // Emit two possibilitys with if/else.
+ O << " if ((Bits >> " << (BitsLeft+AsmStrBits) << ") & "
+ << ((1 << NumBits)-1) << ") {\n"
+ << Commands[1]
+ << " } else {\n"
+ << Commands[0]
+ << " }\n\n";
+ } else {
+ O << " switch ((Bits >> " << (BitsLeft+AsmStrBits) << ") & "
+ << ((1 << NumBits)-1) << ") {\n"
+ << " default: // unreachable.\n";
+
+ // Print out all the cases.
+ for (unsigned i = 0, e = Commands.size(); i != e; ++i) {
+ O << " case " << i << ":\n";
+ O << Commands[i];
+ O << " break;\n";
+ }
+ O << " }\n\n";
+ }
+ }
+
+ // Okay, delete instructions with no operand info left.
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
+ // Entire instruction has been emitted?
+ AsmWriterInst &Inst = Instructions[i];
+ if (Inst.Operands.empty()) {
+ Instructions.erase(Instructions.begin()+i);
+ --i; --e;
+ }
+ }
+
+
+ // Because this is a vector, we want to emit from the end. Reverse all of the
+ // elements in the vector.
+ std::reverse(Instructions.begin(), Instructions.end());
+
+
+ // Now that we've emitted all of the operand info that fit into 32 bits, emit
+ // information for those instructions that are left. This is a less dense
+ // encoding, but we expect the main 32-bit table to handle the majority of
+ // instructions.
+ if (!Instructions.empty()) {
+ // Find the opcode # of inline asm.
+ O << " switch (MI->getOpcode()) {\n";
+ while (!Instructions.empty())
+ EmitInstructions(Instructions, O);
+
+ O << " }\n";
+ O << " return;\n";
+ }
+
+ O << "}\n";
+}
+
+
+void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
+ CodeGenTarget Target;
+ Record *AsmWriter = Target.getAsmWriter();
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+ const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
+
+ StringToOffsetTable StringTable;
+ O <<
+ "\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
+ "/// from the register set description. This returns the assembler name\n"
+ "/// for the specified register.\n"
+ "const char *" << Target.getName() << ClassName
+ << "::getRegisterName(unsigned RegNo) {\n"
+ << " assert(RegNo && RegNo < " << (Registers.size()+1)
+ << " && \"Invalid register number!\");\n"
+ << "\n"
+ << " static const unsigned RegAsmOffset[] = {";
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
+ const CodeGenRegister &Reg = Registers[i];
+
+ std::string AsmName = Reg.TheDef->getValueAsString("AsmName");
+ if (AsmName.empty())
+ AsmName = Reg.getName();
+
+
+ if ((i % 14) == 0)
+ O << "\n ";
+
+ O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
+ }
+ O << "0\n"
+ << " };\n"
+ << "\n";
+
+ O << " const char *AsmStrs =\n";
+ StringTable.EmitString(O);
+ O << ";\n";
+
+ O << " return AsmStrs+RegAsmOffset[RegNo-1];\n"
+ << "}\n";
+}
+
+void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) {
+ CodeGenTarget Target;
+ Record *AsmWriter = Target.getAsmWriter();
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+
+ const std::vector<const CodeGenInstruction*> &NumberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ StringToOffsetTable StringTable;
+ O <<
+"\n\n#ifdef GET_INSTRUCTION_NAME\n"
+"#undef GET_INSTRUCTION_NAME\n\n"
+"/// getInstructionName: This method is automatically generated by tblgen\n"
+"/// from the instruction set description. This returns the enum name of the\n"
+"/// specified instruction.\n"
+ "const char *" << Target.getName() << ClassName
+ << "::getInstructionName(unsigned Opcode) {\n"
+ << " assert(Opcode < " << NumberedInstructions.size()
+ << " && \"Invalid instruction number!\");\n"
+ << "\n"
+ << " static const unsigned InstAsmOffset[] = {";
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ const CodeGenInstruction &Inst = *NumberedInstructions[i];
+
+ std::string AsmName = Inst.TheDef->getName();
+ if ((i % 14) == 0)
+ O << "\n ";
+
+ O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
+ }
+ O << "0\n"
+ << " };\n"
+ << "\n";
+
+ O << " const char *Strs =\n";
+ StringTable.EmitString(O);
+ O << ";\n";
+
+ O << " return Strs+InstAsmOffset[Opcode];\n"
+ << "}\n\n#endif\n";
+}
+
+
+
+void AsmWriterEmitter::run(raw_ostream &O) {
+ EmitSourceFileHeader("Assembly Writer Source Fragment", O);
+
+ EmitPrintInstruction(O);
+ EmitGetRegisterName(O);
+ EmitGetInstructionName(O);
+}
+
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h
new file mode 100644
index 0000000..9f7d776
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h
@@ -0,0 +1,54 @@
+//===- AsmWriterEmitter.h - Generate an assembly writer ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting an assembly printer for the
+// code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ASMWRITER_EMITTER_H
+#define ASMWRITER_EMITTER_H
+
+#include "TableGenBackend.h"
+#include <map>
+#include <vector>
+#include <cassert>
+
+namespace llvm {
+ class AsmWriterInst;
+ class CodeGenInstruction;
+
+ class AsmWriterEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap;
+ std::vector<const CodeGenInstruction*> NumberedInstructions;
+ public:
+ AsmWriterEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the asmwriter, returning true on failure.
+ void run(raw_ostream &o);
+
+private:
+ void EmitPrintInstruction(raw_ostream &o);
+ void EmitGetRegisterName(raw_ostream &o);
+ void EmitGetInstructionName(raw_ostream &o);
+
+ AsmWriterInst *getAsmWriterInstByID(unsigned ID) const {
+ assert(ID < NumberedInstructions.size());
+ std::map<const CodeGenInstruction*, AsmWriterInst*>::const_iterator I =
+ CGIAWIMap.find(NumberedInstructions[ID]);
+ assert(I != CGIAWIMap.end() && "Didn't find inst!");
+ return I->second;
+ }
+ void FindUniqueOperandCommands(std::vector<std::string> &UOC,
+ std::vector<unsigned> &InstIdxs,
+ std::vector<unsigned> &InstOpsUsed) const;
+ };
+}
+#endif
diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.cpp b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp
new file mode 100644
index 0000000..b2228b0
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp
@@ -0,0 +1,265 @@
+//===- AsmWriterInst.h - Classes encapsulating a printable inst -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes implement a parser for assembly strings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AsmWriterInst.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace llvm;
+
+static bool isIdentChar(char C) {
+ return (C >= 'a' && C <= 'z') ||
+ (C >= 'A' && C <= 'Z') ||
+ (C >= '0' && C <= '9') ||
+ C == '_';
+}
+
+std::string AsmWriterOperand::getCode() const {
+ if (OperandType == isLiteralTextOperand) {
+ if (Str.size() == 1)
+ return "O << '" + Str + "'; ";
+ return "O << \"" + Str + "\"; ";
+ }
+
+ if (OperandType == isLiteralStatementOperand)
+ return Str;
+
+ std::string Result = Str + "(MI";
+ if (MIOpNo != ~0U)
+ Result += ", " + utostr(MIOpNo);
+ Result += ", O";
+ if (!MiModifier.empty())
+ Result += ", \"" + MiModifier + '"';
+ return Result + "); ";
+}
+
+/// ParseAsmString - Parse the specified Instruction's AsmString into this
+/// AsmWriterInst.
+///
+AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
+ unsigned Variant,
+ int FirstOperandColumn,
+ int OperandSpacing) {
+ this->CGI = &CGI;
+
+ unsigned CurVariant = ~0U; // ~0 if we are outside a {.|.|.} region, other #.
+
+ // This is the number of tabs we've seen if we're doing columnar layout.
+ unsigned CurColumn = 0;
+
+
+ // NOTE: Any extensions to this code need to be mirrored in the
+ // AsmPrinter::printInlineAsm code that executes as compile time (assuming
+ // that inline asm strings should also get the new feature)!
+ const std::string &AsmString = CGI.AsmString;
+ std::string::size_type LastEmitted = 0;
+ while (LastEmitted != AsmString.size()) {
+ std::string::size_type DollarPos =
+ AsmString.find_first_of("${|}\\", LastEmitted);
+ if (DollarPos == std::string::npos) DollarPos = AsmString.size();
+
+ // Emit a constant string fragment.
+
+ if (DollarPos != LastEmitted) {
+ if (CurVariant == Variant || CurVariant == ~0U) {
+ for (; LastEmitted != DollarPos; ++LastEmitted)
+ switch (AsmString[LastEmitted]) {
+ case '\n':
+ AddLiteralString("\\n");
+ break;
+ case '\t':
+ // If the asm writer is not using a columnar layout, \t is not
+ // magic.
+ if (FirstOperandColumn == -1 || OperandSpacing == -1) {
+ AddLiteralString("\\t");
+ } else {
+ // We recognize a tab as an operand delimeter.
+ unsigned DestColumn = FirstOperandColumn +
+ CurColumn++ * OperandSpacing;
+ Operands.push_back(
+ AsmWriterOperand(
+ "O.PadToColumn(" +
+ utostr(DestColumn) + ");\n",
+ AsmWriterOperand::isLiteralStatementOperand));
+ }
+ break;
+ case '"':
+ AddLiteralString("\\\"");
+ break;
+ case '\\':
+ AddLiteralString("\\\\");
+ break;
+ default:
+ AddLiteralString(std::string(1, AsmString[LastEmitted]));
+ break;
+ }
+ } else {
+ LastEmitted = DollarPos;
+ }
+ } else if (AsmString[DollarPos] == '\\') {
+ if (DollarPos+1 != AsmString.size() &&
+ (CurVariant == Variant || CurVariant == ~0U)) {
+ if (AsmString[DollarPos+1] == 'n') {
+ AddLiteralString("\\n");
+ } else if (AsmString[DollarPos+1] == 't') {
+ // If the asm writer is not using a columnar layout, \t is not
+ // magic.
+ if (FirstOperandColumn == -1 || OperandSpacing == -1) {
+ AddLiteralString("\\t");
+ break;
+ }
+
+ // We recognize a tab as an operand delimeter.
+ unsigned DestColumn = FirstOperandColumn +
+ CurColumn++ * OperandSpacing;
+ Operands.push_back(
+ AsmWriterOperand("O.PadToColumn(" + utostr(DestColumn) + ");\n",
+ AsmWriterOperand::isLiteralStatementOperand));
+ break;
+ } else if (std::string("${|}\\").find(AsmString[DollarPos+1])
+ != std::string::npos) {
+ AddLiteralString(std::string(1, AsmString[DollarPos+1]));
+ } else {
+ throw "Non-supported escaped character found in instruction '" +
+ CGI.TheDef->getName() + "'!";
+ }
+ LastEmitted = DollarPos+2;
+ continue;
+ }
+ } else if (AsmString[DollarPos] == '{') {
+ if (CurVariant != ~0U)
+ throw "Nested variants found for instruction '" +
+ CGI.TheDef->getName() + "'!";
+ LastEmitted = DollarPos+1;
+ CurVariant = 0; // We are now inside of the variant!
+ } else if (AsmString[DollarPos] == '|') {
+ if (CurVariant == ~0U)
+ throw "'|' character found outside of a variant in instruction '"
+ + CGI.TheDef->getName() + "'!";
+ ++CurVariant;
+ ++LastEmitted;
+ } else if (AsmString[DollarPos] == '}') {
+ if (CurVariant == ~0U)
+ throw "'}' character found outside of a variant in instruction '"
+ + CGI.TheDef->getName() + "'!";
+ ++LastEmitted;
+ CurVariant = ~0U;
+ } else if (DollarPos+1 != AsmString.size() &&
+ AsmString[DollarPos+1] == '$') {
+ if (CurVariant == Variant || CurVariant == ~0U) {
+ AddLiteralString("$"); // "$$" -> $
+ }
+ LastEmitted = DollarPos+2;
+ } else {
+ // Get the name of the variable.
+ std::string::size_type VarEnd = DollarPos+1;
+
+ // handle ${foo}bar as $foo by detecting whether the character following
+ // the dollar sign is a curly brace. If so, advance VarEnd and DollarPos
+ // so the variable name does not contain the leading curly brace.
+ bool hasCurlyBraces = false;
+ if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) {
+ hasCurlyBraces = true;
+ ++DollarPos;
+ ++VarEnd;
+ }
+
+ while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
+ ++VarEnd;
+ std::string VarName(AsmString.begin()+DollarPos+1,
+ AsmString.begin()+VarEnd);
+
+ // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed
+ // into printOperand. Also support ${:feature}, which is passed into
+ // PrintSpecial.
+ std::string Modifier;
+
+ // In order to avoid starting the next string at the terminating curly
+ // brace, advance the end position past it if we found an opening curly
+ // brace.
+ if (hasCurlyBraces) {
+ if (VarEnd >= AsmString.size())
+ throw "Reached end of string before terminating curly brace in '"
+ + CGI.TheDef->getName() + "'";
+
+ // Look for a modifier string.
+ if (AsmString[VarEnd] == ':') {
+ ++VarEnd;
+ if (VarEnd >= AsmString.size())
+ throw "Reached end of string before terminating curly brace in '"
+ + CGI.TheDef->getName() + "'";
+
+ unsigned ModifierStart = VarEnd;
+ while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
+ ++VarEnd;
+ Modifier = std::string(AsmString.begin()+ModifierStart,
+ AsmString.begin()+VarEnd);
+ if (Modifier.empty())
+ throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'";
+ }
+
+ if (AsmString[VarEnd] != '}')
+ throw "Variable name beginning with '{' did not end with '}' in '"
+ + CGI.TheDef->getName() + "'";
+ ++VarEnd;
+ }
+ if (VarName.empty() && Modifier.empty())
+ throw "Stray '$' in '" + CGI.TheDef->getName() +
+ "' asm string, maybe you want $$?";
+
+ if (VarName.empty()) {
+ // Just a modifier, pass this into PrintSpecial.
+ Operands.push_back(AsmWriterOperand("PrintSpecial",
+ ~0U,
+ ~0U,
+ Modifier));
+ } else {
+ // Otherwise, normal operand.
+ unsigned OpNo = CGI.getOperandNamed(VarName);
+ CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo];
+
+ if (CurVariant == Variant || CurVariant == ~0U) {
+ unsigned MIOp = OpInfo.MIOperandNo;
+ Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName,
+ OpNo,
+ MIOp,
+ Modifier));
+ }
+ }
+ LastEmitted = VarEnd;
+ }
+ }
+
+ Operands.push_back(AsmWriterOperand("return;",
+ AsmWriterOperand::isLiteralStatementOperand));
+}
+
+/// MatchesAllButOneOp - If this instruction is exactly identical to the
+/// specified instruction except for one differing operand, return the differing
+/// operand number. If more than one operand mismatches, return ~1, otherwise
+/// if the instructions are identical return ~0.
+unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
+ if (Operands.size() != Other.Operands.size()) return ~1;
+
+ unsigned MismatchOperand = ~0U;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (Operands[i] != Other.Operands[i]) {
+ if (MismatchOperand != ~0U) // Already have one mismatch?
+ return ~1U;
+ else
+ MismatchOperand = i;
+ }
+ }
+ return MismatchOperand;
+}
diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.h b/contrib/llvm/utils/TableGen/AsmWriterInst.h
new file mode 100644
index 0000000..20b8588
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/AsmWriterInst.h
@@ -0,0 +1,113 @@
+//===- AsmWriterInst.h - Classes encapsulating a printable inst -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes implement a parser for assembly strings. The parser splits
+// the string into operands, which can be literal strings (the constant bits of
+// the string), actual operands (i.e., operands from the MachineInstr), and
+// dynamically-generated text, specified by raw C++ code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ASMWRITER_INST_H
+#define ASMWRITER_INST_H
+
+#include <string>
+#include <vector>
+
+namespace llvm {
+ class CodeGenInstruction;
+ class Record;
+
+ struct AsmWriterOperand {
+ enum OpType {
+ // Output this text surrounded by quotes to the asm.
+ isLiteralTextOperand,
+ // This is the name of a routine to call to print the operand.
+ isMachineInstrOperand,
+ // Output this text verbatim to the asm writer. It is code that
+ // will output some text to the asm.
+ isLiteralStatementOperand
+ } OperandType;
+
+ /// Str - For isLiteralTextOperand, this IS the literal text. For
+ /// isMachineInstrOperand, this is the PrinterMethodName for the operand..
+ /// For isLiteralStatementOperand, this is the code to insert verbatim
+ /// into the asm writer.
+ std::string Str;
+
+ /// CGIOpNo - For isMachineInstrOperand, this is the index of the operand in
+ /// the CodeGenInstruction.
+ unsigned CGIOpNo;
+
+ /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
+ /// machine instruction.
+ unsigned MIOpNo;
+
+ /// MiModifier - For isMachineInstrOperand, this is the modifier string for
+ /// an operand, specified with syntax like ${opname:modifier}.
+ std::string MiModifier;
+
+ // To make VS STL happy
+ AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
+
+ AsmWriterOperand(const std::string &LitStr,
+ OpType op = isLiteralTextOperand)
+ : OperandType(op), Str(LitStr) {}
+
+ AsmWriterOperand(const std::string &Printer,
+ unsigned _CGIOpNo,
+ unsigned _MIOpNo,
+ const std::string &Modifier,
+ OpType op = isMachineInstrOperand)
+ : OperandType(op), Str(Printer), CGIOpNo(_CGIOpNo), MIOpNo(_MIOpNo),
+ MiModifier(Modifier) {}
+
+ bool operator!=(const AsmWriterOperand &Other) const {
+ if (OperandType != Other.OperandType || Str != Other.Str) return true;
+ if (OperandType == isMachineInstrOperand)
+ return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier;
+ return false;
+ }
+ bool operator==(const AsmWriterOperand &Other) const {
+ return !operator!=(Other);
+ }
+
+ /// getCode - Return the code that prints this operand.
+ std::string getCode() const;
+ };
+
+ class AsmWriterInst {
+ public:
+ std::vector<AsmWriterOperand> Operands;
+ const CodeGenInstruction *CGI;
+
+ AsmWriterInst(const CodeGenInstruction &CGI,
+ unsigned Variant,
+ int FirstOperandColumn,
+ int OperandSpacing);
+
+ /// MatchesAllButOneOp - If this instruction is exactly identical to the
+ /// specified instruction except for one differing operand, return the
+ /// differing operand number. Otherwise return ~0.
+ unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;
+
+ private:
+ void AddLiteralString(const std::string &Str) {
+ // If the last operand was already a literal text string, append this to
+ // it, otherwise add a new operand.
+ if (!Operands.empty() &&
+ Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
+ Operands.back().Str.append(Str);
+ else
+ Operands.push_back(AsmWriterOperand(Str));
+ }
+ };
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CMakeLists.txt b/contrib/llvm/utils/TableGen/CMakeLists.txt
new file mode 100644
index 0000000..972989b
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CMakeLists.txt
@@ -0,0 +1,46 @@
+add_executable(tblgen
+ ARMDecoderEmitter.cpp
+ AsmMatcherEmitter.cpp
+ AsmWriterEmitter.cpp
+ AsmWriterInst.cpp
+ CallingConvEmitter.cpp
+ ClangASTNodesEmitter.cpp
+ ClangAttrEmitter.cpp
+ ClangDiagnosticsEmitter.cpp
+ CodeEmitterGen.cpp
+ CodeGenDAGPatterns.cpp
+ CodeGenInstruction.cpp
+ CodeGenTarget.cpp
+ DAGISelEmitter.cpp
+ DAGISelMatcherEmitter.cpp
+ DAGISelMatcherGen.cpp
+ DAGISelMatcherOpt.cpp
+ DAGISelMatcher.cpp
+ DisassemblerEmitter.cpp
+ EDEmitter.cpp
+ FastISelEmitter.cpp
+ InstrEnumEmitter.cpp
+ InstrInfoEmitter.cpp
+ IntrinsicEmitter.cpp
+ LLVMCConfigurationEmitter.cpp
+ NeonEmitter.cpp
+ OptParserEmitter.cpp
+ Record.cpp
+ RegisterInfoEmitter.cpp
+ SubtargetEmitter.cpp
+ TGLexer.cpp
+ TGParser.cpp
+ TGValueTypes.cpp
+ TableGen.cpp
+ TableGenBackend.cpp
+ X86DisassemblerTables.cpp
+ X86RecognizableInstr.cpp
+ )
+
+target_link_libraries(tblgen LLVMSupport LLVMSystem)
+if( MINGW )
+ target_link_libraries(tblgen imagehlp psapi)
+endif( MINGW )
+if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD AND NOT BEOS )
+ target_link_libraries(tblgen pthread)
+endif()
diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp
new file mode 100644
index 0000000..7643609
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp
@@ -0,0 +1,212 @@
+//===- CallingConvEmitter.cpp - Generate calling conventions --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting descriptions of the calling
+// conventions supported by this target.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CallingConvEmitter.h"
+#include "Record.h"
+#include "CodeGenTarget.h"
+using namespace llvm;
+
+void CallingConvEmitter::run(raw_ostream &O) {
+ EmitSourceFileHeader("Calling Convention Implementation Fragment", O);
+
+ std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");
+
+ // Emit prototypes for all of the CC's so that they can forward ref each
+ // other.
+ for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
+ O << "static bool " << CCs[i]->getName()
+ << "(unsigned ValNo, EVT ValVT,\n"
+ << std::string(CCs[i]->getName().size()+13, ' ')
+ << "EVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << std::string(CCs[i]->getName().size()+13, ' ')
+ << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
+ }
+
+ // Emit each calling convention description in full.
+ for (unsigned i = 0, e = CCs.size(); i != e; ++i)
+ EmitCallingConv(CCs[i], O);
+}
+
+
+void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
+ ListInit *CCActions = CC->getValueAsListInit("Actions");
+ Counter = 0;
+
+ O << "\n\nstatic bool " << CC->getName()
+ << "(unsigned ValNo, EVT ValVT,\n"
+ << std::string(CC->getName().size()+13, ' ')
+ << "EVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << std::string(CC->getName().size()+13, ' ')
+ << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
+ // Emit all of the actions, in order.
+ for (unsigned i = 0, e = CCActions->getSize(); i != e; ++i) {
+ O << "\n";
+ EmitAction(CCActions->getElementAsRecord(i), 2, O);
+ }
+
+ O << "\n return true; // CC didn't match.\n";
+ O << "}\n";
+}
+
+void CallingConvEmitter::EmitAction(Record *Action,
+ unsigned Indent, raw_ostream &O) {
+ std::string IndentStr = std::string(Indent, ' ');
+
+ if (Action->isSubClassOf("CCPredicateAction")) {
+ O << IndentStr << "if (";
+
+ if (Action->isSubClassOf("CCIfType")) {
+ ListInit *VTs = Action->getValueAsListInit("VTs");
+ for (unsigned i = 0, e = VTs->getSize(); i != e; ++i) {
+ Record *VT = VTs->getElementAsRecord(i);
+ if (i != 0) O << " ||\n " << IndentStr;
+ O << "LocVT == " << getEnumName(getValueType(VT));
+ }
+
+ } else if (Action->isSubClassOf("CCIf")) {
+ O << Action->getValueAsString("Predicate");
+ } else {
+ Action->dump();
+ throw "Unknown CCPredicateAction!";
+ }
+
+ O << ") {\n";
+ EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);
+ O << IndentStr << "}\n";
+ } else {
+ if (Action->isSubClassOf("CCDelegateTo")) {
+ Record *CC = Action->getValueAsDef("CC");
+ O << IndentStr << "if (!" << CC->getName()
+ << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"
+ << IndentStr << " return false;\n";
+ } else if (Action->isSubClassOf("CCAssignToReg")) {
+ ListInit *RegList = Action->getValueAsListInit("RegList");
+ if (RegList->getSize() == 1) {
+ O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
+ O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n";
+ } else {
+ O << IndentStr << "static const unsigned RegList" << ++Counter
+ << "[] = {\n";
+ O << IndentStr << " ";
+ for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
+ if (i != 0) O << ", ";
+ O << getQualifiedName(RegList->getElementAsRecord(i));
+ }
+ O << "\n" << IndentStr << "};\n";
+ O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
+ << Counter << ", " << RegList->getSize() << ")) {\n";
+ }
+ O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
+ << "Reg, LocVT, LocInfo));\n";
+ O << IndentStr << " return false;\n";
+ O << IndentStr << "}\n";
+ } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {
+ ListInit *RegList = Action->getValueAsListInit("RegList");
+ ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
+ if (ShadowRegList->getSize() >0 &&
+ ShadowRegList->getSize() != RegList->getSize())
+ throw "Invalid length of list of shadowed registers";
+
+ if (RegList->getSize() == 1) {
+ O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
+ O << getQualifiedName(RegList->getElementAsRecord(0));
+ O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));
+ O << ")) {\n";
+ } else {
+ unsigned RegListNumber = ++Counter;
+ unsigned ShadowRegListNumber = ++Counter;
+
+ O << IndentStr << "static const unsigned RegList" << RegListNumber
+ << "[] = {\n";
+ O << IndentStr << " ";
+ for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
+ if (i != 0) O << ", ";
+ O << getQualifiedName(RegList->getElementAsRecord(i));
+ }
+ O << "\n" << IndentStr << "};\n";
+
+ O << IndentStr << "static const unsigned RegList"
+ << ShadowRegListNumber << "[] = {\n";
+ O << IndentStr << " ";
+ for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) {
+ if (i != 0) O << ", ";
+ O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
+ }
+ O << "\n" << IndentStr << "};\n";
+
+ O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
+ << RegListNumber << ", " << "RegList" << ShadowRegListNumber
+ << ", " << RegList->getSize() << ")) {\n";
+ }
+ O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
+ << "Reg, LocVT, LocInfo));\n";
+ O << IndentStr << " return false;\n";
+ O << IndentStr << "}\n";
+ } else if (Action->isSubClassOf("CCAssignToStack")) {
+ int Size = Action->getValueAsInt("Size");
+ int Align = Action->getValueAsInt("Align");
+
+ O << IndentStr << "unsigned Offset" << ++Counter
+ << " = State.AllocateStack(";
+ if (Size)
+ O << Size << ", ";
+ else
+ O << "\n" << IndentStr << " State.getTarget().getTargetData()"
+ "->getTypeAllocSize(LocVT.getTypeForEVT(State.getContext())), ";
+ if (Align)
+ O << Align;
+ else
+ O << "\n" << IndentStr << " State.getTarget().getTargetData()"
+ "->getABITypeAlignment(LocVT.getTypeForEVT(State.getContext()))";
+ if (Action->isSubClassOf("CCAssignToStackWithShadow"))
+ O << ", " << getQualifiedName(Action->getValueAsDef("ShadowReg"));
+ O << ");\n" << IndentStr
+ << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
+ << Counter << ", LocVT, LocInfo));\n";
+ O << IndentStr << "return false;\n";
+ } else if (Action->isSubClassOf("CCPromoteToType")) {
+ Record *DestTy = Action->getValueAsDef("DestTy");
+ O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
+ O << IndentStr << "if (ArgFlags.isSExt())\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n"
+ << IndentStr << "else if (ArgFlags.isZExt())\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n"
+ << IndentStr << "else\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
+ } else if (Action->isSubClassOf("CCBitConvertToType")) {
+ Record *DestTy = Action->getValueAsDef("DestTy");
+ O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
+ O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
+ } else if (Action->isSubClassOf("CCPassIndirect")) {
+ Record *DestTy = Action->getValueAsDef("DestTy");
+ O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
+ O << IndentStr << "LocInfo = CCValAssign::Indirect;\n";
+ } else if (Action->isSubClassOf("CCPassByVal")) {
+ int Size = Action->getValueAsInt("Size");
+ int Align = Action->getValueAsInt("Align");
+ O << IndentStr
+ << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
+ << Size << ", " << Align << ", ArgFlags);\n";
+ O << IndentStr << "return false;\n";
+ } else if (Action->isSubClassOf("CCCustom")) {
+ O << IndentStr
+ << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "
+ << "LocVT, LocInfo, ArgFlags, State))\n";
+ O << IndentStr << IndentStr << "return false;\n";
+ } else {
+ Action->dump();
+ throw "Unknown CCAction!";
+ }
+ }
+}
diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.h b/contrib/llvm/utils/TableGen/CallingConvEmitter.h
new file mode 100644
index 0000000..7fc2507
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.h
@@ -0,0 +1,38 @@
+//===- CallingConvEmitter.h - Generate calling conventions ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting descriptions of the calling
+// conventions supported by this target.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CALLINGCONV_EMITTER_H
+#define CALLINGCONV_EMITTER_H
+
+#include "TableGenBackend.h"
+#include <map>
+#include <vector>
+#include <cassert>
+
+namespace llvm {
+ class CallingConvEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ public:
+ explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the asmwriter, returning true on failure.
+ void run(raw_ostream &o);
+
+ private:
+ void EmitCallingConv(Record *CC, raw_ostream &O);
+ void EmitAction(Record *Action, unsigned Indent, raw_ostream &O);
+ unsigned Counter;
+ };
+}
+#endif
diff --git a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp
new file mode 100644
index 0000000..187ab46
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp
@@ -0,0 +1,165 @@
+//=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang AST node tables
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangASTNodesEmitter.h"
+#include <set>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Statement Node Tables (.inc file) generation.
+//===----------------------------------------------------------------------===//
+
+// Returns the first and last non-abstract subrecords
+// Called recursively to ensure that nodes remain contiguous
+std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
+ const ChildMap &Tree,
+ raw_ostream &OS,
+ Record *Base) {
+ std::string BaseName = macroName(Base->getName());
+
+ ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
+
+ Record *First = 0, *Last = 0;
+ // This might be the pseudo-node for Stmt; don't assume it has an Abstract
+ // bit
+ if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract"))
+ First = Last = Base;
+
+ for (; i != e; ++i) {
+ Record *R = i->second;
+ bool Abstract = R->getValueAsBit("Abstract");
+ std::string NodeName = macroName(R->getName());
+
+ OS << "#ifndef " << NodeName << "\n";
+ OS << "# define " << NodeName << "(Type, Base) "
+ << BaseName << "(Type, Base)\n";
+ OS << "#endif\n";
+
+ if (Abstract)
+ OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "("
+ << R->getName() << ", " << baseName(*Base) << "))\n";
+ else
+ OS << NodeName << "(" << R->getName() << ", "
+ << baseName(*Base) << ")\n";
+
+ if (Tree.find(R) != Tree.end()) {
+ const std::pair<Record *, Record *> &Result
+ = EmitNode(Tree, OS, R);
+ if (!First && Result.first)
+ First = Result.first;
+ if (Result.second)
+ Last = Result.second;
+ } else {
+ if (!Abstract) {
+ Last = R;
+
+ if (!First)
+ First = R;
+ }
+ }
+
+ OS << "#undef " << NodeName << "\n\n";
+ }
+
+ if (First) {
+ assert (Last && "Got a first node but not a last node for a range!");
+ if (Base == &Root)
+ OS << "LAST_" << macroName(Root.getName()) << "_RANGE(";
+ else
+ OS << macroName(Root.getName()) << "_RANGE(";
+ OS << Base->getName() << ", " << First->getName() << ", "
+ << Last->getName() << ")\n\n";
+ }
+
+ return std::make_pair(First, Last);
+}
+
+void ClangASTNodesEmitter::run(raw_ostream &OS) {
+ // Write the preamble
+ OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n";
+ OS << "# define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n";
+ OS << "#endif\n";
+
+ OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n";
+ OS << "# define "
+ << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
+ OS << "#endif\n\n";
+
+ OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n";
+ OS << "# define LAST_"
+ << macroName(Root.getName()) << "_RANGE(Base, First, Last) "
+ << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
+ OS << "#endif\n\n";
+
+ // Emit statements
+ const std::vector<Record*> Stmts
+ = Records.getAllDerivedDefinitions(Root.getName());
+
+ ChildMap Tree;
+
+ for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
+ Record *R = Stmts[i];
+
+ if (R->getValue("Base"))
+ Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
+ else
+ Tree.insert(std::make_pair(&Root, R));
+ }
+
+ EmitNode(Tree, OS, &Root);
+
+ OS << "#undef " << macroName(Root.getName()) << "\n";
+ OS << "#undef " << macroName(Root.getName()) << "_RANGE\n";
+ OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n";
+ OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n";
+}
+
+void ClangDeclContextEmitter::run(raw_ostream &OS) {
+ // FIXME: Find a .td file format to allow for this to be represented better.
+
+ OS << "#ifndef DECL_CONTEXT\n";
+ OS << "# define DECL_CONTEXT(DECL)\n";
+ OS << "#endif\n";
+
+ OS << "#ifndef DECL_CONTEXT_BASE\n";
+ OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n";
+ OS << "#endif\n";
+
+ typedef std::set<Record*> RecordSet;
+ typedef std::vector<Record*> RecordVector;
+
+ RecordVector DeclContextsVector
+ = Records.getAllDerivedDefinitions("DeclContext");
+ RecordVector Decls = Records.getAllDerivedDefinitions("Decl");
+ RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end());
+
+ for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) {
+ Record *R = *i;
+
+ if (R->getValue("Base")) {
+ Record *B = R->getValueAsDef("Base");
+ if (DeclContexts.find(B) != DeclContexts.end()) {
+ OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n";
+ DeclContexts.erase(B);
+ }
+ }
+ }
+
+ for (RecordSet::iterator i = DeclContexts.begin(), e = DeclContexts.end();
+ i != e; ++i) {
+ OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n";
+ }
+
+ OS << "#undef DECL_CONTEXT\n";
+ OS << "#undef DECL_CONTEXT_BASE\n";
+}
diff --git a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h
new file mode 100644
index 0000000..abf9c9a
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h
@@ -0,0 +1,84 @@
+//===- ClangASTNodesEmitter.h - Generate Clang AST node tables -*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang AST node tables
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANGAST_EMITTER_H
+#define CLANGAST_EMITTER_H
+
+#include "TableGenBackend.h"
+#include "Record.h"
+#include <string>
+#include <cctype>
+#include <map>
+
+namespace llvm {
+
+/// ClangASTNodesEmitter - The top-level class emits .inc files containing
+/// declarations of Clang statements.
+///
+class ClangASTNodesEmitter : public TableGenBackend {
+ // A map from a node to each of its derived nodes.
+ typedef std::multimap<Record*, Record*> ChildMap;
+ typedef ChildMap::const_iterator ChildIterator;
+
+ RecordKeeper &Records;
+ Record Root;
+ const std::string &BaseSuffix;
+
+ // Create a macro-ized version of a name
+ static std::string macroName(std::string S) {
+ for (unsigned i = 0; i < S.size(); ++i)
+ S[i] = std::toupper(S[i]);
+
+ return S;
+ }
+
+ // Return the name to be printed in the base field. Normally this is
+ // the record's name plus the base suffix, but if it is the root node and
+ // the suffix is non-empty, it's just the suffix.
+ std::string baseName(Record &R) {
+ if (&R == &Root && !BaseSuffix.empty())
+ return BaseSuffix;
+
+ return R.getName() + BaseSuffix;
+ }
+
+ std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS,
+ Record *Base);
+public:
+ explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N,
+ const std::string &S)
+ : Records(R), Root(N, SMLoc()), BaseSuffix(S)
+ {}
+
+ // run - Output the .inc file contents
+ void run(raw_ostream &OS);
+};
+
+/// ClangDeclContextEmitter - Emits an addendum to a .inc file to enumerate the
+/// clang declaration contexts.
+///
+class ClangDeclContextEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+public:
+ explicit ClangDeclContextEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ // run - Output the .inc file contents
+ void run(raw_ostream &OS);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp
new file mode 100644
index 0000000..8d3399a
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp
@@ -0,0 +1,638 @@
+//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang attribute processing code
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangAttrEmitter.h"
+#include "Record.h"
+#include "llvm/ADT/StringSwitch.h"
+#include <algorithm>
+#include <cctype>
+
+using namespace llvm;
+
+static const std::vector<StringRef> getValueAsListOfStrings(Record &R,
+ StringRef FieldName) {
+ ListInit *List = R.getValueAsListInit(FieldName);
+ assert (List && "Got a null ListInit");
+
+ std::vector<StringRef> Strings;
+ Strings.reserve(List->getSize());
+
+ for (ListInit::iterator i = List->begin(), e = List->end(); i != e; ++i) {
+ assert(*i && "Got a null element in a ListInit");
+ if (StringInit *S = dynamic_cast<StringInit *>(*i))
+ Strings.push_back(S->getValue());
+ else if (CodeInit *C = dynamic_cast<CodeInit *>(*i))
+ Strings.push_back(C->getValue());
+ else
+ assert(false && "Got a non-string, non-code element in a ListInit");
+ }
+
+ return Strings;
+}
+
+std::string ReadPCHRecord(StringRef type) {
+ return StringSwitch<std::string>(type)
+ .EndsWith("Decl *", "cast_or_null<" + std::string(type, 0, type.size()-1) +
+ ">(GetDecl(Record[Idx++]))")
+ .Case("QualType", "ReadTypeRecord(Idx++)")
+ .Default("Record[Idx++]");
+}
+
+// Assumes that the way to get the value is SA->getname()
+std::string WritePCHRecord(StringRef type, StringRef name) {
+ return StringSwitch<std::string>(type)
+ .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
+ ", Record);\n")
+ .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
+ .Default("Record.push_back(" + std::string(name) + ");\n");
+}
+
+namespace {
+ class Argument {
+ std::string lowerName, upperName;
+ StringRef attrName;
+
+ public:
+ Argument(Record &Arg, StringRef Attr)
+ : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
+ attrName(Attr) {
+ if (!lowerName.empty()) {
+ lowerName[0] = std::tolower(lowerName[0]);
+ upperName[0] = std::toupper(upperName[0]);
+ }
+ }
+ virtual ~Argument() {}
+
+ StringRef getLowerName() const { return lowerName; }
+ StringRef getUpperName() const { return upperName; }
+ StringRef getAttrName() const { return attrName; }
+
+ // These functions print the argument contents formatted in different ways.
+ virtual void writeAccessors(raw_ostream &OS) const = 0;
+ virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
+ virtual void writeCloneArgs(raw_ostream &OS) const = 0;
+ virtual void writeCtorBody(raw_ostream &OS) const {}
+ virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
+ virtual void writeCtorParameters(raw_ostream &OS) const = 0;
+ virtual void writeDeclarations(raw_ostream &OS) const = 0;
+ virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
+ virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
+ virtual void writePCHWrite(raw_ostream &OS) const = 0;
+ };
+
+ class SimpleArgument : public Argument {
+ std::string type;
+
+ public:
+ SimpleArgument(Record &Arg, StringRef Attr, std::string T)
+ : Argument(Arg, Attr), type(T)
+ {}
+
+ void writeAccessors(raw_ostream &OS) const {
+ OS << " " << type << " get" << getUpperName() << "() const {\n";
+ OS << " return " << getLowerName() << ";\n";
+ OS << " }";
+ }
+ void writeCloneArgs(raw_ostream &OS) const {
+ OS << getLowerName();
+ }
+ void writeCtorInitializers(raw_ostream &OS) const {
+ OS << getLowerName() << "(" << getUpperName() << ")";
+ }
+ void writeCtorParameters(raw_ostream &OS) const {
+ OS << type << " " << getUpperName();
+ }
+ void writeDeclarations(raw_ostream &OS) const {
+ OS << type << " " << getLowerName() << ";";
+ }
+ void writePCHReadDecls(raw_ostream &OS) const {
+ std::string read = ReadPCHRecord(type);
+ OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
+ }
+ void writePCHReadArgs(raw_ostream &OS) const {
+ OS << getLowerName();
+ }
+ void writePCHWrite(raw_ostream &OS) const {
+ OS << " " << WritePCHRecord(type, "SA->get" +
+ std::string(getUpperName()) + "()");
+ }
+ };
+
+ class StringArgument : public Argument {
+ public:
+ StringArgument(Record &Arg, StringRef Attr)
+ : Argument(Arg, Attr)
+ {}
+
+ void writeAccessors(raw_ostream &OS) const {
+ OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
+ OS << " return llvm::StringRef(" << getLowerName() << ", "
+ << getLowerName() << "Length);\n";
+ OS << " }\n";
+ OS << " unsigned get" << getUpperName() << "Length() const {\n";
+ OS << " return " << getLowerName() << "Length;\n";
+ OS << " }\n";
+ OS << " void set" << getUpperName()
+ << "(ASTContext &C, llvm::StringRef S) {\n";
+ OS << " " << getLowerName() << "Length = S.size();\n";
+ OS << " this->" << getLowerName() << " = new (C, 1) char ["
+ << getLowerName() << "Length];\n";
+ OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
+ << getLowerName() << "Length);\n";
+ OS << " }";
+ }
+ void writeCloneArgs(raw_ostream &OS) const {
+ OS << "get" << getUpperName() << "()";
+ }
+ void writeCtorBody(raw_ostream &OS) const {
+ OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
+ << ".data(), " << getLowerName() << "Length);";
+ }
+ void writeCtorInitializers(raw_ostream &OS) const {
+ OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
+ << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
+ << "Length])";
+ }
+ void writeCtorParameters(raw_ostream &OS) const {
+ OS << "llvm::StringRef " << getUpperName();
+ }
+ void writeDeclarations(raw_ostream &OS) const {
+ OS << "unsigned " << getLowerName() << "Length;\n";
+ OS << "char *" << getLowerName() << ";";
+ }
+ void writePCHReadDecls(raw_ostream &OS) const {
+ OS << " std::string " << getLowerName() << "= ReadString(Record, Idx);\n";
+ }
+ void writePCHReadArgs(raw_ostream &OS) const {
+ OS << getLowerName();
+ }
+ void writePCHWrite(raw_ostream &OS) const {
+ OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
+ }
+ };
+
+ class AlignedArgument : public Argument {
+ public:
+ AlignedArgument(Record &Arg, StringRef Attr)
+ : Argument(Arg, Attr)
+ {}
+
+ void writeAccessors(raw_ostream &OS) const {
+ OS << " bool is" << getUpperName() << "Dependent() const;\n";
+
+ OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
+
+ OS << " bool is" << getUpperName() << "Expr() const {\n";
+ OS << " return is" << getLowerName() << "Expr;\n";
+ OS << " }\n";
+
+ OS << " Expr *get" << getUpperName() << "Expr() const {\n";
+ OS << " assert(is" << getLowerName() << "Expr);\n";
+ OS << " return " << getLowerName() << "Expr;\n";
+ OS << " }\n";
+
+ OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
+ OS << " assert(!is" << getLowerName() << "Expr);\n";
+ OS << " return " << getLowerName() << "Type;\n";
+ OS << " }";
+ }
+ void writeAccessorDefinitions(raw_ostream &OS) const {
+ OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
+ << "Dependent() const {\n";
+ OS << " if (is" << getLowerName() << "Expr)\n";
+ OS << " return " << getLowerName() << "Expr && (" << getLowerName()
+ << "Expr->isValueDependent() || " << getLowerName()
+ << "Expr->isTypeDependent());\n";
+ OS << " else\n";
+ OS << " return " << getLowerName()
+ << "Type->getType()->isDependentType();\n";
+ OS << "}\n";
+
+ // FIXME: Do not do the calculation here
+ // FIXME: Handle types correctly
+ // A null pointer means maximum alignment
+ // FIXME: Load the platform-specific maximum alignment, rather than
+ // 16, the x86 max.
+ OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
+ << "(ASTContext &Ctx) const {\n";
+ OS << " assert(!is" << getUpperName() << "Dependent());\n";
+ OS << " if (is" << getLowerName() << "Expr)\n";
+ OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
+ << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)"
+ << "* Ctx.getCharWidth();\n";
+ OS << " else\n";
+ OS << " return 0; // FIXME\n";
+ OS << "}\n";
+ }
+ void writeCloneArgs(raw_ostream &OS) const {
+ OS << "is" << getLowerName() << "Expr, is" << getLowerName()
+ << "Expr ? static_cast<void*>(" << getLowerName()
+ << "Expr) : " << getLowerName()
+ << "Type";
+ }
+ void writeCtorBody(raw_ostream &OS) const {
+ OS << " if (is" << getLowerName() << "Expr)\n";
+ OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
+ << getUpperName() << ");\n";
+ OS << " else\n";
+ OS << " " << getLowerName()
+ << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
+ << ");";
+ }
+ void writeCtorInitializers(raw_ostream &OS) const {
+ OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
+ }
+ void writeCtorParameters(raw_ostream &OS) const {
+ OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
+ }
+ void writeDeclarations(raw_ostream &OS) const {
+ OS << "bool is" << getLowerName() << "Expr;\n";
+ OS << "union {\n";
+ OS << "Expr *" << getLowerName() << "Expr;\n";
+ OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
+ OS << "};";
+ }
+ void writePCHReadArgs(raw_ostream &OS) const {
+ OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
+ }
+ void writePCHReadDecls(raw_ostream &OS) const {
+ OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
+ OS << " void *" << getLowerName() << "Ptr;\n";
+ OS << " if (is" << getLowerName() << "Expr)\n";
+ OS << " " << getLowerName() << "Ptr = ReadExpr(DeclsCursor);\n";
+ OS << " else\n";
+ OS << " " << getLowerName()
+ << "Ptr = GetTypeSourceInfo(DeclsCursor, Record, Idx);\n";
+ }
+ void writePCHWrite(raw_ostream &OS) const {
+ OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
+ OS << " if (SA->is" << getUpperName() << "Expr())\n";
+ OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
+ OS << " else\n";
+ OS << " AddTypeSourceInfo(SA->get" << getUpperName()
+ << "Type(), Record);\n";
+ }
+ };
+
+ class VariadicArgument : public Argument {
+ std::string type;
+
+ public:
+ VariadicArgument(Record &Arg, StringRef Attr, std::string T)
+ : Argument(Arg, Attr), type(T)
+ {}
+
+ std::string getType() const { return type; }
+
+ void writeAccessors(raw_ostream &OS) const {
+ OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
+ OS << " " << getLowerName() << "_iterator " << getLowerName()
+ << "_begin() const {\n";
+ OS << " return " << getLowerName() << ";\n";
+ OS << " }\n";
+ OS << " " << getLowerName() << "_iterator " << getLowerName()
+ << "_end() const {\n";
+ OS << " return " << getLowerName() << " + " << getLowerName()
+ << "Size;\n";
+ OS << " }\n";
+ OS << " unsigned " << getLowerName() << "_size() const {\n"
+ << " return " << getLowerName() << "Size;\n;";
+ OS << " }";
+ }
+ void writeCloneArgs(raw_ostream &OS) const {
+ OS << getLowerName() << ", " << getLowerName() << "Size";
+ }
+ void writeCtorBody(raw_ostream &OS) const {
+ // FIXME: memcpy is not safe on non-trivial types.
+ OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
+ << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
+ }
+ void writeCtorInitializers(raw_ostream &OS) const {
+ OS << getLowerName() << "Size(" << getUpperName() << "Size), "
+ << getLowerName() << "(new (Ctx, 16) " << getType() << "["
+ << getLowerName() << "Size])";
+ }
+ void writeCtorParameters(raw_ostream &OS) const {
+ OS << getType() << " *" << getUpperName() << ", unsigned "
+ << getUpperName() << "Size";
+ }
+ void writeDeclarations(raw_ostream &OS) const {
+ OS << " unsigned " << getLowerName() << "Size;\n";
+ OS << " " << getType() << " *" << getLowerName() << ";";
+ }
+ void writePCHReadDecls(raw_ostream &OS) const {
+ OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
+ OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
+ << ";\n";
+ OS << " " << getLowerName() << ".reserve(" << getLowerName()
+ << "Size);\n";
+ OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
+
+ std::string read = ReadPCHRecord(type);
+ OS << " " << getLowerName() << ".push_back(" << read << ");\n";
+ }
+ void writePCHReadArgs(raw_ostream &OS) const {
+ OS << getLowerName() << ".data(), " << getLowerName() << "Size";
+ }
+ void writePCHWrite(raw_ostream &OS) const{
+ OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
+ OS << " for (" << getAttrName() << "Attr::" << getLowerName()
+ << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
+ << getLowerName() << "_end(); i != e; ++i)\n";
+ OS << " " << WritePCHRecord(type, "(*i)");
+ }
+ };
+
+ class EnumArgument : public Argument {
+ std::string type;
+ std::vector<StringRef> values, enums;
+ public:
+ EnumArgument(Record &Arg, StringRef Attr)
+ : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
+ values(getValueAsListOfStrings(Arg, "Values")),
+ enums(getValueAsListOfStrings(Arg, "Enums"))
+ {}
+
+ void writeAccessors(raw_ostream &OS) const {
+ OS << " " << type << " get" << getUpperName() << "() const {\n";
+ OS << " return " << getLowerName() << ";\n";
+ OS << " }";
+ }
+ void writeCloneArgs(raw_ostream &OS) const {
+ OS << getLowerName();
+ }
+ void writeCtorInitializers(raw_ostream &OS) const {
+ OS << getLowerName() << "(" << getUpperName() << ")";
+ }
+ void writeCtorParameters(raw_ostream &OS) const {
+ OS << type << " " << getUpperName();
+ }
+ void writeDeclarations(raw_ostream &OS) const {
+ // Calculate the various enum values
+ std::vector<StringRef> uniques(enums);
+ std::sort(uniques.begin(), uniques.end());
+ uniques.erase(std::unique(uniques.begin(), uniques.end()),
+ uniques.end());
+ // FIXME: Emit a proper error
+ assert(!uniques.empty());
+
+ std::vector<StringRef>::iterator i = uniques.begin(),
+ e = uniques.end();
+ // The last one needs to not have a comma.
+ --e;
+
+ OS << "public:\n";
+ OS << " enum " << type << " {\n";
+ for (; i != e; ++i)
+ OS << " " << *i << ",\n";
+ OS << " " << *e << "\n";
+ OS << " };\n";
+ OS << "private:\n";
+ OS << " " << type << " " << getLowerName() << ";";
+ }
+ void writePCHReadDecls(raw_ostream &OS) const {
+ OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
+ << "(static_cast<" << getAttrName() << "Attr::" << type
+ << ">(Record[Idx++]));\n";
+ }
+ void writePCHReadArgs(raw_ostream &OS) const {
+ OS << getLowerName();
+ }
+ void writePCHWrite(raw_ostream &OS) const {
+ OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
+ }
+ };
+}
+
+static Argument *createArgument(Record &Arg, StringRef Attr,
+ Record *Search = 0) {
+ if (!Search)
+ Search = &Arg;
+
+ Argument *Ptr = 0;
+ llvm::StringRef ArgName = Search->getName();
+
+ if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
+ else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
+ else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
+ "Expr *");
+ else if (ArgName == "FunctionArgument")
+ Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
+ else if (ArgName == "IdentifierArgument")
+ Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
+ else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
+ else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
+ else if (ArgName == "TypeArgument")
+ Ptr = new SimpleArgument(Arg, Attr, "QualType");
+ else if (ArgName == "UnsignedArgument")
+ Ptr = new SimpleArgument(Arg, Attr, "unsigned");
+ else if (ArgName == "VariadicUnsignedArgument")
+ Ptr = new VariadicArgument(Arg, Attr, "unsigned");
+
+ if (!Ptr) {
+ std::vector<Record*> Bases = Search->getSuperClasses();
+ for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
+ i != e; ++i) {
+ Ptr = createArgument(Arg, Attr, *i);
+ if (Ptr)
+ break;
+ }
+ }
+ return Ptr;
+}
+
+void ClangAttrClassEmitter::run(raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+ OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
+ OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+
+ for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
+ i != e; ++i) {
+ Record &R = **i;
+
+ OS << "class " << R.getName() << "Attr : public Attr {\n";
+
+ std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
+ std::vector<Argument*> Args;
+ std::vector<Argument*>::iterator ai, ae;
+ Args.reserve(ArgRecords.size());
+
+ for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
+ re = ArgRecords.end();
+ ri != re; ++ri) {
+ Record &ArgRecord = **ri;
+ Argument *Arg = createArgument(ArgRecord, R.getName());
+ assert(Arg);
+ Args.push_back(Arg);
+
+ Arg->writeDeclarations(OS);
+ OS << "\n\n";
+ }
+
+ ae = Args.end();
+
+ OS << "\n public:\n";
+ OS << " " << R.getName() << "Attr(SourceLocation L, ASTContext &Ctx\n";
+
+ for (ai = Args.begin(); ai != ae; ++ai) {
+ OS << " , ";
+ (*ai)->writeCtorParameters(OS);
+ OS << "\n";
+ }
+
+ OS << " )\n";
+ OS << " : Attr(attr::" << R.getName() << ", L)\n";
+
+ for (ai = Args.begin(); ai != ae; ++ai) {
+ OS << " , ";
+ (*ai)->writeCtorInitializers(OS);
+ OS << "\n";
+ }
+
+ OS << " {\n";
+
+ for (ai = Args.begin(); ai != ae; ++ai) {
+ (*ai)->writeCtorBody(OS);
+ OS << "\n";
+ }
+ OS << " }\n\n";
+
+ OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
+
+ for (ai = Args.begin(); ai != ae; ++ai) {
+ (*ai)->writeAccessors(OS);
+ OS << "\n\n";
+ }
+
+ OS << R.getValueAsCode("AdditionalMembers");
+ OS << "\n\n";
+
+ OS << " static bool classof(const Attr *A) { return A->getKind() == "
+ << "attr::" << R.getName() << "; }\n";
+ OS << " static bool classof(const " << R.getName()
+ << "Attr *) { return true; }\n";
+ OS << "};\n\n";
+ }
+
+ OS << "#endif\n";
+}
+
+void ClangAttrImplEmitter::run(raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+ std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
+ std::vector<Argument*>::iterator ai, ae;
+
+ for (; i != e; ++i) {
+ Record &R = **i;
+ std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
+ std::vector<Argument*> Args;
+ for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
+ Args.push_back(createArgument(**ri, R.getName()));
+
+ for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
+ (*ai)->writeAccessorDefinitions(OS);
+
+ OS << R.getName() << "Attr *" << R.getName()
+ << "Attr::clone(ASTContext &C) const {\n";
+ OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
+ for (ai = Args.begin(); ai != ae; ++ai) {
+ OS << ", ";
+ (*ai)->writeCloneArgs(OS);
+ }
+ OS << ");\n}\n\n";
+ }
+}
+
+void ClangAttrListEmitter::run(raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ OS << "#ifndef LAST_ATTR\n";
+ OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
+ OS << "#endif\n\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+ std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
+
+ if (i != e) {
+ // Move the end iterator back to emit the last attribute.
+ for(--e; i != e; ++i)
+ OS << "ATTR(" << (*i)->getName() << ")\n";
+
+ OS << "LAST_ATTR(" << (*i)->getName() << ")\n\n";
+ }
+
+ OS << "#undef LAST_ATTR\n";
+ OS << "#undef ATTR\n";
+}
+
+void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edi.\n\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
+ ArgRecords;
+ std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
+ std::vector<Argument*> Args;
+ std::vector<Argument*>::iterator ri, re;
+
+ OS << " switch (Kind) {\n";
+ OS << " default:\n";
+ OS << " assert(0 && \"Unknown attribute!\");\n";
+ OS << " break;\n";
+ for (; i != e; ++i) {
+ Record &R = **i;
+ OS << " case attr::" << R.getName() << ": {\n";
+ ArgRecords = R.getValueAsListOfDefs("Args");
+ Args.clear();
+ for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
+ Argument *A = createArgument(**ai, R.getName());
+ Args.push_back(A);
+ A->writePCHReadDecls(OS);
+ }
+ OS << " New = new (*Context) " << R.getName() << "Attr(Loc, *Context";
+ for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
+ OS << ", ";
+ (*ri)->writePCHReadArgs(OS);
+ }
+ OS << ");\n";
+ OS << " break;\n";
+ OS << " }\n";
+ }
+ OS << " }\n";
+}
+
+void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
+ std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
+
+ OS << " switch (A->getKind()) {\n";
+ OS << " default:\n";
+ OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
+ OS << " break;\n";
+ for (; i != e; ++i) {
+ Record &R = **i;
+ OS << " case attr::" << R.getName() << ": {\n";
+ Args = R.getValueAsListOfDefs("Args");
+ if (!Args.empty())
+ OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
+ << "Attr>(A);\n";
+ for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
+ createArgument(**ai, R.getName())->writePCHWrite(OS);
+ OS << " break;\n";
+ OS << " }\n";
+ }
+ OS << " }\n";
+}
diff --git a/contrib/llvm/utils/TableGen/ClangAttrEmitter.h b/contrib/llvm/utils/TableGen/ClangAttrEmitter.h
new file mode 100644
index 0000000..8314982
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/ClangAttrEmitter.h
@@ -0,0 +1,88 @@
+//===- ClangAttrEmitter.h - Generate Clang attribute handling =-*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang attribute processing code
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANGATTR_EMITTER_H
+#define CLANGATTR_EMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+
+/// ClangAttrClassEmitter - class emits the class defintions for attributes for
+/// clang.
+class ClangAttrClassEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+ public:
+ explicit ClangAttrClassEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
+/// ClangAttrImplEmitter - class emits the class method defintions for
+/// attributes for clang.
+class ClangAttrImplEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+ public:
+ explicit ClangAttrImplEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
+/// ClangAttrListEmitter - class emits the enumeration list for attributes for
+/// clang.
+class ClangAttrListEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+ public:
+ explicit ClangAttrListEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
+/// ClangAttrPCHReadEmitter - class emits the code to read an attribute from
+/// a clang precompiled header.
+class ClangAttrPCHReadEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+public:
+ explicit ClangAttrPCHReadEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
+/// ClangAttrPCHWriteEmitter - class emits the code to read an attribute from
+/// a clang precompiled header.
+class ClangAttrPCHWriteEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+public:
+ explicit ClangAttrPCHWriteEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp
new file mode 100644
index 0000000..75b6252
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -0,0 +1,286 @@
+//=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- C++ -*-
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang diagnostics tables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangDiagnosticsEmitter.h"
+#include "Record.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/VectorExtras.h"
+#include <set>
+#include <map>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Diagnostic category computation code.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class DiagGroupParentMap {
+ std::map<const Record*, std::vector<Record*> > Mapping;
+public:
+ DiagGroupParentMap() {
+ std::vector<Record*> DiagGroups
+ = Records.getAllDerivedDefinitions("DiagGroup");
+ for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
+ std::vector<Record*> SubGroups =
+ DiagGroups[i]->getValueAsListOfDefs("SubGroups");
+ for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
+ Mapping[SubGroups[j]].push_back(DiagGroups[i]);
+ }
+ }
+
+ const std::vector<Record*> &getParents(const Record *Group) {
+ return Mapping[Group];
+ }
+};
+} // end anonymous namespace.
+
+
+static std::string
+getCategoryFromDiagGroup(const Record *Group,
+ DiagGroupParentMap &DiagGroupParents) {
+ // If the DiagGroup has a category, return it.
+ std::string CatName = Group->getValueAsString("CategoryName");
+ if (!CatName.empty()) return CatName;
+
+ // The diag group may the subgroup of one or more other diagnostic groups,
+ // check these for a category as well.
+ const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
+ for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
+ CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
+ if (!CatName.empty()) return CatName;
+ }
+ return "";
+}
+
+/// getDiagnosticCategory - Return the category that the specified diagnostic
+/// lives in.
+static std::string getDiagnosticCategory(const Record *R,
+ DiagGroupParentMap &DiagGroupParents) {
+ // If the diagnostic is in a group, and that group has a category, use it.
+ if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"))) {
+ // Check the diagnostic's diag group for a category.
+ std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
+ DiagGroupParents);
+ if (!CatName.empty()) return CatName;
+ }
+
+ // If the diagnostic itself has a category, get it.
+ return R->getValueAsString("CategoryName");
+}
+
+namespace {
+ class DiagCategoryIDMap {
+ StringMap<unsigned> CategoryIDs;
+ std::vector<std::string> CategoryStrings;
+ public:
+ DiagCategoryIDMap() {
+ DiagGroupParentMap ParentInfo;
+
+ // The zero'th category is "".
+ CategoryStrings.push_back("");
+ CategoryIDs[""] = 0;
+
+ std::vector<Record*> Diags =
+ Records.getAllDerivedDefinitions("Diagnostic");
+ for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+ std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
+ if (Category.empty()) continue; // Skip diags with no category.
+
+ unsigned &ID = CategoryIDs[Category];
+ if (ID != 0) continue; // Already seen.
+
+ ID = CategoryStrings.size();
+ CategoryStrings.push_back(Category);
+ }
+ }
+
+ unsigned getID(StringRef CategoryString) {
+ return CategoryIDs[CategoryString];
+ }
+
+ typedef std::vector<std::string>::iterator iterator;
+ iterator begin() { return CategoryStrings.begin(); }
+ iterator end() { return CategoryStrings.end(); }
+ };
+} // end anonymous namespace.
+
+
+
+//===----------------------------------------------------------------------===//
+// Warning Tables (.inc file) generation.
+//===----------------------------------------------------------------------===//
+
+void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
+ // Write the #if guard
+ if (!Component.empty()) {
+ std::string ComponentName = UppercaseString(Component);
+ OS << "#ifdef " << ComponentName << "START\n";
+ OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
+ << ",\n";
+ OS << "#undef " << ComponentName << "START\n";
+ OS << "#endif\n\n";
+ }
+
+ const std::vector<Record*> &Diags =
+ Records.getAllDerivedDefinitions("Diagnostic");
+
+ DiagCategoryIDMap CategoryIDs;
+ DiagGroupParentMap DGParentMap;
+
+ for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+ const Record &R = *Diags[i];
+ // Filter by component.
+ if (!Component.empty() && Component != R.getValueAsString("Component"))
+ continue;
+
+ OS << "DIAG(" << R.getName() << ", ";
+ OS << R.getValueAsDef("Class")->getName();
+ OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName();
+
+ // Description string.
+ OS << ", \"";
+ OS.write_escaped(R.getValueAsString("Text")) << '"';
+
+ // Warning associated with the diagnostic.
+ if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) {
+ OS << ", \"";
+ OS.write_escaped(DI->getDef()->getValueAsString("GroupName")) << '"';
+ } else {
+ OS << ", 0";
+ }
+
+ // SFINAE bit
+ if (R.getValueAsBit("SFINAE"))
+ OS << ", true";
+ else
+ OS << ", false";
+
+ // Category number.
+ OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
+ OS << ")\n";
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Warning Group Tables generation
+//===----------------------------------------------------------------------===//
+
+struct GroupInfo {
+ std::vector<const Record*> DiagsInGroup;
+ std::vector<std::string> SubGroups;
+ unsigned IDNo;
+};
+
+void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
+ // Compute a mapping from a DiagGroup to all of its parents.
+ DiagGroupParentMap DGParentMap;
+
+ // Invert the 1-[0/1] mapping of diags to group into a one to many mapping of
+ // groups to diags in the group.
+ std::map<std::string, GroupInfo> DiagsInGroup;
+
+ std::vector<Record*> Diags =
+ Records.getAllDerivedDefinitions("Diagnostic");
+ for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+ const Record *R = Diags[i];
+ DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group"));
+ if (DI == 0) continue;
+ std::string GroupName = DI->getDef()->getValueAsString("GroupName");
+ DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
+ }
+
+ // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
+ // groups (these are warnings that GCC supports that clang never produces).
+ std::vector<Record*> DiagGroups
+ = Records.getAllDerivedDefinitions("DiagGroup");
+ for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
+ Record *Group = DiagGroups[i];
+ GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
+
+ std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
+ for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
+ GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
+ }
+
+ // Assign unique ID numbers to the groups.
+ unsigned IDNo = 0;
+ for (std::map<std::string, GroupInfo>::iterator
+ I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
+ I->second.IDNo = IDNo;
+
+ // Walk through the groups emitting an array for each diagnostic of the diags
+ // that are mapped to.
+ OS << "\n#ifdef GET_DIAG_ARRAYS\n";
+ unsigned MaxLen = 0;
+ for (std::map<std::string, GroupInfo>::iterator
+ I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
+ MaxLen = std::max(MaxLen, (unsigned)I->first.size());
+
+ std::vector<const Record*> &V = I->second.DiagsInGroup;
+ if (!V.empty()) {
+ OS << "static const short DiagArray" << I->second.IDNo << "[] = { ";
+ for (unsigned i = 0, e = V.size(); i != e; ++i)
+ OS << "diag::" << V[i]->getName() << ", ";
+ OS << "-1 };\n";
+ }
+
+ const std::vector<std::string> &SubGroups = I->second.SubGroups;
+ if (!SubGroups.empty()) {
+ OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { ";
+ for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) {
+ std::map<std::string, GroupInfo>::iterator RI =
+ DiagsInGroup.find(SubGroups[i]);
+ assert(RI != DiagsInGroup.end() && "Referenced without existing?");
+ OS << RI->second.IDNo << ", ";
+ }
+ OS << "-1 };\n";
+ }
+ }
+ OS << "#endif // GET_DIAG_ARRAYS\n\n";
+
+ // Emit the table now.
+ OS << "\n#ifdef GET_DIAG_TABLE\n";
+ for (std::map<std::string, GroupInfo>::iterator
+ I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
+ // Group option string.
+ OS << " { \"";
+ OS.write_escaped(I->first) << "\","
+ << std::string(MaxLen-I->first.size()+1, ' ');
+
+ // Diagnostics in the group.
+ if (I->second.DiagsInGroup.empty())
+ OS << "0, ";
+ else
+ OS << "DiagArray" << I->second.IDNo << ", ";
+
+ // Subgroups.
+ if (I->second.SubGroups.empty())
+ OS << 0;
+ else
+ OS << "DiagSubGroup" << I->second.IDNo;
+ OS << " },\n";
+ }
+ OS << "#endif // GET_DIAG_TABLE\n\n";
+
+ // Emit the category table next.
+ DiagCategoryIDMap CategoriesByID;
+ OS << "\n#ifdef GET_CATEGORY_TABLE\n";
+ for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(),
+ E = CategoriesByID.end(); I != E; ++I)
+ OS << "CATEGORY(\"" << *I << "\")\n";
+ OS << "#endif // GET_CATEGORY_TABLE\n\n";
+}
diff --git a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h
new file mode 100644
index 0000000..edd062a
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h
@@ -0,0 +1,46 @@
+//===- ClangDiagnosticsEmitter.h - Generate Clang diagnostics tables -*- C++ -*-
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang diagnostics tables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANGDIAGS_EMITTER_H
+#define CLANGDIAGS_EMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+
+/// ClangDiagsDefsEmitter - The top-level class emits .def files containing
+/// declarations of Clang diagnostics.
+///
+class ClangDiagsDefsEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ const std::string& Component;
+public:
+ explicit ClangDiagsDefsEmitter(RecordKeeper &R, const std::string& component)
+ : Records(R), Component(component) {}
+
+ // run - Output the .def file contents
+ void run(raw_ostream &OS);
+};
+
+class ClangDiagGroupsEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ explicit ClangDiagGroupsEmitter(RecordKeeper &R) : Records(R) {}
+
+ void run(raw_ostream &OS);
+};
+
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
new file mode 100644
index 0000000..ec702c2a5
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -0,0 +1,224 @@
+//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// CodeEmitterGen uses the descriptions of instructions and their fields to
+// construct an automated code emitter: a function that, given a MachineInstr,
+// returns the (currently, 32-bit unsigned) value of the instruction.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeEmitterGen.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Debug.h"
+using namespace llvm;
+
+void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
+ for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
+ I != E; ++I) {
+ Record *R = *I;
+ if (R->getValueAsString("Namespace") == "TargetOpcode")
+ continue;
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+
+ unsigned numBits = BI->getNumBits();
+ BitsInit *NewBI = new BitsInit(numBits);
+ for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
+ unsigned bitSwapIdx = numBits - bit - 1;
+ Init *OrigBit = BI->getBit(bit);
+ Init *BitSwap = BI->getBit(bitSwapIdx);
+ NewBI->setBit(bit, BitSwap);
+ NewBI->setBit(bitSwapIdx, OrigBit);
+ }
+ if (numBits % 2) {
+ unsigned middle = (numBits + 1) / 2;
+ NewBI->setBit(middle, BI->getBit(middle));
+ }
+
+ // Update the bits in reversed order so that emitInstrOpBits will get the
+ // correct endianness.
+ R->getValue("Inst")->setValue(NewBI);
+ }
+}
+
+
+// If the VarBitInit at position 'bit' matches the specified variable then
+// return the variable bit position. Otherwise return -1.
+int CodeEmitterGen::getVariableBit(const std::string &VarName,
+ BitsInit *BI, int bit) {
+ if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) {
+ TypedInit *TI = VBI->getVariable();
+
+ if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
+ if (VI->getName() == VarName) return VBI->getBitNum();
+ }
+ }
+
+ return -1;
+}
+
+
+void CodeEmitterGen::run(raw_ostream &o) {
+ CodeGenTarget Target;
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+
+ // For little-endian instruction bit encodings, reverse the bit order
+ if (Target.isLittleEndianEncoding()) reverseBits(Insts);
+
+ EmitSourceFileHeader("Machine Code Emitter", o);
+ std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";
+
+ const std::vector<const CodeGenInstruction*> &NumberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ // Emit function declaration
+ o << "unsigned " << Target.getName() << "CodeEmitter::"
+ << "getBinaryCodeForInstr(const MachineInstr &MI) {\n";
+
+ // Emit instruction base values
+ o << " static const unsigned InstBits[] = {\n";
+ for (std::vector<const CodeGenInstruction*>::const_iterator
+ IN = NumberedInstructions.begin(),
+ EN = NumberedInstructions.end();
+ IN != EN; ++IN) {
+ const CodeGenInstruction *CGI = *IN;
+ Record *R = CGI->TheDef;
+
+ if (R->getValueAsString("Namespace") == "TargetOpcode") {
+ o << " 0U,\n";
+ continue;
+ }
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+
+ // Start by filling in fixed values...
+ unsigned Value = 0;
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
+ if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
+ Value |= B->getValue() << (e-i-1);
+ }
+ }
+ o << " " << Value << "U," << '\t' << "// " << R->getName() << "\n";
+ }
+ o << " 0U\n };\n";
+
+ // Map to accumulate all the cases.
+ std::map<std::string, std::vector<std::string> > CaseMap;
+
+ // Construct all cases statement for each opcode
+ for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
+ IC != EC; ++IC) {
+ Record *R = *IC;
+ if (R->getValueAsString("Namespace") == "TargetOpcode")
+ continue;
+ const std::string &InstName = R->getName();
+ std::string Case("");
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+ const std::vector<RecordVal> &Vals = R->getValues();
+ CodeGenInstruction &CGI = Target.getInstruction(R);
+
+ // Loop over all of the fields in the instruction, determining which are the
+ // operands to the instruction.
+ unsigned op = 0;
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
+ // Is the operand continuous? If so, we can just mask and OR it in
+ // instead of doing it bit-by-bit, saving a lot in runtime cost.
+ const std::string &VarName = Vals[i].getName();
+ bool gotOp = false;
+
+ for (int bit = BI->getNumBits()-1; bit >= 0; ) {
+ int varBit = getVariableBit(VarName, BI, bit);
+
+ if (varBit == -1) {
+ --bit;
+ } else {
+ int beginInstBit = bit;
+ int beginVarBit = varBit;
+ int N = 1;
+
+ for (--bit; bit >= 0;) {
+ varBit = getVariableBit(VarName, BI, bit);
+ if (varBit == -1 || varBit != (beginVarBit - N)) break;
+ ++N;
+ --bit;
+ }
+
+ if (!gotOp) {
+ /// If this operand is not supposed to be emitted by the generated
+ /// emitter, skip it.
+ while (CGI.isFlatOperandNotEmitted(op))
+ ++op;
+
+ Case += " // op: " + VarName + "\n"
+ + " op = getMachineOpValue(MI, MI.getOperand("
+ + utostr(op++) + "));\n";
+ gotOp = true;
+ }
+
+ unsigned opMask = ~0U >> (32-N);
+ int opShift = beginVarBit - N + 1;
+ opMask <<= opShift;
+ opShift = beginInstBit - beginVarBit;
+
+ if (opShift > 0) {
+ Case += " Value |= (op & " + utostr(opMask) + "U) << "
+ + itostr(opShift) + ";\n";
+ } else if (opShift < 0) {
+ Case += " Value |= (op & " + utostr(opMask) + "U) >> "
+ + itostr(-opShift) + ";\n";
+ } else {
+ Case += " Value |= op & " + utostr(opMask) + "U;\n";
+ }
+ }
+ }
+ }
+ }
+
+ std::vector<std::string> &InstList = CaseMap[Case];
+ InstList.push_back(InstName);
+ }
+
+
+ // Emit initial function code
+ o << " const unsigned opcode = MI.getOpcode();\n"
+ << " unsigned Value = InstBits[opcode];\n"
+ << " unsigned op = 0;\n"
+ << " op = op; // suppress warning\n"
+ << " switch (opcode) {\n";
+
+ // Emit each case statement
+ std::map<std::string, std::vector<std::string> >::iterator IE, EE;
+ for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
+ const std::string &Case = IE->first;
+ std::vector<std::string> &InstList = IE->second;
+
+ for (int i = 0, N = InstList.size(); i < N; i++) {
+ if (i) o << "\n";
+ o << " case " << Namespace << InstList[i] << ":";
+ }
+ o << " {\n";
+ o << Case;
+ o << " break;\n"
+ << " }\n";
+ }
+
+ // Default case: unhandled opcode
+ o << " default:\n"
+ << " std::string msg;\n"
+ << " raw_string_ostream Msg(msg);\n"
+ << " Msg << \"Not supported instr: \" << MI;\n"
+ << " report_fatal_error(Msg.str());\n"
+ << " }\n"
+ << " return Value;\n"
+ << "}\n\n";
+}
diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.h b/contrib/llvm/utils/TableGen/CodeEmitterGen.h
new file mode 100644
index 0000000..f0b3229
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.h
@@ -0,0 +1,43 @@
+//===- CodeEmitterGen.h - Code Emitter Generator ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// FIXME: document
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEMITTERGEN_H
+#define CODEMITTERGEN_H
+
+#include "TableGenBackend.h"
+#include <map>
+#include <vector>
+#include <string>
+
+namespace llvm {
+
+class RecordVal;
+class BitsInit;
+
+class CodeEmitterGen : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ CodeEmitterGen(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the code emitter
+ void run(raw_ostream &o);
+private:
+ void emitMachineOpEmitter(raw_ostream &o, const std::string &Namespace);
+ void emitGetValueBit(raw_ostream &o, const std::string &Namespace);
+ void reverseBits(std::vector<Record*> &Insts);
+ int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
new file mode 100644
index 0000000..303aa6c
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -0,0 +1,3021 @@
+//===- CodeGenDAGPatterns.cpp - Read DAG patterns from .td file -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the CodeGenDAGPatterns class, which is used to read and
+// represent the patterns present in a .td file for instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenDAGPatterns.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Debug.h"
+#include <set>
+#include <algorithm>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// EEVT::TypeSet Implementation
+//===----------------------------------------------------------------------===//
+
+static inline bool isInteger(MVT::SimpleValueType VT) {
+ return EVT(VT).isInteger();
+}
+static inline bool isFloatingPoint(MVT::SimpleValueType VT) {
+ return EVT(VT).isFloatingPoint();
+}
+static inline bool isVector(MVT::SimpleValueType VT) {
+ return EVT(VT).isVector();
+}
+static inline bool isScalar(MVT::SimpleValueType VT) {
+ return !EVT(VT).isVector();
+}
+
+EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) {
+ if (VT == MVT::iAny)
+ EnforceInteger(TP);
+ else if (VT == MVT::fAny)
+ EnforceFloatingPoint(TP);
+ else if (VT == MVT::vAny)
+ EnforceVector(TP);
+ else {
+ assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR ||
+ VT == MVT::iPTRAny) && "Not a concrete type!");
+ TypeVec.push_back(VT);
+ }
+}
+
+
+EEVT::TypeSet::TypeSet(const std::vector<MVT::SimpleValueType> &VTList) {
+ assert(!VTList.empty() && "empty list?");
+ TypeVec.append(VTList.begin(), VTList.end());
+
+ if (!VTList.empty())
+ assert(VTList[0] != MVT::iAny && VTList[0] != MVT::vAny &&
+ VTList[0] != MVT::fAny);
+
+ // Verify no duplicates.
+ array_pod_sort(TypeVec.begin(), TypeVec.end());
+ assert(std::unique(TypeVec.begin(), TypeVec.end()) == TypeVec.end());
+}
+
+/// FillWithPossibleTypes - Set to all legal types and return true, only valid
+/// on completely unknown type sets.
+bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP,
+ bool (*Pred)(MVT::SimpleValueType),
+ const char *PredicateName) {
+ assert(isCompletelyUnknown());
+ const std::vector<MVT::SimpleValueType> &LegalTypes =
+ TP.getDAGPatterns().getTargetInfo().getLegalValueTypes();
+
+ for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i)
+ if (Pred == 0 || Pred(LegalTypes[i]))
+ TypeVec.push_back(LegalTypes[i]);
+
+ // If we have nothing that matches the predicate, bail out.
+ if (TypeVec.empty())
+ TP.error("Type inference contradiction found, no " +
+ std::string(PredicateName) + " types found");
+ // No need to sort with one element.
+ if (TypeVec.size() == 1) return true;
+
+ // Remove duplicates.
+ array_pod_sort(TypeVec.begin(), TypeVec.end());
+ TypeVec.erase(std::unique(TypeVec.begin(), TypeVec.end()), TypeVec.end());
+
+ return true;
+}
+
+/// hasIntegerTypes - Return true if this TypeSet contains iAny or an
+/// integer value type.
+bool EEVT::TypeSet::hasIntegerTypes() const {
+ for (unsigned i = 0, e = TypeVec.size(); i != e; ++i)
+ if (isInteger(TypeVec[i]))
+ return true;
+ return false;
+}
+
+/// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
+/// a floating point value type.
+bool EEVT::TypeSet::hasFloatingPointTypes() const {
+ for (unsigned i = 0, e = TypeVec.size(); i != e; ++i)
+ if (isFloatingPoint(TypeVec[i]))
+ return true;
+ return false;
+}
+
+/// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector
+/// value type.
+bool EEVT::TypeSet::hasVectorTypes() const {
+ for (unsigned i = 0, e = TypeVec.size(); i != e; ++i)
+ if (isVector(TypeVec[i]))
+ return true;
+ return false;
+}
+
+
+std::string EEVT::TypeSet::getName() const {
+ if (TypeVec.empty()) return "<empty>";
+
+ std::string Result;
+
+ for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) {
+ std::string VTName = llvm::getEnumName(TypeVec[i]);
+ // Strip off MVT:: prefix if present.
+ if (VTName.substr(0,5) == "MVT::")
+ VTName = VTName.substr(5);
+ if (i) Result += ':';
+ Result += VTName;
+ }
+
+ if (TypeVec.size() == 1)
+ return Result;
+ return "{" + Result + "}";
+}
+
+/// MergeInTypeInfo - This merges in type information from the specified
+/// argument. If 'this' changes, it returns true. If the two types are
+/// contradictory (e.g. merge f32 into i32) then this throws an exception.
+bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){
+ if (InVT.isCompletelyUnknown() || *this == InVT)
+ return false;
+
+ if (isCompletelyUnknown()) {
+ *this = InVT;
+ return true;
+ }
+
+ assert(TypeVec.size() >= 1 && InVT.TypeVec.size() >= 1 && "No unknowns");
+
+ // Handle the abstract cases, seeing if we can resolve them better.
+ switch (TypeVec[0]) {
+ default: break;
+ case MVT::iPTR:
+ case MVT::iPTRAny:
+ if (InVT.hasIntegerTypes()) {
+ EEVT::TypeSet InCopy(InVT);
+ InCopy.EnforceInteger(TP);
+ InCopy.EnforceScalar(TP);
+
+ if (InCopy.isConcrete()) {
+ // If the RHS has one integer type, upgrade iPTR to i32.
+ TypeVec[0] = InVT.TypeVec[0];
+ return true;
+ }
+
+ // If the input has multiple scalar integers, this doesn't add any info.
+ if (!InCopy.isCompletelyUnknown())
+ return false;
+ }
+ break;
+ }
+
+ // If the input constraint is iAny/iPTR and this is an integer type list,
+ // remove non-integer types from the list.
+ if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) &&
+ hasIntegerTypes()) {
+ bool MadeChange = EnforceInteger(TP);
+
+ // If we're merging in iPTR/iPTRAny and the node currently has a list of
+ // multiple different integer types, replace them with a single iPTR.
+ if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) &&
+ TypeVec.size() != 1) {
+ TypeVec.resize(1);
+ TypeVec[0] = InVT.TypeVec[0];
+ MadeChange = true;
+ }
+
+ return MadeChange;
+ }
+
+ // If this is a type list and the RHS is a typelist as well, eliminate entries
+ // from this list that aren't in the other one.
+ bool MadeChange = false;
+ TypeSet InputSet(*this);
+
+ for (unsigned i = 0; i != TypeVec.size(); ++i) {
+ bool InInVT = false;
+ for (unsigned j = 0, e = InVT.TypeVec.size(); j != e; ++j)
+ if (TypeVec[i] == InVT.TypeVec[j]) {
+ InInVT = true;
+ break;
+ }
+
+ if (InInVT) continue;
+ TypeVec.erase(TypeVec.begin()+i--);
+ MadeChange = true;
+ }
+
+ // If we removed all of our types, we have a type contradiction.
+ if (!TypeVec.empty())
+ return MadeChange;
+
+ // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, merging '" +
+ InVT.getName() + "' into '" + InputSet.getName() + "'");
+ return true; // unreachable
+}
+
+/// EnforceInteger - Remove all non-integer types from this set.
+bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) {
+ // If we know nothing, then get the full set.
+ if (TypeVec.empty())
+ return FillWithPossibleTypes(TP, isInteger, "integer");
+ if (!hasFloatingPointTypes())
+ return false;
+
+ TypeSet InputSet(*this);
+
+ // Filter out all the fp types.
+ for (unsigned i = 0; i != TypeVec.size(); ++i)
+ if (!isInteger(TypeVec[i]))
+ TypeVec.erase(TypeVec.begin()+i--);
+
+ if (TypeVec.empty())
+ TP.error("Type inference contradiction found, '" +
+ InputSet.getName() + "' needs to be integer");
+ return true;
+}
+
+/// EnforceFloatingPoint - Remove all integer types from this set.
+bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) {
+ // If we know nothing, then get the full set.
+ if (TypeVec.empty())
+ return FillWithPossibleTypes(TP, isFloatingPoint, "floating point");
+
+ if (!hasIntegerTypes())
+ return false;
+
+ TypeSet InputSet(*this);
+
+ // Filter out all the fp types.
+ for (unsigned i = 0; i != TypeVec.size(); ++i)
+ if (!isFloatingPoint(TypeVec[i]))
+ TypeVec.erase(TypeVec.begin()+i--);
+
+ if (TypeVec.empty())
+ TP.error("Type inference contradiction found, '" +
+ InputSet.getName() + "' needs to be floating point");
+ return true;
+}
+
+/// EnforceScalar - Remove all vector types from this.
+bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) {
+ // If we know nothing, then get the full set.
+ if (TypeVec.empty())
+ return FillWithPossibleTypes(TP, isScalar, "scalar");
+
+ if (!hasVectorTypes())
+ return false;
+
+ TypeSet InputSet(*this);
+
+ // Filter out all the vector types.
+ for (unsigned i = 0; i != TypeVec.size(); ++i)
+ if (!isScalar(TypeVec[i]))
+ TypeVec.erase(TypeVec.begin()+i--);
+
+ if (TypeVec.empty())
+ TP.error("Type inference contradiction found, '" +
+ InputSet.getName() + "' needs to be scalar");
+ return true;
+}
+
+/// EnforceVector - Remove all vector types from this.
+bool EEVT::TypeSet::EnforceVector(TreePattern &TP) {
+ // If we know nothing, then get the full set.
+ if (TypeVec.empty())
+ return FillWithPossibleTypes(TP, isVector, "vector");
+
+ TypeSet InputSet(*this);
+ bool MadeChange = false;
+
+ // Filter out all the scalar types.
+ for (unsigned i = 0; i != TypeVec.size(); ++i)
+ if (!isVector(TypeVec[i])) {
+ TypeVec.erase(TypeVec.begin()+i--);
+ MadeChange = true;
+ }
+
+ if (TypeVec.empty())
+ TP.error("Type inference contradiction found, '" +
+ InputSet.getName() + "' needs to be a vector");
+ return MadeChange;
+}
+
+
+
+/// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update
+/// this an other based on this information.
+bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
+ // Both operands must be integer or FP, but we don't care which.
+ bool MadeChange = false;
+
+ if (isCompletelyUnknown())
+ MadeChange = FillWithPossibleTypes(TP);
+
+ if (Other.isCompletelyUnknown())
+ MadeChange = Other.FillWithPossibleTypes(TP);
+
+ // If one side is known to be integer or known to be FP but the other side has
+ // no information, get at least the type integrality info in there.
+ if (!hasFloatingPointTypes())
+ MadeChange |= Other.EnforceInteger(TP);
+ else if (!hasIntegerTypes())
+ MadeChange |= Other.EnforceFloatingPoint(TP);
+ if (!Other.hasFloatingPointTypes())
+ MadeChange |= EnforceInteger(TP);
+ else if (!Other.hasIntegerTypes())
+ MadeChange |= EnforceFloatingPoint(TP);
+
+ assert(!isCompletelyUnknown() && !Other.isCompletelyUnknown() &&
+ "Should have a type list now");
+
+ // If one contains vectors but the other doesn't pull vectors out.
+ if (!hasVectorTypes())
+ MadeChange |= Other.EnforceScalar(TP);
+ if (!hasVectorTypes())
+ MadeChange |= EnforceScalar(TP);
+
+ // This code does not currently handle nodes which have multiple types,
+ // where some types are integer, and some are fp. Assert that this is not
+ // the case.
+ assert(!(hasIntegerTypes() && hasFloatingPointTypes()) &&
+ !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) &&
+ "SDTCisOpSmallerThanOp does not handle mixed int/fp types!");
+
+ // Okay, find the smallest type from the current set and remove it from the
+ // largest set.
+ MVT::SimpleValueType Smallest = TypeVec[0];
+ for (unsigned i = 1, e = TypeVec.size(); i != e; ++i)
+ if (TypeVec[i] < Smallest)
+ Smallest = TypeVec[i];
+
+ // If this is the only type in the large set, the constraint can never be
+ // satisfied.
+ if (Other.TypeVec.size() == 1 && Other.TypeVec[0] == Smallest)
+ TP.error("Type inference contradiction found, '" +
+ Other.getName() + "' has nothing larger than '" + getName() +"'!");
+
+ SmallVector<MVT::SimpleValueType, 2>::iterator TVI =
+ std::find(Other.TypeVec.begin(), Other.TypeVec.end(), Smallest);
+ if (TVI != Other.TypeVec.end()) {
+ Other.TypeVec.erase(TVI);
+ MadeChange = true;
+ }
+
+ // Okay, find the largest type in the Other set and remove it from the
+ // current set.
+ MVT::SimpleValueType Largest = Other.TypeVec[0];
+ for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i)
+ if (Other.TypeVec[i] > Largest)
+ Largest = Other.TypeVec[i];
+
+ // If this is the only type in the small set, the constraint can never be
+ // satisfied.
+ if (TypeVec.size() == 1 && TypeVec[0] == Largest)
+ TP.error("Type inference contradiction found, '" +
+ getName() + "' has nothing smaller than '" + Other.getName()+"'!");
+
+ TVI = std::find(TypeVec.begin(), TypeVec.end(), Largest);
+ if (TVI != TypeVec.end()) {
+ TypeVec.erase(TVI);
+ MadeChange = true;
+ }
+
+ return MadeChange;
+}
+
+/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
+/// whose element is specified by VTOperand.
+bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
+ TreePattern &TP) {
+ // "This" must be a vector and "VTOperand" must be a scalar.
+ bool MadeChange = false;
+ MadeChange |= EnforceVector(TP);
+ MadeChange |= VTOperand.EnforceScalar(TP);
+
+ // If we know the vector type, it forces the scalar to agree.
+ if (isConcrete()) {
+ EVT IVT = getConcrete();
+ IVT = IVT.getVectorElementType();
+ return MadeChange |
+ VTOperand.MergeInTypeInfo(IVT.getSimpleVT().SimpleTy, TP);
+ }
+
+ // If the scalar type is known, filter out vector types whose element types
+ // disagree.
+ if (!VTOperand.isConcrete())
+ return MadeChange;
+
+ MVT::SimpleValueType VT = VTOperand.getConcrete();
+
+ TypeSet InputSet(*this);
+
+ // Filter out all the types which don't have the right element type.
+ for (unsigned i = 0; i != TypeVec.size(); ++i) {
+ assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
+ if (EVT(TypeVec[i]).getVectorElementType().getSimpleVT().SimpleTy != VT) {
+ TypeVec.erase(TypeVec.begin()+i--);
+ MadeChange = true;
+ }
+ }
+
+ if (TypeVec.empty()) // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have a vector element");
+ return MadeChange;
+}
+
+//===----------------------------------------------------------------------===//
+// Helpers for working with extended types.
+
+bool RecordPtrCmp::operator()(const Record *LHS, const Record *RHS) const {
+ return LHS->getID() < RHS->getID();
+}
+
+/// Dependent variable map for CodeGenDAGPattern variant generation
+typedef std::map<std::string, int> DepVarMap;
+
+/// Const iterator shorthand for DepVarMap
+typedef DepVarMap::const_iterator DepVarMap_citer;
+
+namespace {
+void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) {
+ if (N->isLeaf()) {
+ if (dynamic_cast<DefInit*>(N->getLeafValue()) != NULL) {
+ DepMap[N->getName()]++;
+ }
+ } else {
+ for (size_t i = 0, e = N->getNumChildren(); i != e; ++i)
+ FindDepVarsOf(N->getChild(i), DepMap);
+ }
+}
+
+//! Find dependent variables within child patterns
+/*!
+ */
+void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) {
+ DepVarMap depcounts;
+ FindDepVarsOf(N, depcounts);
+ for (DepVarMap_citer i = depcounts.begin(); i != depcounts.end(); ++i) {
+ if (i->second > 1) { // std::pair<std::string, int>
+ DepVars.insert(i->first);
+ }
+ }
+}
+
+//! Dump the dependent variable set:
+void DumpDepVars(MultipleUseVarSet &DepVars) {
+ if (DepVars.empty()) {
+ DEBUG(errs() << "<empty set>");
+ } else {
+ DEBUG(errs() << "[ ");
+ for (MultipleUseVarSet::const_iterator i = DepVars.begin(), e = DepVars.end();
+ i != e; ++i) {
+ DEBUG(errs() << (*i) << " ");
+ }
+ DEBUG(errs() << "]");
+ }
+}
+}
+
+//===----------------------------------------------------------------------===//
+// PatternToMatch implementation
+//
+
+
+/// getPatternSize - Return the 'size' of this pattern. We want to match large
+/// patterns before small ones. This is used to determine the size of a
+/// pattern.
+static unsigned getPatternSize(const TreePatternNode *P,
+ const CodeGenDAGPatterns &CGP) {
+ unsigned Size = 3; // The node itself.
+ // If the root node is a ConstantSDNode, increases its size.
+ // e.g. (set R32:$dst, 0).
+ if (P->isLeaf() && dynamic_cast<IntInit*>(P->getLeafValue()))
+ Size += 2;
+
+ // FIXME: This is a hack to statically increase the priority of patterns
+ // which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD.
+ // Later we can allow complexity / cost for each pattern to be (optionally)
+ // specified. To get best possible pattern match we'll need to dynamically
+ // calculate the complexity of all patterns a dag can potentially map to.
+ const ComplexPattern *AM = P->getComplexPatternInfo(CGP);
+ if (AM)
+ Size += AM->getNumOperands() * 3;
+
+ // If this node has some predicate function that must match, it adds to the
+ // complexity of this node.
+ if (!P->getPredicateFns().empty())
+ ++Size;
+
+ // Count children in the count if they are also nodes.
+ for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = P->getChild(i);
+ if (!Child->isLeaf() && Child->getNumTypes() &&
+ Child->getType(0) != MVT::Other)
+ Size += getPatternSize(Child, CGP);
+ else if (Child->isLeaf()) {
+ if (dynamic_cast<IntInit*>(Child->getLeafValue()))
+ Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
+ else if (Child->getComplexPatternInfo(CGP))
+ Size += getPatternSize(Child, CGP);
+ else if (!Child->getPredicateFns().empty())
+ ++Size;
+ }
+ }
+
+ return Size;
+}
+
+/// Compute the complexity metric for the input pattern. This roughly
+/// corresponds to the number of nodes that are covered.
+unsigned PatternToMatch::
+getPatternComplexity(const CodeGenDAGPatterns &CGP) const {
+ return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity();
+}
+
+
+/// getPredicateCheck - Return a single string containing all of this
+/// pattern's predicates concatenated with "&&" operators.
+///
+std::string PatternToMatch::getPredicateCheck() const {
+ std::string PredicateCheck;
+ for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
+ if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
+ Record *Def = Pred->getDef();
+ if (!Def->isSubClassOf("Predicate")) {
+#ifndef NDEBUG
+ Def->dump();
+#endif
+ assert(0 && "Unknown predicate type!");
+ }
+ if (!PredicateCheck.empty())
+ PredicateCheck += " && ";
+ PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";
+ }
+ }
+
+ return PredicateCheck;
+}
+
+//===----------------------------------------------------------------------===//
+// SDTypeConstraint implementation
+//
+
+SDTypeConstraint::SDTypeConstraint(Record *R) {
+ OperandNo = R->getValueAsInt("OperandNum");
+
+ if (R->isSubClassOf("SDTCisVT")) {
+ ConstraintType = SDTCisVT;
+ x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
+ if (x.SDTCisVT_Info.VT == MVT::isVoid)
+ throw TGError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT");
+
+ } else if (R->isSubClassOf("SDTCisPtrTy")) {
+ ConstraintType = SDTCisPtrTy;
+ } else if (R->isSubClassOf("SDTCisInt")) {
+ ConstraintType = SDTCisInt;
+ } else if (R->isSubClassOf("SDTCisFP")) {
+ ConstraintType = SDTCisFP;
+ } else if (R->isSubClassOf("SDTCisVec")) {
+ ConstraintType = SDTCisVec;
+ } else if (R->isSubClassOf("SDTCisSameAs")) {
+ ConstraintType = SDTCisSameAs;
+ x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum");
+ } else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) {
+ ConstraintType = SDTCisVTSmallerThanOp;
+ x.SDTCisVTSmallerThanOp_Info.OtherOperandNum =
+ R->getValueAsInt("OtherOperandNum");
+ } else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) {
+ ConstraintType = SDTCisOpSmallerThanOp;
+ x.SDTCisOpSmallerThanOp_Info.BigOperandNum =
+ R->getValueAsInt("BigOperandNum");
+ } else if (R->isSubClassOf("SDTCisEltOfVec")) {
+ ConstraintType = SDTCisEltOfVec;
+ x.SDTCisEltOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum");
+ } else {
+ errs() << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n";
+ exit(1);
+ }
+}
+
+/// getOperandNum - Return the node corresponding to operand #OpNo in tree
+/// N, and the result number in ResNo.
+static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N,
+ const SDNodeInfo &NodeInfo,
+ unsigned &ResNo) {
+ unsigned NumResults = NodeInfo.getNumResults();
+ if (OpNo < NumResults) {
+ ResNo = OpNo;
+ return N;
+ }
+
+ OpNo -= NumResults;
+
+ if (OpNo >= N->getNumChildren()) {
+ errs() << "Invalid operand number in type constraint "
+ << (OpNo+NumResults) << " ";
+ N->dump();
+ errs() << '\n';
+ exit(1);
+ }
+
+ return N->getChild(OpNo);
+}
+
+/// ApplyTypeConstraint - Given a node in a pattern, apply this type
+/// constraint to the nodes operands. This returns true if it makes a
+/// change, false otherwise. If a type contradiction is found, throw an
+/// exception.
+bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
+ const SDNodeInfo &NodeInfo,
+ TreePattern &TP) const {
+ unsigned ResNo = 0; // The result number being referenced.
+ TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo);
+
+ switch (ConstraintType) {
+ default: assert(0 && "Unknown constraint type!");
+ case SDTCisVT:
+ // Operand must be a particular type.
+ return NodeToApply->UpdateNodeType(ResNo, x.SDTCisVT_Info.VT, TP);
+ case SDTCisPtrTy:
+ // Operand must be same as target pointer type.
+ return NodeToApply->UpdateNodeType(ResNo, MVT::iPTR, TP);
+ case SDTCisInt:
+ // Require it to be one of the legal integer VTs.
+ return NodeToApply->getExtType(ResNo).EnforceInteger(TP);
+ case SDTCisFP:
+ // Require it to be one of the legal fp VTs.
+ return NodeToApply->getExtType(ResNo).EnforceFloatingPoint(TP);
+ case SDTCisVec:
+ // Require it to be one of the legal vector VTs.
+ return NodeToApply->getExtType(ResNo).EnforceVector(TP);
+ case SDTCisSameAs: {
+ unsigned OResNo = 0;
+ TreePatternNode *OtherNode =
+ getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo);
+ return NodeToApply->UpdateNodeType(OResNo, OtherNode->getExtType(ResNo),TP)|
+ OtherNode->UpdateNodeType(ResNo,NodeToApply->getExtType(OResNo),TP);
+ }
+ case SDTCisVTSmallerThanOp: {
+ // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must
+ // have an integer type that is smaller than the VT.
+ if (!NodeToApply->isLeaf() ||
+ !dynamic_cast<DefInit*>(NodeToApply->getLeafValue()) ||
+ !static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()
+ ->isSubClassOf("ValueType"))
+ TP.error(N->getOperator()->getName() + " expects a VT operand!");
+ MVT::SimpleValueType VT =
+ getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef());
+
+ EEVT::TypeSet TypeListTmp(VT, TP);
+
+ unsigned OResNo = 0;
+ TreePatternNode *OtherNode =
+ getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo,
+ OResNo);
+
+ return TypeListTmp.EnforceSmallerThan(OtherNode->getExtType(OResNo), TP);
+ }
+ case SDTCisOpSmallerThanOp: {
+ unsigned BResNo = 0;
+ TreePatternNode *BigOperand =
+ getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NodeInfo,
+ BResNo);
+ return NodeToApply->getExtType(ResNo).
+ EnforceSmallerThan(BigOperand->getExtType(BResNo), TP);
+ }
+ case SDTCisEltOfVec: {
+ unsigned VResNo = 0;
+ TreePatternNode *VecOperand =
+ getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo,
+ VResNo);
+
+ // Filter vector types out of VecOperand that don't have the right element
+ // type.
+ return VecOperand->getExtType(VResNo).
+ EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), TP);
+ }
+ }
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// SDNodeInfo implementation
+//
+SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
+ EnumName = R->getValueAsString("Opcode");
+ SDClassName = R->getValueAsString("SDClass");
+ Record *TypeProfile = R->getValueAsDef("TypeProfile");
+ NumResults = TypeProfile->getValueAsInt("NumResults");
+ NumOperands = TypeProfile->getValueAsInt("NumOperands");
+
+ // Parse the properties.
+ Properties = 0;
+ std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
+ for (unsigned i = 0, e = PropList.size(); i != e; ++i) {
+ if (PropList[i]->getName() == "SDNPCommutative") {
+ Properties |= 1 << SDNPCommutative;
+ } else if (PropList[i]->getName() == "SDNPAssociative") {
+ Properties |= 1 << SDNPAssociative;
+ } else if (PropList[i]->getName() == "SDNPHasChain") {
+ Properties |= 1 << SDNPHasChain;
+ } else if (PropList[i]->getName() == "SDNPOutFlag") {
+ Properties |= 1 << SDNPOutFlag;
+ } else if (PropList[i]->getName() == "SDNPInFlag") {
+ Properties |= 1 << SDNPInFlag;
+ } else if (PropList[i]->getName() == "SDNPOptInFlag") {
+ Properties |= 1 << SDNPOptInFlag;
+ } else if (PropList[i]->getName() == "SDNPMayStore") {
+ Properties |= 1 << SDNPMayStore;
+ } else if (PropList[i]->getName() == "SDNPMayLoad") {
+ Properties |= 1 << SDNPMayLoad;
+ } else if (PropList[i]->getName() == "SDNPSideEffect") {
+ Properties |= 1 << SDNPSideEffect;
+ } else if (PropList[i]->getName() == "SDNPMemOperand") {
+ Properties |= 1 << SDNPMemOperand;
+ } else if (PropList[i]->getName() == "SDNPVariadic") {
+ Properties |= 1 << SDNPVariadic;
+ } else {
+ errs() << "Unknown SD Node property '" << PropList[i]->getName()
+ << "' on node '" << R->getName() << "'!\n";
+ exit(1);
+ }
+ }
+
+
+ // Parse the type constraints.
+ std::vector<Record*> ConstraintList =
+ TypeProfile->getValueAsListOfDefs("Constraints");
+ TypeConstraints.assign(ConstraintList.begin(), ConstraintList.end());
+}
+
+/// getKnownType - If the type constraints on this node imply a fixed type
+/// (e.g. all stores return void, etc), then return it as an
+/// MVT::SimpleValueType. Otherwise, return EEVT::Other.
+MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const {
+ unsigned NumResults = getNumResults();
+ assert(NumResults <= 1 &&
+ "We only work with nodes with zero or one result so far!");
+ assert(ResNo == 0 && "Only handles single result nodes so far");
+
+ for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) {
+ // Make sure that this applies to the correct node result.
+ if (TypeConstraints[i].OperandNo >= NumResults) // FIXME: need value #
+ continue;
+
+ switch (TypeConstraints[i].ConstraintType) {
+ default: break;
+ case SDTypeConstraint::SDTCisVT:
+ return TypeConstraints[i].x.SDTCisVT_Info.VT;
+ case SDTypeConstraint::SDTCisPtrTy:
+ return MVT::iPTR;
+ }
+ }
+ return MVT::Other;
+}
+
+//===----------------------------------------------------------------------===//
+// TreePatternNode implementation
+//
+
+TreePatternNode::~TreePatternNode() {
+#if 0 // FIXME: implement refcounted tree nodes!
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ delete getChild(i);
+#endif
+}
+
+static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
+ if (Operator->getName() == "set" ||
+ Operator->getName() == "implicit")
+ return 0; // All return nothing.
+
+ if (Operator->isSubClassOf("Intrinsic"))
+ return CDP.getIntrinsic(Operator).IS.RetVTs.size();
+
+ if (Operator->isSubClassOf("SDNode"))
+ return CDP.getSDNodeInfo(Operator).getNumResults();
+
+ if (Operator->isSubClassOf("PatFrag")) {
+ // If we've already parsed this pattern fragment, get it. Otherwise, handle
+ // the forward reference case where one pattern fragment references another
+ // before it is processed.
+ if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator))
+ return PFRec->getOnlyTree()->getNumTypes();
+
+ // Get the result tree.
+ DagInit *Tree = Operator->getValueAsDag("Fragment");
+ Record *Op = 0;
+ if (Tree && dynamic_cast<DefInit*>(Tree->getOperator()))
+ Op = dynamic_cast<DefInit*>(Tree->getOperator())->getDef();
+ assert(Op && "Invalid Fragment");
+ return GetNumNodeResults(Op, CDP);
+ }
+
+ if (Operator->isSubClassOf("Instruction")) {
+ CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator);
+
+ // FIXME: Should allow access to all the results here.
+ unsigned NumDefsToAdd = InstInfo.NumDefs ? 1 : 0;
+
+ // Add on one implicit def if it has a resolvable type.
+ if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other)
+ ++NumDefsToAdd;
+ return NumDefsToAdd;
+ }
+
+ if (Operator->isSubClassOf("SDNodeXForm"))
+ return 1; // FIXME: Generalize SDNodeXForm
+
+ Operator->dump();
+ errs() << "Unhandled node in GetNumNodeResults\n";
+ exit(1);
+}
+
+void TreePatternNode::print(raw_ostream &OS) const {
+ if (isLeaf())
+ OS << *getLeafValue();
+ else
+ OS << '(' << getOperator()->getName();
+
+ for (unsigned i = 0, e = Types.size(); i != e; ++i)
+ OS << ':' << getExtType(i).getName();
+
+ if (!isLeaf()) {
+ if (getNumChildren() != 0) {
+ OS << " ";
+ getChild(0)->print(OS);
+ for (unsigned i = 1, e = getNumChildren(); i != e; ++i) {
+ OS << ", ";
+ getChild(i)->print(OS);
+ }
+ }
+ OS << ")";
+ }
+
+ for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i)
+ OS << "<<P:" << PredicateFns[i] << ">>";
+ if (TransformFn)
+ OS << "<<X:" << TransformFn->getName() << ">>";
+ if (!getName().empty())
+ OS << ":$" << getName();
+
+}
+void TreePatternNode::dump() const {
+ print(errs());
+}
+
+/// isIsomorphicTo - Return true if this node is recursively
+/// isomorphic to the specified node. For this comparison, the node's
+/// entire state is considered. The assigned name is ignored, since
+/// nodes with differing names are considered isomorphic. However, if
+/// the assigned name is present in the dependent variable set, then
+/// the assigned name is considered significant and the node is
+/// isomorphic if the names match.
+bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N,
+ const MultipleUseVarSet &DepVars) const {
+ if (N == this) return true;
+ if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() ||
+ getPredicateFns() != N->getPredicateFns() ||
+ getTransformFn() != N->getTransformFn())
+ return false;
+
+ if (isLeaf()) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue())) {
+ if (DefInit *NDI = dynamic_cast<DefInit*>(N->getLeafValue())) {
+ return ((DI->getDef() == NDI->getDef())
+ && (DepVars.find(getName()) == DepVars.end()
+ || getName() == N->getName()));
+ }
+ }
+ return getLeafValue() == N->getLeafValue();
+ }
+
+ if (N->getOperator() != getOperator() ||
+ N->getNumChildren() != getNumChildren()) return false;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (!getChild(i)->isIsomorphicTo(N->getChild(i), DepVars))
+ return false;
+ return true;
+}
+
+/// clone - Make a copy of this tree and all of its children.
+///
+TreePatternNode *TreePatternNode::clone() const {
+ TreePatternNode *New;
+ if (isLeaf()) {
+ New = new TreePatternNode(getLeafValue(), getNumTypes());
+ } else {
+ std::vector<TreePatternNode*> CChildren;
+ CChildren.reserve(Children.size());
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ CChildren.push_back(getChild(i)->clone());
+ New = new TreePatternNode(getOperator(), CChildren, getNumTypes());
+ }
+ New->setName(getName());
+ New->Types = Types;
+ New->setPredicateFns(getPredicateFns());
+ New->setTransformFn(getTransformFn());
+ return New;
+}
+
+/// RemoveAllTypes - Recursively strip all the types of this tree.
+void TreePatternNode::RemoveAllTypes() {
+ for (unsigned i = 0, e = Types.size(); i != e; ++i)
+ Types[i] = EEVT::TypeSet(); // Reset to unknown type.
+ if (isLeaf()) return;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ getChild(i)->RemoveAllTypes();
+}
+
+
+/// SubstituteFormalArguments - Replace the formal arguments in this tree
+/// with actual values specified by ArgMap.
+void TreePatternNode::
+SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) {
+ if (isLeaf()) return;
+
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = getChild(i);
+ if (Child->isLeaf()) {
+ Init *Val = Child->getLeafValue();
+ if (dynamic_cast<DefInit*>(Val) &&
+ static_cast<DefInit*>(Val)->getDef()->getName() == "node") {
+ // We found a use of a formal argument, replace it with its value.
+ TreePatternNode *NewChild = ArgMap[Child->getName()];
+ assert(NewChild && "Couldn't find formal argument!");
+ assert((Child->getPredicateFns().empty() ||
+ NewChild->getPredicateFns() == Child->getPredicateFns()) &&
+ "Non-empty child predicate clobbered!");
+ setChild(i, NewChild);
+ }
+ } else {
+ getChild(i)->SubstituteFormalArguments(ArgMap);
+ }
+ }
+}
+
+
+/// InlinePatternFragments - If this pattern refers to any pattern
+/// fragments, inline them into place, giving us a pattern without any
+/// PatFrag references.
+TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
+ if (isLeaf()) return this; // nothing to do.
+ Record *Op = getOperator();
+
+ if (!Op->isSubClassOf("PatFrag")) {
+ // Just recursively inline children nodes.
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = getChild(i);
+ TreePatternNode *NewChild = Child->InlinePatternFragments(TP);
+
+ assert((Child->getPredicateFns().empty() ||
+ NewChild->getPredicateFns() == Child->getPredicateFns()) &&
+ "Non-empty child predicate clobbered!");
+
+ setChild(i, NewChild);
+ }
+ return this;
+ }
+
+ // Otherwise, we found a reference to a fragment. First, look up its
+ // TreePattern record.
+ TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op);
+
+ // Verify that we are passing the right number of operands.
+ if (Frag->getNumArgs() != Children.size())
+ TP.error("'" + Op->getName() + "' fragment requires " +
+ utostr(Frag->getNumArgs()) + " operands!");
+
+ TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
+
+ std::string Code = Op->getValueAsCode("Predicate");
+ if (!Code.empty())
+ FragTree->addPredicateFn("Predicate_"+Op->getName());
+
+ // Resolve formal arguments to their actual value.
+ if (Frag->getNumArgs()) {
+ // Compute the map of formal to actual arguments.
+ std::map<std::string, TreePatternNode*> ArgMap;
+ for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i)
+ ArgMap[Frag->getArgName(i)] = getChild(i)->InlinePatternFragments(TP);
+
+ FragTree->SubstituteFormalArguments(ArgMap);
+ }
+
+ FragTree->setName(getName());
+ for (unsigned i = 0, e = Types.size(); i != e; ++i)
+ FragTree->UpdateNodeType(i, getExtType(i), TP);
+
+ // Transfer in the old predicates.
+ for (unsigned i = 0, e = getPredicateFns().size(); i != e; ++i)
+ FragTree->addPredicateFn(getPredicateFns()[i]);
+
+ // Get a new copy of this fragment to stitch into here.
+ //delete this; // FIXME: implement refcounting!
+
+ // The fragment we inlined could have recursive inlining that is needed. See
+ // if there are any pattern fragments in it and inline them as needed.
+ return FragTree->InlinePatternFragments(TP);
+}
+
+/// getImplicitType - Check to see if the specified record has an implicit
+/// type which should be applied to it. This will infer the type of register
+/// references from the register file information, for example.
+///
+static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
+ bool NotRegisters, TreePattern &TP) {
+ // Check to see if this is a register or a register class.
+ if (R->isSubClassOf("RegisterClass")) {
+ assert(ResNo == 0 && "Regclass ref only has one result!");
+ if (NotRegisters)
+ return EEVT::TypeSet(); // Unknown.
+ const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
+ return EEVT::TypeSet(T.getRegisterClass(R).getValueTypes());
+ }
+
+ if (R->isSubClassOf("PatFrag")) {
+ assert(ResNo == 0 && "FIXME: PatFrag with multiple results?");
+ // Pattern fragment types will be resolved when they are inlined.
+ return EEVT::TypeSet(); // Unknown.
+ }
+
+ if (R->isSubClassOf("Register")) {
+ assert(ResNo == 0 && "Registers only produce one result!");
+ if (NotRegisters)
+ return EEVT::TypeSet(); // Unknown.
+ const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
+ return EEVT::TypeSet(T.getRegisterVTs(R));
+ }
+
+ if (R->isSubClassOf("SubRegIndex")) {
+ assert(ResNo == 0 && "SubRegisterIndices only produce one result!");
+ return EEVT::TypeSet();
+ }
+
+ if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
+ assert(ResNo == 0 && "This node only has one result!");
+ // Using a VTSDNode or CondCodeSDNode.
+ return EEVT::TypeSet(MVT::Other, TP);
+ }
+
+ if (R->isSubClassOf("ComplexPattern")) {
+ assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?");
+ if (NotRegisters)
+ return EEVT::TypeSet(); // Unknown.
+ return EEVT::TypeSet(TP.getDAGPatterns().getComplexPattern(R).getValueType(),
+ TP);
+ }
+ if (R->isSubClassOf("PointerLikeRegClass")) {
+ assert(ResNo == 0 && "Regclass can only have one result!");
+ return EEVT::TypeSet(MVT::iPTR, TP);
+ }
+
+ if (R->getName() == "node" || R->getName() == "srcvalue" ||
+ R->getName() == "zero_reg") {
+ // Placeholder.
+ return EEVT::TypeSet(); // Unknown.
+ }
+
+ TP.error("Unknown node flavor used in pattern: " + R->getName());
+ return EEVT::TypeSet(MVT::Other, TP);
+}
+
+
+/// getIntrinsicInfo - If this node corresponds to an intrinsic, return the
+/// CodeGenIntrinsic information for it, otherwise return a null pointer.
+const CodeGenIntrinsic *TreePatternNode::
+getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const {
+ if (getOperator() != CDP.get_intrinsic_void_sdnode() &&
+ getOperator() != CDP.get_intrinsic_w_chain_sdnode() &&
+ getOperator() != CDP.get_intrinsic_wo_chain_sdnode())
+ return 0;
+
+ unsigned IID =
+ dynamic_cast<IntInit*>(getChild(0)->getLeafValue())->getValue();
+ return &CDP.getIntrinsicInfo(IID);
+}
+
+/// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
+/// return the ComplexPattern information, otherwise return null.
+const ComplexPattern *
+TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const {
+ if (!isLeaf()) return 0;
+
+ DefInit *DI = dynamic_cast<DefInit*>(getLeafValue());
+ if (DI && DI->getDef()->isSubClassOf("ComplexPattern"))
+ return &CGP.getComplexPattern(DI->getDef());
+ return 0;
+}
+
+/// NodeHasProperty - Return true if this node has the specified property.
+bool TreePatternNode::NodeHasProperty(SDNP Property,
+ const CodeGenDAGPatterns &CGP) const {
+ if (isLeaf()) {
+ if (const ComplexPattern *CP = getComplexPatternInfo(CGP))
+ return CP->hasProperty(Property);
+ return false;
+ }
+
+ Record *Operator = getOperator();
+ if (!Operator->isSubClassOf("SDNode")) return false;
+
+ return CGP.getSDNodeInfo(Operator).hasProperty(Property);
+}
+
+
+
+
+/// TreeHasProperty - Return true if any node in this tree has the specified
+/// property.
+bool TreePatternNode::TreeHasProperty(SDNP Property,
+ const CodeGenDAGPatterns &CGP) const {
+ if (NodeHasProperty(Property, CGP))
+ return true;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (getChild(i)->TreeHasProperty(Property, CGP))
+ return true;
+ return false;
+}
+
+/// isCommutativeIntrinsic - Return true if the node corresponds to a
+/// commutative intrinsic.
+bool
+TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const {
+ if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP))
+ return Int->isCommutative;
+ return false;
+}
+
+
+/// ApplyTypeConstraints - Apply all of the type constraints relevant to
+/// this node and its children in the tree. This returns true if it makes a
+/// change, false otherwise. If a type contradiction is found, throw an
+/// exception.
+bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
+ CodeGenDAGPatterns &CDP = TP.getDAGPatterns();
+ if (isLeaf()) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue())) {
+ // If it's a regclass or something else known, include the type.
+ bool MadeChange = false;
+ for (unsigned i = 0, e = Types.size(); i != e; ++i)
+ MadeChange |= UpdateNodeType(i, getImplicitType(DI->getDef(), i,
+ NotRegisters, TP), TP);
+ return MadeChange;
+ }
+
+ if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) {
+ assert(Types.size() == 1 && "Invalid IntInit");
+
+ // Int inits are always integers. :)
+ bool MadeChange = Types[0].EnforceInteger(TP);
+
+ if (!Types[0].isConcrete())
+ return MadeChange;
+
+ MVT::SimpleValueType VT = getType(0);
+ if (VT == MVT::iPTR || VT == MVT::iPTRAny)
+ return MadeChange;
+
+ unsigned Size = EVT(VT).getSizeInBits();
+ // Make sure that the value is representable for this type.
+ if (Size >= 32) return MadeChange;
+
+ int Val = (II->getValue() << (32-Size)) >> (32-Size);
+ if (Val == II->getValue()) return MadeChange;
+
+ // If sign-extended doesn't fit, does it fit as unsigned?
+ unsigned ValueMask;
+ unsigned UnsignedVal;
+ ValueMask = unsigned(~uint32_t(0UL) >> (32-Size));
+ UnsignedVal = unsigned(II->getValue());
+
+ if ((ValueMask & UnsignedVal) == UnsignedVal)
+ return MadeChange;
+
+ TP.error("Integer value '" + itostr(II->getValue())+
+ "' is out of range for type '" + getEnumName(getType(0)) + "'!");
+ return MadeChange;
+ }
+ return false;
+ }
+
+ // special handling for set, which isn't really an SDNode.
+ if (getOperator()->getName() == "set") {
+ assert(getNumTypes() == 0 && "Set doesn't produce a value");
+ assert(getNumChildren() >= 2 && "Missing RHS of a set?");
+ unsigned NC = getNumChildren();
+
+ TreePatternNode *SetVal = getChild(NC-1);
+ bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters);
+
+ for (unsigned i = 0; i < NC-1; ++i) {
+ TreePatternNode *Child = getChild(i);
+ MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
+
+ // Types of operands must match.
+ MadeChange |= Child->UpdateNodeType(0, SetVal->getExtType(i), TP);
+ MadeChange |= SetVal->UpdateNodeType(i, Child->getExtType(0), TP);
+ }
+ return MadeChange;
+ }
+
+ if (getOperator()->getName() == "implicit") {
+ assert(getNumTypes() == 0 && "Node doesn't produce a value");
+
+ bool MadeChange = false;
+ for (unsigned i = 0; i < getNumChildren(); ++i)
+ MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
+ return MadeChange;
+ }
+
+ if (getOperator()->getName() == "COPY_TO_REGCLASS") {
+ bool MadeChange = false;
+ MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
+ MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters);
+
+ assert(getChild(0)->getNumTypes() == 1 &&
+ getChild(1)->getNumTypes() == 1 && "Unhandled case");
+
+ // child #1 of COPY_TO_REGCLASS should be a register class. We don't care
+ // what type it gets, so if it didn't get a concrete type just give it the
+ // first viable type from the reg class.
+ if (!getChild(1)->hasTypeSet(0) &&
+ !getChild(1)->getExtType(0).isCompletelyUnknown()) {
+ MVT::SimpleValueType RCVT = getChild(1)->getExtType(0).getTypeList()[0];
+ MadeChange |= getChild(1)->UpdateNodeType(0, RCVT, TP);
+ }
+ return MadeChange;
+ }
+
+ if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
+ bool MadeChange = false;
+
+ // Apply the result type to the node.
+ unsigned NumRetVTs = Int->IS.RetVTs.size();
+ unsigned NumParamVTs = Int->IS.ParamVTs.size();
+
+ for (unsigned i = 0, e = NumRetVTs; i != e; ++i)
+ MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP);
+
+ if (getNumChildren() != NumParamVTs + 1)
+ TP.error("Intrinsic '" + Int->Name + "' expects " +
+ utostr(NumParamVTs) + " operands, not " +
+ utostr(getNumChildren() - 1) + " operands!");
+
+ // Apply type info to the intrinsic ID.
+ MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP);
+
+ for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i) {
+ MadeChange |= getChild(i+1)->ApplyTypeConstraints(TP, NotRegisters);
+
+ MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i];
+ assert(getChild(i+1)->getNumTypes() == 1 && "Unhandled case");
+ MadeChange |= getChild(i+1)->UpdateNodeType(0, OpVT, TP);
+ }
+ return MadeChange;
+ }
+
+ if (getOperator()->isSubClassOf("SDNode")) {
+ const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator());
+
+ // Check that the number of operands is sane. Negative operands -> varargs.
+ if (NI.getNumOperands() >= 0 &&
+ getNumChildren() != (unsigned)NI.getNumOperands())
+ TP.error(getOperator()->getName() + " node requires exactly " +
+ itostr(NI.getNumOperands()) + " operands!");
+
+ bool MadeChange = NI.ApplyTypeConstraints(this, TP);
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
+ return MadeChange;
+ }
+
+ if (getOperator()->isSubClassOf("Instruction")) {
+ const DAGInstruction &Inst = CDP.getInstruction(getOperator());
+ CodeGenInstruction &InstInfo =
+ CDP.getTargetInfo().getInstruction(getOperator());
+
+ bool MadeChange = false;
+
+ // Apply the result types to the node, these come from the things in the
+ // (outs) list of the instruction.
+ // FIXME: Cap at one result so far.
+ unsigned NumResultsToAdd = InstInfo.NumDefs ? 1 : 0;
+ for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) {
+ Record *ResultNode = Inst.getResult(ResNo);
+
+ if (ResultNode->isSubClassOf("PointerLikeRegClass")) {
+ MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP);
+ } else if (ResultNode->getName() == "unknown") {
+ // Nothing to do.
+ } else {
+ assert(ResultNode->isSubClassOf("RegisterClass") &&
+ "Operands should be register classes!");
+ const CodeGenRegisterClass &RC =
+ CDP.getTargetInfo().getRegisterClass(ResultNode);
+ MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP);
+ }
+ }
+
+ // If the instruction has implicit defs, we apply the first one as a result.
+ // FIXME: This sucks, it should apply all implicit defs.
+ if (!InstInfo.ImplicitDefs.empty()) {
+ unsigned ResNo = NumResultsToAdd;
+
+ // FIXME: Generalize to multiple possible types and multiple possible
+ // ImplicitDefs.
+ MVT::SimpleValueType VT =
+ InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo());
+
+ if (VT != MVT::Other)
+ MadeChange |= UpdateNodeType(ResNo, VT, TP);
+ }
+
+ // If this is an INSERT_SUBREG, constrain the source and destination VTs to
+ // be the same.
+ if (getOperator()->getName() == "INSERT_SUBREG") {
+ assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled");
+ MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP);
+ MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP);
+ }
+
+ unsigned ChildNo = 0;
+ for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
+ Record *OperandNode = Inst.getOperand(i);
+
+ // If the instruction expects a predicate or optional def operand, we
+ // codegen this by setting the operand to it's default value if it has a
+ // non-empty DefaultOps field.
+ if ((OperandNode->isSubClassOf("PredicateOperand") ||
+ OperandNode->isSubClassOf("OptionalDefOperand")) &&
+ !CDP.getDefaultOperand(OperandNode).DefaultOps.empty())
+ continue;
+
+ // Verify that we didn't run out of provided operands.
+ if (ChildNo >= getNumChildren())
+ TP.error("Instruction '" + getOperator()->getName() +
+ "' expects more operands than were provided.");
+
+ MVT::SimpleValueType VT;
+ TreePatternNode *Child = getChild(ChildNo++);
+ unsigned ChildResNo = 0; // Instructions always use res #0 of their op.
+
+ if (OperandNode->isSubClassOf("RegisterClass")) {
+ const CodeGenRegisterClass &RC =
+ CDP.getTargetInfo().getRegisterClass(OperandNode);
+ MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP);
+ } else if (OperandNode->isSubClassOf("Operand")) {
+ VT = getValueType(OperandNode->getValueAsDef("Type"));
+ MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP);
+ } else if (OperandNode->isSubClassOf("PointerLikeRegClass")) {
+ MadeChange |= Child->UpdateNodeType(ChildResNo, MVT::iPTR, TP);
+ } else if (OperandNode->getName() == "unknown") {
+ // Nothing to do.
+ } else {
+ assert(0 && "Unknown operand type!");
+ abort();
+ }
+ MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
+ }
+
+ if (ChildNo != getNumChildren())
+ TP.error("Instruction '" + getOperator()->getName() +
+ "' was provided too many operands!");
+
+ return MadeChange;
+ }
+
+ assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
+
+ // Node transforms always take one operand.
+ if (getNumChildren() != 1)
+ TP.error("Node transform '" + getOperator()->getName() +
+ "' requires one operand!");
+
+ bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
+
+
+ // If either the output or input of the xform does not have exact
+ // type info. We assume they must be the same. Otherwise, it is perfectly
+ // legal to transform from one type to a completely different type.
+#if 0
+ if (!hasTypeSet() || !getChild(0)->hasTypeSet()) {
+ bool MadeChange = UpdateNodeType(getChild(0)->getExtType(), TP);
+ MadeChange |= getChild(0)->UpdateNodeType(getExtType(), TP);
+ return MadeChange;
+ }
+#endif
+ return MadeChange;
+}
+
+/// OnlyOnRHSOfCommutative - Return true if this value is only allowed on the
+/// RHS of a commutative operation, not the on LHS.
+static bool OnlyOnRHSOfCommutative(TreePatternNode *N) {
+ if (!N->isLeaf() && N->getOperator()->getName() == "imm")
+ return true;
+ if (N->isLeaf() && dynamic_cast<IntInit*>(N->getLeafValue()))
+ return true;
+ return false;
+}
+
+
+/// canPatternMatch - If it is impossible for this pattern to match on this
+/// target, fill in Reason and return false. Otherwise, return true. This is
+/// used as a sanity check for .td files (to prevent people from writing stuff
+/// that can never possibly work), and to prevent the pattern permuter from
+/// generating stuff that is useless.
+bool TreePatternNode::canPatternMatch(std::string &Reason,
+ const CodeGenDAGPatterns &CDP) {
+ if (isLeaf()) return true;
+
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (!getChild(i)->canPatternMatch(Reason, CDP))
+ return false;
+
+ // If this is an intrinsic, handle cases that would make it not match. For
+ // example, if an operand is required to be an immediate.
+ if (getOperator()->isSubClassOf("Intrinsic")) {
+ // TODO:
+ return true;
+ }
+
+ // If this node is a commutative operator, check that the LHS isn't an
+ // immediate.
+ const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator());
+ bool isCommIntrinsic = isCommutativeIntrinsic(CDP);
+ if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) {
+ // Scan all of the operands of the node and make sure that only the last one
+ // is a constant node, unless the RHS also is.
+ if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) {
+ bool Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id.
+ for (unsigned i = Skip, e = getNumChildren()-1; i != e; ++i)
+ if (OnlyOnRHSOfCommutative(getChild(i))) {
+ Reason="Immediate value must be on the RHS of commutative operators!";
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// TreePattern implementation
+//
+
+TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
+ CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){
+ isInputPattern = isInput;
+ for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i)
+ Trees.push_back(ParseTreePattern(RawPat->getElement(i), ""));
+}
+
+TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
+ CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){
+ isInputPattern = isInput;
+ Trees.push_back(ParseTreePattern(Pat, ""));
+}
+
+TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
+ CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){
+ isInputPattern = isInput;
+ Trees.push_back(Pat);
+}
+
+void TreePattern::error(const std::string &Msg) const {
+ dump();
+ throw TGError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg);
+}
+
+void TreePattern::ComputeNamedNodes() {
+ for (unsigned i = 0, e = Trees.size(); i != e; ++i)
+ ComputeNamedNodes(Trees[i]);
+}
+
+void TreePattern::ComputeNamedNodes(TreePatternNode *N) {
+ if (!N->getName().empty())
+ NamedNodes[N->getName()].push_back(N);
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ ComputeNamedNodes(N->getChild(i));
+}
+
+
+TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
+ if (DefInit *DI = dynamic_cast<DefInit*>(TheInit)) {
+ Record *R = DI->getDef();
+
+ // Direct reference to a leaf DagNode or PatFrag? Turn it into a
+ // TreePatternNode if its own. For example:
+ /// (foo GPR, imm) -> (foo GPR, (imm))
+ if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag"))
+ return ParseTreePattern(new DagInit(DI, "",
+ std::vector<std::pair<Init*, std::string> >()),
+ OpName);
+
+ // Input argument?
+ TreePatternNode *Res = new TreePatternNode(DI, 1);
+ if (R->getName() == "node" && !OpName.empty()) {
+ if (OpName.empty())
+ error("'node' argument requires a name to match with operand list");
+ Args.push_back(OpName);
+ }
+
+ Res->setName(OpName);
+ return Res;
+ }
+
+ if (IntInit *II = dynamic_cast<IntInit*>(TheInit)) {
+ if (!OpName.empty())
+ error("Constant int argument should not have a name!");
+ return new TreePatternNode(II, 1);
+ }
+
+ if (BitsInit *BI = dynamic_cast<BitsInit*>(TheInit)) {
+ // Turn this into an IntInit.
+ Init *II = BI->convertInitializerTo(new IntRecTy());
+ if (II == 0 || !dynamic_cast<IntInit*>(II))
+ error("Bits value must be constants!");
+ return ParseTreePattern(II, OpName);
+ }
+
+ DagInit *Dag = dynamic_cast<DagInit*>(TheInit);
+ if (!Dag) {
+ TheInit->dump();
+ error("Pattern has unexpected init kind!");
+ }
+ DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator());
+ if (!OpDef) error("Pattern has unexpected operator type!");
+ Record *Operator = OpDef->getDef();
+
+ if (Operator->isSubClassOf("ValueType")) {
+ // If the operator is a ValueType, then this must be "type cast" of a leaf
+ // node.
+ if (Dag->getNumArgs() != 1)
+ error("Type cast only takes one operand!");
+
+ TreePatternNode *New = ParseTreePattern(Dag->getArg(0), Dag->getArgName(0));
+
+ // Apply the type cast.
+ assert(New->getNumTypes() == 1 && "FIXME: Unhandled");
+ New->UpdateNodeType(0, getValueType(Operator), *this);
+
+ if (!OpName.empty())
+ error("ValueType cast should not have a name!");
+ return New;
+ }
+
+ // Verify that this is something that makes sense for an operator.
+ if (!Operator->isSubClassOf("PatFrag") &&
+ !Operator->isSubClassOf("SDNode") &&
+ !Operator->isSubClassOf("Instruction") &&
+ !Operator->isSubClassOf("SDNodeXForm") &&
+ !Operator->isSubClassOf("Intrinsic") &&
+ Operator->getName() != "set" &&
+ Operator->getName() != "implicit")
+ error("Unrecognized node '" + Operator->getName() + "'!");
+
+ // Check to see if this is something that is illegal in an input pattern.
+ if (isInputPattern) {
+ if (Operator->isSubClassOf("Instruction") ||
+ Operator->isSubClassOf("SDNodeXForm"))
+ error("Cannot use '" + Operator->getName() + "' in an input pattern!");
+ } else {
+ if (Operator->isSubClassOf("Intrinsic"))
+ error("Cannot use '" + Operator->getName() + "' in an output pattern!");
+
+ if (Operator->isSubClassOf("SDNode") &&
+ Operator->getName() != "imm" &&
+ Operator->getName() != "fpimm" &&
+ Operator->getName() != "tglobaltlsaddr" &&
+ Operator->getName() != "tconstpool" &&
+ Operator->getName() != "tjumptable" &&
+ Operator->getName() != "tframeindex" &&
+ Operator->getName() != "texternalsym" &&
+ Operator->getName() != "tblockaddress" &&
+ Operator->getName() != "tglobaladdr" &&
+ Operator->getName() != "bb" &&
+ Operator->getName() != "vt")
+ error("Cannot use '" + Operator->getName() + "' in an output pattern!");
+ }
+
+ std::vector<TreePatternNode*> Children;
+
+ // Parse all the operands.
+ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i)
+ Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgName(i)));
+
+ // If the operator is an intrinsic, then this is just syntactic sugar for for
+ // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and
+ // convert the intrinsic name to a number.
+ if (Operator->isSubClassOf("Intrinsic")) {
+ const CodeGenIntrinsic &Int = getDAGPatterns().getIntrinsic(Operator);
+ unsigned IID = getDAGPatterns().getIntrinsicID(Operator)+1;
+
+ // If this intrinsic returns void, it must have side-effects and thus a
+ // chain.
+ if (Int.IS.RetVTs.empty())
+ Operator = getDAGPatterns().get_intrinsic_void_sdnode();
+ else if (Int.ModRef != CodeGenIntrinsic::NoMem)
+ // Has side-effects, requires chain.
+ Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode();
+ else // Otherwise, no chain.
+ Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode();
+
+ TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID), 1);
+ Children.insert(Children.begin(), IIDNode);
+ }
+
+ unsigned NumResults = GetNumNodeResults(Operator, CDP);
+ TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults);
+ Result->setName(OpName);
+
+ if (!Dag->getName().empty()) {
+ assert(Result->getName().empty());
+ Result->setName(Dag->getName());
+ }
+ return Result;
+}
+
+/// SimplifyTree - See if we can simplify this tree to eliminate something that
+/// will never match in favor of something obvious that will. This is here
+/// strictly as a convenience to target authors because it allows them to write
+/// more type generic things and have useless type casts fold away.
+///
+/// This returns true if any change is made.
+static bool SimplifyTree(TreePatternNode *&N) {
+ if (N->isLeaf())
+ return false;
+
+ // If we have a bitconvert with a resolved type and if the source and
+ // destination types are the same, then the bitconvert is useless, remove it.
+ if (N->getOperator()->getName() == "bitconvert" &&
+ N->getExtType(0).isConcrete() &&
+ N->getExtType(0) == N->getChild(0)->getExtType(0) &&
+ N->getName().empty()) {
+ N = N->getChild(0);
+ SimplifyTree(N);
+ return true;
+ }
+
+ // Walk all children.
+ bool MadeChange = false;
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = N->getChild(i);
+ MadeChange |= SimplifyTree(Child);
+ N->setChild(i, Child);
+ }
+ return MadeChange;
+}
+
+
+
+/// InferAllTypes - Infer/propagate as many types throughout the expression
+/// patterns as possible. Return true if all types are inferred, false
+/// otherwise. Throw an exception if a type contradiction is found.
+bool TreePattern::
+InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
+ if (NamedNodes.empty())
+ ComputeNamedNodes();
+
+ bool MadeChange = true;
+ while (MadeChange) {
+ MadeChange = false;
+ for (unsigned i = 0, e = Trees.size(); i != e; ++i) {
+ MadeChange |= Trees[i]->ApplyTypeConstraints(*this, false);
+ MadeChange |= SimplifyTree(Trees[i]);
+ }
+
+ // If there are constraints on our named nodes, apply them.
+ for (StringMap<SmallVector<TreePatternNode*,1> >::iterator
+ I = NamedNodes.begin(), E = NamedNodes.end(); I != E; ++I) {
+ SmallVectorImpl<TreePatternNode*> &Nodes = I->second;
+
+ // If we have input named node types, propagate their types to the named
+ // values here.
+ if (InNamedTypes) {
+ // FIXME: Should be error?
+ assert(InNamedTypes->count(I->getKey()) &&
+ "Named node in output pattern but not input pattern?");
+
+ const SmallVectorImpl<TreePatternNode*> &InNodes =
+ InNamedTypes->find(I->getKey())->second;
+
+ // The input types should be fully resolved by now.
+ for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
+ // If this node is a register class, and it is the root of the pattern
+ // then we're mapping something onto an input register. We allow
+ // changing the type of the input register in this case. This allows
+ // us to match things like:
+ // def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>;
+ if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) {
+ DefInit *DI = dynamic_cast<DefInit*>(Nodes[i]->getLeafValue());
+ if (DI && DI->getDef()->isSubClassOf("RegisterClass"))
+ continue;
+ }
+
+ assert(Nodes[i]->getNumTypes() == 1 &&
+ InNodes[0]->getNumTypes() == 1 &&
+ "FIXME: cannot name multiple result nodes yet");
+ MadeChange |= Nodes[i]->UpdateNodeType(0, InNodes[0]->getExtType(0),
+ *this);
+ }
+ }
+
+ // If there are multiple nodes with the same name, they must all have the
+ // same type.
+ if (I->second.size() > 1) {
+ for (unsigned i = 0, e = Nodes.size()-1; i != e; ++i) {
+ TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1];
+ assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 &&
+ "FIXME: cannot name multiple result nodes yet");
+
+ MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this);
+ MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this);
+ }
+ }
+ }
+ }
+
+ bool HasUnresolvedTypes = false;
+ for (unsigned i = 0, e = Trees.size(); i != e; ++i)
+ HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType();
+ return !HasUnresolvedTypes;
+}
+
+void TreePattern::print(raw_ostream &OS) const {
+ OS << getRecord()->getName();
+ if (!Args.empty()) {
+ OS << "(" << Args[0];
+ for (unsigned i = 1, e = Args.size(); i != e; ++i)
+ OS << ", " << Args[i];
+ OS << ")";
+ }
+ OS << ": ";
+
+ if (Trees.size() > 1)
+ OS << "[\n";
+ for (unsigned i = 0, e = Trees.size(); i != e; ++i) {
+ OS << "\t";
+ Trees[i]->print(OS);
+ OS << "\n";
+ }
+
+ if (Trees.size() > 1)
+ OS << "]\n";
+}
+
+void TreePattern::dump() const { print(errs()); }
+
+//===----------------------------------------------------------------------===//
+// CodeGenDAGPatterns implementation
+//
+
+CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) {
+ Intrinsics = LoadIntrinsics(Records, false);
+ TgtIntrinsics = LoadIntrinsics(Records, true);
+ ParseNodeInfo();
+ ParseNodeTransforms();
+ ParseComplexPatterns();
+ ParsePatternFragments();
+ ParseDefaultOperands();
+ ParseInstructions();
+ ParsePatterns();
+
+ // Generate variants. For example, commutative patterns can match
+ // multiple ways. Add them to PatternsToMatch as well.
+ GenerateVariants();
+
+ // Infer instruction flags. For example, we can detect loads,
+ // stores, and side effects in many cases by examining an
+ // instruction's pattern.
+ InferInstructionFlags();
+}
+
+CodeGenDAGPatterns::~CodeGenDAGPatterns() {
+ for (pf_iterator I = PatternFragments.begin(),
+ E = PatternFragments.end(); I != E; ++I)
+ delete I->second;
+}
+
+
+Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const {
+ Record *N = Records.getDef(Name);
+ if (!N || !N->isSubClassOf("SDNode")) {
+ errs() << "Error getting SDNode '" << Name << "'!\n";
+ exit(1);
+ }
+ return N;
+}
+
+// Parse all of the SDNode definitions for the target, populating SDNodes.
+void CodeGenDAGPatterns::ParseNodeInfo() {
+ std::vector<Record*> Nodes = Records.getAllDerivedDefinitions("SDNode");
+ while (!Nodes.empty()) {
+ SDNodes.insert(std::make_pair(Nodes.back(), Nodes.back()));
+ Nodes.pop_back();
+ }
+
+ // Get the builtin intrinsic nodes.
+ intrinsic_void_sdnode = getSDNodeNamed("intrinsic_void");
+ intrinsic_w_chain_sdnode = getSDNodeNamed("intrinsic_w_chain");
+ intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain");
+}
+
+/// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms
+/// map, and emit them to the file as functions.
+void CodeGenDAGPatterns::ParseNodeTransforms() {
+ std::vector<Record*> Xforms = Records.getAllDerivedDefinitions("SDNodeXForm");
+ while (!Xforms.empty()) {
+ Record *XFormNode = Xforms.back();
+ Record *SDNode = XFormNode->getValueAsDef("Opcode");
+ std::string Code = XFormNode->getValueAsCode("XFormFunction");
+ SDNodeXForms.insert(std::make_pair(XFormNode, NodeXForm(SDNode, Code)));
+
+ Xforms.pop_back();
+ }
+}
+
+void CodeGenDAGPatterns::ParseComplexPatterns() {
+ std::vector<Record*> AMs = Records.getAllDerivedDefinitions("ComplexPattern");
+ while (!AMs.empty()) {
+ ComplexPatterns.insert(std::make_pair(AMs.back(), AMs.back()));
+ AMs.pop_back();
+ }
+}
+
+
+/// ParsePatternFragments - Parse all of the PatFrag definitions in the .td
+/// file, building up the PatternFragments map. After we've collected them all,
+/// inline fragments together as necessary, so that there are no references left
+/// inside a pattern fragment to a pattern fragment.
+///
+void CodeGenDAGPatterns::ParsePatternFragments() {
+ std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag");
+
+ // First step, parse all of the fragments.
+ for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
+ DagInit *Tree = Fragments[i]->getValueAsDag("Fragment");
+ TreePattern *P = new TreePattern(Fragments[i], Tree, true, *this);
+ PatternFragments[Fragments[i]] = P;
+
+ // Validate the argument list, converting it to set, to discard duplicates.
+ std::vector<std::string> &Args = P->getArgList();
+ std::set<std::string> OperandsSet(Args.begin(), Args.end());
+
+ if (OperandsSet.count(""))
+ P->error("Cannot have unnamed 'node' values in pattern fragment!");
+
+ // Parse the operands list.
+ DagInit *OpsList = Fragments[i]->getValueAsDag("Operands");
+ DefInit *OpsOp = dynamic_cast<DefInit*>(OpsList->getOperator());
+ // Special cases: ops == outs == ins. Different names are used to
+ // improve readability.
+ if (!OpsOp ||
+ (OpsOp->getDef()->getName() != "ops" &&
+ OpsOp->getDef()->getName() != "outs" &&
+ OpsOp->getDef()->getName() != "ins"))
+ P->error("Operands list should start with '(ops ... '!");
+
+ // Copy over the arguments.
+ Args.clear();
+ for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) {
+ if (!dynamic_cast<DefInit*>(OpsList->getArg(j)) ||
+ static_cast<DefInit*>(OpsList->getArg(j))->
+ getDef()->getName() != "node")
+ P->error("Operands list should all be 'node' values.");
+ if (OpsList->getArgName(j).empty())
+ P->error("Operands list should have names for each operand!");
+ if (!OperandsSet.count(OpsList->getArgName(j)))
+ P->error("'" + OpsList->getArgName(j) +
+ "' does not occur in pattern or was multiply specified!");
+ OperandsSet.erase(OpsList->getArgName(j));
+ Args.push_back(OpsList->getArgName(j));
+ }
+
+ if (!OperandsSet.empty())
+ P->error("Operands list does not contain an entry for operand '" +
+ *OperandsSet.begin() + "'!");
+
+ // If there is a code init for this fragment, keep track of the fact that
+ // this fragment uses it.
+ std::string Code = Fragments[i]->getValueAsCode("Predicate");
+ if (!Code.empty())
+ P->getOnlyTree()->addPredicateFn("Predicate_"+Fragments[i]->getName());
+
+ // If there is a node transformation corresponding to this, keep track of
+ // it.
+ Record *Transform = Fragments[i]->getValueAsDef("OperandTransform");
+ if (!getSDNodeTransform(Transform).second.empty()) // not noop xform?
+ P->getOnlyTree()->setTransformFn(Transform);
+ }
+
+ // Now that we've parsed all of the tree fragments, do a closure on them so
+ // that there are not references to PatFrags left inside of them.
+ for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
+ TreePattern *ThePat = PatternFragments[Fragments[i]];
+ ThePat->InlinePatternFragments();
+
+ // Infer as many types as possible. Don't worry about it if we don't infer
+ // all of them, some may depend on the inputs of the pattern.
+ try {
+ ThePat->InferAllTypes();
+ } catch (...) {
+ // If this pattern fragment is not supported by this target (no types can
+ // satisfy its constraints), just ignore it. If the bogus pattern is
+ // actually used by instructions, the type consistency error will be
+ // reported there.
+ }
+
+ // If debugging, print out the pattern fragment result.
+ DEBUG(ThePat->dump());
+ }
+}
+
+void CodeGenDAGPatterns::ParseDefaultOperands() {
+ std::vector<Record*> DefaultOps[2];
+ DefaultOps[0] = Records.getAllDerivedDefinitions("PredicateOperand");
+ DefaultOps[1] = Records.getAllDerivedDefinitions("OptionalDefOperand");
+
+ // Find some SDNode.
+ assert(!SDNodes.empty() && "No SDNodes parsed?");
+ Init *SomeSDNode = new DefInit(SDNodes.begin()->first);
+
+ for (unsigned iter = 0; iter != 2; ++iter) {
+ for (unsigned i = 0, e = DefaultOps[iter].size(); i != e; ++i) {
+ DagInit *DefaultInfo = DefaultOps[iter][i]->getValueAsDag("DefaultOps");
+
+ // Clone the DefaultInfo dag node, changing the operator from 'ops' to
+ // SomeSDnode so that we can parse this.
+ std::vector<std::pair<Init*, std::string> > Ops;
+ for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
+ Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
+ DefaultInfo->getArgName(op)));
+ DagInit *DI = new DagInit(SomeSDNode, "", Ops);
+
+ // Create a TreePattern to parse this.
+ TreePattern P(DefaultOps[iter][i], DI, false, *this);
+ assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!");
+
+ // Copy the operands over into a DAGDefaultOperand.
+ DAGDefaultOperand DefaultOpInfo;
+
+ TreePatternNode *T = P.getTree(0);
+ for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
+ TreePatternNode *TPN = T->getChild(op);
+ while (TPN->ApplyTypeConstraints(P, false))
+ /* Resolve all types */;
+
+ if (TPN->ContainsUnresolvedType()) {
+ if (iter == 0)
+ throw "Value #" + utostr(i) + " of PredicateOperand '" +
+ DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!";
+ else
+ throw "Value #" + utostr(i) + " of OptionalDefOperand '" +
+ DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!";
+ }
+ DefaultOpInfo.DefaultOps.push_back(TPN);
+ }
+
+ // Insert it into the DefaultOperands map so we can find it later.
+ DefaultOperands[DefaultOps[iter][i]] = DefaultOpInfo;
+ }
+ }
+}
+
+/// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an
+/// instruction input. Return true if this is a real use.
+static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
+ std::map<std::string, TreePatternNode*> &InstInputs) {
+ // No name -> not interesting.
+ if (Pat->getName().empty()) {
+ if (Pat->isLeaf()) {
+ DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
+ if (DI && DI->getDef()->isSubClassOf("RegisterClass"))
+ I->error("Input " + DI->getDef()->getName() + " must be named!");
+ }
+ return false;
+ }
+
+ Record *Rec;
+ if (Pat->isLeaf()) {
+ DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
+ if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!");
+ Rec = DI->getDef();
+ } else {
+ Rec = Pat->getOperator();
+ }
+
+ // SRCVALUE nodes are ignored.
+ if (Rec->getName() == "srcvalue")
+ return false;
+
+ TreePatternNode *&Slot = InstInputs[Pat->getName()];
+ if (!Slot) {
+ Slot = Pat;
+ return true;
+ }
+ Record *SlotRec;
+ if (Slot->isLeaf()) {
+ SlotRec = dynamic_cast<DefInit*>(Slot->getLeafValue())->getDef();
+ } else {
+ assert(Slot->getNumChildren() == 0 && "can't be a use with children!");
+ SlotRec = Slot->getOperator();
+ }
+
+ // Ensure that the inputs agree if we've already seen this input.
+ if (Rec != SlotRec)
+ I->error("All $" + Pat->getName() + " inputs must agree with each other");
+ if (Slot->getExtTypes() != Pat->getExtTypes())
+ I->error("All $" + Pat->getName() + " inputs must agree with each other");
+ return true;
+}
+
+/// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is
+/// part of "I", the instruction), computing the set of inputs and outputs of
+/// the pattern. Report errors if we see anything naughty.
+void CodeGenDAGPatterns::
+FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
+ std::map<std::string, TreePatternNode*> &InstInputs,
+ std::map<std::string, TreePatternNode*>&InstResults,
+ std::vector<Record*> &InstImpResults) {
+ if (Pat->isLeaf()) {
+ bool isUse = HandleUse(I, Pat, InstInputs);
+ if (!isUse && Pat->getTransformFn())
+ I->error("Cannot specify a transform function for a non-input value!");
+ return;
+ }
+
+ if (Pat->getOperator()->getName() == "implicit") {
+ for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Dest = Pat->getChild(i);
+ if (!Dest->isLeaf())
+ I->error("implicitly defined value should be a register!");
+
+ DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue());
+ if (!Val || !Val->getDef()->isSubClassOf("Register"))
+ I->error("implicitly defined value should be a register!");
+ InstImpResults.push_back(Val->getDef());
+ }
+ return;
+ }
+
+ if (Pat->getOperator()->getName() != "set") {
+ // If this is not a set, verify that the children nodes are not void typed,
+ // and recurse.
+ for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
+ if (Pat->getChild(i)->getNumTypes() == 0)
+ I->error("Cannot have void nodes inside of patterns!");
+ FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults,
+ InstImpResults);
+ }
+
+ // If this is a non-leaf node with no children, treat it basically as if
+ // it were a leaf. This handles nodes like (imm).
+ bool isUse = HandleUse(I, Pat, InstInputs);
+
+ if (!isUse && Pat->getTransformFn())
+ I->error("Cannot specify a transform function for a non-input value!");
+ return;
+ }
+
+ // Otherwise, this is a set, validate and collect instruction results.
+ if (Pat->getNumChildren() == 0)
+ I->error("set requires operands!");
+
+ if (Pat->getTransformFn())
+ I->error("Cannot specify a transform function on a set node!");
+
+ // Check the set destinations.
+ unsigned NumDests = Pat->getNumChildren()-1;
+ for (unsigned i = 0; i != NumDests; ++i) {
+ TreePatternNode *Dest = Pat->getChild(i);
+ if (!Dest->isLeaf())
+ I->error("set destination should be a register!");
+
+ DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue());
+ if (!Val)
+ I->error("set destination should be a register!");
+
+ if (Val->getDef()->isSubClassOf("RegisterClass") ||
+ Val->getDef()->isSubClassOf("PointerLikeRegClass")) {
+ if (Dest->getName().empty())
+ I->error("set destination must have a name!");
+ if (InstResults.count(Dest->getName()))
+ I->error("cannot set '" + Dest->getName() +"' multiple times");
+ InstResults[Dest->getName()] = Dest;
+ } else if (Val->getDef()->isSubClassOf("Register")) {
+ InstImpResults.push_back(Val->getDef());
+ } else {
+ I->error("set destination should be a register!");
+ }
+ }
+
+ // Verify and collect info from the computation.
+ FindPatternInputsAndOutputs(I, Pat->getChild(NumDests),
+ InstInputs, InstResults, InstImpResults);
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction Analysis
+//===----------------------------------------------------------------------===//
+
+class InstAnalyzer {
+ const CodeGenDAGPatterns &CDP;
+ bool &mayStore;
+ bool &mayLoad;
+ bool &HasSideEffects;
+ bool &IsVariadic;
+public:
+ InstAnalyzer(const CodeGenDAGPatterns &cdp,
+ bool &maystore, bool &mayload, bool &hse, bool &isv)
+ : CDP(cdp), mayStore(maystore), mayLoad(mayload), HasSideEffects(hse),
+ IsVariadic(isv) {
+ }
+
+ /// Analyze - Analyze the specified instruction, returning true if the
+ /// instruction had a pattern.
+ bool Analyze(Record *InstRecord) {
+ const TreePattern *Pattern = CDP.getInstruction(InstRecord).getPattern();
+ if (Pattern == 0) {
+ HasSideEffects = 1;
+ return false; // No pattern.
+ }
+
+ // FIXME: Assume only the first tree is the pattern. The others are clobber
+ // nodes.
+ AnalyzeNode(Pattern->getTree(0));
+ return true;
+ }
+
+private:
+ void AnalyzeNode(const TreePatternNode *N) {
+ if (N->isLeaf()) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
+ Record *LeafRec = DI->getDef();
+ // Handle ComplexPattern leaves.
+ if (LeafRec->isSubClassOf("ComplexPattern")) {
+ const ComplexPattern &CP = CDP.getComplexPattern(LeafRec);
+ if (CP.hasProperty(SDNPMayStore)) mayStore = true;
+ if (CP.hasProperty(SDNPMayLoad)) mayLoad = true;
+ if (CP.hasProperty(SDNPSideEffect)) HasSideEffects = true;
+ }
+ }
+ return;
+ }
+
+ // Analyze children.
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ AnalyzeNode(N->getChild(i));
+
+ // Ignore set nodes, which are not SDNodes.
+ if (N->getOperator()->getName() == "set")
+ return;
+
+ // Get information about the SDNode for the operator.
+ const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator());
+
+ // Notice properties of the node.
+ if (OpInfo.hasProperty(SDNPMayStore)) mayStore = true;
+ if (OpInfo.hasProperty(SDNPMayLoad)) mayLoad = true;
+ if (OpInfo.hasProperty(SDNPSideEffect)) HasSideEffects = true;
+ if (OpInfo.hasProperty(SDNPVariadic)) IsVariadic = true;
+
+ if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) {
+ // If this is an intrinsic, analyze it.
+ if (IntInfo->ModRef >= CodeGenIntrinsic::ReadArgMem)
+ mayLoad = true;// These may load memory.
+
+ if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteArgMem)
+ mayStore = true;// Intrinsics that can write to memory are 'mayStore'.
+
+ if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteMem)
+ // WriteMem intrinsics can have other strange effects.
+ HasSideEffects = true;
+ }
+ }
+
+};
+
+static void InferFromPattern(const CodeGenInstruction &Inst,
+ bool &MayStore, bool &MayLoad,
+ bool &HasSideEffects, bool &IsVariadic,
+ const CodeGenDAGPatterns &CDP) {
+ MayStore = MayLoad = HasSideEffects = IsVariadic = false;
+
+ bool HadPattern =
+ InstAnalyzer(CDP, MayStore, MayLoad, HasSideEffects, IsVariadic)
+ .Analyze(Inst.TheDef);
+
+ // InstAnalyzer only correctly analyzes mayStore/mayLoad so far.
+ if (Inst.mayStore) { // If the .td file explicitly sets mayStore, use it.
+ // If we decided that this is a store from the pattern, then the .td file
+ // entry is redundant.
+ if (MayStore)
+ fprintf(stderr,
+ "Warning: mayStore flag explicitly set on instruction '%s'"
+ " but flag already inferred from pattern.\n",
+ Inst.TheDef->getName().c_str());
+ MayStore = true;
+ }
+
+ if (Inst.mayLoad) { // If the .td file explicitly sets mayLoad, use it.
+ // If we decided that this is a load from the pattern, then the .td file
+ // entry is redundant.
+ if (MayLoad)
+ fprintf(stderr,
+ "Warning: mayLoad flag explicitly set on instruction '%s'"
+ " but flag already inferred from pattern.\n",
+ Inst.TheDef->getName().c_str());
+ MayLoad = true;
+ }
+
+ if (Inst.neverHasSideEffects) {
+ if (HadPattern)
+ fprintf(stderr, "Warning: neverHasSideEffects set on instruction '%s' "
+ "which already has a pattern\n", Inst.TheDef->getName().c_str());
+ HasSideEffects = false;
+ }
+
+ if (Inst.hasSideEffects) {
+ if (HasSideEffects)
+ fprintf(stderr, "Warning: hasSideEffects set on instruction '%s' "
+ "which already inferred this.\n", Inst.TheDef->getName().c_str());
+ HasSideEffects = true;
+ }
+
+ if (Inst.isVariadic)
+ IsVariadic = true; // Can warn if we want.
+}
+
+/// ParseInstructions - Parse all of the instructions, inlining and resolving
+/// any fragments involved. This populates the Instructions list with fully
+/// resolved instructions.
+void CodeGenDAGPatterns::ParseInstructions() {
+ std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction");
+
+ for (unsigned i = 0, e = Instrs.size(); i != e; ++i) {
+ ListInit *LI = 0;
+
+ if (dynamic_cast<ListInit*>(Instrs[i]->getValueInit("Pattern")))
+ LI = Instrs[i]->getValueAsListInit("Pattern");
+
+ // If there is no pattern, only collect minimal information about the
+ // instruction for its operand list. We have to assume that there is one
+ // result, as we have no detailed info.
+ if (!LI || LI->getSize() == 0) {
+ std::vector<Record*> Results;
+ std::vector<Record*> Operands;
+
+ CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]);
+
+ if (InstInfo.OperandList.size() != 0) {
+ if (InstInfo.NumDefs == 0) {
+ // These produce no results
+ for (unsigned j = 0, e = InstInfo.OperandList.size(); j < e; ++j)
+ Operands.push_back(InstInfo.OperandList[j].Rec);
+ } else {
+ // Assume the first operand is the result.
+ Results.push_back(InstInfo.OperandList[0].Rec);
+
+ // The rest are inputs.
+ for (unsigned j = 1, e = InstInfo.OperandList.size(); j < e; ++j)
+ Operands.push_back(InstInfo.OperandList[j].Rec);
+ }
+ }
+
+ // Create and insert the instruction.
+ std::vector<Record*> ImpResults;
+ Instructions.insert(std::make_pair(Instrs[i],
+ DAGInstruction(0, Results, Operands, ImpResults)));
+ continue; // no pattern.
+ }
+
+ // Parse the instruction.
+ TreePattern *I = new TreePattern(Instrs[i], LI, true, *this);
+ // Inline pattern fragments into it.
+ I->InlinePatternFragments();
+
+ // Infer as many types as possible. If we cannot infer all of them, we can
+ // never do anything with this instruction pattern: report it to the user.
+ if (!I->InferAllTypes())
+ I->error("Could not infer all types in pattern!");
+
+ // InstInputs - Keep track of all of the inputs of the instruction, along
+ // with the record they are declared as.
+ std::map<std::string, TreePatternNode*> InstInputs;
+
+ // InstResults - Keep track of all the virtual registers that are 'set'
+ // in the instruction, including what reg class they are.
+ std::map<std::string, TreePatternNode*> InstResults;
+
+ std::vector<Record*> InstImpResults;
+
+ // Verify that the top-level forms in the instruction are of void type, and
+ // fill in the InstResults map.
+ for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
+ TreePatternNode *Pat = I->getTree(j);
+ if (Pat->getNumTypes() != 0)
+ I->error("Top-level forms in instruction pattern should have"
+ " void types");
+
+ // Find inputs and outputs, and verify the structure of the uses/defs.
+ FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,
+ InstImpResults);
+ }
+
+ // Now that we have inputs and outputs of the pattern, inspect the operands
+ // list for the instruction. This determines the order that operands are
+ // added to the machine instruction the node corresponds to.
+ unsigned NumResults = InstResults.size();
+
+ // Parse the operands list from the (ops) list, validating it.
+ assert(I->getArgList().empty() && "Args list should still be empty here!");
+ CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]);
+
+ // Check that all of the results occur first in the list.
+ std::vector<Record*> Results;
+ TreePatternNode *Res0Node = 0;
+ for (unsigned i = 0; i != NumResults; ++i) {
+ if (i == CGI.OperandList.size())
+ I->error("'" + InstResults.begin()->first +
+ "' set but does not appear in operand list!");
+ const std::string &OpName = CGI.OperandList[i].Name;
+
+ // Check that it exists in InstResults.
+ TreePatternNode *RNode = InstResults[OpName];
+ if (RNode == 0)
+ I->error("Operand $" + OpName + " does not exist in operand list!");
+
+ if (i == 0)
+ Res0Node = RNode;
+ Record *R = dynamic_cast<DefInit*>(RNode->getLeafValue())->getDef();
+ if (R == 0)
+ I->error("Operand $" + OpName + " should be a set destination: all "
+ "outputs must occur before inputs in operand list!");
+
+ if (CGI.OperandList[i].Rec != R)
+ I->error("Operand $" + OpName + " class mismatch!");
+
+ // Remember the return type.
+ Results.push_back(CGI.OperandList[i].Rec);
+
+ // Okay, this one checks out.
+ InstResults.erase(OpName);
+ }
+
+ // Loop over the inputs next. Make a copy of InstInputs so we can destroy
+ // the copy while we're checking the inputs.
+ std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs);
+
+ std::vector<TreePatternNode*> ResultNodeOperands;
+ std::vector<Record*> Operands;
+ for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) {
+ CodeGenInstruction::OperandInfo &Op = CGI.OperandList[i];
+ const std::string &OpName = Op.Name;
+ if (OpName.empty())
+ I->error("Operand #" + utostr(i) + " in operands list has no name!");
+
+ if (!InstInputsCheck.count(OpName)) {
+ // If this is an predicate operand or optional def operand with an
+ // DefaultOps set filled in, we can ignore this. When we codegen it,
+ // we will do so as always executed.
+ if (Op.Rec->isSubClassOf("PredicateOperand") ||
+ Op.Rec->isSubClassOf("OptionalDefOperand")) {
+ // Does it have a non-empty DefaultOps field? If so, ignore this
+ // operand.
+ if (!getDefaultOperand(Op.Rec).DefaultOps.empty())
+ continue;
+ }
+ I->error("Operand $" + OpName +
+ " does not appear in the instruction pattern");
+ }
+ TreePatternNode *InVal = InstInputsCheck[OpName];
+ InstInputsCheck.erase(OpName); // It occurred, remove from map.
+
+ if (InVal->isLeaf() &&
+ dynamic_cast<DefInit*>(InVal->getLeafValue())) {
+ Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
+ if (Op.Rec != InRec && !InRec->isSubClassOf("ComplexPattern"))
+ I->error("Operand $" + OpName + "'s register class disagrees"
+ " between the operand and pattern");
+ }
+ Operands.push_back(Op.Rec);
+
+ // Construct the result for the dest-pattern operand list.
+ TreePatternNode *OpNode = InVal->clone();
+
+ // No predicate is useful on the result.
+ OpNode->clearPredicateFns();
+
+ // Promote the xform function to be an explicit node if set.
+ if (Record *Xform = OpNode->getTransformFn()) {
+ OpNode->setTransformFn(0);
+ std::vector<TreePatternNode*> Children;
+ Children.push_back(OpNode);
+ OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
+ }
+
+ ResultNodeOperands.push_back(OpNode);
+ }
+
+ if (!InstInputsCheck.empty())
+ I->error("Input operand $" + InstInputsCheck.begin()->first +
+ " occurs in pattern but not in operands list!");
+
+ TreePatternNode *ResultPattern =
+ new TreePatternNode(I->getRecord(), ResultNodeOperands,
+ GetNumNodeResults(I->getRecord(), *this));
+ // Copy fully inferred output node type to instruction result pattern.
+ for (unsigned i = 0; i != NumResults; ++i)
+ ResultPattern->setType(i, Res0Node->getExtType(i));
+
+ // Create and insert the instruction.
+ // FIXME: InstImpResults should not be part of DAGInstruction.
+ DAGInstruction TheInst(I, Results, Operands, InstImpResults);
+ Instructions.insert(std::make_pair(I->getRecord(), TheInst));
+
+ // Use a temporary tree pattern to infer all types and make sure that the
+ // constructed result is correct. This depends on the instruction already
+ // being inserted into the Instructions map.
+ TreePattern Temp(I->getRecord(), ResultPattern, false, *this);
+ Temp.InferAllTypes(&I->getNamedNodesMap());
+
+ DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second;
+ TheInsertedInst.setResultPattern(Temp.getOnlyTree());
+
+ DEBUG(I->dump());
+ }
+
+ // If we can, convert the instructions to be patterns that are matched!
+ for (std::map<Record*, DAGInstruction, RecordPtrCmp>::iterator II =
+ Instructions.begin(),
+ E = Instructions.end(); II != E; ++II) {
+ DAGInstruction &TheInst = II->second;
+ const TreePattern *I = TheInst.getPattern();
+ if (I == 0) continue; // No pattern.
+
+ // FIXME: Assume only the first tree is the pattern. The others are clobber
+ // nodes.
+ TreePatternNode *Pattern = I->getTree(0);
+ TreePatternNode *SrcPattern;
+ if (Pattern->getOperator()->getName() == "set") {
+ SrcPattern = Pattern->getChild(Pattern->getNumChildren()-1)->clone();
+ } else{
+ // Not a set (store or something?)
+ SrcPattern = Pattern;
+ }
+
+ Record *Instr = II->first;
+ AddPatternToMatch(I,
+ PatternToMatch(Instr->getValueAsListInit("Predicates"),
+ SrcPattern,
+ TheInst.getResultPattern(),
+ TheInst.getImpResults(),
+ Instr->getValueAsInt("AddedComplexity"),
+ Instr->getID()));
+ }
+}
+
+
+typedef std::pair<const TreePatternNode*, unsigned> NameRecord;
+
+static void FindNames(const TreePatternNode *P,
+ std::map<std::string, NameRecord> &Names,
+ const TreePattern *PatternTop) {
+ if (!P->getName().empty()) {
+ NameRecord &Rec = Names[P->getName()];
+ // If this is the first instance of the name, remember the node.
+ if (Rec.second++ == 0)
+ Rec.first = P;
+ else if (Rec.first->getExtTypes() != P->getExtTypes())
+ PatternTop->error("repetition of value: $" + P->getName() +
+ " where different uses have different types!");
+ }
+
+ if (!P->isLeaf()) {
+ for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
+ FindNames(P->getChild(i), Names, PatternTop);
+ }
+}
+
+void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern,
+ const PatternToMatch &PTM) {
+ // Do some sanity checking on the pattern we're about to match.
+ std::string Reason;
+ if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this))
+ Pattern->error("Pattern can never match: " + Reason);
+
+ // If the source pattern's root is a complex pattern, that complex pattern
+ // must specify the nodes it can potentially match.
+ if (const ComplexPattern *CP =
+ PTM.getSrcPattern()->getComplexPatternInfo(*this))
+ if (CP->getRootNodes().empty())
+ Pattern->error("ComplexPattern at root must specify list of opcodes it"
+ " could match");
+
+
+ // Find all of the named values in the input and output, ensure they have the
+ // same type.
+ std::map<std::string, NameRecord> SrcNames, DstNames;
+ FindNames(PTM.getSrcPattern(), SrcNames, Pattern);
+ FindNames(PTM.getDstPattern(), DstNames, Pattern);
+
+ // Scan all of the named values in the destination pattern, rejecting them if
+ // they don't exist in the input pattern.
+ for (std::map<std::string, NameRecord>::iterator
+ I = DstNames.begin(), E = DstNames.end(); I != E; ++I) {
+ if (SrcNames[I->first].first == 0)
+ Pattern->error("Pattern has input without matching name in output: $" +
+ I->first);
+ }
+
+ // Scan all of the named values in the source pattern, rejecting them if the
+ // name isn't used in the dest, and isn't used to tie two values together.
+ for (std::map<std::string, NameRecord>::iterator
+ I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I)
+ if (DstNames[I->first].first == 0 && SrcNames[I->first].second == 1)
+ Pattern->error("Pattern has dead named input: $" + I->first);
+
+ PatternsToMatch.push_back(PTM);
+}
+
+
+
+void CodeGenDAGPatterns::InferInstructionFlags() {
+ const std::vector<const CodeGenInstruction*> &Instructions =
+ Target.getInstructionsByEnumValue();
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
+ CodeGenInstruction &InstInfo =
+ const_cast<CodeGenInstruction &>(*Instructions[i]);
+ // Determine properties of the instruction from its pattern.
+ bool MayStore, MayLoad, HasSideEffects, IsVariadic;
+ InferFromPattern(InstInfo, MayStore, MayLoad, HasSideEffects, IsVariadic,
+ *this);
+ InstInfo.mayStore = MayStore;
+ InstInfo.mayLoad = MayLoad;
+ InstInfo.hasSideEffects = HasSideEffects;
+ InstInfo.isVariadic = IsVariadic;
+ }
+}
+
+/// Given a pattern result with an unresolved type, see if we can find one
+/// instruction with an unresolved result type. Force this result type to an
+/// arbitrary element if it's possible types to converge results.
+static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) {
+ if (N->isLeaf())
+ return false;
+
+ // Analyze children.
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ if (ForceArbitraryInstResultType(N->getChild(i), TP))
+ return true;
+
+ if (!N->getOperator()->isSubClassOf("Instruction"))
+ return false;
+
+ // If this type is already concrete or completely unknown we can't do
+ // anything.
+ for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) {
+ if (N->getExtType(i).isCompletelyUnknown() || N->getExtType(i).isConcrete())
+ continue;
+
+ // Otherwise, force its type to the first possibility (an arbitrary choice).
+ if (N->getExtType(i).MergeInTypeInfo(N->getExtType(i).getTypeList()[0], TP))
+ return true;
+ }
+
+ return false;
+}
+
+void CodeGenDAGPatterns::ParsePatterns() {
+ std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern");
+
+ for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
+ Record *CurPattern = Patterns[i];
+ DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch");
+ TreePattern *Pattern = new TreePattern(CurPattern, Tree, true, *this);
+
+ // Inline pattern fragments into it.
+ Pattern->InlinePatternFragments();
+
+ ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs");
+ if (LI->getSize() == 0) continue; // no pattern.
+
+ // Parse the instruction.
+ TreePattern *Result = new TreePattern(CurPattern, LI, false, *this);
+
+ // Inline pattern fragments into it.
+ Result->InlinePatternFragments();
+
+ if (Result->getNumTrees() != 1)
+ Result->error("Cannot handle instructions producing instructions "
+ "with temporaries yet!");
+
+ bool IterateInference;
+ bool InferredAllPatternTypes, InferredAllResultTypes;
+ do {
+ // Infer as many types as possible. If we cannot infer all of them, we
+ // can never do anything with this pattern: report it to the user.
+ InferredAllPatternTypes =
+ Pattern->InferAllTypes(&Pattern->getNamedNodesMap());
+
+ // Infer as many types as possible. If we cannot infer all of them, we
+ // can never do anything with this pattern: report it to the user.
+ InferredAllResultTypes =
+ Result->InferAllTypes(&Pattern->getNamedNodesMap());
+
+ IterateInference = false;
+
+ // Apply the type of the result to the source pattern. This helps us
+ // resolve cases where the input type is known to be a pointer type (which
+ // is considered resolved), but the result knows it needs to be 32- or
+ // 64-bits. Infer the other way for good measure.
+ for (unsigned i = 0, e = std::min(Result->getTree(0)->getNumTypes(),
+ Pattern->getTree(0)->getNumTypes());
+ i != e; ++i) {
+ IterateInference = Pattern->getTree(0)->
+ UpdateNodeType(i, Result->getTree(0)->getExtType(i), *Result);
+ IterateInference |= Result->getTree(0)->
+ UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result);
+ }
+
+ // If our iteration has converged and the input pattern's types are fully
+ // resolved but the result pattern is not fully resolved, we may have a
+ // situation where we have two instructions in the result pattern and
+ // the instructions require a common register class, but don't care about
+ // what actual MVT is used. This is actually a bug in our modelling:
+ // output patterns should have register classes, not MVTs.
+ //
+ // In any case, to handle this, we just go through and disambiguate some
+ // arbitrary types to the result pattern's nodes.
+ if (!IterateInference && InferredAllPatternTypes &&
+ !InferredAllResultTypes)
+ IterateInference = ForceArbitraryInstResultType(Result->getTree(0),
+ *Result);
+ } while (IterateInference);
+
+ // Verify that we inferred enough types that we can do something with the
+ // pattern and result. If these fire the user has to add type casts.
+ if (!InferredAllPatternTypes)
+ Pattern->error("Could not infer all types in pattern!");
+ if (!InferredAllResultTypes) {
+ Pattern->dump();
+ Result->error("Could not infer all types in pattern result!");
+ }
+
+ // Validate that the input pattern is correct.
+ std::map<std::string, TreePatternNode*> InstInputs;
+ std::map<std::string, TreePatternNode*> InstResults;
+ std::vector<Record*> InstImpResults;
+ for (unsigned j = 0, ee = Pattern->getNumTrees(); j != ee; ++j)
+ FindPatternInputsAndOutputs(Pattern, Pattern->getTree(j),
+ InstInputs, InstResults,
+ InstImpResults);
+
+ // Promote the xform function to be an explicit node if set.
+ TreePatternNode *DstPattern = Result->getOnlyTree();
+ std::vector<TreePatternNode*> ResultNodeOperands;
+ for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) {
+ TreePatternNode *OpNode = DstPattern->getChild(ii);
+ if (Record *Xform = OpNode->getTransformFn()) {
+ OpNode->setTransformFn(0);
+ std::vector<TreePatternNode*> Children;
+ Children.push_back(OpNode);
+ OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
+ }
+ ResultNodeOperands.push_back(OpNode);
+ }
+ DstPattern = Result->getOnlyTree();
+ if (!DstPattern->isLeaf())
+ DstPattern = new TreePatternNode(DstPattern->getOperator(),
+ ResultNodeOperands,
+ DstPattern->getNumTypes());
+
+ for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i)
+ DstPattern->setType(i, Result->getOnlyTree()->getExtType(i));
+
+ TreePattern Temp(Result->getRecord(), DstPattern, false, *this);
+ Temp.InferAllTypes();
+
+
+ AddPatternToMatch(Pattern,
+ PatternToMatch(CurPattern->getValueAsListInit("Predicates"),
+ Pattern->getTree(0),
+ Temp.getOnlyTree(), InstImpResults,
+ CurPattern->getValueAsInt("AddedComplexity"),
+ CurPattern->getID()));
+ }
+}
+
+/// CombineChildVariants - Given a bunch of permutations of each child of the
+/// 'operator' node, put them together in all possible ways.
+static void CombineChildVariants(TreePatternNode *Orig,
+ const std::vector<std::vector<TreePatternNode*> > &ChildVariants,
+ std::vector<TreePatternNode*> &OutVariants,
+ CodeGenDAGPatterns &CDP,
+ const MultipleUseVarSet &DepVars) {
+ // Make sure that each operand has at least one variant to choose from.
+ for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
+ if (ChildVariants[i].empty())
+ return;
+
+ // The end result is an all-pairs construction of the resultant pattern.
+ std::vector<unsigned> Idxs;
+ Idxs.resize(ChildVariants.size());
+ bool NotDone;
+ do {
+#ifndef NDEBUG
+ DEBUG(if (!Idxs.empty()) {
+ errs() << Orig->getOperator()->getName() << ": Idxs = [ ";
+ for (unsigned i = 0; i < Idxs.size(); ++i) {
+ errs() << Idxs[i] << " ";
+ }
+ errs() << "]\n";
+ });
+#endif
+ // Create the variant and add it to the output list.
+ std::vector<TreePatternNode*> NewChildren;
+ for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
+ NewChildren.push_back(ChildVariants[i][Idxs[i]]);
+ TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren,
+ Orig->getNumTypes());
+
+ // Copy over properties.
+ R->setName(Orig->getName());
+ R->setPredicateFns(Orig->getPredicateFns());
+ R->setTransformFn(Orig->getTransformFn());
+ for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i)
+ R->setType(i, Orig->getExtType(i));
+
+ // If this pattern cannot match, do not include it as a variant.
+ std::string ErrString;
+ if (!R->canPatternMatch(ErrString, CDP)) {
+ delete R;
+ } else {
+ bool AlreadyExists = false;
+
+ // Scan to see if this pattern has already been emitted. We can get
+ // duplication due to things like commuting:
+ // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
+ // which are the same pattern. Ignore the dups.
+ for (unsigned i = 0, e = OutVariants.size(); i != e; ++i)
+ if (R->isIsomorphicTo(OutVariants[i], DepVars)) {
+ AlreadyExists = true;
+ break;
+ }
+
+ if (AlreadyExists)
+ delete R;
+ else
+ OutVariants.push_back(R);
+ }
+
+ // Increment indices to the next permutation by incrementing the
+ // indicies from last index backward, e.g., generate the sequence
+ // [0, 0], [0, 1], [1, 0], [1, 1].
+ int IdxsIdx;
+ for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) {
+ if (++Idxs[IdxsIdx] == ChildVariants[IdxsIdx].size())
+ Idxs[IdxsIdx] = 0;
+ else
+ break;
+ }
+ NotDone = (IdxsIdx >= 0);
+ } while (NotDone);
+}
+
+/// CombineChildVariants - A helper function for binary operators.
+///
+static void CombineChildVariants(TreePatternNode *Orig,
+ const std::vector<TreePatternNode*> &LHS,
+ const std::vector<TreePatternNode*> &RHS,
+ std::vector<TreePatternNode*> &OutVariants,
+ CodeGenDAGPatterns &CDP,
+ const MultipleUseVarSet &DepVars) {
+ std::vector<std::vector<TreePatternNode*> > ChildVariants;
+ ChildVariants.push_back(LHS);
+ ChildVariants.push_back(RHS);
+ CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars);
+}
+
+
+static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N,
+ std::vector<TreePatternNode *> &Children) {
+ assert(N->getNumChildren()==2 &&"Associative but doesn't have 2 children!");
+ Record *Operator = N->getOperator();
+
+ // Only permit raw nodes.
+ if (!N->getName().empty() || !N->getPredicateFns().empty() ||
+ N->getTransformFn()) {
+ Children.push_back(N);
+ return;
+ }
+
+ if (N->getChild(0)->isLeaf() || N->getChild(0)->getOperator() != Operator)
+ Children.push_back(N->getChild(0));
+ else
+ GatherChildrenOfAssociativeOpcode(N->getChild(0), Children);
+
+ if (N->getChild(1)->isLeaf() || N->getChild(1)->getOperator() != Operator)
+ Children.push_back(N->getChild(1));
+ else
+ GatherChildrenOfAssociativeOpcode(N->getChild(1), Children);
+}
+
+/// GenerateVariantsOf - Given a pattern N, generate all permutations we can of
+/// the (potentially recursive) pattern by using algebraic laws.
+///
+static void GenerateVariantsOf(TreePatternNode *N,
+ std::vector<TreePatternNode*> &OutVariants,
+ CodeGenDAGPatterns &CDP,
+ const MultipleUseVarSet &DepVars) {
+ // We cannot permute leaves.
+ if (N->isLeaf()) {
+ OutVariants.push_back(N);
+ return;
+ }
+
+ // Look up interesting info about the node.
+ const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(N->getOperator());
+
+ // If this node is associative, re-associate.
+ if (NodeInfo.hasProperty(SDNPAssociative)) {
+ // Re-associate by pulling together all of the linked operators
+ std::vector<TreePatternNode*> MaximalChildren;
+ GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
+
+ // Only handle child sizes of 3. Otherwise we'll end up trying too many
+ // permutations.
+ if (MaximalChildren.size() == 3) {
+ // Find the variants of all of our maximal children.
+ std::vector<TreePatternNode*> AVariants, BVariants, CVariants;
+ GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars);
+ GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars);
+ GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars);
+
+ // There are only two ways we can permute the tree:
+ // (A op B) op C and A op (B op C)
+ // Within these forms, we can also permute A/B/C.
+
+ // Generate legal pair permutations of A/B/C.
+ std::vector<TreePatternNode*> ABVariants;
+ std::vector<TreePatternNode*> BAVariants;
+ std::vector<TreePatternNode*> ACVariants;
+ std::vector<TreePatternNode*> CAVariants;
+ std::vector<TreePatternNode*> BCVariants;
+ std::vector<TreePatternNode*> CBVariants;
+ CombineChildVariants(N, AVariants, BVariants, ABVariants, CDP, DepVars);
+ CombineChildVariants(N, BVariants, AVariants, BAVariants, CDP, DepVars);
+ CombineChildVariants(N, AVariants, CVariants, ACVariants, CDP, DepVars);
+ CombineChildVariants(N, CVariants, AVariants, CAVariants, CDP, DepVars);
+ CombineChildVariants(N, BVariants, CVariants, BCVariants, CDP, DepVars);
+ CombineChildVariants(N, CVariants, BVariants, CBVariants, CDP, DepVars);
+
+ // Combine those into the result: (x op x) op x
+ CombineChildVariants(N, ABVariants, CVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, BAVariants, CVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, ACVariants, BVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, CAVariants, BVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, BCVariants, AVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, CBVariants, AVariants, OutVariants, CDP, DepVars);
+
+ // Combine those into the result: x op (x op x)
+ CombineChildVariants(N, CVariants, ABVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, CVariants, BAVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, BVariants, ACVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, BVariants, CAVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, AVariants, BCVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, AVariants, CBVariants, OutVariants, CDP, DepVars);
+ return;
+ }
+ }
+
+ // Compute permutations of all children.
+ std::vector<std::vector<TreePatternNode*> > ChildVariants;
+ ChildVariants.resize(N->getNumChildren());
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ GenerateVariantsOf(N->getChild(i), ChildVariants[i], CDP, DepVars);
+
+ // Build all permutations based on how the children were formed.
+ CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars);
+
+ // If this node is commutative, consider the commuted order.
+ bool isCommIntrinsic = N->isCommutativeIntrinsic(CDP);
+ if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) {
+ assert((N->getNumChildren()==2 || isCommIntrinsic) &&
+ "Commutative but doesn't have 2 children!");
+ // Don't count children which are actually register references.
+ unsigned NC = 0;
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = N->getChild(i);
+ if (Child->isLeaf())
+ if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
+ Record *RR = DI->getDef();
+ if (RR->isSubClassOf("Register"))
+ continue;
+ }
+ NC++;
+ }
+ // Consider the commuted order.
+ if (isCommIntrinsic) {
+ // Commutative intrinsic. First operand is the intrinsic id, 2nd and 3rd
+ // operands are the commutative operands, and there might be more operands
+ // after those.
+ assert(NC >= 3 &&
+ "Commutative intrinsic should have at least 3 childrean!");
+ std::vector<std::vector<TreePatternNode*> > Variants;
+ Variants.push_back(ChildVariants[0]); // Intrinsic id.
+ Variants.push_back(ChildVariants[2]);
+ Variants.push_back(ChildVariants[1]);
+ for (unsigned i = 3; i != NC; ++i)
+ Variants.push_back(ChildVariants[i]);
+ CombineChildVariants(N, Variants, OutVariants, CDP, DepVars);
+ } else if (NC == 2)
+ CombineChildVariants(N, ChildVariants[1], ChildVariants[0],
+ OutVariants, CDP, DepVars);
+ }
+}
+
+
+// GenerateVariants - Generate variants. For example, commutative patterns can
+// match multiple ways. Add them to PatternsToMatch as well.
+void CodeGenDAGPatterns::GenerateVariants() {
+ DEBUG(errs() << "Generating instruction variants.\n");
+
+ // Loop over all of the patterns we've collected, checking to see if we can
+ // generate variants of the instruction, through the exploitation of
+ // identities. This permits the target to provide aggressive matching without
+ // the .td file having to contain tons of variants of instructions.
+ //
+ // Note that this loop adds new patterns to the PatternsToMatch list, but we
+ // intentionally do not reconsider these. Any variants of added patterns have
+ // already been added.
+ //
+ for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
+ MultipleUseVarSet DepVars;
+ std::vector<TreePatternNode*> Variants;
+ FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars);
+ DEBUG(errs() << "Dependent/multiply used variables: ");
+ DEBUG(DumpDepVars(DepVars));
+ DEBUG(errs() << "\n");
+ GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this, DepVars);
+
+ assert(!Variants.empty() && "Must create at least original variant!");
+ Variants.erase(Variants.begin()); // Remove the original pattern.
+
+ if (Variants.empty()) // No variants for this pattern.
+ continue;
+
+ DEBUG(errs() << "FOUND VARIANTS OF: ";
+ PatternsToMatch[i].getSrcPattern()->dump();
+ errs() << "\n");
+
+ for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
+ TreePatternNode *Variant = Variants[v];
+
+ DEBUG(errs() << " VAR#" << v << ": ";
+ Variant->dump();
+ errs() << "\n");
+
+ // Scan to see if an instruction or explicit pattern already matches this.
+ bool AlreadyExists = false;
+ for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
+ // Skip if the top level predicates do not match.
+ if (PatternsToMatch[i].getPredicates() !=
+ PatternsToMatch[p].getPredicates())
+ continue;
+ // Check to see if this variant already exists.
+ if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(), DepVars)) {
+ DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n");
+ AlreadyExists = true;
+ break;
+ }
+ }
+ // If we already have it, ignore the variant.
+ if (AlreadyExists) continue;
+
+ // Otherwise, add it to the list of patterns we have.
+ PatternsToMatch.
+ push_back(PatternToMatch(PatternsToMatch[i].getPredicates(),
+ Variant, PatternsToMatch[i].getDstPattern(),
+ PatternsToMatch[i].getDstRegs(),
+ PatternsToMatch[i].getAddedComplexity(),
+ Record::getNewUID()));
+ }
+
+ DEBUG(errs() << "\n");
+ }
+}
+
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
new file mode 100644
index 0000000..0a1362a
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
@@ -0,0 +1,748 @@
+//===- CodeGenDAGPatterns.h - Read DAG patterns from .td file ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the CodeGenDAGPatterns class, which is used to read and
+// represent the patterns present in a .td file for instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_DAGPATTERNS_H
+#define CODEGEN_DAGPATTERNS_H
+
+#include "CodeGenTarget.h"
+#include "CodeGenIntrinsics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include <set>
+#include <algorithm>
+#include <vector>
+#include <map>
+
+namespace llvm {
+ class Record;
+ struct Init;
+ class ListInit;
+ class DagInit;
+ class SDNodeInfo;
+ class TreePattern;
+ class TreePatternNode;
+ class CodeGenDAGPatterns;
+ class ComplexPattern;
+
+/// EEVT::DAGISelGenValueType - These are some extended forms of
+/// MVT::SimpleValueType that we use as lattice values during type inference.
+/// The existing MVT iAny, fAny and vAny types suffice to represent
+/// arbitrary integer, floating-point, and vector types, so only an unknown
+/// value is needed.
+namespace EEVT {
+ /// TypeSet - This is either empty if it's completely unknown, or holds a set
+ /// of types. It is used during type inference because register classes can
+ /// have multiple possible types and we don't know which one they get until
+ /// type inference is complete.
+ ///
+ /// TypeSet can have three states:
+ /// Vector is empty: The type is completely unknown, it can be any valid
+ /// target type.
+ /// Vector has multiple constrained types: (e.g. v4i32 + v4f32) it is one
+ /// of those types only.
+ /// Vector has one concrete type: The type is completely known.
+ ///
+ class TypeSet {
+ SmallVector<MVT::SimpleValueType, 4> TypeVec;
+ public:
+ TypeSet() {}
+ TypeSet(MVT::SimpleValueType VT, TreePattern &TP);
+ TypeSet(const std::vector<MVT::SimpleValueType> &VTList);
+
+ bool isCompletelyUnknown() const { return TypeVec.empty(); }
+
+ bool isConcrete() const {
+ if (TypeVec.size() != 1) return false;
+ unsigned char T = TypeVec[0]; (void)T;
+ assert(T < MVT::LAST_VALUETYPE || T == MVT::iPTR || T == MVT::iPTRAny);
+ return true;
+ }
+
+ MVT::SimpleValueType getConcrete() const {
+ assert(isConcrete() && "Type isn't concrete yet");
+ return (MVT::SimpleValueType)TypeVec[0];
+ }
+
+ bool isDynamicallyResolved() const {
+ return getConcrete() == MVT::iPTR || getConcrete() == MVT::iPTRAny;
+ }
+
+ const SmallVectorImpl<MVT::SimpleValueType> &getTypeList() const {
+ assert(!TypeVec.empty() && "Not a type list!");
+ return TypeVec;
+ }
+
+ bool isVoid() const {
+ return TypeVec.size() == 1 && TypeVec[0] == MVT::isVoid;
+ }
+
+ /// hasIntegerTypes - Return true if this TypeSet contains any integer value
+ /// types.
+ bool hasIntegerTypes() const;
+
+ /// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
+ /// a floating point value type.
+ bool hasFloatingPointTypes() const;
+
+ /// hasVectorTypes - Return true if this TypeSet contains a vector value
+ /// type.
+ bool hasVectorTypes() const;
+
+ /// getName() - Return this TypeSet as a string.
+ std::string getName() const;
+
+ /// MergeInTypeInfo - This merges in type information from the specified
+ /// argument. If 'this' changes, it returns true. If the two types are
+ /// contradictory (e.g. merge f32 into i32) then this throws an exception.
+ bool MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP);
+
+ bool MergeInTypeInfo(MVT::SimpleValueType InVT, TreePattern &TP) {
+ return MergeInTypeInfo(EEVT::TypeSet(InVT, TP), TP);
+ }
+
+ /// Force this type list to only contain integer types.
+ bool EnforceInteger(TreePattern &TP);
+
+ /// Force this type list to only contain floating point types.
+ bool EnforceFloatingPoint(TreePattern &TP);
+
+ /// EnforceScalar - Remove all vector types from this type list.
+ bool EnforceScalar(TreePattern &TP);
+
+ /// EnforceVector - Remove all non-vector types from this type list.
+ bool EnforceVector(TreePattern &TP);
+
+ /// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update
+ /// this an other based on this information.
+ bool EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP);
+
+ /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
+ /// whose element is VT.
+ bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
+
+ bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; }
+ bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; }
+
+ private:
+ /// FillWithPossibleTypes - Set to all legal types and return true, only
+ /// valid on completely unknown type sets. If Pred is non-null, only MVTs
+ /// that pass the predicate are added.
+ bool FillWithPossibleTypes(TreePattern &TP,
+ bool (*Pred)(MVT::SimpleValueType) = 0,
+ const char *PredicateName = 0);
+ };
+}
+
+/// Set type used to track multiply used variables in patterns
+typedef std::set<std::string> MultipleUseVarSet;
+
+/// SDTypeConstraint - This is a discriminated union of constraints,
+/// corresponding to the SDTypeConstraint tablegen class in Target.td.
+struct SDTypeConstraint {
+ SDTypeConstraint(Record *R);
+
+ unsigned OperandNo; // The operand # this constraint applies to.
+ enum {
+ SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
+ SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec
+ } ConstraintType;
+
+ union { // The discriminated union.
+ struct {
+ MVT::SimpleValueType VT;
+ } SDTCisVT_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisSameAs_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisVTSmallerThanOp_Info;
+ struct {
+ unsigned BigOperandNum;
+ } SDTCisOpSmallerThanOp_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisEltOfVec_Info;
+ } x;
+
+ /// ApplyTypeConstraint - Given a node in a pattern, apply this type
+ /// constraint to the nodes operands. This returns true if it makes a
+ /// change, false otherwise. If a type contradiction is found, throw an
+ /// exception.
+ bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo,
+ TreePattern &TP) const;
+};
+
+/// SDNodeInfo - One of these records is created for each SDNode instance in
+/// the target .td file. This represents the various dag nodes we will be
+/// processing.
+class SDNodeInfo {
+ Record *Def;
+ std::string EnumName;
+ std::string SDClassName;
+ unsigned Properties;
+ unsigned NumResults;
+ int NumOperands;
+ std::vector<SDTypeConstraint> TypeConstraints;
+public:
+ SDNodeInfo(Record *R); // Parse the specified record.
+
+ unsigned getNumResults() const { return NumResults; }
+
+ /// getNumOperands - This is the number of operands required or -1 if
+ /// variadic.
+ int getNumOperands() const { return NumOperands; }
+ Record *getRecord() const { return Def; }
+ const std::string &getEnumName() const { return EnumName; }
+ const std::string &getSDClassName() const { return SDClassName; }
+
+ const std::vector<SDTypeConstraint> &getTypeConstraints() const {
+ return TypeConstraints;
+ }
+
+ /// getKnownType - If the type constraints on this node imply a fixed type
+ /// (e.g. all stores return void, etc), then return it as an
+ /// MVT::SimpleValueType. Otherwise, return MVT::Other.
+ MVT::SimpleValueType getKnownType(unsigned ResNo) const;
+
+ /// hasProperty - Return true if this node has the specified property.
+ ///
+ bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
+
+ /// ApplyTypeConstraints - Given a node in a pattern, apply the type
+ /// constraints for this node to the operands of the node. This returns
+ /// true if it makes a change, false otherwise. If a type contradiction is
+ /// found, throw an exception.
+ bool ApplyTypeConstraints(TreePatternNode *N, TreePattern &TP) const {
+ bool MadeChange = false;
+ for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i)
+ MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP);
+ return MadeChange;
+ }
+};
+
+/// FIXME: TreePatternNode's can be shared in some cases (due to dag-shaped
+/// patterns), and as such should be ref counted. We currently just leak all
+/// TreePatternNode objects!
+class TreePatternNode {
+ /// The type of each node result. Before and during type inference, each
+ /// result may be a set of possible types. After (successful) type inference,
+ /// each is a single concrete type.
+ SmallVector<EEVT::TypeSet, 1> Types;
+
+ /// Operator - The Record for the operator if this is an interior node (not
+ /// a leaf).
+ Record *Operator;
+
+ /// Val - The init value (e.g. the "GPRC" record, or "7") for a leaf.
+ ///
+ Init *Val;
+
+ /// Name - The name given to this node with the :$foo notation.
+ ///
+ std::string Name;
+
+ /// PredicateFns - The predicate functions to execute on this node to check
+ /// for a match. If this list is empty, no predicate is involved.
+ std::vector<std::string> PredicateFns;
+
+ /// TransformFn - The transformation function to execute on this node before
+ /// it can be substituted into the resulting instruction on a pattern match.
+ Record *TransformFn;
+
+ std::vector<TreePatternNode*> Children;
+public:
+ TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch,
+ unsigned NumResults)
+ : Operator(Op), Val(0), TransformFn(0), Children(Ch) {
+ Types.resize(NumResults);
+ }
+ TreePatternNode(Init *val, unsigned NumResults) // leaf ctor
+ : Operator(0), Val(val), TransformFn(0) {
+ Types.resize(NumResults);
+ }
+ ~TreePatternNode();
+
+ const std::string &getName() const { return Name; }
+ void setName(StringRef N) { Name.assign(N.begin(), N.end()); }
+
+ bool isLeaf() const { return Val != 0; }
+
+ // Type accessors.
+ unsigned getNumTypes() const { return Types.size(); }
+ MVT::SimpleValueType getType(unsigned ResNo) const {
+ return Types[ResNo].getConcrete();
+ }
+ const SmallVectorImpl<EEVT::TypeSet> &getExtTypes() const { return Types; }
+ const EEVT::TypeSet &getExtType(unsigned ResNo) const { return Types[ResNo]; }
+ EEVT::TypeSet &getExtType(unsigned ResNo) { return Types[ResNo]; }
+ void setType(unsigned ResNo, const EEVT::TypeSet &T) { Types[ResNo] = T; }
+
+ bool hasTypeSet(unsigned ResNo) const {
+ return Types[ResNo].isConcrete();
+ }
+ bool isTypeCompletelyUnknown(unsigned ResNo) const {
+ return Types[ResNo].isCompletelyUnknown();
+ }
+ bool isTypeDynamicallyResolved(unsigned ResNo) const {
+ return Types[ResNo].isDynamicallyResolved();
+ }
+
+ Init *getLeafValue() const { assert(isLeaf()); return Val; }
+ Record *getOperator() const { assert(!isLeaf()); return Operator; }
+
+ unsigned getNumChildren() const { return Children.size(); }
+ TreePatternNode *getChild(unsigned N) const { return Children[N]; }
+ void setChild(unsigned i, TreePatternNode *N) {
+ Children[i] = N;
+ }
+
+ /// hasChild - Return true if N is any of our children.
+ bool hasChild(const TreePatternNode *N) const {
+ for (unsigned i = 0, e = Children.size(); i != e; ++i)
+ if (Children[i] == N) return true;
+ return false;
+ }
+
+ const std::vector<std::string> &getPredicateFns() const {return PredicateFns;}
+ void clearPredicateFns() { PredicateFns.clear(); }
+ void setPredicateFns(const std::vector<std::string> &Fns) {
+ assert(PredicateFns.empty() && "Overwriting non-empty predicate list!");
+ PredicateFns = Fns;
+ }
+ void addPredicateFn(const std::string &Fn) {
+ assert(!Fn.empty() && "Empty predicate string!");
+ if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) ==
+ PredicateFns.end())
+ PredicateFns.push_back(Fn);
+ }
+
+ Record *getTransformFn() const { return TransformFn; }
+ void setTransformFn(Record *Fn) { TransformFn = Fn; }
+
+ /// getIntrinsicInfo - If this node corresponds to an intrinsic, return the
+ /// CodeGenIntrinsic information for it, otherwise return a null pointer.
+ const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const;
+
+ /// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
+ /// return the ComplexPattern information, otherwise return null.
+ const ComplexPattern *
+ getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const;
+
+ /// NodeHasProperty - Return true if this node has the specified property.
+ bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
+
+ /// TreeHasProperty - Return true if any node in this tree has the specified
+ /// property.
+ bool TreeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
+
+ /// isCommutativeIntrinsic - Return true if the node is an intrinsic which is
+ /// marked isCommutative.
+ bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const;
+
+ void print(raw_ostream &OS) const;
+ void dump() const;
+
+public: // Higher level manipulation routines.
+
+ /// clone - Return a new copy of this tree.
+ ///
+ TreePatternNode *clone() const;
+
+ /// RemoveAllTypes - Recursively strip all the types of this tree.
+ void RemoveAllTypes();
+
+ /// isIsomorphicTo - Return true if this node is recursively isomorphic to
+ /// the specified node. For this comparison, all of the state of the node
+ /// is considered, except for the assigned name. Nodes with differing names
+ /// that are otherwise identical are considered isomorphic.
+ bool isIsomorphicTo(const TreePatternNode *N,
+ const MultipleUseVarSet &DepVars) const;
+
+ /// SubstituteFormalArguments - Replace the formal arguments in this tree
+ /// with actual values specified by ArgMap.
+ void SubstituteFormalArguments(std::map<std::string,
+ TreePatternNode*> &ArgMap);
+
+ /// InlinePatternFragments - If this pattern refers to any pattern
+ /// fragments, inline them into place, giving us a pattern without any
+ /// PatFrag references.
+ TreePatternNode *InlinePatternFragments(TreePattern &TP);
+
+ /// ApplyTypeConstraints - Apply all of the type constraints relevant to
+ /// this node and its children in the tree. This returns true if it makes a
+ /// change, false otherwise. If a type contradiction is found, throw an
+ /// exception.
+ bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters);
+
+ /// UpdateNodeType - Set the node type of N to VT if VT contains
+ /// information. If N already contains a conflicting type, then throw an
+ /// exception. This returns true if any information was updated.
+ ///
+ bool UpdateNodeType(unsigned ResNo, const EEVT::TypeSet &InTy,
+ TreePattern &TP) {
+ return Types[ResNo].MergeInTypeInfo(InTy, TP);
+ }
+
+ bool UpdateNodeType(unsigned ResNo, MVT::SimpleValueType InTy,
+ TreePattern &TP) {
+ return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP);
+ }
+
+ /// ContainsUnresolvedType - Return true if this tree contains any
+ /// unresolved types.
+ bool ContainsUnresolvedType() const {
+ for (unsigned i = 0, e = Types.size(); i != e; ++i)
+ if (!Types[i].isConcrete()) return true;
+
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (getChild(i)->ContainsUnresolvedType()) return true;
+ return false;
+ }
+
+ /// canPatternMatch - If it is impossible for this pattern to match on this
+ /// target, fill in Reason and return false. Otherwise, return true.
+ bool canPatternMatch(std::string &Reason, const CodeGenDAGPatterns &CDP);
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const TreePatternNode &TPN) {
+ TPN.print(OS);
+ return OS;
+}
+
+
+/// TreePattern - Represent a pattern, used for instructions, pattern
+/// fragments, etc.
+///
+class TreePattern {
+ /// Trees - The list of pattern trees which corresponds to this pattern.
+ /// Note that PatFrag's only have a single tree.
+ ///
+ std::vector<TreePatternNode*> Trees;
+
+ /// NamedNodes - This is all of the nodes that have names in the trees in this
+ /// pattern.
+ StringMap<SmallVector<TreePatternNode*,1> > NamedNodes;
+
+ /// TheRecord - The actual TableGen record corresponding to this pattern.
+ ///
+ Record *TheRecord;
+
+ /// Args - This is a list of all of the arguments to this pattern (for
+ /// PatFrag patterns), which are the 'node' markers in this pattern.
+ std::vector<std::string> Args;
+
+ /// CDP - the top-level object coordinating this madness.
+ ///
+ CodeGenDAGPatterns &CDP;
+
+ /// isInputPattern - True if this is an input pattern, something to match.
+ /// False if this is an output pattern, something to emit.
+ bool isInputPattern;
+public:
+
+ /// TreePattern constructor - Parse the specified DagInits into the
+ /// current record.
+ TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
+ CodeGenDAGPatterns &ise);
+ TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
+ CodeGenDAGPatterns &ise);
+ TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
+ CodeGenDAGPatterns &ise);
+
+ /// getTrees - Return the tree patterns which corresponds to this pattern.
+ ///
+ const std::vector<TreePatternNode*> &getTrees() const { return Trees; }
+ unsigned getNumTrees() const { return Trees.size(); }
+ TreePatternNode *getTree(unsigned i) const { return Trees[i]; }
+ TreePatternNode *getOnlyTree() const {
+ assert(Trees.size() == 1 && "Doesn't have exactly one pattern!");
+ return Trees[0];
+ }
+
+ const StringMap<SmallVector<TreePatternNode*,1> > &getNamedNodesMap() {
+ if (NamedNodes.empty())
+ ComputeNamedNodes();
+ return NamedNodes;
+ }
+
+ /// getRecord - Return the actual TableGen record corresponding to this
+ /// pattern.
+ ///
+ Record *getRecord() const { return TheRecord; }
+
+ unsigned getNumArgs() const { return Args.size(); }
+ const std::string &getArgName(unsigned i) const {
+ assert(i < Args.size() && "Argument reference out of range!");
+ return Args[i];
+ }
+ std::vector<std::string> &getArgList() { return Args; }
+
+ CodeGenDAGPatterns &getDAGPatterns() const { return CDP; }
+
+ /// InlinePatternFragments - If this pattern refers to any pattern
+ /// fragments, inline them into place, giving us a pattern without any
+ /// PatFrag references.
+ void InlinePatternFragments() {
+ for (unsigned i = 0, e = Trees.size(); i != e; ++i)
+ Trees[i] = Trees[i]->InlinePatternFragments(*this);
+ }
+
+ /// InferAllTypes - Infer/propagate as many types throughout the expression
+ /// patterns as possible. Return true if all types are inferred, false
+ /// otherwise. Throw an exception if a type contradiction is found.
+ bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> >
+ *NamedTypes=0);
+
+ /// error - Throw an exception, prefixing it with information about this
+ /// pattern.
+ void error(const std::string &Msg) const;
+
+ void print(raw_ostream &OS) const;
+ void dump() const;
+
+private:
+ TreePatternNode *ParseTreePattern(Init *DI, StringRef OpName);
+ void ComputeNamedNodes();
+ void ComputeNamedNodes(TreePatternNode *N);
+};
+
+/// DAGDefaultOperand - One of these is created for each PredicateOperand
+/// or OptionalDefOperand that has a set ExecuteAlways / DefaultOps field.
+struct DAGDefaultOperand {
+ std::vector<TreePatternNode*> DefaultOps;
+};
+
+class DAGInstruction {
+ TreePattern *Pattern;
+ std::vector<Record*> Results;
+ std::vector<Record*> Operands;
+ std::vector<Record*> ImpResults;
+ TreePatternNode *ResultPattern;
+public:
+ DAGInstruction(TreePattern *TP,
+ const std::vector<Record*> &results,
+ const std::vector<Record*> &operands,
+ const std::vector<Record*> &impresults)
+ : Pattern(TP), Results(results), Operands(operands),
+ ImpResults(impresults), ResultPattern(0) {}
+
+ const TreePattern *getPattern() const { return Pattern; }
+ unsigned getNumResults() const { return Results.size(); }
+ unsigned getNumOperands() const { return Operands.size(); }
+ unsigned getNumImpResults() const { return ImpResults.size(); }
+ const std::vector<Record*>& getImpResults() const { return ImpResults; }
+
+ void setResultPattern(TreePatternNode *R) { ResultPattern = R; }
+
+ Record *getResult(unsigned RN) const {
+ assert(RN < Results.size());
+ return Results[RN];
+ }
+
+ Record *getOperand(unsigned ON) const {
+ assert(ON < Operands.size());
+ return Operands[ON];
+ }
+
+ Record *getImpResult(unsigned RN) const {
+ assert(RN < ImpResults.size());
+ return ImpResults[RN];
+ }
+
+ TreePatternNode *getResultPattern() const { return ResultPattern; }
+};
+
+/// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns
+/// processed to produce isel.
+class PatternToMatch {
+public:
+ PatternToMatch(ListInit *preds,
+ TreePatternNode *src, TreePatternNode *dst,
+ const std::vector<Record*> &dstregs,
+ unsigned complexity, unsigned uid)
+ : Predicates(preds), SrcPattern(src), DstPattern(dst),
+ Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {}
+
+ ListInit *Predicates; // Top level predicate conditions to match.
+ TreePatternNode *SrcPattern; // Source pattern to match.
+ TreePatternNode *DstPattern; // Resulting pattern.
+ std::vector<Record*> Dstregs; // Physical register defs being matched.
+ unsigned AddedComplexity; // Add to matching pattern complexity.
+ unsigned ID; // Unique ID for the record.
+
+ ListInit *getPredicates() const { return Predicates; }
+ TreePatternNode *getSrcPattern() const { return SrcPattern; }
+ TreePatternNode *getDstPattern() const { return DstPattern; }
+ const std::vector<Record*> &getDstRegs() const { return Dstregs; }
+ unsigned getAddedComplexity() const { return AddedComplexity; }
+
+ std::string getPredicateCheck() const;
+
+ /// Compute the complexity metric for the input pattern. This roughly
+ /// corresponds to the number of nodes that are covered.
+ unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const;
+};
+
+// Deterministic comparison of Record*.
+struct RecordPtrCmp {
+ bool operator()(const Record *LHS, const Record *RHS) const;
+};
+
+class CodeGenDAGPatterns {
+ RecordKeeper &Records;
+ CodeGenTarget Target;
+ std::vector<CodeGenIntrinsic> Intrinsics;
+ std::vector<CodeGenIntrinsic> TgtIntrinsics;
+
+ std::map<Record*, SDNodeInfo, RecordPtrCmp> SDNodes;
+ std::map<Record*, std::pair<Record*, std::string>, RecordPtrCmp> SDNodeXForms;
+ std::map<Record*, ComplexPattern, RecordPtrCmp> ComplexPatterns;
+ std::map<Record*, TreePattern*, RecordPtrCmp> PatternFragments;
+ std::map<Record*, DAGDefaultOperand, RecordPtrCmp> DefaultOperands;
+ std::map<Record*, DAGInstruction, RecordPtrCmp> Instructions;
+
+ // Specific SDNode definitions:
+ Record *intrinsic_void_sdnode;
+ Record *intrinsic_w_chain_sdnode, *intrinsic_wo_chain_sdnode;
+
+ /// PatternsToMatch - All of the things we are matching on the DAG. The first
+ /// value is the pattern to match, the second pattern is the result to
+ /// emit.
+ std::vector<PatternToMatch> PatternsToMatch;
+public:
+ CodeGenDAGPatterns(RecordKeeper &R);
+ ~CodeGenDAGPatterns();
+
+ CodeGenTarget &getTargetInfo() { return Target; }
+ const CodeGenTarget &getTargetInfo() const { return Target; }
+
+ Record *getSDNodeNamed(const std::string &Name) const;
+
+ const SDNodeInfo &getSDNodeInfo(Record *R) const {
+ assert(SDNodes.count(R) && "Unknown node!");
+ return SDNodes.find(R)->second;
+ }
+
+ // Node transformation lookups.
+ typedef std::pair<Record*, std::string> NodeXForm;
+ const NodeXForm &getSDNodeTransform(Record *R) const {
+ assert(SDNodeXForms.count(R) && "Invalid transform!");
+ return SDNodeXForms.find(R)->second;
+ }
+
+ typedef std::map<Record*, NodeXForm, RecordPtrCmp>::const_iterator
+ nx_iterator;
+ nx_iterator nx_begin() const { return SDNodeXForms.begin(); }
+ nx_iterator nx_end() const { return SDNodeXForms.end(); }
+
+
+ const ComplexPattern &getComplexPattern(Record *R) const {
+ assert(ComplexPatterns.count(R) && "Unknown addressing mode!");
+ return ComplexPatterns.find(R)->second;
+ }
+
+ const CodeGenIntrinsic &getIntrinsic(Record *R) const {
+ for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
+ if (Intrinsics[i].TheDef == R) return Intrinsics[i];
+ for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i)
+ if (TgtIntrinsics[i].TheDef == R) return TgtIntrinsics[i];
+ assert(0 && "Unknown intrinsic!");
+ abort();
+ }
+
+ const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const {
+ if (IID-1 < Intrinsics.size())
+ return Intrinsics[IID-1];
+ if (IID-Intrinsics.size()-1 < TgtIntrinsics.size())
+ return TgtIntrinsics[IID-Intrinsics.size()-1];
+ assert(0 && "Bad intrinsic ID!");
+ abort();
+ }
+
+ unsigned getIntrinsicID(Record *R) const {
+ for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
+ if (Intrinsics[i].TheDef == R) return i;
+ for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i)
+ if (TgtIntrinsics[i].TheDef == R) return i + Intrinsics.size();
+ assert(0 && "Unknown intrinsic!");
+ abort();
+ }
+
+ const DAGDefaultOperand &getDefaultOperand(Record *R) const {
+ assert(DefaultOperands.count(R) &&"Isn't an analyzed default operand!");
+ return DefaultOperands.find(R)->second;
+ }
+
+ // Pattern Fragment information.
+ TreePattern *getPatternFragment(Record *R) const {
+ assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
+ return PatternFragments.find(R)->second;
+ }
+ TreePattern *getPatternFragmentIfRead(Record *R) const {
+ if (!PatternFragments.count(R)) return 0;
+ return PatternFragments.find(R)->second;
+ }
+
+ typedef std::map<Record*, TreePattern*, RecordPtrCmp>::const_iterator
+ pf_iterator;
+ pf_iterator pf_begin() const { return PatternFragments.begin(); }
+ pf_iterator pf_end() const { return PatternFragments.end(); }
+
+ // Patterns to match information.
+ typedef std::vector<PatternToMatch>::const_iterator ptm_iterator;
+ ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); }
+ ptm_iterator ptm_end() const { return PatternsToMatch.end(); }
+
+
+
+ const DAGInstruction &getInstruction(Record *R) const {
+ assert(Instructions.count(R) && "Unknown instruction!");
+ return Instructions.find(R)->second;
+ }
+
+ Record *get_intrinsic_void_sdnode() const {
+ return intrinsic_void_sdnode;
+ }
+ Record *get_intrinsic_w_chain_sdnode() const {
+ return intrinsic_w_chain_sdnode;
+ }
+ Record *get_intrinsic_wo_chain_sdnode() const {
+ return intrinsic_wo_chain_sdnode;
+ }
+
+ bool hasTargetIntrinsics() { return !TgtIntrinsics.empty(); }
+
+private:
+ void ParseNodeInfo();
+ void ParseNodeTransforms();
+ void ParseComplexPatterns();
+ void ParsePatternFragments();
+ void ParseDefaultOperands();
+ void ParseInstructions();
+ void ParsePatterns();
+ void InferInstructionFlags();
+ void GenerateVariants();
+
+ void AddPatternToMatch(const TreePattern *Pattern, const PatternToMatch &PTM);
+ void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
+ std::map<std::string,
+ TreePatternNode*> &InstInputs,
+ std::map<std::string,
+ TreePatternNode*> &InstResults,
+ std::vector<Record*> &InstImpResults);
+};
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
new file mode 100644
index 0000000..01a1fe1
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -0,0 +1,306 @@
+//===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the CodeGenInstruction class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenInstruction.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/STLExtras.h"
+#include <set>
+using namespace llvm;
+
+static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
+ // EARLY_CLOBBER: @early $reg
+ std::string::size_type wpos = CStr.find_first_of(" \t");
+ std::string::size_type start = CStr.find_first_not_of(" \t");
+ std::string Tok = CStr.substr(start, wpos - start);
+ if (Tok == "@earlyclobber") {
+ std::string Name = CStr.substr(wpos+1);
+ wpos = Name.find_first_not_of(" \t");
+ if (wpos == std::string::npos)
+ throw "Illegal format for @earlyclobber constraint: '" + CStr + "'";
+ Name = Name.substr(wpos);
+ std::pair<unsigned,unsigned> Op =
+ I->ParseOperandName(Name, false);
+
+ // Build the string for the operand
+ if (!I->OperandList[Op.first].Constraints[Op.second].isNone())
+ throw "Operand '" + Name + "' cannot have multiple constraints!";
+ I->OperandList[Op.first].Constraints[Op.second] =
+ CodeGenInstruction::ConstraintInfo::getEarlyClobber();
+ return;
+ }
+
+ // Only other constraint is "TIED_TO" for now.
+ std::string::size_type pos = CStr.find_first_of('=');
+ assert(pos != std::string::npos && "Unrecognized constraint");
+ start = CStr.find_first_not_of(" \t");
+ std::string Name = CStr.substr(start, pos - start);
+
+ // TIED_TO: $src1 = $dst
+ wpos = Name.find_first_of(" \t");
+ if (wpos == std::string::npos)
+ throw "Illegal format for tied-to constraint: '" + CStr + "'";
+ std::string DestOpName = Name.substr(0, wpos);
+ std::pair<unsigned,unsigned> DestOp = I->ParseOperandName(DestOpName, false);
+
+ Name = CStr.substr(pos+1);
+ wpos = Name.find_first_not_of(" \t");
+ if (wpos == std::string::npos)
+ throw "Illegal format for tied-to constraint: '" + CStr + "'";
+
+ std::pair<unsigned,unsigned> SrcOp =
+ I->ParseOperandName(Name.substr(wpos), false);
+ if (SrcOp > DestOp)
+ throw "Illegal tied-to operand constraint '" + CStr + "'";
+
+
+ unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp);
+
+ if (!I->OperandList[DestOp.first].Constraints[DestOp.second].isNone())
+ throw "Operand '" + DestOpName + "' cannot have multiple constraints!";
+ I->OperandList[DestOp.first].Constraints[DestOp.second] =
+ CodeGenInstruction::ConstraintInfo::getTied(FlatOpNo);
+}
+
+static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) {
+ // Make sure the constraints list for each operand is large enough to hold
+ // constraint info, even if none is present.
+ for (unsigned i = 0, e = I->OperandList.size(); i != e; ++i)
+ I->OperandList[i].Constraints.resize(I->OperandList[i].MINumOperands);
+
+ if (CStr.empty()) return;
+
+ const std::string delims(",");
+ std::string::size_type bidx, eidx;
+
+ bidx = CStr.find_first_not_of(delims);
+ while (bidx != std::string::npos) {
+ eidx = CStr.find_first_of(delims, bidx);
+ if (eidx == std::string::npos)
+ eidx = CStr.length();
+
+ ParseConstraint(CStr.substr(bidx, eidx - bidx), I);
+ bidx = CStr.find_first_not_of(delims, eidx);
+ }
+}
+
+CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
+ : TheDef(R), AsmString(AsmStr) {
+ Namespace = R->getValueAsString("Namespace");
+
+ isReturn = R->getValueAsBit("isReturn");
+ isBranch = R->getValueAsBit("isBranch");
+ isIndirectBranch = R->getValueAsBit("isIndirectBranch");
+ isCompare = R->getValueAsBit("isCompare");
+ isBarrier = R->getValueAsBit("isBarrier");
+ isCall = R->getValueAsBit("isCall");
+ canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
+ mayLoad = R->getValueAsBit("mayLoad");
+ mayStore = R->getValueAsBit("mayStore");
+ isPredicable = R->getValueAsBit("isPredicable");
+ isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
+ isCommutable = R->getValueAsBit("isCommutable");
+ isTerminator = R->getValueAsBit("isTerminator");
+ isReMaterializable = R->getValueAsBit("isReMaterializable");
+ hasDelaySlot = R->getValueAsBit("hasDelaySlot");
+ usesCustomInserter = R->getValueAsBit("usesCustomInserter");
+ hasCtrlDep = R->getValueAsBit("hasCtrlDep");
+ isNotDuplicable = R->getValueAsBit("isNotDuplicable");
+ hasSideEffects = R->getValueAsBit("hasSideEffects");
+ neverHasSideEffects = R->getValueAsBit("neverHasSideEffects");
+ isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
+ hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
+ hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq");
+ hasOptionalDef = false;
+ isVariadic = false;
+ ImplicitDefs = R->getValueAsListOfDefs("Defs");
+ ImplicitUses = R->getValueAsListOfDefs("Uses");
+
+ if (neverHasSideEffects + hasSideEffects > 1)
+ throw R->getName() + ": multiple conflicting side-effect flags set!";
+
+ DagInit *OutDI = R->getValueAsDag("OutOperandList");
+
+ if (DefInit *Init = dynamic_cast<DefInit*>(OutDI->getOperator())) {
+ if (Init->getDef()->getName() != "outs")
+ throw R->getName() + ": invalid def name for output list: use 'outs'";
+ } else
+ throw R->getName() + ": invalid output list: use 'outs'";
+
+ NumDefs = OutDI->getNumArgs();
+
+ DagInit *InDI = R->getValueAsDag("InOperandList");
+ if (DefInit *Init = dynamic_cast<DefInit*>(InDI->getOperator())) {
+ if (Init->getDef()->getName() != "ins")
+ throw R->getName() + ": invalid def name for input list: use 'ins'";
+ } else
+ throw R->getName() + ": invalid input list: use 'ins'";
+
+ unsigned MIOperandNo = 0;
+ std::set<std::string> OperandNames;
+ for (unsigned i = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){
+ Init *ArgInit;
+ std::string ArgName;
+ if (i < NumDefs) {
+ ArgInit = OutDI->getArg(i);
+ ArgName = OutDI->getArgName(i);
+ } else {
+ ArgInit = InDI->getArg(i-NumDefs);
+ ArgName = InDI->getArgName(i-NumDefs);
+ }
+
+ DefInit *Arg = dynamic_cast<DefInit*>(ArgInit);
+ if (!Arg)
+ throw "Illegal operand for the '" + R->getName() + "' instruction!";
+
+ Record *Rec = Arg->getDef();
+ std::string PrintMethod = "printOperand";
+ unsigned NumOps = 1;
+ DagInit *MIOpInfo = 0;
+ if (Rec->isSubClassOf("Operand")) {
+ PrintMethod = Rec->getValueAsString("PrintMethod");
+ MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
+
+ // Verify that MIOpInfo has an 'ops' root value.
+ if (!dynamic_cast<DefInit*>(MIOpInfo->getOperator()) ||
+ dynamic_cast<DefInit*>(MIOpInfo->getOperator())
+ ->getDef()->getName() != "ops")
+ throw "Bad value for MIOperandInfo in operand '" + Rec->getName() +
+ "'\n";
+
+ // If we have MIOpInfo, then we have #operands equal to number of entries
+ // in MIOperandInfo.
+ if (unsigned NumArgs = MIOpInfo->getNumArgs())
+ NumOps = NumArgs;
+
+ if (Rec->isSubClassOf("PredicateOperand"))
+ isPredicable = true;
+ else if (Rec->isSubClassOf("OptionalDefOperand"))
+ hasOptionalDef = true;
+ } else if (Rec->getName() == "variable_ops") {
+ isVariadic = true;
+ continue;
+ } else if (!Rec->isSubClassOf("RegisterClass") &&
+ Rec->getName() != "ptr_rc" && Rec->getName() != "unknown")
+ throw "Unknown operand class '" + Rec->getName() +
+ "' in '" + R->getName() + "' instruction!";
+
+ // Check that the operand has a name and that it's unique.
+ if (ArgName.empty())
+ throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
+ " has no name!";
+ if (!OperandNames.insert(ArgName).second)
+ throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
+ " has the same name as a previous operand!";
+
+ OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod,
+ MIOperandNo, NumOps, MIOpInfo));
+ MIOperandNo += NumOps;
+ }
+
+ // Parse Constraints.
+ ParseConstraints(R->getValueAsString("Constraints"), this);
+
+ // Parse the DisableEncoding field.
+ std::string DisableEncoding = R->getValueAsString("DisableEncoding");
+ while (1) {
+ std::string OpName;
+ tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t");
+ if (OpName.empty()) break;
+
+ // Figure out which operand this is.
+ std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false);
+
+ // Mark the operand as not-to-be encoded.
+ if (Op.second >= OperandList[Op.first].DoNotEncode.size())
+ OperandList[Op.first].DoNotEncode.resize(Op.second+1);
+ OperandList[Op.first].DoNotEncode[Op.second] = true;
+ }
+}
+
+/// getOperandNamed - Return the index of the operand with the specified
+/// non-empty name. If the instruction does not have an operand with the
+/// specified name, throw an exception.
+///
+unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const {
+ assert(!Name.empty() && "Cannot search for operand with no name!");
+ for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
+ if (OperandList[i].Name == Name) return i;
+ throw "Instruction '" + TheDef->getName() +
+ "' does not have an operand named '$" + Name + "'!";
+}
+
+std::pair<unsigned,unsigned>
+CodeGenInstruction::ParseOperandName(const std::string &Op,
+ bool AllowWholeOp) {
+ if (Op.empty() || Op[0] != '$')
+ throw TheDef->getName() + ": Illegal operand name: '" + Op + "'";
+
+ std::string OpName = Op.substr(1);
+ std::string SubOpName;
+
+ // Check to see if this is $foo.bar.
+ std::string::size_type DotIdx = OpName.find_first_of(".");
+ if (DotIdx != std::string::npos) {
+ SubOpName = OpName.substr(DotIdx+1);
+ if (SubOpName.empty())
+ throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'";
+ OpName = OpName.substr(0, DotIdx);
+ }
+
+ unsigned OpIdx = getOperandNamed(OpName);
+
+ if (SubOpName.empty()) { // If no suboperand name was specified:
+ // If one was needed, throw.
+ if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
+ SubOpName.empty())
+ throw TheDef->getName() + ": Illegal to refer to"
+ " whole operand part of complex operand '" + Op + "'";
+
+ // Otherwise, return the operand.
+ return std::make_pair(OpIdx, 0U);
+ }
+
+ // Find the suboperand number involved.
+ DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
+ if (MIOpInfo == 0)
+ throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
+
+ // Find the operand with the right name.
+ for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
+ if (MIOpInfo->getArgName(i) == SubOpName)
+ return std::make_pair(OpIdx, i);
+
+ // Otherwise, didn't find it!
+ throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
+}
+
+
+/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
+/// implicit def and it has a known VT, return the VT, otherwise return
+/// MVT::Other.
+MVT::SimpleValueType CodeGenInstruction::
+HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const {
+ if (ImplicitDefs.empty()) return MVT::Other;
+
+ // Check to see if the first implicit def has a resolvable type.
+ Record *FirstImplicitDef = ImplicitDefs[0];
+ assert(FirstImplicitDef->isSubClassOf("Register"));
+ const std::vector<MVT::SimpleValueType> &RegVTs =
+ TargetInfo.getRegisterVTs(FirstImplicitDef);
+ if (RegVTs.size() == 1)
+ return RegVTs[0];
+ return MVT::Other;
+}
+
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.h b/contrib/llvm/utils/TableGen/CodeGenInstruction.h
new file mode 100644
index 0000000..b02d0d3
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.h
@@ -0,0 +1,197 @@
+//===- CodeGenInstruction.h - Instruction Class Wrapper ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a wrapper class for the 'Instruction' TableGen class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_INSTRUCTION_H
+#define CODEGEN_INSTRUCTION_H
+
+#include "llvm/CodeGen/ValueTypes.h"
+#include <string>
+#include <vector>
+#include <utility>
+
+namespace llvm {
+ class Record;
+ class DagInit;
+ class CodeGenTarget;
+
+ class CodeGenInstruction {
+ public:
+ Record *TheDef; // The actual record defining this instruction.
+ std::string Namespace; // The namespace the instruction is in.
+
+ /// AsmString - The format string used to emit a .s file for the
+ /// instruction.
+ std::string AsmString;
+
+ class ConstraintInfo {
+ enum { None, EarlyClobber, Tied } Kind;
+ unsigned OtherTiedOperand;
+ public:
+ ConstraintInfo() : Kind(None) {}
+
+ static ConstraintInfo getEarlyClobber() {
+ ConstraintInfo I;
+ I.Kind = EarlyClobber;
+ I.OtherTiedOperand = 0;
+ return I;
+ }
+
+ static ConstraintInfo getTied(unsigned Op) {
+ ConstraintInfo I;
+ I.Kind = Tied;
+ I.OtherTiedOperand = Op;
+ return I;
+ }
+
+ bool isNone() const { return Kind == None; }
+ bool isEarlyClobber() const { return Kind == EarlyClobber; }
+ bool isTied() const { return Kind == Tied; }
+
+ unsigned getTiedOperand() const {
+ assert(isTied());
+ return OtherTiedOperand;
+ }
+ };
+
+ /// OperandInfo - The information we keep track of for each operand in the
+ /// operand list for a tablegen instruction.
+ struct OperandInfo {
+ /// Rec - The definition this operand is declared as.
+ ///
+ Record *Rec;
+
+ /// Name - If this operand was assigned a symbolic name, this is it,
+ /// otherwise, it's empty.
+ std::string Name;
+
+ /// PrinterMethodName - The method used to print operands of this type in
+ /// the asmprinter.
+ std::string PrinterMethodName;
+
+ /// MIOperandNo - Currently (this is meant to be phased out), some logical
+ /// operands correspond to multiple MachineInstr operands. In the X86
+ /// target for example, one address operand is represented as 4
+ /// MachineOperands. Because of this, the operand number in the
+ /// OperandList may not match the MachineInstr operand num. Until it
+ /// does, this contains the MI operand index of this operand.
+ unsigned MIOperandNo;
+ unsigned MINumOperands; // The number of operands.
+
+ /// DoNotEncode - Bools are set to true in this vector for each operand in
+ /// the DisableEncoding list. These should not be emitted by the code
+ /// emitter.
+ std::vector<bool> DoNotEncode;
+
+ /// MIOperandInfo - Default MI operand type. Note an operand may be made
+ /// up of multiple MI operands.
+ DagInit *MIOperandInfo;
+
+ /// Constraint info for this operand. This operand can have pieces, so we
+ /// track constraint info for each.
+ std::vector<ConstraintInfo> Constraints;
+
+ OperandInfo(Record *R, const std::string &N, const std::string &PMN,
+ unsigned MION, unsigned MINO, DagInit *MIOI)
+ : Rec(R), Name(N), PrinterMethodName(PMN), MIOperandNo(MION),
+ MINumOperands(MINO), MIOperandInfo(MIOI) {}
+ };
+
+ /// NumDefs - Number of def operands declared, this is the number of
+ /// elements in the instruction's (outs) list.
+ ///
+ unsigned NumDefs;
+
+ /// OperandList - The list of declared operands, along with their declared
+ /// type (which is a record).
+ std::vector<OperandInfo> OperandList;
+
+ /// ImplicitDefs/ImplicitUses - These are lists of registers that are
+ /// implicitly defined and used by the instruction.
+ std::vector<Record*> ImplicitDefs, ImplicitUses;
+
+ // Various boolean values we track for the instruction.
+ bool isReturn;
+ bool isBranch;
+ bool isIndirectBranch;
+ bool isCompare;
+ bool isBarrier;
+ bool isCall;
+ bool canFoldAsLoad;
+ bool mayLoad, mayStore;
+ bool isPredicable;
+ bool isConvertibleToThreeAddress;
+ bool isCommutable;
+ bool isTerminator;
+ bool isReMaterializable;
+ bool hasDelaySlot;
+ bool usesCustomInserter;
+ bool isVariadic;
+ bool hasCtrlDep;
+ bool isNotDuplicable;
+ bool hasOptionalDef;
+ bool hasSideEffects;
+ bool neverHasSideEffects;
+ bool isAsCheapAsAMove;
+ bool hasExtraSrcRegAllocReq;
+ bool hasExtraDefRegAllocReq;
+
+ /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
+ /// where $foo is a whole operand and $foo.bar refers to a suboperand.
+ /// This throws an exception if the name is invalid. If AllowWholeOp is
+ /// true, references to operands with suboperands are allowed, otherwise
+ /// not.
+ std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op,
+ bool AllowWholeOp = true);
+
+ /// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
+ /// flat machineinstr operand #.
+ unsigned getFlattenedOperandNumber(std::pair<unsigned,unsigned> Op) const {
+ return OperandList[Op.first].MIOperandNo + Op.second;
+ }
+
+ /// getSubOperandNumber - Unflatten a operand number into an
+ /// operand/suboperand pair.
+ std::pair<unsigned,unsigned> getSubOperandNumber(unsigned Op) const {
+ for (unsigned i = 0; ; ++i) {
+ assert(i < OperandList.size() && "Invalid flat operand #");
+ if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op)
+ return std::make_pair(i, Op-OperandList[i].MIOperandNo);
+ }
+ }
+
+
+ /// isFlatOperandNotEmitted - Return true if the specified flat operand #
+ /// should not be emitted with the code emitter.
+ bool isFlatOperandNotEmitted(unsigned FlatOpNo) const {
+ std::pair<unsigned,unsigned> Op = getSubOperandNumber(FlatOpNo);
+ if (OperandList[Op.first].DoNotEncode.size() > Op.second)
+ return OperandList[Op.first].DoNotEncode[Op.second];
+ return false;
+ }
+
+ CodeGenInstruction(Record *R, const std::string &AsmStr);
+
+ /// getOperandNamed - Return the index of the operand with the specified
+ /// non-empty name. If the instruction does not have an operand with the
+ /// specified name, throw an exception.
+ unsigned getOperandNamed(const std::string &Name) const;
+
+ /// HasOneImplicitDefWithKnownVT - If the instruction has at least one
+ /// implicit def and it has a known VT, return the VT, otherwise return
+ /// MVT::Other.
+ MVT::SimpleValueType
+ HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const;
+ };
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
new file mode 100644
index 0000000..3208c0d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
@@ -0,0 +1,87 @@
+//===- CodeGenIntrinsic.h - Intrinsic Class Wrapper ------------*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a wrapper class for the 'Intrinsic' TableGen class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_INTRINSIC_H
+#define CODEGEN_INTRINSIC_H
+
+#include <string>
+#include <vector>
+#include "llvm/CodeGen/ValueTypes.h"
+
+namespace llvm {
+ class Record;
+ class RecordKeeper;
+ class CodeGenTarget;
+
+ struct CodeGenIntrinsic {
+ Record *TheDef; // The actual record defining this intrinsic.
+ std::string Name; // The name of the LLVM function "llvm.bswap.i32"
+ std::string EnumName; // The name of the enum "bswap_i32"
+ std::string GCCBuiltinName;// Name of the corresponding GCC builtin, or "".
+ std::string TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics.
+
+ /// IntrinsicSignature - This structure holds the return values and
+ /// parameter values of an intrinsic. If the number of return values is > 1,
+ /// then the intrinsic implicitly returns a first-class aggregate. The
+ /// numbering of the types starts at 0 with the first return value and
+ /// continues from there through the parameter list. This is useful for
+ /// "matching" types.
+ struct IntrinsicSignature {
+ /// RetVTs - The MVT::SimpleValueType for each return type. Note that this
+ /// list is only populated when in the context of a target .td file. When
+ /// building Intrinsics.td, this isn't available, because we don't know
+ /// the target pointer size.
+ std::vector<MVT::SimpleValueType> RetVTs;
+
+ /// RetTypeDefs - The records for each return type.
+ std::vector<Record*> RetTypeDefs;
+
+ /// ParamVTs - The MVT::SimpleValueType for each parameter type. Note that
+ /// this list is only populated when in the context of a target .td file.
+ /// When building Intrinsics.td, this isn't available, because we don't
+ /// know the target pointer size.
+ std::vector<MVT::SimpleValueType> ParamVTs;
+
+ /// ParamTypeDefs - The records for each parameter type.
+ std::vector<Record*> ParamTypeDefs;
+ };
+
+ IntrinsicSignature IS;
+
+ // Memory mod/ref behavior of this intrinsic.
+ enum {
+ NoMem, ReadArgMem, ReadMem, ReadWriteArgMem, ReadWriteMem
+ } ModRef;
+
+ /// This is set to true if the intrinsic is overloaded by its argument
+ /// types.
+ bool isOverloaded;
+
+ /// isCommutative - True if the intrinsic is commutative.
+ bool isCommutative;
+
+ enum ArgAttribute {
+ NoCapture
+ };
+ std::vector<std::pair<unsigned, ArgAttribute> > ArgumentAttributes;
+
+ CodeGenIntrinsic(Record *R);
+ };
+
+ /// LoadIntrinsics - Read all of the intrinsics defined in the specified
+ /// .td file.
+ std::vector<CodeGenIntrinsic> LoadIntrinsics(const RecordKeeper &RC,
+ bool TargetOnly);
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h
new file mode 100644
index 0000000..ccd3d22
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h
@@ -0,0 +1,95 @@
+//===- CodeGenRegisters.h - Register and RegisterClass Info -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines structures to encapsulate information gleaned from the
+// target register and register class definitions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_REGISTERS_H
+#define CODEGEN_REGISTERS_H
+
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/ADT/DenseMap.h"
+#include <string>
+#include <vector>
+#include <set>
+#include <cstdlib>
+
+namespace llvm {
+ class Record;
+
+ /// CodeGenRegister - Represents a register definition.
+ struct CodeGenRegister {
+ Record *TheDef;
+ const std::string &getName() const;
+ unsigned DeclaredSpillSize, DeclaredSpillAlignment;
+ CodeGenRegister(Record *R);
+ };
+
+
+ struct CodeGenRegisterClass {
+ Record *TheDef;
+ std::string Namespace;
+ std::vector<Record*> Elements;
+ std::vector<MVT::SimpleValueType> VTs;
+ unsigned SpillSize;
+ unsigned SpillAlignment;
+ int CopyCost;
+ // Map SubRegIndex -> RegisterClass
+ DenseMap<Record*,Record*> SubRegClasses;
+ std::string MethodProtos, MethodBodies;
+
+ const std::string &getName() const;
+ const std::vector<MVT::SimpleValueType> &getValueTypes() const {return VTs;}
+ unsigned getNumValueTypes() const { return VTs.size(); }
+
+ MVT::SimpleValueType getValueTypeNum(unsigned VTNum) const {
+ if (VTNum < VTs.size())
+ return VTs[VTNum];
+ assert(0 && "VTNum greater than number of ValueTypes in RegClass!");
+ abort();
+ }
+
+ // Returns true if RC is a strict subclass.
+ // RC is a sub-class of this class if it is a valid replacement for any
+ // instruction operand where a register of this classis required. It must
+ // satisfy these conditions:
+ //
+ // 1. All RC registers are also in this.
+ // 2. The RC spill size must not be smaller than our spill size.
+ // 3. RC spill alignment must be compatible with ours.
+ //
+ bool hasSubClass(const CodeGenRegisterClass *RC) const {
+
+ if (RC->Elements.size() > Elements.size() ||
+ (SpillAlignment && RC->SpillAlignment % SpillAlignment) ||
+ SpillSize > RC->SpillSize)
+ return false;
+
+ std::set<Record*> RegSet;
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
+ Record *Reg = Elements[i];
+ RegSet.insert(Reg);
+ }
+
+ for (unsigned i = 0, e = RC->Elements.size(); i != e; ++i) {
+ Record *Reg = RC->Elements[i];
+ if (!RegSet.count(Reg))
+ return false;
+ }
+
+ return true;
+ }
+
+ CodeGenRegisterClass(Record *R);
+ };
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
new file mode 100644
index 0000000..cbfe2ad
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -0,0 +1,568 @@
+//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class wraps target description classes used by the various code
+// generation TableGen backends. This makes it easier to access the data and
+// provides a single place that needs to check it for validity. All of these
+// classes throw exceptions on error conditions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTarget.h"
+#include "CodeGenIntrinsics.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include <algorithm>
+using namespace llvm;
+
+static cl::opt<unsigned>
+AsmParserNum("asmparsernum", cl::init(0),
+ cl::desc("Make -gen-asm-parser emit assembly parser #N"));
+
+static cl::opt<unsigned>
+AsmWriterNum("asmwriternum", cl::init(0),
+ cl::desc("Make -gen-asm-writer emit assembly writer #N"));
+
+/// getValueType - Return the MVT::SimpleValueType that the specified TableGen
+/// record corresponds to.
+MVT::SimpleValueType llvm::getValueType(Record *Rec) {
+ return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
+}
+
+std::string llvm::getName(MVT::SimpleValueType T) {
+ switch (T) {
+ case MVT::Other: return "UNKNOWN";
+ case MVT::iPTR: return "TLI.getPointerTy()";
+ case MVT::iPTRAny: return "TLI.getPointerTy()";
+ default: return getEnumName(T);
+ }
+}
+
+std::string llvm::getEnumName(MVT::SimpleValueType T) {
+ switch (T) {
+ case MVT::Other: return "MVT::Other";
+ case MVT::i1: return "MVT::i1";
+ case MVT::i8: return "MVT::i8";
+ case MVT::i16: return "MVT::i16";
+ case MVT::i32: return "MVT::i32";
+ case MVT::i64: return "MVT::i64";
+ case MVT::i128: return "MVT::i128";
+ case MVT::iAny: return "MVT::iAny";
+ case MVT::fAny: return "MVT::fAny";
+ case MVT::vAny: return "MVT::vAny";
+ case MVT::f32: return "MVT::f32";
+ case MVT::f64: return "MVT::f64";
+ case MVT::f80: return "MVT::f80";
+ case MVT::f128: return "MVT::f128";
+ case MVT::ppcf128: return "MVT::ppcf128";
+ case MVT::Flag: return "MVT::Flag";
+ case MVT::isVoid:return "MVT::isVoid";
+ case MVT::v2i8: return "MVT::v2i8";
+ case MVT::v4i8: return "MVT::v4i8";
+ case MVT::v8i8: return "MVT::v8i8";
+ case MVT::v16i8: return "MVT::v16i8";
+ case MVT::v32i8: return "MVT::v32i8";
+ case MVT::v2i16: return "MVT::v2i16";
+ case MVT::v4i16: return "MVT::v4i16";
+ case MVT::v8i16: return "MVT::v8i16";
+ case MVT::v16i16: return "MVT::v16i16";
+ case MVT::v2i32: return "MVT::v2i32";
+ case MVT::v4i32: return "MVT::v4i32";
+ case MVT::v8i32: return "MVT::v8i32";
+ case MVT::v1i64: return "MVT::v1i64";
+ case MVT::v2i64: return "MVT::v2i64";
+ case MVT::v4i64: return "MVT::v4i64";
+ case MVT::v8i64: return "MVT::v8i64";
+ case MVT::v2f32: return "MVT::v2f32";
+ case MVT::v4f32: return "MVT::v4f32";
+ case MVT::v8f32: return "MVT::v8f32";
+ case MVT::v2f64: return "MVT::v2f64";
+ case MVT::v4f64: return "MVT::v4f64";
+ case MVT::Metadata: return "MVT::Metadata";
+ case MVT::iPTR: return "MVT::iPTR";
+ case MVT::iPTRAny: return "MVT::iPTRAny";
+ default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
+ }
+}
+
+/// getQualifiedName - Return the name of the specified record, with a
+/// namespace qualifier if the record contains one.
+///
+std::string llvm::getQualifiedName(const Record *R) {
+ std::string Namespace = R->getValueAsString("Namespace");
+ if (Namespace.empty()) return R->getName();
+ return Namespace + "::" + R->getName();
+}
+
+
+
+
+/// getTarget - Return the current instance of the Target class.
+///
+CodeGenTarget::CodeGenTarget() {
+ std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
+ if (Targets.size() == 0)
+ throw std::string("ERROR: No 'Target' subclasses defined!");
+ if (Targets.size() != 1)
+ throw std::string("ERROR: Multiple subclasses of Target defined!");
+ TargetRec = Targets[0];
+}
+
+
+const std::string &CodeGenTarget::getName() const {
+ return TargetRec->getName();
+}
+
+std::string CodeGenTarget::getInstNamespace() const {
+ for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) {
+ // Make sure not to pick up "TargetOpcode" by accidentally getting
+ // the namespace off the PHI instruction or something.
+ if ((*i)->Namespace != "TargetOpcode")
+ return (*i)->Namespace;
+ }
+
+ return "";
+}
+
+Record *CodeGenTarget::getInstructionSet() const {
+ return TargetRec->getValueAsDef("InstructionSet");
+}
+
+
+/// getAsmParser - Return the AssemblyParser definition for this target.
+///
+Record *CodeGenTarget::getAsmParser() const {
+ std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
+ if (AsmParserNum >= LI.size())
+ throw "Target does not have an AsmParser #" + utostr(AsmParserNum) + "!";
+ return LI[AsmParserNum];
+}
+
+/// getAsmWriter - Return the AssemblyWriter definition for this target.
+///
+Record *CodeGenTarget::getAsmWriter() const {
+ std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
+ if (AsmWriterNum >= LI.size())
+ throw "Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!";
+ return LI[AsmWriterNum];
+}
+
+void CodeGenTarget::ReadRegisters() const {
+ std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register");
+ if (Regs.empty())
+ throw std::string("No 'Register' subclasses defined!");
+ std::sort(Regs.begin(), Regs.end(), LessRecord());
+
+ Registers.reserve(Regs.size());
+ Registers.assign(Regs.begin(), Regs.end());
+}
+
+CodeGenRegister::CodeGenRegister(Record *R) : TheDef(R) {
+ DeclaredSpillSize = R->getValueAsInt("SpillSize");
+ DeclaredSpillAlignment = R->getValueAsInt("SpillAlignment");
+}
+
+const std::string &CodeGenRegister::getName() const {
+ return TheDef->getName();
+}
+
+void CodeGenTarget::ReadSubRegIndices() const {
+ SubRegIndices = Records.getAllDerivedDefinitions("SubRegIndex");
+ std::sort(SubRegIndices.begin(), SubRegIndices.end(), LessRecord());
+}
+
+void CodeGenTarget::ReadRegisterClasses() const {
+ std::vector<Record*> RegClasses =
+ Records.getAllDerivedDefinitions("RegisterClass");
+ if (RegClasses.empty())
+ throw std::string("No 'RegisterClass' subclasses defined!");
+
+ RegisterClasses.reserve(RegClasses.size());
+ RegisterClasses.assign(RegClasses.begin(), RegClasses.end());
+}
+
+std::vector<MVT::SimpleValueType> CodeGenTarget::
+getRegisterVTs(Record *R) const {
+ std::vector<MVT::SimpleValueType> Result;
+ const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
+ for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
+ const CodeGenRegisterClass &RC = RegisterClasses[i];
+ for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) {
+ if (R == RC.Elements[ei]) {
+ const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes();
+ Result.insert(Result.end(), InVTs.begin(), InVTs.end());
+ }
+ }
+ }
+
+ // Remove duplicates.
+ array_pod_sort(Result.begin(), Result.end());
+ Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
+ return Result;
+}
+
+
+CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) {
+ // Rename anonymous register classes.
+ if (R->getName().size() > 9 && R->getName()[9] == '.') {
+ static unsigned AnonCounter = 0;
+ R->setName("AnonRegClass_"+utostr(AnonCounter++));
+ }
+
+ std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes");
+ for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
+ Record *Type = TypeList[i];
+ if (!Type->isSubClassOf("ValueType"))
+ throw "RegTypes list member '" + Type->getName() +
+ "' does not derive from the ValueType class!";
+ VTs.push_back(getValueType(Type));
+ }
+ assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!");
+
+ std::vector<Record*> RegList = R->getValueAsListOfDefs("MemberList");
+ for (unsigned i = 0, e = RegList.size(); i != e; ++i) {
+ Record *Reg = RegList[i];
+ if (!Reg->isSubClassOf("Register"))
+ throw "Register Class member '" + Reg->getName() +
+ "' does not derive from the Register class!";
+ Elements.push_back(Reg);
+ }
+
+ // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags.
+ ListInit *SRC = R->getValueAsListInit("SubRegClasses");
+ for (ListInit::const_iterator i = SRC->begin(), e = SRC->end(); i != e; ++i) {
+ DagInit *DAG = dynamic_cast<DagInit*>(*i);
+ if (!DAG) throw "SubRegClasses must contain DAGs";
+ DefInit *DAGOp = dynamic_cast<DefInit*>(DAG->getOperator());
+ Record *RCRec;
+ if (!DAGOp || !(RCRec = DAGOp->getDef())->isSubClassOf("RegisterClass"))
+ throw "Operator '" + DAG->getOperator()->getAsString() +
+ "' in SubRegClasses is not a RegisterClass";
+ // Iterate over args, all SubRegIndex instances.
+ for (DagInit::const_arg_iterator ai = DAG->arg_begin(), ae = DAG->arg_end();
+ ai != ae; ++ai) {
+ DefInit *Idx = dynamic_cast<DefInit*>(*ai);
+ Record *IdxRec;
+ if (!Idx || !(IdxRec = Idx->getDef())->isSubClassOf("SubRegIndex"))
+ throw "Argument '" + (*ai)->getAsString() +
+ "' in SubRegClasses is not a SubRegIndex";
+ if (!SubRegClasses.insert(std::make_pair(IdxRec, RCRec)).second)
+ throw "SubRegIndex '" + IdxRec->getName() + "' mentioned twice";
+ }
+ }
+
+ // Allow targets to override the size in bits of the RegisterClass.
+ unsigned Size = R->getValueAsInt("Size");
+
+ Namespace = R->getValueAsString("Namespace");
+ SpillSize = Size ? Size : EVT(VTs[0]).getSizeInBits();
+ SpillAlignment = R->getValueAsInt("Alignment");
+ CopyCost = R->getValueAsInt("CopyCost");
+ MethodBodies = R->getValueAsCode("MethodBodies");
+ MethodProtos = R->getValueAsCode("MethodProtos");
+}
+
+const std::string &CodeGenRegisterClass::getName() const {
+ return TheDef->getName();
+}
+
+void CodeGenTarget::ReadLegalValueTypes() const {
+ const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
+ for (unsigned i = 0, e = RCs.size(); i != e; ++i)
+ for (unsigned ri = 0, re = RCs[i].VTs.size(); ri != re; ++ri)
+ LegalValueTypes.push_back(RCs[i].VTs[ri]);
+
+ // Remove duplicates.
+ std::sort(LegalValueTypes.begin(), LegalValueTypes.end());
+ LegalValueTypes.erase(std::unique(LegalValueTypes.begin(),
+ LegalValueTypes.end()),
+ LegalValueTypes.end());
+}
+
+
+void CodeGenTarget::ReadInstructions() const {
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+ if (Insts.size() <= 2)
+ throw std::string("No 'Instruction' subclasses defined!");
+
+ // Parse the instructions defined in the .td file.
+ std::string InstFormatName =
+ getAsmWriter()->getValueAsString("InstFormatName");
+
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
+ std::string AsmStr = Insts[i]->getValueAsString(InstFormatName);
+ Instructions[Insts[i]] = new CodeGenInstruction(Insts[i], AsmStr);
+ }
+}
+
+static const CodeGenInstruction *
+GetInstByName(const char *Name,
+ const DenseMap<const Record*, CodeGenInstruction*> &Insts) {
+ const Record *Rec = Records.getDef(Name);
+
+ DenseMap<const Record*, CodeGenInstruction*>::const_iterator
+ I = Insts.find(Rec);
+ if (Rec == 0 || I == Insts.end())
+ throw std::string("Could not find '") + Name + "' instruction!";
+ return I->second;
+}
+
+namespace {
+/// SortInstByName - Sorting predicate to sort instructions by name.
+///
+struct SortInstByName {
+ bool operator()(const CodeGenInstruction *Rec1,
+ const CodeGenInstruction *Rec2) const {
+ return Rec1->TheDef->getName() < Rec2->TheDef->getName();
+ }
+};
+}
+
+/// getInstructionsByEnumValue - Return all of the instructions defined by the
+/// target, ordered by their enum value.
+void CodeGenTarget::ComputeInstrsByEnum() const {
+ // The ordering here must match the ordering in TargetOpcodes.h.
+ const char *const FixedInstrs[] = {
+ "PHI",
+ "INLINEASM",
+ "PROLOG_LABEL",
+ "EH_LABEL",
+ "GC_LABEL",
+ "KILL",
+ "EXTRACT_SUBREG",
+ "INSERT_SUBREG",
+ "IMPLICIT_DEF",
+ "SUBREG_TO_REG",
+ "COPY_TO_REGCLASS",
+ "DBG_VALUE",
+ "REG_SEQUENCE",
+ "COPY",
+ 0
+ };
+ const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions();
+ for (const char *const *p = FixedInstrs; *p; ++p) {
+ const CodeGenInstruction *Instr = GetInstByName(*p, Insts);
+ assert(Instr && "Missing target independent instruction");
+ assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
+ InstrsByEnum.push_back(Instr);
+ }
+ unsigned EndOfPredefines = InstrsByEnum.size();
+
+ for (DenseMap<const Record*, CodeGenInstruction*>::const_iterator
+ I = Insts.begin(), E = Insts.end(); I != E; ++I) {
+ const CodeGenInstruction *CGI = I->second;
+ if (CGI->Namespace != "TargetOpcode")
+ InstrsByEnum.push_back(CGI);
+ }
+
+ assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");
+
+ // All of the instructions are now in random order based on the map iteration.
+ // Sort them by name.
+ std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(),
+ SortInstByName());
+}
+
+
+/// isLittleEndianEncoding - Return whether this target encodes its instruction
+/// in little-endian format, i.e. bits laid out in the order [0..n]
+///
+bool CodeGenTarget::isLittleEndianEncoding() const {
+ return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
+}
+
+//===----------------------------------------------------------------------===//
+// ComplexPattern implementation
+//
+ComplexPattern::ComplexPattern(Record *R) {
+ Ty = ::getValueType(R->getValueAsDef("Ty"));
+ NumOperands = R->getValueAsInt("NumOperands");
+ SelectFunc = R->getValueAsString("SelectFunc");
+ RootNodes = R->getValueAsListOfDefs("RootNodes");
+
+ // Parse the properties.
+ Properties = 0;
+ std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
+ for (unsigned i = 0, e = PropList.size(); i != e; ++i)
+ if (PropList[i]->getName() == "SDNPHasChain") {
+ Properties |= 1 << SDNPHasChain;
+ } else if (PropList[i]->getName() == "SDNPOptInFlag") {
+ Properties |= 1 << SDNPOptInFlag;
+ } else if (PropList[i]->getName() == "SDNPMayStore") {
+ Properties |= 1 << SDNPMayStore;
+ } else if (PropList[i]->getName() == "SDNPMayLoad") {
+ Properties |= 1 << SDNPMayLoad;
+ } else if (PropList[i]->getName() == "SDNPSideEffect") {
+ Properties |= 1 << SDNPSideEffect;
+ } else if (PropList[i]->getName() == "SDNPMemOperand") {
+ Properties |= 1 << SDNPMemOperand;
+ } else if (PropList[i]->getName() == "SDNPVariadic") {
+ Properties |= 1 << SDNPVariadic;
+ } else {
+ errs() << "Unsupported SD Node property '" << PropList[i]->getName()
+ << "' on ComplexPattern '" << R->getName() << "'!\n";
+ exit(1);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// CodeGenIntrinsic Implementation
+//===----------------------------------------------------------------------===//
+
+std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC,
+ bool TargetOnly) {
+ std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic");
+
+ std::vector<CodeGenIntrinsic> Result;
+
+ for (unsigned i = 0, e = I.size(); i != e; ++i) {
+ bool isTarget = I[i]->getValueAsBit("isTarget");
+ if (isTarget == TargetOnly)
+ Result.push_back(CodeGenIntrinsic(I[i]));
+ }
+ return Result;
+}
+
+CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
+ TheDef = R;
+ std::string DefName = R->getName();
+ ModRef = ReadWriteMem;
+ isOverloaded = false;
+ isCommutative = false;
+
+ if (DefName.size() <= 4 ||
+ std::string(DefName.begin(), DefName.begin() + 4) != "int_")
+ throw "Intrinsic '" + DefName + "' does not start with 'int_'!";
+
+ EnumName = std::string(DefName.begin()+4, DefName.end());
+
+ if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field.
+ GCCBuiltinName = R->getValueAsString("GCCBuiltinName");
+
+ TargetPrefix = R->getValueAsString("TargetPrefix");
+ Name = R->getValueAsString("LLVMName");
+
+ if (Name == "") {
+ // If an explicit name isn't specified, derive one from the DefName.
+ Name = "llvm.";
+
+ for (unsigned i = 0, e = EnumName.size(); i != e; ++i)
+ Name += (EnumName[i] == '_') ? '.' : EnumName[i];
+ } else {
+ // Verify it starts with "llvm.".
+ if (Name.size() <= 5 ||
+ std::string(Name.begin(), Name.begin() + 5) != "llvm.")
+ throw "Intrinsic '" + DefName + "'s name does not start with 'llvm.'!";
+ }
+
+ // If TargetPrefix is specified, make sure that Name starts with
+ // "llvm.<targetprefix>.".
+ if (!TargetPrefix.empty()) {
+ if (Name.size() < 6+TargetPrefix.size() ||
+ std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size())
+ != (TargetPrefix + "."))
+ throw "Intrinsic '" + DefName + "' does not start with 'llvm." +
+ TargetPrefix + ".'!";
+ }
+
+ // Parse the list of return types.
+ std::vector<MVT::SimpleValueType> OverloadedVTs;
+ ListInit *TypeList = R->getValueAsListInit("RetTypes");
+ for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) {
+ Record *TyEl = TypeList->getElementAsRecord(i);
+ assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
+ MVT::SimpleValueType VT;
+ if (TyEl->isSubClassOf("LLVMMatchType")) {
+ unsigned MatchTy = TyEl->getValueAsInt("Number");
+ assert(MatchTy < OverloadedVTs.size() &&
+ "Invalid matching number!");
+ VT = OverloadedVTs[MatchTy];
+ // It only makes sense to use the extended and truncated vector element
+ // variants with iAny types; otherwise, if the intrinsic is not
+ // overloaded, all the types can be specified directly.
+ assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") &&
+ !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) ||
+ VT == MVT::iAny || VT == MVT::vAny) &&
+ "Expected iAny or vAny type");
+ } else {
+ VT = getValueType(TyEl->getValueAsDef("VT"));
+ }
+ if (EVT(VT).isOverloaded()) {
+ OverloadedVTs.push_back(VT);
+ isOverloaded = true;
+ }
+
+ // Reject invalid types.
+ if (VT == MVT::isVoid)
+ throw "Intrinsic '" + DefName + " has void in result type list!";
+
+ IS.RetVTs.push_back(VT);
+ IS.RetTypeDefs.push_back(TyEl);
+ }
+
+ // Parse the list of parameter types.
+ TypeList = R->getValueAsListInit("ParamTypes");
+ for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) {
+ Record *TyEl = TypeList->getElementAsRecord(i);
+ assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
+ MVT::SimpleValueType VT;
+ if (TyEl->isSubClassOf("LLVMMatchType")) {
+ unsigned MatchTy = TyEl->getValueAsInt("Number");
+ assert(MatchTy < OverloadedVTs.size() &&
+ "Invalid matching number!");
+ VT = OverloadedVTs[MatchTy];
+ // It only makes sense to use the extended and truncated vector element
+ // variants with iAny types; otherwise, if the intrinsic is not
+ // overloaded, all the types can be specified directly.
+ assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") &&
+ !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) ||
+ VT == MVT::iAny || VT == MVT::vAny) &&
+ "Expected iAny or vAny type");
+ } else
+ VT = getValueType(TyEl->getValueAsDef("VT"));
+
+ if (EVT(VT).isOverloaded()) {
+ OverloadedVTs.push_back(VT);
+ isOverloaded = true;
+ }
+
+ // Reject invalid types.
+ if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
+ throw "Intrinsic '" + DefName + " has void in result type list!";
+
+ IS.ParamVTs.push_back(VT);
+ IS.ParamTypeDefs.push_back(TyEl);
+ }
+
+ // Parse the intrinsic properties.
+ ListInit *PropList = R->getValueAsListInit("Properties");
+ for (unsigned i = 0, e = PropList->getSize(); i != e; ++i) {
+ Record *Property = PropList->getElementAsRecord(i);
+ assert(Property->isSubClassOf("IntrinsicProperty") &&
+ "Expected a property!");
+
+ if (Property->getName() == "IntrNoMem")
+ ModRef = NoMem;
+ else if (Property->getName() == "IntrReadArgMem")
+ ModRef = ReadArgMem;
+ else if (Property->getName() == "IntrReadMem")
+ ModRef = ReadMem;
+ else if (Property->getName() == "IntrReadWriteArgMem")
+ ModRef = ReadWriteArgMem;
+ else if (Property->getName() == "Commutative")
+ isCommutative = true;
+ else if (Property->isSubClassOf("NoCapture")) {
+ unsigned ArgNo = Property->getValueAsInt("ArgNo");
+ ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture));
+ } else
+ assert(0 && "Unknown property!");
+ }
+}
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h
new file mode 100644
index 0000000..6b06b66
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h
@@ -0,0 +1,262 @@
+//===- CodeGenTarget.h - Target Class Wrapper -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines wrappers for the Target class and related global
+// functionality. This makes it easier to access the data and provides a single
+// place that needs to check it for validity. All of these classes throw
+// exceptions on error conditions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_TARGET_H
+#define CODEGEN_TARGET_H
+
+#include "CodeGenRegisters.h"
+#include "CodeGenInstruction.h"
+#include "Record.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+
+namespace llvm {
+
+struct CodeGenRegister;
+class CodeGenTarget;
+
+// SelectionDAG node properties.
+// SDNPMemOperand: indicates that a node touches memory and therefore must
+// have an associated memory operand that describes the access.
+enum SDNP {
+ SDNPCommutative,
+ SDNPAssociative,
+ SDNPHasChain,
+ SDNPOutFlag,
+ SDNPInFlag,
+ SDNPOptInFlag,
+ SDNPMayLoad,
+ SDNPMayStore,
+ SDNPSideEffect,
+ SDNPMemOperand,
+ SDNPVariadic
+};
+
+/// getValueType - Return the MVT::SimpleValueType that the specified TableGen
+/// record corresponds to.
+MVT::SimpleValueType getValueType(Record *Rec);
+
+std::string getName(MVT::SimpleValueType T);
+std::string getEnumName(MVT::SimpleValueType T);
+
+/// getQualifiedName - Return the name of the specified record, with a
+/// namespace qualifier if the record contains one.
+std::string getQualifiedName(const Record *R);
+
+/// CodeGenTarget - This class corresponds to the Target class in the .td files.
+///
+class CodeGenTarget {
+ Record *TargetRec;
+
+ mutable DenseMap<const Record*, CodeGenInstruction*> Instructions;
+ mutable std::vector<CodeGenRegister> Registers;
+ mutable std::vector<Record*> SubRegIndices;
+ mutable std::vector<CodeGenRegisterClass> RegisterClasses;
+ mutable std::vector<MVT::SimpleValueType> LegalValueTypes;
+ void ReadRegisters() const;
+ void ReadSubRegIndices() const;
+ void ReadRegisterClasses() const;
+ void ReadInstructions() const;
+ void ReadLegalValueTypes() const;
+
+ mutable std::vector<const CodeGenInstruction*> InstrsByEnum;
+public:
+ CodeGenTarget();
+
+ Record *getTargetRecord() const { return TargetRec; }
+ const std::string &getName() const;
+
+ /// getInstNamespace - Return the target-specific instruction namespace.
+ ///
+ std::string getInstNamespace() const;
+
+ /// getInstructionSet - Return the InstructionSet object.
+ ///
+ Record *getInstructionSet() const;
+
+ /// getAsmParser - Return the AssemblyParser definition for this target.
+ ///
+ Record *getAsmParser() const;
+
+ /// getAsmWriter - Return the AssemblyWriter definition for this target.
+ ///
+ Record *getAsmWriter() const;
+
+ const std::vector<CodeGenRegister> &getRegisters() const {
+ if (Registers.empty()) ReadRegisters();
+ return Registers;
+ }
+
+ const std::vector<Record*> &getSubRegIndices() const {
+ if (SubRegIndices.empty()) ReadSubRegIndices();
+ return SubRegIndices;
+ }
+
+ // Map a SubRegIndex Record to its number.
+ unsigned getSubRegIndexNo(Record *idx) const {
+ if (SubRegIndices.empty()) ReadSubRegIndices();
+ std::vector<Record*>::const_iterator i =
+ std::find(SubRegIndices.begin(), SubRegIndices.end(), idx);
+ assert(i != SubRegIndices.end() && "Not a SubRegIndex");
+ return (i - SubRegIndices.begin()) + 1;
+ }
+
+ const std::vector<CodeGenRegisterClass> &getRegisterClasses() const {
+ if (RegisterClasses.empty()) ReadRegisterClasses();
+ return RegisterClasses;
+ }
+
+ const CodeGenRegisterClass &getRegisterClass(Record *R) const {
+ const std::vector<CodeGenRegisterClass> &RC = getRegisterClasses();
+ for (unsigned i = 0, e = RC.size(); i != e; ++i)
+ if (RC[i].TheDef == R)
+ return RC[i];
+ assert(0 && "Didn't find the register class");
+ abort();
+ }
+
+ /// getRegisterClassForRegister - Find the register class that contains the
+ /// specified physical register. If the register is not in a register
+ /// class, return null. If the register is in multiple classes, and the
+ /// classes have a superset-subset relationship and the same set of
+ /// types, return the superclass. Otherwise return null.
+ const CodeGenRegisterClass *getRegisterClassForRegister(Record *R) const {
+ const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
+ const CodeGenRegisterClass *FoundRC = 0;
+ for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
+ const CodeGenRegisterClass &RC = RegisterClasses[i];
+ for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) {
+ if (R != RC.Elements[ei])
+ continue;
+
+ // If a register's classes have different types, return null.
+ if (FoundRC && RC.getValueTypes() != FoundRC->getValueTypes())
+ return 0;
+
+ // If this is the first class that contains the register,
+ // make a note of it and go on to the next class.
+ if (!FoundRC) {
+ FoundRC = &RC;
+ break;
+ }
+
+ std::vector<Record *> Elements(RC.Elements);
+ std::vector<Record *> FoundElements(FoundRC->Elements);
+ std::sort(Elements.begin(), Elements.end());
+ std::sort(FoundElements.begin(), FoundElements.end());
+
+ // Check to see if the previously found class that contains
+ // the register is a subclass of the current class. If so,
+ // prefer the superclass.
+ if (std::includes(Elements.begin(), Elements.end(),
+ FoundElements.begin(), FoundElements.end())) {
+ FoundRC = &RC;
+ break;
+ }
+
+ // Check to see if the previously found class that contains
+ // the register is a superclass of the current class. If so,
+ // prefer the superclass.
+ if (std::includes(FoundElements.begin(), FoundElements.end(),
+ Elements.begin(), Elements.end()))
+ break;
+
+ // Multiple classes, and neither is a superclass of the other.
+ // Return null.
+ return 0;
+ }
+ }
+ return FoundRC;
+ }
+
+ /// getRegisterVTs - Find the union of all possible SimpleValueTypes for the
+ /// specified physical register.
+ std::vector<MVT::SimpleValueType> getRegisterVTs(Record *R) const;
+
+ const std::vector<MVT::SimpleValueType> &getLegalValueTypes() const {
+ if (LegalValueTypes.empty()) ReadLegalValueTypes();
+ return LegalValueTypes;
+ }
+
+ /// isLegalValueType - Return true if the specified value type is natively
+ /// supported by the target (i.e. there are registers that directly hold it).
+ bool isLegalValueType(MVT::SimpleValueType VT) const {
+ const std::vector<MVT::SimpleValueType> &LegalVTs = getLegalValueTypes();
+ for (unsigned i = 0, e = LegalVTs.size(); i != e; ++i)
+ if (LegalVTs[i] == VT) return true;
+ return false;
+ }
+
+private:
+ DenseMap<const Record*, CodeGenInstruction*> &getInstructions() const {
+ if (Instructions.empty()) ReadInstructions();
+ return Instructions;
+ }
+public:
+
+ CodeGenInstruction &getInstruction(const Record *InstRec) const {
+ if (Instructions.empty()) ReadInstructions();
+ DenseMap<const Record*, CodeGenInstruction*>::iterator I =
+ Instructions.find(InstRec);
+ assert(I != Instructions.end() && "Not an instruction");
+ return *I->second;
+ }
+
+ /// getInstructionsByEnumValue - Return all of the instructions defined by the
+ /// target, ordered by their enum value.
+ const std::vector<const CodeGenInstruction*> &
+ getInstructionsByEnumValue() const {
+ if (InstrsByEnum.empty()) ComputeInstrsByEnum();
+ return InstrsByEnum;
+ }
+
+ typedef std::vector<const CodeGenInstruction*>::const_iterator inst_iterator;
+ inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();}
+ inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); }
+
+
+ /// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]?
+ ///
+ bool isLittleEndianEncoding() const;
+
+private:
+ void ComputeInstrsByEnum() const;
+};
+
+/// ComplexPattern - ComplexPattern info, corresponding to the ComplexPattern
+/// tablegen class in TargetSelectionDAG.td
+class ComplexPattern {
+ MVT::SimpleValueType Ty;
+ unsigned NumOperands;
+ std::string SelectFunc;
+ std::vector<Record*> RootNodes;
+ unsigned Properties; // Node properties
+public:
+ ComplexPattern() : NumOperands(0) {}
+ ComplexPattern(Record *R);
+
+ MVT::SimpleValueType getValueType() const { return Ty; }
+ unsigned getNumOperands() const { return NumOperands; }
+ const std::string &getSelectFunc() const { return SelectFunc; }
+ const std::vector<Record*> &getRootNodes() const {
+ return RootNodes;
+ }
+ bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp
new file mode 100644
index 0000000..8a73404
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp
@@ -0,0 +1,155 @@
+//===- DAGISelEmitter.cpp - Generate an instruction selector --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits a DAG instruction selector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelEmitter.h"
+#include "DAGISelMatcher.h"
+#include "Record.h"
+#include "llvm/Support/Debug.h"
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// DAGISelEmitter Helper methods
+//
+
+/// getResultPatternCost - Compute the number of instructions for this pattern.
+/// This is a temporary hack. We should really include the instruction
+/// latencies in this calculation.
+static unsigned getResultPatternCost(TreePatternNode *P,
+ CodeGenDAGPatterns &CGP) {
+ if (P->isLeaf()) return 0;
+
+ unsigned Cost = 0;
+ Record *Op = P->getOperator();
+ if (Op->isSubClassOf("Instruction")) {
+ Cost++;
+ CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);
+ if (II.usesCustomInserter)
+ Cost += 10;
+ }
+ for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
+ Cost += getResultPatternCost(P->getChild(i), CGP);
+ return Cost;
+}
+
+/// getResultPatternCodeSize - Compute the code size of instructions for this
+/// pattern.
+static unsigned getResultPatternSize(TreePatternNode *P,
+ CodeGenDAGPatterns &CGP) {
+ if (P->isLeaf()) return 0;
+
+ unsigned Cost = 0;
+ Record *Op = P->getOperator();
+ if (Op->isSubClassOf("Instruction")) {
+ Cost += Op->getValueAsInt("CodeSize");
+ }
+ for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
+ Cost += getResultPatternSize(P->getChild(i), CGP);
+ return Cost;
+}
+
+namespace {
+// PatternSortingPredicate - return true if we prefer to match LHS before RHS.
+// In particular, we want to match maximal patterns first and lowest cost within
+// a particular complexity first.
+struct PatternSortingPredicate {
+ PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {}
+ CodeGenDAGPatterns &CGP;
+
+ bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) {
+ const TreePatternNode *LHSSrc = LHS->getSrcPattern();
+ const TreePatternNode *RHSSrc = RHS->getSrcPattern();
+
+ if (LHSSrc->getNumTypes() != 0 && RHSSrc->getNumTypes() != 0 &&
+ LHSSrc->getType(0) != RHSSrc->getType(0)) {
+ MVT::SimpleValueType V1 = LHSSrc->getType(0), V2 = RHSSrc->getType(0);
+ if (MVT(V1).isVector() != MVT(V2).isVector())
+ return MVT(V2).isVector();
+
+ if (MVT(V1).isFloatingPoint() != MVT(V2).isFloatingPoint())
+ return MVT(V2).isFloatingPoint();
+ }
+
+ // Otherwise, if the patterns might both match, sort based on complexity,
+ // which means that we prefer to match patterns that cover more nodes in the
+ // input over nodes that cover fewer.
+ unsigned LHSSize = LHS->getPatternComplexity(CGP);
+ unsigned RHSSize = RHS->getPatternComplexity(CGP);
+ if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
+ if (LHSSize < RHSSize) return false;
+
+ // If the patterns have equal complexity, compare generated instruction cost
+ unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP);
+ unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP);
+ if (LHSCost < RHSCost) return true;
+ if (LHSCost > RHSCost) return false;
+
+ unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP);
+ unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP);
+ if (LHSPatSize < RHSPatSize) return true;
+ if (LHSPatSize > RHSPatSize) return false;
+
+ // Sort based on the UID of the pattern, giving us a deterministic ordering
+ // if all other sorting conditions fail.
+ assert(LHS == RHS || LHS->ID != RHS->ID);
+ return LHS->ID < RHS->ID;
+ }
+};
+}
+
+
+void DAGISelEmitter::run(raw_ostream &OS) {
+ EmitSourceFileHeader("DAG Instruction Selector for the " +
+ CGP.getTargetInfo().getName() + " target", OS);
+
+ OS << "// *** NOTE: This file is #included into the middle of the target\n"
+ << "// *** instruction selector class. These functions are really "
+ << "methods.\n\n";
+
+ DEBUG(errs() << "\n\nALL PATTERNS TO MATCH:\n\n";
+ for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
+ E = CGP.ptm_end(); I != E; ++I) {
+ errs() << "PATTERN: "; I->getSrcPattern()->dump();
+ errs() << "\nRESULT: "; I->getDstPattern()->dump();
+ errs() << "\n";
+ });
+
+ // Add all the patterns to a temporary list so we can sort them.
+ std::vector<const PatternToMatch*> Patterns;
+ for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();
+ I != E; ++I)
+ Patterns.push_back(&*I);
+
+ // We want to process the matches in order of minimal cost. Sort the patterns
+ // so the least cost one is at the start.
+ std::sort(Patterns.begin(), Patterns.end(), PatternSortingPredicate(CGP));
+
+
+ // Convert each variant of each pattern into a Matcher.
+ std::vector<Matcher*> PatternMatchers;
+ for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
+ for (unsigned Variant = 0; ; ++Variant) {
+ if (Matcher *M = ConvertPatternToMatcher(*Patterns[i], Variant, CGP))
+ PatternMatchers.push_back(M);
+ else
+ break;
+ }
+ }
+
+ Matcher *TheMatcher = new ScopeMatcher(&PatternMatchers[0],
+ PatternMatchers.size());
+
+ TheMatcher = OptimizeMatcher(TheMatcher, CGP);
+ //Matcher->dump();
+ EmitMatcherTable(TheMatcher, CGP, OS);
+ delete TheMatcher;
+}
diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.h b/contrib/llvm/utils/TableGen/DAGISelEmitter.h
new file mode 100644
index 0000000..2117e65
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.h
@@ -0,0 +1,38 @@
+//===- DAGISelEmitter.h - Generate an instruction selector ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits a DAG instruction selector.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DAGISEL_EMITTER_H
+#define DAGISEL_EMITTER_H
+
+#include "TableGenBackend.h"
+#include "CodeGenDAGPatterns.h"
+#include <set>
+
+namespace llvm {
+
+/// DAGISelEmitter - The top-level class which coordinates construction
+/// and emission of the instruction selector.
+///
+class DAGISelEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ CodeGenDAGPatterns CGP;
+public:
+ explicit DAGISelEmitter(RecordKeeper &R) : Records(R), CGP(R) {}
+
+ // run - Output the isel, returning true on failure.
+ void run(raw_ostream &OS);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp
new file mode 100644
index 0000000..9f12a68
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp
@@ -0,0 +1,401 @@
+//===- DAGISelMatcher.cpp - Representation of DAG pattern matcher ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace llvm;
+
+void Matcher::dump() const {
+ print(errs(), 0);
+}
+
+void Matcher::print(raw_ostream &OS, unsigned indent) const {
+ printImpl(OS, indent);
+ if (Next)
+ return Next->print(OS, indent);
+}
+
+void Matcher::printOne(raw_ostream &OS) const {
+ printImpl(OS, 0);
+}
+
+/// unlinkNode - Unlink the specified node from this chain. If Other == this,
+/// we unlink the next pointer and return it. Otherwise we unlink Other from
+/// the list and return this.
+Matcher *Matcher::unlinkNode(Matcher *Other) {
+ if (this == Other)
+ return takeNext();
+
+ // Scan until we find the predecessor of Other.
+ Matcher *Cur = this;
+ for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext())
+ /*empty*/;
+
+ if (Cur == 0) return 0;
+ Cur->takeNext();
+ Cur->setNext(Other->takeNext());
+ return this;
+}
+
+/// canMoveBefore - Return true if this matcher is the same as Other, or if
+/// we can move this matcher past all of the nodes in-between Other and this
+/// node. Other must be equal to or before this.
+bool Matcher::canMoveBefore(const Matcher *Other) const {
+ for (;; Other = Other->getNext()) {
+ assert(Other && "Other didn't come before 'this'?");
+ if (this == Other) return true;
+
+ // We have to be able to move this node across the Other node.
+ if (!canMoveBeforeNode(Other))
+ return false;
+ }
+}
+
+/// canMoveBefore - Return true if it is safe to move the current matcher
+/// across the specified one.
+bool Matcher::canMoveBeforeNode(const Matcher *Other) const {
+ // We can move simple predicates before record nodes.
+ if (isSimplePredicateNode())
+ return Other->isSimplePredicateOrRecordNode();
+
+ // We can move record nodes across simple predicates.
+ if (isSimplePredicateOrRecordNode())
+ return isSimplePredicateNode();
+
+ // We can't move record nodes across each other etc.
+ return false;
+}
+
+
+ScopeMatcher::~ScopeMatcher() {
+ for (unsigned i = 0, e = Children.size(); i != e; ++i)
+ delete Children[i];
+}
+
+
+// printImpl methods.
+
+void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "Scope\n";
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+ if (getChild(i) == 0)
+ OS.indent(indent+1) << "NULL POINTER\n";
+ else
+ getChild(i)->print(OS, indent+2);
+ }
+}
+
+void RecordMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "Record\n";
+}
+
+void RecordChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "RecordChild: " << ChildNo << '\n';
+}
+
+void RecordMemRefMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "RecordMemRef\n";
+}
+
+void CaptureFlagInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{
+ OS.indent(indent) << "CaptureFlagInput\n";
+}
+
+void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MoveChild " << ChildNo << '\n';
+}
+
+void MoveParentMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MoveParent\n";
+}
+
+void CheckSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckSame " << MatchNumber << '\n';
+}
+
+void CheckPatternPredicateMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckPatternPredicate " << Predicate << '\n';
+}
+
+void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckPredicate " << PredName << '\n';
+}
+
+void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckOpcode " << Opcode.getEnumName() << '\n';
+}
+
+void SwitchOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "SwitchOpcode: {\n";
+ for (unsigned i = 0, e = Cases.size(); i != e; ++i) {
+ OS.indent(indent) << "case " << Cases[i].first->getEnumName() << ":\n";
+ Cases[i].second->print(OS, indent+2);
+ }
+ OS.indent(indent) << "}\n";
+}
+
+
+void CheckTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckType " << getEnumName(Type) << ", ResNo="
+ << ResNo << '\n';
+}
+
+void SwitchTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "SwitchType: {\n";
+ for (unsigned i = 0, e = Cases.size(); i != e; ++i) {
+ OS.indent(indent) << "case " << getEnumName(Cases[i].first) << ":\n";
+ Cases[i].second->print(OS, indent+2);
+ }
+ OS.indent(indent) << "}\n";
+}
+
+void CheckChildTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckChildType " << ChildNo << " "
+ << getEnumName(Type) << '\n';
+}
+
+
+void CheckIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckInteger " << Value << '\n';
+}
+
+void CheckCondCodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckCondCode ISD::" << CondCodeName << '\n';
+}
+
+void CheckValueTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckValueType MVT::" << TypeName << '\n';
+}
+
+void CheckComplexPatMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckComplexPat " << Pattern.getSelectFunc() << '\n';
+}
+
+void CheckAndImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckAndImm " << Value << '\n';
+}
+
+void CheckOrImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckOrImm " << Value << '\n';
+}
+
+void CheckFoldableChainNodeMatcher::printImpl(raw_ostream &OS,
+ unsigned indent) const {
+ OS.indent(indent) << "CheckFoldableChainNode\n";
+}
+
+void EmitIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitInteger " << Val << " VT=" << VT << '\n';
+}
+
+void EmitStringIntegerMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << VT << '\n';
+}
+
+void EmitRegisterMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitRegister ";
+ if (Reg)
+ OS << Reg->getName();
+ else
+ OS << "zero_reg";
+ OS << " VT=" << VT << '\n';
+}
+
+void EmitConvertToTargetMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitConvertToTarget " << Slot << '\n';
+}
+
+void EmitMergeInputChainsMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitMergeInputChains <todo: args>\n";
+}
+
+void EmitCopyToRegMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitCopyToReg <todo: args>\n";
+}
+
+void EmitNodeXFormMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitNodeXForm " << NodeXForm->getName()
+ << " Slot=" << Slot << '\n';
+}
+
+
+void EmitNodeMatcherCommon::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent);
+ OS << (isa<MorphNodeToMatcher>(this) ? "MorphNodeTo: " : "EmitNode: ")
+ << OpcodeName << ": <todo flags> ";
+
+ for (unsigned i = 0, e = VTs.size(); i != e; ++i)
+ OS << ' ' << getEnumName(VTs[i]);
+ OS << '(';
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ OS << Operands[i] << ' ';
+ OS << ")\n";
+}
+
+void MarkFlagResultsMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MarkFlagResults <todo: args>\n";
+}
+
+void CompleteMatchMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CompleteMatch <todo args>\n";
+ OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n";
+ OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n";
+}
+
+// getHashImpl Implementation.
+
+unsigned CheckPatternPredicateMatcher::getHashImpl() const {
+ return HashString(Predicate);
+}
+
+unsigned CheckPredicateMatcher::getHashImpl() const {
+ return HashString(PredName);
+}
+
+unsigned CheckOpcodeMatcher::getHashImpl() const {
+ return HashString(Opcode.getEnumName());
+}
+
+unsigned CheckCondCodeMatcher::getHashImpl() const {
+ return HashString(CondCodeName);
+}
+
+unsigned CheckValueTypeMatcher::getHashImpl() const {
+ return HashString(TypeName);
+}
+
+unsigned EmitStringIntegerMatcher::getHashImpl() const {
+ return HashString(Val) ^ VT;
+}
+
+template<typename It>
+static unsigned HashUnsigneds(It I, It E) {
+ unsigned Result = 0;
+ for (; I != E; ++I)
+ Result = (Result<<3) ^ *I;
+ return Result;
+}
+
+unsigned EmitMergeInputChainsMatcher::getHashImpl() const {
+ return HashUnsigneds(ChainNodes.begin(), ChainNodes.end());
+}
+
+bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const {
+ // Note: pointer equality isn't enough here, we have to check the enum names
+ // to ensure that the nodes are for the same opcode.
+ return cast<CheckOpcodeMatcher>(M)->Opcode.getEnumName() ==
+ Opcode.getEnumName();
+}
+
+
+bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {
+ const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m);
+ return M->OpcodeName == OpcodeName && M->VTs == VTs &&
+ M->Operands == Operands && M->HasChain == HasChain &&
+ M->HasInFlag == HasInFlag && M->HasOutFlag == HasOutFlag &&
+ M->HasMemRefs == HasMemRefs &&
+ M->NumFixedArityOperands == NumFixedArityOperands;
+}
+
+unsigned EmitNodeMatcherCommon::getHashImpl() const {
+ return (HashString(OpcodeName) << 4) | Operands.size();
+}
+
+
+unsigned MarkFlagResultsMatcher::getHashImpl() const {
+ return HashUnsigneds(FlagResultNodes.begin(), FlagResultNodes.end());
+}
+
+unsigned CompleteMatchMatcher::getHashImpl() const {
+ return HashUnsigneds(Results.begin(), Results.end()) ^
+ ((unsigned)(intptr_t)&Pattern << 8);
+}
+
+// isContradictoryImpl Implementations.
+
+static bool TypesAreContradictory(MVT::SimpleValueType T1,
+ MVT::SimpleValueType T2) {
+ // If the two types are the same, then they are the same, so they don't
+ // contradict.
+ if (T1 == T2) return false;
+
+ // If either type is about iPtr, then they don't conflict unless the other
+ // one is not a scalar integer type.
+ if (T1 == MVT::iPTR)
+ return !MVT(T2).isInteger() || MVT(T2).isVector();
+
+ if (T2 == MVT::iPTR)
+ return !MVT(T1).isInteger() || MVT(T1).isVector();
+
+ // Otherwise, they are two different non-iPTR types, they conflict.
+ return true;
+}
+
+bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckOpcodeMatcher *COM = dyn_cast<CheckOpcodeMatcher>(M)) {
+ // One node can't have two different opcodes!
+ // Note: pointer equality isn't enough here, we have to check the enum names
+ // to ensure that the nodes are for the same opcode.
+ return COM->getOpcode().getEnumName() != getOpcode().getEnumName();
+ }
+
+ // If the node has a known type, and if the type we're checking for is
+ // different, then we know they contradict. For example, a check for
+ // ISD::STORE will never be true at the same time a check for Type i32 is.
+ if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M)) {
+ // If checking for a result the opcode doesn't have, it can't match.
+ if (CT->getResNo() >= getOpcode().getNumResults())
+ return true;
+
+ MVT::SimpleValueType NodeType = getOpcode().getKnownType(CT->getResNo());
+ if (NodeType != MVT::Other)
+ return TypesAreContradictory(NodeType, CT->getType());
+ }
+
+ return false;
+}
+
+bool CheckTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M))
+ return TypesAreContradictory(getType(), CT->getType());
+ return false;
+}
+
+bool CheckChildTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckChildTypeMatcher *CC = dyn_cast<CheckChildTypeMatcher>(M)) {
+ // If the two checks are about different nodes, we don't know if they
+ // conflict!
+ if (CC->getChildNo() != getChildNo())
+ return false;
+
+ return TypesAreContradictory(getType(), CC->getType());
+ }
+ return false;
+}
+
+bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckIntegerMatcher *CIM = dyn_cast<CheckIntegerMatcher>(M))
+ return CIM->getValue() != getValue();
+ return false;
+}
+
+bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckValueTypeMatcher *CVT = dyn_cast<CheckValueTypeMatcher>(M))
+ return CVT->getTypeName() != getTypeName();
+ return false;
+}
+
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.h b/contrib/llvm/utils/TableGen/DAGISelMatcher.h
new file mode 100644
index 0000000..d9b25d5
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.h
@@ -0,0 +1,1114 @@
+//===- DAGISelMatcher.h - Representation of DAG pattern matcher -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TBLGEN_DAGISELMATCHER_H
+#define TBLGEN_DAGISELMATCHER_H
+
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+
+namespace llvm {
+ class CodeGenDAGPatterns;
+ class Matcher;
+ class PatternToMatch;
+ class raw_ostream;
+ class ComplexPattern;
+ class Record;
+ class SDNodeInfo;
+
+Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant,
+ const CodeGenDAGPatterns &CGP);
+Matcher *OptimizeMatcher(Matcher *Matcher, const CodeGenDAGPatterns &CGP);
+void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP,
+ raw_ostream &OS);
+
+
+/// Matcher - Base class for all the the DAG ISel Matcher representation
+/// nodes.
+class Matcher {
+ // The next matcher node that is executed after this one. Null if this is the
+ // last stage of a match.
+ OwningPtr<Matcher> Next;
+public:
+ enum KindTy {
+ // Matcher state manipulation.
+ Scope, // Push a checking scope.
+ RecordNode, // Record the current node.
+ RecordChild, // Record a child of the current node.
+ RecordMemRef, // Record the memref in the current node.
+ CaptureFlagInput, // If the current node has an input flag, save it.
+ MoveChild, // Move current node to specified child.
+ MoveParent, // Move current node to parent.
+
+ // Predicate checking.
+ CheckSame, // Fail if not same as prev match.
+ CheckPatternPredicate,
+ CheckPredicate, // Fail if node predicate fails.
+ CheckOpcode, // Fail if not opcode.
+ SwitchOpcode, // Dispatch based on opcode.
+ CheckType, // Fail if not correct type.
+ SwitchType, // Dispatch based on type.
+ CheckChildType, // Fail if child has wrong type.
+ CheckInteger, // Fail if wrong val.
+ CheckCondCode, // Fail if not condcode.
+ CheckValueType,
+ CheckComplexPat,
+ CheckAndImm,
+ CheckOrImm,
+ CheckFoldableChainNode,
+
+ // Node creation/emisssion.
+ EmitInteger, // Create a TargetConstant
+ EmitStringInteger, // Create a TargetConstant from a string.
+ EmitRegister, // Create a register.
+ EmitConvertToTarget, // Convert a imm/fpimm to target imm/fpimm
+ EmitMergeInputChains, // Merge together a chains for an input.
+ EmitCopyToReg, // Emit a copytoreg into a physreg.
+ EmitNode, // Create a DAG node
+ EmitNodeXForm, // Run a SDNodeXForm
+ MarkFlagResults, // Indicate which interior nodes have flag results.
+ CompleteMatch, // Finish a match and update the results.
+ MorphNodeTo // Build a node, finish a match and update results.
+ };
+ const KindTy Kind;
+
+protected:
+ Matcher(KindTy K) : Kind(K) {}
+public:
+ virtual ~Matcher() {}
+
+ KindTy getKind() const { return Kind; }
+
+ Matcher *getNext() { return Next.get(); }
+ const Matcher *getNext() const { return Next.get(); }
+ void setNext(Matcher *C) { Next.reset(C); }
+ Matcher *takeNext() { return Next.take(); }
+
+ OwningPtr<Matcher> &getNextPtr() { return Next; }
+
+ static inline bool classof(const Matcher *) { return true; }
+
+ bool isEqual(const Matcher *M) const {
+ if (getKind() != M->getKind()) return false;
+ return isEqualImpl(M);
+ }
+
+ unsigned getHash() const {
+ // Clear the high bit so we don't conflict with tombstones etc.
+ return ((getHashImpl() << 4) ^ getKind()) & (~0U>>1);
+ }
+
+ /// isSafeToReorderWithPatternPredicate - Return true if it is safe to sink a
+ /// PatternPredicate node past this one.
+ virtual bool isSafeToReorderWithPatternPredicate() const {
+ return false;
+ }
+
+ /// isSimplePredicateNode - Return true if this is a simple predicate that
+ /// operates on the node or its children without potential side effects or a
+ /// change of the current node.
+ bool isSimplePredicateNode() const {
+ switch (getKind()) {
+ default: return false;
+ case CheckSame:
+ case CheckPatternPredicate:
+ case CheckPredicate:
+ case CheckOpcode:
+ case CheckType:
+ case CheckChildType:
+ case CheckInteger:
+ case CheckCondCode:
+ case CheckValueType:
+ case CheckAndImm:
+ case CheckOrImm:
+ case CheckFoldableChainNode:
+ return true;
+ }
+ }
+
+ /// isSimplePredicateOrRecordNode - Return true if this is a record node or
+ /// a simple predicate.
+ bool isSimplePredicateOrRecordNode() const {
+ return isSimplePredicateNode() ||
+ getKind() == RecordNode || getKind() == RecordChild;
+ }
+
+ /// unlinkNode - Unlink the specified node from this chain. If Other == this,
+ /// we unlink the next pointer and return it. Otherwise we unlink Other from
+ /// the list and return this.
+ Matcher *unlinkNode(Matcher *Other);
+
+ /// canMoveBefore - Return true if this matcher is the same as Other, or if
+ /// we can move this matcher past all of the nodes in-between Other and this
+ /// node. Other must be equal to or before this.
+ bool canMoveBefore(const Matcher *Other) const;
+
+ /// canMoveBefore - Return true if it is safe to move the current matcher
+ /// across the specified one.
+ bool canMoveBeforeNode(const Matcher *Other) const;
+
+ /// isContradictory - Return true of these two matchers could never match on
+ /// the same node.
+ bool isContradictory(const Matcher *Other) const {
+ // Since this predicate is reflexive, we canonicalize the ordering so that
+ // we always match a node against nodes with kinds that are greater or equal
+ // to them. For example, we'll pass in a CheckType node as an argument to
+ // the CheckOpcode method, not the other way around.
+ if (getKind() < Other->getKind())
+ return isContradictoryImpl(Other);
+ return Other->isContradictoryImpl(this);
+ }
+
+ void print(raw_ostream &OS, unsigned indent = 0) const;
+ void printOne(raw_ostream &OS) const;
+ void dump() const;
+protected:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const = 0;
+ virtual bool isEqualImpl(const Matcher *M) const = 0;
+ virtual unsigned getHashImpl() const = 0;
+ virtual bool isContradictoryImpl(const Matcher *M) const { return false; }
+};
+
+/// ScopeMatcher - This attempts to match each of its children to find the first
+/// one that successfully matches. If one child fails, it tries the next child.
+/// If none of the children match then this check fails. It never has a 'next'.
+class ScopeMatcher : public Matcher {
+ SmallVector<Matcher*, 4> Children;
+public:
+ ScopeMatcher(Matcher *const *children, unsigned numchildren)
+ : Matcher(Scope), Children(children, children+numchildren) {
+ }
+ virtual ~ScopeMatcher();
+
+ unsigned getNumChildren() const { return Children.size(); }
+
+ Matcher *getChild(unsigned i) { return Children[i]; }
+ const Matcher *getChild(unsigned i) const { return Children[i]; }
+
+ void resetChild(unsigned i, Matcher *N) {
+ delete Children[i];
+ Children[i] = N;
+ }
+
+ Matcher *takeChild(unsigned i) {
+ Matcher *Res = Children[i];
+ Children[i] = 0;
+ return Res;
+ }
+
+ void setNumChildren(unsigned NC) {
+ if (NC < Children.size()) {
+ // delete any children we're about to lose pointers to.
+ for (unsigned i = NC, e = Children.size(); i != e; ++i)
+ delete Children[i];
+ }
+ Children.resize(NC);
+ }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == Scope;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return false; }
+ virtual unsigned getHashImpl() const { return 12312; }
+};
+
+/// RecordMatcher - Save the current node in the operand list.
+class RecordMatcher : public Matcher {
+ /// WhatFor - This is a string indicating why we're recording this. This
+ /// should only be used for comment generation not anything semantic.
+ std::string WhatFor;
+
+ /// ResultNo - The slot number in the RecordedNodes vector that this will be,
+ /// just printed as a comment.
+ unsigned ResultNo;
+public:
+ RecordMatcher(const std::string &whatfor, unsigned resultNo)
+ : Matcher(RecordNode), WhatFor(whatfor), ResultNo(resultNo) {}
+
+ const std::string &getWhatFor() const { return WhatFor; }
+ unsigned getResultNo() const { return ResultNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == RecordNode;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return true; }
+ virtual unsigned getHashImpl() const { return 0; }
+};
+
+/// RecordChildMatcher - Save a numbered child of the current node, or fail
+/// the match if it doesn't exist. This is logically equivalent to:
+/// MoveChild N + RecordNode + MoveParent.
+class RecordChildMatcher : public Matcher {
+ unsigned ChildNo;
+
+ /// WhatFor - This is a string indicating why we're recording this. This
+ /// should only be used for comment generation not anything semantic.
+ std::string WhatFor;
+
+ /// ResultNo - The slot number in the RecordedNodes vector that this will be,
+ /// just printed as a comment.
+ unsigned ResultNo;
+public:
+ RecordChildMatcher(unsigned childno, const std::string &whatfor,
+ unsigned resultNo)
+ : Matcher(RecordChild), ChildNo(childno), WhatFor(whatfor),
+ ResultNo(resultNo) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+ const std::string &getWhatFor() const { return WhatFor; }
+ unsigned getResultNo() const { return ResultNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == RecordChild;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<RecordChildMatcher>(M)->getChildNo() == getChildNo();
+ }
+ virtual unsigned getHashImpl() const { return getChildNo(); }
+};
+
+/// RecordMemRefMatcher - Save the current node's memref.
+class RecordMemRefMatcher : public Matcher {
+public:
+ RecordMemRefMatcher() : Matcher(RecordMemRef) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == RecordMemRef;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return true; }
+ virtual unsigned getHashImpl() const { return 0; }
+};
+
+
+/// CaptureFlagInputMatcher - If the current record has a flag input, record
+/// it so that it is used as an input to the generated code.
+class CaptureFlagInputMatcher : public Matcher {
+public:
+ CaptureFlagInputMatcher() : Matcher(CaptureFlagInput) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CaptureFlagInput;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return true; }
+ virtual unsigned getHashImpl() const { return 0; }
+};
+
+/// MoveChildMatcher - This tells the interpreter to move into the
+/// specified child node.
+class MoveChildMatcher : public Matcher {
+ unsigned ChildNo;
+public:
+ MoveChildMatcher(unsigned childNo) : Matcher(MoveChild), ChildNo(childNo) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MoveChild;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<MoveChildMatcher>(M)->getChildNo() == getChildNo();
+ }
+ virtual unsigned getHashImpl() const { return getChildNo(); }
+};
+
+/// MoveParentMatcher - This tells the interpreter to move to the parent
+/// of the current node.
+class MoveParentMatcher : public Matcher {
+public:
+ MoveParentMatcher() : Matcher(MoveParent) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MoveParent;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return true; }
+ virtual unsigned getHashImpl() const { return 0; }
+};
+
+/// CheckSameMatcher - This checks to see if this node is exactly the same
+/// node as the specified match that was recorded with 'Record'. This is used
+/// when patterns have the same name in them, like '(mul GPR:$in, GPR:$in)'.
+class CheckSameMatcher : public Matcher {
+ unsigned MatchNumber;
+public:
+ CheckSameMatcher(unsigned matchnumber)
+ : Matcher(CheckSame), MatchNumber(matchnumber) {}
+
+ unsigned getMatchNumber() const { return MatchNumber; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckSame;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckSameMatcher>(M)->getMatchNumber() == getMatchNumber();
+ }
+ virtual unsigned getHashImpl() const { return getMatchNumber(); }
+};
+
+/// CheckPatternPredicateMatcher - This checks the target-specific predicate
+/// to see if the entire pattern is capable of matching. This predicate does
+/// not take a node as input. This is used for subtarget feature checks etc.
+class CheckPatternPredicateMatcher : public Matcher {
+ std::string Predicate;
+public:
+ CheckPatternPredicateMatcher(StringRef predicate)
+ : Matcher(CheckPatternPredicate), Predicate(predicate) {}
+
+ StringRef getPredicate() const { return Predicate; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckPatternPredicate;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckPatternPredicateMatcher>(M)->getPredicate() == Predicate;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+/// CheckPredicateMatcher - This checks the target-specific predicate to
+/// see if the node is acceptable.
+class CheckPredicateMatcher : public Matcher {
+ StringRef PredName;
+public:
+ CheckPredicateMatcher(StringRef predname)
+ : Matcher(CheckPredicate), PredName(predname) {}
+
+ StringRef getPredicateName() const { return PredName; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckPredicate;
+ }
+
+ // TODO: Ok?
+ //virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckPredicateMatcher>(M)->PredName == PredName;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+
+/// CheckOpcodeMatcher - This checks to see if the current node has the
+/// specified opcode, if not it fails to match.
+class CheckOpcodeMatcher : public Matcher {
+ const SDNodeInfo &Opcode;
+public:
+ CheckOpcodeMatcher(const SDNodeInfo &opcode)
+ : Matcher(CheckOpcode), Opcode(opcode) {}
+
+ const SDNodeInfo &getOpcode() const { return Opcode; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckOpcode;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const;
+ virtual unsigned getHashImpl() const;
+ virtual bool isContradictoryImpl(const Matcher *M) const;
+};
+
+/// SwitchOpcodeMatcher - Switch based on the current node's opcode, dispatching
+/// to one matcher per opcode. If the opcode doesn't match any of the cases,
+/// then the match fails. This is semantically equivalent to a Scope node where
+/// every child does a CheckOpcode, but is much faster.
+class SwitchOpcodeMatcher : public Matcher {
+ SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;
+public:
+ SwitchOpcodeMatcher(const std::pair<const SDNodeInfo*, Matcher*> *cases,
+ unsigned numcases)
+ : Matcher(SwitchOpcode), Cases(cases, cases+numcases) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == SwitchOpcode;
+ }
+
+ unsigned getNumCases() const { return Cases.size(); }
+
+ const SDNodeInfo &getCaseOpcode(unsigned i) const { return *Cases[i].first; }
+ Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
+ const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return false; }
+ virtual unsigned getHashImpl() const { return 4123; }
+};
+
+/// CheckTypeMatcher - This checks to see if the current node has the
+/// specified type at the specified result, if not it fails to match.
+class CheckTypeMatcher : public Matcher {
+ MVT::SimpleValueType Type;
+ unsigned ResNo;
+public:
+ CheckTypeMatcher(MVT::SimpleValueType type, unsigned resno)
+ : Matcher(CheckType), Type(type), ResNo(resno) {}
+
+ MVT::SimpleValueType getType() const { return Type; }
+ unsigned getResNo() const { return ResNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckType;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckTypeMatcher>(M)->Type == Type;
+ }
+ virtual unsigned getHashImpl() const { return Type; }
+ virtual bool isContradictoryImpl(const Matcher *M) const;
+};
+
+/// SwitchTypeMatcher - Switch based on the current node's type, dispatching
+/// to one matcher per case. If the type doesn't match any of the cases,
+/// then the match fails. This is semantically equivalent to a Scope node where
+/// every child does a CheckType, but is much faster.
+class SwitchTypeMatcher : public Matcher {
+ SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;
+public:
+ SwitchTypeMatcher(const std::pair<MVT::SimpleValueType, Matcher*> *cases,
+ unsigned numcases)
+ : Matcher(SwitchType), Cases(cases, cases+numcases) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == SwitchType;
+ }
+
+ unsigned getNumCases() const { return Cases.size(); }
+
+ MVT::SimpleValueType getCaseType(unsigned i) const { return Cases[i].first; }
+ Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
+ const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return false; }
+ virtual unsigned getHashImpl() const { return 4123; }
+};
+
+
+/// CheckChildTypeMatcher - This checks to see if a child node has the
+/// specified type, if not it fails to match.
+class CheckChildTypeMatcher : public Matcher {
+ unsigned ChildNo;
+ MVT::SimpleValueType Type;
+public:
+ CheckChildTypeMatcher(unsigned childno, MVT::SimpleValueType type)
+ : Matcher(CheckChildType), ChildNo(childno), Type(type) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+ MVT::SimpleValueType getType() const { return Type; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckChildType;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckChildTypeMatcher>(M)->ChildNo == ChildNo &&
+ cast<CheckChildTypeMatcher>(M)->Type == Type;
+ }
+ virtual unsigned getHashImpl() const { return (Type << 3) | ChildNo; }
+ virtual bool isContradictoryImpl(const Matcher *M) const;
+};
+
+
+/// CheckIntegerMatcher - This checks to see if the current node is a
+/// ConstantSDNode with the specified integer value, if not it fails to match.
+class CheckIntegerMatcher : public Matcher {
+ int64_t Value;
+public:
+ CheckIntegerMatcher(int64_t value)
+ : Matcher(CheckInteger), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckInteger;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckIntegerMatcher>(M)->Value == Value;
+ }
+ virtual unsigned getHashImpl() const { return Value; }
+ virtual bool isContradictoryImpl(const Matcher *M) const;
+};
+
+/// CheckCondCodeMatcher - This checks to see if the current node is a
+/// CondCodeSDNode with the specified condition, if not it fails to match.
+class CheckCondCodeMatcher : public Matcher {
+ StringRef CondCodeName;
+public:
+ CheckCondCodeMatcher(StringRef condcodename)
+ : Matcher(CheckCondCode), CondCodeName(condcodename) {}
+
+ StringRef getCondCodeName() const { return CondCodeName; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckCondCode;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckCondCodeMatcher>(M)->CondCodeName == CondCodeName;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+/// CheckValueTypeMatcher - This checks to see if the current node is a
+/// VTSDNode with the specified type, if not it fails to match.
+class CheckValueTypeMatcher : public Matcher {
+ StringRef TypeName;
+public:
+ CheckValueTypeMatcher(StringRef type_name)
+ : Matcher(CheckValueType), TypeName(type_name) {}
+
+ StringRef getTypeName() const { return TypeName; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckValueType;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckValueTypeMatcher>(M)->TypeName == TypeName;
+ }
+ virtual unsigned getHashImpl() const;
+ bool isContradictoryImpl(const Matcher *M) const;
+};
+
+
+
+/// CheckComplexPatMatcher - This node runs the specified ComplexPattern on
+/// the current node.
+class CheckComplexPatMatcher : public Matcher {
+ const ComplexPattern &Pattern;
+
+ /// MatchNumber - This is the recorded nodes slot that contains the node we want to
+ /// match against.
+ unsigned MatchNumber;
+
+ /// Name - The name of the node we're matching, for comment emission.
+ std::string Name;
+
+ /// FirstResult - This is the first slot in the RecordedNodes list that the
+ /// result of the match populates.
+ unsigned FirstResult;
+public:
+ CheckComplexPatMatcher(const ComplexPattern &pattern, unsigned matchnumber,
+ const std::string &name, unsigned firstresult)
+ : Matcher(CheckComplexPat), Pattern(pattern), MatchNumber(matchnumber),
+ Name(name), FirstResult(firstresult) {}
+
+ const ComplexPattern &getPattern() const { return Pattern; }
+ unsigned getMatchNumber() const { return MatchNumber; }
+
+ const std::string getName() const { return Name; }
+ unsigned getFirstResult() const { return FirstResult; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckComplexPat;
+ }
+
+ // Not safe to move a pattern predicate past a complex pattern.
+ virtual bool isSafeToReorderWithPatternPredicate() const { return false; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return &cast<CheckComplexPatMatcher>(M)->Pattern == &Pattern &&
+ cast<CheckComplexPatMatcher>(M)->MatchNumber == MatchNumber;
+ }
+ virtual unsigned getHashImpl() const {
+ return (unsigned)(intptr_t)&Pattern ^ MatchNumber;
+ }
+};
+
+/// CheckAndImmMatcher - This checks to see if the current node is an 'and'
+/// with something equivalent to the specified immediate.
+class CheckAndImmMatcher : public Matcher {
+ int64_t Value;
+public:
+ CheckAndImmMatcher(int64_t value)
+ : Matcher(CheckAndImm), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckAndImm;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckAndImmMatcher>(M)->Value == Value;
+ }
+ virtual unsigned getHashImpl() const { return Value; }
+};
+
+/// CheckOrImmMatcher - This checks to see if the current node is an 'and'
+/// with something equivalent to the specified immediate.
+class CheckOrImmMatcher : public Matcher {
+ int64_t Value;
+public:
+ CheckOrImmMatcher(int64_t value)
+ : Matcher(CheckOrImm), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckOrImm;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckOrImmMatcher>(M)->Value == Value;
+ }
+ virtual unsigned getHashImpl() const { return Value; }
+};
+
+/// CheckFoldableChainNodeMatcher - This checks to see if the current node
+/// (which defines a chain operand) is safe to fold into a larger pattern.
+class CheckFoldableChainNodeMatcher : public Matcher {
+public:
+ CheckFoldableChainNodeMatcher()
+ : Matcher(CheckFoldableChainNode) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckFoldableChainNode;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return true; }
+ virtual unsigned getHashImpl() const { return 0; }
+};
+
+/// EmitIntegerMatcher - This creates a new TargetConstant.
+class EmitIntegerMatcher : public Matcher {
+ int64_t Val;
+ MVT::SimpleValueType VT;
+public:
+ EmitIntegerMatcher(int64_t val, MVT::SimpleValueType vt)
+ : Matcher(EmitInteger), Val(val), VT(vt) {}
+
+ int64_t getValue() const { return Val; }
+ MVT::SimpleValueType getVT() const { return VT; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitInteger;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitIntegerMatcher>(M)->Val == Val &&
+ cast<EmitIntegerMatcher>(M)->VT == VT;
+ }
+ virtual unsigned getHashImpl() const { return (Val << 4) | VT; }
+};
+
+/// EmitStringIntegerMatcher - A target constant whose value is represented
+/// by a string.
+class EmitStringIntegerMatcher : public Matcher {
+ std::string Val;
+ MVT::SimpleValueType VT;
+public:
+ EmitStringIntegerMatcher(const std::string &val, MVT::SimpleValueType vt)
+ : Matcher(EmitStringInteger), Val(val), VT(vt) {}
+
+ const std::string &getValue() const { return Val; }
+ MVT::SimpleValueType getVT() const { return VT; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitStringInteger;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitStringIntegerMatcher>(M)->Val == Val &&
+ cast<EmitStringIntegerMatcher>(M)->VT == VT;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+/// EmitRegisterMatcher - This creates a new TargetConstant.
+class EmitRegisterMatcher : public Matcher {
+ /// Reg - The def for the register that we're emitting. If this is null, then
+ /// this is a reference to zero_reg.
+ Record *Reg;
+ MVT::SimpleValueType VT;
+public:
+ EmitRegisterMatcher(Record *reg, MVT::SimpleValueType vt)
+ : Matcher(EmitRegister), Reg(reg), VT(vt) {}
+
+ Record *getReg() const { return Reg; }
+ MVT::SimpleValueType getVT() const { return VT; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitRegister;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitRegisterMatcher>(M)->Reg == Reg &&
+ cast<EmitRegisterMatcher>(M)->VT == VT;
+ }
+ virtual unsigned getHashImpl() const {
+ return ((unsigned)(intptr_t)Reg) << 4 | VT;
+ }
+};
+
+/// EmitConvertToTargetMatcher - Emit an operation that reads a specified
+/// recorded node and converts it from being a ISD::Constant to
+/// ISD::TargetConstant, likewise for ConstantFP.
+class EmitConvertToTargetMatcher : public Matcher {
+ unsigned Slot;
+public:
+ EmitConvertToTargetMatcher(unsigned slot)
+ : Matcher(EmitConvertToTarget), Slot(slot) {}
+
+ unsigned getSlot() const { return Slot; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitConvertToTarget;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitConvertToTargetMatcher>(M)->Slot == Slot;
+ }
+ virtual unsigned getHashImpl() const { return Slot; }
+};
+
+/// EmitMergeInputChainsMatcher - Emit a node that merges a list of input
+/// chains together with a token factor. The list of nodes are the nodes in the
+/// matched pattern that have chain input/outputs. This node adds all input
+/// chains of these nodes if they are not themselves a node in the pattern.
+class EmitMergeInputChainsMatcher : public Matcher {
+ SmallVector<unsigned, 3> ChainNodes;
+public:
+ EmitMergeInputChainsMatcher(const unsigned *nodes, unsigned NumNodes)
+ : Matcher(EmitMergeInputChains), ChainNodes(nodes, nodes+NumNodes) {}
+
+ unsigned getNumNodes() const { return ChainNodes.size(); }
+
+ unsigned getNode(unsigned i) const {
+ assert(i < ChainNodes.size());
+ return ChainNodes[i];
+ }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitMergeInputChains;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitMergeInputChainsMatcher>(M)->ChainNodes == ChainNodes;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+/// EmitCopyToRegMatcher - Emit a CopyToReg node from a value to a physreg,
+/// pushing the chain and flag results.
+///
+class EmitCopyToRegMatcher : public Matcher {
+ unsigned SrcSlot; // Value to copy into the physreg.
+ Record *DestPhysReg;
+public:
+ EmitCopyToRegMatcher(unsigned srcSlot, Record *destPhysReg)
+ : Matcher(EmitCopyToReg), SrcSlot(srcSlot), DestPhysReg(destPhysReg) {}
+
+ unsigned getSrcSlot() const { return SrcSlot; }
+ Record *getDestPhysReg() const { return DestPhysReg; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitCopyToReg;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitCopyToRegMatcher>(M)->SrcSlot == SrcSlot &&
+ cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg;
+ }
+ virtual unsigned getHashImpl() const {
+ return SrcSlot ^ ((unsigned)(intptr_t)DestPhysReg << 4);
+ }
+};
+
+
+
+/// EmitNodeXFormMatcher - Emit an operation that runs an SDNodeXForm on a
+/// recorded node and records the result.
+class EmitNodeXFormMatcher : public Matcher {
+ unsigned Slot;
+ Record *NodeXForm;
+public:
+ EmitNodeXFormMatcher(unsigned slot, Record *nodeXForm)
+ : Matcher(EmitNodeXForm), Slot(slot), NodeXForm(nodeXForm) {}
+
+ unsigned getSlot() const { return Slot; }
+ Record *getNodeXForm() const { return NodeXForm; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitNodeXForm;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitNodeXFormMatcher>(M)->Slot == Slot &&
+ cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm;
+ }
+ virtual unsigned getHashImpl() const {
+ return Slot ^ ((unsigned)(intptr_t)NodeXForm << 4);
+ }
+};
+
+/// EmitNodeMatcherCommon - Common class shared between EmitNode and
+/// MorphNodeTo.
+class EmitNodeMatcherCommon : public Matcher {
+ std::string OpcodeName;
+ const SmallVector<MVT::SimpleValueType, 3> VTs;
+ const SmallVector<unsigned, 6> Operands;
+ bool HasChain, HasInFlag, HasOutFlag, HasMemRefs;
+
+ /// NumFixedArityOperands - If this is a fixed arity node, this is set to -1.
+ /// If this is a varidic node, this is set to the number of fixed arity
+ /// operands in the root of the pattern. The rest are appended to this node.
+ int NumFixedArityOperands;
+public:
+ EmitNodeMatcherCommon(const std::string &opcodeName,
+ const MVT::SimpleValueType *vts, unsigned numvts,
+ const unsigned *operands, unsigned numops,
+ bool hasChain, bool hasInFlag, bool hasOutFlag,
+ bool hasmemrefs,
+ int numfixedarityoperands, bool isMorphNodeTo)
+ : Matcher(isMorphNodeTo ? MorphNodeTo : EmitNode), OpcodeName(opcodeName),
+ VTs(vts, vts+numvts), Operands(operands, operands+numops),
+ HasChain(hasChain), HasInFlag(hasInFlag), HasOutFlag(hasOutFlag),
+ HasMemRefs(hasmemrefs), NumFixedArityOperands(numfixedarityoperands) {}
+
+ const std::string &getOpcodeName() const { return OpcodeName; }
+
+ unsigned getNumVTs() const { return VTs.size(); }
+ MVT::SimpleValueType getVT(unsigned i) const {
+ assert(i < VTs.size());
+ return VTs[i];
+ }
+
+ unsigned getNumOperands() const { return Operands.size(); }
+ unsigned getOperand(unsigned i) const {
+ assert(i < Operands.size());
+ return Operands[i];
+ }
+
+ const SmallVectorImpl<MVT::SimpleValueType> &getVTList() const { return VTs; }
+ const SmallVectorImpl<unsigned> &getOperandList() const { return Operands; }
+
+
+ bool hasChain() const { return HasChain; }
+ bool hasInFlag() const { return HasInFlag; }
+ bool hasOutFlag() const { return HasOutFlag; }
+ bool hasMemRefs() const { return HasMemRefs; }
+ int getNumFixedArityOperands() const { return NumFixedArityOperands; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitNode || N->getKind() == MorphNodeTo;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const;
+ virtual unsigned getHashImpl() const;
+};
+
+/// EmitNodeMatcher - This signals a successful match and generates a node.
+class EmitNodeMatcher : public EmitNodeMatcherCommon {
+ unsigned FirstResultSlot;
+public:
+ EmitNodeMatcher(const std::string &opcodeName,
+ const MVT::SimpleValueType *vts, unsigned numvts,
+ const unsigned *operands, unsigned numops,
+ bool hasChain, bool hasInFlag, bool hasOutFlag,
+ bool hasmemrefs,
+ int numfixedarityoperands, unsigned firstresultslot)
+ : EmitNodeMatcherCommon(opcodeName, vts, numvts, operands, numops, hasChain,
+ hasInFlag, hasOutFlag, hasmemrefs,
+ numfixedarityoperands, false),
+ FirstResultSlot(firstresultslot) {}
+
+ unsigned getFirstResultSlot() const { return FirstResultSlot; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitNode;
+ }
+
+};
+
+class MorphNodeToMatcher : public EmitNodeMatcherCommon {
+ const PatternToMatch &Pattern;
+public:
+ MorphNodeToMatcher(const std::string &opcodeName,
+ const MVT::SimpleValueType *vts, unsigned numvts,
+ const unsigned *operands, unsigned numops,
+ bool hasChain, bool hasInFlag, bool hasOutFlag,
+ bool hasmemrefs,
+ int numfixedarityoperands, const PatternToMatch &pattern)
+ : EmitNodeMatcherCommon(opcodeName, vts, numvts, operands, numops, hasChain,
+ hasInFlag, hasOutFlag, hasmemrefs,
+ numfixedarityoperands, true),
+ Pattern(pattern) {
+ }
+
+ const PatternToMatch &getPattern() const { return Pattern; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MorphNodeTo;
+ }
+};
+
+/// MarkFlagResultsMatcher - This node indicates which non-root nodes in the
+/// pattern produce flags. This allows CompleteMatchMatcher to update them
+/// with the output flag of the resultant code.
+class MarkFlagResultsMatcher : public Matcher {
+ SmallVector<unsigned, 3> FlagResultNodes;
+public:
+ MarkFlagResultsMatcher(const unsigned *nodes, unsigned NumNodes)
+ : Matcher(MarkFlagResults), FlagResultNodes(nodes, nodes+NumNodes) {}
+
+ unsigned getNumNodes() const { return FlagResultNodes.size(); }
+
+ unsigned getNode(unsigned i) const {
+ assert(i < FlagResultNodes.size());
+ return FlagResultNodes[i];
+ }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MarkFlagResults;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<MarkFlagResultsMatcher>(M)->FlagResultNodes == FlagResultNodes;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+/// CompleteMatchMatcher - Complete a match by replacing the results of the
+/// pattern with the newly generated nodes. This also prints a comment
+/// indicating the source and dest patterns.
+class CompleteMatchMatcher : public Matcher {
+ SmallVector<unsigned, 2> Results;
+ const PatternToMatch &Pattern;
+public:
+ CompleteMatchMatcher(const unsigned *results, unsigned numresults,
+ const PatternToMatch &pattern)
+ : Matcher(CompleteMatch), Results(results, results+numresults),
+ Pattern(pattern) {}
+
+ unsigned getNumResults() const { return Results.size(); }
+ unsigned getResult(unsigned R) const { return Results[R]; }
+ const PatternToMatch &getPattern() const { return Pattern; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CompleteMatch;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CompleteMatchMatcher>(M)->Results == Results &&
+ &cast<CompleteMatchMatcher>(M)->Pattern == &Pattern;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
new file mode 100644
index 0000000..dfbfe80
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -0,0 +1,795 @@
+//===- DAGISelMatcherEmitter.cpp - Matcher Emitter ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to generate C++ code for a matcher.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "Record.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
+using namespace llvm;
+
+enum {
+ CommentIndent = 30
+};
+
+// To reduce generated source code size.
+static cl::opt<bool>
+OmitComments("omit-comments", cl::desc("Do not generate comments"),
+ cl::init(false));
+
+namespace {
+class MatcherTableEmitter {
+ const CodeGenDAGPatterns &CGP;
+ StringMap<unsigned> NodePredicateMap, PatternPredicateMap;
+ std::vector<std::string> NodePredicates, PatternPredicates;
+
+ DenseMap<const ComplexPattern*, unsigned> ComplexPatternMap;
+ std::vector<const ComplexPattern*> ComplexPatterns;
+
+
+ DenseMap<Record*, unsigned> NodeXFormMap;
+ std::vector<Record*> NodeXForms;
+
+public:
+ MatcherTableEmitter(const CodeGenDAGPatterns &cgp) : CGP(cgp) {}
+
+ unsigned EmitMatcherList(const Matcher *N, unsigned Indent,
+ unsigned StartIdx, formatted_raw_ostream &OS);
+
+ void EmitPredicateFunctions(formatted_raw_ostream &OS);
+
+ void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS);
+private:
+ unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
+ formatted_raw_ostream &OS);
+
+ unsigned getNodePredicate(StringRef PredName) {
+ unsigned &Entry = NodePredicateMap[PredName];
+ if (Entry == 0) {
+ NodePredicates.push_back(PredName.str());
+ Entry = NodePredicates.size();
+ }
+ return Entry-1;
+ }
+ unsigned getPatternPredicate(StringRef PredName) {
+ unsigned &Entry = PatternPredicateMap[PredName];
+ if (Entry == 0) {
+ PatternPredicates.push_back(PredName.str());
+ Entry = PatternPredicates.size();
+ }
+ return Entry-1;
+ }
+
+ unsigned getComplexPat(const ComplexPattern &P) {
+ unsigned &Entry = ComplexPatternMap[&P];
+ if (Entry == 0) {
+ ComplexPatterns.push_back(&P);
+ Entry = ComplexPatterns.size();
+ }
+ return Entry-1;
+ }
+
+ unsigned getNodeXFormID(Record *Rec) {
+ unsigned &Entry = NodeXFormMap[Rec];
+ if (Entry == 0) {
+ NodeXForms.push_back(Rec);
+ Entry = NodeXForms.size();
+ }
+ return Entry-1;
+ }
+
+};
+} // end anonymous namespace.
+
+static unsigned GetVBRSize(unsigned Val) {
+ if (Val <= 127) return 1;
+
+ unsigned NumBytes = 0;
+ while (Val >= 128) {
+ Val >>= 7;
+ ++NumBytes;
+ }
+ return NumBytes+1;
+}
+
+/// EmitVBRValue - Emit the specified value as a VBR, returning the number of
+/// bytes emitted.
+static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) {
+ if (Val <= 127) {
+ OS << Val << ", ";
+ return 1;
+ }
+
+ uint64_t InVal = Val;
+ unsigned NumBytes = 0;
+ while (Val >= 128) {
+ OS << (Val&127) << "|128,";
+ Val >>= 7;
+ ++NumBytes;
+ }
+ OS << Val;
+ if (!OmitComments)
+ OS << "/*" << InVal << "*/";
+ OS << ", ";
+ return NumBytes+1;
+}
+
+/// EmitMatcherOpcodes - Emit bytes for the specified matcher and return
+/// the number of bytes emitted.
+unsigned MatcherTableEmitter::
+EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
+ formatted_raw_ostream &OS) {
+ OS.PadToColumn(Indent*2);
+
+ switch (N->getKind()) {
+ case Matcher::Scope: {
+ const ScopeMatcher *SM = cast<ScopeMatcher>(N);
+ assert(SM->getNext() == 0 && "Shouldn't have next after scope");
+
+ unsigned StartIdx = CurrentIdx;
+
+ // Emit all of the children.
+ for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) {
+ if (i == 0) {
+ OS << "OPC_Scope, ";
+ ++CurrentIdx;
+ } else {
+ if (!OmitComments) {
+ OS << "/*" << CurrentIdx << "*/";
+ OS.PadToColumn(Indent*2) << "/*Scope*/ ";
+ } else
+ OS.PadToColumn(Indent*2);
+ }
+
+ // We need to encode the child and the offset of the failure code before
+ // emitting either of them. Handle this by buffering the output into a
+ // string while we get the size. Unfortunately, the offset of the
+ // children depends on the VBR size of the child, so for large children we
+ // have to iterate a bit.
+ SmallString<128> TmpBuf;
+ unsigned ChildSize = 0;
+ unsigned VBRSize = 0;
+ do {
+ VBRSize = GetVBRSize(ChildSize);
+
+ TmpBuf.clear();
+ raw_svector_ostream OS(TmpBuf);
+ formatted_raw_ostream FOS(OS);
+ ChildSize = EmitMatcherList(SM->getChild(i), Indent+1,
+ CurrentIdx+VBRSize, FOS);
+ } while (GetVBRSize(ChildSize) != VBRSize);
+
+ assert(ChildSize != 0 && "Should not have a zero-sized child!");
+
+ CurrentIdx += EmitVBRValue(ChildSize, OS);
+ if (!OmitComments) {
+ OS << "/*->" << CurrentIdx+ChildSize << "*/";
+
+ if (i == 0)
+ OS.PadToColumn(CommentIndent) << "// " << SM->getNumChildren()
+ << " children in Scope";
+ }
+
+ OS << '\n' << TmpBuf.str();
+ CurrentIdx += ChildSize;
+ }
+
+ // Emit a zero as a sentinel indicating end of 'Scope'.
+ if (!OmitComments)
+ OS << "/*" << CurrentIdx << "*/";
+ OS.PadToColumn(Indent*2) << "0, ";
+ if (!OmitComments)
+ OS << "/*End of Scope*/";
+ OS << '\n';
+ return CurrentIdx - StartIdx + 1;
+ }
+
+ case Matcher::RecordNode:
+ OS << "OPC_RecordNode,";
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// #"
+ << cast<RecordMatcher>(N)->getResultNo() << " = "
+ << cast<RecordMatcher>(N)->getWhatFor();
+ OS << '\n';
+ return 1;
+
+ case Matcher::RecordChild:
+ OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo()
+ << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// #"
+ << cast<RecordChildMatcher>(N)->getResultNo() << " = "
+ << cast<RecordChildMatcher>(N)->getWhatFor();
+ OS << '\n';
+ return 1;
+
+ case Matcher::RecordMemRef:
+ OS << "OPC_RecordMemRef,\n";
+ return 1;
+
+ case Matcher::CaptureFlagInput:
+ OS << "OPC_CaptureFlagInput,\n";
+ return 1;
+
+ case Matcher::MoveChild:
+ OS << "OPC_MoveChild, " << cast<MoveChildMatcher>(N)->getChildNo() << ",\n";
+ return 2;
+
+ case Matcher::MoveParent:
+ OS << "OPC_MoveParent,\n";
+ return 1;
+
+ case Matcher::CheckSame:
+ OS << "OPC_CheckSame, "
+ << cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n";
+ return 2;
+
+ case Matcher::CheckPatternPredicate: {
+ StringRef Pred = cast<CheckPatternPredicateMatcher>(N)->getPredicate();
+ OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// " << Pred;
+ OS << '\n';
+ return 2;
+ }
+ case Matcher::CheckPredicate: {
+ StringRef Pred = cast<CheckPredicateMatcher>(N)->getPredicateName();
+ OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// " << Pred;
+ OS << '\n';
+ return 2;
+ }
+
+ case Matcher::CheckOpcode:
+ OS << "OPC_CheckOpcode, TARGET_OPCODE("
+ << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n";
+ return 3;
+
+ case Matcher::SwitchOpcode:
+ case Matcher::SwitchType: {
+ unsigned StartIdx = CurrentIdx;
+
+ unsigned NumCases;
+ if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
+ OS << "OPC_SwitchOpcode ";
+ NumCases = SOM->getNumCases();
+ } else {
+ OS << "OPC_SwitchType ";
+ NumCases = cast<SwitchTypeMatcher>(N)->getNumCases();
+ }
+
+ if (!OmitComments)
+ OS << "/*" << NumCases << " cases */";
+ OS << ", ";
+ ++CurrentIdx;
+
+ // For each case we emit the size, then the opcode, then the matcher.
+ for (unsigned i = 0, e = NumCases; i != e; ++i) {
+ const Matcher *Child;
+ unsigned IdxSize;
+ if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
+ Child = SOM->getCaseMatcher(i);
+ IdxSize = 2; // size of opcode in table is 2 bytes.
+ } else {
+ Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
+ IdxSize = 1; // size of type in table is 1 byte.
+ }
+
+ // We need to encode the opcode and the offset of the case code before
+ // emitting the case code. Handle this by buffering the output into a
+ // string while we get the size. Unfortunately, the offset of the
+ // children depends on the VBR size of the child, so for large children we
+ // have to iterate a bit.
+ SmallString<128> TmpBuf;
+ unsigned ChildSize = 0;
+ unsigned VBRSize = 0;
+ do {
+ VBRSize = GetVBRSize(ChildSize);
+
+ TmpBuf.clear();
+ raw_svector_ostream OS(TmpBuf);
+ formatted_raw_ostream FOS(OS);
+ ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize,
+ FOS);
+ } while (GetVBRSize(ChildSize) != VBRSize);
+
+ assert(ChildSize != 0 && "Should not have a zero-sized child!");
+
+ if (i != 0) {
+ OS.PadToColumn(Indent*2);
+ if (!OmitComments)
+ OS << (isa<SwitchOpcodeMatcher>(N) ?
+ "/*SwitchOpcode*/ " : "/*SwitchType*/ ");
+ }
+
+ // Emit the VBR.
+ CurrentIdx += EmitVBRValue(ChildSize, OS);
+
+ OS << ' ';
+ if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
+ OS << "TARGET_OPCODE(" << SOM->getCaseOpcode(i).getEnumName() << "),";
+ else
+ OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ',';
+
+ CurrentIdx += IdxSize;
+
+ if (!OmitComments)
+ OS << "// ->" << CurrentIdx+ChildSize;
+ OS << '\n';
+ OS << TmpBuf.str();
+ CurrentIdx += ChildSize;
+ }
+
+ // Emit the final zero to terminate the switch.
+ OS.PadToColumn(Indent*2) << "0, ";
+ if (!OmitComments)
+ OS << (isa<SwitchOpcodeMatcher>(N) ?
+ "// EndSwitchOpcode" : "// EndSwitchType");
+
+ OS << '\n';
+ ++CurrentIdx;
+ return CurrentIdx-StartIdx;
+ }
+
+ case Matcher::CheckType:
+ assert(cast<CheckTypeMatcher>(N)->getResNo() == 0 &&
+ "FIXME: Add support for CheckType of resno != 0");
+ OS << "OPC_CheckType, "
+ << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n";
+ return 2;
+
+ case Matcher::CheckChildType:
+ OS << "OPC_CheckChild"
+ << cast<CheckChildTypeMatcher>(N)->getChildNo() << "Type, "
+ << getEnumName(cast<CheckChildTypeMatcher>(N)->getType()) << ",\n";
+ return 2;
+
+ case Matcher::CheckInteger: {
+ OS << "OPC_CheckInteger, ";
+ unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);
+ OS << '\n';
+ return Bytes;
+ }
+ case Matcher::CheckCondCode:
+ OS << "OPC_CheckCondCode, ISD::"
+ << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n";
+ return 2;
+
+ case Matcher::CheckValueType:
+ OS << "OPC_CheckValueType, MVT::"
+ << cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n";
+ return 2;
+
+ case Matcher::CheckComplexPat: {
+ const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N);
+ const ComplexPattern &Pattern = CCPM->getPattern();
+ OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/"
+ << CCPM->getMatchNumber() << ',';
+
+ if (!OmitComments) {
+ OS.PadToColumn(CommentIndent) << "// " << Pattern.getSelectFunc();
+ OS << ":$" << CCPM->getName();
+ for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i)
+ OS << " #" << CCPM->getFirstResult()+i;
+
+ if (Pattern.hasProperty(SDNPHasChain))
+ OS << " + chain result";
+ }
+ OS << '\n';
+ return 3;
+ }
+
+ case Matcher::CheckAndImm: {
+ OS << "OPC_CheckAndImm, ";
+ unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS);
+ OS << '\n';
+ return Bytes;
+ }
+
+ case Matcher::CheckOrImm: {
+ OS << "OPC_CheckOrImm, ";
+ unsigned Bytes = 1+EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS);
+ OS << '\n';
+ return Bytes;
+ }
+
+ case Matcher::CheckFoldableChainNode:
+ OS << "OPC_CheckFoldableChainNode,\n";
+ return 1;
+
+ case Matcher::EmitInteger: {
+ int64_t Val = cast<EmitIntegerMatcher>(N)->getValue();
+ OS << "OPC_EmitInteger, "
+ << getEnumName(cast<EmitIntegerMatcher>(N)->getVT()) << ", ";
+ unsigned Bytes = 2+EmitVBRValue(Val, OS);
+ OS << '\n';
+ return Bytes;
+ }
+ case Matcher::EmitStringInteger: {
+ const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue();
+ // These should always fit into one byte.
+ OS << "OPC_EmitInteger, "
+ << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", "
+ << Val << ",\n";
+ return 3;
+ }
+
+ case Matcher::EmitRegister:
+ OS << "OPC_EmitRegister, "
+ << getEnumName(cast<EmitRegisterMatcher>(N)->getVT()) << ", ";
+ if (Record *R = cast<EmitRegisterMatcher>(N)->getReg())
+ OS << getQualifiedName(R) << ",\n";
+ else {
+ OS << "0 ";
+ if (!OmitComments)
+ OS << "/*zero_reg*/";
+ OS << ",\n";
+ }
+ return 3;
+
+ case Matcher::EmitConvertToTarget:
+ OS << "OPC_EmitConvertToTarget, "
+ << cast<EmitConvertToTargetMatcher>(N)->getSlot() << ",\n";
+ return 2;
+
+ case Matcher::EmitMergeInputChains: {
+ const EmitMergeInputChainsMatcher *MN =
+ cast<EmitMergeInputChainsMatcher>(N);
+
+ // Handle the specialized forms OPC_EmitMergeInputChains1_0 and 1_1.
+ if (MN->getNumNodes() == 1 && MN->getNode(0) < 2) {
+ OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n";
+ return 1;
+ }
+
+ OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", ";
+ for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i)
+ OS << MN->getNode(i) << ", ";
+ OS << '\n';
+ return 2+MN->getNumNodes();
+ }
+ case Matcher::EmitCopyToReg:
+ OS << "OPC_EmitCopyToReg, "
+ << cast<EmitCopyToRegMatcher>(N)->getSrcSlot() << ", "
+ << getQualifiedName(cast<EmitCopyToRegMatcher>(N)->getDestPhysReg())
+ << ",\n";
+ return 3;
+ case Matcher::EmitNodeXForm: {
+ const EmitNodeXFormMatcher *XF = cast<EmitNodeXFormMatcher>(N);
+ OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", "
+ << XF->getSlot() << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// "<<XF->getNodeXForm()->getName();
+ OS <<'\n';
+ return 3;
+ }
+
+ case Matcher::EmitNode:
+ case Matcher::MorphNodeTo: {
+ const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N);
+ OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo");
+ OS << ", TARGET_OPCODE(" << EN->getOpcodeName() << "), 0";
+
+ if (EN->hasChain()) OS << "|OPFL_Chain";
+ if (EN->hasInFlag()) OS << "|OPFL_FlagInput";
+ if (EN->hasOutFlag()) OS << "|OPFL_FlagOutput";
+ if (EN->hasMemRefs()) OS << "|OPFL_MemRefs";
+ if (EN->getNumFixedArityOperands() != -1)
+ OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();
+ OS << ",\n";
+
+ OS.PadToColumn(Indent*2+4) << EN->getNumVTs();
+ if (!OmitComments)
+ OS << "/*#VTs*/";
+ OS << ", ";
+ for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i)
+ OS << getEnumName(EN->getVT(i)) << ", ";
+
+ OS << EN->getNumOperands();
+ if (!OmitComments)
+ OS << "/*#Ops*/";
+ OS << ", ";
+ unsigned NumOperandBytes = 0;
+ for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i)
+ NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS);
+
+ if (!OmitComments) {
+ // Print the result #'s for EmitNode.
+ if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) {
+ if (unsigned NumResults = EN->getNumVTs()) {
+ OS.PadToColumn(CommentIndent) << "// Results = ";
+ unsigned First = E->getFirstResultSlot();
+ for (unsigned i = 0; i != NumResults; ++i)
+ OS << "#" << First+i << " ";
+ }
+ }
+ OS << '\n';
+
+ if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
+ OS.PadToColumn(Indent*2) << "// Src: "
+ << *SNT->getPattern().getSrcPattern() << " - Complexity = "
+ << SNT->getPattern().getPatternComplexity(CGP) << '\n';
+ OS.PadToColumn(Indent*2) << "// Dst: "
+ << *SNT->getPattern().getDstPattern() << '\n';
+ }
+ } else
+ OS << '\n';
+
+ return 6+EN->getNumVTs()+NumOperandBytes;
+ }
+ case Matcher::MarkFlagResults: {
+ const MarkFlagResultsMatcher *CFR = cast<MarkFlagResultsMatcher>(N);
+ OS << "OPC_MarkFlagResults, " << CFR->getNumNodes() << ", ";
+ unsigned NumOperandBytes = 0;
+ for (unsigned i = 0, e = CFR->getNumNodes(); i != e; ++i)
+ NumOperandBytes += EmitVBRValue(CFR->getNode(i), OS);
+ OS << '\n';
+ return 2+NumOperandBytes;
+ }
+ case Matcher::CompleteMatch: {
+ const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N);
+ OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", ";
+ unsigned NumResultBytes = 0;
+ for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
+ NumResultBytes += EmitVBRValue(CM->getResult(i), OS);
+ OS << '\n';
+ if (!OmitComments) {
+ OS.PadToColumn(Indent*2) << "// Src: "
+ << *CM->getPattern().getSrcPattern() << " - Complexity = "
+ << CM->getPattern().getPatternComplexity(CGP) << '\n';
+ OS.PadToColumn(Indent*2) << "// Dst: "
+ << *CM->getPattern().getDstPattern();
+ }
+ OS << '\n';
+ return 2 + NumResultBytes;
+ }
+ }
+ assert(0 && "Unreachable");
+ return 0;
+}
+
+/// EmitMatcherList - Emit the bytes for the specified matcher subtree.
+unsigned MatcherTableEmitter::
+EmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
+ formatted_raw_ostream &OS) {
+ unsigned Size = 0;
+ while (N) {
+ if (!OmitComments)
+ OS << "/*" << CurrentIdx << "*/";
+ unsigned MatcherSize = EmitMatcher(N, Indent, CurrentIdx, OS);
+ Size += MatcherSize;
+ CurrentIdx += MatcherSize;
+
+ // If there are other nodes in this list, iterate to them, otherwise we're
+ // done.
+ N = N->getNext();
+ }
+ return Size;
+}
+
+void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
+ // Emit pattern predicates.
+ if (!PatternPredicates.empty()) {
+ OS << "bool CheckPatternPredicate(unsigned PredNo) const {\n";
+ OS << " switch (PredNo) {\n";
+ OS << " default: assert(0 && \"Invalid predicate in table?\");\n";
+ for (unsigned i = 0, e = PatternPredicates.size(); i != e; ++i)
+ OS << " case " << i << ": return " << PatternPredicates[i] << ";\n";
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+
+ // Emit Node predicates.
+ // FIXME: Annoyingly, these are stored by name, which we never even emit. Yay?
+ StringMap<TreePattern*> PFsByName;
+
+ for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end();
+ I != E; ++I)
+ PFsByName[I->first->getName()] = I->second;
+
+ if (!NodePredicates.empty()) {
+ OS << "bool CheckNodePredicate(SDNode *Node, unsigned PredNo) const {\n";
+ OS << " switch (PredNo) {\n";
+ OS << " default: assert(0 && \"Invalid predicate in table?\");\n";
+ for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) {
+ // FIXME: Storing this by name is horrible.
+ TreePattern *P =PFsByName[NodePredicates[i].substr(strlen("Predicate_"))];
+ assert(P && "Unknown name?");
+
+ // Emit the predicate code corresponding to this pattern.
+ std::string Code = P->getRecord()->getValueAsCode("Predicate");
+ assert(!Code.empty() && "No code in this predicate");
+ OS << " case " << i << ": { // " << NodePredicates[i] << '\n';
+ std::string ClassName;
+ if (P->getOnlyTree()->isLeaf())
+ ClassName = "SDNode";
+ else
+ ClassName =
+ CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
+ if (ClassName == "SDNode")
+ OS << " SDNode *N = Node;\n";
+ else
+ OS << " " << ClassName << "*N = cast<" << ClassName << ">(Node);\n";
+ OS << Code << "\n }\n";
+ }
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+
+ // Emit CompletePattern matchers.
+ // FIXME: This should be const.
+ if (!ComplexPatterns.empty()) {
+ OS << "bool CheckComplexPattern(SDNode *Root, SDValue N,\n";
+ OS << " unsigned PatternNo, SmallVectorImpl<SDValue> &Result) {\n";
+ OS << " unsigned NextRes = Result.size();\n";
+ OS << " switch (PatternNo) {\n";
+ OS << " default: assert(0 && \"Invalid pattern # in table?\");\n";
+ for (unsigned i = 0, e = ComplexPatterns.size(); i != e; ++i) {
+ const ComplexPattern &P = *ComplexPatterns[i];
+ unsigned NumOps = P.getNumOperands();
+
+ if (P.hasProperty(SDNPHasChain))
+ ++NumOps; // Get the chained node too.
+
+ OS << " case " << i << ":\n";
+ OS << " Result.resize(NextRes+" << NumOps << ");\n";
+ OS << " return " << P.getSelectFunc();
+
+ OS << "(Root, N";
+ for (unsigned i = 0; i != NumOps; ++i)
+ OS << ", Result[NextRes+" << i << ']';
+ OS << ");\n";
+ }
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+
+
+ // Emit SDNodeXForm handlers.
+ // FIXME: This should be const.
+ if (!NodeXForms.empty()) {
+ OS << "SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) {\n";
+ OS << " switch (XFormNo) {\n";
+ OS << " default: assert(0 && \"Invalid xform # in table?\");\n";
+
+ // FIXME: The node xform could take SDValue's instead of SDNode*'s.
+ for (unsigned i = 0, e = NodeXForms.size(); i != e; ++i) {
+ const CodeGenDAGPatterns::NodeXForm &Entry =
+ CGP.getSDNodeTransform(NodeXForms[i]);
+
+ Record *SDNode = Entry.first;
+ const std::string &Code = Entry.second;
+
+ OS << " case " << i << ": { ";
+ if (!OmitComments)
+ OS << "// " << NodeXForms[i]->getName();
+ OS << '\n';
+
+ std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName();
+ if (ClassName == "SDNode")
+ OS << " SDNode *N = V.getNode();\n";
+ else
+ OS << " " << ClassName << " *N = cast<" << ClassName
+ << ">(V.getNode());\n";
+ OS << Code << "\n }\n";
+ }
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+}
+
+static void BuildHistogram(const Matcher *M, std::vector<unsigned> &OpcodeFreq){
+ for (; M != 0; M = M->getNext()) {
+ // Count this node.
+ if (unsigned(M->getKind()) >= OpcodeFreq.size())
+ OpcodeFreq.resize(M->getKind()+1);
+ OpcodeFreq[M->getKind()]++;
+
+ // Handle recursive nodes.
+ if (const ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M)) {
+ for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i)
+ BuildHistogram(SM->getChild(i), OpcodeFreq);
+ } else if (const SwitchOpcodeMatcher *SOM =
+ dyn_cast<SwitchOpcodeMatcher>(M)) {
+ for (unsigned i = 0, e = SOM->getNumCases(); i != e; ++i)
+ BuildHistogram(SOM->getCaseMatcher(i), OpcodeFreq);
+ } else if (const SwitchTypeMatcher *STM = dyn_cast<SwitchTypeMatcher>(M)) {
+ for (unsigned i = 0, e = STM->getNumCases(); i != e; ++i)
+ BuildHistogram(STM->getCaseMatcher(i), OpcodeFreq);
+ }
+ }
+}
+
+void MatcherTableEmitter::EmitHistogram(const Matcher *M,
+ formatted_raw_ostream &OS) {
+ if (OmitComments)
+ return;
+
+ std::vector<unsigned> OpcodeFreq;
+ BuildHistogram(M, OpcodeFreq);
+
+ OS << " // Opcode Histogram:\n";
+ for (unsigned i = 0, e = OpcodeFreq.size(); i != e; ++i) {
+ OS << " // #";
+ switch ((Matcher::KindTy)i) {
+ case Matcher::Scope: OS << "OPC_Scope"; break;
+ case Matcher::RecordNode: OS << "OPC_RecordNode"; break;
+ case Matcher::RecordChild: OS << "OPC_RecordChild"; break;
+ case Matcher::RecordMemRef: OS << "OPC_RecordMemRef"; break;
+ case Matcher::CaptureFlagInput: OS << "OPC_CaptureFlagInput"; break;
+ case Matcher::MoveChild: OS << "OPC_MoveChild"; break;
+ case Matcher::MoveParent: OS << "OPC_MoveParent"; break;
+ case Matcher::CheckSame: OS << "OPC_CheckSame"; break;
+ case Matcher::CheckPatternPredicate:
+ OS << "OPC_CheckPatternPredicate"; break;
+ case Matcher::CheckPredicate: OS << "OPC_CheckPredicate"; break;
+ case Matcher::CheckOpcode: OS << "OPC_CheckOpcode"; break;
+ case Matcher::SwitchOpcode: OS << "OPC_SwitchOpcode"; break;
+ case Matcher::CheckType: OS << "OPC_CheckType"; break;
+ case Matcher::SwitchType: OS << "OPC_SwitchType"; break;
+ case Matcher::CheckChildType: OS << "OPC_CheckChildType"; break;
+ case Matcher::CheckInteger: OS << "OPC_CheckInteger"; break;
+ case Matcher::CheckCondCode: OS << "OPC_CheckCondCode"; break;
+ case Matcher::CheckValueType: OS << "OPC_CheckValueType"; break;
+ case Matcher::CheckComplexPat: OS << "OPC_CheckComplexPat"; break;
+ case Matcher::CheckAndImm: OS << "OPC_CheckAndImm"; break;
+ case Matcher::CheckOrImm: OS << "OPC_CheckOrImm"; break;
+ case Matcher::CheckFoldableChainNode:
+ OS << "OPC_CheckFoldableChainNode"; break;
+ case Matcher::EmitInteger: OS << "OPC_EmitInteger"; break;
+ case Matcher::EmitStringInteger: OS << "OPC_EmitStringInteger"; break;
+ case Matcher::EmitRegister: OS << "OPC_EmitRegister"; break;
+ case Matcher::EmitConvertToTarget: OS << "OPC_EmitConvertToTarget"; break;
+ case Matcher::EmitMergeInputChains: OS << "OPC_EmitMergeInputChains"; break;
+ case Matcher::EmitCopyToReg: OS << "OPC_EmitCopyToReg"; break;
+ case Matcher::EmitNode: OS << "OPC_EmitNode"; break;
+ case Matcher::MorphNodeTo: OS << "OPC_MorphNodeTo"; break;
+ case Matcher::EmitNodeXForm: OS << "OPC_EmitNodeXForm"; break;
+ case Matcher::MarkFlagResults: OS << "OPC_MarkFlagResults"; break;
+ case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break;
+ }
+
+ OS.PadToColumn(40) << " = " << OpcodeFreq[i] << '\n';
+ }
+ OS << '\n';
+}
+
+
+void llvm::EmitMatcherTable(const Matcher *TheMatcher,
+ const CodeGenDAGPatterns &CGP, raw_ostream &O) {
+ formatted_raw_ostream OS(O);
+
+ OS << "// The main instruction selector code.\n";
+ OS << "SDNode *SelectCode(SDNode *N) {\n";
+
+ MatcherTableEmitter MatcherEmitter(CGP);
+
+ OS << " // Opcodes are emitted as 2 bytes, TARGET_OPCODE handles this.\n";
+ OS << " #define TARGET_OPCODE(X) X & 255, unsigned(X) >> 8\n";
+ OS << " static const unsigned char MatcherTable[] = {\n";
+ unsigned TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 5, 0, OS);
+ OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n";
+
+ MatcherEmitter.EmitHistogram(TheMatcher, OS);
+
+ OS << " #undef TARGET_OPCODE\n";
+ OS << " return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n";
+ OS << '\n';
+
+ // Next up, emit the function for node and pattern predicates:
+ MatcherEmitter.EmitPredicateFunctions(OS);
+}
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
new file mode 100644
index 0000000..aba6636
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
@@ -0,0 +1,910 @@
+//===- DAGISelMatcherGen.cpp - Matcher generator --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "Record.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include <utility>
+using namespace llvm;
+
+
+/// getRegisterValueType - Look up and return the ValueType of the specified
+/// register. If the register is a member of multiple register classes which
+/// have different associated types, return MVT::Other.
+static MVT::SimpleValueType getRegisterValueType(Record *R,
+ const CodeGenTarget &T) {
+ bool FoundRC = false;
+ MVT::SimpleValueType VT = MVT::Other;
+ const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
+ std::vector<Record*>::const_iterator Element;
+
+ for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RCs[rc];
+ if (!std::count(RC.Elements.begin(), RC.Elements.end(), R))
+ continue;
+
+ if (!FoundRC) {
+ FoundRC = true;
+ VT = RC.getValueTypeNum(0);
+ continue;
+ }
+
+ // If this occurs in multiple register classes, they all have to agree.
+ assert(VT == RC.getValueTypeNum(0));
+ }
+ return VT;
+}
+
+
+namespace {
+ class MatcherGen {
+ const PatternToMatch &Pattern;
+ const CodeGenDAGPatterns &CGP;
+
+ /// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts
+ /// out with all of the types removed. This allows us to insert type checks
+ /// as we scan the tree.
+ TreePatternNode *PatWithNoTypes;
+
+ /// VariableMap - A map from variable names ('$dst') to the recorded operand
+ /// number that they were captured as. These are biased by 1 to make
+ /// insertion easier.
+ StringMap<unsigned> VariableMap;
+
+ /// NextRecordedOperandNo - As we emit opcodes to record matched values in
+ /// the RecordedNodes array, this keeps track of which slot will be next to
+ /// record into.
+ unsigned NextRecordedOperandNo;
+
+ /// MatchedChainNodes - This maintains the position in the recorded nodes
+ /// array of all of the recorded input nodes that have chains.
+ SmallVector<unsigned, 2> MatchedChainNodes;
+
+ /// MatchedFlagResultNodes - This maintains the position in the recorded
+ /// nodes array of all of the recorded input nodes that have flag results.
+ SmallVector<unsigned, 2> MatchedFlagResultNodes;
+
+ /// MatchedComplexPatterns - This maintains a list of all of the
+ /// ComplexPatterns that we need to check. The patterns are known to have
+ /// names which were recorded. The second element of each pair is the first
+ /// slot number that the OPC_CheckComplexPat opcode drops the matched
+ /// results into.
+ SmallVector<std::pair<const TreePatternNode*,
+ unsigned>, 2> MatchedComplexPatterns;
+
+ /// PhysRegInputs - List list has an entry for each explicitly specified
+ /// physreg input to the pattern. The first elt is the Register node, the
+ /// second is the recorded slot number the input pattern match saved it in.
+ SmallVector<std::pair<Record*, unsigned>, 2> PhysRegInputs;
+
+ /// Matcher - This is the top level of the generated matcher, the result.
+ Matcher *TheMatcher;
+
+ /// CurPredicate - As we emit matcher nodes, this points to the latest check
+ /// which should have future checks stuck into its Next position.
+ Matcher *CurPredicate;
+ public:
+ MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp);
+
+ ~MatcherGen() {
+ delete PatWithNoTypes;
+ }
+
+ bool EmitMatcherCode(unsigned Variant);
+ void EmitResultCode();
+
+ Matcher *GetMatcher() const { return TheMatcher; }
+ Matcher *GetCurPredicate() const { return CurPredicate; }
+ private:
+ void AddMatcher(Matcher *NewNode);
+ void InferPossibleTypes();
+
+ // Matcher Generation.
+ void EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes);
+ void EmitLeafMatchCode(const TreePatternNode *N);
+ void EmitOperatorMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes);
+
+ // Result Code Generation.
+ unsigned getNamedArgumentSlot(StringRef Name) {
+ unsigned VarMapEntry = VariableMap[Name];
+ assert(VarMapEntry != 0 &&
+ "Variable referenced but not defined and not caught earlier!");
+ return VarMapEntry-1;
+ }
+
+ /// GetInstPatternNode - Get the pattern for an instruction.
+ const TreePatternNode *GetInstPatternNode(const DAGInstruction &Ins,
+ const TreePatternNode *N);
+
+ void EmitResultOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultOfNamedOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultLeafAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultInstructionAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ };
+
+} // end anon namespace.
+
+MatcherGen::MatcherGen(const PatternToMatch &pattern,
+ const CodeGenDAGPatterns &cgp)
+: Pattern(pattern), CGP(cgp), NextRecordedOperandNo(0),
+ TheMatcher(0), CurPredicate(0) {
+ // We need to produce the matcher tree for the patterns source pattern. To do
+ // this we need to match the structure as well as the types. To do the type
+ // matching, we want to figure out the fewest number of type checks we need to
+ // emit. For example, if there is only one integer type supported by a
+ // target, there should be no type comparisons at all for integer patterns!
+ //
+ // To figure out the fewest number of type checks needed, clone the pattern,
+ // remove the types, then perform type inference on the pattern as a whole.
+ // If there are unresolved types, emit an explicit check for those types,
+ // apply the type to the tree, then rerun type inference. Iterate until all
+ // types are resolved.
+ //
+ PatWithNoTypes = Pattern.getSrcPattern()->clone();
+ PatWithNoTypes->RemoveAllTypes();
+
+ // If there are types that are manifestly known, infer them.
+ InferPossibleTypes();
+}
+
+/// InferPossibleTypes - As we emit the pattern, we end up generating type
+/// checks and applying them to the 'PatWithNoTypes' tree. As we do this, we
+/// want to propagate implied types as far throughout the tree as possible so
+/// that we avoid doing redundant type checks. This does the type propagation.
+void MatcherGen::InferPossibleTypes() {
+ // TP - Get *SOME* tree pattern, we don't care which. It is only used for
+ // diagnostics, which we know are impossible at this point.
+ TreePattern &TP = *CGP.pf_begin()->second;
+
+ try {
+ bool MadeChange = true;
+ while (MadeChange)
+ MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP,
+ true/*Ignore reg constraints*/);
+ } catch (...) {
+ errs() << "Type constraint application shouldn't fail!";
+ abort();
+ }
+}
+
+
+/// AddMatcher - Add a matcher node to the current graph we're building.
+void MatcherGen::AddMatcher(Matcher *NewNode) {
+ if (CurPredicate != 0)
+ CurPredicate->setNext(NewNode);
+ else
+ TheMatcher = NewNode;
+ CurPredicate = NewNode;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Pattern Match Generation
+//===----------------------------------------------------------------------===//
+
+/// EmitLeafMatchCode - Generate matching code for leaf nodes.
+void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
+ assert(N->isLeaf() && "Not a leaf?");
+
+ // Direct match against an integer constant.
+ if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
+ // If this is the root of the dag we're matching, we emit a redundant opcode
+ // check to ensure that this gets folded into the normal top-level
+ // OpcodeSwitch.
+ if (N == Pattern.getSrcPattern()) {
+ const SDNodeInfo &NI = CGP.getSDNodeInfo(CGP.getSDNodeNamed("imm"));
+ AddMatcher(new CheckOpcodeMatcher(NI));
+ }
+
+ return AddMatcher(new CheckIntegerMatcher(II->getValue()));
+ }
+
+ DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue());
+ if (DI == 0) {
+ errs() << "Unknown leaf kind: " << *DI << "\n";
+ abort();
+ }
+
+ Record *LeafRec = DI->getDef();
+ if (// Handle register references. Nothing to do here, they always match.
+ LeafRec->isSubClassOf("RegisterClass") ||
+ LeafRec->isSubClassOf("PointerLikeRegClass") ||
+ LeafRec->isSubClassOf("SubRegIndex") ||
+ // Place holder for SRCVALUE nodes. Nothing to do here.
+ LeafRec->getName() == "srcvalue")
+ return;
+
+ // If we have a physreg reference like (mul gpr:$src, EAX) then we need to
+ // record the register
+ if (LeafRec->isSubClassOf("Register")) {
+ AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName(),
+ NextRecordedOperandNo));
+ PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++));
+ return;
+ }
+
+ if (LeafRec->isSubClassOf("ValueType"))
+ return AddMatcher(new CheckValueTypeMatcher(LeafRec->getName()));
+
+ if (LeafRec->isSubClassOf("CondCode"))
+ return AddMatcher(new CheckCondCodeMatcher(LeafRec->getName()));
+
+ if (LeafRec->isSubClassOf("ComplexPattern")) {
+ // We can't model ComplexPattern uses that don't have their name taken yet.
+ // The OPC_CheckComplexPattern operation implicitly records the results.
+ if (N->getName().empty()) {
+ errs() << "We expect complex pattern uses to have names: " << *N << "\n";
+ exit(1);
+ }
+
+ // Remember this ComplexPattern so that we can emit it after all the other
+ // structural matches are done.
+ MatchedComplexPatterns.push_back(std::make_pair(N, 0));
+ return;
+ }
+
+ errs() << "Unknown leaf kind: " << *N << "\n";
+ abort();
+}
+
+void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes) {
+ assert(!N->isLeaf() && "Not an operator?");
+ const SDNodeInfo &CInfo = CGP.getSDNodeInfo(N->getOperator());
+
+ // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
+ // a constant without a predicate fn that has more that one bit set, handle
+ // this as a special case. This is usually for targets that have special
+ // handling of certain large constants (e.g. alpha with it's 8/16/32-bit
+ // handling stuff). Using these instructions is often far more efficient
+ // than materializing the constant. Unfortunately, both the instcombiner
+ // and the dag combiner can often infer that bits are dead, and thus drop
+ // them from the mask in the dag. For example, it might turn 'AND X, 255'
+ // into 'AND X, 254' if it knows the low bit is set. Emit code that checks
+ // to handle this.
+ if ((N->getOperator()->getName() == "and" ||
+ N->getOperator()->getName() == "or") &&
+ N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty() &&
+ N->getPredicateFns().empty()) {
+ if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) {
+ if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
+ // If this is at the root of the pattern, we emit a redundant
+ // CheckOpcode so that the following checks get factored properly under
+ // a single opcode check.
+ if (N == Pattern.getSrcPattern())
+ AddMatcher(new CheckOpcodeMatcher(CInfo));
+
+ // Emit the CheckAndImm/CheckOrImm node.
+ if (N->getOperator()->getName() == "and")
+ AddMatcher(new CheckAndImmMatcher(II->getValue()));
+ else
+ AddMatcher(new CheckOrImmMatcher(II->getValue()));
+
+ // Match the LHS of the AND as appropriate.
+ AddMatcher(new MoveChildMatcher(0));
+ EmitMatchCode(N->getChild(0), NodeNoTypes->getChild(0));
+ AddMatcher(new MoveParentMatcher());
+ return;
+ }
+ }
+ }
+
+ // Check that the current opcode lines up.
+ AddMatcher(new CheckOpcodeMatcher(CInfo));
+
+ // If this node has memory references (i.e. is a load or store), tell the
+ // interpreter to capture them in the memref array.
+ if (N->NodeHasProperty(SDNPMemOperand, CGP))
+ AddMatcher(new RecordMemRefMatcher());
+
+ // If this node has a chain, then the chain is operand #0 is the SDNode, and
+ // the child numbers of the node are all offset by one.
+ unsigned OpNo = 0;
+ if (N->NodeHasProperty(SDNPHasChain, CGP)) {
+ // Record the node and remember it in our chained nodes list.
+ AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +
+ "' chained node",
+ NextRecordedOperandNo));
+ // Remember all of the input chains our pattern will match.
+ MatchedChainNodes.push_back(NextRecordedOperandNo++);
+
+ // Don't look at the input chain when matching the tree pattern to the
+ // SDNode.
+ OpNo = 1;
+
+ // If this node is not the root and the subtree underneath it produces a
+ // chain, then the result of matching the node is also produce a chain.
+ // Beyond that, this means that we're also folding (at least) the root node
+ // into the node that produce the chain (for example, matching
+ // "(add reg, (load ptr))" as a add_with_memory on X86). This is
+ // problematic, if the 'reg' node also uses the load (say, its chain).
+ // Graphically:
+ //
+ // [LD]
+ // ^ ^
+ // | \ DAG's like cheese.
+ // / |
+ // / [YY]
+ // | ^
+ // [XX]--/
+ //
+ // It would be invalid to fold XX and LD. In this case, folding the two
+ // nodes together would induce a cycle in the DAG, making it a 'cyclic DAG'
+ // To prevent this, we emit a dynamic check for legality before allowing
+ // this to be folded.
+ //
+ const TreePatternNode *Root = Pattern.getSrcPattern();
+ if (N != Root) { // Not the root of the pattern.
+ // If there is a node between the root and this node, then we definitely
+ // need to emit the check.
+ bool NeedCheck = !Root->hasChild(N);
+
+ // If it *is* an immediate child of the root, we can still need a check if
+ // the root SDNode has multiple inputs. For us, this means that it is an
+ // intrinsic, has multiple operands, or has other inputs like chain or
+ // flag).
+ if (!NeedCheck) {
+ const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Root->getOperator());
+ NeedCheck =
+ Root->getOperator() == CGP.get_intrinsic_void_sdnode() ||
+ Root->getOperator() == CGP.get_intrinsic_w_chain_sdnode() ||
+ Root->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||
+ PInfo.getNumOperands() > 1 ||
+ PInfo.hasProperty(SDNPHasChain) ||
+ PInfo.hasProperty(SDNPInFlag) ||
+ PInfo.hasProperty(SDNPOptInFlag);
+ }
+
+ if (NeedCheck)
+ AddMatcher(new CheckFoldableChainNodeMatcher());
+ }
+ }
+
+ // If this node has an output flag and isn't the root, remember it.
+ if (N->NodeHasProperty(SDNPOutFlag, CGP) &&
+ N != Pattern.getSrcPattern()) {
+ // TODO: This redundantly records nodes with both flags and chains.
+
+ // Record the node and remember it in our chained nodes list.
+ AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +
+ "' flag output node",
+ NextRecordedOperandNo));
+ // Remember all of the nodes with output flags our pattern will match.
+ MatchedFlagResultNodes.push_back(NextRecordedOperandNo++);
+ }
+
+ // If this node is known to have an input flag or if it *might* have an input
+ // flag, capture it as the flag input of the pattern.
+ if (N->NodeHasProperty(SDNPOptInFlag, CGP) ||
+ N->NodeHasProperty(SDNPInFlag, CGP))
+ AddMatcher(new CaptureFlagInputMatcher());
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
+ // Get the code suitable for matching this child. Move to the child, check
+ // it then move back to the parent.
+ AddMatcher(new MoveChildMatcher(OpNo));
+ EmitMatchCode(N->getChild(i), NodeNoTypes->getChild(i));
+ AddMatcher(new MoveParentMatcher());
+ }
+}
+
+
+void MatcherGen::EmitMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes) {
+ // If N and NodeNoTypes don't agree on a type, then this is a case where we
+ // need to do a type check. Emit the check, apply the tyep to NodeNoTypes and
+ // reinfer any correlated types.
+ SmallVector<unsigned, 2> ResultsToTypeCheck;
+
+ for (unsigned i = 0, e = NodeNoTypes->getNumTypes(); i != e; ++i) {
+ if (NodeNoTypes->getExtType(i) == N->getExtType(i)) continue;
+ NodeNoTypes->setType(i, N->getExtType(i));
+ InferPossibleTypes();
+ ResultsToTypeCheck.push_back(i);
+ }
+
+ // If this node has a name associated with it, capture it in VariableMap. If
+ // we already saw this in the pattern, emit code to verify dagness.
+ if (!N->getName().empty()) {
+ unsigned &VarMapEntry = VariableMap[N->getName()];
+ if (VarMapEntry == 0) {
+ // If it is a named node, we must emit a 'Record' opcode.
+ AddMatcher(new RecordMatcher("$" + N->getName(), NextRecordedOperandNo));
+ VarMapEntry = ++NextRecordedOperandNo;
+ } else {
+ // If we get here, this is a second reference to a specific name. Since
+ // we already have checked that the first reference is valid, we don't
+ // have to recursively match it, just check that it's the same as the
+ // previously named thing.
+ AddMatcher(new CheckSameMatcher(VarMapEntry-1));
+ return;
+ }
+ }
+
+ if (N->isLeaf())
+ EmitLeafMatchCode(N);
+ else
+ EmitOperatorMatchCode(N, NodeNoTypes);
+
+ // If there are node predicates for this node, generate their checks.
+ for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
+ AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i]));
+
+ for (unsigned i = 0, e = ResultsToTypeCheck.size(); i != e; ++i)
+ AddMatcher(new CheckTypeMatcher(N->getType(ResultsToTypeCheck[i]),
+ ResultsToTypeCheck[i]));
+}
+
+/// EmitMatcherCode - Generate the code that matches the predicate of this
+/// pattern for the specified Variant. If the variant is invalid this returns
+/// true and does not generate code, if it is valid, it returns false.
+bool MatcherGen::EmitMatcherCode(unsigned Variant) {
+ // If the root of the pattern is a ComplexPattern and if it is specified to
+ // match some number of root opcodes, these are considered to be our variants.
+ // Depending on which variant we're generating code for, emit the root opcode
+ // check.
+ if (const ComplexPattern *CP =
+ Pattern.getSrcPattern()->getComplexPatternInfo(CGP)) {
+ const std::vector<Record*> &OpNodes = CP->getRootNodes();
+ assert(!OpNodes.empty() &&"Complex Pattern must specify what it can match");
+ if (Variant >= OpNodes.size()) return true;
+
+ AddMatcher(new CheckOpcodeMatcher(CGP.getSDNodeInfo(OpNodes[Variant])));
+ } else {
+ if (Variant != 0) return true;
+ }
+
+ // Emit the matcher for the pattern structure and types.
+ EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes);
+
+ // If the pattern has a predicate on it (e.g. only enabled when a subtarget
+ // feature is around, do the check).
+ if (!Pattern.getPredicateCheck().empty())
+ AddMatcher(new CheckPatternPredicateMatcher(Pattern.getPredicateCheck()));
+
+ // Now that we've completed the structural type match, emit any ComplexPattern
+ // checks (e.g. addrmode matches). We emit this after the structural match
+ // because they are generally more expensive to evaluate and more difficult to
+ // factor.
+ for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) {
+ const TreePatternNode *N = MatchedComplexPatterns[i].first;
+
+ // Remember where the results of this match get stuck.
+ MatchedComplexPatterns[i].second = NextRecordedOperandNo;
+
+ // Get the slot we recorded the value in from the name on the node.
+ unsigned RecNodeEntry = VariableMap[N->getName()];
+ assert(!N->getName().empty() && RecNodeEntry &&
+ "Complex pattern should have a name and slot");
+ --RecNodeEntry; // Entries in VariableMap are biased.
+
+ const ComplexPattern &CP =
+ CGP.getComplexPattern(((DefInit*)N->getLeafValue())->getDef());
+
+ // Emit a CheckComplexPat operation, which does the match (aborting if it
+ // fails) and pushes the matched operands onto the recorded nodes list.
+ AddMatcher(new CheckComplexPatMatcher(CP, RecNodeEntry,
+ N->getName(), NextRecordedOperandNo));
+
+ // Record the right number of operands.
+ NextRecordedOperandNo += CP.getNumOperands();
+ if (CP.hasProperty(SDNPHasChain)) {
+ // If the complex pattern has a chain, then we need to keep track of the
+ // fact that we just recorded a chain input. The chain input will be
+ // matched as the last operand of the predicate if it was successful.
+ ++NextRecordedOperandNo; // Chained node operand.
+
+ // It is the last operand recorded.
+ assert(NextRecordedOperandNo > 1 &&
+ "Should have recorded input/result chains at least!");
+ MatchedChainNodes.push_back(NextRecordedOperandNo-1);
+ }
+
+ // TODO: Complex patterns can't have output flags, if they did, we'd want
+ // to record them.
+ }
+
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Node Result Generation
+//===----------------------------------------------------------------------===//
+
+void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps){
+ assert(!N->getName().empty() && "Operand not named!");
+
+ // A reference to a complex pattern gets all of the results of the complex
+ // pattern's match.
+ if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) {
+ unsigned SlotNo = 0;
+ for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i)
+ if (MatchedComplexPatterns[i].first->getName() == N->getName()) {
+ SlotNo = MatchedComplexPatterns[i].second;
+ break;
+ }
+ assert(SlotNo != 0 && "Didn't get a slot number assigned?");
+
+ // The first slot entry is the node itself, the subsequent entries are the
+ // matched values.
+ for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
+ ResultOps.push_back(SlotNo+i);
+ return;
+ }
+
+ unsigned SlotNo = getNamedArgumentSlot(N->getName());
+
+ // If this is an 'imm' or 'fpimm' node, make sure to convert it to the target
+ // version of the immediate so that it doesn't get selected due to some other
+ // node use.
+ if (!N->isLeaf()) {
+ StringRef OperatorName = N->getOperator()->getName();
+ if (OperatorName == "imm" || OperatorName == "fpimm") {
+ AddMatcher(new EmitConvertToTargetMatcher(SlotNo));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+ }
+
+ ResultOps.push_back(SlotNo);
+}
+
+void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps) {
+ assert(N->isLeaf() && "Must be a leaf");
+
+ if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
+ AddMatcher(new EmitIntegerMatcher(II->getValue(), N->getType(0)));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ // If this is an explicit register reference, handle it.
+ if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
+ if (DI->getDef()->isSubClassOf("Register")) {
+ AddMatcher(new EmitRegisterMatcher(DI->getDef(), N->getType(0)));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ if (DI->getDef()->getName() == "zero_reg") {
+ AddMatcher(new EmitRegisterMatcher(0, N->getType(0)));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ // Handle a reference to a register class. This is used
+ // in COPY_TO_SUBREG instructions.
+ if (DI->getDef()->isSubClassOf("RegisterClass")) {
+ std::string Value = getQualifiedName(DI->getDef()) + "RegClassID";
+ AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ // Handle a subregister index. This is used for INSERT_SUBREG etc.
+ if (DI->getDef()->isSubClassOf("SubRegIndex")) {
+ std::string Value = getQualifiedName(DI->getDef());
+ AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+ }
+
+ errs() << "unhandled leaf node: \n";
+ N->dump();
+}
+
+/// GetInstPatternNode - Get the pattern for an instruction.
+///
+const TreePatternNode *MatcherGen::
+GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) {
+ const TreePattern *InstPat = Inst.getPattern();
+
+ // FIXME2?: Assume actual pattern comes before "implicit".
+ TreePatternNode *InstPatNode;
+ if (InstPat)
+ InstPatNode = InstPat->getTree(0);
+ else if (/*isRoot*/ N == Pattern.getDstPattern())
+ InstPatNode = Pattern.getSrcPattern();
+ else
+ return 0;
+
+ if (InstPatNode && !InstPatNode->isLeaf() &&
+ InstPatNode->getOperator()->getName() == "set")
+ InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
+
+ return InstPatNode;
+}
+
+void MatcherGen::
+EmitResultInstructionAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &OutputOps) {
+ Record *Op = N->getOperator();
+ const CodeGenTarget &CGT = CGP.getTargetInfo();
+ CodeGenInstruction &II = CGT.getInstruction(Op);
+ const DAGInstruction &Inst = CGP.getInstruction(Op);
+
+ // If we can, get the pattern for the instruction we're generating. We derive
+ // a variety of information from this pattern, such as whether it has a chain.
+ //
+ // FIXME2: This is extremely dubious for several reasons, not the least of
+ // which it gives special status to instructions with patterns that Pat<>
+ // nodes can't duplicate.
+ const TreePatternNode *InstPatNode = GetInstPatternNode(Inst, N);
+
+ // NodeHasChain - Whether the instruction node we're creating takes chains.
+ bool NodeHasChain = InstPatNode &&
+ InstPatNode->TreeHasProperty(SDNPHasChain, CGP);
+
+ bool isRoot = N == Pattern.getDstPattern();
+
+ // TreeHasOutFlag - True if this tree has a flag.
+ bool TreeHasInFlag = false, TreeHasOutFlag = false;
+ if (isRoot) {
+ const TreePatternNode *SrcPat = Pattern.getSrcPattern();
+ TreeHasInFlag = SrcPat->TreeHasProperty(SDNPOptInFlag, CGP) ||
+ SrcPat->TreeHasProperty(SDNPInFlag, CGP);
+
+ // FIXME2: this is checking the entire pattern, not just the node in
+ // question, doing this just for the root seems like a total hack.
+ TreeHasOutFlag = SrcPat->TreeHasProperty(SDNPOutFlag, CGP);
+ }
+
+ // NumResults - This is the number of results produced by the instruction in
+ // the "outs" list.
+ unsigned NumResults = Inst.getNumResults();
+
+ // Loop over all of the operands of the instruction pattern, emitting code
+ // to fill them all in. The node 'N' usually has number children equal to
+ // the number of input operands of the instruction. However, in cases
+ // where there are predicate operands for an instruction, we need to fill
+ // in the 'execute always' values. Match up the node operands to the
+ // instruction operands to do this.
+ SmallVector<unsigned, 8> InstOps;
+ for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.OperandList.size();
+ InstOpNo != e; ++InstOpNo) {
+
+ // Determine what to emit for this operand.
+ Record *OperandNode = II.OperandList[InstOpNo].Rec;
+ if ((OperandNode->isSubClassOf("PredicateOperand") ||
+ OperandNode->isSubClassOf("OptionalDefOperand")) &&
+ !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
+ // This is a predicate or optional def operand; emit the
+ // 'default ops' operands.
+ const DAGDefaultOperand &DefaultOp
+ = CGP.getDefaultOperand(OperandNode);
+ for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i)
+ EmitResultOperand(DefaultOp.DefaultOps[i], InstOps);
+ continue;
+ }
+
+ const TreePatternNode *Child = N->getChild(ChildNo);
+
+ // Otherwise this is a normal operand or a predicate operand without
+ // 'execute always'; emit it.
+ unsigned BeforeAddingNumOps = InstOps.size();
+ EmitResultOperand(Child, InstOps);
+ assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands");
+
+ // If the operand is an instruction and it produced multiple results, just
+ // take the first one.
+ if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction"))
+ InstOps.resize(BeforeAddingNumOps+1);
+
+ ++ChildNo;
+ }
+
+ // If this node has an input flag or explicitly specified input physregs, we
+ // need to add chained and flagged copyfromreg nodes and materialize the flag
+ // input.
+ if (isRoot && !PhysRegInputs.empty()) {
+ // Emit all of the CopyToReg nodes for the input physical registers. These
+ // occur in patterns like (mul:i8 AL:i8, GR8:i8:$src).
+ for (unsigned i = 0, e = PhysRegInputs.size(); i != e; ++i)
+ AddMatcher(new EmitCopyToRegMatcher(PhysRegInputs[i].second,
+ PhysRegInputs[i].first));
+ // Even if the node has no other flag inputs, the resultant node must be
+ // flagged to the CopyFromReg nodes we just generated.
+ TreeHasInFlag = true;
+ }
+
+ // Result order: node results, chain, flags
+
+ // Determine the result types.
+ SmallVector<MVT::SimpleValueType, 4> ResultVTs;
+ for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i)
+ ResultVTs.push_back(N->getType(i));
+
+ // If this is the root instruction of a pattern that has physical registers in
+ // its result pattern, add output VTs for them. For example, X86 has:
+ // (set AL, (mul ...))
+ // This also handles implicit results like:
+ // (implicit EFLAGS)
+ if (isRoot && !Pattern.getDstRegs().empty()) {
+ // If the root came from an implicit def in the instruction handling stuff,
+ // don't re-add it.
+ Record *HandledReg = 0;
+ if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other)
+ HandledReg = II.ImplicitDefs[0];
+
+ for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) {
+ Record *Reg = Pattern.getDstRegs()[i];
+ if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
+ ResultVTs.push_back(getRegisterValueType(Reg, CGT));
+ }
+ }
+
+ // If this is the root of the pattern and the pattern we're matching includes
+ // a node that is variadic, mark the generated node as variadic so that it
+ // gets the excess operands from the input DAG.
+ int NumFixedArityOperands = -1;
+ if (isRoot &&
+ (Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP)))
+ NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren();
+
+ // If this is the root node and any of the nodes matched nodes in the input
+ // pattern have MemRefs in them, have the interpreter collect them and plop
+ // them onto this node.
+ //
+ // FIXME3: This is actively incorrect for result patterns where the root of
+ // the pattern is not the memory reference and is also incorrect when the
+ // result pattern has multiple memory-referencing instructions. For example,
+ // in the X86 backend, this pattern causes the memrefs to get attached to the
+ // CVTSS2SDrr instead of the MOVSSrm:
+ //
+ // def : Pat<(extloadf32 addr:$src),
+ // (CVTSS2SDrr (MOVSSrm addr:$src))>;
+ //
+ bool NodeHasMemRefs =
+ isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP);
+
+ assert((!ResultVTs.empty() || TreeHasOutFlag || NodeHasChain) &&
+ "Node has no result");
+
+ AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(),
+ ResultVTs.data(), ResultVTs.size(),
+ InstOps.data(), InstOps.size(),
+ NodeHasChain, TreeHasInFlag, TreeHasOutFlag,
+ NodeHasMemRefs, NumFixedArityOperands,
+ NextRecordedOperandNo));
+
+ // The non-chain and non-flag results of the newly emitted node get recorded.
+ for (unsigned i = 0, e = ResultVTs.size(); i != e; ++i) {
+ if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Flag) break;
+ OutputOps.push_back(NextRecordedOperandNo++);
+ }
+}
+
+void MatcherGen::
+EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps) {
+ assert(N->getOperator()->isSubClassOf("SDNodeXForm") && "Not SDNodeXForm?");
+
+ // Emit the operand.
+ SmallVector<unsigned, 8> InputOps;
+
+ // FIXME2: Could easily generalize this to support multiple inputs and outputs
+ // to the SDNodeXForm. For now we just support one input and one output like
+ // the old instruction selector.
+ assert(N->getNumChildren() == 1);
+ EmitResultOperand(N->getChild(0), InputOps);
+
+ // The input currently must have produced exactly one result.
+ assert(InputOps.size() == 1 && "Unexpected input to SDNodeXForm");
+
+ AddMatcher(new EmitNodeXFormMatcher(InputOps[0], N->getOperator()));
+ ResultOps.push_back(NextRecordedOperandNo++);
+}
+
+void MatcherGen::EmitResultOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps) {
+ // This is something selected from the pattern we matched.
+ if (!N->getName().empty())
+ return EmitResultOfNamedOperand(N, ResultOps);
+
+ if (N->isLeaf())
+ return EmitResultLeafAsOperand(N, ResultOps);
+
+ Record *OpRec = N->getOperator();
+ if (OpRec->isSubClassOf("Instruction"))
+ return EmitResultInstructionAsOperand(N, ResultOps);
+ if (OpRec->isSubClassOf("SDNodeXForm"))
+ return EmitResultSDNodeXFormAsOperand(N, ResultOps);
+ errs() << "Unknown result node to emit code for: " << *N << '\n';
+ throw std::string("Unknown node in result pattern!");
+}
+
+void MatcherGen::EmitResultCode() {
+ // Patterns that match nodes with (potentially multiple) chain inputs have to
+ // merge them together into a token factor. This informs the generated code
+ // what all the chained nodes are.
+ if (!MatchedChainNodes.empty())
+ AddMatcher(new EmitMergeInputChainsMatcher
+ (MatchedChainNodes.data(), MatchedChainNodes.size()));
+
+ // Codegen the root of the result pattern, capturing the resulting values.
+ SmallVector<unsigned, 8> Ops;
+ EmitResultOperand(Pattern.getDstPattern(), Ops);
+
+ // At this point, we have however many values the result pattern produces.
+ // However, the input pattern might not need all of these. If there are
+ // excess values at the end (such as implicit defs of condition codes etc)
+ // just lop them off. This doesn't need to worry about flags or chains, just
+ // explicit results.
+ //
+ unsigned NumSrcResults = Pattern.getSrcPattern()->getNumTypes();
+
+ // If the pattern also has (implicit) results, count them as well.
+ if (!Pattern.getDstRegs().empty()) {
+ // If the root came from an implicit def in the instruction handling stuff,
+ // don't re-add it.
+ Record *HandledReg = 0;
+ const TreePatternNode *DstPat = Pattern.getDstPattern();
+ if (!DstPat->isLeaf() &&DstPat->getOperator()->isSubClassOf("Instruction")){
+ const CodeGenTarget &CGT = CGP.getTargetInfo();
+ CodeGenInstruction &II = CGT.getInstruction(DstPat->getOperator());
+
+ if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other)
+ HandledReg = II.ImplicitDefs[0];
+ }
+
+ for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) {
+ Record *Reg = Pattern.getDstRegs()[i];
+ if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
+ ++NumSrcResults;
+ }
+ }
+
+ assert(Ops.size() >= NumSrcResults && "Didn't provide enough results");
+ Ops.resize(NumSrcResults);
+
+ // If the matched pattern covers nodes which define a flag result, emit a node
+ // that tells the matcher about them so that it can update their results.
+ if (!MatchedFlagResultNodes.empty())
+ AddMatcher(new MarkFlagResultsMatcher(MatchedFlagResultNodes.data(),
+ MatchedFlagResultNodes.size()));
+
+ AddMatcher(new CompleteMatchMatcher(Ops.data(), Ops.size(), Pattern));
+}
+
+
+/// ConvertPatternToMatcher - Create the matcher for the specified pattern with
+/// the specified variant. If the variant number is invalid, this returns null.
+Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern,
+ unsigned Variant,
+ const CodeGenDAGPatterns &CGP) {
+ MatcherGen Gen(Pattern, CGP);
+
+ // Generate the code for the matcher.
+ if (Gen.EmitMatcherCode(Variant))
+ return 0;
+
+ // FIXME2: Kill extra MoveParent commands at the end of the matcher sequence.
+ // FIXME2: Split result code out to another table, and make the matcher end
+ // with an "Emit <index>" command. This allows result generation stuff to be
+ // shared and factored?
+
+ // If the match succeeds, then we generate Pattern.
+ Gen.EmitResultCode();
+
+ // Unconditional match.
+ return Gen.GetMatcher();
+}
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
new file mode 100644
index 0000000..c73bdb9
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -0,0 +1,514 @@
+//===- DAGISelMatcherOpt.cpp - Optimize a DAG Matcher ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the DAG Matcher optimizer.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "isel-opt"
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+using namespace llvm;
+
+/// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record'
+/// into single compound nodes like RecordChild.
+static void ContractNodes(OwningPtr<Matcher> &MatcherPtr,
+ const CodeGenDAGPatterns &CGP) {
+ // If we reached the end of the chain, we're done.
+ Matcher *N = MatcherPtr.get();
+ if (N == 0) return;
+
+ // If we have a scope node, walk down all of the children.
+ if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) {
+ for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
+ OwningPtr<Matcher> Child(Scope->takeChild(i));
+ ContractNodes(Child, CGP);
+ Scope->resetChild(i, Child.take());
+ }
+ return;
+ }
+
+ // If we found a movechild node with a node that comes in a 'foochild' form,
+ // transform it.
+ if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) {
+ Matcher *New = 0;
+ if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext()))
+ if (MC->getChildNo() < 8) // Only have RecordChild0...7
+ New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(),
+ RM->getResultNo());
+
+ if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext()))
+ if (MC->getChildNo() < 8 && // Only have CheckChildType0...7
+ CT->getResNo() == 0) // CheckChildType checks res #0
+ New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType());
+
+ if (New) {
+ // Insert the new node.
+ New->setNext(MatcherPtr.take());
+ MatcherPtr.reset(New);
+ // Remove the old one.
+ MC->setNext(MC->getNext()->takeNext());
+ return ContractNodes(MatcherPtr, CGP);
+ }
+ }
+
+ // Zap movechild -> moveparent.
+ if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N))
+ if (MoveParentMatcher *MP =
+ dyn_cast<MoveParentMatcher>(MC->getNext())) {
+ MatcherPtr.reset(MP->takeNext());
+ return ContractNodes(MatcherPtr, CGP);
+ }
+
+ // Turn EmitNode->MarkFlagResults->CompleteMatch into
+ // MarkFlagResults->EmitNode->CompleteMatch when we can to encourage
+ // MorphNodeTo formation. This is safe because MarkFlagResults never refers
+ // to the root of the pattern.
+ if (isa<EmitNodeMatcher>(N) && isa<MarkFlagResultsMatcher>(N->getNext()) &&
+ isa<CompleteMatchMatcher>(N->getNext()->getNext())) {
+ // Unlink the two nodes from the list.
+ Matcher *EmitNode = MatcherPtr.take();
+ Matcher *MFR = EmitNode->takeNext();
+ Matcher *Tail = MFR->takeNext();
+
+ // Relink them.
+ MatcherPtr.reset(MFR);
+ MFR->setNext(EmitNode);
+ EmitNode->setNext(Tail);
+ return ContractNodes(MatcherPtr, CGP);
+ }
+
+ // Turn EmitNode->CompleteMatch into MorphNodeTo if we can.
+ if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N))
+ if (CompleteMatchMatcher *CM =
+ dyn_cast<CompleteMatchMatcher>(EN->getNext())) {
+ // We can only use MorphNodeTo if the result values match up.
+ unsigned RootResultFirst = EN->getFirstResultSlot();
+ bool ResultsMatch = true;
+ for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
+ if (CM->getResult(i) != RootResultFirst+i)
+ ResultsMatch = false;
+
+ // If the selected node defines a subset of the flag/chain results, we
+ // can't use MorphNodeTo. For example, we can't use MorphNodeTo if the
+ // matched pattern has a chain but the root node doesn't.
+ const PatternToMatch &Pattern = CM->getPattern();
+
+ if (!EN->hasChain() &&
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPHasChain, CGP))
+ ResultsMatch = false;
+
+ // If the matched node has a flag and the output root doesn't, we can't
+ // use MorphNodeTo.
+ //
+ // NOTE: Strictly speaking, we don't have to check for the flag here
+ // because the code in the pattern generator doesn't handle it right. We
+ // do it anyway for thoroughness.
+ if (!EN->hasOutFlag() &&
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPOutFlag, CGP))
+ ResultsMatch = false;
+
+
+ // If the root result node defines more results than the source root node
+ // *and* has a chain or flag input, then we can't match it because it
+ // would end up replacing the extra result with the chain/flag.
+#if 0
+ if ((EN->hasFlag() || EN->hasChain()) &&
+ EN->getNumNonChainFlagVTs() > ... need to get no results reliably ...)
+ ResultMatch = false;
+#endif
+
+ if (ResultsMatch) {
+ const SmallVectorImpl<MVT::SimpleValueType> &VTs = EN->getVTList();
+ const SmallVectorImpl<unsigned> &Operands = EN->getOperandList();
+ MatcherPtr.reset(new MorphNodeToMatcher(EN->getOpcodeName(),
+ VTs.data(), VTs.size(),
+ Operands.data(),Operands.size(),
+ EN->hasChain(), EN->hasInFlag(),
+ EN->hasOutFlag(),
+ EN->hasMemRefs(),
+ EN->getNumFixedArityOperands(),
+ Pattern));
+ return;
+ }
+
+ // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode
+ // variants.
+ }
+
+ ContractNodes(N->getNextPtr(), CGP);
+
+
+ // If we have a CheckType/CheckChildType/Record node followed by a
+ // CheckOpcode, invert the two nodes. We prefer to do structural checks
+ // before type checks, as this opens opportunities for factoring on targets
+ // like X86 where many operations are valid on multiple types.
+ if ((isa<CheckTypeMatcher>(N) || isa<CheckChildTypeMatcher>(N) ||
+ isa<RecordMatcher>(N)) &&
+ isa<CheckOpcodeMatcher>(N->getNext())) {
+ // Unlink the two nodes from the list.
+ Matcher *CheckType = MatcherPtr.take();
+ Matcher *CheckOpcode = CheckType->takeNext();
+ Matcher *Tail = CheckOpcode->takeNext();
+
+ // Relink them.
+ MatcherPtr.reset(CheckOpcode);
+ CheckOpcode->setNext(CheckType);
+ CheckType->setNext(Tail);
+ return ContractNodes(MatcherPtr, CGP);
+ }
+}
+
+/// SinkPatternPredicates - Pattern predicates can be checked at any level of
+/// the matching tree. The generator dumps them at the top level of the pattern
+/// though, which prevents factoring from being able to see past them. This
+/// optimization sinks them as far down into the pattern as possible.
+///
+/// Conceptually, we'd like to sink these predicates all the way to the last
+/// matcher predicate in the series. However, it turns out that some
+/// ComplexPatterns have side effects on the graph, so we really don't want to
+/// run a the complex pattern if the pattern predicate will fail. For this
+/// reason, we refuse to sink the pattern predicate past a ComplexPattern.
+///
+static void SinkPatternPredicates(OwningPtr<Matcher> &MatcherPtr) {
+ // Recursively scan for a PatternPredicate.
+ // If we reached the end of the chain, we're done.
+ Matcher *N = MatcherPtr.get();
+ if (N == 0) return;
+
+ // Walk down all members of a scope node.
+ if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) {
+ for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
+ OwningPtr<Matcher> Child(Scope->takeChild(i));
+ SinkPatternPredicates(Child);
+ Scope->resetChild(i, Child.take());
+ }
+ return;
+ }
+
+ // If this node isn't a CheckPatternPredicateMatcher we keep scanning until
+ // we find one.
+ CheckPatternPredicateMatcher *CPPM =dyn_cast<CheckPatternPredicateMatcher>(N);
+ if (CPPM == 0)
+ return SinkPatternPredicates(N->getNextPtr());
+
+ // Ok, we found one, lets try to sink it. Check if we can sink it past the
+ // next node in the chain. If not, we won't be able to change anything and
+ // might as well bail.
+ if (!CPPM->getNext()->isSafeToReorderWithPatternPredicate())
+ return;
+
+ // Okay, we know we can sink it past at least one node. Unlink it from the
+ // chain and scan for the new insertion point.
+ MatcherPtr.take(); // Don't delete CPPM.
+ MatcherPtr.reset(CPPM->takeNext());
+
+ N = MatcherPtr.get();
+ while (N->getNext()->isSafeToReorderWithPatternPredicate())
+ N = N->getNext();
+
+ // At this point, we want to insert CPPM after N.
+ CPPM->setNext(N->takeNext());
+ N->setNext(CPPM);
+}
+
+/// FindNodeWithKind - Scan a series of matchers looking for a matcher with a
+/// specified kind. Return null if we didn't find one otherwise return the
+/// matcher.
+static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) {
+ for (; M; M = M->getNext())
+ if (M->getKind() == Kind)
+ return M;
+ return 0;
+}
+
+
+/// FactorNodes - Turn matches like this:
+/// Scope
+/// OPC_CheckType i32
+/// ABC
+/// OPC_CheckType i32
+/// XYZ
+/// into:
+/// OPC_CheckType i32
+/// Scope
+/// ABC
+/// XYZ
+///
+static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) {
+ // If we reached the end of the chain, we're done.
+ Matcher *N = MatcherPtr.get();
+ if (N == 0) return;
+
+ // If this is not a push node, just scan for one.
+ ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N);
+ if (Scope == 0)
+ return FactorNodes(N->getNextPtr());
+
+ // Okay, pull together the children of the scope node into a vector so we can
+ // inspect it more easily. While we're at it, bucket them up by the hash
+ // code of their first predicate.
+ SmallVector<Matcher*, 32> OptionsToMatch;
+
+ for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
+ // Factor the subexpression.
+ OwningPtr<Matcher> Child(Scope->takeChild(i));
+ FactorNodes(Child);
+
+ if (Matcher *N = Child.take())
+ OptionsToMatch.push_back(N);
+ }
+
+ SmallVector<Matcher*, 32> NewOptionsToMatch;
+
+ // Loop over options to match, merging neighboring patterns with identical
+ // starting nodes into a shared matcher.
+ for (unsigned OptionIdx = 0, e = OptionsToMatch.size(); OptionIdx != e;) {
+ // Find the set of matchers that start with this node.
+ Matcher *Optn = OptionsToMatch[OptionIdx++];
+
+ if (OptionIdx == e) {
+ NewOptionsToMatch.push_back(Optn);
+ continue;
+ }
+
+ // See if the next option starts with the same matcher. If the two
+ // neighbors *do* start with the same matcher, we can factor the matcher out
+ // of at least these two patterns. See what the maximal set we can merge
+ // together is.
+ SmallVector<Matcher*, 8> EqualMatchers;
+ EqualMatchers.push_back(Optn);
+
+ // Factor all of the known-equal matchers after this one into the same
+ // group.
+ while (OptionIdx != e && OptionsToMatch[OptionIdx]->isEqual(Optn))
+ EqualMatchers.push_back(OptionsToMatch[OptionIdx++]);
+
+ // If we found a non-equal matcher, see if it is contradictory with the
+ // current node. If so, we know that the ordering relation between the
+ // current sets of nodes and this node don't matter. Look past it to see if
+ // we can merge anything else into this matching group.
+ unsigned Scan = OptionIdx;
+ while (1) {
+ // If we ran out of stuff to scan, we're done.
+ if (Scan == e) break;
+
+ Matcher *ScanMatcher = OptionsToMatch[Scan];
+
+ // If we found an entry that matches out matcher, merge it into the set to
+ // handle.
+ if (Optn->isEqual(ScanMatcher)) {
+ // If is equal after all, add the option to EqualMatchers and remove it
+ // from OptionsToMatch.
+ EqualMatchers.push_back(ScanMatcher);
+ OptionsToMatch.erase(OptionsToMatch.begin()+Scan);
+ --e;
+ continue;
+ }
+
+ // If the option we're checking for contradicts the start of the list,
+ // skip over it.
+ if (Optn->isContradictory(ScanMatcher)) {
+ ++Scan;
+ continue;
+ }
+
+ // If we're scanning for a simple node, see if it occurs later in the
+ // sequence. If so, and if we can move it up, it might be contradictory
+ // or the same as what we're looking for. If so, reorder it.
+ if (Optn->isSimplePredicateOrRecordNode()) {
+ Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind());
+ if (M2 != 0 && M2 != ScanMatcher &&
+ M2->canMoveBefore(ScanMatcher) &&
+ (M2->isEqual(Optn) || M2->isContradictory(Optn))) {
+ Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2);
+ M2->setNext(MatcherWithoutM2);
+ OptionsToMatch[Scan] = M2;
+ continue;
+ }
+ }
+
+ // Otherwise, we don't know how to handle this entry, we have to bail.
+ break;
+ }
+
+ if (Scan != e &&
+ // Don't print it's obvious nothing extra could be merged anyway.
+ Scan+1 != e) {
+ DEBUG(errs() << "Couldn't merge this:\n";
+ Optn->print(errs(), 4);
+ errs() << "into this:\n";
+ OptionsToMatch[Scan]->print(errs(), 4);
+ if (Scan+1 != e)
+ OptionsToMatch[Scan+1]->printOne(errs());
+ if (Scan+2 < e)
+ OptionsToMatch[Scan+2]->printOne(errs());
+ errs() << "\n");
+ }
+
+ // If we only found one option starting with this matcher, no factoring is
+ // possible.
+ if (EqualMatchers.size() == 1) {
+ NewOptionsToMatch.push_back(EqualMatchers[0]);
+ continue;
+ }
+
+ // Factor these checks by pulling the first node off each entry and
+ // discarding it. Take the first one off the first entry to reuse.
+ Matcher *Shared = Optn;
+ Optn = Optn->takeNext();
+ EqualMatchers[0] = Optn;
+
+ // Remove and delete the first node from the other matchers we're factoring.
+ for (unsigned i = 1, e = EqualMatchers.size(); i != e; ++i) {
+ Matcher *Tmp = EqualMatchers[i]->takeNext();
+ delete EqualMatchers[i];
+ EqualMatchers[i] = Tmp;
+ }
+
+ Shared->setNext(new ScopeMatcher(&EqualMatchers[0], EqualMatchers.size()));
+
+ // Recursively factor the newly created node.
+ FactorNodes(Shared->getNextPtr());
+
+ NewOptionsToMatch.push_back(Shared);
+ }
+
+ // If we're down to a single pattern to match, then we don't need this scope
+ // anymore.
+ if (NewOptionsToMatch.size() == 1) {
+ MatcherPtr.reset(NewOptionsToMatch[0]);
+ return;
+ }
+
+ if (NewOptionsToMatch.empty()) {
+ MatcherPtr.reset(0);
+ return;
+ }
+
+ // If our factoring failed (didn't achieve anything) see if we can simplify in
+ // other ways.
+
+ // Check to see if all of the leading entries are now opcode checks. If so,
+ // we can convert this Scope to be a OpcodeSwitch instead.
+ bool AllOpcodeChecks = true, AllTypeChecks = true;
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
+ // Check to see if this breaks a series of CheckOpcodeMatchers.
+ if (AllOpcodeChecks &&
+ !isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) {
+#if 0
+ if (i > 3) {
+ errs() << "FAILING OPC #" << i << "\n";
+ NewOptionsToMatch[i]->dump();
+ }
+#endif
+ AllOpcodeChecks = false;
+ }
+
+ // Check to see if this breaks a series of CheckTypeMatcher's.
+ if (AllTypeChecks) {
+ CheckTypeMatcher *CTM =
+ cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
+ Matcher::CheckType));
+ if (CTM == 0 ||
+ // iPTR checks could alias any other case without us knowing, don't
+ // bother with them.
+ CTM->getType() == MVT::iPTR ||
+ // SwitchType only works for result #0.
+ CTM->getResNo() != 0 ||
+ // If the CheckType isn't at the start of the list, see if we can move
+ // it there.
+ !CTM->canMoveBefore(NewOptionsToMatch[i])) {
+#if 0
+ if (i > 3 && AllTypeChecks) {
+ errs() << "FAILING TYPE #" << i << "\n";
+ NewOptionsToMatch[i]->dump();
+ }
+#endif
+ AllTypeChecks = false;
+ }
+ }
+ }
+
+ // If all the options are CheckOpcode's, we can form the SwitchOpcode, woot.
+ if (AllOpcodeChecks) {
+ StringSet<> Opcodes;
+ SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
+ CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]);
+ assert(Opcodes.insert(COM->getOpcode().getEnumName()) &&
+ "Duplicate opcodes not factored?");
+ Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext()));
+ }
+
+ MatcherPtr.reset(new SwitchOpcodeMatcher(&Cases[0], Cases.size()));
+ return;
+ }
+
+ // If all the options are CheckType's, we can form the SwitchType, woot.
+ if (AllTypeChecks) {
+ DenseMap<unsigned, unsigned> TypeEntry;
+ SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
+ CheckTypeMatcher *CTM =
+ cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
+ Matcher::CheckType));
+ Matcher *MatcherWithoutCTM = NewOptionsToMatch[i]->unlinkNode(CTM);
+ MVT::SimpleValueType CTMTy = CTM->getType();
+ delete CTM;
+
+ unsigned &Entry = TypeEntry[CTMTy];
+ if (Entry != 0) {
+ // If we have unfactored duplicate types, then we should factor them.
+ Matcher *PrevMatcher = Cases[Entry-1].second;
+ if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) {
+ SM->setNumChildren(SM->getNumChildren()+1);
+ SM->resetChild(SM->getNumChildren()-1, MatcherWithoutCTM);
+ continue;
+ }
+
+ Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM };
+ Cases[Entry-1].second = new ScopeMatcher(Entries, 2);
+ continue;
+ }
+
+ Entry = Cases.size()+1;
+ Cases.push_back(std::make_pair(CTMTy, MatcherWithoutCTM));
+ }
+
+ if (Cases.size() != 1) {
+ MatcherPtr.reset(new SwitchTypeMatcher(&Cases[0], Cases.size()));
+ } else {
+ // If we factored and ended up with one case, create it now.
+ MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first, 0));
+ MatcherPtr->setNext(Cases[0].second);
+ }
+ return;
+ }
+
+
+ // Reassemble the Scope node with the adjusted children.
+ Scope->setNumChildren(NewOptionsToMatch.size());
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i)
+ Scope->resetChild(i, NewOptionsToMatch[i]);
+}
+
+Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher,
+ const CodeGenDAGPatterns &CGP) {
+ OwningPtr<Matcher> MatcherPtr(TheMatcher);
+ ContractNodes(MatcherPtr, CGP);
+ SinkPatternPredicates(MatcherPtr);
+ FactorNodes(MatcherPtr);
+ return MatcherPtr.take();
+}
diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
new file mode 100644
index 0000000..3284366
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
@@ -0,0 +1,137 @@
+//===- DisassemblerEmitter.cpp - Generate a disassembler ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DisassemblerEmitter.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "X86DisassemblerTables.h"
+#include "X86RecognizableInstr.h"
+#include "ARMDecoderEmitter.h"
+
+using namespace llvm;
+using namespace llvm::X86Disassembler;
+
+/// DisassemblerEmitter - Contains disassembler table emitters for various
+/// architectures.
+
+/// X86 Disassembler Emitter
+///
+/// *** IF YOU'RE HERE TO RESOLVE A "Primary decode conflict", LOOK DOWN NEAR
+/// THE END OF THIS COMMENT!
+///
+/// The X86 disassembler emitter is part of the X86 Disassembler, which is
+/// documented in lib/Target/X86/X86Disassembler.h.
+///
+/// The emitter produces the tables that the disassembler uses to translate
+/// instructions. The emitter generates the following tables:
+///
+/// - One table (CONTEXTS_SYM) that contains a mapping of attribute masks to
+/// instruction contexts. Although for each attribute there are cases where
+/// that attribute determines decoding, in the majority of cases decoding is
+/// the same whether or not an attribute is present. For example, a 64-bit
+/// instruction with an OPSIZE prefix and an XS prefix decodes the same way in
+/// all cases as a 64-bit instruction with only OPSIZE set. (The XS prefix
+/// may have effects on its execution, but does not change the instruction
+/// returned.) This allows considerable space savings in other tables.
+/// - Four tables (ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, and
+/// THREEBYTE3A_SYM) contain the hierarchy that the decoder traverses while
+/// decoding an instruction. At the lowest level of this hierarchy are
+/// instruction UIDs, 16-bit integers that can be used to uniquely identify
+/// the instruction and correspond exactly to its position in the list of
+/// CodeGenInstructions for the target.
+/// - One table (INSTRUCTIONS_SYM) contains information about the operands of
+/// each instruction and how to decode them.
+///
+/// During table generation, there may be conflicts between instructions that
+/// occupy the same space in the decode tables. These conflicts are resolved as
+/// follows in setTableFields() (X86DisassemblerTables.cpp)
+///
+/// - If the current context is the native context for one of the instructions
+/// (that is, the attributes specified for it in the LLVM tables specify
+/// precisely the current context), then it has priority.
+/// - If the current context isn't native for either of the instructions, then
+/// the higher-priority context wins (that is, the one that is more specific).
+/// That hierarchy is determined by outranks() (X86DisassemblerTables.cpp)
+/// - If the current context is native for both instructions, then the table
+/// emitter reports a conflict and dies.
+///
+/// *** RESOLUTION FOR "Primary decode conflict"S
+///
+/// If two instructions collide, typically the solution is (in order of
+/// likelihood):
+///
+/// (1) to filter out one of the instructions by editing filter()
+/// (X86RecognizableInstr.cpp). This is the most common resolution, but
+/// check the Intel manuals first to make sure that (2) and (3) are not the
+/// problem.
+/// (2) to fix the tables (X86.td and its subsidiaries) so the opcodes are
+/// accurate. Sometimes they are not.
+/// (3) to fix the tables to reflect the actual context (for example, required
+/// prefixes), and possibly to add a new context by editing
+/// lib/Target/X86/X86DisassemblerDecoderCommon.h. This is unlikely to be
+/// the cause.
+///
+/// DisassemblerEmitter.cpp contains the implementation for the emitter,
+/// which simply pulls out instructions from the CodeGenTarget and pushes them
+/// into X86DisassemblerTables.
+/// X86DisassemblerTables.h contains the interface for the instruction tables,
+/// which manage and emit the structures discussed above.
+/// X86DisassemblerTables.cpp contains the implementation for the instruction
+/// tables.
+/// X86ModRMFilters.h contains filters that can be used to determine which
+/// ModR/M values are valid for a particular instruction. These are used to
+/// populate ModRMDecisions.
+/// X86RecognizableInstr.h contains the interface for a single instruction,
+/// which knows how to translate itself from a CodeGenInstruction and provide
+/// the information necessary for integration into the tables.
+/// X86RecognizableInstr.cpp contains the implementation for a single
+/// instruction.
+
+void DisassemblerEmitter::run(raw_ostream &OS) {
+ CodeGenTarget Target;
+
+ OS << "/*===- TableGen'erated file "
+ << "---------------------------------------*- C -*-===*\n"
+ << " *\n"
+ << " * " << Target.getName() << " Disassembler\n"
+ << " *\n"
+ << " * Automatically generated file, do not edit!\n"
+ << " *\n"
+ << " *===---------------------------------------------------------------"
+ << "-------===*/\n";
+
+ // X86 uses a custom disassembler.
+ if (Target.getName() == "X86") {
+ DisassemblerTables Tables;
+
+ const std::vector<const CodeGenInstruction*> &numberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i)
+ RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i);
+
+ // FIXME: As long as we are using exceptions, might as well drop this to the
+ // actual conflict site.
+ if (Tables.hasConflicts())
+ throw TGError(Target.getTargetRecord()->getLoc(),
+ "Primary decode conflict");
+
+ Tables.emit(OS);
+ return;
+ }
+
+ // Fixed-instruction-length targets use a common disassembler.
+ if (Target.getName() == "ARM") {
+ ARMDecoderEmitter(Records).run(OS);
+ return;
+ }
+
+ throw TGError(Target.getTargetRecord()->getLoc(),
+ "Unable to generate disassembler for this target");
+}
diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.h b/contrib/llvm/utils/TableGen/DisassemblerEmitter.h
new file mode 100644
index 0000000..7229d81
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.h
@@ -0,0 +1,28 @@
+//===- DisassemblerEmitter.h - Disassembler Generator -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DISASSEMBLEREMITTER_H
+#define DISASSEMBLEREMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+
+ class DisassemblerEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ public:
+ DisassemblerEmitter(RecordKeeper &R) : Records(R) {}
+
+ /// run - Output the disassembler.
+ void run(raw_ostream &o);
+ };
+
+} // end llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/EDEmitter.cpp b/contrib/llvm/utils/TableGen/EDEmitter.cpp
new file mode 100644
index 0000000..525fffb
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/EDEmitter.cpp
@@ -0,0 +1,864 @@
+//===- EDEmitter.cpp - Generate instruction descriptions for ED -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of each
+// instruction in a format that the enhanced disassembler can use to tokenize
+// and parse instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EDEmitter.h"
+
+#include "AsmWriterInst.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+
+#include "llvm/MC/EDInstInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+///////////////////////////////////////////////////////////
+// Support classes for emitting nested C data structures //
+///////////////////////////////////////////////////////////
+
+namespace {
+
+ class EnumEmitter {
+ private:
+ std::string Name;
+ std::vector<std::string> Entries;
+ public:
+ EnumEmitter(const char *N) : Name(N) {
+ }
+ int addEntry(const char *e) {
+ Entries.push_back(std::string(e));
+ return Entries.size() - 1;
+ }
+ void emit(raw_ostream &o, unsigned int &i) {
+ o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
+ i += 2;
+
+ unsigned int index = 0;
+ unsigned int numEntries = Entries.size();
+ for (index = 0; index < numEntries; ++index) {
+ o.indent(i) << Entries[index];
+ if (index < (numEntries - 1))
+ o << ",";
+ o << "\n";
+ }
+
+ i -= 2;
+ o.indent(i) << "};" << "\n";
+ }
+
+ void emitAsFlags(raw_ostream &o, unsigned int &i) {
+ o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
+ i += 2;
+
+ unsigned int index = 0;
+ unsigned int numEntries = Entries.size();
+ unsigned int flag = 1;
+ for (index = 0; index < numEntries; ++index) {
+ o.indent(i) << Entries[index] << " = " << format("0x%x", flag);
+ if (index < (numEntries - 1))
+ o << ",";
+ o << "\n";
+ flag <<= 1;
+ }
+
+ i -= 2;
+ o.indent(i) << "};" << "\n";
+ }
+ };
+
+ class ConstantEmitter {
+ public:
+ virtual ~ConstantEmitter() { }
+ virtual void emit(raw_ostream &o, unsigned int &i) = 0;
+ };
+
+ class LiteralConstantEmitter : public ConstantEmitter {
+ private:
+ bool IsNumber;
+ union {
+ int Number;
+ const char* String;
+ };
+ public:
+ LiteralConstantEmitter(int number = 0) :
+ IsNumber(true),
+ Number(number) {
+ }
+ void set(const char *string) {
+ IsNumber = false;
+ Number = 0;
+ String = string;
+ }
+ bool is(const char *string) {
+ return !strcmp(String, string);
+ }
+ void emit(raw_ostream &o, unsigned int &i) {
+ if (IsNumber)
+ o << Number;
+ else
+ o << String;
+ }
+ };
+
+ class CompoundConstantEmitter : public ConstantEmitter {
+ private:
+ unsigned int Padding;
+ std::vector<ConstantEmitter *> Entries;
+ public:
+ CompoundConstantEmitter(unsigned int padding = 0) : Padding(padding) {
+ }
+ CompoundConstantEmitter &addEntry(ConstantEmitter *e) {
+ Entries.push_back(e);
+
+ return *this;
+ }
+ ~CompoundConstantEmitter() {
+ while (Entries.size()) {
+ ConstantEmitter *entry = Entries.back();
+ Entries.pop_back();
+ delete entry;
+ }
+ }
+ void emit(raw_ostream &o, unsigned int &i) {
+ o << "{" << "\n";
+ i += 2;
+
+ unsigned int index;
+ unsigned int numEntries = Entries.size();
+
+ unsigned int numToPrint;
+
+ if (Padding) {
+ if (numEntries > Padding) {
+ fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding);
+ llvm_unreachable("More entries than padding");
+ }
+ numToPrint = Padding;
+ } else {
+ numToPrint = numEntries;
+ }
+
+ for (index = 0; index < numToPrint; ++index) {
+ o.indent(i);
+ if (index < numEntries)
+ Entries[index]->emit(o, i);
+ else
+ o << "-1";
+
+ if (index < (numToPrint - 1))
+ o << ",";
+ o << "\n";
+ }
+
+ i -= 2;
+ o.indent(i) << "}";
+ }
+ };
+
+ class FlagsConstantEmitter : public ConstantEmitter {
+ private:
+ std::vector<std::string> Flags;
+ public:
+ FlagsConstantEmitter() {
+ }
+ FlagsConstantEmitter &addEntry(const char *f) {
+ Flags.push_back(std::string(f));
+ return *this;
+ }
+ void emit(raw_ostream &o, unsigned int &i) {
+ unsigned int index;
+ unsigned int numFlags = Flags.size();
+ if (numFlags == 0)
+ o << "0";
+
+ for (index = 0; index < numFlags; ++index) {
+ o << Flags[index].c_str();
+ if (index < (numFlags - 1))
+ o << " | ";
+ }
+ }
+ };
+}
+
+EDEmitter::EDEmitter(RecordKeeper &R) : Records(R) {
+}
+
+/// populateOperandOrder - Accepts a CodeGenInstruction and generates its
+/// AsmWriterInst for the desired assembly syntax, giving an ordered list of
+/// operands in the order they appear in the printed instruction. Then, for
+/// each entry in that list, determines the index of the same operand in the
+/// CodeGenInstruction, and emits the resulting mapping into an array, filling
+/// in unused slots with -1.
+///
+/// @arg operandOrder - The array that will be populated with the operand
+/// mapping. Each entry will contain -1 (invalid index
+/// into the operands present in the AsmString) or a number
+/// representing an index in the operand descriptor array.
+/// @arg inst - The instruction to use when looking up the operands
+/// @arg syntax - The syntax to use, according to LLVM's enumeration
+void populateOperandOrder(CompoundConstantEmitter *operandOrder,
+ const CodeGenInstruction &inst,
+ unsigned syntax) {
+ unsigned int numArgs = 0;
+
+ AsmWriterInst awInst(inst, syntax, -1, -1);
+
+ std::vector<AsmWriterOperand>::iterator operandIterator;
+
+ for (operandIterator = awInst.Operands.begin();
+ operandIterator != awInst.Operands.end();
+ ++operandIterator) {
+ if (operandIterator->OperandType ==
+ AsmWriterOperand::isMachineInstrOperand) {
+ operandOrder->addEntry(
+ new LiteralConstantEmitter(operandIterator->CGIOpNo));
+ numArgs++;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////
+// Support functions for handling X86 instructions //
+/////////////////////////////////////////////////////
+
+#define SET(flag) { type->set(flag); return 0; }
+
+#define REG(str) if (name == str) SET("kOperandTypeRegister");
+#define MEM(str) if (name == str) SET("kOperandTypeX86Memory");
+#define LEA(str) if (name == str) SET("kOperandTypeX86EffectiveAddress");
+#define IMM(str) if (name == str) SET("kOperandTypeImmediate");
+#define PCR(str) if (name == str) SET("kOperandTypeX86PCRelative");
+
+/// X86TypeFromOpName - Processes the name of a single X86 operand (which is
+/// actually its type) and translates it into an operand type
+///
+/// @arg flags - The type object to set
+/// @arg name - The name of the operand
+static int X86TypeFromOpName(LiteralConstantEmitter *type,
+ const std::string &name) {
+ REG("GR8");
+ REG("GR8_NOREX");
+ REG("GR16");
+ REG("GR32");
+ REG("GR32_NOREX");
+ REG("GR32_TC");
+ REG("FR32");
+ REG("RFP32");
+ REG("GR64");
+ REG("GR64_TC");
+ REG("FR64");
+ REG("VR64");
+ REG("RFP64");
+ REG("RFP80");
+ REG("VR128");
+ REG("VR256");
+ REG("RST");
+ REG("SEGMENT_REG");
+ REG("DEBUG_REG");
+ REG("CONTROL_REG");
+
+ IMM("i8imm");
+ IMM("i16imm");
+ IMM("i16i8imm");
+ IMM("i32imm");
+ IMM("i32i8imm");
+ IMM("i64imm");
+ IMM("i64i8imm");
+ IMM("i64i32imm");
+ IMM("SSECC");
+
+ // all R, I, R, I, R
+ MEM("i8mem");
+ MEM("i8mem_NOREX");
+ MEM("i16mem");
+ MEM("i32mem");
+ MEM("i32mem_TC");
+ MEM("f32mem");
+ MEM("ssmem");
+ MEM("opaque32mem");
+ MEM("opaque48mem");
+ MEM("i64mem");
+ MEM("i64mem_TC");
+ MEM("f64mem");
+ MEM("sdmem");
+ MEM("f80mem");
+ MEM("opaque80mem");
+ MEM("i128mem");
+ MEM("i256mem");
+ MEM("f128mem");
+ MEM("f256mem");
+ MEM("opaque512mem");
+
+ // all R, I, R, I
+ LEA("lea32mem");
+ LEA("lea64_32mem");
+ LEA("lea64mem");
+
+ // all I
+ PCR("i16imm_pcrel");
+ PCR("i32imm_pcrel");
+ PCR("i64i32imm_pcrel");
+ PCR("brtarget8");
+ PCR("offset8");
+ PCR("offset16");
+ PCR("offset32");
+ PCR("offset64");
+ PCR("brtarget");
+
+ return 1;
+}
+
+#undef REG
+#undef MEM
+#undef LEA
+#undef IMM
+#undef PCR
+
+#undef SET
+
+/// X86PopulateOperands - Handles all the operands in an X86 instruction, adding
+/// the appropriate flags to their descriptors
+///
+/// @operandFlags - A reference the array of operand flag objects
+/// @inst - The instruction to use as a source of information
+static void X86PopulateOperands(
+ LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS],
+ const CodeGenInstruction &inst) {
+ if (!inst.TheDef->isSubClassOf("X86Inst"))
+ return;
+
+ unsigned int index;
+ unsigned int numOperands = inst.OperandList.size();
+
+ for (index = 0; index < numOperands; ++index) {
+ const CodeGenInstruction::OperandInfo &operandInfo =
+ inst.OperandList[index];
+ Record &rec = *operandInfo.Rec;
+
+ if (X86TypeFromOpName(operandTypes[index], rec.getName())) {
+ errs() << "Operand type: " << rec.getName().c_str() << "\n";
+ errs() << "Operand name: " << operandInfo.Name.c_str() << "\n";
+ errs() << "Instruction mame: " << inst.TheDef->getName().c_str() << "\n";
+ llvm_unreachable("Unhandled type");
+ }
+ }
+}
+
+/// decorate1 - Decorates a named operand with a new flag
+///
+/// @operandFlags - The array of operand flag objects, which don't have names
+/// @inst - The CodeGenInstruction, which provides a way to translate
+/// between names and operand indices
+/// @opName - The name of the operand
+/// @flag - The name of the flag to add
+static inline void decorate1(
+ FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS],
+ const CodeGenInstruction &inst,
+ const char *opName,
+ const char *opFlag) {
+ unsigned opIndex;
+
+ opIndex = inst.getOperandNamed(std::string(opName));
+
+ operandFlags[opIndex]->addEntry(opFlag);
+}
+
+#define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag)
+
+#define MOV(source, target) { \
+ instType.set("kInstructionTypeMove"); \
+ DECORATE1(source, "kOperandFlagSource"); \
+ DECORATE1(target, "kOperandFlagTarget"); \
+}
+
+#define BRANCH(target) { \
+ instType.set("kInstructionTypeBranch"); \
+ DECORATE1(target, "kOperandFlagTarget"); \
+}
+
+#define PUSH(source) { \
+ instType.set("kInstructionTypePush"); \
+ DECORATE1(source, "kOperandFlagSource"); \
+}
+
+#define POP(target) { \
+ instType.set("kInstructionTypePop"); \
+ DECORATE1(target, "kOperandFlagTarget"); \
+}
+
+#define CALL(target) { \
+ instType.set("kInstructionTypeCall"); \
+ DECORATE1(target, "kOperandFlagTarget"); \
+}
+
+#define RETURN() { \
+ instType.set("kInstructionTypeReturn"); \
+}
+
+/// X86ExtractSemantics - Performs various checks on the name of an X86
+/// instruction to determine what sort of an instruction it is and then adds
+/// the appropriate flags to the instruction and its operands
+///
+/// @arg instType - A reference to the type for the instruction as a whole
+/// @arg operandFlags - A reference to the array of operand flag object pointers
+/// @arg inst - A reference to the original instruction
+static void X86ExtractSemantics(
+ LiteralConstantEmitter &instType,
+ FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS],
+ const CodeGenInstruction &inst) {
+ const std::string &name = inst.TheDef->getName();
+
+ if (name.find("MOV") != name.npos) {
+ if (name.find("MOV_V") != name.npos) {
+ // ignore (this is a pseudoinstruction)
+ } else if (name.find("MASK") != name.npos) {
+ // ignore (this is a masking move)
+ } else if (name.find("r0") != name.npos) {
+ // ignore (this is a pseudoinstruction)
+ } else if (name.find("PS") != name.npos ||
+ name.find("PD") != name.npos) {
+ // ignore (this is a shuffling move)
+ } else if (name.find("MOVS") != name.npos) {
+ // ignore (this is a string move)
+ } else if (name.find("_F") != name.npos) {
+ // TODO handle _F moves to ST(0)
+ } else if (name.find("a") != name.npos) {
+ // TODO handle moves to/from %ax
+ } else if (name.find("CMOV") != name.npos) {
+ MOV("src2", "dst");
+ } else if (name.find("PC") != name.npos) {
+ MOV("label", "reg")
+ } else {
+ MOV("src", "dst");
+ }
+ }
+
+ if (name.find("JMP") != name.npos ||
+ name.find("J") == 0) {
+ if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
+ BRANCH("off");
+ } else {
+ BRANCH("dst");
+ }
+ }
+
+ if (name.find("PUSH") != name.npos) {
+ if (name.find("FS") != name.npos ||
+ name.find("GS") != name.npos) {
+ instType.set("kInstructionTypePush");
+ // TODO add support for fixed operands
+ } else if (name.find("F") != name.npos) {
+ // ignore (this pushes onto the FP stack)
+ } else if (name.find("A") != name.npos) {
+ // ignore (pushes all GP registoers onto the stack)
+ } else if (name[name.length() - 1] == 'm') {
+ PUSH("src");
+ } else if (name.find("i") != name.npos) {
+ PUSH("imm");
+ } else {
+ PUSH("reg");
+ }
+ }
+
+ if (name.find("POP") != name.npos) {
+ if (name.find("POPCNT") != name.npos) {
+ // ignore (not a real pop)
+ } else if (name.find("FS") != name.npos ||
+ name.find("GS") != name.npos) {
+ instType.set("kInstructionTypePop");
+ // TODO add support for fixed operands
+ } else if (name.find("F") != name.npos) {
+ // ignore (this pops from the FP stack)
+ } else if (name.find("A") != name.npos) {
+ // ignore (pushes all GP registoers onto the stack)
+ } else if (name[name.length() - 1] == 'm') {
+ POP("dst");
+ } else {
+ POP("reg");
+ }
+ }
+
+ if (name.find("CALL") != name.npos) {
+ if (name.find("ADJ") != name.npos) {
+ // ignore (not a call)
+ } else if (name.find("SYSCALL") != name.npos) {
+ // ignore (doesn't go anywhere we know about)
+ } else if (name.find("VMCALL") != name.npos) {
+ // ignore (rather different semantics than a regular call)
+ } else if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
+ CALL("off");
+ } else {
+ CALL("dst");
+ }
+ }
+
+ if (name.find("RET") != name.npos) {
+ RETURN();
+ }
+}
+
+#undef MOV
+#undef BRANCH
+#undef PUSH
+#undef POP
+#undef CALL
+#undef RETURN
+
+/////////////////////////////////////////////////////
+// Support functions for handling ARM instructions //
+/////////////////////////////////////////////////////
+
+#define SET(flag) { type->set(flag); return 0; }
+
+#define REG(str) if (name == str) SET("kOperandTypeRegister");
+#define IMM(str) if (name == str) SET("kOperandTypeImmediate");
+
+#define MISC(str, type) if (name == str) SET(type);
+
+/// ARMFlagFromOpName - Processes the name of a single ARM operand (which is
+/// actually its type) and translates it into an operand type
+///
+/// @arg type - The type object to set
+/// @arg name - The name of the operand
+static int ARMFlagFromOpName(LiteralConstantEmitter *type,
+ const std::string &name) {
+ REG("GPR");
+ REG("rGPR");
+ REG("tcGPR");
+ REG("cc_out");
+ REG("s_cc_out");
+ REG("tGPR");
+ REG("DPR");
+ REG("DPR_VFP2");
+ REG("DPR_8");
+ REG("SPR");
+ REG("QPR");
+ REG("QQPR");
+ REG("QQQQPR");
+
+ IMM("i32imm");
+ IMM("bf_inv_mask_imm");
+ IMM("jtblock_operand");
+ IMM("nohash_imm");
+ IMM("cpinst_operand");
+ IMM("cps_opt");
+ IMM("vfp_f64imm");
+ IMM("vfp_f32imm");
+ IMM("memb_opt");
+ IMM("msr_mask");
+ IMM("neg_zero");
+ IMM("imm0_31");
+ IMM("nModImm");
+ IMM("imm0_4095");
+ IMM("jt2block_operand");
+ IMM("t_imm_s4");
+ IMM("pclabel");
+ IMM("shift_imm");
+
+ MISC("brtarget", "kOperandTypeARMBranchTarget"); // ?
+ MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I
+ MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I
+ MISC("so_imm", "kOperandTypeARMSoImm"); // I
+ MISC("t2_so_imm", "kOperandTypeThumb2SoImm"); // I
+ MISC("so_imm2part", "kOperandTypeARMSoImm2Part"); // I
+ MISC("pred", "kOperandTypeARMPredicate"); // I, R
+ MISC("it_pred", "kOperandTypeARMPredicate"); // I
+ MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I
+ MISC("am2offset", "kOperandTypeARMAddrMode2Offset"); // R, I
+ MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I
+ MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I
+ MISC("addrmode4", "kOperandTypeARMAddrMode4"); // R, I
+ MISC("addrmode5", "kOperandTypeARMAddrMode5"); // R, I
+ MISC("addrmode6", "kOperandTypeARMAddrMode6"); // R, R, I, I
+ MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I
+ MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I
+ MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ...
+ MISC("it_mask", "kOperandTypeThumbITMask"); // I
+ MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
+ MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I
+ MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I
+ MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I
+ MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I
+ MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset");
+ // R, I
+ MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I
+ MISC("t_addrmode_s1", "kOperandTypeThumbAddrModeS1"); // R, I, R
+ MISC("t_addrmode_s2", "kOperandTypeThumbAddrModeS2"); // R, I, R
+ MISC("t_addrmode_s4", "kOperandTypeThumbAddrModeS4"); // R, I, R
+ MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R
+ MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I
+
+ return 1;
+}
+
+#undef SOREG
+#undef SOIMM
+#undef PRED
+#undef REG
+#undef MEM
+#undef LEA
+#undef IMM
+#undef PCR
+
+#undef SET
+
+/// ARMPopulateOperands - Handles all the operands in an ARM instruction, adding
+/// the appropriate flags to their descriptors
+///
+/// @operandFlags - A reference the array of operand flag objects
+/// @inst - The instruction to use as a source of information
+static void ARMPopulateOperands(
+ LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS],
+ const CodeGenInstruction &inst) {
+ if (!inst.TheDef->isSubClassOf("InstARM") &&
+ !inst.TheDef->isSubClassOf("InstThumb"))
+ return;
+
+ unsigned int index;
+ unsigned int numOperands = inst.OperandList.size();
+
+ if (numOperands > EDIS_MAX_OPERANDS) {
+ errs() << "numOperands == " << numOperands << " > " <<
+ EDIS_MAX_OPERANDS << '\n';
+ llvm_unreachable("Too many operands");
+ }
+
+ for (index = 0; index < numOperands; ++index) {
+ const CodeGenInstruction::OperandInfo &operandInfo =
+ inst.OperandList[index];
+ Record &rec = *operandInfo.Rec;
+
+ if (ARMFlagFromOpName(operandTypes[index], rec.getName())) {
+ errs() << "Operand type: " << rec.getName() << '\n';
+ errs() << "Operand name: " << operandInfo.Name << '\n';
+ errs() << "Instruction mame: " << inst.TheDef->getName() << '\n';
+ llvm_unreachable("Unhandled type");
+ }
+ }
+}
+
+#define BRANCH(target) { \
+ instType.set("kInstructionTypeBranch"); \
+ DECORATE1(target, "kOperandFlagTarget"); \
+}
+
+/// ARMExtractSemantics - Performs various checks on the name of an ARM
+/// instruction to determine what sort of an instruction it is and then adds
+/// the appropriate flags to the instruction and its operands
+///
+/// @arg instType - A reference to the type for the instruction as a whole
+/// @arg operandTypes - A reference to the array of operand type object pointers
+/// @arg operandFlags - A reference to the array of operand flag object pointers
+/// @arg inst - A reference to the original instruction
+static void ARMExtractSemantics(
+ LiteralConstantEmitter &instType,
+ LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS],
+ FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS],
+ const CodeGenInstruction &inst) {
+ const std::string &name = inst.TheDef->getName();
+
+ if (name == "tBcc" ||
+ name == "tB" ||
+ name == "t2Bcc" ||
+ name == "Bcc" ||
+ name == "tCBZ" ||
+ name == "tCBNZ") {
+ BRANCH("target");
+ }
+
+ if (name == "tBLr9" ||
+ name == "BLr9_pred" ||
+ name == "tBLXi_r9" ||
+ name == "tBLXr_r9" ||
+ name == "BLXr9" ||
+ name == "t2BXJ" ||
+ name == "BXJ") {
+ BRANCH("func");
+
+ unsigned opIndex;
+ opIndex = inst.getOperandNamed("func");
+ if (operandTypes[opIndex]->is("kOperandTypeImmediate"))
+ operandTypes[opIndex]->set("kOperandTypeARMBranchTarget");
+ }
+}
+
+#undef BRANCH
+
+/// populateInstInfo - Fills an array of InstInfos with information about each
+/// instruction in a target
+///
+/// @arg infoArray - The array of InstInfo objects to populate
+/// @arg target - The CodeGenTarget to use as a source of instructions
+static void populateInstInfo(CompoundConstantEmitter &infoArray,
+ CodeGenTarget &target) {
+ const std::vector<const CodeGenInstruction*> &numberedInstructions =
+ target.getInstructionsByEnumValue();
+
+ unsigned int index;
+ unsigned int numInstructions = numberedInstructions.size();
+
+ for (index = 0; index < numInstructions; ++index) {
+ const CodeGenInstruction& inst = *numberedInstructions[index];
+
+ CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter;
+ infoArray.addEntry(infoStruct);
+
+ LiteralConstantEmitter *instType = new LiteralConstantEmitter;
+ infoStruct->addEntry(instType);
+
+ LiteralConstantEmitter *numOperandsEmitter =
+ new LiteralConstantEmitter(inst.OperandList.size());
+ infoStruct->addEntry(numOperandsEmitter);
+
+ CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter;
+ infoStruct->addEntry(operandTypeArray);
+
+ LiteralConstantEmitter *operandTypes[EDIS_MAX_OPERANDS];
+
+ CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter;
+ infoStruct->addEntry(operandFlagArray);
+
+ FlagsConstantEmitter *operandFlags[EDIS_MAX_OPERANDS];
+
+ for (unsigned operandIndex = 0;
+ operandIndex < EDIS_MAX_OPERANDS;
+ ++operandIndex) {
+ operandTypes[operandIndex] = new LiteralConstantEmitter;
+ operandTypeArray->addEntry(operandTypes[operandIndex]);
+
+ operandFlags[operandIndex] = new FlagsConstantEmitter;
+ operandFlagArray->addEntry(operandFlags[operandIndex]);
+ }
+
+ unsigned numSyntaxes = 0;
+
+ if (target.getName() == "X86") {
+ X86PopulateOperands(operandTypes, inst);
+ X86ExtractSemantics(*instType, operandFlags, inst);
+ numSyntaxes = 2;
+ }
+ else if (target.getName() == "ARM") {
+ ARMPopulateOperands(operandTypes, inst);
+ ARMExtractSemantics(*instType, operandTypes, operandFlags, inst);
+ numSyntaxes = 1;
+ }
+
+ CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter;
+
+ infoStruct->addEntry(operandOrderArray);
+
+ for (unsigned syntaxIndex = 0;
+ syntaxIndex < EDIS_MAX_SYNTAXES;
+ ++syntaxIndex) {
+ CompoundConstantEmitter *operandOrder =
+ new CompoundConstantEmitter(EDIS_MAX_OPERANDS);
+
+ operandOrderArray->addEntry(operandOrder);
+
+ if (syntaxIndex < numSyntaxes) {
+ populateOperandOrder(operandOrder, inst, syntaxIndex);
+ }
+ }
+
+ infoStruct = NULL;
+ }
+}
+
+static void emitCommonEnums(raw_ostream &o, unsigned int &i) {
+ EnumEmitter operandTypes("OperandTypes");
+ operandTypes.addEntry("kOperandTypeNone");
+ operandTypes.addEntry("kOperandTypeImmediate");
+ operandTypes.addEntry("kOperandTypeRegister");
+ operandTypes.addEntry("kOperandTypeX86Memory");
+ operandTypes.addEntry("kOperandTypeX86EffectiveAddress");
+ operandTypes.addEntry("kOperandTypeX86PCRelative");
+ operandTypes.addEntry("kOperandTypeARMBranchTarget");
+ operandTypes.addEntry("kOperandTypeARMSoReg");
+ operandTypes.addEntry("kOperandTypeARMSoImm");
+ operandTypes.addEntry("kOperandTypeARMSoImm2Part");
+ operandTypes.addEntry("kOperandTypeARMPredicate");
+ operandTypes.addEntry("kOperandTypeARMAddrMode2");
+ operandTypes.addEntry("kOperandTypeARMAddrMode2Offset");
+ operandTypes.addEntry("kOperandTypeARMAddrMode3");
+ operandTypes.addEntry("kOperandTypeARMAddrMode3Offset");
+ operandTypes.addEntry("kOperandTypeARMAddrMode4");
+ operandTypes.addEntry("kOperandTypeARMAddrMode5");
+ operandTypes.addEntry("kOperandTypeARMAddrMode6");
+ operandTypes.addEntry("kOperandTypeARMAddrMode6Offset");
+ operandTypes.addEntry("kOperandTypeARMAddrModePC");
+ operandTypes.addEntry("kOperandTypeARMRegisterList");
+ operandTypes.addEntry("kOperandTypeARMTBAddrMode");
+ operandTypes.addEntry("kOperandTypeThumbITMask");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeS1");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeS2");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeS4");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeRR");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeSP");
+ operandTypes.addEntry("kOperandTypeThumb2SoReg");
+ operandTypes.addEntry("kOperandTypeThumb2SoImm");
+ operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8");
+ operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8Offset");
+ operandTypes.addEntry("kOperandTypeThumb2AddrModeImm12");
+ operandTypes.addEntry("kOperandTypeThumb2AddrModeSoReg");
+ operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4");
+ operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4Offset");
+ operandTypes.emit(o, i);
+
+ o << "\n";
+
+ EnumEmitter operandFlags("OperandFlags");
+ operandFlags.addEntry("kOperandFlagSource");
+ operandFlags.addEntry("kOperandFlagTarget");
+ operandFlags.emitAsFlags(o, i);
+
+ o << "\n";
+
+ EnumEmitter instructionTypes("InstructionTypes");
+ instructionTypes.addEntry("kInstructionTypeNone");
+ instructionTypes.addEntry("kInstructionTypeMove");
+ instructionTypes.addEntry("kInstructionTypeBranch");
+ instructionTypes.addEntry("kInstructionTypePush");
+ instructionTypes.addEntry("kInstructionTypePop");
+ instructionTypes.addEntry("kInstructionTypeCall");
+ instructionTypes.addEntry("kInstructionTypeReturn");
+ instructionTypes.emit(o, i);
+
+ o << "\n";
+}
+
+void EDEmitter::run(raw_ostream &o) {
+ unsigned int i = 0;
+
+ CompoundConstantEmitter infoArray;
+ CodeGenTarget target;
+
+ populateInstInfo(infoArray, target);
+
+ emitCommonEnums(o, i);
+
+ o << "namespace {\n";
+
+ o << "llvm::EDInstInfo instInfo" << target.getName().c_str() << "[] = ";
+ infoArray.emit(o, i);
+ o << ";" << "\n";
+
+ o << "}\n";
+}
diff --git a/contrib/llvm/utils/TableGen/EDEmitter.h b/contrib/llvm/utils/TableGen/EDEmitter.h
new file mode 100644
index 0000000..e30373f
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/EDEmitter.h
@@ -0,0 +1,34 @@
+//===- EDEmitter.h - Generate instruction descriptions for ED ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of each
+// instruction in a format that the semantic disassembler can use to tokenize
+// and parse instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SEMANTIC_INFO_EMITTER_H
+#define SEMANTIC_INFO_EMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+
+ class EDEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ public:
+ EDEmitter(RecordKeeper &R);
+
+ // run - Output the instruction table.
+ void run(raw_ostream &o);
+ };
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
new file mode 100644
index 0000000..6c16fcf
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
@@ -0,0 +1,651 @@
+//===- FastISelEmitter.cpp - Generate an instruction selector -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits code for use by the "fast" instruction
+// selection algorithm. See the comments at the top of
+// lib/CodeGen/SelectionDAG/FastISel.cpp for background.
+//
+// This file scans through the target's tablegen instruction-info files
+// and extracts instructions with obvious-looking patterns, and it emits
+// code to look up these instructions by type and operator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FastISelEmitter.h"
+#include "Record.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/ADT/VectorExtras.h"
+using namespace llvm;
+
+namespace {
+
+/// InstructionMemo - This class holds additional information about an
+/// instruction needed to emit code for it.
+///
+struct InstructionMemo {
+ std::string Name;
+ const CodeGenRegisterClass *RC;
+ std::string SubRegNo;
+ std::vector<std::string>* PhysRegs;
+};
+
+/// OperandsSignature - This class holds a description of a list of operand
+/// types. It has utility methods for emitting text based on the operands.
+///
+struct OperandsSignature {
+ std::vector<std::string> Operands;
+
+ bool operator<(const OperandsSignature &O) const {
+ return Operands < O.Operands;
+ }
+
+ bool empty() const { return Operands.empty(); }
+
+ /// initialize - Examine the given pattern and initialize the contents
+ /// of the Operands array accordingly. Return true if all the operands
+ /// are supported, false otherwise.
+ ///
+ bool initialize(TreePatternNode *InstPatNode,
+ const CodeGenTarget &Target,
+ MVT::SimpleValueType VT) {
+
+ if (!InstPatNode->isLeaf()) {
+ if (InstPatNode->getOperator()->getName() == "imm") {
+ Operands.push_back("i");
+ return true;
+ }
+ if (InstPatNode->getOperator()->getName() == "fpimm") {
+ Operands.push_back("f");
+ return true;
+ }
+ }
+
+ const CodeGenRegisterClass *DstRC = 0;
+
+ for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Op = InstPatNode->getChild(i);
+
+ // For now, filter out any operand with a predicate.
+ // For now, filter out any operand with multiple values.
+ if (!Op->getPredicateFns().empty() ||
+ Op->getNumTypes() != 1)
+ return false;
+
+ assert(Op->hasTypeSet(0) && "Type infererence not done?");
+ // For now, all the operands must have the same type.
+ if (Op->getType(0) != VT)
+ return false;
+
+ if (!Op->isLeaf()) {
+ if (Op->getOperator()->getName() == "imm") {
+ Operands.push_back("i");
+ continue;
+ }
+ if (Op->getOperator()->getName() == "fpimm") {
+ Operands.push_back("f");
+ continue;
+ }
+ // For now, ignore other non-leaf nodes.
+ return false;
+ }
+ DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue());
+ if (!OpDI)
+ return false;
+ Record *OpLeafRec = OpDI->getDef();
+ // For now, the only other thing we accept is register operands.
+
+ const CodeGenRegisterClass *RC = 0;
+ if (OpLeafRec->isSubClassOf("RegisterClass"))
+ RC = &Target.getRegisterClass(OpLeafRec);
+ else if (OpLeafRec->isSubClassOf("Register"))
+ RC = Target.getRegisterClassForRegister(OpLeafRec);
+ else
+ return false;
+
+ // For now, this needs to be a register class of some sort.
+ if (!RC)
+ return false;
+
+ // For now, all the operands must have the same register class or be
+ // a strict subclass of the destination.
+ if (DstRC) {
+ if (DstRC != RC && !DstRC->hasSubClass(RC))
+ return false;
+ } else
+ DstRC = RC;
+ Operands.push_back("r");
+ }
+ return true;
+ }
+
+ void PrintParameters(raw_ostream &OS) const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (Operands[i] == "r") {
+ OS << "unsigned Op" << i << ", bool Op" << i << "IsKill";
+ } else if (Operands[i] == "i") {
+ OS << "uint64_t imm" << i;
+ } else if (Operands[i] == "f") {
+ OS << "ConstantFP *f" << i;
+ } else {
+ assert("Unknown operand kind!");
+ abort();
+ }
+ if (i + 1 != e)
+ OS << ", ";
+ }
+ }
+
+ void PrintArguments(raw_ostream &OS,
+ const std::vector<std::string>& PR) const {
+ assert(PR.size() == Operands.size());
+ bool PrintedArg = false;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (PR[i] != "")
+ // Implicit physical register operand.
+ continue;
+
+ if (PrintedArg)
+ OS << ", ";
+ if (Operands[i] == "r") {
+ OS << "Op" << i << ", Op" << i << "IsKill";
+ PrintedArg = true;
+ } else if (Operands[i] == "i") {
+ OS << "imm" << i;
+ PrintedArg = true;
+ } else if (Operands[i] == "f") {
+ OS << "f" << i;
+ PrintedArg = true;
+ } else {
+ assert("Unknown operand kind!");
+ abort();
+ }
+ }
+ }
+
+ void PrintArguments(raw_ostream &OS) const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (Operands[i] == "r") {
+ OS << "Op" << i << ", Op" << i << "IsKill";
+ } else if (Operands[i] == "i") {
+ OS << "imm" << i;
+ } else if (Operands[i] == "f") {
+ OS << "f" << i;
+ } else {
+ assert("Unknown operand kind!");
+ abort();
+ }
+ if (i + 1 != e)
+ OS << ", ";
+ }
+ }
+
+
+ void PrintManglingSuffix(raw_ostream &OS,
+ const std::vector<std::string>& PR) const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (PR[i] != "")
+ // Implicit physical register operand. e.g. Instruction::Mul expect to
+ // select to a binary op. On x86, mul may take a single operand with
+ // the other operand being implicit. We must emit something that looks
+ // like a binary instruction except for the very inner FastEmitInst_*
+ // call.
+ continue;
+ OS << Operands[i];
+ }
+ }
+
+ void PrintManglingSuffix(raw_ostream &OS) const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ OS << Operands[i];
+ }
+ }
+};
+
+class FastISelMap {
+ typedef std::map<std::string, InstructionMemo> PredMap;
+ typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap;
+ typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap;
+ typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap;
+ typedef std::map<OperandsSignature, OpcodeTypeRetPredMap>
+ OperandsOpcodeTypeRetPredMap;
+
+ OperandsOpcodeTypeRetPredMap SimplePatterns;
+
+ std::string InstNS;
+
+public:
+ explicit FastISelMap(std::string InstNS);
+
+ void CollectPatterns(CodeGenDAGPatterns &CGP);
+ void PrintFunctionDefinitions(raw_ostream &OS);
+};
+
+}
+
+static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {
+ return CGP.getSDNodeInfo(Op).getEnumName();
+}
+
+static std::string getLegalCName(std::string OpName) {
+ std::string::size_type pos = OpName.find("::");
+ if (pos != std::string::npos)
+ OpName.replace(pos, 2, "_");
+ return OpName;
+}
+
+FastISelMap::FastISelMap(std::string instns)
+ : InstNS(instns) {
+}
+
+void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) {
+ const CodeGenTarget &Target = CGP.getTargetInfo();
+
+ // Determine the target's namespace name.
+ InstNS = Target.getInstNamespace() + "::";
+ assert(InstNS.size() > 2 && "Can't determine target-specific namespace!");
+
+ // Scan through all the patterns and record the simple ones.
+ for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
+ E = CGP.ptm_end(); I != E; ++I) {
+ const PatternToMatch &Pattern = *I;
+
+ // For now, just look at Instructions, so that we don't have to worry
+ // about emitting multiple instructions for a pattern.
+ TreePatternNode *Dst = Pattern.getDstPattern();
+ if (Dst->isLeaf()) continue;
+ Record *Op = Dst->getOperator();
+ if (!Op->isSubClassOf("Instruction"))
+ continue;
+ CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);
+ if (II.OperandList.empty())
+ continue;
+
+ // For now, ignore multi-instruction patterns.
+ bool MultiInsts = false;
+ for (unsigned i = 0, e = Dst->getNumChildren(); i != e; ++i) {
+ TreePatternNode *ChildOp = Dst->getChild(i);
+ if (ChildOp->isLeaf())
+ continue;
+ if (ChildOp->getOperator()->isSubClassOf("Instruction")) {
+ MultiInsts = true;
+ break;
+ }
+ }
+ if (MultiInsts)
+ continue;
+
+ // For now, ignore instructions where the first operand is not an
+ // output register.
+ const CodeGenRegisterClass *DstRC = 0;
+ std::string SubRegNo;
+ if (Op->getName() != "EXTRACT_SUBREG") {
+ Record *Op0Rec = II.OperandList[0].Rec;
+ if (!Op0Rec->isSubClassOf("RegisterClass"))
+ continue;
+ DstRC = &Target.getRegisterClass(Op0Rec);
+ if (!DstRC)
+ continue;
+ } else {
+ // If this isn't a leaf, then continue since the register classes are
+ // a bit too complicated for now.
+ if (!Dst->getChild(1)->isLeaf()) continue;
+
+ DefInit *SR = dynamic_cast<DefInit*>(Dst->getChild(1)->getLeafValue());
+ if (SR)
+ SubRegNo = getQualifiedName(SR->getDef());
+ else
+ SubRegNo = Dst->getChild(1)->getLeafValue()->getAsString();
+ }
+
+ // Inspect the pattern.
+ TreePatternNode *InstPatNode = Pattern.getSrcPattern();
+ if (!InstPatNode) continue;
+ if (InstPatNode->isLeaf()) continue;
+
+ // Ignore multiple result nodes for now.
+ if (InstPatNode->getNumTypes() > 1) continue;
+
+ Record *InstPatOp = InstPatNode->getOperator();
+ std::string OpcodeName = getOpcodeName(InstPatOp, CGP);
+ MVT::SimpleValueType RetVT = MVT::isVoid;
+ if (InstPatNode->getNumTypes()) RetVT = InstPatNode->getType(0);
+ MVT::SimpleValueType VT = RetVT;
+ if (InstPatNode->getNumChildren()) {
+ assert(InstPatNode->getChild(0)->getNumTypes() == 1);
+ VT = InstPatNode->getChild(0)->getType(0);
+ }
+
+ // For now, filter out instructions which just set a register to
+ // an Operand or an immediate, like MOV32ri.
+ if (InstPatOp->isSubClassOf("Operand"))
+ continue;
+
+ // For now, filter out any instructions with predicates.
+ if (!InstPatNode->getPredicateFns().empty())
+ continue;
+
+ // Check all the operands.
+ OperandsSignature Operands;
+ if (!Operands.initialize(InstPatNode, Target, VT))
+ continue;
+
+ std::vector<std::string>* PhysRegInputs = new std::vector<std::string>();
+ if (!InstPatNode->isLeaf() &&
+ (InstPatNode->getOperator()->getName() == "imm" ||
+ InstPatNode->getOperator()->getName() == "fpimmm"))
+ PhysRegInputs->push_back("");
+ else if (!InstPatNode->isLeaf()) {
+ for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Op = InstPatNode->getChild(i);
+ if (!Op->isLeaf()) {
+ PhysRegInputs->push_back("");
+ continue;
+ }
+
+ DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue());
+ Record *OpLeafRec = OpDI->getDef();
+ std::string PhysReg;
+ if (OpLeafRec->isSubClassOf("Register")) {
+ PhysReg += static_cast<StringInit*>(OpLeafRec->getValue( \
+ "Namespace")->getValue())->getValue();
+ PhysReg += "::";
+
+ std::vector<CodeGenRegister> Regs = Target.getRegisters();
+ for (unsigned i = 0; i < Regs.size(); ++i) {
+ if (Regs[i].TheDef == OpLeafRec) {
+ PhysReg += Regs[i].getName();
+ break;
+ }
+ }
+ }
+
+ PhysRegInputs->push_back(PhysReg);
+ }
+ } else
+ PhysRegInputs->push_back("");
+
+ // Get the predicate that guards this pattern.
+ std::string PredicateCheck = Pattern.getPredicateCheck();
+
+ // Ok, we found a pattern that we can handle. Remember it.
+ InstructionMemo Memo = {
+ Pattern.getDstPattern()->getOperator()->getName(),
+ DstRC,
+ SubRegNo,
+ PhysRegInputs
+ };
+ assert(!SimplePatterns[Operands][OpcodeName][VT][RetVT]
+ .count(PredicateCheck) &&
+ "Duplicate pattern!");
+ SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo;
+ }
+}
+
+void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
+ // Now emit code for all the patterns that we collected.
+ for (OperandsOpcodeTypeRetPredMap::const_iterator OI = SimplePatterns.begin(),
+ OE = SimplePatterns.end(); OI != OE; ++OI) {
+ const OperandsSignature &Operands = OI->first;
+ const OpcodeTypeRetPredMap &OTM = OI->second;
+
+ for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end();
+ I != E; ++I) {
+ const std::string &Opcode = I->first;
+ const TypeRetPredMap &TM = I->second;
+
+ OS << "// FastEmit functions for " << Opcode << ".\n";
+ OS << "\n";
+
+ // Emit one function for each opcode,type pair.
+ for (TypeRetPredMap::const_iterator TI = TM.begin(), TE = TM.end();
+ TI != TE; ++TI) {
+ MVT::SimpleValueType VT = TI->first;
+ const RetPredMap &RM = TI->second;
+ if (RM.size() != 1) {
+ for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end();
+ RI != RE; ++RI) {
+ MVT::SimpleValueType RetVT = RI->first;
+ const PredMap &PM = RI->second;
+ bool HasPred = false;
+
+ OS << "unsigned FastEmit_"
+ << getLegalCName(Opcode)
+ << "_" << getLegalCName(getName(VT))
+ << "_" << getLegalCName(getName(RetVT)) << "_";
+ Operands.PrintManglingSuffix(OS);
+ OS << "(";
+ Operands.PrintParameters(OS);
+ OS << ") {\n";
+
+ // Emit code for each possible instruction. There may be
+ // multiple if there are subtarget concerns.
+ for (PredMap::const_iterator PI = PM.begin(), PE = PM.end();
+ PI != PE; ++PI) {
+ std::string PredicateCheck = PI->first;
+ const InstructionMemo &Memo = PI->second;
+
+ if (PredicateCheck.empty()) {
+ assert(!HasPred &&
+ "Multiple instructions match, at least one has "
+ "a predicate and at least one doesn't!");
+ } else {
+ OS << " if (" + PredicateCheck + ") {\n";
+ OS << " ";
+ HasPred = true;
+ }
+
+ for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
+ if ((*Memo.PhysRegs)[i] != "")
+ OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, "
+ << "TII.get(TargetOpcode::COPY), "
+ << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
+ }
+
+ OS << " return FastEmitInst_";
+ if (Memo.SubRegNo.empty()) {
+ Operands.PrintManglingSuffix(OS, *Memo.PhysRegs);
+ OS << "(" << InstNS << Memo.Name << ", ";
+ OS << InstNS << Memo.RC->getName() << "RegisterClass";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintArguments(OS, *Memo.PhysRegs);
+ OS << ");\n";
+ } else {
+ OS << "extractsubreg(" << getName(RetVT);
+ OS << ", Op0, Op0IsKill, ";
+ OS << Memo.SubRegNo;
+ OS << ");\n";
+ }
+
+ if (HasPred)
+ OS << " }\n";
+
+ }
+ // Return 0 if none of the predicates were satisfied.
+ if (HasPred)
+ OS << " return 0;\n";
+ OS << "}\n";
+ OS << "\n";
+ }
+
+ // Emit one function for the type that demultiplexes on return type.
+ OS << "unsigned FastEmit_"
+ << getLegalCName(Opcode) << "_"
+ << getLegalCName(getName(VT)) << "_";
+ Operands.PrintManglingSuffix(OS);
+ OS << "(MVT RetVT";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintParameters(OS);
+ OS << ") {\nswitch (RetVT.SimpleTy) {\n";
+ for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end();
+ RI != RE; ++RI) {
+ MVT::SimpleValueType RetVT = RI->first;
+ OS << " case " << getName(RetVT) << ": return FastEmit_"
+ << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT))
+ << "_" << getLegalCName(getName(RetVT)) << "_";
+ Operands.PrintManglingSuffix(OS);
+ OS << "(";
+ Operands.PrintArguments(OS);
+ OS << ");\n";
+ }
+ OS << " default: return 0;\n}\n}\n\n";
+
+ } else {
+ // Non-variadic return type.
+ OS << "unsigned FastEmit_"
+ << getLegalCName(Opcode) << "_"
+ << getLegalCName(getName(VT)) << "_";
+ Operands.PrintManglingSuffix(OS);
+ OS << "(MVT RetVT";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintParameters(OS);
+ OS << ") {\n";
+
+ OS << " if (RetVT.SimpleTy != " << getName(RM.begin()->first)
+ << ")\n return 0;\n";
+
+ const PredMap &PM = RM.begin()->second;
+ bool HasPred = false;
+
+ // Emit code for each possible instruction. There may be
+ // multiple if there are subtarget concerns.
+ for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); PI != PE;
+ ++PI) {
+ std::string PredicateCheck = PI->first;
+ const InstructionMemo &Memo = PI->second;
+
+ if (PredicateCheck.empty()) {
+ assert(!HasPred &&
+ "Multiple instructions match, at least one has "
+ "a predicate and at least one doesn't!");
+ } else {
+ OS << " if (" + PredicateCheck + ") {\n";
+ OS << " ";
+ HasPred = true;
+ }
+
+ for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
+ if ((*Memo.PhysRegs)[i] != "")
+ OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, "
+ << "TII.get(TargetOpcode::COPY), "
+ << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
+ }
+
+ OS << " return FastEmitInst_";
+
+ if (Memo.SubRegNo.empty()) {
+ Operands.PrintManglingSuffix(OS, *Memo.PhysRegs);
+ OS << "(" << InstNS << Memo.Name << ", ";
+ OS << InstNS << Memo.RC->getName() << "RegisterClass";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintArguments(OS, *Memo.PhysRegs);
+ OS << ");\n";
+ } else {
+ OS << "extractsubreg(RetVT, Op0, Op0IsKill, ";
+ OS << Memo.SubRegNo;
+ OS << ");\n";
+ }
+
+ if (HasPred)
+ OS << " }\n";
+ }
+
+ // Return 0 if none of the predicates were satisfied.
+ if (HasPred)
+ OS << " return 0;\n";
+ OS << "}\n";
+ OS << "\n";
+ }
+ }
+
+ // Emit one function for the opcode that demultiplexes based on the type.
+ OS << "unsigned FastEmit_"
+ << getLegalCName(Opcode) << "_";
+ Operands.PrintManglingSuffix(OS);
+ OS << "(MVT VT, MVT RetVT";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintParameters(OS);
+ OS << ") {\n";
+ OS << " switch (VT.SimpleTy) {\n";
+ for (TypeRetPredMap::const_iterator TI = TM.begin(), TE = TM.end();
+ TI != TE; ++TI) {
+ MVT::SimpleValueType VT = TI->first;
+ std::string TypeName = getName(VT);
+ OS << " case " << TypeName << ": return FastEmit_"
+ << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";
+ Operands.PrintManglingSuffix(OS);
+ OS << "(RetVT";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintArguments(OS);
+ OS << ");\n";
+ }
+ OS << " default: return 0;\n";
+ OS << " }\n";
+ OS << "}\n";
+ OS << "\n";
+ }
+
+ OS << "// Top-level FastEmit function.\n";
+ OS << "\n";
+
+ // Emit one function for the operand signature that demultiplexes based
+ // on opcode and type.
+ OS << "unsigned FastEmit_";
+ Operands.PrintManglingSuffix(OS);
+ OS << "(MVT VT, MVT RetVT, unsigned Opcode";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintParameters(OS);
+ OS << ") {\n";
+ OS << " switch (Opcode) {\n";
+ for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end();
+ I != E; ++I) {
+ const std::string &Opcode = I->first;
+
+ OS << " case " << Opcode << ": return FastEmit_"
+ << getLegalCName(Opcode) << "_";
+ Operands.PrintManglingSuffix(OS);
+ OS << "(VT, RetVT";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintArguments(OS);
+ OS << ");\n";
+ }
+ OS << " default: return 0;\n";
+ OS << " }\n";
+ OS << "}\n";
+ OS << "\n";
+ }
+}
+
+void FastISelEmitter::run(raw_ostream &OS) {
+ const CodeGenTarget &Target = CGP.getTargetInfo();
+
+ // Determine the target's namespace name.
+ std::string InstNS = Target.getInstNamespace() + "::";
+ assert(InstNS.size() > 2 && "Can't determine target-specific namespace!");
+
+ EmitSourceFileHeader("\"Fast\" Instruction Selector for the " +
+ Target.getName() + " target", OS);
+
+ FastISelMap F(InstNS);
+ F.CollectPatterns(CGP);
+ F.PrintFunctionDefinitions(OS);
+}
+
+FastISelEmitter::FastISelEmitter(RecordKeeper &R)
+ : Records(R),
+ CGP(R) {
+}
+
diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.h b/contrib/llvm/utils/TableGen/FastISelEmitter.h
new file mode 100644
index 0000000..ce4e77e
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/FastISelEmitter.h
@@ -0,0 +1,39 @@
+//===- FastISelEmitter.h - Generate an instruction selector -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits a "fast" instruction selector.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FASTISEL_EMITTER_H
+#define FASTISEL_EMITTER_H
+
+#include "TableGenBackend.h"
+#include "CodeGenDAGPatterns.h"
+
+namespace llvm {
+
+class CodeGenTarget;
+
+/// FastISelEmitter - The top-level class which coordinates construction
+/// and emission of the instruction selector.
+///
+class FastISelEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ CodeGenDAGPatterns CGP;
+public:
+ explicit FastISelEmitter(RecordKeeper &R);
+
+ // run - Output the isel, returning true on failure.
+ void run(raw_ostream &OS);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp b/contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp
new file mode 100644
index 0000000..47a8474
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/InstrEnumEmitter.cpp
@@ -0,0 +1,48 @@
+//===- InstrEnumEmitter.cpp - Generate Instruction Set Enums --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting enums for each machine
+// instruction.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InstrEnumEmitter.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include <cstdio>
+using namespace llvm;
+
+// runEnums - Print out enum values for all of the instructions.
+void InstrEnumEmitter::run(raw_ostream &OS) {
+ EmitSourceFileHeader("Target Instruction Enum Values", OS);
+ OS << "namespace llvm {\n\n";
+
+ CodeGenTarget Target;
+
+ // We must emit the PHI opcode first...
+ std::string Namespace = Target.getInstNamespace();
+
+ if (Namespace.empty()) {
+ fprintf(stderr, "No instructions defined!\n");
+ exit(1);
+ }
+
+ const std::vector<const CodeGenInstruction*> &NumberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ OS << "namespace " << Namespace << " {\n";
+ OS << " enum {\n";
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ OS << " " << NumberedInstructions[i]->TheDef->getName()
+ << "\t= " << i << ",\n";
+ }
+ OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n";
+ OS << " };\n}\n";
+ OS << "} // End llvm namespace \n";
+}
diff --git a/contrib/llvm/utils/TableGen/InstrEnumEmitter.h b/contrib/llvm/utils/TableGen/InstrEnumEmitter.h
new file mode 100644
index 0000000..89f8b65
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/InstrEnumEmitter.h
@@ -0,0 +1,33 @@
+//===- InstrEnumEmitter.h - Generate Instruction Set Enums ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting enums for each machine
+// instruction.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INSTRENUM_EMITTER_H
+#define INSTRENUM_EMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+
+class InstrEnumEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ InstrEnumEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the instruction set description, returning true on failure.
+ void run(raw_ostream &OS);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
new file mode 100644
index 0000000..4d3aa5e
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -0,0 +1,335 @@
+//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InstrInfoEmitter.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include <algorithm>
+using namespace llvm;
+
+static void PrintDefList(const std::vector<Record*> &Uses,
+ unsigned Num, raw_ostream &OS) {
+ OS << "static const unsigned ImplicitList" << Num << "[] = { ";
+ for (unsigned i = 0, e = Uses.size(); i != e; ++i)
+ OS << getQualifiedName(Uses[i]) << ", ";
+ OS << "0 };\n";
+}
+
+static void PrintBarriers(std::vector<Record*> &Barriers,
+ unsigned Num, raw_ostream &OS) {
+ OS << "static const TargetRegisterClass* Barriers" << Num << "[] = { ";
+ for (unsigned i = 0, e = Barriers.size(); i != e; ++i)
+ OS << "&" << getQualifiedName(Barriers[i]) << "RegClass, ";
+ OS << "NULL };\n";
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction Itinerary Information.
+//===----------------------------------------------------------------------===//
+
+void InstrInfoEmitter::GatherItinClasses() {
+ std::vector<Record*> DefList =
+ Records.getAllDerivedDefinitions("InstrItinClass");
+ std::sort(DefList.begin(), DefList.end(), LessRecord());
+
+ for (unsigned i = 0, N = DefList.size(); i < N; i++)
+ ItinClassMap[DefList[i]->getName()] = i;
+}
+
+unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
+ return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()];
+}
+
+//===----------------------------------------------------------------------===//
+// Operand Info Emission.
+//===----------------------------------------------------------------------===//
+
+std::vector<std::string>
+InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
+ std::vector<std::string> Result;
+
+ for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) {
+ // Handle aggregate operands and normal operands the same way by expanding
+ // either case into a list of operands for this op.
+ std::vector<CodeGenInstruction::OperandInfo> OperandList;
+
+ // This might be a multiple operand thing. Targets like X86 have
+ // registers in their multi-operand operands. It may also be an anonymous
+ // operand, which has a single operand, but no declared class for the
+ // operand.
+ DagInit *MIOI = Inst.OperandList[i].MIOperandInfo;
+
+ if (!MIOI || MIOI->getNumArgs() == 0) {
+ // Single, anonymous, operand.
+ OperandList.push_back(Inst.OperandList[i]);
+ } else {
+ for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) {
+ OperandList.push_back(Inst.OperandList[i]);
+
+ Record *OpR = dynamic_cast<DefInit*>(MIOI->getArg(j))->getDef();
+ OperandList.back().Rec = OpR;
+ }
+ }
+
+ for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
+ Record *OpR = OperandList[j].Rec;
+ std::string Res;
+
+ if (OpR->isSubClassOf("RegisterClass"))
+ Res += getQualifiedName(OpR) + "RegClassID, ";
+ else if (OpR->isSubClassOf("PointerLikeRegClass"))
+ Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", ";
+ else
+ // -1 means the operand does not have a fixed register class.
+ Res += "-1, ";
+
+ // Fill in applicable flags.
+ Res += "0";
+
+ // Ptr value whose register class is resolved via callback.
+ if (OpR->isSubClassOf("PointerLikeRegClass"))
+ Res += "|(1<<TOI::LookupPtrRegClass)";
+
+ // Predicate operands. Check to see if the original unexpanded operand
+ // was of type PredicateOperand.
+ if (Inst.OperandList[i].Rec->isSubClassOf("PredicateOperand"))
+ Res += "|(1<<TOI::Predicate)";
+
+ // Optional def operands. Check to see if the original unexpanded operand
+ // was of type OptionalDefOperand.
+ if (Inst.OperandList[i].Rec->isSubClassOf("OptionalDefOperand"))
+ Res += "|(1<<TOI::OptionalDef)";
+
+ // Fill in constraint info.
+ Res += ", ";
+
+ const CodeGenInstruction::ConstraintInfo &Constraint =
+ Inst.OperandList[i].Constraints[j];
+ if (Constraint.isNone())
+ Res += "0";
+ else if (Constraint.isEarlyClobber())
+ Res += "(1 << TOI::EARLY_CLOBBER)";
+ else {
+ assert(Constraint.isTied());
+ Res += "((" + utostr(Constraint.getTiedOperand()) +
+ " << 16) | (1 << TOI::TIED_TO))";
+ }
+
+ Result.push_back(Res);
+ }
+ }
+
+ return Result;
+}
+
+void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
+ OperandInfoMapTy &OperandInfoIDs) {
+ // ID #0 is for no operand info.
+ unsigned OperandListNum = 0;
+ OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
+
+ OS << "\n";
+ const CodeGenTarget &Target = CDP.getTargetInfo();
+ for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
+ E = Target.inst_end(); II != E; ++II) {
+ std::vector<std::string> OperandInfo = GetOperandInfo(**II);
+ unsigned &N = OperandInfoIDs[OperandInfo];
+ if (N != 0) continue;
+
+ N = ++OperandListNum;
+ OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { ";
+ for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i)
+ OS << "{ " << OperandInfo[i] << " }, ";
+ OS << "};\n";
+ }
+}
+
+void InstrInfoEmitter::DetectRegisterClassBarriers(std::vector<Record*> &Defs,
+ const std::vector<CodeGenRegisterClass> &RCs,
+ std::vector<Record*> &Barriers) {
+ std::set<Record*> DefSet;
+ unsigned NumDefs = Defs.size();
+ for (unsigned i = 0; i < NumDefs; ++i)
+ DefSet.insert(Defs[i]);
+
+ for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
+ const CodeGenRegisterClass &RC = RCs[i];
+ unsigned NumRegs = RC.Elements.size();
+ if (NumRegs > NumDefs)
+ continue; // Can't possibly clobber this RC.
+
+ bool Clobber = true;
+ for (unsigned j = 0; j < NumRegs; ++j) {
+ Record *Reg = RC.Elements[j];
+ if (!DefSet.count(Reg)) {
+ Clobber = false;
+ break;
+ }
+ }
+ if (Clobber)
+ Barriers.push_back(RC.TheDef);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Main Output.
+//===----------------------------------------------------------------------===//
+
+// run - Emit the main instruction description records for the target...
+void InstrInfoEmitter::run(raw_ostream &OS) {
+ GatherItinClasses();
+
+ EmitSourceFileHeader("Target Instruction Descriptors", OS);
+ OS << "namespace llvm {\n\n";
+
+ CodeGenTarget &Target = CDP.getTargetInfo();
+ const std::string &TargetName = Target.getName();
+ Record *InstrInfo = Target.getInstructionSet();
+ const std::vector<CodeGenRegisterClass> &RCs = Target.getRegisterClasses();
+
+ // Keep track of all of the def lists we have emitted already.
+ std::map<std::vector<Record*>, unsigned> EmittedLists;
+ unsigned ListNumber = 0;
+ std::map<std::vector<Record*>, unsigned> EmittedBarriers;
+ unsigned BarrierNumber = 0;
+ std::map<Record*, unsigned> BarriersMap;
+
+ // Emit all of the instruction's implicit uses and defs.
+ for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
+ E = Target.inst_end(); II != E; ++II) {
+ Record *Inst = (*II)->TheDef;
+ std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses");
+ if (!Uses.empty()) {
+ unsigned &IL = EmittedLists[Uses];
+ if (!IL) PrintDefList(Uses, IL = ++ListNumber, OS);
+ }
+ std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs");
+ if (!Defs.empty()) {
+ std::vector<Record*> RCBarriers;
+ DetectRegisterClassBarriers(Defs, RCs, RCBarriers);
+ if (!RCBarriers.empty()) {
+ unsigned &IB = EmittedBarriers[RCBarriers];
+ if (!IB) PrintBarriers(RCBarriers, IB = ++BarrierNumber, OS);
+ BarriersMap.insert(std::make_pair(Inst, IB));
+ }
+
+ unsigned &IL = EmittedLists[Defs];
+ if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS);
+ }
+ }
+
+ OperandInfoMapTy OperandInfoIDs;
+
+ // Emit all of the operand info records.
+ EmitOperandInfo(OS, OperandInfoIDs);
+
+ // Emit all of the TargetInstrDesc records in their ENUM ordering.
+ //
+ OS << "\nstatic const TargetInstrDesc " << TargetName
+ << "Insts[] = {\n";
+ const std::vector<const CodeGenInstruction*> &NumberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i)
+ emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists,
+ BarriersMap, OperandInfoIDs, OS);
+ OS << "};\n";
+ OS << "} // End llvm namespace \n";
+}
+
+void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
+ Record *InstrInfo,
+ std::map<std::vector<Record*>, unsigned> &EmittedLists,
+ std::map<Record*, unsigned> &BarriersMap,
+ const OperandInfoMapTy &OpInfo,
+ raw_ostream &OS) {
+ int MinOperands = 0;
+ if (!Inst.OperandList.empty())
+ // Each logical operand can be multiple MI operands.
+ MinOperands = Inst.OperandList.back().MIOperandNo +
+ Inst.OperandList.back().MINumOperands;
+
+ OS << " { ";
+ OS << Num << ",\t" << MinOperands << ",\t"
+ << Inst.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef)
+ << ",\t\"" << Inst.TheDef->getName() << "\", 0";
+
+ // Emit all of the target indepedent flags...
+ if (Inst.isReturn) OS << "|(1<<TID::Return)";
+ if (Inst.isBranch) OS << "|(1<<TID::Branch)";
+ if (Inst.isIndirectBranch) OS << "|(1<<TID::IndirectBranch)";
+ if (Inst.isCompare) OS << "|(1<<TID::Compare)";
+ if (Inst.isBarrier) OS << "|(1<<TID::Barrier)";
+ if (Inst.hasDelaySlot) OS << "|(1<<TID::DelaySlot)";
+ if (Inst.isCall) OS << "|(1<<TID::Call)";
+ if (Inst.canFoldAsLoad) OS << "|(1<<TID::FoldableAsLoad)";
+ if (Inst.mayLoad) OS << "|(1<<TID::MayLoad)";
+ if (Inst.mayStore) OS << "|(1<<TID::MayStore)";
+ if (Inst.isPredicable) OS << "|(1<<TID::Predicable)";
+ if (Inst.isConvertibleToThreeAddress) OS << "|(1<<TID::ConvertibleTo3Addr)";
+ if (Inst.isCommutable) OS << "|(1<<TID::Commutable)";
+ if (Inst.isTerminator) OS << "|(1<<TID::Terminator)";
+ if (Inst.isReMaterializable) OS << "|(1<<TID::Rematerializable)";
+ if (Inst.isNotDuplicable) OS << "|(1<<TID::NotDuplicable)";
+ if (Inst.hasOptionalDef) OS << "|(1<<TID::HasOptionalDef)";
+ if (Inst.usesCustomInserter) OS << "|(1<<TID::UsesCustomInserter)";
+ if (Inst.isVariadic) OS << "|(1<<TID::Variadic)";
+ if (Inst.hasSideEffects) OS << "|(1<<TID::UnmodeledSideEffects)";
+ if (Inst.isAsCheapAsAMove) OS << "|(1<<TID::CheapAsAMove)";
+ if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<TID::ExtraSrcRegAllocReq)";
+ if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<TID::ExtraDefRegAllocReq)";
+
+ // Emit all of the target-specific flags...
+ BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
+ if (!TSF) throw "no TSFlags?";
+ uint64_t Value = 0;
+ for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) {
+ if (BitInit *Bit = dynamic_cast<BitInit*>(TSF->getBit(i)))
+ Value |= uint64_t(Bit->getValue()) << i;
+ else
+ throw "Invalid TSFlags bit in " + Inst.TheDef->getName();
+ }
+ OS << ", 0x";
+ OS.write_hex(Value);
+ OS << "ULL, ";
+
+ // Emit the implicit uses and defs lists...
+ std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses");
+ if (UseList.empty())
+ OS << "NULL, ";
+ else
+ OS << "ImplicitList" << EmittedLists[UseList] << ", ";
+
+ std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs");
+ if (DefList.empty())
+ OS << "NULL, ";
+ else
+ OS << "ImplicitList" << EmittedLists[DefList] << ", ";
+
+ std::map<Record*, unsigned>::iterator BI = BarriersMap.find(Inst.TheDef);
+ if (BI == BarriersMap.end())
+ OS << "NULL, ";
+ else
+ OS << "Barriers" << BI->second << ", ";
+
+ // Emit the operand info.
+ std::vector<std::string> OperandInfo = GetOperandInfo(Inst);
+ if (OperandInfo.empty())
+ OS << "0";
+ else
+ OS << "OperandInfo" << OpInfo.find(OperandInfo)->second;
+
+ OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
+}
diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.h b/contrib/llvm/utils/TableGen/InstrInfoEmitter.h
new file mode 100644
index 0000000..abb1c6b
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.h
@@ -0,0 +1,66 @@
+//===- InstrInfoEmitter.h - Generate a Instruction Set Desc. ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INSTRINFO_EMITTER_H
+#define INSTRINFO_EMITTER_H
+
+#include "TableGenBackend.h"
+#include "CodeGenDAGPatterns.h"
+#include <vector>
+#include <map>
+
+namespace llvm {
+
+class StringInit;
+class IntInit;
+class ListInit;
+class CodeGenInstruction;
+
+class InstrInfoEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ CodeGenDAGPatterns CDP;
+ std::map<std::string, unsigned> ItinClassMap;
+
+public:
+ InstrInfoEmitter(RecordKeeper &R) : Records(R), CDP(R) { }
+
+ // run - Output the instruction set description, returning true on failure.
+ void run(raw_ostream &OS);
+
+private:
+ typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy;
+
+ void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
+ Record *InstrInfo,
+ std::map<std::vector<Record*>, unsigned> &EL,
+ std::map<Record*, unsigned> &BM,
+ const OperandInfoMapTy &OpInfo,
+ raw_ostream &OS);
+
+ // Itinerary information.
+ void GatherItinClasses();
+ unsigned getItinClassNumber(const Record *InstRec);
+
+ // Operand information.
+ void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
+ std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst);
+
+ void DetectRegisterClassBarriers(std::vector<Record*> &Defs,
+ const std::vector<CodeGenRegisterClass> &RCs,
+ std::vector<Record*> &Barriers);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
new file mode 100644
index 0000000..ba30d97
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -0,0 +1,751 @@
+//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits information about intrinsic functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTarget.h"
+#include "IntrinsicEmitter.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include <algorithm>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// IntrinsicEmitter Implementation
+//===----------------------------------------------------------------------===//
+
+void IntrinsicEmitter::run(raw_ostream &OS) {
+ EmitSourceFileHeader("Intrinsic Function Source Fragment", OS);
+
+ std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
+
+ if (TargetOnly && !Ints.empty())
+ TargetPrefix = Ints[0].TargetPrefix;
+
+ EmitPrefix(OS);
+
+ // Emit the enum information.
+ EmitEnumInfo(Ints, OS);
+
+ // Emit the intrinsic ID -> name table.
+ EmitIntrinsicToNameTable(Ints, OS);
+
+ // Emit the intrinsic ID -> overload table.
+ EmitIntrinsicToOverloadTable(Ints, OS);
+
+ // Emit the function name recognizer.
+ EmitFnNameRecognizer(Ints, OS);
+
+ // Emit the intrinsic verifier.
+ EmitVerifier(Ints, OS);
+
+ // Emit the intrinsic declaration generator.
+ EmitGenerator(Ints, OS);
+
+ // Emit the intrinsic parameter attributes.
+ EmitAttributes(Ints, OS);
+
+ // Emit intrinsic alias analysis mod/ref behavior.
+ EmitModRefBehavior(Ints, OS);
+
+ // Emit a list of intrinsics with corresponding GCC builtins.
+ EmitGCCBuiltinList(Ints, OS);
+
+ // Emit code to translate GCC builtins into LLVM intrinsics.
+ EmitIntrinsicToGCCBuiltinMap(Ints, OS);
+
+ EmitSuffix(OS);
+}
+
+void IntrinsicEmitter::EmitPrefix(raw_ostream &OS) {
+ OS << "// VisualStudio defines setjmp as _setjmp\n"
+ "#if defined(_MSC_VER) && defined(setjmp)\n"
+ "#define setjmp_undefined_for_visual_studio\n"
+ "#undef setjmp\n"
+ "#endif\n\n";
+}
+
+void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
+ OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_visual_studio)\n"
+ "// let's return it to _setjmp state\n"
+ "#define setjmp _setjmp\n"
+ "#endif\n\n";
+}
+
+void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS) {
+ OS << "// Enum values for Intrinsics.h\n";
+ OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ OS << " " << Ints[i].EnumName;
+ OS << ((i != e-1) ? ", " : " ");
+ OS << std::string(40-Ints[i].EnumName.size(), ' ')
+ << "// " << Ints[i].Name << "\n";
+ }
+ OS << "#endif\n\n";
+}
+
+void IntrinsicEmitter::
+EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS) {
+ // Build a function name -> intrinsic name mapping.
+ std::map<std::string, unsigned> IntMapping;
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i)
+ IntMapping[Ints[i].Name] = i;
+
+ OS << "// Function name -> enum value recognizer code.\n";
+ OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
+ OS << " switch (Name[5]) {\n";
+ OS << " default:\n";
+ // Emit the intrinsics in sorted order.
+ char LastChar = 0;
+ for (std::map<std::string, unsigned>::iterator I = IntMapping.begin(),
+ E = IntMapping.end(); I != E; ++I) {
+ if (I->first[5] != LastChar) {
+ LastChar = I->first[5];
+ OS << " break;\n";
+ OS << " case '" << LastChar << "':\n";
+ }
+
+ // For overloaded intrinsics, only the prefix needs to match
+ if (Ints[I->second].isOverloaded)
+ OS << " if (Len > " << I->first.size()
+ << " && !memcmp(Name, \"" << I->first << ".\", "
+ << (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::"
+ << Ints[I->second].EnumName << ";\n";
+ else
+ OS << " if (Len == " << I->first.size()
+ << " && !memcmp(Name, \"" << I->first << "\", "
+ << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::"
+ << Ints[I->second].EnumName << ";\n";
+ }
+ OS << " }\n";
+ OS << "#endif\n\n";
+}
+
+void IntrinsicEmitter::
+EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS) {
+ OS << "// Intrinsic ID to name table\n";
+ OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
+ OS << " // Note that entry #0 is the invalid intrinsic!\n";
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i)
+ OS << " \"" << Ints[i].Name << "\",\n";
+ OS << "#endif\n\n";
+}
+
+void IntrinsicEmitter::
+EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS) {
+ OS << "// Intrinsic ID to overload table\n";
+ OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
+ OS << " // Note that entry #0 is the invalid intrinsic!\n";
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ OS << " ";
+ if (Ints[i].isOverloaded)
+ OS << "true";
+ else
+ OS << "false";
+ OS << ",\n";
+ }
+ OS << "#endif\n\n";
+}
+
+static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
+ if (EVT(VT).isInteger()) {
+ unsigned BitWidth = EVT(VT).getSizeInBits();
+ OS << "IntegerType::get(Context, " << BitWidth << ")";
+ } else if (VT == MVT::Other) {
+ // MVT::OtherVT is used to mean the empty struct type here.
+ OS << "StructType::get(Context)";
+ } else if (VT == MVT::f32) {
+ OS << "Type::getFloatTy(Context)";
+ } else if (VT == MVT::f64) {
+ OS << "Type::getDoubleTy(Context)";
+ } else if (VT == MVT::f80) {
+ OS << "Type::getX86_FP80Ty(Context)";
+ } else if (VT == MVT::f128) {
+ OS << "Type::getFP128Ty(Context)";
+ } else if (VT == MVT::ppcf128) {
+ OS << "Type::getPPC_FP128Ty(Context)";
+ } else if (VT == MVT::isVoid) {
+ OS << "Type::getVoidTy(Context)";
+ } else if (VT == MVT::Metadata) {
+ OS << "Type::getMetadataTy(Context)";
+ } else {
+ assert(false && "Unsupported ValueType!");
+ }
+}
+
+static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
+ unsigned &ArgNo);
+
+static void EmitTypeGenerate(raw_ostream &OS,
+ const std::vector<Record*> &ArgTypes,
+ unsigned &ArgNo) {
+ if (ArgTypes.empty())
+ return EmitTypeForValueType(OS, MVT::isVoid);
+
+ if (ArgTypes.size() == 1)
+ return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
+
+ OS << "StructType::get(Context, ";
+
+ for (std::vector<Record*>::const_iterator
+ I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
+ EmitTypeGenerate(OS, *I, ArgNo);
+ OS << ", ";
+ }
+
+ OS << " NULL)";
+}
+
+static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
+ unsigned &ArgNo) {
+ MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
+
+ if (ArgType->isSubClassOf("LLVMMatchType")) {
+ unsigned Number = ArgType->getValueAsInt("Number");
+ assert(Number < ArgNo && "Invalid matching number!");
+ if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+ OS << "VectorType::getExtendedElementVectorType"
+ << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
+ else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+ OS << "VectorType::getTruncatedElementVectorType"
+ << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
+ else
+ OS << "Tys[" << Number << "]";
+ } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
+ // NOTE: The ArgNo variable here is not the absolute argument number, it is
+ // the index of the "arbitrary" type in the Tys array passed to the
+ // Intrinsic::getDeclaration function. Consequently, we only want to
+ // increment it when we actually hit an overloaded type. Getting this wrong
+ // leads to very subtle bugs!
+ OS << "Tys[" << ArgNo++ << "]";
+ } else if (EVT(VT).isVector()) {
+ EVT VVT = VT;
+ OS << "VectorType::get(";
+ EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
+ OS << ", " << VVT.getVectorNumElements() << ")";
+ } else if (VT == MVT::iPTR) {
+ OS << "PointerType::getUnqual(";
+ EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
+ OS << ")";
+ } else if (VT == MVT::iPTRAny) {
+ // Make sure the user has passed us an argument type to overload. If not,
+ // treat it as an ordinary (not overloaded) intrinsic.
+ OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo
+ << "] : PointerType::getUnqual(";
+ EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
+ OS << ")";
+ ++ArgNo;
+ } else if (VT == MVT::isVoid) {
+ if (ArgNo == 0)
+ OS << "Type::getVoidTy(Context)";
+ else
+ // MVT::isVoid is used to mean varargs here.
+ OS << "...";
+ } else {
+ EmitTypeForValueType(OS, VT);
+ }
+}
+
+/// RecordListComparator - Provide a deterministic comparator for lists of
+/// records.
+namespace {
+ typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair;
+ struct RecordListComparator {
+ bool operator()(const RecPair &LHS,
+ const RecPair &RHS) const {
+ unsigned i = 0;
+ const std::vector<Record*> *LHSVec = &LHS.first;
+ const std::vector<Record*> *RHSVec = &RHS.first;
+ unsigned RHSSize = RHSVec->size();
+ unsigned LHSSize = LHSVec->size();
+
+ for (; i != LHSSize; ++i) {
+ if (i == RHSSize) return false; // RHS is shorter than LHS.
+ if ((*LHSVec)[i] != (*RHSVec)[i])
+ return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
+ }
+
+ if (i != RHSSize) return true;
+
+ i = 0;
+ LHSVec = &LHS.second;
+ RHSVec = &RHS.second;
+ RHSSize = RHSVec->size();
+ LHSSize = LHSVec->size();
+
+ for (i = 0; i != LHSSize; ++i) {
+ if (i == RHSSize) return false; // RHS is shorter than LHS.
+ if ((*LHSVec)[i] != (*RHSVec)[i])
+ return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
+ }
+
+ return i != RHSSize;
+ }
+ };
+}
+
+void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS) {
+ OS << "// Verifier::visitIntrinsicFunctionCall code.\n";
+ OS << "#ifdef GET_INTRINSIC_VERIFIER\n";
+ OS << " switch (ID) {\n";
+ OS << " default: assert(0 && \"Invalid intrinsic!\");\n";
+
+ // This checking can emit a lot of very common code. To reduce the amount of
+ // code that we emit, batch up cases that have identical types. This avoids
+ // problems where GCC can run out of memory compiling Verifier.cpp.
+ typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
+ MapTy UniqueArgInfos;
+
+ // Compute the unique argument type info.
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i)
+ UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
+ Ints[i].IS.ParamTypeDefs)].push_back(i);
+
+ // Loop through the array, emitting one comparison for each batch.
+ for (MapTy::iterator I = UniqueArgInfos.begin(),
+ E = UniqueArgInfos.end(); I != E; ++I) {
+ for (unsigned i = 0, e = I->second.size(); i != e; ++i)
+ OS << " case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
+ << Ints[I->second[i]].Name << "\n";
+
+ const RecPair &ArgTypes = I->first;
+ const std::vector<Record*> &RetTys = ArgTypes.first;
+ const std::vector<Record*> &ParamTys = ArgTypes.second;
+ std::vector<unsigned> OverloadedTypeIndices;
+
+ OS << " VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", "
+ << ParamTys.size();
+
+ // Emit return types.
+ for (unsigned j = 0, je = RetTys.size(); j != je; ++j) {
+ Record *ArgType = RetTys[j];
+ OS << ", ";
+
+ if (ArgType->isSubClassOf("LLVMMatchType")) {
+ unsigned Number = ArgType->getValueAsInt("Number");
+ assert(Number < OverloadedTypeIndices.size() &&
+ "Invalid matching number!");
+ Number = OverloadedTypeIndices[Number];
+ if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+ OS << "~(ExtendedElementVectorType | " << Number << ")";
+ else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+ OS << "~(TruncatedElementVectorType | " << Number << ")";
+ else
+ OS << "~" << Number;
+ } else {
+ MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
+ OS << getEnumName(VT);
+
+ if (EVT(VT).isOverloaded())
+ OverloadedTypeIndices.push_back(j);
+
+ if (VT == MVT::isVoid && j != 0 && j != je - 1)
+ throw "Var arg type not last argument";
+ }
+ }
+
+ // Emit the parameter types.
+ for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) {
+ Record *ArgType = ParamTys[j];
+ OS << ", ";
+
+ if (ArgType->isSubClassOf("LLVMMatchType")) {
+ unsigned Number = ArgType->getValueAsInt("Number");
+ assert(Number < OverloadedTypeIndices.size() &&
+ "Invalid matching number!");
+ Number = OverloadedTypeIndices[Number];
+ if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+ OS << "~(ExtendedElementVectorType | " << Number << ")";
+ else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+ OS << "~(TruncatedElementVectorType | " << Number << ")";
+ else
+ OS << "~" << Number;
+ } else {
+ MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
+ OS << getEnumName(VT);
+
+ if (EVT(VT).isOverloaded())
+ OverloadedTypeIndices.push_back(j + RetTys.size());
+
+ if (VT == MVT::isVoid && j != 0 && j != je - 1)
+ throw "Var arg type not last argument";
+ }
+ }
+
+ OS << ");\n";
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ OS << "#endif\n\n";
+}
+
+void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS) {
+ OS << "// Code for generating Intrinsic function declarations.\n";
+ OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
+ OS << " switch (id) {\n";
+ OS << " default: assert(0 && \"Invalid intrinsic!\");\n";
+
+ // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
+ // types.
+ typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
+ MapTy UniqueArgInfos;
+
+ // Compute the unique argument type info.
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i)
+ UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
+ Ints[i].IS.ParamTypeDefs)].push_back(i);
+
+ // Loop through the array, emitting one generator for each batch.
+ std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
+
+ for (MapTy::iterator I = UniqueArgInfos.begin(),
+ E = UniqueArgInfos.end(); I != E; ++I) {
+ for (unsigned i = 0, e = I->second.size(); i != e; ++i)
+ OS << " case " << IntrinsicStr << Ints[I->second[i]].EnumName
+ << ":\t\t// " << Ints[I->second[i]].Name << "\n";
+
+ const RecPair &ArgTypes = I->first;
+ const std::vector<Record*> &RetTys = ArgTypes.first;
+ const std::vector<Record*> &ParamTys = ArgTypes.second;
+
+ unsigned N = ParamTys.size();
+
+ if (N > 1 &&
+ getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
+ OS << " IsVarArg = true;\n";
+ --N;
+ }
+
+ unsigned ArgNo = 0;
+ OS << " ResultTy = ";
+ EmitTypeGenerate(OS, RetTys, ArgNo);
+ OS << ";\n";
+
+ for (unsigned j = 0; j != N; ++j) {
+ OS << " ArgTys.push_back(";
+ EmitTypeGenerate(OS, ParamTys[j], ArgNo);
+ OS << ");\n";
+ }
+
+ OS << " break;\n";
+ }
+
+ OS << " }\n";
+ OS << "#endif\n\n";
+}
+
+/// EmitAttributes - This emits the Intrinsic::getAttributes method.
+void IntrinsicEmitter::
+EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
+ OS << "// Add parameter attributes that are not common to all intrinsics.\n";
+ OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
+ if (TargetOnly)
+ OS << "static AttrListPtr getAttributes(" << TargetPrefix
+ << "Intrinsic::ID id) {";
+ else
+ OS << "AttrListPtr Intrinsic::getAttributes(ID id) {";
+ OS << " // No intrinsic can throw exceptions.\n";
+ OS << " Attributes Attr = Attribute::NoUnwind;\n";
+ OS << " switch (id) {\n";
+ OS << " default: break;\n";
+ unsigned MaxArgAttrs = 0;
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ MaxArgAttrs =
+ std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size()));
+ switch (Ints[i].ModRef) {
+ default: break;
+ case CodeGenIntrinsic::NoMem:
+ OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
+ << ":\n";
+ break;
+ }
+ }
+ OS << " Attr |= Attribute::ReadNone; // These do not access memory.\n";
+ OS << " break;\n";
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ switch (Ints[i].ModRef) {
+ default: break;
+ case CodeGenIntrinsic::ReadArgMem:
+ case CodeGenIntrinsic::ReadMem:
+ OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
+ << ":\n";
+ break;
+ }
+ }
+ OS << " Attr |= Attribute::ReadOnly; // These do not write memory.\n";
+ OS << " break;\n";
+ OS << " }\n";
+ OS << " AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n";
+ OS << " unsigned NumAttrs = 0;\n";
+ OS << " switch (id) {\n";
+ OS << " default: break;\n";
+
+ // Add argument attributes for any intrinsics that have them.
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ if (Ints[i].ArgumentAttributes.empty()) continue;
+
+ OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
+ << ":\n";
+
+ std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs =
+ Ints[i].ArgumentAttributes;
+ // Sort by argument index.
+ std::sort(ArgAttrs.begin(), ArgAttrs.end());
+
+ unsigned NumArgsWithAttrs = 0;
+
+ while (!ArgAttrs.empty()) {
+ unsigned ArgNo = ArgAttrs[0].first;
+
+ OS << " AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get("
+ << ArgNo+1 << ", 0";
+
+ while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) {
+ switch (ArgAttrs[0].second) {
+ default: assert(0 && "Unknown arg attribute");
+ case CodeGenIntrinsic::NoCapture:
+ OS << "|Attribute::NoCapture";
+ break;
+ }
+ ArgAttrs.erase(ArgAttrs.begin());
+ }
+ OS << ");\n";
+ }
+
+ OS << " NumAttrs = " << NumArgsWithAttrs << ";\n";
+ OS << " break;\n";
+ }
+
+ OS << " }\n";
+ OS << " AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n";
+ OS << " return AttrListPtr::get(AWI, NumAttrs+1);\n";
+ OS << "}\n";
+ OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
+}
+
+/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior.
+void IntrinsicEmitter::
+EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
+ OS << "// Determine intrinsic alias analysis mod/ref behavior.\n";
+ OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n";
+ OS << "switch (iid) {\n";
+ OS << "default:\n return UnknownModRefBehavior;\n";
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ if (Ints[i].ModRef == CodeGenIntrinsic::ReadWriteMem)
+ continue;
+ OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
+ << ":\n";
+ switch (Ints[i].ModRef) {
+ default:
+ assert(false && "Unknown Mod/Ref type!");
+ case CodeGenIntrinsic::NoMem:
+ OS << " return DoesNotAccessMemory;\n";
+ break;
+ case CodeGenIntrinsic::ReadArgMem:
+ case CodeGenIntrinsic::ReadMem:
+ OS << " return OnlyReadsMemory;\n";
+ break;
+ case CodeGenIntrinsic::ReadWriteArgMem:
+ OS << " return AccessesArguments;\n";
+ break;
+ }
+ }
+ OS << "}\n";
+ OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n";
+}
+
+void IntrinsicEmitter::
+EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
+ OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n";
+ OS << "#ifdef GET_GCC_BUILTIN_NAME\n";
+ OS << " switch (F->getIntrinsicID()) {\n";
+ OS << " default: BuiltinName = \"\"; break;\n";
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ if (!Ints[i].GCCBuiltinName.empty()) {
+ OS << " case Intrinsic::" << Ints[i].EnumName << ": BuiltinName = \""
+ << Ints[i].GCCBuiltinName << "\"; break;\n";
+ }
+ }
+ OS << " }\n";
+ OS << "#endif\n\n";
+}
+
+/// EmitBuiltinComparisons - Emit comparisons to determine whether the specified
+/// sorted range of builtin names is equal to the current builtin. This breaks
+/// it down into a simple tree.
+///
+/// At this point, we know that all the builtins in the range have the same name
+/// for the first 'CharStart' characters. Only the end of the name needs to be
+/// discriminated.
+typedef std::map<std::string, std::string>::const_iterator StrMapIterator;
+static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
+ unsigned CharStart, unsigned Indent,
+ std::string TargetPrefix, raw_ostream &OS) {
+ if (Start == End) return; // empty range.
+
+ // Determine what, if anything, is the same about all these strings.
+ std::string CommonString = Start->first;
+ unsigned NumInRange = 0;
+ for (StrMapIterator I = Start; I != End; ++I, ++NumInRange) {
+ // Find the first character that doesn't match.
+ const std::string &ThisStr = I->first;
+ unsigned NonMatchChar = CharStart;
+ while (NonMatchChar < CommonString.size() &&
+ NonMatchChar < ThisStr.size() &&
+ CommonString[NonMatchChar] == ThisStr[NonMatchChar])
+ ++NonMatchChar;
+ // Truncate off pieces that don't match.
+ CommonString.resize(NonMatchChar);
+ }
+
+ // Just compare the rest of the string.
+ if (NumInRange == 1) {
+ if (CharStart != CommonString.size()) {
+ OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName";
+ if (CharStart) OS << "+" << CharStart;
+ OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
+ OS << CommonString.size() - CharStart << "))\n";
+ ++Indent;
+ }
+ OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix
+ << "Intrinsic::";
+ OS << Start->second << ";\n";
+ return;
+ }
+
+ // At this point, we potentially have a common prefix for these builtins, emit
+ // a check for this common prefix.
+ if (CommonString.size() != CharStart) {
+ OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName";
+ if (CharStart) OS << "+" << CharStart;
+ OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
+ OS << CommonString.size()-CharStart << ")) {\n";
+
+ EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1,
+ TargetPrefix, OS);
+ OS << std::string(Indent*2, ' ') << "}\n";
+ return;
+ }
+
+ // Output a switch on the character that differs across the set.
+ OS << std::string(Indent*2, ' ') << "switch (BuiltinName[" << CharStart
+ << "]) {";
+ if (CharStart)
+ OS << " // \"" << std::string(Start->first.begin(),
+ Start->first.begin()+CharStart) << "\"";
+ OS << "\n";
+
+ for (StrMapIterator I = Start; I != End; ) {
+ char ThisChar = I->first[CharStart];
+ OS << std::string(Indent*2, ' ') << "case '" << ThisChar << "':\n";
+ // Figure out the range that has this common character.
+ StrMapIterator NextChar = I;
+ for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar;
+ ++NextChar)
+ /*empty*/;
+ EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS);
+ OS << std::string(Indent*2, ' ') << " break;\n";
+ I = NextChar;
+ }
+ OS << std::string(Indent*2, ' ') << "}\n";
+}
+
+/// EmitTargetBuiltins - All of the builtins in the specified map are for the
+/// same target, and we already checked it.
+static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
+ const std::string &TargetPrefix,
+ raw_ostream &OS) {
+ // Rearrange the builtins by length.
+ std::vector<std::map<std::string, std::string> > BuiltinsByLen;
+ BuiltinsByLen.reserve(100);
+
+ for (StrMapIterator I = BIM.begin(), E = BIM.end(); I != E; ++I) {
+ if (I->first.size() >= BuiltinsByLen.size())
+ BuiltinsByLen.resize(I->first.size()+1);
+ BuiltinsByLen[I->first.size()].insert(*I);
+ }
+
+ // Now that we have all the builtins by their length, emit a switch stmt.
+ OS << " switch (strlen(BuiltinName)) {\n";
+ OS << " default: break;\n";
+ for (unsigned i = 0, e = BuiltinsByLen.size(); i != e; ++i) {
+ if (BuiltinsByLen[i].empty()) continue;
+ OS << " case " << i << ":\n";
+ EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(),
+ 0, 3, TargetPrefix, OS);
+ OS << " break;\n";
+ }
+ OS << " }\n";
+}
+
+
+void IntrinsicEmitter::
+EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS) {
+ typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
+ BIMTy BuiltinMap;
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ if (!Ints[i].GCCBuiltinName.empty()) {
+ // Get the map for this target prefix.
+ std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix];
+
+ if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
+ Ints[i].EnumName)).second)
+ throw "Intrinsic '" + Ints[i].TheDef->getName() +
+ "': duplicate GCC builtin name!";
+ }
+ }
+
+ OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n";
+ OS << "// This is used by the C front-end. The GCC builtin name is passed\n";
+ OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
+ OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n";
+ OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
+
+ if (TargetOnly) {
+ OS << "static " << TargetPrefix << "Intrinsic::ID "
+ << "getIntrinsicForGCCBuiltin(const char "
+ << "*TargetPrefix, const char *BuiltinName) {\n";
+ OS << " " << TargetPrefix << "Intrinsic::ID IntrinsicID = ";
+ } else {
+ OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
+ << "*TargetPrefix, const char *BuiltinName) {\n";
+ OS << " Intrinsic::ID IntrinsicID = ";
+ }
+
+ if (TargetOnly)
+ OS << "(" << TargetPrefix<< "Intrinsic::ID)";
+
+ OS << "Intrinsic::not_intrinsic;\n";
+
+ // Note: this could emit significantly better code if we cared.
+ for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
+ OS << " ";
+ if (!I->first.empty())
+ OS << "if (!strcmp(TargetPrefix, \"" << I->first << "\")) ";
+ else
+ OS << "/* Target Independent Builtins */ ";
+ OS << "{\n";
+
+ // Emit the comparisons for this target prefix.
+ EmitTargetBuiltins(I->second, TargetPrefix, OS);
+ OS << " }\n";
+ }
+ OS << " return IntrinsicID;\n";
+ OS << "}\n";
+ OS << "#endif\n\n";
+}
diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.h b/contrib/llvm/utils/TableGen/IntrinsicEmitter.h
new file mode 100644
index 0000000..b1efecb
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.h
@@ -0,0 +1,63 @@
+//===- IntrinsicEmitter.h - Generate intrinsic information ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits information about intrinsic functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INTRINSIC_EMITTER_H
+#define INTRINSIC_EMITTER_H
+
+#include "CodeGenIntrinsics.h"
+#include "TableGenBackend.h"
+
+namespace llvm {
+ class IntrinsicEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ bool TargetOnly;
+ std::string TargetPrefix;
+
+ public:
+ IntrinsicEmitter(RecordKeeper &R, bool T = false)
+ : Records(R), TargetOnly(T) {}
+
+ void run(raw_ostream &OS);
+
+ void EmitPrefix(raw_ostream &OS);
+
+ void EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS);
+
+ void EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS);
+ void EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS);
+ void EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS);
+ void EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS);
+ void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS);
+ void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS);
+ void EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS);
+ void EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS);
+ void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
+ raw_ostream &OS);
+ void EmitSuffix(raw_ostream &OS);
+ };
+
+} // End llvm namespace
+
+#endif
+
+
+
diff --git a/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp b/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp
new file mode 100644
index 0000000..8b81e14
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -0,0 +1,3110 @@
+//===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting LLVMC configuration code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LLVMCConfigurationEmitter.h"
+#include "Record.h"
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
+
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <stdexcept>
+#include <string>
+#include <typeinfo>
+
+using namespace llvm;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+/// Typedefs
+
+typedef std::vector<Record*> RecordVector;
+typedef std::vector<const DagInit*> DagVector;
+typedef std::vector<std::string> StrVector;
+
+//===----------------------------------------------------------------------===//
+/// Constants
+
+// Indentation.
+const unsigned TabWidth = 4;
+const unsigned Indent1 = TabWidth*1;
+const unsigned Indent2 = TabWidth*2;
+const unsigned Indent3 = TabWidth*3;
+const unsigned Indent4 = TabWidth*4;
+
+// Default help string.
+const char * const DefaultHelpString = "NO HELP MESSAGE PROVIDED";
+
+// Name for the "sink" option.
+const char * const SinkOptionName = "SinkOption";
+
+//===----------------------------------------------------------------------===//
+/// Helper functions
+
+/// Id - An 'identity' function object.
+struct Id {
+ template<typename T0>
+ void operator()(const T0&) const {
+ }
+ template<typename T0, typename T1>
+ void operator()(const T0&, const T1&) const {
+ }
+ template<typename T0, typename T1, typename T2>
+ void operator()(const T0&, const T1&, const T2&) const {
+ }
+};
+
+int InitPtrToInt(const Init* ptr) {
+ const IntInit& val = dynamic_cast<const IntInit&>(*ptr);
+ return val.getValue();
+}
+
+const std::string& InitPtrToString(const Init* ptr) {
+ const StringInit& val = dynamic_cast<const StringInit&>(*ptr);
+ return val.getValue();
+}
+
+const ListInit& InitPtrToList(const Init* ptr) {
+ const ListInit& val = dynamic_cast<const ListInit&>(*ptr);
+ return val;
+}
+
+const DagInit& InitPtrToDag(const Init* ptr) {
+ const DagInit& val = dynamic_cast<const DagInit&>(*ptr);
+ return val;
+}
+
+const std::string GetOperatorName(const DagInit& D) {
+ return D.getOperator()->getAsString();
+}
+
+/// CheckBooleanConstant - Check that the provided value is a boolean constant.
+void CheckBooleanConstant(const Init* I) {
+ const DefInit& val = dynamic_cast<const DefInit&>(*I);
+ const std::string& str = val.getAsString();
+
+ if (str != "true" && str != "false") {
+ throw "Incorrect boolean value: '" + str +
+ "': must be either 'true' or 'false'";
+ }
+}
+
+// CheckNumberOfArguments - Ensure that the number of args in d is
+// greater than or equal to min_arguments, otherwise throw an exception.
+void CheckNumberOfArguments (const DagInit& d, unsigned minArgs) {
+ if (d.getNumArgs() < minArgs)
+ throw GetOperatorName(d) + ": too few arguments!";
+}
+
+// EscapeVariableName - Escape commas and other symbols not allowed
+// in the C++ variable names. Makes it possible to use options named
+// like "Wa," (useful for prefix options).
+std::string EscapeVariableName (const std::string& Var) {
+ std::string ret;
+ for (unsigned i = 0; i != Var.size(); ++i) {
+ char cur_char = Var[i];
+ if (cur_char == ',') {
+ ret += "_comma_";
+ }
+ else if (cur_char == '+') {
+ ret += "_plus_";
+ }
+ else if (cur_char == '-') {
+ ret += "_dash_";
+ }
+ else {
+ ret.push_back(cur_char);
+ }
+ }
+ return ret;
+}
+
+/// EscapeQuotes - Replace '"' with '\"'.
+std::string EscapeQuotes (const std::string& Var) {
+ std::string ret;
+ for (unsigned i = 0; i != Var.size(); ++i) {
+ char cur_char = Var[i];
+ if (cur_char == '"') {
+ ret += "\\\"";
+ }
+ else {
+ ret.push_back(cur_char);
+ }
+ }
+ return ret;
+}
+
+/// OneOf - Does the input string contain this character?
+bool OneOf(const char* lst, char c) {
+ while (*lst) {
+ if (*lst++ == c)
+ return true;
+ }
+ return false;
+}
+
+template <class I, class S>
+void CheckedIncrement(I& P, I E, S ErrorString) {
+ ++P;
+ if (P == E)
+ throw ErrorString;
+}
+
+// apply is needed because C++'s syntax doesn't let us construct a function
+// object and call it in the same statement.
+template<typename F, typename T0>
+void apply(F Fun, T0& Arg0) {
+ return Fun(Arg0);
+}
+
+template<typename F, typename T0, typename T1>
+void apply(F Fun, T0& Arg0, T1& Arg1) {
+ return Fun(Arg0, Arg1);
+}
+
+//===----------------------------------------------------------------------===//
+/// Back-end specific code
+
+
+/// OptionType - One of six different option types. See the
+/// documentation for detailed description of differences.
+namespace OptionType {
+
+ enum OptionType { Alias, Switch, SwitchList,
+ Parameter, ParameterList, Prefix, PrefixList };
+
+ bool IsAlias(OptionType t) {
+ return (t == Alias);
+ }
+
+ bool IsList (OptionType t) {
+ return (t == SwitchList || t == ParameterList || t == PrefixList);
+ }
+
+ bool IsSwitch (OptionType t) {
+ return (t == Switch);
+ }
+
+ bool IsSwitchList (OptionType t) {
+ return (t == SwitchList);
+ }
+
+ bool IsParameter (OptionType t) {
+ return (t == Parameter || t == Prefix);
+ }
+
+}
+
+OptionType::OptionType stringToOptionType(const std::string& T) {
+ if (T == "alias_option")
+ return OptionType::Alias;
+ else if (T == "switch_option")
+ return OptionType::Switch;
+ else if (T == "switch_list_option")
+ return OptionType::SwitchList;
+ else if (T == "parameter_option")
+ return OptionType::Parameter;
+ else if (T == "parameter_list_option")
+ return OptionType::ParameterList;
+ else if (T == "prefix_option")
+ return OptionType::Prefix;
+ else if (T == "prefix_list_option")
+ return OptionType::PrefixList;
+ else
+ throw "Unknown option type: " + T + '!';
+}
+
+namespace OptionDescriptionFlags {
+ enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
+ ReallyHidden = 0x4, OneOrMore = 0x8,
+ Optional = 0x10, CommaSeparated = 0x20,
+ ForwardNotSplit = 0x40, ZeroOrMore = 0x80 };
+}
+
+/// OptionDescription - Represents data contained in a single
+/// OptionList entry.
+struct OptionDescription {
+ OptionType::OptionType Type;
+ std::string Name;
+ unsigned Flags;
+ std::string Help;
+ unsigned MultiVal;
+ Init* InitVal;
+
+ OptionDescription(OptionType::OptionType t = OptionType::Switch,
+ const std::string& n = "",
+ const std::string& h = DefaultHelpString)
+ : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)
+ {}
+
+ /// GenTypeDeclaration - Returns the C++ variable type of this
+ /// option.
+ const char* GenTypeDeclaration() const;
+
+ /// GenVariableName - Returns the variable name used in the
+ /// generated C++ code.
+ std::string GenVariableName() const
+ { return "autogenerated::" + GenOptionType() + EscapeVariableName(Name); }
+
+ /// GenPlainVariableName - Returns the variable name without the namespace
+ /// prefix.
+ std::string GenPlainVariableName() const
+ { return GenOptionType() + EscapeVariableName(Name); }
+
+ /// Merge - Merge two option descriptions.
+ void Merge (const OptionDescription& other);
+
+ /// CheckConsistency - Check that the flags are consistent.
+ void CheckConsistency() const;
+
+ // Misc convenient getters/setters.
+
+ bool isAlias() const;
+
+ bool isMultiVal() const;
+
+ bool isCommaSeparated() const;
+ void setCommaSeparated();
+
+ bool isForwardNotSplit() const;
+ void setForwardNotSplit();
+
+ bool isRequired() const;
+ void setRequired();
+
+ bool isOneOrMore() const;
+ void setOneOrMore();
+
+ bool isZeroOrMore() const;
+ void setZeroOrMore();
+
+ bool isOptional() const;
+ void setOptional();
+
+ bool isHidden() const;
+ void setHidden();
+
+ bool isReallyHidden() const;
+ void setReallyHidden();
+
+ bool isSwitch() const
+ { return OptionType::IsSwitch(this->Type); }
+
+ bool isSwitchList() const
+ { return OptionType::IsSwitchList(this->Type); }
+
+ bool isParameter() const
+ { return OptionType::IsParameter(this->Type); }
+
+ bool isList() const
+ { return OptionType::IsList(this->Type); }
+
+ bool isParameterList() const
+ { return (OptionType::IsList(this->Type)
+ && !OptionType::IsSwitchList(this->Type)); }
+
+private:
+
+ // GenOptionType - Helper function used by GenVariableName().
+ std::string GenOptionType() const;
+};
+
+void OptionDescription::CheckConsistency() const {
+ unsigned i = 0;
+
+ i += this->isRequired();
+ i += this->isOptional();
+ i += this->isOneOrMore();
+ i += this->isZeroOrMore();
+
+ if (i > 1) {
+ throw "Only one of (required), (optional), (one_or_more) or "
+ "(zero_or_more) properties is allowed!";
+ }
+}
+
+void OptionDescription::Merge (const OptionDescription& other)
+{
+ if (other.Type != Type)
+ throw "Conflicting definitions for the option " + Name + "!";
+
+ if (Help == other.Help || Help == DefaultHelpString)
+ Help = other.Help;
+ else if (other.Help != DefaultHelpString) {
+ llvm::errs() << "Warning: several different help strings"
+ " defined for option " + Name + "\n";
+ }
+
+ Flags |= other.Flags;
+}
+
+bool OptionDescription::isAlias() const {
+ return OptionType::IsAlias(this->Type);
+}
+
+bool OptionDescription::isMultiVal() const {
+ return MultiVal > 1;
+}
+
+bool OptionDescription::isCommaSeparated() const {
+ return Flags & OptionDescriptionFlags::CommaSeparated;
+}
+void OptionDescription::setCommaSeparated() {
+ Flags |= OptionDescriptionFlags::CommaSeparated;
+}
+
+bool OptionDescription::isForwardNotSplit() const {
+ return Flags & OptionDescriptionFlags::ForwardNotSplit;
+}
+void OptionDescription::setForwardNotSplit() {
+ Flags |= OptionDescriptionFlags::ForwardNotSplit;
+}
+
+bool OptionDescription::isRequired() const {
+ return Flags & OptionDescriptionFlags::Required;
+}
+void OptionDescription::setRequired() {
+ Flags |= OptionDescriptionFlags::Required;
+}
+
+bool OptionDescription::isOneOrMore() const {
+ return Flags & OptionDescriptionFlags::OneOrMore;
+}
+void OptionDescription::setOneOrMore() {
+ Flags |= OptionDescriptionFlags::OneOrMore;
+}
+
+bool OptionDescription::isZeroOrMore() const {
+ return Flags & OptionDescriptionFlags::ZeroOrMore;
+}
+void OptionDescription::setZeroOrMore() {
+ Flags |= OptionDescriptionFlags::ZeroOrMore;
+}
+
+bool OptionDescription::isOptional() const {
+ return Flags & OptionDescriptionFlags::Optional;
+}
+void OptionDescription::setOptional() {
+ Flags |= OptionDescriptionFlags::Optional;
+}
+
+bool OptionDescription::isHidden() const {
+ return Flags & OptionDescriptionFlags::Hidden;
+}
+void OptionDescription::setHidden() {
+ Flags |= OptionDescriptionFlags::Hidden;
+}
+
+bool OptionDescription::isReallyHidden() const {
+ return Flags & OptionDescriptionFlags::ReallyHidden;
+}
+void OptionDescription::setReallyHidden() {
+ Flags |= OptionDescriptionFlags::ReallyHidden;
+}
+
+const char* OptionDescription::GenTypeDeclaration() const {
+ switch (Type) {
+ case OptionType::Alias:
+ return "cl::alias";
+ case OptionType::PrefixList:
+ case OptionType::ParameterList:
+ return "cl::list<std::string>";
+ case OptionType::Switch:
+ return "cl::opt<bool>";
+ case OptionType::SwitchList:
+ return "cl::list<bool>";
+ case OptionType::Parameter:
+ case OptionType::Prefix:
+ default:
+ return "cl::opt<std::string>";
+ }
+}
+
+std::string OptionDescription::GenOptionType() const {
+ switch (Type) {
+ case OptionType::Alias:
+ return "Alias_";
+ case OptionType::PrefixList:
+ case OptionType::ParameterList:
+ return "List_";
+ case OptionType::Switch:
+ return "Switch_";
+ case OptionType::SwitchList:
+ return "SwitchList_";
+ case OptionType::Prefix:
+ case OptionType::Parameter:
+ default:
+ return "Parameter_";
+ }
+}
+
+/// OptionDescriptions - An OptionDescription array plus some helper
+/// functions.
+class OptionDescriptions {
+ typedef StringMap<OptionDescription> container_type;
+
+ /// Descriptions - A list of OptionDescriptions.
+ container_type Descriptions;
+
+public:
+ /// FindOption - exception-throwing wrapper for find().
+ const OptionDescription& FindOption(const std::string& OptName) const;
+
+ // Wrappers for FindOption that throw an exception in case the option has a
+ // wrong type.
+ const OptionDescription& FindSwitch(const std::string& OptName) const;
+ const OptionDescription& FindParameter(const std::string& OptName) const;
+ const OptionDescription& FindParameterList(const std::string& OptName) const;
+ const OptionDescription&
+ FindListOrParameter(const std::string& OptName) const;
+ const OptionDescription&
+ FindParameterListOrParameter(const std::string& OptName) const;
+
+ /// insertDescription - Insert new OptionDescription into
+ /// OptionDescriptions list
+ void InsertDescription (const OptionDescription& o);
+
+ // Support for STL-style iteration
+ typedef container_type::const_iterator const_iterator;
+ const_iterator begin() const { return Descriptions.begin(); }
+ const_iterator end() const { return Descriptions.end(); }
+};
+
+const OptionDescription&
+OptionDescriptions::FindOption(const std::string& OptName) const {
+ const_iterator I = Descriptions.find(OptName);
+ if (I != Descriptions.end())
+ return I->second;
+ else
+ throw OptName + ": no such option!";
+}
+
+const OptionDescription&
+OptionDescriptions::FindSwitch(const std::string& OptName) const {
+ const OptionDescription& OptDesc = this->FindOption(OptName);
+ if (!OptDesc.isSwitch())
+ throw OptName + ": incorrect option type - should be a switch!";
+ return OptDesc;
+}
+
+const OptionDescription&
+OptionDescriptions::FindParameterList(const std::string& OptName) const {
+ const OptionDescription& OptDesc = this->FindOption(OptName);
+ if (!OptDesc.isList() || OptDesc.isSwitchList())
+ throw OptName + ": incorrect option type - should be a parameter list!";
+ return OptDesc;
+}
+
+const OptionDescription&
+OptionDescriptions::FindParameter(const std::string& OptName) const {
+ const OptionDescription& OptDesc = this->FindOption(OptName);
+ if (!OptDesc.isParameter())
+ throw OptName + ": incorrect option type - should be a parameter!";
+ return OptDesc;
+}
+
+const OptionDescription&
+OptionDescriptions::FindListOrParameter(const std::string& OptName) const {
+ const OptionDescription& OptDesc = this->FindOption(OptName);
+ if (!OptDesc.isList() && !OptDesc.isParameter())
+ throw OptName
+ + ": incorrect option type - should be a list or parameter!";
+ return OptDesc;
+}
+
+const OptionDescription&
+OptionDescriptions::FindParameterListOrParameter
+(const std::string& OptName) const {
+ const OptionDescription& OptDesc = this->FindOption(OptName);
+ if ((!OptDesc.isList() && !OptDesc.isParameter()) || OptDesc.isSwitchList())
+ throw OptName
+ + ": incorrect option type - should be a parameter list or parameter!";
+ return OptDesc;
+}
+
+void OptionDescriptions::InsertDescription (const OptionDescription& o) {
+ container_type::iterator I = Descriptions.find(o.Name);
+ if (I != Descriptions.end()) {
+ OptionDescription& D = I->second;
+ D.Merge(o);
+ }
+ else {
+ Descriptions[o.Name] = o;
+ }
+}
+
+/// HandlerTable - A base class for function objects implemented as
+/// 'tables of handlers'.
+template <typename Handler>
+class HandlerTable {
+protected:
+ // Implementation details.
+
+ /// HandlerMap - A map from property names to property handlers
+ typedef StringMap<Handler> HandlerMap;
+
+ static HandlerMap Handlers_;
+ static bool staticMembersInitialized_;
+
+public:
+
+ Handler GetHandler (const std::string& HandlerName) const {
+ typename HandlerMap::iterator method = Handlers_.find(HandlerName);
+
+ if (method != Handlers_.end()) {
+ Handler h = method->second;
+ return h;
+ }
+ else {
+ throw "No handler found for property " + HandlerName + "!";
+ }
+ }
+
+ void AddHandler(const char* Property, Handler H) {
+ Handlers_[Property] = H;
+ }
+
+};
+
+template <class Handler, class FunctionObject>
+Handler GetHandler(FunctionObject* Obj, const DagInit& Dag) {
+ const std::string& HandlerName = GetOperatorName(Dag);
+ return Obj->GetHandler(HandlerName);
+}
+
+template <class FunctionObject>
+void InvokeDagInitHandler(FunctionObject* Obj, Init* I) {
+ typedef void (FunctionObject::*Handler) (const DagInit&);
+
+ const DagInit& Dag = InitPtrToDag(I);
+ Handler h = GetHandler<Handler>(Obj, Dag);
+
+ ((Obj)->*(h))(Dag);
+}
+
+template <class FunctionObject>
+void InvokeDagInitHandler(const FunctionObject* const Obj,
+ const Init* I, unsigned IndentLevel, raw_ostream& O)
+{
+ typedef void (FunctionObject::*Handler)
+ (const DagInit&, unsigned IndentLevel, raw_ostream& O) const;
+
+ const DagInit& Dag = InitPtrToDag(I);
+ Handler h = GetHandler<Handler>(Obj, Dag);
+
+ ((Obj)->*(h))(Dag, IndentLevel, O);
+}
+
+template <typename H>
+typename HandlerTable<H>::HandlerMap HandlerTable<H>::Handlers_;
+
+template <typename H>
+bool HandlerTable<H>::staticMembersInitialized_ = false;
+
+
+/// CollectOptionProperties - Function object for iterating over an
+/// option property list.
+class CollectOptionProperties;
+typedef void (CollectOptionProperties::* CollectOptionPropertiesHandler)
+(const DagInit&);
+
+class CollectOptionProperties
+: public HandlerTable<CollectOptionPropertiesHandler>
+{
+private:
+
+ /// optDescs_ - OptionDescriptions table. This is where the
+ /// information is stored.
+ OptionDescription& optDesc_;
+
+public:
+
+ explicit CollectOptionProperties(OptionDescription& OD)
+ : optDesc_(OD)
+ {
+ if (!staticMembersInitialized_) {
+ AddHandler("help", &CollectOptionProperties::onHelp);
+ AddHandler("hidden", &CollectOptionProperties::onHidden);
+ AddHandler("init", &CollectOptionProperties::onInit);
+ AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
+ AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
+ AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore);
+ AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
+ AddHandler("required", &CollectOptionProperties::onRequired);
+ AddHandler("optional", &CollectOptionProperties::onOptional);
+ AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated);
+ AddHandler("forward_not_split",
+ &CollectOptionProperties::onForwardNotSplit);
+
+ staticMembersInitialized_ = true;
+ }
+ }
+
+ /// operator() - Just forwards to the corresponding property
+ /// handler.
+ void operator() (Init* I) {
+ InvokeDagInitHandler(this, I);
+ }
+
+private:
+
+ /// Option property handlers --
+ /// Methods that handle option properties such as (help) or (hidden).
+
+ void onHelp (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ optDesc_.Help = EscapeQuotes(InitPtrToString(d.getArg(0)));
+ }
+
+ void onHidden (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+ optDesc_.setHidden();
+ }
+
+ void onReallyHidden (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+ optDesc_.setReallyHidden();
+ }
+
+ void onCommaSeparated (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+ if (!optDesc_.isParameterList())
+ throw "'comma_separated' is valid only on parameter list options!";
+ optDesc_.setCommaSeparated();
+ }
+
+ void onForwardNotSplit (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+ if (!optDesc_.isParameter())
+ throw "'forward_not_split' is valid only for parameter options!";
+ optDesc_.setForwardNotSplit();
+ }
+
+ void onRequired (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+
+ optDesc_.setRequired();
+ optDesc_.CheckConsistency();
+ }
+
+ void onInit (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ Init* i = d.getArg(0);
+ const std::string& str = i->getAsString();
+
+ bool correct = optDesc_.isParameter() && dynamic_cast<StringInit*>(i);
+ correct |= (optDesc_.isSwitch() && (str == "true" || str == "false"));
+
+ if (!correct)
+ throw "Incorrect usage of the 'init' option property!";
+
+ optDesc_.InitVal = i;
+ }
+
+ void onOneOrMore (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+
+ optDesc_.setOneOrMore();
+ optDesc_.CheckConsistency();
+ }
+
+ void onZeroOrMore (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+
+ if (optDesc_.isList())
+ llvm::errs() << "Warning: specifying the 'zero_or_more' property "
+ "on a list option has no effect.\n";
+
+ optDesc_.setZeroOrMore();
+ optDesc_.CheckConsistency();
+ }
+
+ void onOptional (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+
+ if (!optDesc_.isList())
+ llvm::errs() << "Warning: specifying the 'optional' property"
+ "on a non-list option has no effect.\n";
+
+ optDesc_.setOptional();
+ optDesc_.CheckConsistency();
+ }
+
+ void onMultiVal (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ int val = InitPtrToInt(d.getArg(0));
+ if (val < 2)
+ throw "Error in the 'multi_val' property: "
+ "the value must be greater than 1!";
+ if (!optDesc_.isParameterList())
+ throw "The multi_val property is valid only on list options!";
+ optDesc_.MultiVal = val;
+ }
+
+};
+
+/// AddOption - A function object that is applied to every option
+/// description. Used by CollectOptionDescriptions.
+class AddOption {
+private:
+ OptionDescriptions& OptDescs_;
+
+public:
+ explicit AddOption(OptionDescriptions& OD) : OptDescs_(OD)
+ {}
+
+ void operator()(const Init* i) {
+ const DagInit& d = InitPtrToDag(i);
+ CheckNumberOfArguments(d, 1);
+
+ const OptionType::OptionType Type =
+ stringToOptionType(GetOperatorName(d));
+ const std::string& Name = InitPtrToString(d.getArg(0));
+
+ OptionDescription OD(Type, Name);
+
+ CheckNumberOfArguments(d, 2);
+
+ if (OD.isAlias()) {
+ // Aliases store the aliased option name in the 'Help' field.
+ OD.Help = InitPtrToString(d.getArg(1));
+ }
+ else {
+ processOptionProperties(d, OD);
+ }
+
+ OptDescs_.InsertDescription(OD);
+ }
+
+private:
+ /// processOptionProperties - Go through the list of option
+ /// properties and call a corresponding handler for each.
+ static void processOptionProperties (const DagInit& d, OptionDescription& o) {
+ CheckNumberOfArguments(d, 2);
+ DagInit::const_arg_iterator B = d.arg_begin();
+ // Skip the first argument: it's always the option name.
+ ++B;
+ std::for_each(B, d.arg_end(), CollectOptionProperties(o));
+ }
+
+};
+
+/// CollectOptionDescriptions - Collects option properties from all
+/// OptionLists.
+void CollectOptionDescriptions (const RecordVector& V,
+ OptionDescriptions& OptDescs)
+{
+ // For every OptionList:
+ for (RecordVector::const_iterator B = V.begin(),
+ E = V.end(); B!=E; ++B) {
+ // Throws an exception if the value does not exist.
+ ListInit* PropList = (*B)->getValueAsListInit("options");
+
+ // For every option description in this list:
+ // collect the information and
+ std::for_each(PropList->begin(), PropList->end(), AddOption(OptDescs));
+ }
+}
+
+// Tool information record
+
+namespace ToolFlags {
+ enum ToolFlags { Join = 0x1, Sink = 0x2 };
+}
+
+struct ToolDescription : public RefCountedBase<ToolDescription> {
+ std::string Name;
+ Init* CmdLine;
+ Init* Actions;
+ StrVector InLanguage;
+ std::string InFileOption;
+ std::string OutFileOption;
+ std::string OutLanguage;
+ std::string OutputSuffix;
+ unsigned Flags;
+ const Init* OnEmpty;
+
+ // Various boolean properties
+ void setSink() { Flags |= ToolFlags::Sink; }
+ bool isSink() const { return Flags & ToolFlags::Sink; }
+ void setJoin() { Flags |= ToolFlags::Join; }
+ bool isJoin() const { return Flags & ToolFlags::Join; }
+
+ // Default ctor here is needed because StringMap can only store
+ // DefaultConstructible objects
+ ToolDescription (const std::string &n = "")
+ : Name(n), CmdLine(0), Actions(0), OutFileOption("-o"),
+ Flags(0), OnEmpty(0)
+ {}
+};
+
+/// ToolDescriptions - A list of Tool information records.
+typedef std::vector<IntrusiveRefCntPtr<ToolDescription> > ToolDescriptions;
+
+
+/// CollectToolProperties - Function object for iterating over a list of
+/// tool property records.
+
+class CollectToolProperties;
+typedef void (CollectToolProperties::* CollectToolPropertiesHandler)
+(const DagInit&);
+
+class CollectToolProperties : public HandlerTable<CollectToolPropertiesHandler>
+{
+private:
+
+ /// toolDesc_ - Properties of the current Tool. This is where the
+ /// information is stored.
+ ToolDescription& toolDesc_;
+
+public:
+
+ explicit CollectToolProperties (ToolDescription& d)
+ : toolDesc_(d)
+ {
+ if (!staticMembersInitialized_) {
+
+ AddHandler("actions", &CollectToolProperties::onActions);
+ AddHandler("command", &CollectToolProperties::onCommand);
+ AddHandler("in_language", &CollectToolProperties::onInLanguage);
+ AddHandler("join", &CollectToolProperties::onJoin);
+ AddHandler("out_language", &CollectToolProperties::onOutLanguage);
+
+ AddHandler("out_file_option", &CollectToolProperties::onOutFileOption);
+ AddHandler("in_file_option", &CollectToolProperties::onInFileOption);
+
+ AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix);
+ AddHandler("sink", &CollectToolProperties::onSink);
+ AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty);
+
+ staticMembersInitialized_ = true;
+ }
+ }
+
+ void operator() (Init* I) {
+ InvokeDagInitHandler(this, I);
+ }
+
+private:
+
+ /// Property handlers --
+ /// Functions that extract information about tool properties from
+ /// DAG representation.
+
+ void onActions (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ Init* Case = d.getArg(0);
+ if (typeid(*Case) != typeid(DagInit) ||
+ GetOperatorName(static_cast<DagInit&>(*Case)) != "case")
+ throw "The argument to (actions) should be a 'case' construct!";
+ toolDesc_.Actions = Case;
+ }
+
+ void onCommand (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ toolDesc_.CmdLine = d.getArg(0);
+ }
+
+ void onInLanguage (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ Init* arg = d.getArg(0);
+
+ // Find out the argument's type.
+ if (typeid(*arg) == typeid(StringInit)) {
+ // It's a string.
+ toolDesc_.InLanguage.push_back(InitPtrToString(arg));
+ }
+ else {
+ // It's a list.
+ const ListInit& lst = InitPtrToList(arg);
+ StrVector& out = toolDesc_.InLanguage;
+
+ // Copy strings to the output vector.
+ for (ListInit::const_iterator B = lst.begin(), E = lst.end();
+ B != E; ++B) {
+ out.push_back(InitPtrToString(*B));
+ }
+
+ // Remove duplicates.
+ std::sort(out.begin(), out.end());
+ StrVector::iterator newE = std::unique(out.begin(), out.end());
+ out.erase(newE, out.end());
+ }
+ }
+
+ void onJoin (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+ toolDesc_.setJoin();
+ }
+
+ void onOutLanguage (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ toolDesc_.OutLanguage = InitPtrToString(d.getArg(0));
+ }
+
+ void onOutFileOption (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ toolDesc_.OutFileOption = InitPtrToString(d.getArg(0));
+ }
+
+ void onInFileOption (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ toolDesc_.InFileOption = InitPtrToString(d.getArg(0));
+ }
+
+ void onOutputSuffix (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ toolDesc_.OutputSuffix = InitPtrToString(d.getArg(0));
+ }
+
+ void onSink (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+ toolDesc_.setSink();
+ }
+
+ void onWorksOnEmpty (const DagInit& d) {
+ toolDesc_.OnEmpty = d.getArg(0);
+ }
+
+};
+
+/// CollectToolDescriptions - Gather information about tool properties
+/// from the parsed TableGen data (basically a wrapper for the
+/// CollectToolProperties function object).
+void CollectToolDescriptions (const RecordVector& Tools,
+ ToolDescriptions& ToolDescs)
+{
+ // Iterate over a properties list of every Tool definition
+ for (RecordVector::const_iterator B = Tools.begin(),
+ E = Tools.end(); B!=E; ++B) {
+ const Record* T = *B;
+ // Throws an exception if the value does not exist.
+ ListInit* PropList = T->getValueAsListInit("properties");
+
+ IntrusiveRefCntPtr<ToolDescription>
+ ToolDesc(new ToolDescription(T->getName()));
+
+ std::for_each(PropList->begin(), PropList->end(),
+ CollectToolProperties(*ToolDesc));
+ ToolDescs.push_back(ToolDesc);
+ }
+}
+
+/// FillInEdgeVector - Merge all compilation graph definitions into
+/// one single edge list.
+void FillInEdgeVector(const RecordVector& CompilationGraphs,
+ DagVector& Out) {
+ for (RecordVector::const_iterator B = CompilationGraphs.begin(),
+ E = CompilationGraphs.end(); B != E; ++B) {
+ const ListInit* Edges = (*B)->getValueAsListInit("edges");
+
+ for (ListInit::const_iterator B = Edges->begin(),
+ E = Edges->end(); B != E; ++B) {
+ Out.push_back(&InitPtrToDag(*B));
+ }
+ }
+}
+
+/// NotInGraph - Helper function object for FilterNotInGraph.
+struct NotInGraph {
+private:
+ const llvm::StringSet<>& ToolsInGraph_;
+
+public:
+ NotInGraph(const llvm::StringSet<>& ToolsInGraph)
+ : ToolsInGraph_(ToolsInGraph)
+ {}
+
+ bool operator()(const IntrusiveRefCntPtr<ToolDescription>& x) {
+ return (ToolsInGraph_.count(x->Name) == 0);
+ }
+};
+
+/// FilterNotInGraph - Filter out from ToolDescs all Tools not
+/// mentioned in the compilation graph definition.
+void FilterNotInGraph (const DagVector& EdgeVector,
+ ToolDescriptions& ToolDescs) {
+
+ // List all tools mentioned in the graph.
+ llvm::StringSet<> ToolsInGraph;
+
+ for (DagVector::const_iterator B = EdgeVector.begin(),
+ E = EdgeVector.end(); B != E; ++B) {
+
+ const DagInit* Edge = *B;
+ const std::string& NodeA = InitPtrToString(Edge->getArg(0));
+ const std::string& NodeB = InitPtrToString(Edge->getArg(1));
+
+ if (NodeA != "root")
+ ToolsInGraph.insert(NodeA);
+ ToolsInGraph.insert(NodeB);
+ }
+
+ // Filter ToolPropertiesList.
+ ToolDescriptions::iterator new_end =
+ std::remove_if(ToolDescs.begin(), ToolDescs.end(),
+ NotInGraph(ToolsInGraph));
+ ToolDescs.erase(new_end, ToolDescs.end());
+}
+
+/// FillInToolToLang - Fills in two tables that map tool names to
+/// (input, output) languages. Helper function used by TypecheckGraph().
+void FillInToolToLang (const ToolDescriptions& ToolDescs,
+ StringMap<StringSet<> >& ToolToInLang,
+ StringMap<std::string>& ToolToOutLang) {
+ for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
+ E = ToolDescs.end(); B != E; ++B) {
+ const ToolDescription& D = *(*B);
+ for (StrVector::const_iterator B = D.InLanguage.begin(),
+ E = D.InLanguage.end(); B != E; ++B)
+ ToolToInLang[D.Name].insert(*B);
+ ToolToOutLang[D.Name] = D.OutLanguage;
+ }
+}
+
+/// TypecheckGraph - Check that names for output and input languages
+/// on all edges do match.
+void TypecheckGraph (const DagVector& EdgeVector,
+ const ToolDescriptions& ToolDescs) {
+ StringMap<StringSet<> > ToolToInLang;
+ StringMap<std::string> ToolToOutLang;
+
+ FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang);
+ StringMap<std::string>::iterator IAE = ToolToOutLang.end();
+ StringMap<StringSet<> >::iterator IBE = ToolToInLang.end();
+
+ for (DagVector::const_iterator B = EdgeVector.begin(),
+ E = EdgeVector.end(); B != E; ++B) {
+ const DagInit* Edge = *B;
+ const std::string& NodeA = InitPtrToString(Edge->getArg(0));
+ const std::string& NodeB = InitPtrToString(Edge->getArg(1));
+ StringMap<std::string>::iterator IA = ToolToOutLang.find(NodeA);
+ StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB);
+
+ if (NodeA != "root") {
+ if (IA != IAE && IB != IBE && IB->second.count(IA->second) == 0)
+ throw "Edge " + NodeA + "->" + NodeB
+ + ": output->input language mismatch";
+ }
+
+ if (NodeB == "root")
+ throw "Edges back to the root are not allowed!";
+ }
+}
+
+/// WalkCase - Walks the 'case' expression DAG and invokes
+/// TestCallback on every test, and StatementCallback on every
+/// statement. Handles 'case' nesting, but not the 'and' and 'or'
+/// combinators (that is, they are passed directly to TestCallback).
+/// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
+/// IndentLevel, bool FirstTest)'.
+/// StatementCallback must have type 'void StatementCallback(const Init*,
+/// unsigned IndentLevel)'.
+template <typename F1, typename F2>
+void WalkCase(const Init* Case, F1 TestCallback, F2 StatementCallback,
+ unsigned IndentLevel = 0)
+{
+ const DagInit& d = InitPtrToDag(Case);
+
+ // Error checks.
+ if (GetOperatorName(d) != "case")
+ throw "WalkCase should be invoked only on 'case' expressions!";
+
+ if (d.getNumArgs() < 2)
+ throw "There should be at least one clause in the 'case' expression:\n"
+ + d.getAsString();
+
+ // Main loop.
+ bool even = false;
+ const unsigned numArgs = d.getNumArgs();
+ unsigned i = 1;
+ for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
+ B != E; ++B) {
+ Init* arg = *B;
+
+ if (!even)
+ {
+ // Handle test.
+ const DagInit& Test = InitPtrToDag(arg);
+
+ if (GetOperatorName(Test) == "default" && (i+1 != numArgs))
+ throw "The 'default' clause should be the last in the "
+ "'case' construct!";
+ if (i == numArgs)
+ throw "Case construct handler: no corresponding action "
+ "found for the test " + Test.getAsString() + '!';
+
+ TestCallback(Test, IndentLevel, (i == 1));
+ }
+ else
+ {
+ if (dynamic_cast<DagInit*>(arg)
+ && GetOperatorName(static_cast<DagInit&>(*arg)) == "case") {
+ // Nested 'case'.
+ WalkCase(arg, TestCallback, StatementCallback, IndentLevel + Indent1);
+ }
+
+ // Handle statement.
+ StatementCallback(arg, IndentLevel);
+ }
+
+ ++i;
+ even = !even;
+ }
+}
+
+/// ExtractOptionNames - A helper function object used by
+/// CheckForSuperfluousOptions() to walk the 'case' DAG.
+class ExtractOptionNames {
+ llvm::StringSet<>& OptionNames_;
+
+ void processDag(const Init* Statement) {
+ const DagInit& Stmt = InitPtrToDag(Statement);
+ const std::string& ActionName = GetOperatorName(Stmt);
+ if (ActionName == "forward" || ActionName == "forward_as" ||
+ ActionName == "forward_value" ||
+ ActionName == "forward_transformed_value" ||
+ ActionName == "switch_on" || ActionName == "any_switch_on" ||
+ ActionName == "parameter_equals" ||
+ ActionName == "element_in_list" || ActionName == "not_empty" ||
+ ActionName == "empty") {
+ CheckNumberOfArguments(Stmt, 1);
+
+ Init* Arg = Stmt.getArg(0);
+ if (typeid(*Arg) == typeid(StringInit)) {
+ const std::string& Name = InitPtrToString(Arg);
+ OptionNames_.insert(Name);
+ }
+ else {
+ // It's a list.
+ const ListInit& List = InitPtrToList(Arg);
+ for (ListInit::const_iterator B = List.begin(), E = List.end();
+ B != E; ++B) {
+ const std::string& Name = InitPtrToString(*B);
+ OptionNames_.insert(Name);
+ }
+ }
+ }
+ else if (ActionName == "and" || ActionName == "or" || ActionName == "not") {
+ for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
+ this->processDag(Stmt.getArg(i));
+ }
+ }
+ }
+
+public:
+ ExtractOptionNames(llvm::StringSet<>& OptionNames) : OptionNames_(OptionNames)
+ {}
+
+ void operator()(const Init* Statement) {
+ if (typeid(*Statement) == typeid(ListInit)) {
+ const ListInit& DagList = *static_cast<const ListInit*>(Statement);
+ for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
+ B != E; ++B)
+ this->processDag(*B);
+ }
+ else {
+ this->processDag(Statement);
+ }
+ }
+
+ void operator()(const DagInit& Test, unsigned, bool) {
+ this->operator()(&Test);
+ }
+ void operator()(const Init* Statement, unsigned) {
+ this->operator()(Statement);
+ }
+};
+
+/// IsOptionalEdge - Validate that the 'optional_edge' has proper structure.
+bool IsOptionalEdge (const DagInit& Edg) {
+ return (GetOperatorName(Edg) == "optional_edge") && (Edg.getNumArgs() > 2);
+}
+
+/// CheckForSuperfluousOptions - Check that there are no side
+/// effect-free options (specified only in the OptionList). Otherwise,
+/// output a warning.
+void CheckForSuperfluousOptions (const DagVector& EdgeVector,
+ const ToolDescriptions& ToolDescs,
+ const OptionDescriptions& OptDescs) {
+ llvm::StringSet<> nonSuperfluousOptions;
+
+ // Add all options mentioned in the ToolDesc.Actions to the set of
+ // non-superfluous options.
+ for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
+ E = ToolDescs.end(); B != E; ++B) {
+ const ToolDescription& TD = *(*B);
+ ExtractOptionNames Callback(nonSuperfluousOptions);
+ if (TD.Actions)
+ WalkCase(TD.Actions, Callback, Callback);
+ }
+
+ // Add all options mentioned in the 'case' clauses of the
+ // OptionalEdges of the compilation graph to the set of
+ // non-superfluous options.
+ for (DagVector::const_iterator B = EdgeVector.begin(),
+ E = EdgeVector.end(); B != E; ++B) {
+ const DagInit& Edge = **B;
+ if (IsOptionalEdge(Edge)) {
+ const DagInit& Weight = InitPtrToDag(Edge.getArg(2));
+ WalkCase(&Weight, ExtractOptionNames(nonSuperfluousOptions), Id());
+ }
+ }
+
+ // Check that all options in OptDescs belong to the set of
+ // non-superfluous options.
+ for (OptionDescriptions::const_iterator B = OptDescs.begin(),
+ E = OptDescs.end(); B != E; ++B) {
+ const OptionDescription& Val = B->second;
+ if (!nonSuperfluousOptions.count(Val.Name)
+ && Val.Type != OptionType::Alias)
+ llvm::errs() << "Warning: option '-" << Val.Name << "' has no effect! "
+ "Probable cause: this option is specified only in the OptionList.\n";
+ }
+}
+
+/// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler().
+bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) {
+ if (TestName == "single_input_file") {
+ O << "InputFilenames.size() == 1";
+ return true;
+ }
+ else if (TestName == "multiple_input_files") {
+ O << "InputFilenames.size() > 1";
+ return true;
+ }
+
+ return false;
+}
+
+/// EmitListTest - Helper function used by EmitCaseTest1ArgList().
+template <typename F>
+void EmitListTest(const ListInit& L, const char* LogicOp,
+ F Callback, raw_ostream& O)
+{
+ // This is a lot like EmitLogicalOperationTest, but works on ListInits instead
+ // of Dags...
+ bool isFirst = true;
+ for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) {
+ if (isFirst)
+ isFirst = false;
+ else
+ O << ' ' << LogicOp << ' ';
+ Callback(InitPtrToString(*B), O);
+ }
+}
+
+// Callbacks for use with EmitListTest.
+
+class EmitSwitchOn {
+ const OptionDescriptions& OptDescs_;
+public:
+ EmitSwitchOn(const OptionDescriptions& OptDescs) : OptDescs_(OptDescs)
+ {}
+
+ void operator()(const std::string& OptName, raw_ostream& O) const {
+ const OptionDescription& OptDesc = OptDescs_.FindSwitch(OptName);
+ O << OptDesc.GenVariableName();
+ }
+};
+
+class EmitEmptyTest {
+ bool EmitNegate_;
+ const OptionDescriptions& OptDescs_;
+public:
+ EmitEmptyTest(bool EmitNegate, const OptionDescriptions& OptDescs)
+ : EmitNegate_(EmitNegate), OptDescs_(OptDescs)
+ {}
+
+ void operator()(const std::string& OptName, raw_ostream& O) const {
+ const char* Neg = (EmitNegate_ ? "!" : "");
+ if (OptName == "o") {
+ O << Neg << "OutputFilename.empty()";
+ }
+ else if (OptName == "save-temps") {
+ O << Neg << "(SaveTemps == SaveTempsEnum::Unset)";
+ }
+ else {
+ const OptionDescription& OptDesc = OptDescs_.FindListOrParameter(OptName);
+ O << Neg << OptDesc.GenVariableName() << ".empty()";
+ }
+ }
+};
+
+
+/// EmitCaseTest1ArgList - Helper function used by EmitCaseTest1Arg();
+bool EmitCaseTest1ArgList(const std::string& TestName,
+ const DagInit& d,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+ const ListInit& L = InitPtrToList(d.getArg(0));
+
+ if (TestName == "any_switch_on") {
+ EmitListTest(L, "||", EmitSwitchOn(OptDescs), O);
+ return true;
+ }
+ else if (TestName == "switch_on") {
+ EmitListTest(L, "&&", EmitSwitchOn(OptDescs), O);
+ return true;
+ }
+ else if (TestName == "any_not_empty") {
+ EmitListTest(L, "||", EmitEmptyTest(true, OptDescs), O);
+ return true;
+ }
+ else if (TestName == "any_empty") {
+ EmitListTest(L, "||", EmitEmptyTest(false, OptDescs), O);
+ return true;
+ }
+ else if (TestName == "not_empty") {
+ EmitListTest(L, "&&", EmitEmptyTest(true, OptDescs), O);
+ return true;
+ }
+ else if (TestName == "empty") {
+ EmitListTest(L, "&&", EmitEmptyTest(false, OptDescs), O);
+ return true;
+ }
+
+ return false;
+}
+
+/// EmitCaseTest1ArgStr - Helper function used by EmitCaseTest1Arg();
+bool EmitCaseTest1ArgStr(const std::string& TestName,
+ const DagInit& d,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+ const std::string& OptName = InitPtrToString(d.getArg(0));
+
+ if (TestName == "switch_on") {
+ apply(EmitSwitchOn(OptDescs), OptName, O);
+ return true;
+ }
+ else if (TestName == "input_languages_contain") {
+ O << "InLangs.count(\"" << OptName << "\") != 0";
+ return true;
+ }
+ else if (TestName == "in_language") {
+ // This works only for single-argument Tool::GenerateAction. Join
+ // tools can process several files in different languages simultaneously.
+
+ // TODO: make this work with Edge::Weight (if possible).
+ O << "LangMap.GetLanguage(inFile) == \"" << OptName << '\"';
+ return true;
+ }
+ else if (TestName == "not_empty" || TestName == "empty") {
+ bool EmitNegate = (TestName == "not_empty");
+ apply(EmitEmptyTest(EmitNegate, OptDescs), OptName, O);
+ return true;
+ }
+
+ return false;
+}
+
+/// EmitCaseTest1Arg - Helper function used by EmitCaseConstructHandler();
+bool EmitCaseTest1Arg(const std::string& TestName,
+ const DagInit& d,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+ CheckNumberOfArguments(d, 1);
+ if (typeid(*d.getArg(0)) == typeid(ListInit))
+ return EmitCaseTest1ArgList(TestName, d, OptDescs, O);
+ else
+ return EmitCaseTest1ArgStr(TestName, d, OptDescs, O);
+}
+
+/// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().
+bool EmitCaseTest2Args(const std::string& TestName,
+ const DagInit& d,
+ unsigned IndentLevel,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+ CheckNumberOfArguments(d, 2);
+ const std::string& OptName = InitPtrToString(d.getArg(0));
+ const std::string& OptArg = InitPtrToString(d.getArg(1));
+
+ if (TestName == "parameter_equals") {
+ const OptionDescription& OptDesc = OptDescs.FindParameter(OptName);
+ O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
+ return true;
+ }
+ else if (TestName == "element_in_list") {
+ const OptionDescription& OptDesc = OptDescs.FindParameterList(OptName);
+ const std::string& VarName = OptDesc.GenVariableName();
+ O << "std::find(" << VarName << ".begin(),\n";
+ O.indent(IndentLevel + Indent1)
+ << VarName << ".end(), \""
+ << OptArg << "\") != " << VarName << ".end()";
+ return true;
+ }
+
+ return false;
+}
+
+// Forward declaration.
+// EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
+void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O);
+
+/// EmitLogicalOperationTest - Helper function used by
+/// EmitCaseConstructHandler.
+void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
+ unsigned IndentLevel,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+ O << '(';
+ for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) {
+ const DagInit& InnerTest = InitPtrToDag(d.getArg(j));
+ EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
+ if (j != NumArgs - 1) {
+ O << ")\n";
+ O.indent(IndentLevel + Indent1) << ' ' << LogicOp << " (";
+ }
+ else {
+ O << ')';
+ }
+ }
+}
+
+void EmitLogicalNot(const DagInit& d, unsigned IndentLevel,
+ const OptionDescriptions& OptDescs, raw_ostream& O)
+{
+ CheckNumberOfArguments(d, 1);
+ const DagInit& InnerTest = InitPtrToDag(d.getArg(0));
+ O << "! (";
+ EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
+ O << ")";
+}
+
+/// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
+void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+ const std::string& TestName = GetOperatorName(d);
+
+ if (TestName == "and")
+ EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
+ else if (TestName == "or")
+ EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O);
+ else if (TestName == "not")
+ EmitLogicalNot(d, IndentLevel, OptDescs, O);
+ else if (EmitCaseTest0Args(TestName, O))
+ return;
+ else if (EmitCaseTest1Arg(TestName, d, OptDescs, O))
+ return;
+ else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O))
+ return;
+ else
+ throw "Unknown test '" + TestName + "' used in the 'case' construct!";
+}
+
+
+/// EmitCaseTestCallback - Callback used by EmitCaseConstructHandler.
+class EmitCaseTestCallback {
+ bool EmitElseIf_;
+ const OptionDescriptions& OptDescs_;
+ raw_ostream& O_;
+public:
+
+ EmitCaseTestCallback(bool EmitElseIf,
+ const OptionDescriptions& OptDescs, raw_ostream& O)
+ : EmitElseIf_(EmitElseIf), OptDescs_(OptDescs), O_(O)
+ {}
+
+ void operator()(const DagInit& Test, unsigned IndentLevel, bool FirstTest)
+ {
+ if (GetOperatorName(Test) == "default") {
+ O_.indent(IndentLevel) << "else {\n";
+ }
+ else {
+ O_.indent(IndentLevel)
+ << ((!FirstTest && EmitElseIf_) ? "else if (" : "if (");
+ EmitCaseTest(Test, IndentLevel, OptDescs_, O_);
+ O_ << ") {\n";
+ }
+ }
+};
+
+/// EmitCaseStatementCallback - Callback used by EmitCaseConstructHandler.
+template <typename F>
+class EmitCaseStatementCallback {
+ F Callback_;
+ raw_ostream& O_;
+public:
+
+ EmitCaseStatementCallback(F Callback, raw_ostream& O)
+ : Callback_(Callback), O_(O)
+ {}
+
+ void operator() (const Init* Statement, unsigned IndentLevel) {
+
+ // Ignore nested 'case' DAG.
+ if (!(dynamic_cast<const DagInit*>(Statement) &&
+ GetOperatorName(static_cast<const DagInit&>(*Statement)) == "case")) {
+ if (typeid(*Statement) == typeid(ListInit)) {
+ const ListInit& DagList = *static_cast<const ListInit*>(Statement);
+ for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
+ B != E; ++B)
+ Callback_(*B, (IndentLevel + Indent1), O_);
+ }
+ else {
+ Callback_(Statement, (IndentLevel + Indent1), O_);
+ }
+ }
+ O_.indent(IndentLevel) << "}\n";
+ }
+
+};
+
+/// EmitCaseConstructHandler - Emit code that handles the 'case'
+/// construct. Takes a function object that should emit code for every case
+/// clause. Implemented on top of WalkCase.
+/// Callback's type is void F(const Init* Statement, unsigned IndentLevel,
+/// raw_ostream& O).
+/// EmitElseIf parameter controls the type of condition that is emitted ('if
+/// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..) {..}
+/// .. else {..}').
+template <typename F>
+void EmitCaseConstructHandler(const Init* Case, unsigned IndentLevel,
+ F Callback, bool EmitElseIf,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+ WalkCase(Case, EmitCaseTestCallback(EmitElseIf, OptDescs, O),
+ EmitCaseStatementCallback<F>(Callback, O), IndentLevel);
+}
+
+/// TokenizeCmdLine - converts from
+/// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to
+/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"].
+void TokenizeCmdLine(const std::string& CmdLine, StrVector& Out) {
+ const char* Delimiters = " \t\n\v\f\r";
+ enum TokenizerState
+ { Normal, SpecialCommand, InsideSpecialCommand, InsideQuotationMarks }
+ cur_st = Normal;
+
+ if (CmdLine.empty())
+ return;
+ Out.push_back("");
+
+ std::string::size_type B = CmdLine.find_first_not_of(Delimiters),
+ E = CmdLine.size();
+
+ for (; B != E; ++B) {
+ char cur_ch = CmdLine[B];
+
+ switch (cur_st) {
+ case Normal:
+ if (cur_ch == '$') {
+ cur_st = SpecialCommand;
+ break;
+ }
+ if (OneOf(Delimiters, cur_ch)) {
+ // Skip whitespace
+ B = CmdLine.find_first_not_of(Delimiters, B);
+ if (B == std::string::npos) {
+ B = E-1;
+ continue;
+ }
+ --B;
+ Out.push_back("");
+ continue;
+ }
+ break;
+
+
+ case SpecialCommand:
+ if (OneOf(Delimiters, cur_ch)) {
+ cur_st = Normal;
+ Out.push_back("");
+ continue;
+ }
+ if (cur_ch == '(') {
+ Out.push_back("");
+ cur_st = InsideSpecialCommand;
+ continue;
+ }
+ break;
+
+ case InsideSpecialCommand:
+ if (OneOf(Delimiters, cur_ch)) {
+ continue;
+ }
+ if (cur_ch == '\'') {
+ cur_st = InsideQuotationMarks;
+ Out.push_back("");
+ continue;
+ }
+ if (cur_ch == ')') {
+ cur_st = Normal;
+ Out.push_back("");
+ }
+ if (cur_ch == ',') {
+ continue;
+ }
+
+ break;
+
+ case InsideQuotationMarks:
+ if (cur_ch == '\'') {
+ cur_st = InsideSpecialCommand;
+ continue;
+ }
+ break;
+ }
+
+ Out.back().push_back(cur_ch);
+ }
+}
+
+/// SubstituteCall - Given "$CALL(HookName, [Arg1 [, Arg2 [...]]])", output
+/// "hooks::HookName([Arg1 [, Arg2 [, ...]]])". Helper function used by
+/// SubstituteSpecialCommands().
+StrVector::const_iterator
+SubstituteCall (StrVector::const_iterator Pos,
+ StrVector::const_iterator End,
+ bool IsJoin, raw_ostream& O)
+{
+ const char* errorMessage = "Syntax error in $CALL invocation!";
+ CheckedIncrement(Pos, End, errorMessage);
+ const std::string& CmdName = *Pos;
+
+ if (CmdName == ")")
+ throw "$CALL invocation: empty argument list!";
+
+ O << "hooks::";
+ O << CmdName << "(";
+
+
+ bool firstIteration = true;
+ while (true) {
+ CheckedIncrement(Pos, End, errorMessage);
+ const std::string& Arg = *Pos;
+ assert(Arg.size() != 0);
+
+ if (Arg[0] == ')')
+ break;
+
+ if (firstIteration)
+ firstIteration = false;
+ else
+ O << ", ";
+
+ if (Arg == "$INFILE") {
+ if (IsJoin)
+ throw "$CALL(Hook, $INFILE) can't be used with a Join tool!";
+ else
+ O << "inFile.c_str()";
+ }
+ else {
+ O << '"' << Arg << '"';
+ }
+ }
+
+ O << ')';
+
+ return Pos;
+}
+
+/// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper
+/// function used by SubstituteSpecialCommands().
+StrVector::const_iterator
+SubstituteEnv (StrVector::const_iterator Pos,
+ StrVector::const_iterator End, raw_ostream& O)
+{
+ const char* errorMessage = "Syntax error in $ENV invocation!";
+ CheckedIncrement(Pos, End, errorMessage);
+ const std::string& EnvName = *Pos;
+
+ if (EnvName == ")")
+ throw "$ENV invocation: empty argument list!";
+
+ O << "checkCString(std::getenv(\"";
+ O << EnvName;
+ O << "\"))";
+
+ CheckedIncrement(Pos, End, errorMessage);
+
+ return Pos;
+}
+
+/// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output
+/// handler code. Helper function used by EmitCmdLineVecFill().
+StrVector::const_iterator
+SubstituteSpecialCommands (StrVector::const_iterator Pos,
+ StrVector::const_iterator End,
+ bool IsJoin, raw_ostream& O)
+{
+
+ const std::string& cmd = *Pos;
+
+ // Perform substitution.
+ if (cmd == "$CALL") {
+ Pos = SubstituteCall(Pos, End, IsJoin, O);
+ }
+ else if (cmd == "$ENV") {
+ Pos = SubstituteEnv(Pos, End, O);
+ }
+ else {
+ throw "Unknown special command: " + cmd;
+ }
+
+ // Handle '$CMD(ARG)/additional/text'.
+ const std::string& Leftover = *Pos;
+ assert(Leftover.at(0) == ')');
+ if (Leftover.size() != 1)
+ O << " + std::string(\"" << (Leftover.c_str() + 1) << "\")";
+
+ return Pos;
+}
+
+/// EmitCmdLineVecFill - Emit code that fills in the command line
+/// vector. Helper function used by EmitGenerateActionMethod().
+void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
+ bool IsJoin, unsigned IndentLevel,
+ raw_ostream& O) {
+ StrVector StrVec;
+ TokenizeCmdLine(InitPtrToString(CmdLine), StrVec);
+
+ if (StrVec.empty())
+ throw "Tool '" + ToolName + "' has empty command line!";
+
+ StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
+
+ // Emit the command itself.
+ assert(!StrVec[0].empty());
+ O.indent(IndentLevel) << "cmd = ";
+ if (StrVec[0][0] == '$') {
+ B = SubstituteSpecialCommands(B, E, IsJoin, O);
+ ++B;
+ }
+ else {
+ O << '"' << StrVec[0] << '"';
+ ++B;
+ }
+ O << ";\n";
+
+ // Go through the command arguments.
+ assert(B <= E);
+ for (; B != E; ++B) {
+ const std::string& cmd = *B;
+
+ assert(!cmd.empty());
+ O.indent(IndentLevel);
+
+ if (cmd.at(0) == '$') {
+ O << "vec.push_back(std::make_pair(0, ";
+ B = SubstituteSpecialCommands(B, E, IsJoin, O);
+ O << "));\n";
+ }
+ else {
+ O << "vec.push_back(std::make_pair(0, \"" << cmd << "\"));\n";
+ }
+ }
+
+}
+
+/// EmitForEachListElementCycleHeader - Emit common code for iterating through
+/// all elements of a list. Helper function used by
+/// EmitForwardOptionPropertyHandlingCode.
+void EmitForEachListElementCycleHeader (const OptionDescription& D,
+ unsigned IndentLevel,
+ raw_ostream& O) {
+ unsigned IndentLevel1 = IndentLevel + Indent1;
+
+ O.indent(IndentLevel)
+ << "for (" << D.GenTypeDeclaration()
+ << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
+ O.indent(IndentLevel)
+ << "E = " << D.GenVariableName() << ".end(); B != E;) {\n";
+ O.indent(IndentLevel1) << "unsigned pos = " << D.GenVariableName()
+ << ".getPosition(B - " << D.GenVariableName()
+ << ".begin());\n";
+}
+
+/// EmitForwardOptionPropertyHandlingCode - Helper function used to
+/// implement EmitActionHandler. Emits code for
+/// handling the (forward) and (forward_as) option properties.
+void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
+ unsigned IndentLevel,
+ const std::string& NewName,
+ raw_ostream& O) {
+ const std::string& Name = NewName.empty()
+ ? ("-" + D.Name)
+ : NewName;
+ unsigned IndentLevel1 = IndentLevel + Indent1;
+
+ switch (D.Type) {
+ case OptionType::Switch:
+ O.indent(IndentLevel)
+ << "vec.push_back(std::make_pair(" << D.GenVariableName()
+ << ".getPosition(), \"" << Name << "\"));\n";
+ break;
+ case OptionType::Parameter:
+ O.indent(IndentLevel) << "vec.push_back(std::make_pair("
+ << D.GenVariableName()
+ <<".getPosition(), \"" << Name;
+
+ if (!D.isForwardNotSplit()) {
+ O << "\"));\n";
+ O.indent(IndentLevel) << "vec.push_back(std::make_pair("
+ << D.GenVariableName() << ".getPosition(), "
+ << D.GenVariableName() << "));\n";
+ }
+ else {
+ O << "=\" + " << D.GenVariableName() << "));\n";
+ }
+ break;
+ case OptionType::Prefix:
+ O.indent(IndentLevel) << "vec.push_back(std::make_pair("
+ << D.GenVariableName() << ".getPosition(), \""
+ << Name << "\" + "
+ << D.GenVariableName() << "));\n";
+ break;
+ case OptionType::PrefixList:
+ EmitForEachListElementCycleHeader(D, IndentLevel, O);
+ O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
+ << Name << "\" + " << "*B));\n";
+ O.indent(IndentLevel1) << "++B;\n";
+
+ for (int i = 1, j = D.MultiVal; i < j; ++i) {
+ O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
+ O.indent(IndentLevel1) << "++B;\n";
+ }
+
+ O.indent(IndentLevel) << "}\n";
+ break;
+ case OptionType::ParameterList:
+ EmitForEachListElementCycleHeader(D, IndentLevel, O);
+ O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
+ << Name << "\"));\n";
+
+ for (int i = 0, j = D.MultiVal; i < j; ++i) {
+ O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
+ O.indent(IndentLevel1) << "++B;\n";
+ }
+
+ O.indent(IndentLevel) << "}\n";
+ break;
+ case OptionType::SwitchList:
+ EmitForEachListElementCycleHeader(D, IndentLevel, O);
+ O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
+ << Name << "\"));\n";
+ O.indent(IndentLevel1) << "++B;\n";
+ O.indent(IndentLevel) << "}\n";
+ break;
+ case OptionType::Alias:
+ default:
+ throw "Aliases are not allowed in tool option descriptions!";
+ }
+}
+
+/// ActionHandlingCallbackBase - Base class of EmitActionHandlersCallback and
+/// EmitPreprocessOptionsCallback.
+struct ActionHandlingCallbackBase
+{
+
+ void onErrorDag(const DagInit& d,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ O.indent(IndentLevel)
+ << "PrintError(\""
+ << (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0)) : "Unknown error!")
+ << "\");\n";
+ O.indent(IndentLevel) << "return 1;\n";
+ }
+
+ void onWarningDag(const DagInit& d,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(d, 1);
+ O.indent(IndentLevel) << "llvm::errs() << \""
+ << InitPtrToString(d.getArg(0)) << "\";\n";
+ }
+
+};
+
+/// EmitActionHandlersCallback - Emit code that handles actions. Used by
+/// EmitGenerateActionMethod() as an argument to EmitCaseConstructHandler().
+class EmitActionHandlersCallback;
+
+typedef void (EmitActionHandlersCallback::* EmitActionHandlersCallbackHandler)
+(const DagInit&, unsigned, raw_ostream&) const;
+
+class EmitActionHandlersCallback :
+ public ActionHandlingCallbackBase,
+ public HandlerTable<EmitActionHandlersCallbackHandler>
+{
+ typedef EmitActionHandlersCallbackHandler Handler;
+
+ const OptionDescriptions& OptDescs;
+
+ /// EmitHookInvocation - Common code for hook invocation from actions. Used by
+ /// onAppendCmd and onOutputSuffix.
+ void EmitHookInvocation(const std::string& Str,
+ const char* BlockOpen, const char* BlockClose,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ StrVector Out;
+ TokenizeCmdLine(Str, Out);
+
+ for (StrVector::const_iterator B = Out.begin(), E = Out.end();
+ B != E; ++B) {
+ const std::string& cmd = *B;
+
+ O.indent(IndentLevel) << BlockOpen;
+
+ if (cmd.at(0) == '$')
+ B = SubstituteSpecialCommands(B, E, /* IsJoin = */ true, O);
+ else
+ O << '"' << cmd << '"';
+
+ O << BlockClose;
+ }
+ }
+
+ void onAppendCmd (const DagInit& Dag,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(Dag, 1);
+ this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
+ "vec.push_back(std::make_pair(65536, ", "));\n",
+ IndentLevel, O);
+ }
+
+ void onForward (const DagInit& Dag,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(Dag, 1);
+ const std::string& Name = InitPtrToString(Dag.getArg(0));
+ EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
+ IndentLevel, "", O);
+ }
+
+ void onForwardAs (const DagInit& Dag,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(Dag, 2);
+ const std::string& Name = InitPtrToString(Dag.getArg(0));
+ const std::string& NewName = InitPtrToString(Dag.getArg(1));
+ EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
+ IndentLevel, NewName, O);
+ }
+
+ void onForwardValue (const DagInit& Dag,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(Dag, 1);
+ const std::string& Name = InitPtrToString(Dag.getArg(0));
+ const OptionDescription& D = OptDescs.FindParameterListOrParameter(Name);
+
+ if (D.isSwitchList()) {
+ throw std::runtime_error
+ ("forward_value is not allowed with switch_list");
+ }
+
+ if (D.isParameter()) {
+ O.indent(IndentLevel) << "vec.push_back(std::make_pair("
+ << D.GenVariableName() << ".getPosition(), "
+ << D.GenVariableName() << "));\n";
+ }
+ else {
+ O.indent(IndentLevel) << "for (" << D.GenTypeDeclaration()
+ << "::iterator B = " << D.GenVariableName()
+ << ".begin(), \n";
+ O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName()
+ << ".end(); B != E; ++B)\n";
+ O.indent(IndentLevel) << "{\n";
+ O.indent(IndentLevel + Indent1)
+ << "unsigned pos = " << D.GenVariableName()
+ << ".getPosition(B - " << D.GenVariableName()
+ << ".begin());\n";
+ O.indent(IndentLevel + Indent1)
+ << "vec.push_back(std::make_pair(pos, *B));\n";
+ O.indent(IndentLevel) << "}\n";
+ }
+ }
+
+ void onForwardTransformedValue (const DagInit& Dag,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(Dag, 2);
+ const std::string& Name = InitPtrToString(Dag.getArg(0));
+ const std::string& Hook = InitPtrToString(Dag.getArg(1));
+ const OptionDescription& D = OptDescs.FindParameterListOrParameter(Name);
+
+ O.indent(IndentLevel) << "vec.push_back(std::make_pair("
+ << D.GenVariableName() << ".getPosition("
+ << (D.isList() ? "0" : "") << "), "
+ << "hooks::" << Hook << "(" << D.GenVariableName()
+ << (D.isParameter() ? ".c_str()" : "") << ")));\n";
+ }
+
+ void onNoOutFile (const DagInit& Dag,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(Dag, 0);
+ O.indent(IndentLevel) << "no_out_file = true;\n";
+ }
+
+ void onOutputSuffix (const DagInit& Dag,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(Dag, 1);
+ this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
+ "output_suffix = ", ";\n", IndentLevel, O);
+ }
+
+ void onStopCompilation (const DagInit& Dag,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ O.indent(IndentLevel) << "stop_compilation = true;\n";
+ }
+
+
+ void onUnpackValues (const DagInit& Dag,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ throw "'unpack_values' is deprecated. "
+ "Use 'comma_separated' + 'forward_value' instead!";
+ }
+
+ public:
+
+ explicit EmitActionHandlersCallback(const OptionDescriptions& OD)
+ : OptDescs(OD)
+ {
+ if (!staticMembersInitialized_) {
+ AddHandler("error", &EmitActionHandlersCallback::onErrorDag);
+ AddHandler("warning", &EmitActionHandlersCallback::onWarningDag);
+ AddHandler("append_cmd", &EmitActionHandlersCallback::onAppendCmd);
+ AddHandler("forward", &EmitActionHandlersCallback::onForward);
+ AddHandler("forward_as", &EmitActionHandlersCallback::onForwardAs);
+ AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue);
+ AddHandler("forward_transformed_value",
+ &EmitActionHandlersCallback::onForwardTransformedValue);
+ AddHandler("no_out_file",
+ &EmitActionHandlersCallback::onNoOutFile);
+ AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix);
+ AddHandler("stop_compilation",
+ &EmitActionHandlersCallback::onStopCompilation);
+ AddHandler("unpack_values",
+ &EmitActionHandlersCallback::onUnpackValues);
+
+
+ staticMembersInitialized_ = true;
+ }
+ }
+
+ void operator()(const Init* I,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ InvokeDagInitHandler(this, I, IndentLevel, O);
+ }
+};
+
+void EmitGenerateActionMethodHeader(const ToolDescription& D,
+ bool IsJoin, bool Naked,
+ raw_ostream& O)
+{
+ O.indent(Indent1) << "int GenerateAction(Action& Out,\n";
+
+ if (IsJoin)
+ O.indent(Indent2) << "const PathVector& inFiles,\n";
+ else
+ O.indent(Indent2) << "const sys::Path& inFile,\n";
+
+ O.indent(Indent2) << "const bool HasChildren,\n";
+ O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n";
+ O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n";
+ O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
+ O.indent(Indent1) << "{\n";
+
+ if (!Naked) {
+ O.indent(Indent2) << "std::string cmd;\n";
+ O.indent(Indent2) << "std::string out_file;\n";
+ O.indent(Indent2)
+ << "std::vector<std::pair<unsigned, std::string> > vec;\n";
+ O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n";
+ O.indent(Indent2) << "bool no_out_file = false;\n";
+ O.indent(Indent2) << "std::string output_suffix(\""
+ << D.OutputSuffix << "\");\n";
+ }
+}
+
+// EmitGenerateActionMethod - Emit either a normal or a "join" version of the
+// Tool::GenerateAction() method.
+void EmitGenerateActionMethod (const ToolDescription& D,
+ const OptionDescriptions& OptDescs,
+ bool IsJoin, raw_ostream& O) {
+
+ EmitGenerateActionMethodHeader(D, IsJoin, /* Naked = */ false, O);
+
+ if (!D.CmdLine)
+ throw "Tool " + D.Name + " has no cmd_line property!";
+
+ // Process the 'command' property.
+ O << '\n';
+ EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
+ O << '\n';
+
+ // Process the 'actions' list of this tool.
+ if (D.Actions)
+ EmitCaseConstructHandler(D.Actions, Indent2,
+ EmitActionHandlersCallback(OptDescs),
+ false, OptDescs, O);
+ O << '\n';
+
+ // Input file (s)
+ if (!D.InFileOption.empty()) {
+ O.indent(Indent2)
+ << "vec.push_back(std::make_pair(InputFilenames.getPosition(0), \""
+ << D.InFileOption << "\");\n";
+ }
+
+ if (IsJoin) {
+ O.indent(Indent2)
+ << "for (PathVector::const_iterator B = inFiles.begin(),\n";
+ O.indent(Indent3) << "E = inFiles.end(); B != E; ++B)\n";
+ O.indent(Indent2) << "{\n";
+ O.indent(Indent3) << "vec.push_back(std::make_pair("
+ << "InputFilenames.getPosition(B - inFiles.begin()), "
+ << "B->str()));\n";
+ O.indent(Indent2) << "}\n";
+ }
+ else {
+ O.indent(Indent2) << "vec.push_back(std::make_pair("
+ << "InputFilenames.getPosition(0), inFile.str()));\n";
+ }
+
+ // Output file
+ O.indent(Indent2) << "if (!no_out_file) {\n";
+ if (!D.OutFileOption.empty())
+ O.indent(Indent3) << "vec.push_back(std::make_pair(65536, \""
+ << D.OutFileOption << "\"));\n";
+
+ O.indent(Indent3) << "out_file = this->OutFilename("
+ << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
+ O.indent(Indent4) <<
+ "TempDir, stop_compilation, output_suffix.c_str()).str();\n\n";
+ O.indent(Indent3) << "vec.push_back(std::make_pair(65536, out_file));\n";
+
+ O.indent(Indent2) << "}\n\n";
+
+ // Handle the Sink property.
+ std::string SinkOption("autogenerated::");
+ SinkOption += SinkOptionName;
+ if (D.isSink()) {
+ O.indent(Indent2) << "if (!" << SinkOption << ".empty()) {\n";
+ O.indent(Indent3) << "for (cl::list<std::string>::iterator B = "
+ << SinkOption << ".begin(), E = " << SinkOption
+ << ".end(); B != E; ++B)\n";
+ O.indent(Indent4) << "vec.push_back(std::make_pair(" << SinkOption
+ << ".getPosition(B - " << SinkOption
+ << ".begin()), *B));\n";
+ O.indent(Indent2) << "}\n";
+ }
+
+ O.indent(Indent2) << "Out.Construct(cmd, this->SortArgs(vec), "
+ << "stop_compilation, out_file);\n";
+ O.indent(Indent2) << "return 0;\n";
+ O.indent(Indent1) << "}\n\n";
+}
+
+/// EmitGenerateActionMethods - Emit two GenerateAction() methods for
+/// a given Tool class.
+void EmitGenerateActionMethods (const ToolDescription& ToolDesc,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+ if (!ToolDesc.isJoin()) {
+ EmitGenerateActionMethodHeader(ToolDesc, /* IsJoin = */ true,
+ /* Naked = */ true, O);
+ O.indent(Indent2) << "PrintError(\"" << ToolDesc.Name
+ << " is not a Join tool!\");\n";
+ O.indent(Indent2) << "return -1;\n";
+ O.indent(Indent1) << "}\n\n";
+ }
+ else {
+ EmitGenerateActionMethod(ToolDesc, OptDescs, true, O);
+ }
+
+ EmitGenerateActionMethod(ToolDesc, OptDescs, false, O);
+}
+
+/// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
+/// methods for a given Tool class.
+void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) {
+ O.indent(Indent1) << "const char** InputLanguages() const {\n";
+ O.indent(Indent2) << "return InputLanguages_;\n";
+ O.indent(Indent1) << "}\n\n";
+
+ if (D.OutLanguage.empty())
+ throw "Tool " + D.Name + " has no 'out_language' property!";
+
+ O.indent(Indent1) << "const char* OutputLanguage() const {\n";
+ O.indent(Indent2) << "return \"" << D.OutLanguage << "\";\n";
+ O.indent(Indent1) << "}\n\n";
+}
+
+/// EmitNameMethod - Emit the Name() method for a given Tool class.
+void EmitNameMethod (const ToolDescription& D, raw_ostream& O) {
+ O.indent(Indent1) << "const char* Name() const {\n";
+ O.indent(Indent2) << "return \"" << D.Name << "\";\n";
+ O.indent(Indent1) << "}\n\n";
+}
+
+/// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
+/// class.
+void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) {
+ O.indent(Indent1) << "bool IsJoin() const {\n";
+ if (D.isJoin())
+ O.indent(Indent2) << "return true;\n";
+ else
+ O.indent(Indent2) << "return false;\n";
+ O.indent(Indent1) << "}\n\n";
+}
+
+/// EmitWorksOnEmptyCallback - Callback used by EmitWorksOnEmptyMethod in
+/// conjunction with EmitCaseConstructHandler.
+void EmitWorksOnEmptyCallback (const Init* Value,
+ unsigned IndentLevel, raw_ostream& O) {
+ CheckBooleanConstant(Value);
+ O.indent(IndentLevel) << "return " << Value->getAsString() << ";\n";
+}
+
+/// EmitWorksOnEmptyMethod - Emit the WorksOnEmpty() method for a given Tool
+/// class.
+void EmitWorksOnEmptyMethod (const ToolDescription& D,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O)
+{
+ O.indent(Indent1) << "bool WorksOnEmpty() const {\n";
+ if (D.OnEmpty == 0)
+ O.indent(Indent2) << "return false;\n";
+ else
+ EmitCaseConstructHandler(D.OnEmpty, Indent2, EmitWorksOnEmptyCallback,
+ /*EmitElseIf = */ true, OptDescs, O);
+ O.indent(Indent1) << "}\n\n";
+}
+
+/// EmitStaticMemberDefinitions - Emit static member definitions for a
+/// given Tool class.
+void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) {
+ if (D.InLanguage.empty())
+ throw "Tool " + D.Name + " has no 'in_language' property!";
+
+ O << "const char* " << D.Name << "::InputLanguages_[] = {";
+ for (StrVector::const_iterator B = D.InLanguage.begin(),
+ E = D.InLanguage.end(); B != E; ++B)
+ O << '\"' << *B << "\", ";
+ O << "0};\n\n";
+}
+
+/// EmitToolClassDefinition - Emit a Tool class definition.
+void EmitToolClassDefinition (const ToolDescription& D,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+ if (D.Name == "root")
+ return;
+
+ // Header
+ O << "class " << D.Name << " : public ";
+ if (D.isJoin())
+ O << "JoinTool";
+ else
+ O << "Tool";
+
+ O << " {\nprivate:\n";
+ O.indent(Indent1) << "static const char* InputLanguages_[];\n\n";
+
+ O << "public:\n";
+ EmitNameMethod(D, O);
+ EmitInOutLanguageMethods(D, O);
+ EmitIsJoinMethod(D, O);
+ EmitWorksOnEmptyMethod(D, OptDescs, O);
+ EmitGenerateActionMethods(D, OptDescs, O);
+
+ // Close class definition
+ O << "};\n";
+
+ EmitStaticMemberDefinitions(D, O);
+
+}
+
+/// EmitOptionDefinitions - Iterate over a list of option descriptions
+/// and emit registration code.
+void EmitOptionDefinitions (const OptionDescriptions& descs,
+ bool HasSink, raw_ostream& O)
+{
+ std::vector<OptionDescription> Aliases;
+
+ // Emit static cl::Option variables.
+ for (OptionDescriptions::const_iterator B = descs.begin(),
+ E = descs.end(); B!=E; ++B) {
+ const OptionDescription& val = B->second;
+
+ if (val.Type == OptionType::Alias) {
+ Aliases.push_back(val);
+ continue;
+ }
+
+ O << val.GenTypeDeclaration() << ' '
+ << val.GenPlainVariableName();
+
+ O << "(\"" << val.Name << "\"\n";
+
+ if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
+ O << ", cl::Prefix";
+
+ if (val.isRequired()) {
+ if (val.isList() && !val.isMultiVal())
+ O << ", cl::OneOrMore";
+ else
+ O << ", cl::Required";
+ }
+
+ if (val.isOptional())
+ O << ", cl::Optional";
+
+ if (val.isOneOrMore())
+ O << ", cl::OneOrMore";
+
+ if (val.isZeroOrMore())
+ O << ", cl::ZeroOrMore";
+
+ if (val.isReallyHidden())
+ O << ", cl::ReallyHidden";
+ else if (val.isHidden())
+ O << ", cl::Hidden";
+
+ if (val.isCommaSeparated())
+ O << ", cl::CommaSeparated";
+
+ if (val.MultiVal > 1)
+ O << ", cl::multi_val(" << val.MultiVal << ')';
+
+ if (val.InitVal) {
+ const std::string& str = val.InitVal->getAsString();
+ O << ", cl::init(" << str << ')';
+ }
+
+ if (!val.Help.empty())
+ O << ", cl::desc(\"" << val.Help << "\")";
+
+ O << ");\n\n";
+ }
+
+ // Emit the aliases (they should go after all the 'proper' options).
+ for (std::vector<OptionDescription>::const_iterator
+ B = Aliases.begin(), E = Aliases.end(); B != E; ++B) {
+ const OptionDescription& val = *B;
+
+ O << val.GenTypeDeclaration() << ' '
+ << val.GenPlainVariableName()
+ << "(\"" << val.Name << '\"';
+
+ const OptionDescription& D = descs.FindOption(val.Help);
+ O << ", cl::aliasopt(" << D.GenVariableName() << ")";
+
+ O << ", cl::desc(\"" << "An alias for -" + val.Help << "\"));\n";
+ }
+
+ // Emit the sink option.
+ if (HasSink)
+ O << "cl::list<std::string> " << SinkOptionName << "(cl::Sink);\n";
+
+ O << '\n';
+}
+
+/// EmitPreprocessOptionsCallback - Helper function passed to
+/// EmitCaseConstructHandler() by EmitPreprocessOptions().
+
+class EmitPreprocessOptionsCallback;
+
+typedef void
+(EmitPreprocessOptionsCallback::* EmitPreprocessOptionsCallbackHandler)
+(const DagInit&, unsigned, raw_ostream&) const;
+
+class EmitPreprocessOptionsCallback :
+ public ActionHandlingCallbackBase,
+ public HandlerTable<EmitPreprocessOptionsCallbackHandler>
+{
+ typedef EmitPreprocessOptionsCallbackHandler Handler;
+ typedef void
+ (EmitPreprocessOptionsCallback::* HandlerImpl)
+ (const Init*, unsigned, raw_ostream&) const;
+
+ const OptionDescriptions& OptDescs_;
+
+ void onListOrDag(const DagInit& d, HandlerImpl h,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(d, 1);
+ const Init* I = d.getArg(0);
+
+ // If I is a list, apply h to each element.
+ if (typeid(*I) == typeid(ListInit)) {
+ const ListInit& L = *static_cast<const ListInit*>(I);
+ for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B)
+ ((this)->*(h))(*B, IndentLevel, O);
+ }
+ // Otherwise, apply h to I.
+ else {
+ ((this)->*(h))(I, IndentLevel, O);
+ }
+ }
+
+ void onUnsetOptionImpl(const Init* I,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ const std::string& OptName = InitPtrToString(I);
+ const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
+
+ if (OptDesc.isSwitch()) {
+ O.indent(IndentLevel) << OptDesc.GenVariableName() << " = false;\n";
+ }
+ else if (OptDesc.isParameter()) {
+ O.indent(IndentLevel) << OptDesc.GenVariableName() << " = \"\";\n";
+ }
+ else if (OptDesc.isList()) {
+ O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
+ }
+ else {
+ throw "Can't apply 'unset_option' to alias option '" + OptName + "'!";
+ }
+ }
+
+ void onUnsetOption(const DagInit& d,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ this->onListOrDag(d, &EmitPreprocessOptionsCallback::onUnsetOptionImpl,
+ IndentLevel, O);
+ }
+
+ void onSetOptionImpl(const DagInit& d,
+ unsigned IndentLevel, raw_ostream& O) const {
+ CheckNumberOfArguments(d, 2);
+ const std::string& OptName = InitPtrToString(d.getArg(0));
+ const Init* Value = d.getArg(1);
+ const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
+
+ if (OptDesc.isList()) {
+ const ListInit& List = InitPtrToList(Value);
+
+ O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
+ for (ListInit::const_iterator B = List.begin(), E = List.end();
+ B != E; ++B) {
+ const Init* CurElem = *B;
+ if (OptDesc.isSwitchList())
+ CheckBooleanConstant(CurElem);
+
+ O.indent(IndentLevel)
+ << OptDesc.GenVariableName() << ".push_back(\""
+ << (OptDesc.isSwitchList() ? CurElem->getAsString()
+ : InitPtrToString(CurElem))
+ << "\");\n";
+ }
+ }
+ else if (OptDesc.isSwitch()) {
+ CheckBooleanConstant(Value);
+ O.indent(IndentLevel) << OptDesc.GenVariableName()
+ << " = " << Value->getAsString() << ";\n";
+ }
+ else if (OptDesc.isParameter()) {
+ const std::string& Str = InitPtrToString(Value);
+ O.indent(IndentLevel) << OptDesc.GenVariableName()
+ << " = \"" << Str << "\";\n";
+ }
+ else {
+ throw "Can't apply 'set_option' to alias option -" + OptName + " !";
+ }
+ }
+
+ void onSetSwitch(const Init* I,
+ unsigned IndentLevel, raw_ostream& O) const {
+ const std::string& OptName = InitPtrToString(I);
+ const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
+
+ if (OptDesc.isSwitch())
+ O.indent(IndentLevel) << OptDesc.GenVariableName() << " = true;\n";
+ else
+ throw "set_option: -" + OptName + " is not a switch option!";
+ }
+
+ void onSetOption(const DagInit& d,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(d, 1);
+
+ // Two arguments: (set_option "parameter", VALUE), where VALUE can be a
+ // boolean, a string or a string list.
+ if (d.getNumArgs() > 1)
+ this->onSetOptionImpl(d, IndentLevel, O);
+ // One argument: (set_option "switch")
+ // or (set_option ["switch1", "switch2", ...])
+ else
+ this->onListOrDag(d, &EmitPreprocessOptionsCallback::onSetSwitch,
+ IndentLevel, O);
+ }
+
+public:
+
+ EmitPreprocessOptionsCallback(const OptionDescriptions& OptDescs)
+ : OptDescs_(OptDescs)
+ {
+ if (!staticMembersInitialized_) {
+ AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag);
+ AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag);
+ AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption);
+ AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption);
+
+ staticMembersInitialized_ = true;
+ }
+ }
+
+ void operator()(const Init* I,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ InvokeDagInitHandler(this, I, IndentLevel, O);
+ }
+
+};
+
+/// EmitPreprocessOptions - Emit the PreprocessOptions() function.
+void EmitPreprocessOptions (const RecordKeeper& Records,
+ const OptionDescriptions& OptDecs, raw_ostream& O)
+{
+ O << "int PreprocessOptions () {\n";
+
+ const RecordVector& OptionPreprocessors =
+ Records.getAllDerivedDefinitions("OptionPreprocessor");
+
+ for (RecordVector::const_iterator B = OptionPreprocessors.begin(),
+ E = OptionPreprocessors.end(); B!=E; ++B) {
+ DagInit* Case = (*B)->getValueAsDag("preprocessor");
+ EmitCaseConstructHandler(Case, Indent1,
+ EmitPreprocessOptionsCallback(OptDecs),
+ false, OptDecs, O);
+ }
+
+ O << '\n';
+ O.indent(Indent1) << "return 0;\n";
+ O << "}\n\n";
+}
+
+class DoEmitPopulateLanguageMap;
+typedef void (DoEmitPopulateLanguageMap::* DoEmitPopulateLanguageMapHandler)
+(const DagInit& D);
+
+class DoEmitPopulateLanguageMap
+: public HandlerTable<DoEmitPopulateLanguageMapHandler>
+{
+private:
+ raw_ostream& O_;
+
+public:
+
+ explicit DoEmitPopulateLanguageMap (raw_ostream& O) : O_(O) {
+ if (!staticMembersInitialized_) {
+ AddHandler("lang_to_suffixes",
+ &DoEmitPopulateLanguageMap::onLangToSuffixes);
+
+ staticMembersInitialized_ = true;
+ }
+ }
+
+ void operator() (Init* I) {
+ InvokeDagInitHandler(this, I);
+ }
+
+private:
+
+ void onLangToSuffixes (const DagInit& d) {
+ CheckNumberOfArguments(d, 2);
+
+ const std::string& Lang = InitPtrToString(d.getArg(0));
+ Init* Suffixes = d.getArg(1);
+
+ // Second argument to lang_to_suffixes is either a single string...
+ if (typeid(*Suffixes) == typeid(StringInit)) {
+ O_.indent(Indent1) << "langMap[\"" << InitPtrToString(Suffixes)
+ << "\"] = \"" << Lang << "\";\n";
+ }
+ // ...or a list of strings.
+ else {
+ const ListInit& Lst = InitPtrToList(Suffixes);
+ assert(Lst.size() != 0);
+ for (ListInit::const_iterator B = Lst.begin(), E = Lst.end();
+ B != E; ++B) {
+ O_.indent(Indent1) << "langMap[\"" << InitPtrToString(*B)
+ << "\"] = \"" << Lang << "\";\n";
+ }
+ }
+ }
+
+};
+
+/// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
+void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
+{
+ O << "int PopulateLanguageMap (LanguageMap& langMap) {\n";
+
+ // For each LangMap:
+ const RecordVector& LangMaps =
+ Records.getAllDerivedDefinitions("LanguageMap");
+
+ for (RecordVector::const_iterator B = LangMaps.begin(),
+ E = LangMaps.end(); B!=E; ++B) {
+ ListInit* LangMap = (*B)->getValueAsListInit("map");
+ std::for_each(LangMap->begin(), LangMap->end(),
+ DoEmitPopulateLanguageMap(O));
+ }
+
+ O << '\n';
+ O.indent(Indent1) << "return 0;\n";
+ O << "}\n\n";
+}
+
+/// EmitEdgePropertyHandlerCallback - Emits code that handles edge
+/// properties. Helper function passed to EmitCaseConstructHandler() by
+/// EmitEdgeClass().
+void EmitEdgePropertyHandlerCallback (const Init* i, unsigned IndentLevel,
+ raw_ostream& O) {
+ const DagInit& d = InitPtrToDag(i);
+ const std::string& OpName = GetOperatorName(d);
+
+ if (OpName == "inc_weight") {
+ O.indent(IndentLevel) << "ret += ";
+ }
+ else if (OpName == "error") {
+ CheckNumberOfArguments(d, 1);
+ O.indent(IndentLevel) << "PrintError(\""
+ << InitPtrToString(d.getArg(0))
+ << "\");\n";
+ O.indent(IndentLevel) << "return -1;\n";
+ return;
+ }
+ else {
+ throw "Unknown operator in edge properties list: '" + OpName + "'!"
+ "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";
+ }
+
+ if (d.getNumArgs() > 0)
+ O << InitPtrToInt(d.getArg(0)) << ";\n";
+ else
+ O << "2;\n";
+
+}
+
+/// EmitEdgeClass - Emit a single Edge# class.
+void EmitEdgeClass (unsigned N, const std::string& Target,
+ const DagInit& Case, const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+
+ // Class constructor.
+ O << "class Edge" << N << ": public Edge {\n"
+ << "public:\n";
+ O.indent(Indent1) << "Edge" << N << "() : Edge(\"" << Target
+ << "\") {}\n\n";
+
+ // Function Weight().
+ O.indent(Indent1)
+ << "int Weight(const InputLanguagesSet& InLangs) const {\n";
+ O.indent(Indent2) << "unsigned ret = 0;\n";
+
+ // Handle the 'case' construct.
+ EmitCaseConstructHandler(&Case, Indent2, EmitEdgePropertyHandlerCallback,
+ false, OptDescs, O);
+
+ O.indent(Indent2) << "return ret;\n";
+ O.indent(Indent1) << "}\n\n};\n\n";
+}
+
+/// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
+void EmitEdgeClasses (const DagVector& EdgeVector,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O) {
+ int i = 0;
+ for (DagVector::const_iterator B = EdgeVector.begin(),
+ E = EdgeVector.end(); B != E; ++B) {
+ const DagInit& Edge = **B;
+ const std::string& Name = GetOperatorName(Edge);
+
+ if (Name == "optional_edge") {
+ assert(IsOptionalEdge(Edge));
+ const std::string& NodeB = InitPtrToString(Edge.getArg(1));
+
+ const DagInit& Weight = InitPtrToDag(Edge.getArg(2));
+ EmitEdgeClass(i, NodeB, Weight, OptDescs, O);
+ }
+ else if (Name != "edge") {
+ throw "Unknown edge class: '" + Name + "'!";
+ }
+
+ ++i;
+ }
+}
+
+/// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph() function.
+void EmitPopulateCompilationGraph (const DagVector& EdgeVector,
+ const ToolDescriptions& ToolDescs,
+ raw_ostream& O)
+{
+ O << "int PopulateCompilationGraph (CompilationGraph& G) {\n";
+
+ for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
+ E = ToolDescs.end(); B != E; ++B)
+ O.indent(Indent1) << "G.insertNode(new " << (*B)->Name << "());\n";
+
+ O << '\n';
+
+ // Insert edges.
+
+ int i = 0;
+ for (DagVector::const_iterator B = EdgeVector.begin(),
+ E = EdgeVector.end(); B != E; ++B) {
+ const DagInit& Edge = **B;
+ const std::string& NodeA = InitPtrToString(Edge.getArg(0));
+ const std::string& NodeB = InitPtrToString(Edge.getArg(1));
+
+ O.indent(Indent1) << "if (int ret = G.insertEdge(\"" << NodeA << "\", ";
+
+ if (IsOptionalEdge(Edge))
+ O << "new Edge" << i << "()";
+ else
+ O << "new SimpleEdge(\"" << NodeB << "\")";
+
+ O << "))\n";
+ O.indent(Indent2) << "return ret;\n";
+
+ ++i;
+ }
+
+ O << '\n';
+ O.indent(Indent1) << "return 0;\n";
+ O << "}\n\n";
+}
+
+/// HookInfo - Information about the hook type and number of arguments.
+struct HookInfo {
+
+ // A hook can either have a single parameter of type std::vector<std::string>,
+ // or NumArgs parameters of type const char*.
+ enum HookType { ListHook, ArgHook };
+
+ HookType Type;
+ unsigned NumArgs;
+
+ HookInfo() : Type(ArgHook), NumArgs(1)
+ {}
+
+ HookInfo(HookType T) : Type(T), NumArgs(1)
+ {}
+
+ HookInfo(unsigned N) : Type(ArgHook), NumArgs(N)
+ {}
+};
+
+typedef llvm::StringMap<HookInfo> HookInfoMap;
+
+/// ExtractHookNames - Extract the hook names from all instances of
+/// $CALL(HookName) in the provided command line string/action. Helper
+/// function used by FillInHookNames().
+class ExtractHookNames {
+ HookInfoMap& HookNames_;
+ const OptionDescriptions& OptDescs_;
+public:
+ ExtractHookNames(HookInfoMap& HookNames, const OptionDescriptions& OptDescs)
+ : HookNames_(HookNames), OptDescs_(OptDescs)
+ {}
+
+ void onAction (const DagInit& Dag) {
+ const std::string& Name = GetOperatorName(Dag);
+
+ if (Name == "forward_transformed_value") {
+ CheckNumberOfArguments(Dag, 2);
+ const std::string& OptName = InitPtrToString(Dag.getArg(0));
+ const std::string& HookName = InitPtrToString(Dag.getArg(1));
+ const OptionDescription& D =
+ OptDescs_.FindParameterListOrParameter(OptName);
+
+ HookNames_[HookName] = HookInfo(D.isList() ? HookInfo::ListHook
+ : HookInfo::ArgHook);
+ }
+ else if (Name == "append_cmd" || Name == "output_suffix") {
+ CheckNumberOfArguments(Dag, 1);
+ this->onCmdLine(InitPtrToString(Dag.getArg(0)));
+ }
+ }
+
+ void onCmdLine(const std::string& Cmd) {
+ StrVector cmds;
+ TokenizeCmdLine(Cmd, cmds);
+
+ for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
+ B != E; ++B) {
+ const std::string& cmd = *B;
+
+ if (cmd == "$CALL") {
+ unsigned NumArgs = 0;
+ CheckedIncrement(B, E, "Syntax error in $CALL invocation!");
+ const std::string& HookName = *B;
+
+ if (HookName.at(0) == ')')
+ throw "$CALL invoked with no arguments!";
+
+ while (++B != E && B->at(0) != ')') {
+ ++NumArgs;
+ }
+
+ HookInfoMap::const_iterator H = HookNames_.find(HookName);
+
+ if (H != HookNames_.end() && H->second.NumArgs != NumArgs &&
+ H->second.Type != HookInfo::ArgHook)
+ throw "Overloading of hooks is not allowed. Overloaded hook: "
+ + HookName;
+ else
+ HookNames_[HookName] = HookInfo(NumArgs);
+ }
+ }
+ }
+
+ void operator()(const Init* Arg) {
+
+ // We're invoked on an action (either a dag or a dag list).
+ if (typeid(*Arg) == typeid(DagInit)) {
+ const DagInit& Dag = InitPtrToDag(Arg);
+ this->onAction(Dag);
+ return;
+ }
+ else if (typeid(*Arg) == typeid(ListInit)) {
+ const ListInit& List = InitPtrToList(Arg);
+ for (ListInit::const_iterator B = List.begin(), E = List.end(); B != E;
+ ++B) {
+ const DagInit& Dag = InitPtrToDag(*B);
+ this->onAction(Dag);
+ }
+ return;
+ }
+
+ // We're invoked on a command line.
+ this->onCmdLine(InitPtrToString(Arg));
+ }
+
+ void operator()(const Init* Statement, unsigned) {
+ this->operator()(Statement);
+ }
+};
+
+/// FillInHookNames - Actually extract the hook names from all command
+/// line strings. Helper function used by EmitHookDeclarations().
+void FillInHookNames(const ToolDescriptions& ToolDescs,
+ const OptionDescriptions& OptDescs,
+ HookInfoMap& HookNames)
+{
+ // For all tool descriptions:
+ for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
+ E = ToolDescs.end(); B != E; ++B) {
+ const ToolDescription& D = *(*B);
+
+ // Look for 'forward_transformed_value' in 'actions'.
+ if (D.Actions)
+ WalkCase(D.Actions, Id(), ExtractHookNames(HookNames, OptDescs));
+
+ // Look for hook invocations in 'cmd_line'.
+ if (!D.CmdLine)
+ continue;
+ if (dynamic_cast<StringInit*>(D.CmdLine))
+ // This is a string.
+ ExtractHookNames(HookNames, OptDescs).operator()(D.CmdLine);
+ else
+ // This is a 'case' construct.
+ WalkCase(D.CmdLine, Id(), ExtractHookNames(HookNames, OptDescs));
+ }
+}
+
+/// EmitHookDeclarations - Parse CmdLine fields of all the tool
+/// property records and emit hook function declaration for each
+/// instance of $CALL(HookName).
+void EmitHookDeclarations(const ToolDescriptions& ToolDescs,
+ const OptionDescriptions& OptDescs, raw_ostream& O) {
+ HookInfoMap HookNames;
+
+ FillInHookNames(ToolDescs, OptDescs, HookNames);
+ if (HookNames.empty())
+ return;
+
+ for (HookInfoMap::const_iterator B = HookNames.begin(),
+ E = HookNames.end(); B != E; ++B) {
+ const char* HookName = B->first();
+ const HookInfo& Info = B->second;
+
+ O.indent(Indent1) << "std::string " << HookName << "(";
+
+ if (Info.Type == HookInfo::ArgHook) {
+ for (unsigned i = 0, j = Info.NumArgs; i < j; ++i) {
+ O << "const char* Arg" << i << (i+1 == j ? "" : ", ");
+ }
+ }
+ else {
+ O << "const std::vector<std::string>& Arg";
+ }
+
+ O <<");\n";
+ }
+}
+
+/// EmitIncludes - Emit necessary #include directives and some
+/// additional declarations.
+void EmitIncludes(raw_ostream& O) {
+ O << "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n"
+ << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
+ << "#include \"llvm/CompilerDriver/Error.h\"\n"
+ << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
+
+ << "#include \"llvm/Support/CommandLine.h\"\n"
+ << "#include \"llvm/Support/raw_ostream.h\"\n\n"
+
+ << "#include <algorithm>\n"
+ << "#include <cstdlib>\n"
+ << "#include <iterator>\n"
+ << "#include <stdexcept>\n\n"
+
+ << "using namespace llvm;\n"
+ << "using namespace llvmc;\n\n"
+
+ << "inline const char* checkCString(const char* s)\n"
+ << "{ return s == NULL ? \"\" : s; }\n\n";
+}
+
+
+/// DriverData - Holds all information about the driver.
+struct DriverData {
+ OptionDescriptions OptDescs;
+ ToolDescriptions ToolDescs;
+ DagVector Edges;
+ bool HasSink;
+};
+
+/// HasSink - Go through the list of tool descriptions and check if
+/// there are any with the 'sink' property set.
+bool HasSink(const ToolDescriptions& ToolDescs) {
+ for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
+ E = ToolDescs.end(); B != E; ++B)
+ if ((*B)->isSink())
+ return true;
+
+ return false;
+}
+
+/// CollectDriverData - Collect compilation graph edges, tool properties and
+/// option properties from the parse tree.
+void CollectDriverData (const RecordKeeper& Records, DriverData& Data) {
+ // Collect option properties.
+ const RecordVector& OptionLists =
+ Records.getAllDerivedDefinitions("OptionList");
+ CollectOptionDescriptions(OptionLists, Data.OptDescs);
+
+ // Collect tool properties.
+ const RecordVector& Tools = Records.getAllDerivedDefinitions("Tool");
+ CollectToolDescriptions(Tools, Data.ToolDescs);
+ Data.HasSink = HasSink(Data.ToolDescs);
+
+ // Collect compilation graph edges.
+ const RecordVector& CompilationGraphs =
+ Records.getAllDerivedDefinitions("CompilationGraph");
+ FillInEdgeVector(CompilationGraphs, Data.Edges);
+}
+
+/// CheckDriverData - Perform some sanity checks on the collected data.
+void CheckDriverData(DriverData& Data) {
+ // Filter out all tools not mentioned in the compilation graph.
+ FilterNotInGraph(Data.Edges, Data.ToolDescs);
+
+ // Typecheck the compilation graph.
+ TypecheckGraph(Data.Edges, Data.ToolDescs);
+
+ // Check that there are no options without side effects (specified
+ // only in the OptionList).
+ CheckForSuperfluousOptions(Data.Edges, Data.ToolDescs, Data.OptDescs);
+}
+
+void EmitDriverCode(const DriverData& Data, raw_ostream& O) {
+ // Emit file header.
+ EmitIncludes(O);
+
+ // Emit global option registration code.
+ O << "namespace llvmc {\n"
+ << "namespace autogenerated {\n\n";
+ EmitOptionDefinitions(Data.OptDescs, Data.HasSink, O);
+ O << "} // End namespace autogenerated.\n"
+ << "} // End namespace llvmc.\n\n";
+
+ // Emit hook declarations.
+ O << "namespace hooks {\n";
+ EmitHookDeclarations(Data.ToolDescs, Data.OptDescs, O);
+ O << "} // End namespace hooks.\n\n";
+
+ O << "namespace {\n\n";
+ O << "using namespace llvmc::autogenerated;\n\n";
+
+ // Emit Tool classes.
+ for (ToolDescriptions::const_iterator B = Data.ToolDescs.begin(),
+ E = Data.ToolDescs.end(); B!=E; ++B)
+ EmitToolClassDefinition(*(*B), Data.OptDescs, O);
+
+ // Emit Edge# classes.
+ EmitEdgeClasses(Data.Edges, Data.OptDescs, O);
+
+ O << "} // End anonymous namespace.\n\n";
+
+ O << "namespace llvmc {\n";
+ O << "namespace autogenerated {\n\n";
+
+ // Emit PreprocessOptions() function.
+ EmitPreprocessOptions(Records, Data.OptDescs, O);
+
+ // Emit PopulateLanguageMap() function
+ // (language map maps from file extensions to language names).
+ EmitPopulateLanguageMap(Records, O);
+
+ // Emit PopulateCompilationGraph() function.
+ EmitPopulateCompilationGraph(Data.Edges, Data.ToolDescs, O);
+
+ O << "} // End namespace autogenerated.\n";
+ O << "} // End namespace llvmc.\n\n";
+
+ // EOF
+}
+
+
+// End of anonymous namespace
+}
+
+/// run - The back-end entry point.
+void LLVMCConfigurationEmitter::run (raw_ostream &O) {
+ try {
+ DriverData Data;
+
+ CollectDriverData(Records, Data);
+ CheckDriverData(Data);
+
+ this->EmitSourceFileHeader("llvmc-based driver: auto-generated code", O);
+ EmitDriverCode(Data, O);
+
+ } catch (std::exception& Error) {
+ throw Error.what() + std::string(" - usually this means a syntax error.");
+ }
+}
diff --git a/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.h b/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.h
new file mode 100644
index 0000000..b37b83f
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.h
@@ -0,0 +1,32 @@
+//===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting LLVMCC configuration code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
+#define LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+
+ /// LLVMCConfigurationEmitter - TableGen backend that generates
+ /// configuration code for LLVMC.
+ class LLVMCConfigurationEmitter : public TableGenBackend {
+ public:
+ explicit LLVMCConfigurationEmitter(RecordKeeper&) {}
+
+ // run - Output the asmwriter, returning true on failure.
+ void run(raw_ostream &o);
+ };
+}
+
+#endif //LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
diff --git a/contrib/llvm/utils/TableGen/Makefile b/contrib/llvm/utils/TableGen/Makefile
new file mode 100644
index 0000000..f27cd99
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/Makefile
@@ -0,0 +1,20 @@
+##===- utils/TableGen/Makefile -----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TOOLNAME = tblgen
+USEDLIBS = LLVMSupport.a LLVMSystem.a
+REQUIRES_EH := 1
+REQUIRES_RTTI := 1
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/contrib/llvm/utils/TableGen/NeonEmitter.cpp b/contrib/llvm/utils/TableGen/NeonEmitter.cpp
new file mode 100644
index 0000000..0a12f37
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/NeonEmitter.cpp
@@ -0,0 +1,1207 @@
+//===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting arm_neon.h, which includes
+// a declaration and definition of each function specified by the ARM NEON
+// compiler interface. See ARM document DUI0348B.
+//
+// Each NEON instruction is implemented in terms of 1 or more functions which
+// are suffixed with the element type of the input vectors. Functions may be
+// implemented in terms of generic vector operations such as +, *, -, etc. or
+// by calling a __builtin_-prefixed function which will be handled by clang's
+// CodeGen library.
+//
+// Additional validation code can be generated by this file when runHeader() is
+// called, rather than the normal run() entry point.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NeonEmitter.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include <string>
+
+using namespace llvm;
+
+/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
+/// which each StringRef representing a single type declared in the string.
+/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
+/// 2xfloat and 4xfloat respectively.
+static void ParseTypes(Record *r, std::string &s,
+ SmallVectorImpl<StringRef> &TV) {
+ const char *data = s.data();
+ int len = 0;
+
+ for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
+ if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
+ continue;
+
+ switch (data[len]) {
+ case 'c':
+ case 's':
+ case 'i':
+ case 'l':
+ case 'h':
+ case 'f':
+ break;
+ default:
+ throw TGError(r->getLoc(),
+ "Unexpected letter: " + std::string(data + len, 1));
+ break;
+ }
+ TV.push_back(StringRef(data, len + 1));
+ data += len + 1;
+ len = -1;
+ }
+}
+
+/// Widen - Convert a type code into the next wider type. char -> short,
+/// short -> int, etc.
+static char Widen(const char t) {
+ switch (t) {
+ case 'c':
+ return 's';
+ case 's':
+ return 'i';
+ case 'i':
+ return 'l';
+ default: throw "unhandled type in widen!";
+ }
+ return '\0';
+}
+
+/// Narrow - Convert a type code into the next smaller type. short -> char,
+/// float -> half float, etc.
+static char Narrow(const char t) {
+ switch (t) {
+ case 's':
+ return 'c';
+ case 'i':
+ return 's';
+ case 'l':
+ return 'i';
+ case 'f':
+ return 'h';
+ default: throw "unhandled type in widen!";
+ }
+ return '\0';
+}
+
+/// For a particular StringRef, return the base type code, and whether it has
+/// the quad-vector, polynomial, or unsigned modifiers set.
+static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
+ unsigned off = 0;
+
+ // remember quad.
+ if (ty[off] == 'Q') {
+ quad = true;
+ ++off;
+ }
+
+ // remember poly.
+ if (ty[off] == 'P') {
+ poly = true;
+ ++off;
+ }
+
+ // remember unsigned.
+ if (ty[off] == 'U') {
+ usgn = true;
+ ++off;
+ }
+
+ // base type to get the type string for.
+ return ty[off];
+}
+
+/// ModType - Transform a type code and its modifiers based on a mod code. The
+/// mod code definitions may be found at the top of arm_neon.td.
+static char ModType(const char mod, char type, bool &quad, bool &poly,
+ bool &usgn, bool &scal, bool &cnst, bool &pntr) {
+ switch (mod) {
+ case 't':
+ if (poly) {
+ poly = false;
+ usgn = true;
+ }
+ break;
+ case 'u':
+ usgn = true;
+ case 'x':
+ poly = false;
+ if (type == 'f')
+ type = 'i';
+ break;
+ case 'f':
+ if (type == 'h')
+ quad = true;
+ type = 'f';
+ usgn = false;
+ break;
+ case 'g':
+ quad = false;
+ break;
+ case 'w':
+ type = Widen(type);
+ quad = true;
+ break;
+ case 'n':
+ type = Widen(type);
+ break;
+ case 'l':
+ type = 'l';
+ scal = true;
+ usgn = true;
+ break;
+ case 's':
+ case 'a':
+ scal = true;
+ break;
+ case 'k':
+ quad = true;
+ break;
+ case 'c':
+ cnst = true;
+ case 'p':
+ pntr = true;
+ scal = true;
+ break;
+ case 'h':
+ type = Narrow(type);
+ if (type == 'h')
+ quad = false;
+ break;
+ case 'e':
+ type = Narrow(type);
+ usgn = true;
+ break;
+ default:
+ break;
+ }
+ return type;
+}
+
+/// TypeString - for a modifier and type, generate the name of the typedef for
+/// that type. If generic is true, emit the generic vector type rather than
+/// the public NEON type. QUc -> uint8x8_t / __neon_uint8x8_t.
+static std::string TypeString(const char mod, StringRef typestr,
+ bool generic = false) {
+ bool quad = false;
+ bool poly = false;
+ bool usgn = false;
+ bool scal = false;
+ bool cnst = false;
+ bool pntr = false;
+
+ if (mod == 'v')
+ return "void";
+ if (mod == 'i')
+ return "int";
+
+ // base type to get the type string for.
+ char type = ClassifyType(typestr, quad, poly, usgn);
+
+ // Based on the modifying character, change the type and width if necessary.
+ type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
+
+ SmallString<128> s;
+
+ if (generic)
+ s += "__neon_";
+
+ if (usgn)
+ s.push_back('u');
+
+ switch (type) {
+ case 'c':
+ s += poly ? "poly8" : "int8";
+ if (scal)
+ break;
+ s += quad ? "x16" : "x8";
+ break;
+ case 's':
+ s += poly ? "poly16" : "int16";
+ if (scal)
+ break;
+ s += quad ? "x8" : "x4";
+ break;
+ case 'i':
+ s += "int32";
+ if (scal)
+ break;
+ s += quad ? "x4" : "x2";
+ break;
+ case 'l':
+ s += "int64";
+ if (scal)
+ break;
+ s += quad ? "x2" : "x1";
+ break;
+ case 'h':
+ s += "float16";
+ if (scal)
+ break;
+ s += quad ? "x8" : "x4";
+ break;
+ case 'f':
+ s += "float32";
+ if (scal)
+ break;
+ s += quad ? "x4" : "x2";
+ break;
+ default:
+ throw "unhandled type!";
+ break;
+ }
+
+ if (mod == '2')
+ s += "x2";
+ if (mod == '3')
+ s += "x3";
+ if (mod == '4')
+ s += "x4";
+
+ // Append _t, finishing the type string typedef type.
+ s += "_t";
+
+ if (cnst)
+ s += " const";
+
+ if (pntr)
+ s += " *";
+
+ return s.str();
+}
+
+/// BuiltinTypeString - for a modifier and type, generate the clang
+/// BuiltinsARM.def prototype code for the function. See the top of clang's
+/// Builtins.def for a description of the type strings.
+static std::string BuiltinTypeString(const char mod, StringRef typestr,
+ ClassKind ck, bool ret) {
+ bool quad = false;
+ bool poly = false;
+ bool usgn = false;
+ bool scal = false;
+ bool cnst = false;
+ bool pntr = false;
+
+ if (mod == 'v')
+ return "v";
+ if (mod == 'i')
+ return "i";
+
+ // base type to get the type string for.
+ char type = ClassifyType(typestr, quad, poly, usgn);
+
+ // Based on the modifying character, change the type and width if necessary.
+ type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
+
+ if (pntr) {
+ usgn = false;
+ poly = false;
+ type = 'v';
+ }
+ if (type == 'h') {
+ type = 's';
+ usgn = true;
+ }
+ usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
+
+ if (scal) {
+ SmallString<128> s;
+
+ if (usgn)
+ s.push_back('U');
+
+ if (type == 'l')
+ s += "LLi";
+ else
+ s.push_back(type);
+
+ if (cnst)
+ s.push_back('C');
+ if (pntr)
+ s.push_back('*');
+ return s.str();
+ }
+
+ // Since the return value must be one type, return a vector type of the
+ // appropriate width which we will bitcast. An exception is made for
+ // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
+ // fashion, storing them to a pointer arg.
+ if (ret) {
+ if (mod == '2' || mod == '3' || mod == '4')
+ return "vv*";
+ if (mod == 'f' || (ck != ClassB && type == 'f'))
+ return quad ? "V4f" : "V2f";
+ if (ck != ClassB && type == 's')
+ return quad ? "V8s" : "V4s";
+ if (ck != ClassB && type == 'i')
+ return quad ? "V4i" : "V2i";
+ if (ck != ClassB && type == 'l')
+ return quad ? "V2LLi" : "V1LLi";
+
+ return quad ? "V16c" : "V8c";
+ }
+
+ // Non-return array types are passed as individual vectors.
+ if (mod == '2')
+ return quad ? "V16cV16c" : "V8cV8c";
+ if (mod == '3')
+ return quad ? "V16cV16cV16c" : "V8cV8cV8c";
+ if (mod == '4')
+ return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c";
+
+ if (mod == 'f' || (ck != ClassB && type == 'f'))
+ return quad ? "V4f" : "V2f";
+ if (ck != ClassB && type == 's')
+ return quad ? "V8s" : "V4s";
+ if (ck != ClassB && type == 'i')
+ return quad ? "V4i" : "V2i";
+ if (ck != ClassB && type == 'l')
+ return quad ? "V2LLi" : "V1LLi";
+
+ return quad ? "V16c" : "V8c";
+}
+
+/// StructTag - generate the name of the struct tag for a type.
+/// These names are mandated by ARM's ABI.
+static std::string StructTag(StringRef typestr) {
+ bool quad = false;
+ bool poly = false;
+ bool usgn = false;
+
+ // base type to get the type string for.
+ char type = ClassifyType(typestr, quad, poly, usgn);
+
+ SmallString<128> s;
+ s += "__simd";
+ s += quad ? "128_" : "64_";
+ if (usgn)
+ s.push_back('u');
+
+ switch (type) {
+ case 'c':
+ s += poly ? "poly8" : "int8";
+ break;
+ case 's':
+ s += poly ? "poly16" : "int16";
+ break;
+ case 'i':
+ s += "int32";
+ break;
+ case 'l':
+ s += "int64";
+ break;
+ case 'h':
+ s += "float16";
+ break;
+ case 'f':
+ s += "float32";
+ break;
+ default:
+ throw "unhandled type!";
+ break;
+ }
+
+ // Append _t, finishing the struct tag name.
+ s += "_t";
+
+ return s.str();
+}
+
+/// MangleName - Append a type or width suffix to a base neon function name,
+/// and insert a 'q' in the appropriate location if the operation works on
+/// 128b rather than 64b. E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
+static std::string MangleName(const std::string &name, StringRef typestr,
+ ClassKind ck) {
+ if (name == "vcvt_f32_f16")
+ return name;
+
+ bool quad = false;
+ bool poly = false;
+ bool usgn = false;
+ char type = ClassifyType(typestr, quad, poly, usgn);
+
+ std::string s = name;
+
+ switch (type) {
+ case 'c':
+ switch (ck) {
+ case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
+ case ClassI: s += "_i8"; break;
+ case ClassW: s += "_8"; break;
+ default: break;
+ }
+ break;
+ case 's':
+ switch (ck) {
+ case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
+ case ClassI: s += "_i16"; break;
+ case ClassW: s += "_16"; break;
+ default: break;
+ }
+ break;
+ case 'i':
+ switch (ck) {
+ case ClassS: s += usgn ? "_u32" : "_s32"; break;
+ case ClassI: s += "_i32"; break;
+ case ClassW: s += "_32"; break;
+ default: break;
+ }
+ break;
+ case 'l':
+ switch (ck) {
+ case ClassS: s += usgn ? "_u64" : "_s64"; break;
+ case ClassI: s += "_i64"; break;
+ case ClassW: s += "_64"; break;
+ default: break;
+ }
+ break;
+ case 'h':
+ switch (ck) {
+ case ClassS:
+ case ClassI: s += "_f16"; break;
+ case ClassW: s += "_16"; break;
+ default: break;
+ }
+ break;
+ case 'f':
+ switch (ck) {
+ case ClassS:
+ case ClassI: s += "_f32"; break;
+ case ClassW: s += "_32"; break;
+ default: break;
+ }
+ break;
+ default:
+ throw "unhandled type!";
+ break;
+ }
+ if (ck == ClassB)
+ s += "_v";
+
+ // Insert a 'q' before the first '_' character so that it ends up before
+ // _lane or _n on vector-scalar operations.
+ if (quad) {
+ size_t pos = s.find('_');
+ s = s.insert(pos, "q");
+ }
+ return s;
+}
+
+// Generate the string "(argtype a, argtype b, ...)"
+static std::string GenArgs(const std::string &proto, StringRef typestr) {
+ bool define = proto.find('i') != std::string::npos;
+ char arg = 'a';
+
+ std::string s;
+ s += "(";
+
+ for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+ if (!define) {
+ s += TypeString(proto[i], typestr);
+ s.push_back(' ');
+ }
+ s.push_back(arg);
+ if ((i + 1) < e)
+ s += ", ";
+ }
+
+ s += ")";
+ return s;
+}
+
+static std::string Duplicate(unsigned nElts, StringRef typestr,
+ const std::string &a) {
+ std::string s;
+
+ s = "(__neon_" + TypeString('d', typestr) + "){ ";
+ for (unsigned i = 0; i != nElts; ++i) {
+ s += a;
+ if ((i + 1) < nElts)
+ s += ", ";
+ }
+ s += " }";
+
+ return s;
+}
+
+// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
+// If structTypes is true, the NEON types are structs of vector types rather
+// than vector types, and the call becomes "a.val + b.val"
+static std::string GenOpString(OpKind op, const std::string &proto,
+ StringRef typestr, bool structTypes = true) {
+ bool dummy, quad = false;
+ char type = ClassifyType(typestr, quad, dummy, dummy);
+ unsigned nElts = 0;
+ switch (type) {
+ case 'c': nElts = 8; break;
+ case 's': nElts = 4; break;
+ case 'i': nElts = 2; break;
+ case 'l': nElts = 1; break;
+ case 'h': nElts = 4; break;
+ case 'f': nElts = 2; break;
+ }
+
+ std::string ts = TypeString(proto[0], typestr);
+ std::string s = ts + " r; r";
+
+ if (structTypes)
+ s += ".val";
+
+ s += " = ";
+
+ std::string a, b, c;
+ if (proto.size() > 1)
+ a = (structTypes && proto[1] != 'l' && proto[1] != 's') ? "a.val" : "a";
+ b = structTypes ? "b.val" : "b";
+ c = structTypes ? "c.val" : "c";
+
+ switch(op) {
+ case OpAdd:
+ s += a + " + " + b;
+ break;
+ case OpSub:
+ s += a + " - " + b;
+ break;
+ case OpMulN:
+ b = Duplicate(nElts << (int)quad, typestr, "b");
+ case OpMul:
+ s += a + " * " + b;
+ break;
+ case OpMlaN:
+ c = Duplicate(nElts << (int)quad, typestr, "c");
+ case OpMla:
+ s += a + " + ( " + b + " * " + c + " )";
+ break;
+ case OpMlsN:
+ c = Duplicate(nElts << (int)quad, typestr, "c");
+ case OpMls:
+ s += a + " - ( " + b + " * " + c + " )";
+ break;
+ case OpEq:
+ s += "(__neon_" + ts + ")(" + a + " == " + b + ")";
+ break;
+ case OpGe:
+ s += "(__neon_" + ts + ")(" + a + " >= " + b + ")";
+ break;
+ case OpLe:
+ s += "(__neon_" + ts + ")(" + a + " <= " + b + ")";
+ break;
+ case OpGt:
+ s += "(__neon_" + ts + ")(" + a + " > " + b + ")";
+ break;
+ case OpLt:
+ s += "(__neon_" + ts + ")(" + a + " < " + b + ")";
+ break;
+ case OpNeg:
+ s += " -" + a;
+ break;
+ case OpNot:
+ s += " ~" + a;
+ break;
+ case OpAnd:
+ s += a + " & " + b;
+ break;
+ case OpOr:
+ s += a + " | " + b;
+ break;
+ case OpXor:
+ s += a + " ^ " + b;
+ break;
+ case OpAndNot:
+ s += a + " & ~" + b;
+ break;
+ case OpOrNot:
+ s += a + " | ~" + b;
+ break;
+ case OpCast:
+ s += "(__neon_" + ts + ")" + a;
+ break;
+ case OpConcat:
+ s += "__builtin_shufflevector((__neon_int64x1_t)" + a;
+ s += ", (__neon_int64x1_t)" + b + ", 0, 1)";
+ break;
+ case OpHi:
+ s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[1])";
+ break;
+ case OpLo:
+ s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[0])";
+ break;
+ case OpDup:
+ s += Duplicate(nElts << (int)quad, typestr, a);
+ break;
+ case OpSelect:
+ // ((0 & 1) | (~0 & 2))
+ ts = TypeString(proto[1], typestr);
+ s += "( " + a + " & (__neon_" + ts + ")" + b + ") | ";
+ s += "(~" + a + " & (__neon_" + ts + ")" + c + ")";
+ break;
+ case OpRev16:
+ s += "__builtin_shufflevector(" + a + ", " + a;
+ for (unsigned i = 2; i <= nElts << (int)quad; i += 2)
+ for (unsigned j = 0; j != 2; ++j)
+ s += ", " + utostr(i - j - 1);
+ s += ")";
+ break;
+ case OpRev32:
+ nElts >>= 1;
+ s += "__builtin_shufflevector(" + a + ", " + a;
+ for (unsigned i = nElts; i <= nElts << (1 + (int)quad); i += nElts)
+ for (unsigned j = 0; j != nElts; ++j)
+ s += ", " + utostr(i - j - 1);
+ s += ")";
+ break;
+ case OpRev64:
+ s += "__builtin_shufflevector(" + a + ", " + a;
+ for (unsigned i = nElts; i <= nElts << (int)quad; i += nElts)
+ for (unsigned j = 0; j != nElts; ++j)
+ s += ", " + utostr(i - j - 1);
+ s += ")";
+ break;
+ default:
+ throw "unknown OpKind!";
+ break;
+ }
+ s += "; return r;";
+ return s;
+}
+
+static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
+ unsigned mod = proto[0];
+ unsigned ret = 0;
+
+ if (mod == 'v' || mod == 'f')
+ mod = proto[1];
+
+ bool quad = false;
+ bool poly = false;
+ bool usgn = false;
+ bool scal = false;
+ bool cnst = false;
+ bool pntr = false;
+
+ // Base type to get the type string for.
+ char type = ClassifyType(typestr, quad, poly, usgn);
+
+ // Based on the modifying character, change the type and width if necessary.
+ type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
+
+ if (usgn)
+ ret |= 0x08;
+ if (quad && proto[1] != 'g')
+ ret |= 0x10;
+
+ switch (type) {
+ case 'c':
+ ret |= poly ? 5 : 0;
+ break;
+ case 's':
+ ret |= poly ? 6 : 1;
+ break;
+ case 'i':
+ ret |= 2;
+ break;
+ case 'l':
+ ret |= 3;
+ break;
+ case 'h':
+ ret |= 7;
+ break;
+ case 'f':
+ ret |= 4;
+ break;
+ default:
+ throw "unhandled type!";
+ break;
+ }
+ return ret;
+}
+
+// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
+// If structTypes is true, the NEON types are structs of vector types rather
+// than vector types, and the call becomes __builtin_neon_cls(a.val)
+static std::string GenBuiltin(const std::string &name, const std::string &proto,
+ StringRef typestr, ClassKind ck,
+ bool structTypes = true) {
+ bool dummy, quad = false;
+ char type = ClassifyType(typestr, quad, dummy, dummy);
+ unsigned nElts = 0;
+ switch (type) {
+ case 'c': nElts = 8; break;
+ case 's': nElts = 4; break;
+ case 'i': nElts = 2; break;
+ case 'l': nElts = 1; break;
+ case 'h': nElts = 4; break;
+ case 'f': nElts = 2; break;
+ }
+ if (quad) nElts <<= 1;
+
+ char arg = 'a';
+ std::string s;
+
+ // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
+ // sret-like argument.
+ bool sret = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
+
+ // If this builtin takes an immediate argument, we need to #define it rather
+ // than use a standard declaration, so that SemaChecking can range check
+ // the immediate passed by the user.
+ bool define = proto.find('i') != std::string::npos;
+
+ // If all types are the same size, bitcasting the args will take care
+ // of arg checking. The actual signedness etc. will be taken care of with
+ // special enums.
+ if (proto.find('s') == std::string::npos)
+ ck = ClassB;
+
+ if (proto[0] != 'v') {
+ std::string ts = TypeString(proto[0], typestr);
+
+ if (define) {
+ if (sret)
+ s += "({ " + ts + " r; ";
+ else if (proto[0] != 's')
+ s += "(" + ts + "){(__neon_" + ts + ")";
+ } else if (sret) {
+ s += ts + " r; ";
+ } else {
+ s += ts + " r; r";
+ if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l')
+ s += ".val";
+
+ s += " = ";
+ }
+ }
+
+ bool splat = proto.find('a') != std::string::npos;
+
+ s += "__builtin_neon_";
+ if (splat) {
+ std::string vname(name, 0, name.size()-2);
+ s += MangleName(vname, typestr, ck);
+ } else {
+ s += MangleName(name, typestr, ck);
+ }
+ s += "(";
+
+ // Pass the address of the return variable as the first argument to sret-like
+ // builtins.
+ if (sret)
+ s += "&r, ";
+
+ for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+ std::string args = std::string(&arg, 1);
+ if (define)
+ args = "(" + args + ")";
+
+ // Handle multiple-vector values specially, emitting each subvector as an
+ // argument to the __builtin.
+ if (structTypes && (proto[i] == '2' || proto[i] == '3' || proto[i] == '4')){
+ for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
+ s += args + ".val[" + utostr(vi) + "].val";
+ if ((vi + 1) < ve)
+ s += ", ";
+ }
+ if ((i + 1) < e)
+ s += ", ";
+
+ continue;
+ }
+
+ if (splat && (i + 1) == e)
+ s += Duplicate(nElts, typestr, args);
+ else
+ s += args;
+
+ if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
+ proto[i] != 'p' && proto[i] != 'c' && proto[i] != 'a') {
+ s += ".val";
+ }
+ if ((i + 1) < e)
+ s += ", ";
+ }
+
+ // Extra constant integer to hold type class enum for this function, e.g. s8
+ if (ck == ClassB)
+ s += ", " + utostr(GetNeonEnum(proto, typestr));
+
+ if (define)
+ s += ")";
+ else
+ s += ");";
+
+ if (proto[0] != 'v') {
+ if (define) {
+ if (sret)
+ s += "; r; })";
+ else if (proto[0] != 's')
+ s += "}";
+ } else {
+ s += " return r;";
+ }
+ }
+ return s;
+}
+
+static std::string GenBuiltinDef(const std::string &name,
+ const std::string &proto,
+ StringRef typestr, ClassKind ck) {
+ std::string s("BUILTIN(__builtin_neon_");
+
+ // If all types are the same size, bitcasting the args will take care
+ // of arg checking. The actual signedness etc. will be taken care of with
+ // special enums.
+ if (proto.find('s') == std::string::npos)
+ ck = ClassB;
+
+ s += MangleName(name, typestr, ck);
+ s += ", \"";
+
+ for (unsigned i = 0, e = proto.size(); i != e; ++i)
+ s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
+
+ // Extra constant integer to hold type class enum for this function, e.g. s8
+ if (ck == ClassB)
+ s += "i";
+
+ s += "\", \"n\")";
+ return s;
+}
+
+/// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h
+/// is comprised of type definitions and function declarations.
+void NeonEmitter::run(raw_ostream &OS) {
+ EmitSourceFileHeader("ARM NEON Header", OS);
+
+ // FIXME: emit license into file?
+
+ OS << "#ifndef __ARM_NEON_H\n";
+ OS << "#define __ARM_NEON_H\n\n";
+
+ OS << "#ifndef __ARM_NEON__\n";
+ OS << "#error \"NEON support not enabled\"\n";
+ OS << "#endif\n\n";
+
+ OS << "#include <stdint.h>\n\n";
+
+ // Emit NEON-specific scalar typedefs.
+ OS << "typedef float float32_t;\n";
+ OS << "typedef uint8_t poly8_t;\n";
+ OS << "typedef uint16_t poly16_t;\n";
+ OS << "typedef uint16_t float16_t;\n";
+
+ // Emit Neon vector typedefs.
+ std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
+ SmallVector<StringRef, 24> TDTypeVec;
+ ParseTypes(0, TypedefTypes, TDTypeVec);
+
+ // Emit vector typedefs.
+ for (unsigned v = 1; v != 5; ++v) {
+ for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
+ bool dummy, quad = false;
+ (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
+ OS << "typedef __attribute__(( __vector_size__(";
+
+ OS << utostr(8*v*(quad ? 2 : 1)) << ") )) ";
+ if (!quad)
+ OS << " ";
+
+ OS << TypeString('s', TDTypeVec[i]);
+ OS << " __neon_";
+
+ char t = (v == 1) ? 'd' : '0' + v;
+ OS << TypeString(t, TDTypeVec[i]) << ";\n";
+ }
+ }
+ OS << "\n";
+
+ // Emit struct typedefs.
+ for (unsigned vi = 1; vi != 5; ++vi) {
+ for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
+ std::string ts = TypeString('d', TDTypeVec[i], vi == 1);
+ std::string vs = TypeString((vi > 1) ? '0' + vi : 'd', TDTypeVec[i]);
+ std::string tag = (vi > 1) ? vs : StructTag(TDTypeVec[i]);
+ OS << "typedef struct " << tag << " {\n";
+ OS << " " << ts << " val";
+ if (vi > 1)
+ OS << "[" << utostr(vi) << "]";
+ OS << ";\n} " << vs << ";\n\n";
+ }
+ }
+
+ OS << "#define __ai static __attribute__((__always_inline__))\n\n";
+
+ std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
+
+ // Unique the return+pattern types, and assign them.
+ for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+ Record *R = RV[i];
+ std::string name = LowercaseString(R->getName());
+ std::string Proto = R->getValueAsString("Prototype");
+ std::string Types = R->getValueAsString("Types");
+
+ SmallVector<StringRef, 16> TypeVec;
+ ParseTypes(R, Types, TypeVec);
+
+ OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+
+ bool define = Proto.find('i') != std::string::npos;
+
+ for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+ assert(!Proto.empty() && "");
+
+ // static always inline + return type
+ if (define)
+ OS << "#define";
+ else
+ OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
+
+ // Function name with type suffix
+ OS << " " << MangleName(name, TypeVec[ti], ClassS);
+
+ // Function arguments
+ OS << GenArgs(Proto, TypeVec[ti]);
+
+ // Definition.
+ if (define)
+ OS << " ";
+ else
+ OS << " { ";
+
+ if (k != OpNone) {
+ OS << GenOpString(k, Proto, TypeVec[ti]);
+ } else {
+ if (R->getSuperClasses().size() < 2)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+
+ ClassKind ck = ClassMap[R->getSuperClasses()[1]];
+
+ if (ck == ClassNone)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+ OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
+ }
+ if (!define)
+ OS << " }";
+ OS << "\n";
+ }
+ OS << "\n";
+ }
+ OS << "#undef __ai\n\n";
+ OS << "#endif /* __ARM_NEON_H */\n";
+}
+
+static unsigned RangeFromType(StringRef typestr) {
+ // base type to get the type string for.
+ bool quad = false, dummy = false;
+ char type = ClassifyType(typestr, quad, dummy, dummy);
+
+ switch (type) {
+ case 'c':
+ return (8 << (int)quad) - 1;
+ case 'h':
+ case 's':
+ return (4 << (int)quad) - 1;
+ case 'f':
+ case 'i':
+ return (2 << (int)quad) - 1;
+ case 'l':
+ return (1 << (int)quad) - 1;
+ default:
+ throw "unhandled type!";
+ break;
+ }
+ assert(0 && "unreachable");
+ return 0;
+}
+
+/// runHeader - Emit a file with sections defining:
+/// 1. the NEON section of BuiltinsARM.def.
+/// 2. the SemaChecking code for the type overload checking.
+/// 3. the SemaChecking code for validation of intrinsic immedate arguments.
+void NeonEmitter::runHeader(raw_ostream &OS) {
+ std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
+
+ StringMap<OpKind> EmittedMap;
+
+ // Generate BuiltinsARM.def for NEON
+ OS << "#ifdef GET_NEON_BUILTINS\n";
+ for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+ Record *R = RV[i];
+ OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+ if (k != OpNone)
+ continue;
+
+ std::string Proto = R->getValueAsString("Prototype");
+
+ // Functions with 'a' (the splat code) in the type prototype should not get
+ // their own builtin as they use the non-splat variant.
+ if (Proto.find('a') != std::string::npos)
+ continue;
+
+ std::string Types = R->getValueAsString("Types");
+ SmallVector<StringRef, 16> TypeVec;
+ ParseTypes(R, Types, TypeVec);
+
+ if (R->getSuperClasses().size() < 2)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+
+ std::string name = LowercaseString(R->getName());
+ ClassKind ck = ClassMap[R->getSuperClasses()[1]];
+
+ for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+ // Generate the BuiltinsARM.def declaration for this builtin, ensuring
+ // that each unique BUILTIN() macro appears only once in the output
+ // stream.
+ std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
+ if (EmittedMap.count(bd))
+ continue;
+
+ EmittedMap[bd] = OpNone;
+ OS << bd << "\n";
+ }
+ }
+ OS << "#endif\n\n";
+
+ // Generate the overloaded type checking code for SemaChecking.cpp
+ OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
+ for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+ Record *R = RV[i];
+ OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+ if (k != OpNone)
+ continue;
+
+ std::string Proto = R->getValueAsString("Prototype");
+ std::string Types = R->getValueAsString("Types");
+ std::string name = LowercaseString(R->getName());
+
+ // Functions with 'a' (the splat code) in the type prototype should not get
+ // their own builtin as they use the non-splat variant.
+ if (Proto.find('a') != std::string::npos)
+ continue;
+
+ // Functions which have a scalar argument cannot be overloaded, no need to
+ // check them if we are emitting the type checking code.
+ if (Proto.find('s') != std::string::npos)
+ continue;
+
+ SmallVector<StringRef, 16> TypeVec;
+ ParseTypes(R, Types, TypeVec);
+
+ if (R->getSuperClasses().size() < 2)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+
+ int si = -1, qi = -1;
+ unsigned mask = 0, qmask = 0;
+ for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+ // Generate the switch case(s) for this builtin for the type validation.
+ bool quad = false, poly = false, usgn = false;
+ (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
+
+ if (quad) {
+ qi = ti;
+ qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+ } else {
+ si = ti;
+ mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+ }
+ }
+ if (mask)
+ OS << "case ARM::BI__builtin_neon_"
+ << MangleName(name, TypeVec[si], ClassB)
+ << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
+ if (qmask)
+ OS << "case ARM::BI__builtin_neon_"
+ << MangleName(name, TypeVec[qi], ClassB)
+ << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
+ }
+ OS << "#endif\n\n";
+
+ // Generate the intrinsic range checking code for shift/lane immediates.
+ OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
+ for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+ Record *R = RV[i];
+
+ OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+ if (k != OpNone)
+ continue;
+
+ std::string name = LowercaseString(R->getName());
+ std::string Proto = R->getValueAsString("Prototype");
+ std::string Types = R->getValueAsString("Types");
+
+ // Functions with 'a' (the splat code) in the type prototype should not get
+ // their own builtin as they use the non-splat variant.
+ if (Proto.find('a') != std::string::npos)
+ continue;
+
+ // Functions which do not have an immediate do not need to have range
+ // checking code emitted.
+ if (Proto.find('i') == std::string::npos)
+ continue;
+
+ SmallVector<StringRef, 16> TypeVec;
+ ParseTypes(R, Types, TypeVec);
+
+ if (R->getSuperClasses().size() < 2)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+
+ ClassKind ck = ClassMap[R->getSuperClasses()[1]];
+
+ for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+ std::string namestr, shiftstr, rangestr;
+
+ // Builtins which are overloaded by type will need to have their upper
+ // bound computed at Sema time based on the type constant.
+ if (Proto.find('s') == std::string::npos) {
+ ck = ClassB;
+ if (R->getValueAsBit("isShift")) {
+ shiftstr = ", true";
+
+ // Right shifts have an 'r' in the name, left shifts do not.
+ if (name.find('r') != std::string::npos)
+ rangestr = "l = 1; ";
+ }
+ rangestr += "u = RFT(TV" + shiftstr + ")";
+ } else {
+ rangestr = "u = " + utostr(RangeFromType(TypeVec[ti]));
+ }
+ // Make sure cases appear only once by uniquing them in a string map.
+ namestr = MangleName(name, TypeVec[ti], ck);
+ if (EmittedMap.count(namestr))
+ continue;
+ EmittedMap[namestr] = OpNone;
+
+ // Calculate the index of the immediate that should be range checked.
+ unsigned immidx = 0;
+
+ // Builtins that return a struct of multiple vectors have an extra
+ // leading arg for the struct return.
+ if (Proto[0] == '2' || Proto[0] == '3' || Proto[0] == '4')
+ ++immidx;
+
+ // Add one to the index for each argument until we reach the immediate
+ // to be checked. Structs of vectors are passed as multiple arguments.
+ for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
+ switch (Proto[ii]) {
+ default: immidx += 1; break;
+ case '2': immidx += 2; break;
+ case '3': immidx += 3; break;
+ case '4': immidx += 4; break;
+ case 'i': ie = ii + 1; break;
+ }
+ }
+ OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
+ << ": i = " << immidx << "; " << rangestr << "; break;\n";
+ }
+ }
+ OS << "#endif\n\n";
+}
diff --git a/contrib/llvm/utils/TableGen/NeonEmitter.h b/contrib/llvm/utils/TableGen/NeonEmitter.h
new file mode 100644
index 0000000..6c6760d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/NeonEmitter.h
@@ -0,0 +1,122 @@
+//===- NeonEmitter.h - Generate arm_neon.h for use with clang ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting arm_neon.h, which includes
+// a declaration and definition of each function specified by the ARM NEON
+// compiler interface. See ARM document DUI0348B.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef NEON_EMITTER_H
+#define NEON_EMITTER_H
+
+#include "Record.h"
+#include "TableGenBackend.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+
+enum OpKind {
+ OpNone,
+ OpAdd,
+ OpSub,
+ OpMul,
+ OpMla,
+ OpMls,
+ OpMulN,
+ OpMlaN,
+ OpMlsN,
+ OpEq,
+ OpGe,
+ OpLe,
+ OpGt,
+ OpLt,
+ OpNeg,
+ OpNot,
+ OpAnd,
+ OpOr,
+ OpXor,
+ OpAndNot,
+ OpOrNot,
+ OpCast,
+ OpConcat,
+ OpDup,
+ OpHi,
+ OpLo,
+ OpSelect,
+ OpRev16,
+ OpRev32,
+ OpRev64
+};
+
+enum ClassKind {
+ ClassNone,
+ ClassI,
+ ClassS,
+ ClassW,
+ ClassB
+};
+
+namespace llvm {
+
+ class NeonEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ StringMap<OpKind> OpMap;
+ DenseMap<Record*, ClassKind> ClassMap;
+
+ public:
+ NeonEmitter(RecordKeeper &R) : Records(R) {
+ OpMap["OP_NONE"] = OpNone;
+ OpMap["OP_ADD"] = OpAdd;
+ OpMap["OP_SUB"] = OpSub;
+ OpMap["OP_MUL"] = OpMul;
+ OpMap["OP_MLA"] = OpMla;
+ OpMap["OP_MLS"] = OpMls;
+ OpMap["OP_MUL_N"] = OpMulN;
+ OpMap["OP_MLA_N"] = OpMlaN;
+ OpMap["OP_MLS_N"] = OpMlsN;
+ OpMap["OP_EQ"] = OpEq;
+ OpMap["OP_GE"] = OpGe;
+ OpMap["OP_LE"] = OpLe;
+ OpMap["OP_GT"] = OpGt;
+ OpMap["OP_LT"] = OpLt;
+ OpMap["OP_NEG"] = OpNeg;
+ OpMap["OP_NOT"] = OpNot;
+ OpMap["OP_AND"] = OpAnd;
+ OpMap["OP_OR"] = OpOr;
+ OpMap["OP_XOR"] = OpXor;
+ OpMap["OP_ANDN"] = OpAndNot;
+ OpMap["OP_ORN"] = OpOrNot;
+ OpMap["OP_CAST"] = OpCast;
+ OpMap["OP_CONC"] = OpConcat;
+ OpMap["OP_HI"] = OpHi;
+ OpMap["OP_LO"] = OpLo;
+ OpMap["OP_DUP"] = OpDup;
+ OpMap["OP_SEL"] = OpSelect;
+ OpMap["OP_REV16"] = OpRev16;
+ OpMap["OP_REV32"] = OpRev32;
+ OpMap["OP_REV64"] = OpRev64;
+
+ Record *SI = R.getClass("SInst");
+ Record *II = R.getClass("IInst");
+ Record *WI = R.getClass("WInst");
+ ClassMap[SI] = ClassS;
+ ClassMap[II] = ClassI;
+ ClassMap[WI] = ClassW;
+ }
+
+ // run - Emit arm_neon.h.inc
+ void run(raw_ostream &o);
+
+ // runHeader - Emit all the __builtin prototypes used in arm_neon.h
+ void runHeader(raw_ostream &o);
+ };
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp
new file mode 100644
index 0000000..6892912
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -0,0 +1,194 @@
+//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OptParserEmitter.h"
+#include "Record.h"
+#include "llvm/ADT/STLExtras.h"
+using namespace llvm;
+
+static int StrCmpOptionName(const char *A, const char *B) {
+ char a = *A, b = *B;
+ while (a == b) {
+ if (a == '\0')
+ return 0;
+
+ a = *++A;
+ b = *++B;
+ }
+
+ if (a == '\0') // A is a prefix of B.
+ return 1;
+ if (b == '\0') // B is a prefix of A.
+ return -1;
+
+ // Otherwise lexicographic.
+ return (a < b) ? -1 : 1;
+}
+
+static int CompareOptionRecords(const void *Av, const void *Bv) {
+ const Record *A = *(Record**) Av;
+ const Record *B = *(Record**) Bv;
+
+ // Sentinel options preceed all others and are only ordered by precedence.
+ bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
+ bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
+ if (ASent != BSent)
+ return ASent ? -1 : 1;
+
+ // Compare options by name, unless they are sentinels.
+ if (!ASent)
+ if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
+ B->getValueAsString("Name").c_str()))
+ return Cmp;
+
+ // Then by the kind precedence;
+ int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
+ int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
+ assert(APrec != BPrec && "Options are equivalent!");
+ return APrec < BPrec ? -1 : 1;
+}
+
+static const std::string getOptionName(const Record &R) {
+ // Use the record name unless EnumName is defined.
+ if (dynamic_cast<UnsetInit*>(R.getValueInit("EnumName")))
+ return R.getName();
+
+ return R.getValueAsString("EnumName");
+}
+
+static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
+ OS << '"';
+ OS.write_escaped(Str);
+ OS << '"';
+ return OS;
+}
+
+void OptParserEmitter::run(raw_ostream &OS) {
+ // Get the option groups and options.
+ const std::vector<Record*> &Groups =
+ Records.getAllDerivedDefinitions("OptionGroup");
+ std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
+
+ if (GenDefs)
+ EmitSourceFileHeader("Option Parsing Definitions", OS);
+ else
+ EmitSourceFileHeader("Option Parsing Table", OS);
+
+ array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
+ if (GenDefs) {
+ OS << "#ifndef OPTION\n";
+ OS << "#error \"Define OPTION prior to including this file!\"\n";
+ OS << "#endif\n\n";
+
+ OS << "/////////\n";
+ OS << "// Groups\n\n";
+ for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
+ const Record &R = *Groups[i];
+
+ // Start a single option entry.
+ OS << "OPTION(";
+
+ // The option string.
+ OS << '"' << R.getValueAsString("Name") << '"';
+
+ // The option identifier name.
+ OS << ", "<< getOptionName(R);
+
+ // The option kind.
+ OS << ", Group";
+
+ // The containing option group (if any).
+ OS << ", ";
+ if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
+ OS << getOptionName(*DI->getDef());
+ else
+ OS << "INVALID";
+
+ // The other option arguments (unused for groups).
+ OS << ", INVALID, 0, 0";
+
+ // The option help text.
+ if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
+ OS << ",\n";
+ OS << " ";
+ write_cstring(OS, R.getValueAsString("HelpText"));
+ } else
+ OS << ", 0";
+
+ // The option meta-variable name (unused).
+ OS << ", 0)\n";
+ }
+ OS << "\n";
+
+ OS << "//////////\n";
+ OS << "// Options\n\n";
+ for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
+ const Record &R = *Opts[i];
+
+ // Start a single option entry.
+ OS << "OPTION(";
+
+ // The option string.
+ write_cstring(OS, R.getValueAsString("Name"));
+
+ // The option identifier name.
+ OS << ", "<< getOptionName(R);
+
+ // The option kind.
+ OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
+
+ // The containing option group (if any).
+ OS << ", ";
+ if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
+ OS << getOptionName(*DI->getDef());
+ else
+ OS << "INVALID";
+
+ // The option alias (if any).
+ OS << ", ";
+ if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Alias")))
+ OS << getOptionName(*DI->getDef());
+ else
+ OS << "INVALID";
+
+ // The option flags.
+ const ListInit *LI = R.getValueAsListInit("Flags");
+ if (LI->empty()) {
+ OS << ", 0";
+ } else {
+ OS << ", ";
+ for (unsigned i = 0, e = LI->size(); i != e; ++i) {
+ if (i)
+ OS << " | ";
+ OS << dynamic_cast<DefInit*>(LI->getElement(i))->getDef()->getName();
+ }
+ }
+
+ // The option parameter field.
+ OS << ", " << R.getValueAsInt("NumArgs");
+
+ // The option help text.
+ if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
+ OS << ",\n";
+ OS << " ";
+ write_cstring(OS, R.getValueAsString("HelpText"));
+ } else
+ OS << ", 0";
+
+ // The option meta-variable name.
+ OS << ", ";
+ if (!dynamic_cast<UnsetInit*>(R.getValueInit("MetaVarName")))
+ write_cstring(OS, R.getValueAsString("MetaVarName"));
+ else
+ OS << "0";
+
+ OS << ")\n";
+ }
+ }
+}
diff --git a/contrib/llvm/utils/TableGen/OptParserEmitter.h b/contrib/llvm/utils/TableGen/OptParserEmitter.h
new file mode 100644
index 0000000..241a3f2
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/OptParserEmitter.h
@@ -0,0 +1,34 @@
+//===- OptParserEmitter.h - Table Driven Command Line Parsing ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef UTILS_TABLEGEN_OPTPARSEREMITTER_H
+#define UTILS_TABLEGEN_OPTPARSEREMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+ /// OptParserEmitter - This tablegen backend takes an input .td file
+ /// describing a list of options and emits a data structure for parsing and
+ /// working with those options when given an input command line.
+ class OptParserEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ bool GenDefs;
+
+ public:
+ OptParserEmitter(RecordKeeper &R, bool _GenDefs)
+ : Records(R), GenDefs(_GenDefs) {}
+
+ /// run - Output the option parsing information.
+ ///
+ /// \param GenHeader - Generate the header describing the option IDs.x
+ void run(raw_ostream &OS);
+ };
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/Record.cpp b/contrib/llvm/utils/TableGen/Record.cpp
new file mode 100644
index 0000000..dc79358
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/Record.cpp
@@ -0,0 +1,1588 @@
+//===- Record.cpp - Record implementation ---------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implement the tablegen record classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Record.h"
+#include "llvm/System/DataTypes.h"
+#include "llvm/Support/Format.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Type implementations
+//===----------------------------------------------------------------------===//
+
+void RecTy::dump() const { print(errs()); }
+
+Init *BitRecTy::convertValue(BitsInit *BI) {
+ if (BI->getNumBits() != 1) return 0; // Only accept if just one bit!
+ return BI->getBit(0);
+}
+
+bool BitRecTy::baseClassOf(const BitsRecTy *RHS) const {
+ return RHS->getNumBits() == 1;
+}
+
+Init *BitRecTy::convertValue(IntInit *II) {
+ int64_t Val = II->getValue();
+ if (Val != 0 && Val != 1) return 0; // Only accept 0 or 1 for a bit!
+
+ return new BitInit(Val != 0);
+}
+
+Init *BitRecTy::convertValue(TypedInit *VI) {
+ if (dynamic_cast<BitRecTy*>(VI->getType()))
+ return VI; // Accept variable if it is already of bit type!
+ return 0;
+}
+
+std::string BitsRecTy::getAsString() const {
+ return "bits<" + utostr(Size) + ">";
+}
+
+Init *BitsRecTy::convertValue(UnsetInit *UI) {
+ BitsInit *Ret = new BitsInit(Size);
+
+ for (unsigned i = 0; i != Size; ++i)
+ Ret->setBit(i, new UnsetInit());
+ return Ret;
+}
+
+Init *BitsRecTy::convertValue(BitInit *UI) {
+ if (Size != 1) return 0; // Can only convert single bit...
+ BitsInit *Ret = new BitsInit(1);
+ Ret->setBit(0, UI);
+ return Ret;
+}
+
+// convertValue from Int initializer to bits type: Split the integer up into the
+// appropriate bits...
+//
+Init *BitsRecTy::convertValue(IntInit *II) {
+ int64_t Value = II->getValue();
+ // Make sure this bitfield is large enough to hold the integer value...
+ if (Value >= 0) {
+ if (Value & ~((1LL << Size)-1))
+ return 0;
+ } else {
+ if ((Value >> Size) != -1 || ((Value & (1LL << (Size-1))) == 0))
+ return 0;
+ }
+
+ BitsInit *Ret = new BitsInit(Size);
+ for (unsigned i = 0; i != Size; ++i)
+ Ret->setBit(i, new BitInit(Value & (1LL << i)));
+
+ return Ret;
+}
+
+Init *BitsRecTy::convertValue(BitsInit *BI) {
+ // If the number of bits is right, return it. Otherwise we need to expand or
+ // truncate...
+ if (BI->getNumBits() == Size) return BI;
+ return 0;
+}
+
+Init *BitsRecTy::convertValue(TypedInit *VI) {
+ if (BitsRecTy *BRT = dynamic_cast<BitsRecTy*>(VI->getType()))
+ if (BRT->Size == Size) {
+ BitsInit *Ret = new BitsInit(Size);
+ for (unsigned i = 0; i != Size; ++i)
+ Ret->setBit(i, new VarBitInit(VI, i));
+ return Ret;
+ }
+ if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) {
+ BitsInit *Ret = new BitsInit(1);
+ Ret->setBit(0, VI);
+ return Ret;
+ }
+
+ return 0;
+}
+
+Init *IntRecTy::convertValue(BitInit *BI) {
+ return new IntInit(BI->getValue());
+}
+
+Init *IntRecTy::convertValue(BitsInit *BI) {
+ int64_t Result = 0;
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
+ if (BitInit *Bit = dynamic_cast<BitInit*>(BI->getBit(i))) {
+ Result |= Bit->getValue() << i;
+ } else {
+ return 0;
+ }
+ return new IntInit(Result);
+}
+
+Init *IntRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI; // Accept variable if already of the right type!
+ return 0;
+}
+
+Init *StringRecTy::convertValue(UnOpInit *BO) {
+ if (BO->getOpcode() == UnOpInit::CAST) {
+ Init *L = BO->getOperand()->convertInitializerTo(this);
+ if (L == 0) return 0;
+ if (L != BO->getOperand())
+ return new UnOpInit(UnOpInit::CAST, L, new StringRecTy);
+ return BO;
+ }
+
+ return convertValue((TypedInit*)BO);
+}
+
+Init *StringRecTy::convertValue(BinOpInit *BO) {
+ if (BO->getOpcode() == BinOpInit::STRCONCAT) {
+ Init *L = BO->getLHS()->convertInitializerTo(this);
+ Init *R = BO->getRHS()->convertInitializerTo(this);
+ if (L == 0 || R == 0) return 0;
+ if (L != BO->getLHS() || R != BO->getRHS())
+ return new BinOpInit(BinOpInit::STRCONCAT, L, R, new StringRecTy);
+ return BO;
+ }
+ if (BO->getOpcode() == BinOpInit::NAMECONCAT) {
+ if (BO->getType()->getAsString() == getAsString()) {
+ Init *L = BO->getLHS()->convertInitializerTo(this);
+ Init *R = BO->getRHS()->convertInitializerTo(this);
+ if (L == 0 || R == 0) return 0;
+ if (L != BO->getLHS() || R != BO->getRHS())
+ return new BinOpInit(BinOpInit::NAMECONCAT, L, R, new StringRecTy);
+ return BO;
+ }
+ }
+
+ return convertValue((TypedInit*)BO);
+}
+
+
+Init *StringRecTy::convertValue(TypedInit *TI) {
+ if (dynamic_cast<StringRecTy*>(TI->getType()))
+ return TI; // Accept variable if already of the right type!
+ return 0;
+}
+
+std::string ListRecTy::getAsString() const {
+ return "list<" + Ty->getAsString() + ">";
+}
+
+Init *ListRecTy::convertValue(ListInit *LI) {
+ std::vector<Init*> Elements;
+
+ // Verify that all of the elements of the list are subclasses of the
+ // appropriate class!
+ for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
+ if (Init *CI = LI->getElement(i)->convertInitializerTo(Ty))
+ Elements.push_back(CI);
+ else
+ return 0;
+
+ ListRecTy *LType = dynamic_cast<ListRecTy*>(LI->getType());
+ if (LType == 0) {
+ return 0;
+ }
+
+ return new ListInit(Elements, new ListRecTy(Ty));
+}
+
+Init *ListRecTy::convertValue(TypedInit *TI) {
+ // Ensure that TI is compatible with our class.
+ if (ListRecTy *LRT = dynamic_cast<ListRecTy*>(TI->getType()))
+ if (LRT->getElementType()->typeIsConvertibleTo(getElementType()))
+ return TI;
+ return 0;
+}
+
+Init *CodeRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI;
+ return 0;
+}
+
+Init *DagRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI;
+ return 0;
+}
+
+Init *DagRecTy::convertValue(UnOpInit *BO) {
+ if (BO->getOpcode() == UnOpInit::CAST) {
+ Init *L = BO->getOperand()->convertInitializerTo(this);
+ if (L == 0) return 0;
+ if (L != BO->getOperand())
+ return new UnOpInit(UnOpInit::CAST, L, new DagRecTy);
+ return BO;
+ }
+ return 0;
+}
+
+Init *DagRecTy::convertValue(BinOpInit *BO) {
+ if (BO->getOpcode() == BinOpInit::CONCAT) {
+ Init *L = BO->getLHS()->convertInitializerTo(this);
+ Init *R = BO->getRHS()->convertInitializerTo(this);
+ if (L == 0 || R == 0) return 0;
+ if (L != BO->getLHS() || R != BO->getRHS())
+ return new BinOpInit(BinOpInit::CONCAT, L, R, new DagRecTy);
+ return BO;
+ }
+ if (BO->getOpcode() == BinOpInit::NAMECONCAT) {
+ if (BO->getType()->getAsString() == getAsString()) {
+ Init *L = BO->getLHS()->convertInitializerTo(this);
+ Init *R = BO->getRHS()->convertInitializerTo(this);
+ if (L == 0 || R == 0) return 0;
+ if (L != BO->getLHS() || R != BO->getRHS())
+ return new BinOpInit(BinOpInit::CONCAT, L, R, new DagRecTy);
+ return BO;
+ }
+ }
+ return 0;
+}
+
+std::string RecordRecTy::getAsString() const {
+ return Rec->getName();
+}
+
+Init *RecordRecTy::convertValue(DefInit *DI) {
+ // Ensure that DI is a subclass of Rec.
+ if (!DI->getDef()->isSubClassOf(Rec))
+ return 0;
+ return DI;
+}
+
+Init *RecordRecTy::convertValue(TypedInit *TI) {
+ // Ensure that TI is compatible with Rec.
+ if (RecordRecTy *RRT = dynamic_cast<RecordRecTy*>(TI->getType()))
+ if (RRT->getRecord()->isSubClassOf(getRecord()) ||
+ RRT->getRecord() == getRecord())
+ return TI;
+ return 0;
+}
+
+bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const {
+ if (Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec))
+ return true;
+
+ const std::vector<Record*> &SC = Rec->getSuperClasses();
+ for (unsigned i = 0, e = SC.size(); i != e; ++i)
+ if (RHS->getRecord()->isSubClassOf(SC[i]))
+ return true;
+
+ return false;
+}
+
+
+/// resolveTypes - Find a common type that T1 and T2 convert to.
+/// Return 0 if no such type exists.
+///
+RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) {
+ if (!T1->typeIsConvertibleTo(T2)) {
+ if (!T2->typeIsConvertibleTo(T1)) {
+ // If one is a Record type, check superclasses
+ RecordRecTy *RecTy1 = dynamic_cast<RecordRecTy*>(T1);
+ if (RecTy1) {
+ // See if T2 inherits from a type T1 also inherits from
+ const std::vector<Record *> &T1SuperClasses =
+ RecTy1->getRecord()->getSuperClasses();
+ for(std::vector<Record *>::const_iterator i = T1SuperClasses.begin(),
+ iend = T1SuperClasses.end();
+ i != iend;
+ ++i) {
+ RecordRecTy *SuperRecTy1 = new RecordRecTy(*i);
+ RecTy *NewType1 = resolveTypes(SuperRecTy1, T2);
+ if (NewType1 != 0) {
+ if (NewType1 != SuperRecTy1) {
+ delete SuperRecTy1;
+ }
+ return NewType1;
+ }
+ }
+ }
+ RecordRecTy *RecTy2 = dynamic_cast<RecordRecTy*>(T2);
+ if (RecTy2) {
+ // See if T1 inherits from a type T2 also inherits from
+ const std::vector<Record *> &T2SuperClasses =
+ RecTy2->getRecord()->getSuperClasses();
+ for (std::vector<Record *>::const_iterator i = T2SuperClasses.begin(),
+ iend = T2SuperClasses.end();
+ i != iend;
+ ++i) {
+ RecordRecTy *SuperRecTy2 = new RecordRecTy(*i);
+ RecTy *NewType2 = resolveTypes(T1, SuperRecTy2);
+ if (NewType2 != 0) {
+ if (NewType2 != SuperRecTy2) {
+ delete SuperRecTy2;
+ }
+ return NewType2;
+ }
+ }
+ }
+ return 0;
+ }
+ return T2;
+ }
+ return T1;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Initializer implementations
+//===----------------------------------------------------------------------===//
+
+void Init::dump() const { return print(errs()); }
+
+Init *BitsInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsInit *BI = new BitsInit(Bits.size());
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= getNumBits()) {
+ delete BI;
+ return 0;
+ }
+ BI->setBit(i, getBit(Bits[i]));
+ }
+ return BI;
+}
+
+std::string BitsInit::getAsString() const {
+ std::string Result = "{ ";
+ for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
+ if (i) Result += ", ";
+ if (Init *Bit = getBit(e-i-1))
+ Result += Bit->getAsString();
+ else
+ Result += "*";
+ }
+ return Result + " }";
+}
+
+// resolveReferences - If there are any field references that refer to fields
+// that have been filled in, we can propagate the values now.
+//
+Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) {
+ bool Changed = false;
+ BitsInit *New = new BitsInit(getNumBits());
+
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ Init *B;
+ Init *CurBit = getBit(i);
+
+ do {
+ B = CurBit;
+ CurBit = CurBit->resolveReferences(R, RV);
+ Changed |= B != CurBit;
+ } while (B != CurBit);
+ New->setBit(i, CurBit);
+ }
+
+ if (Changed)
+ return New;
+ delete New;
+ return this;
+}
+
+std::string IntInit::getAsString() const {
+ return itostr(Value);
+}
+
+Init *IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsInit *BI = new BitsInit(Bits.size());
+
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= 64) {
+ delete BI;
+ return 0;
+ }
+ BI->setBit(i, new BitInit(Value & (INT64_C(1) << Bits[i])));
+ }
+ return BI;
+}
+
+Init *ListInit::convertInitListSlice(const std::vector<unsigned> &Elements) {
+ std::vector<Init*> Vals;
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
+ if (Elements[i] >= getSize())
+ return 0;
+ Vals.push_back(getElement(Elements[i]));
+ }
+ return new ListInit(Vals, getType());
+}
+
+Record *ListInit::getElementAsRecord(unsigned i) const {
+ assert(i < Values.size() && "List element index out of range!");
+ DefInit *DI = dynamic_cast<DefInit*>(Values[i]);
+ if (DI == 0) throw "Expected record in list!";
+ return DI->getDef();
+}
+
+Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) {
+ std::vector<Init*> Resolved;
+ Resolved.reserve(getSize());
+ bool Changed = false;
+
+ for (unsigned i = 0, e = getSize(); i != e; ++i) {
+ Init *E;
+ Init *CurElt = getElement(i);
+
+ do {
+ E = CurElt;
+ CurElt = CurElt->resolveReferences(R, RV);
+ Changed |= E != CurElt;
+ } while (E != CurElt);
+ Resolved.push_back(E);
+ }
+
+ if (Changed)
+ return new ListInit(Resolved, getType());
+ return this;
+}
+
+Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV,
+ unsigned Elt) {
+ if (Elt >= getSize())
+ return 0; // Out of range reference.
+ Init *E = getElement(Elt);
+ // If the element is set to some value, or if we are resolving a reference
+ // to a specific variable and that variable is explicitly unset, then
+ // replace the VarListElementInit with it.
+ if (IRV || !dynamic_cast<UnsetInit*>(E))
+ return E;
+ return 0;
+}
+
+std::string ListInit::getAsString() const {
+ std::string Result = "[";
+ for (unsigned i = 0, e = Values.size(); i != e; ++i) {
+ if (i) Result += ", ";
+ Result += Values[i]->getAsString();
+ }
+ return Result + "]";
+}
+
+Init *OpInit::resolveBitReference(Record &R, const RecordVal *IRV,
+ unsigned Bit) {
+ Init *Folded = Fold(&R, 0);
+
+ if (Folded != this) {
+ TypedInit *Typed = dynamic_cast<TypedInit *>(Folded);
+ if (Typed) {
+ return Typed->resolveBitReference(R, IRV, Bit);
+ }
+ }
+
+ return 0;
+}
+
+Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV,
+ unsigned Elt) {
+ Init *Folded = Fold(&R, 0);
+
+ if (Folded != this) {
+ TypedInit *Typed = dynamic_cast<TypedInit *>(Folded);
+ if (Typed) {
+ return Typed->resolveListElementReference(R, IRV, Elt);
+ }
+ }
+
+ return 0;
+}
+
+Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
+ switch (getOpcode()) {
+ default: assert(0 && "Unknown unop");
+ case CAST: {
+ if (getType()->getAsString() == "string") {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ if (LHSs) {
+ return LHSs;
+ }
+
+ DefInit *LHSd = dynamic_cast<DefInit*>(LHS);
+ if (LHSd) {
+ return new StringInit(LHSd->getDef()->getName());
+ }
+ } else {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ if (LHSs) {
+ std::string Name = LHSs->getValue();
+
+ // From TGParser::ParseIDValue
+ if (CurRec) {
+ if (const RecordVal *RV = CurRec->getValue(Name)) {
+ if (RV->getType() != getType()) {
+ throw "type mismatch in nameconcat";
+ }
+ return new VarInit(Name, RV->getType());
+ }
+
+ std::string TemplateArgName = CurRec->getName()+":"+Name;
+ if (CurRec->isTemplateArg(TemplateArgName)) {
+ const RecordVal *RV = CurRec->getValue(TemplateArgName);
+ assert(RV && "Template arg doesn't exist??");
+
+ if (RV->getType() != getType()) {
+ throw "type mismatch in nameconcat";
+ }
+
+ return new VarInit(TemplateArgName, RV->getType());
+ }
+ }
+
+ if (CurMultiClass) {
+ std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
+ if (CurMultiClass->Rec.isTemplateArg(MCName)) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
+ assert(RV && "Template arg doesn't exist??");
+
+ if (RV->getType() != getType()) {
+ throw "type mismatch in nameconcat";
+ }
+
+ return new VarInit(MCName, RV->getType());
+ }
+ }
+
+ if (Record *D = Records.getDef(Name))
+ return new DefInit(D);
+
+ errs() << "Variable not defined: '" + Name + "'\n";
+ assert(0 && "Variable not found");
+ return 0;
+ }
+ }
+ break;
+ }
+ case CAR: {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ if (LHSl) {
+ if (LHSl->getSize() == 0) {
+ assert(0 && "Empty list in car");
+ return 0;
+ }
+ return LHSl->getElement(0);
+ }
+ break;
+ }
+ case CDR: {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ if (LHSl) {
+ if (LHSl->getSize() == 0) {
+ assert(0 && "Empty list in cdr");
+ return 0;
+ }
+ ListInit *Result = new ListInit(LHSl->begin()+1, LHSl->end(),
+ LHSl->getType());
+ return Result;
+ }
+ break;
+ }
+ case LNULL: {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ if (LHSl) {
+ if (LHSl->getSize() == 0) {
+ return new IntInit(1);
+ } else {
+ return new IntInit(0);
+ }
+ }
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ if (LHSs) {
+ if (LHSs->getValue().empty()) {
+ return new IntInit(1);
+ } else {
+ return new IntInit(0);
+ }
+ }
+
+ break;
+ }
+ }
+ return this;
+}
+
+Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) {
+ Init *lhs = LHS->resolveReferences(R, RV);
+
+ if (LHS != lhs)
+ return (new UnOpInit(getOpcode(), lhs, getType()))->Fold(&R, 0);
+ return Fold(&R, 0);
+}
+
+std::string UnOpInit::getAsString() const {
+ std::string Result;
+ switch (Opc) {
+ case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
+ case CAR: Result = "!car"; break;
+ case CDR: Result = "!cdr"; break;
+ case LNULL: Result = "!null"; break;
+ }
+ return Result + "(" + LHS->getAsString() + ")";
+}
+
+Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
+ switch (getOpcode()) {
+ default: assert(0 && "Unknown binop");
+ case CONCAT: {
+ DagInit *LHSs = dynamic_cast<DagInit*>(LHS);
+ DagInit *RHSs = dynamic_cast<DagInit*>(RHS);
+ if (LHSs && RHSs) {
+ DefInit *LOp = dynamic_cast<DefInit*>(LHSs->getOperator());
+ DefInit *ROp = dynamic_cast<DefInit*>(RHSs->getOperator());
+ if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef())
+ throw "Concated Dag operators do not match!";
+ std::vector<Init*> Args;
+ std::vector<std::string> ArgNames;
+ for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) {
+ Args.push_back(LHSs->getArg(i));
+ ArgNames.push_back(LHSs->getArgName(i));
+ }
+ for (unsigned i = 0, e = RHSs->getNumArgs(); i != e; ++i) {
+ Args.push_back(RHSs->getArg(i));
+ ArgNames.push_back(RHSs->getArgName(i));
+ }
+ return new DagInit(LHSs->getOperator(), "", Args, ArgNames);
+ }
+ break;
+ }
+ case STRCONCAT: {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+ if (LHSs && RHSs)
+ return new StringInit(LHSs->getValue() + RHSs->getValue());
+ break;
+ }
+ case NAMECONCAT: {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+ if (LHSs && RHSs) {
+ std::string Name(LHSs->getValue() + RHSs->getValue());
+
+ // From TGParser::ParseIDValue
+ if (CurRec) {
+ if (const RecordVal *RV = CurRec->getValue(Name)) {
+ if (RV->getType() != getType()) {
+ throw "type mismatch in nameconcat";
+ }
+ return new VarInit(Name, RV->getType());
+ }
+
+ std::string TemplateArgName = CurRec->getName()+":"+Name;
+ if (CurRec->isTemplateArg(TemplateArgName)) {
+ const RecordVal *RV = CurRec->getValue(TemplateArgName);
+ assert(RV && "Template arg doesn't exist??");
+
+ if (RV->getType() != getType()) {
+ throw "type mismatch in nameconcat";
+ }
+
+ return new VarInit(TemplateArgName, RV->getType());
+ }
+ }
+
+ if (CurMultiClass) {
+ std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
+ if (CurMultiClass->Rec.isTemplateArg(MCName)) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
+ assert(RV && "Template arg doesn't exist??");
+
+ if (RV->getType() != getType()) {
+ throw "type mismatch in nameconcat";
+ }
+
+ return new VarInit(MCName, RV->getType());
+ }
+ }
+
+ if (Record *D = Records.getDef(Name))
+ return new DefInit(D);
+
+ errs() << "Variable not defined in !nameconcat: '" + Name + "'\n";
+ assert(0 && "Variable not found in !nameconcat");
+ return 0;
+ }
+ break;
+ }
+ case EQ: {
+ // try to fold eq comparison for 'bit' and 'int', otherwise fallback
+ // to string objects.
+ IntInit* L =
+ dynamic_cast<IntInit*>(LHS->convertInitializerTo(new IntRecTy()));
+ IntInit* R =
+ dynamic_cast<IntInit*>(RHS->convertInitializerTo(new IntRecTy()));
+
+ if (L && R)
+ return new IntInit(L->getValue() == R->getValue());
+
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+
+ // Make sure we've resolved
+ if (LHSs && RHSs)
+ return new IntInit(LHSs->getValue() == RHSs->getValue());
+
+ break;
+ }
+ case SHL:
+ case SRA:
+ case SRL: {
+ IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
+ IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
+ if (LHSi && RHSi) {
+ int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
+ int64_t Result;
+ switch (getOpcode()) {
+ default: assert(0 && "Bad opcode!");
+ case SHL: Result = LHSv << RHSv; break;
+ case SRA: Result = LHSv >> RHSv; break;
+ case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break;
+ }
+ return new IntInit(Result);
+ }
+ break;
+ }
+ }
+ return this;
+}
+
+Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) {
+ Init *lhs = LHS->resolveReferences(R, RV);
+ Init *rhs = RHS->resolveReferences(R, RV);
+
+ if (LHS != lhs || RHS != rhs)
+ return (new BinOpInit(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0);
+ return Fold(&R, 0);
+}
+
+std::string BinOpInit::getAsString() const {
+ std::string Result;
+ switch (Opc) {
+ case CONCAT: Result = "!con"; break;
+ case SHL: Result = "!shl"; break;
+ case SRA: Result = "!sra"; break;
+ case SRL: Result = "!srl"; break;
+ case EQ: Result = "!eq"; break;
+ case STRCONCAT: Result = "!strconcat"; break;
+ case NAMECONCAT:
+ Result = "!nameconcat<" + getType()->getAsString() + ">"; break;
+ }
+ return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";
+}
+
+static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
+ Record *CurRec, MultiClass *CurMultiClass);
+
+static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg,
+ RecTy *Type, Record *CurRec,
+ MultiClass *CurMultiClass) {
+ std::vector<Init *> NewOperands;
+
+ TypedInit *TArg = dynamic_cast<TypedInit*>(Arg);
+
+ // If this is a dag, recurse
+ if (TArg && TArg->getType()->getAsString() == "dag") {
+ Init *Result = ForeachHelper(LHS, Arg, RHSo, Type,
+ CurRec, CurMultiClass);
+ if (Result != 0) {
+ return Result;
+ } else {
+ return 0;
+ }
+ }
+
+ for (int i = 0; i < RHSo->getNumOperands(); ++i) {
+ OpInit *RHSoo = dynamic_cast<OpInit*>(RHSo->getOperand(i));
+
+ if (RHSoo) {
+ Init *Result = EvaluateOperation(RHSoo, LHS, Arg,
+ Type, CurRec, CurMultiClass);
+ if (Result != 0) {
+ NewOperands.push_back(Result);
+ } else {
+ NewOperands.push_back(Arg);
+ }
+ } else if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
+ NewOperands.push_back(Arg);
+ } else {
+ NewOperands.push_back(RHSo->getOperand(i));
+ }
+ }
+
+ // Now run the operator and use its result as the new leaf
+ OpInit *NewOp = RHSo->clone(NewOperands);
+ Init *NewVal = NewOp->Fold(CurRec, CurMultiClass);
+ if (NewVal != NewOp) {
+ delete NewOp;
+ return NewVal;
+ }
+ return 0;
+}
+
+static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
+ Record *CurRec, MultiClass *CurMultiClass) {
+ DagInit *MHSd = dynamic_cast<DagInit*>(MHS);
+ ListInit *MHSl = dynamic_cast<ListInit*>(MHS);
+
+ DagRecTy *DagType = dynamic_cast<DagRecTy*>(Type);
+ ListRecTy *ListType = dynamic_cast<ListRecTy*>(Type);
+
+ OpInit *RHSo = dynamic_cast<OpInit*>(RHS);
+
+ if (!RHSo) {
+ errs() << "!foreach requires an operator\n";
+ assert(0 && "No operator for !foreach");
+ }
+
+ TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
+
+ if (!LHSt) {
+ errs() << "!foreach requires typed variable\n";
+ assert(0 && "No typed variable for !foreach");
+ }
+
+ if ((MHSd && DagType) || (MHSl && ListType)) {
+ if (MHSd) {
+ Init *Val = MHSd->getOperator();
+ Init *Result = EvaluateOperation(RHSo, LHS, Val,
+ Type, CurRec, CurMultiClass);
+ if (Result != 0) {
+ Val = Result;
+ }
+
+ std::vector<std::pair<Init *, std::string> > args;
+ for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) {
+ Init *Arg;
+ std::string ArgName;
+ Arg = MHSd->getArg(i);
+ ArgName = MHSd->getArgName(i);
+
+ // Process args
+ Init *Result = EvaluateOperation(RHSo, LHS, Arg, Type,
+ CurRec, CurMultiClass);
+ if (Result != 0) {
+ Arg = Result;
+ }
+
+ // TODO: Process arg names
+ args.push_back(std::make_pair(Arg, ArgName));
+ }
+
+ return new DagInit(Val, "", args);
+ }
+ if (MHSl) {
+ std::vector<Init *> NewOperands;
+ std::vector<Init *> NewList(MHSl->begin(), MHSl->end());
+
+ for (ListInit::iterator li = NewList.begin(),
+ liend = NewList.end();
+ li != liend;
+ ++li) {
+ Init *Item = *li;
+ NewOperands.clear();
+ for(int i = 0; i < RHSo->getNumOperands(); ++i) {
+ // First, replace the foreach variable with the list item
+ if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
+ NewOperands.push_back(Item);
+ } else {
+ NewOperands.push_back(RHSo->getOperand(i));
+ }
+ }
+
+ // Now run the operator and use its result as the new list item
+ OpInit *NewOp = RHSo->clone(NewOperands);
+ Init *NewItem = NewOp->Fold(CurRec, CurMultiClass);
+ if (NewItem != NewOp) {
+ *li = NewItem;
+ delete NewOp;
+ }
+ }
+ return new ListInit(NewList, MHSl->getType());
+ }
+ }
+ return 0;
+}
+
+Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
+ switch (getOpcode()) {
+ default: assert(0 && "Unknown binop");
+ case SUBST: {
+ DefInit *LHSd = dynamic_cast<DefInit*>(LHS);
+ VarInit *LHSv = dynamic_cast<VarInit*>(LHS);
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+
+ DefInit *MHSd = dynamic_cast<DefInit*>(MHS);
+ VarInit *MHSv = dynamic_cast<VarInit*>(MHS);
+ StringInit *MHSs = dynamic_cast<StringInit*>(MHS);
+
+ DefInit *RHSd = dynamic_cast<DefInit*>(RHS);
+ VarInit *RHSv = dynamic_cast<VarInit*>(RHS);
+ StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+
+ if ((LHSd && MHSd && RHSd)
+ || (LHSv && MHSv && RHSv)
+ || (LHSs && MHSs && RHSs)) {
+ if (RHSd) {
+ Record *Val = RHSd->getDef();
+ if (LHSd->getAsString() == RHSd->getAsString()) {
+ Val = MHSd->getDef();
+ }
+ return new DefInit(Val);
+ }
+ if (RHSv) {
+ std::string Val = RHSv->getName();
+ if (LHSv->getAsString() == RHSv->getAsString()) {
+ Val = MHSv->getName();
+ }
+ return new VarInit(Val, getType());
+ }
+ if (RHSs) {
+ std::string Val = RHSs->getValue();
+
+ std::string::size_type found;
+ std::string::size_type idx = 0;
+ do {
+ found = Val.find(LHSs->getValue(), idx);
+ if (found != std::string::npos) {
+ Val.replace(found, LHSs->getValue().size(), MHSs->getValue());
+ }
+ idx = found + MHSs->getValue().size();
+ } while (found != std::string::npos);
+
+ return new StringInit(Val);
+ }
+ }
+ break;
+ }
+
+ case FOREACH: {
+ Init *Result = ForeachHelper(LHS, MHS, RHS, getType(),
+ CurRec, CurMultiClass);
+ if (Result != 0) {
+ return Result;
+ }
+ break;
+ }
+
+ case IF: {
+ IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
+ if (Init *I = LHS->convertInitializerTo(new IntRecTy()))
+ LHSi = dynamic_cast<IntInit*>(I);
+ if (LHSi) {
+ if (LHSi->getValue()) {
+ return MHS;
+ } else {
+ return RHS;
+ }
+ }
+ break;
+ }
+ }
+
+ return this;
+}
+
+Init *TernOpInit::resolveReferences(Record &R, const RecordVal *RV) {
+ Init *lhs = LHS->resolveReferences(R, RV);
+
+ if (Opc == IF && lhs != LHS) {
+ IntInit *Value = dynamic_cast<IntInit*>(lhs);
+ if (Init *I = lhs->convertInitializerTo(new IntRecTy()))
+ Value = dynamic_cast<IntInit*>(I);
+ if (Value != 0) {
+ // Short-circuit
+ if (Value->getValue()) {
+ Init *mhs = MHS->resolveReferences(R, RV);
+ return (new TernOpInit(getOpcode(), lhs, mhs,
+ RHS, getType()))->Fold(&R, 0);
+ } else {
+ Init *rhs = RHS->resolveReferences(R, RV);
+ return (new TernOpInit(getOpcode(), lhs, MHS,
+ rhs, getType()))->Fold(&R, 0);
+ }
+ }
+ }
+
+ Init *mhs = MHS->resolveReferences(R, RV);
+ Init *rhs = RHS->resolveReferences(R, RV);
+
+ if (LHS != lhs || MHS != mhs || RHS != rhs)
+ return (new TernOpInit(getOpcode(), lhs, mhs, rhs, getType()))->Fold(&R, 0);
+ return Fold(&R, 0);
+}
+
+std::string TernOpInit::getAsString() const {
+ std::string Result;
+ switch (Opc) {
+ case SUBST: Result = "!subst"; break;
+ case FOREACH: Result = "!foreach"; break;
+ case IF: Result = "!if"; break;
+ }
+ return Result + "(" + LHS->getAsString() + ", " + MHS->getAsString() + ", "
+ + RHS->getAsString() + ")";
+}
+
+RecTy *TypedInit::getFieldType(const std::string &FieldName) const {
+ RecordRecTy *RecordType = dynamic_cast<RecordRecTy *>(getType());
+ if (RecordType) {
+ RecordVal *Field = RecordType->getRecord()->getValue(FieldName);
+ if (Field) {
+ return Field->getType();
+ }
+ }
+ return 0;
+}
+
+Init *TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
+ if (T == 0) return 0; // Cannot subscript a non-bits variable...
+ unsigned NumBits = T->getNumBits();
+
+ BitsInit *BI = new BitsInit(Bits.size());
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= NumBits) {
+ delete BI;
+ return 0;
+ }
+ BI->setBit(i, new VarBitInit(this, Bits[i]));
+ }
+ return BI;
+}
+
+Init *TypedInit::convertInitListSlice(const std::vector<unsigned> &Elements) {
+ ListRecTy *T = dynamic_cast<ListRecTy*>(getType());
+ if (T == 0) return 0; // Cannot subscript a non-list variable...
+
+ if (Elements.size() == 1)
+ return new VarListElementInit(this, Elements[0]);
+
+ std::vector<Init*> ListInits;
+ ListInits.reserve(Elements.size());
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i)
+ ListInits.push_back(new VarListElementInit(this, Elements[i]));
+ return new ListInit(ListInits, T);
+}
+
+
+Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV,
+ unsigned Bit) {
+ if (R.isTemplateArg(getName())) return 0;
+ if (IRV && IRV->getName() != getName()) return 0;
+
+ RecordVal *RV = R.getValue(getName());
+ assert(RV && "Reference to a non-existent variable?");
+ assert(dynamic_cast<BitsInit*>(RV->getValue()));
+ BitsInit *BI = (BitsInit*)RV->getValue();
+
+ assert(Bit < BI->getNumBits() && "Bit reference out of range!");
+ Init *B = BI->getBit(Bit);
+
+ // If the bit is set to some value, or if we are resolving a reference to a
+ // specific variable and that variable is explicitly unset, then replace the
+ // VarBitInit with it.
+ if (IRV || !dynamic_cast<UnsetInit*>(B))
+ return B;
+ return 0;
+}
+
+Init *VarInit::resolveListElementReference(Record &R, const RecordVal *IRV,
+ unsigned Elt) {
+ if (R.isTemplateArg(getName())) return 0;
+ if (IRV && IRV->getName() != getName()) return 0;
+
+ RecordVal *RV = R.getValue(getName());
+ assert(RV && "Reference to a non-existent variable?");
+ ListInit *LI = dynamic_cast<ListInit*>(RV->getValue());
+ if (!LI) {
+ VarInit *VI = dynamic_cast<VarInit*>(RV->getValue());
+ assert(VI && "Invalid list element!");
+ return new VarListElementInit(VI, Elt);
+ }
+
+ if (Elt >= LI->getSize())
+ return 0; // Out of range reference.
+ Init *E = LI->getElement(Elt);
+ // If the element is set to some value, or if we are resolving a reference
+ // to a specific variable and that variable is explicitly unset, then
+ // replace the VarListElementInit with it.
+ if (IRV || !dynamic_cast<UnsetInit*>(E))
+ return E;
+ return 0;
+}
+
+
+RecTy *VarInit::getFieldType(const std::string &FieldName) const {
+ if (RecordRecTy *RTy = dynamic_cast<RecordRecTy*>(getType()))
+ if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName))
+ return RV->getType();
+ return 0;
+}
+
+Init *VarInit::getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const {
+ if (dynamic_cast<RecordRecTy*>(getType()))
+ if (const RecordVal *Val = R.getValue(VarName)) {
+ if (RV != Val && (RV || dynamic_cast<UnsetInit*>(Val->getValue())))
+ return 0;
+ Init *TheInit = Val->getValue();
+ assert(TheInit != this && "Infinite loop detected!");
+ if (Init *I = TheInit->getFieldInit(R, RV, FieldName))
+ return I;
+ else
+ return 0;
+ }
+ return 0;
+}
+
+/// resolveReferences - This method is used by classes that refer to other
+/// variables which may not be defined at the time the expression is formed.
+/// If a value is set for the variable later, this method will be called on
+/// users of the value to allow the value to propagate out.
+///
+Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) {
+ if (RecordVal *Val = R.getValue(VarName))
+ if (RV == Val || (RV == 0 && !dynamic_cast<UnsetInit*>(Val->getValue())))
+ return Val->getValue();
+ return this;
+}
+
+std::string VarBitInit::getAsString() const {
+ return TI->getAsString() + "{" + utostr(Bit) + "}";
+}
+
+Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) {
+ if (Init *I = getVariable()->resolveBitReference(R, RV, getBitNum()))
+ return I;
+ return this;
+}
+
+std::string VarListElementInit::getAsString() const {
+ return TI->getAsString() + "[" + utostr(Element) + "]";
+}
+
+Init *VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) {
+ if (Init *I = getVariable()->resolveListElementReference(R, RV,
+ getElementNum()))
+ return I;
+ return this;
+}
+
+Init *VarListElementInit::resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) {
+ // FIXME: This should be implemented, to support references like:
+ // bit B = AA[0]{1};
+ return 0;
+}
+
+Init *VarListElementInit::
+resolveListElementReference(Record &R, const RecordVal *RV, unsigned Elt) {
+ // FIXME: This should be implemented, to support references like:
+ // int B = AA[0][1];
+ return 0;
+}
+
+RecTy *DefInit::getFieldType(const std::string &FieldName) const {
+ if (const RecordVal *RV = Def->getValue(FieldName))
+ return RV->getType();
+ return 0;
+}
+
+Init *DefInit::getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const {
+ return Def->getValue(FieldName)->getValue();
+}
+
+
+std::string DefInit::getAsString() const {
+ return Def->getName();
+}
+
+Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) {
+ if (Init *BitsVal = Rec->getFieldInit(R, RV, FieldName))
+ if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) {
+ assert(Bit < BI->getNumBits() && "Bit reference out of range!");
+ Init *B = BI->getBit(Bit);
+
+ if (dynamic_cast<BitInit*>(B)) // If the bit is set...
+ return B; // Replace the VarBitInit with it.
+ }
+ return 0;
+}
+
+Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) {
+ if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName))
+ if (ListInit *LI = dynamic_cast<ListInit*>(ListVal)) {
+ if (Elt >= LI->getSize()) return 0;
+ Init *E = LI->getElement(Elt);
+
+ // If the element is set to some value, or if we are resolving a
+ // reference to a specific variable and that variable is explicitly
+ // unset, then replace the VarListElementInit with it.
+ if (RV || !dynamic_cast<UnsetInit*>(E))
+ return E;
+ }
+ return 0;
+}
+
+Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) {
+ Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec;
+
+ Init *BitsVal = NewRec->getFieldInit(R, RV, FieldName);
+ if (BitsVal) {
+ Init *BVR = BitsVal->resolveReferences(R, RV);
+ return BVR->isComplete() ? BVR : this;
+ }
+
+ if (NewRec != Rec) {
+ return new FieldInit(NewRec, FieldName);
+ }
+ return this;
+}
+
+Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) {
+ std::vector<Init*> NewArgs;
+ for (unsigned i = 0, e = Args.size(); i != e; ++i)
+ NewArgs.push_back(Args[i]->resolveReferences(R, RV));
+
+ Init *Op = Val->resolveReferences(R, RV);
+
+ if (Args != NewArgs || Op != Val)
+ return new DagInit(Op, ValName, NewArgs, ArgNames);
+
+ return this;
+}
+
+
+std::string DagInit::getAsString() const {
+ std::string Result = "(" + Val->getAsString();
+ if (!ValName.empty())
+ Result += ":" + ValName;
+ if (Args.size()) {
+ Result += " " + Args[0]->getAsString();
+ if (!ArgNames[0].empty()) Result += ":$" + ArgNames[0];
+ for (unsigned i = 1, e = Args.size(); i != e; ++i) {
+ Result += ", " + Args[i]->getAsString();
+ if (!ArgNames[i].empty()) Result += ":$" + ArgNames[i];
+ }
+ }
+ return Result + ")";
+}
+
+
+//===----------------------------------------------------------------------===//
+// Other implementations
+//===----------------------------------------------------------------------===//
+
+RecordVal::RecordVal(const std::string &N, RecTy *T, unsigned P)
+ : Name(N), Ty(T), Prefix(P) {
+ Value = Ty->convertValue(new UnsetInit());
+ assert(Value && "Cannot create unset value for current type!");
+}
+
+void RecordVal::dump() const { errs() << *this; }
+
+void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
+ if (getPrefix()) OS << "field ";
+ OS << *getType() << " " << getName();
+
+ if (getValue())
+ OS << " = " << *getValue();
+
+ if (PrintSem) OS << ";\n";
+}
+
+unsigned Record::LastID = 0;
+
+void Record::setName(const std::string &Name) {
+ if (Records.getDef(getName()) == this) {
+ Records.removeDef(getName());
+ this->Name = Name;
+ Records.addDef(this);
+ } else {
+ Records.removeClass(getName());
+ this->Name = Name;
+ Records.addClass(this);
+ }
+}
+
+/// resolveReferencesTo - If anything in this record refers to RV, replace the
+/// reference to RV with the RHS of RV. If RV is null, we resolve all possible
+/// references.
+void Record::resolveReferencesTo(const RecordVal *RV) {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i) {
+ if (Init *V = Values[i].getValue())
+ Values[i].setValue(V->resolveReferences(*this, RV));
+ }
+}
+
+void Record::dump() const { errs() << *this; }
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) {
+ OS << R.getName();
+
+ const std::vector<std::string> &TArgs = R.getTemplateArgs();
+ if (!TArgs.empty()) {
+ OS << "<";
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ if (i) OS << ", ";
+ const RecordVal *RV = R.getValue(TArgs[i]);
+ assert(RV && "Template argument record not found??");
+ RV->print(OS, false);
+ }
+ OS << ">";
+ }
+
+ OS << " {";
+ const std::vector<Record*> &SC = R.getSuperClasses();
+ if (!SC.empty()) {
+ OS << "\t//";
+ for (unsigned i = 0, e = SC.size(); i != e; ++i)
+ OS << " " << SC[i]->getName();
+ }
+ OS << "\n";
+
+ const std::vector<RecordVal> &Vals = R.getValues();
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
+ OS << Vals[i];
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (!Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
+ OS << Vals[i];
+
+ return OS << "}\n";
+}
+
+/// getValueInit - Return the initializer for a value with the specified name,
+/// or throw an exception if the field does not exist.
+///
+Init *Record::getValueInit(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+ return R->getValue();
+}
+
+
+/// getValueAsString - This method looks up the specified field and returns its
+/// value as a string, throwing an exception if the field does not exist or if
+/// the value is not a string.
+///
+std::string Record::getValueAsString(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (const StringInit *SI = dynamic_cast<const StringInit*>(R->getValue()))
+ return SI->getValue();
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a string initializer!";
+}
+
+/// getValueAsBitsInit - This method looks up the specified field and returns
+/// its value as a BitsInit, throwing an exception if the field does not exist
+/// or if the value is not the right type.
+///
+BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (BitsInit *BI = dynamic_cast<BitsInit*>(R->getValue()))
+ return BI;
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a BitsInit initializer!";
+}
+
+/// getValueAsListInit - This method looks up the specified field and returns
+/// its value as a ListInit, throwing an exception if the field does not exist
+/// or if the value is not the right type.
+///
+ListInit *Record::getValueAsListInit(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (ListInit *LI = dynamic_cast<ListInit*>(R->getValue()))
+ return LI;
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a list initializer!";
+}
+
+/// getValueAsListOfDefs - This method looks up the specified field and returns
+/// its value as a vector of records, throwing an exception if the field does
+/// not exist or if the value is not the right type.
+///
+std::vector<Record*>
+Record::getValueAsListOfDefs(StringRef FieldName) const {
+ ListInit *List = getValueAsListInit(FieldName);
+ std::vector<Record*> Defs;
+ for (unsigned i = 0; i < List->getSize(); i++) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(List->getElement(i))) {
+ Defs.push_back(DI->getDef());
+ } else {
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' list is not entirely DefInit!";
+ }
+ }
+ return Defs;
+}
+
+/// getValueAsInt - This method looks up the specified field and returns its
+/// value as an int64_t, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+int64_t Record::getValueAsInt(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (IntInit *II = dynamic_cast<IntInit*>(R->getValue()))
+ return II->getValue();
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have an int initializer!";
+}
+
+/// getValueAsListOfInts - This method looks up the specified field and returns
+/// its value as a vector of integers, throwing an exception if the field does
+/// not exist or if the value is not the right type.
+///
+std::vector<int64_t>
+Record::getValueAsListOfInts(StringRef FieldName) const {
+ ListInit *List = getValueAsListInit(FieldName);
+ std::vector<int64_t> Ints;
+ for (unsigned i = 0; i < List->getSize(); i++) {
+ if (IntInit *II = dynamic_cast<IntInit*>(List->getElement(i))) {
+ Ints.push_back(II->getValue());
+ } else {
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a list of ints initializer!";
+ }
+ }
+ return Ints;
+}
+
+/// getValueAsDef - This method looks up the specified field and returns its
+/// value as a Record, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+Record *Record::getValueAsDef(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (DefInit *DI = dynamic_cast<DefInit*>(R->getValue()))
+ return DI->getDef();
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a def initializer!";
+}
+
+/// getValueAsBit - This method looks up the specified field and returns its
+/// value as a bit, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+bool Record::getValueAsBit(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (BitInit *BI = dynamic_cast<BitInit*>(R->getValue()))
+ return BI->getValue();
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a bit initializer!";
+}
+
+/// getValueAsDag - This method looks up the specified field and returns its
+/// value as an Dag, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+DagInit *Record::getValueAsDag(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (DagInit *DI = dynamic_cast<DagInit*>(R->getValue()))
+ return DI;
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a dag initializer!";
+}
+
+std::string Record::getValueAsCode(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (const CodeInit *CI = dynamic_cast<const CodeInit*>(R->getValue()))
+ return CI->getValue();
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a code initializer!";
+}
+
+
+void MultiClass::dump() const {
+ errs() << "Record:\n";
+ Rec.dump();
+
+ errs() << "Defs:\n";
+ for (RecordVector::const_iterator r = DefPrototypes.begin(),
+ rend = DefPrototypes.end();
+ r != rend;
+ ++r) {
+ (*r)->dump();
+ }
+}
+
+
+void RecordKeeper::dump() const { errs() << *this; }
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) {
+ OS << "------------- Classes -----------------\n";
+ const std::map<std::string, Record*> &Classes = RK.getClasses();
+ for (std::map<std::string, Record*>::const_iterator I = Classes.begin(),
+ E = Classes.end(); I != E; ++I)
+ OS << "class " << *I->second;
+
+ OS << "------------- Defs -----------------\n";
+ const std::map<std::string, Record*> &Defs = RK.getDefs();
+ for (std::map<std::string, Record*>::const_iterator I = Defs.begin(),
+ E = Defs.end(); I != E; ++I)
+ OS << "def " << *I->second;
+ return OS;
+}
+
+
+/// getAllDerivedDefinitions - This method returns all concrete definitions
+/// that derive from the specified class name. If a class with the specified
+/// name does not exist, an error is printed and true is returned.
+std::vector<Record*>
+RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const {
+ Record *Class = Records.getClass(ClassName);
+ if (!Class)
+ throw "ERROR: Couldn't find the `" + ClassName + "' class!\n";
+
+ std::vector<Record*> Defs;
+ for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(),
+ E = getDefs().end(); I != E; ++I)
+ if (I->second->isSubClassOf(Class))
+ Defs.push_back(I->second);
+
+ return Defs;
+}
+
diff --git a/contrib/llvm/utils/TableGen/Record.h b/contrib/llvm/utils/TableGen/Record.h
new file mode 100644
index 0000000..d6f37ee
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/Record.h
@@ -0,0 +1,1497 @@
+//===- Record.h - Classes to represent Table Records ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the main TableGen data structures, including the TableGen
+// types, values, and high-level data structures.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef RECORD_H
+#define RECORD_H
+
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/System/DataTypes.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+
+namespace llvm {
+class raw_ostream;
+
+// RecTy subclasses.
+class BitRecTy;
+class BitsRecTy;
+class IntRecTy;
+class StringRecTy;
+class ListRecTy;
+class CodeRecTy;
+class DagRecTy;
+class RecordRecTy;
+
+// Init subclasses.
+struct Init;
+class UnsetInit;
+class BitInit;
+class BitsInit;
+class IntInit;
+class StringInit;
+class CodeInit;
+class ListInit;
+class UnOpInit;
+class BinOpInit;
+class TernOpInit;
+class DefInit;
+class DagInit;
+class TypedInit;
+class VarInit;
+class FieldInit;
+class VarBitInit;
+class VarListElementInit;
+
+// Other classes.
+class Record;
+class RecordVal;
+struct MultiClass;
+
+//===----------------------------------------------------------------------===//
+// Type Classes
+//===----------------------------------------------------------------------===//
+
+struct RecTy {
+ virtual ~RecTy() {}
+
+ virtual std::string getAsString() const = 0;
+ void print(raw_ostream &OS) const { OS << getAsString(); }
+ void dump() const;
+
+ /// typeIsConvertibleTo - Return true if all values of 'this' type can be
+ /// converted to the specified type.
+ virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0;
+
+public: // These methods should only be called from subclasses of Init
+ virtual Init *convertValue( UnsetInit *UI) { return 0; }
+ virtual Init *convertValue( BitInit *BI) { return 0; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) {
+ return convertValue((TypedInit*)UI);
+ }
+ virtual Init *convertValue( BinOpInit *UI) {
+ return convertValue((TypedInit*)UI);
+ }
+ virtual Init *convertValue( TernOpInit *UI) {
+ return convertValue((TypedInit*)UI);
+ }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( TypedInit *TI) { return 0; }
+ virtual Init *convertValue( VarInit *VI) {
+ return convertValue((TypedInit*)VI);
+ }
+ virtual Init *convertValue( FieldInit *FI) {
+ return convertValue((TypedInit*)FI);
+ }
+
+public: // These methods should only be called by subclasses of RecTy.
+ // baseClassOf - These virtual methods should be overloaded to return true iff
+ // all values of type 'RHS' can be converted to the 'this' type.
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
+ Ty.print(OS);
+ return OS;
+}
+
+
+/// BitRecTy - 'bit' - Represent a single bit
+///
+class BitRecTy : public RecTy {
+public:
+ virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
+ virtual Init *convertValue( BitInit *BI) { return (Init*)BI; }
+ virtual Init *convertValue( BitsInit *BI);
+ virtual Init *convertValue( IntInit *II);
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const { return "bit"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const;
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+
+};
+
+
+// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
+/// BitsRecTy - 'bits&lt;n&gt;' - Represent a fixed number of bits
+///
+class BitsRecTy : public RecTy {
+ unsigned Size;
+public:
+ explicit BitsRecTy(unsigned Sz) : Size(Sz) {}
+
+ unsigned getNumBits() const { return Size; }
+
+ virtual Init *convertValue( UnsetInit *UI);
+ virtual Init *convertValue( BitInit *UI);
+ virtual Init *convertValue( BitsInit *BI);
+ virtual Init *convertValue( IntInit *II);
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const {
+ return RHS->Size == Size;
+ }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+
+};
+
+
+/// IntRecTy - 'int' - Represent an integer value of no particular size
+///
+class IntRecTy : public RecTy {
+public:
+ virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
+ virtual Init *convertValue( BitInit *BI);
+ virtual Init *convertValue( BitsInit *BI);
+ virtual Init *convertValue( IntInit *II) { return (Init*)II; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const { return "int"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+
+};
+
+/// StringRecTy - 'string' - Represent an string value
+///
+class StringRecTy : public RecTy {
+public:
+ virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
+ virtual Init *convertValue( BitInit *BI) { return 0; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return (Init*)SI; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( UnOpInit *BO);
+ virtual Init *convertValue( BinOpInit *BO);
+ virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
+
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const { return "string"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
+// the specified type.
+/// ListRecTy - 'list&lt;Ty&gt;' - Represent a list of values, all of which must
+/// be of the specified type.
+///
+class ListRecTy : public RecTy {
+ RecTy *Ty;
+public:
+ explicit ListRecTy(RecTy *T) : Ty(T) {}
+
+ RecTy *getElementType() const { return Ty; }
+
+ virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
+ virtual Init *convertValue( BitInit *BI) { return 0; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI);
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const {
+ return RHS->getElementType()->typeIsConvertibleTo(Ty);
+ }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+/// CodeRecTy - 'code' - Represent an code fragment, function or method.
+///
+class CodeRecTy : public RecTy {
+public:
+ virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
+ virtual Init *convertValue( BitInit *BI) { return 0; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return (Init*)CI; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const { return "code"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+/// DagRecTy - 'dag' - Represent a dag fragment
+///
+class DagRecTy : public RecTy {
+public:
+ virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
+ virtual Init *convertValue( BitInit *BI) { return 0; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *BO);
+ virtual Init *convertValue( BinOpInit *BO);
+ virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
+ virtual Init *convertValue( DagInit *CI) { return (Init*)CI; }
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const { return "dag"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+
+/// RecordRecTy - '[classname]' - Represent an instance of a class, such as:
+/// (R32 X = EAX).
+///
+class RecordRecTy : public RecTy {
+ Record *Rec;
+public:
+ explicit RecordRecTy(Record *R) : Rec(R) {}
+
+ Record *getRecord() const { return Rec; }
+
+ virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
+ virtual Init *convertValue( BitInit *BI) { return 0; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( DefInit *DI);
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( TypedInit *VI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const;
+};
+
+/// resolveTypes - Find a common type that T1 and T2 convert to.
+/// Return 0 if no such type exists.
+///
+RecTy *resolveTypes(RecTy *T1, RecTy *T2);
+
+//===----------------------------------------------------------------------===//
+// Initializer Classes
+//===----------------------------------------------------------------------===//
+
+struct Init {
+ virtual ~Init() {}
+
+ /// isComplete - This virtual method should be overridden by values that may
+ /// not be completely specified yet.
+ virtual bool isComplete() const { return true; }
+
+ /// print - Print out this value.
+ void print(raw_ostream &OS) const { OS << getAsString(); }
+
+ /// getAsString - Convert this value to a string form.
+ virtual std::string getAsString() const = 0;
+
+ /// dump - Debugging method that may be called through a debugger, just
+ /// invokes print on stderr.
+ void dump() const;
+
+ /// convertInitializerTo - This virtual function is a simple call-back
+ /// function that should be overridden to call the appropriate
+ /// RecTy::convertValue method.
+ ///
+ virtual Init *convertInitializerTo(RecTy *Ty) = 0;
+
+ /// convertInitializerBitRange - This method is used to implement the bitrange
+ /// selection operator. Given an initializer, it selects the specified bits
+ /// out, returning them as a new init of bits type. If it is not legal to use
+ /// the bit subscript operator on this initializer, return null.
+ ///
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ return 0;
+ }
+
+ /// convertInitListSlice - This method is used to implement the list slice
+ /// selection operator. Given an initializer, it selects the specified list
+ /// elements, returning them as a new init of list type. If it is not legal
+ /// to take a slice of this, return null.
+ ///
+ virtual Init *convertInitListSlice(const std::vector<unsigned> &Elements) {
+ return 0;
+ }
+
+ /// getFieldType - This method is used to implement the FieldInit class.
+ /// Implementors of this method should return the type of the named field if
+ /// they are of record type.
+ ///
+ virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; }
+
+ /// getFieldInit - This method complements getFieldType to return the
+ /// initializer for the specified field. If getFieldType returns non-null
+ /// this method should return non-null, otherwise it returns null.
+ ///
+ virtual Init *getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const {
+ return 0;
+ }
+
+ /// resolveReferences - This method is used by classes that refer to other
+ /// variables which may not be defined at the time the expression is formed.
+ /// If a value is set for the variable later, this method will be called on
+ /// users of the value to allow the value to propagate out.
+ ///
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV) {
+ return this;
+ }
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
+ I.print(OS); return OS;
+}
+
+/// TypedInit - This is the common super-class of types that have a specific,
+/// explicit, type.
+///
+class TypedInit : public Init {
+ RecTy *Ty;
+public:
+ explicit TypedInit(RecTy *T) : Ty(T) {}
+
+ RecTy *getType() const { return Ty; }
+
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+ virtual Init *convertInitListSlice(const std::vector<unsigned> &Elements);
+
+ /// getFieldType - This method is used to implement the FieldInit class.
+ /// Implementors of this method should return the type of the named field if
+ /// they are of record type.
+ ///
+ virtual RecTy *getFieldType(const std::string &FieldName) const;
+
+ /// resolveBitReference - This method is used to implement
+ /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
+ /// simply return the resolved value, otherwise we return null.
+ ///
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) = 0;
+
+ /// resolveListElementReference - This method is used to implement
+ /// VarListElementInit::resolveReferences. If the list element is resolvable
+ /// now, we return the resolved value, otherwise we return null.
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) = 0;
+};
+
+
+/// UnsetInit - ? - Represents an uninitialized value
+///
+class UnsetInit : public Init {
+public:
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual bool isComplete() const { return false; }
+ virtual std::string getAsString() const { return "?"; }
+};
+
+
+/// BitInit - true/false - Represent a concrete initializer for a bit.
+///
+class BitInit : public Init {
+ bool Value;
+public:
+ explicit BitInit(bool V) : Value(V) {}
+
+ bool getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual std::string getAsString() const { return Value ? "1" : "0"; }
+};
+
+/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value.
+/// It contains a vector of bits, whose size is determined by the type.
+///
+class BitsInit : public Init {
+ std::vector<Init*> Bits;
+public:
+ explicit BitsInit(unsigned Size) : Bits(Size) {}
+
+ unsigned getNumBits() const { return Bits.size(); }
+
+ Init *getBit(unsigned Bit) const {
+ assert(Bit < Bits.size() && "Bit index out of range!");
+ return Bits[Bit];
+ }
+ void setBit(unsigned Bit, Init *V) {
+ assert(Bit < Bits.size() && "Bit index out of range!");
+ assert(Bits[Bit] == 0 && "Bit already set!");
+ Bits[Bit] = V;
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual bool isComplete() const {
+ for (unsigned i = 0; i != getNumBits(); ++i)
+ if (!getBit(i)->isComplete()) return false;
+ return true;
+ }
+ bool allInComplete() const {
+ for (unsigned i = 0; i != getNumBits(); ++i)
+ if (getBit(i)->isComplete()) return false;
+ return true;
+ }
+ virtual std::string getAsString() const;
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+};
+
+
+/// IntInit - 7 - Represent an initalization by a literal integer value.
+///
+class IntInit : public TypedInit {
+ int64_t Value;
+public:
+ explicit IntInit(int64_t V) : TypedInit(new IntRecTy), Value(V) {}
+
+ int64_t getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual std::string getAsString() const;
+
+ /// resolveBitReference - This method is used to implement
+ /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
+ /// simply return the resolved value, otherwise we return null.
+ ///
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) {
+ assert(0 && "Illegal bit reference off int");
+ return 0;
+ }
+
+ /// resolveListElementReference - This method is used to implement
+ /// VarListElementInit::resolveReferences. If the list element is resolvable
+ /// now, we return the resolved value, otherwise we return null.
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) {
+ assert(0 && "Illegal element reference off int");
+ return 0;
+ }
+};
+
+
+/// StringInit - "foo" - Represent an initialization by a string value.
+///
+class StringInit : public TypedInit {
+ std::string Value;
+public:
+ explicit StringInit(const std::string &V)
+ : TypedInit(new StringRecTy), Value(V) {}
+
+ const std::string &getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual std::string getAsString() const { return "\"" + Value + "\""; }
+
+ /// resolveBitReference - This method is used to implement
+ /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
+ /// simply return the resolved value, otherwise we return null.
+ ///
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) {
+ assert(0 && "Illegal bit reference off string");
+ return 0;
+ }
+
+ /// resolveListElementReference - This method is used to implement
+ /// VarListElementInit::resolveReferences. If the list element is resolvable
+ /// now, we return the resolved value, otherwise we return null.
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) {
+ assert(0 && "Illegal element reference off string");
+ return 0;
+ }
+};
+
+/// CodeInit - "[{...}]" - Represent a code fragment.
+///
+class CodeInit : public Init {
+ std::string Value;
+public:
+ explicit CodeInit(const std::string &V) : Value(V) {}
+
+ const std::string getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual std::string getAsString() const { return "[{" + Value + "}]"; }
+};
+
+/// ListInit - [AL, AH, CL] - Represent a list of defs
+///
+class ListInit : public TypedInit {
+ std::vector<Init*> Values;
+public:
+ typedef std::vector<Init*>::iterator iterator;
+ typedef std::vector<Init*>::const_iterator const_iterator;
+
+ explicit ListInit(std::vector<Init*> &Vs, RecTy *EltTy)
+ : TypedInit(new ListRecTy(EltTy)) {
+ Values.swap(Vs);
+ }
+ explicit ListInit(iterator Start, iterator End, RecTy *EltTy)
+ : TypedInit(new ListRecTy(EltTy)), Values(Start, End) {}
+
+ unsigned getSize() const { return Values.size(); }
+ Init *getElement(unsigned i) const {
+ assert(i < Values.size() && "List element index out of range!");
+ return Values[i];
+ }
+
+ Record *getElementAsRecord(unsigned i) const;
+
+ Init *convertInitListSlice(const std::vector<unsigned> &Elements);
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ /// resolveReferences - This method is used by classes that refer to other
+ /// variables which may not be defined at the time they expression is formed.
+ /// If a value is set for the variable later, this method will be called on
+ /// users of the value to allow the value to propagate out.
+ ///
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+
+ virtual std::string getAsString() const;
+
+ inline iterator begin() { return Values.begin(); }
+ inline const_iterator begin() const { return Values.begin(); }
+ inline iterator end () { return Values.end(); }
+ inline const_iterator end () const { return Values.end(); }
+
+ inline size_t size () const { return Values.size(); }
+ inline bool empty() const { return Values.empty(); }
+
+ /// resolveBitReference - This method is used to implement
+ /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
+ /// simply return the resolved value, otherwise we return null.
+ ///
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) {
+ assert(0 && "Illegal bit reference off list");
+ return 0;
+ }
+
+ /// resolveListElementReference - This method is used to implement
+ /// VarListElementInit::resolveReferences. If the list element is resolvable
+ /// now, we return the resolved value, otherwise we return null.
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt);
+};
+
+
+/// OpInit - Base class for operators
+///
+class OpInit : public TypedInit {
+public:
+ OpInit(RecTy *Type) : TypedInit(Type) {}
+
+ // Clone - Clone this operator, replacing arguments with the new list
+ virtual OpInit *clone(std::vector<Init *> &Operands) = 0;
+
+ virtual int getNumOperands() const = 0;
+ virtual Init *getOperand(int i) = 0;
+
+ // Fold - If possible, fold this to a simpler init. Return this if not
+ // possible to fold.
+ virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) = 0;
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit);
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt);
+};
+
+
+/// UnOpInit - !op (X) - Transform an init.
+///
+class UnOpInit : public OpInit {
+public:
+ enum UnaryOp { CAST, CAR, CDR, LNULL };
+private:
+ UnaryOp Opc;
+ Init *LHS;
+public:
+ UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type) :
+ OpInit(Type), Opc(opc), LHS(lhs) {
+ }
+
+ // Clone - Clone this operator, replacing arguments with the new list
+ virtual OpInit *clone(std::vector<Init *> &Operands) {
+ assert(Operands.size() == 1 &&
+ "Wrong number of operands for unary operation");
+ return new UnOpInit(getOpcode(), *Operands.begin(), getType());
+ }
+
+ int getNumOperands() const { return 1; }
+ Init *getOperand(int i) {
+ assert(i == 0 && "Invalid operand id for unary operator");
+ return getOperand();
+ }
+
+ UnaryOp getOpcode() const { return Opc; }
+ Init *getOperand() const { return LHS; }
+
+ // Fold - If possible, fold this to a simpler init. Return this if not
+ // possible to fold.
+ Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+
+ virtual std::string getAsString() const;
+};
+
+/// BinOpInit - !op (X, Y) - Combine two inits.
+///
+class BinOpInit : public OpInit {
+public:
+ enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, NAMECONCAT, EQ };
+private:
+ BinaryOp Opc;
+ Init *LHS, *RHS;
+public:
+ BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
+ OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {
+ }
+
+ // Clone - Clone this operator, replacing arguments with the new list
+ virtual OpInit *clone(std::vector<Init *> &Operands) {
+ assert(Operands.size() == 2 &&
+ "Wrong number of operands for binary operation");
+ return new BinOpInit(getOpcode(), Operands[0], Operands[1], getType());
+ }
+
+ int getNumOperands() const { return 2; }
+ Init *getOperand(int i) {
+ assert((i == 0 || i == 1) && "Invalid operand id for binary operator");
+ if (i == 0) {
+ return getLHS();
+ } else {
+ return getRHS();
+ }
+ }
+
+ BinaryOp getOpcode() const { return Opc; }
+ Init *getLHS() const { return LHS; }
+ Init *getRHS() const { return RHS; }
+
+ // Fold - If possible, fold this to a simpler init. Return this if not
+ // possible to fold.
+ Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+
+ virtual std::string getAsString() const;
+};
+
+/// TernOpInit - !op (X, Y, Z) - Combine two inits.
+///
+class TernOpInit : public OpInit {
+public:
+ enum TernaryOp { SUBST, FOREACH, IF };
+private:
+ TernaryOp Opc;
+ Init *LHS, *MHS, *RHS;
+public:
+ TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, RecTy *Type) :
+ OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {
+ }
+
+ // Clone - Clone this operator, replacing arguments with the new list
+ virtual OpInit *clone(std::vector<Init *> &Operands) {
+ assert(Operands.size() == 3 &&
+ "Wrong number of operands for ternary operation");
+ return new TernOpInit(getOpcode(), Operands[0], Operands[1], Operands[2],
+ getType());
+ }
+
+ int getNumOperands() const { return 3; }
+ Init *getOperand(int i) {
+ assert((i == 0 || i == 1 || i == 2) &&
+ "Invalid operand id for ternary operator");
+ if (i == 0) {
+ return getLHS();
+ } else if (i == 1) {
+ return getMHS();
+ } else {
+ return getRHS();
+ }
+ }
+
+ TernaryOp getOpcode() const { return Opc; }
+ Init *getLHS() const { return LHS; }
+ Init *getMHS() const { return MHS; }
+ Init *getRHS() const { return RHS; }
+
+ // Fold - If possible, fold this to a simpler init. Return this if not
+ // possible to fold.
+ Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+
+ virtual std::string getAsString() const;
+};
+
+
+/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
+///
+class VarInit : public TypedInit {
+ std::string VarName;
+public:
+ explicit VarInit(const std::string &VN, RecTy *T)
+ : TypedInit(T), VarName(VN) {}
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ const std::string &getName() const { return VarName; }
+
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit);
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt);
+
+ virtual RecTy *getFieldType(const std::string &FieldName) const;
+ virtual Init *getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const;
+
+ /// resolveReferences - This method is used by classes that refer to other
+ /// variables which may not be defined at the time they expression is formed.
+ /// If a value is set for the variable later, this method will be called on
+ /// users of the value to allow the value to propagate out.
+ ///
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+
+ virtual std::string getAsString() const { return VarName; }
+};
+
+
+/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field.
+///
+class VarBitInit : public Init {
+ TypedInit *TI;
+ unsigned Bit;
+public:
+ VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) {
+ assert(T->getType() && dynamic_cast<BitsRecTy*>(T->getType()) &&
+ ((BitsRecTy*)T->getType())->getNumBits() > B &&
+ "Illegal VarBitInit expression!");
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ TypedInit *getVariable() const { return TI; }
+ unsigned getBitNum() const { return Bit; }
+
+ virtual std::string getAsString() const;
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+};
+
+/// VarListElementInit - List[4] - Represent access to one element of a var or
+/// field.
+class VarListElementInit : public TypedInit {
+ TypedInit *TI;
+ unsigned Element;
+public:
+ VarListElementInit(TypedInit *T, unsigned E)
+ : TypedInit(dynamic_cast<ListRecTy*>(T->getType())->getElementType()),
+ TI(T), Element(E) {
+ assert(T->getType() && dynamic_cast<ListRecTy*>(T->getType()) &&
+ "Illegal VarBitInit expression!");
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ TypedInit *getVariable() const { return TI; }
+ unsigned getElementNum() const { return Element; }
+
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit);
+
+ /// resolveListElementReference - This method is used to implement
+ /// VarListElementInit::resolveReferences. If the list element is resolvable
+ /// now, we return the resolved value, otherwise we return null.
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt);
+
+ virtual std::string getAsString() const;
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+};
+
+/// DefInit - AL - Represent a reference to a 'def' in the description
+///
+class DefInit : public TypedInit {
+ Record *Def;
+public:
+ explicit DefInit(Record *D) : TypedInit(new RecordRecTy(D)), Def(D) {}
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ Record *getDef() const { return Def; }
+
+ //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual RecTy *getFieldType(const std::string &FieldName) const;
+ virtual Init *getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const;
+
+ virtual std::string getAsString() const;
+
+ /// resolveBitReference - This method is used to implement
+ /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
+ /// simply return the resolved value, otherwise we return null.
+ ///
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) {
+ assert(0 && "Illegal bit reference off def");
+ return 0;
+ }
+
+ /// resolveListElementReference - This method is used to implement
+ /// VarListElementInit::resolveReferences. If the list element is resolvable
+ /// now, we return the resolved value, otherwise we return null.
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) {
+ assert(0 && "Illegal element reference off def");
+ return 0;
+ }
+};
+
+
+/// FieldInit - X.Y - Represent a reference to a subfield of a variable
+///
+class FieldInit : public TypedInit {
+ Init *Rec; // Record we are referring to
+ std::string FieldName; // Field we are accessing
+public:
+ FieldInit(Init *R, const std::string &FN)
+ : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) {
+ assert(getType() && "FieldInit with non-record type!");
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit);
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt);
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+
+ virtual std::string getAsString() const {
+ return Rec->getAsString() + "." + FieldName;
+ }
+};
+
+/// DagInit - (v a, b) - Represent a DAG tree value. DAG inits are required
+/// to have at least one value then a (possibly empty) list of arguments. Each
+/// argument can have a name associated with it.
+///
+class DagInit : public TypedInit {
+ Init *Val;
+ std::string ValName;
+ std::vector<Init*> Args;
+ std::vector<std::string> ArgNames;
+public:
+ DagInit(Init *V, std::string VN,
+ const std::vector<std::pair<Init*, std::string> > &args)
+ : TypedInit(new DagRecTy), Val(V), ValName(VN) {
+ Args.reserve(args.size());
+ ArgNames.reserve(args.size());
+ for (unsigned i = 0, e = args.size(); i != e; ++i) {
+ Args.push_back(args[i].first);
+ ArgNames.push_back(args[i].second);
+ }
+ }
+ DagInit(Init *V, std::string VN, const std::vector<Init*> &args,
+ const std::vector<std::string> &argNames)
+ : TypedInit(new DagRecTy), Val(V), ValName(VN), Args(args),
+ ArgNames(argNames) { }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ Init *getOperator() const { return Val; }
+
+ const std::string &getName() const { return ValName; }
+
+ unsigned getNumArgs() const { return Args.size(); }
+ Init *getArg(unsigned Num) const {
+ assert(Num < Args.size() && "Arg number out of range!");
+ return Args[Num];
+ }
+ const std::string &getArgName(unsigned Num) const {
+ assert(Num < ArgNames.size() && "Arg number out of range!");
+ return ArgNames[Num];
+ }
+
+ void setArg(unsigned Num, Init *I) {
+ assert(Num < Args.size() && "Arg number out of range!");
+ Args[Num] = I;
+ }
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV);
+
+ virtual std::string getAsString() const;
+
+ typedef std::vector<Init*>::iterator arg_iterator;
+ typedef std::vector<Init*>::const_iterator const_arg_iterator;
+ typedef std::vector<std::string>::iterator name_iterator;
+ typedef std::vector<std::string>::const_iterator const_name_iterator;
+
+ inline arg_iterator arg_begin() { return Args.begin(); }
+ inline const_arg_iterator arg_begin() const { return Args.begin(); }
+ inline arg_iterator arg_end () { return Args.end(); }
+ inline const_arg_iterator arg_end () const { return Args.end(); }
+
+ inline size_t arg_size () const { return Args.size(); }
+ inline bool arg_empty() const { return Args.empty(); }
+
+ inline name_iterator name_begin() { return ArgNames.begin(); }
+ inline const_name_iterator name_begin() const { return ArgNames.begin(); }
+ inline name_iterator name_end () { return ArgNames.end(); }
+ inline const_name_iterator name_end () const { return ArgNames.end(); }
+
+ inline size_t name_size () const { return ArgNames.size(); }
+ inline bool name_empty() const { return ArgNames.empty(); }
+
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) {
+ assert(0 && "Illegal bit reference off dag");
+ return 0;
+ }
+
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) {
+ assert(0 && "Illegal element reference off dag");
+ return 0;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// High-Level Classes
+//===----------------------------------------------------------------------===//
+
+class RecordVal {
+ std::string Name;
+ RecTy *Ty;
+ unsigned Prefix;
+ Init *Value;
+public:
+ RecordVal(const std::string &N, RecTy *T, unsigned P);
+
+ const std::string &getName() const { return Name; }
+
+ unsigned getPrefix() const { return Prefix; }
+ RecTy *getType() const { return Ty; }
+ Init *getValue() const { return Value; }
+
+ bool setValue(Init *V) {
+ if (V) {
+ Value = V->convertInitializerTo(Ty);
+ return Value == 0;
+ }
+ Value = 0;
+ return false;
+ }
+
+ void dump() const;
+ void print(raw_ostream &OS, bool PrintSem = true) const;
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
+ RV.print(OS << " ");
+ return OS;
+}
+
+class Record {
+ static unsigned LastID;
+
+ // Unique record ID.
+ unsigned ID;
+ std::string Name;
+ SMLoc Loc;
+ std::vector<std::string> TemplateArgs;
+ std::vector<RecordVal> Values;
+ std::vector<Record*> SuperClasses;
+public:
+
+ explicit Record(const std::string &N, SMLoc loc) :
+ ID(LastID++), Name(N), Loc(loc) {}
+ ~Record() {}
+
+
+ static unsigned getNewUID() { return LastID++; }
+
+
+ unsigned getID() const { return ID; }
+
+ const std::string &getName() const { return Name; }
+ void setName(const std::string &Name); // Also updates RecordKeeper.
+
+ SMLoc getLoc() const { return Loc; }
+
+ const std::vector<std::string> &getTemplateArgs() const {
+ return TemplateArgs;
+ }
+ const std::vector<RecordVal> &getValues() const { return Values; }
+ const std::vector<Record*> &getSuperClasses() const { return SuperClasses; }
+
+ bool isTemplateArg(StringRef Name) const {
+ for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
+ if (TemplateArgs[i] == Name) return true;
+ return false;
+ }
+
+ const RecordVal *getValue(StringRef Name) const {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) return &Values[i];
+ return 0;
+ }
+ RecordVal *getValue(StringRef Name) {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) return &Values[i];
+ return 0;
+ }
+
+ void addTemplateArg(StringRef Name) {
+ assert(!isTemplateArg(Name) && "Template arg already defined!");
+ TemplateArgs.push_back(Name);
+ }
+
+ void addValue(const RecordVal &RV) {
+ assert(getValue(RV.getName()) == 0 && "Value already added!");
+ Values.push_back(RV);
+ }
+
+ void removeValue(StringRef Name) {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) {
+ Values.erase(Values.begin()+i);
+ return;
+ }
+ assert(0 && "Cannot remove an entry that does not exist!");
+ }
+
+ bool isSubClassOf(const Record *R) const {
+ for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+ if (SuperClasses[i] == R)
+ return true;
+ return false;
+ }
+
+ bool isSubClassOf(StringRef Name) const {
+ for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+ if (SuperClasses[i]->getName() == Name)
+ return true;
+ return false;
+ }
+
+ void addSuperClass(Record *R) {
+ assert(!isSubClassOf(R) && "Already subclassing record!");
+ SuperClasses.push_back(R);
+ }
+
+ /// resolveReferences - If there are any field references that refer to fields
+ /// that have been filled in, we can propagate the values now.
+ ///
+ void resolveReferences() { resolveReferencesTo(0); }
+
+ /// resolveReferencesTo - If anything in this record refers to RV, replace the
+ /// reference to RV with the RHS of RV. If RV is null, we resolve all
+ /// possible references.
+ void resolveReferencesTo(const RecordVal *RV);
+
+ void dump() const;
+
+ //===--------------------------------------------------------------------===//
+ // High-level methods useful to tablegen back-ends
+ //
+
+ /// getValueInit - Return the initializer for a value with the specified name,
+ /// or throw an exception if the field does not exist.
+ ///
+ Init *getValueInit(StringRef FieldName) const;
+
+ /// getValueAsString - This method looks up the specified field and returns
+ /// its value as a string, throwing an exception if the field does not exist
+ /// or if the value is not a string.
+ ///
+ std::string getValueAsString(StringRef FieldName) const;
+
+ /// getValueAsBitsInit - This method looks up the specified field and returns
+ /// its value as a BitsInit, throwing an exception if the field does not exist
+ /// or if the value is not the right type.
+ ///
+ BitsInit *getValueAsBitsInit(StringRef FieldName) const;
+
+ /// getValueAsListInit - This method looks up the specified field and returns
+ /// its value as a ListInit, throwing an exception if the field does not exist
+ /// or if the value is not the right type.
+ ///
+ ListInit *getValueAsListInit(StringRef FieldName) const;
+
+ /// getValueAsListOfDefs - This method looks up the specified field and
+ /// returns its value as a vector of records, throwing an exception if the
+ /// field does not exist or if the value is not the right type.
+ ///
+ std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;
+
+ /// getValueAsListOfInts - This method looks up the specified field and returns
+ /// its value as a vector of integers, throwing an exception if the field does
+ /// not exist or if the value is not the right type.
+ ///
+ std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
+
+ /// getValueAsDef - This method looks up the specified field and returns its
+ /// value as a Record, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ Record *getValueAsDef(StringRef FieldName) const;
+
+ /// getValueAsBit - This method looks up the specified field and returns its
+ /// value as a bit, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ bool getValueAsBit(StringRef FieldName) const;
+
+ /// getValueAsInt - This method looks up the specified field and returns its
+ /// value as an int64_t, throwing an exception if the field does not exist or
+ /// if the value is not the right type.
+ ///
+ int64_t getValueAsInt(StringRef FieldName) const;
+
+ /// getValueAsDag - This method looks up the specified field and returns its
+ /// value as an Dag, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ DagInit *getValueAsDag(StringRef FieldName) const;
+
+ /// getValueAsCode - This method looks up the specified field and returns
+ /// its value as the string data in a CodeInit, throwing an exception if the
+ /// field does not exist or if the value is not a code object.
+ ///
+ std::string getValueAsCode(StringRef FieldName) const;
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const Record &R);
+
+struct MultiClass {
+ Record Rec; // Placeholder for template args and Name.
+ typedef std::vector<Record*> RecordVector;
+ RecordVector DefPrototypes;
+
+ void dump() const;
+
+ MultiClass(const std::string &Name, SMLoc Loc) : Rec(Name, Loc) {}
+};
+
+class RecordKeeper {
+ std::map<std::string, Record*> Classes, Defs;
+public:
+ ~RecordKeeper() {
+ for (std::map<std::string, Record*>::iterator I = Classes.begin(),
+ E = Classes.end(); I != E; ++I)
+ delete I->second;
+ for (std::map<std::string, Record*>::iterator I = Defs.begin(),
+ E = Defs.end(); I != E; ++I)
+ delete I->second;
+ }
+
+ const std::map<std::string, Record*> &getClasses() const { return Classes; }
+ const std::map<std::string, Record*> &getDefs() const { return Defs; }
+
+ Record *getClass(const std::string &Name) const {
+ std::map<std::string, Record*>::const_iterator I = Classes.find(Name);
+ return I == Classes.end() ? 0 : I->second;
+ }
+ Record *getDef(const std::string &Name) const {
+ std::map<std::string, Record*>::const_iterator I = Defs.find(Name);
+ return I == Defs.end() ? 0 : I->second;
+ }
+ void addClass(Record *R) {
+ assert(getClass(R->getName()) == 0 && "Class already exists!");
+ Classes.insert(std::make_pair(R->getName(), R));
+ }
+ void addDef(Record *R) {
+ assert(getDef(R->getName()) == 0 && "Def already exists!");
+ Defs.insert(std::make_pair(R->getName(), R));
+ }
+
+ /// removeClass - Remove, but do not delete, the specified record.
+ ///
+ void removeClass(const std::string &Name) {
+ assert(Classes.count(Name) && "Class does not exist!");
+ Classes.erase(Name);
+ }
+ /// removeDef - Remove, but do not delete, the specified record.
+ ///
+ void removeDef(const std::string &Name) {
+ assert(Defs.count(Name) && "Def does not exist!");
+ Defs.erase(Name);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // High-level helper methods, useful for tablegen backends...
+
+ /// getAllDerivedDefinitions - This method returns all concrete definitions
+ /// that derive from the specified class name. If a class with the specified
+ /// name does not exist, an exception is thrown.
+ std::vector<Record*>
+ getAllDerivedDefinitions(const std::string &ClassName) const;
+
+
+ void dump() const;
+};
+
+/// LessRecord - Sorting predicate to sort record pointers by name.
+///
+struct LessRecord {
+ bool operator()(const Record *Rec1, const Record *Rec2) const {
+ return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
+ }
+};
+
+/// LessRecordFieldName - Sorting predicate to sort record pointers by their
+/// name field.
+///
+struct LessRecordFieldName {
+ bool operator()(const Record *Rec1, const Record *Rec2) const {
+ return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
+ }
+};
+
+
+class TGError {
+ SMLoc Loc;
+ std::string Message;
+public:
+ TGError(SMLoc loc, const std::string &message) : Loc(loc), Message(message) {}
+
+ SMLoc getLoc() const { return Loc; }
+ const std::string &getMessage() const { return Message; }
+};
+
+
+raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);
+
+extern RecordKeeper Records;
+
+void PrintError(SMLoc ErrorLoc, const std::string &Msg);
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
new file mode 100644
index 0000000..6f06705
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -0,0 +1,1017 @@
+//===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of a target
+// register file for a code generator. It uses instances of the Register,
+// RegisterAliases, and RegisterClass classes to gather this information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterInfoEmitter.h"
+#include "CodeGenTarget.h"
+#include "CodeGenRegisters.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/STLExtras.h"
+#include <algorithm>
+#include <set>
+using namespace llvm;
+
+// runEnums - Print out enum values for all of the registers.
+void RegisterInfoEmitter::runEnums(raw_ostream &OS) {
+ CodeGenTarget Target;
+ const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
+
+ std::string Namespace = Registers[0].TheDef->getValueAsString("Namespace");
+
+ EmitSourceFileHeader("Target Register Enum Values", OS);
+ OS << "namespace llvm {\n\n";
+
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << "enum {\n NoRegister,\n";
+
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i)
+ OS << " " << Registers[i].getName() << ", \t// " << i+1 << "\n";
+ OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
+ OS << "};\n";
+ if (!Namespace.empty())
+ OS << "}\n";
+
+ const std::vector<Record*> SubRegIndices = Target.getSubRegIndices();
+ if (!SubRegIndices.empty()) {
+ OS << "\n// Subregister indices\n";
+ Namespace = SubRegIndices[0]->getValueAsString("Namespace");
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << "enum {\n NoSubRegister,\n";
+ for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i)
+ OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n";
+ OS << " NUM_TARGET_SUBREGS = " << SubRegIndices.size()+1 << "\n";
+ OS << "};\n";
+ if (!Namespace.empty())
+ OS << "}\n";
+ }
+ OS << "} // End llvm namespace \n";
+}
+
+void RegisterInfoEmitter::runHeader(raw_ostream &OS) {
+ EmitSourceFileHeader("Register Information Header Fragment", OS);
+ CodeGenTarget Target;
+ const std::string &TargetName = Target.getName();
+ std::string ClassName = TargetName + "GenRegisterInfo";
+
+ OS << "#include \"llvm/Target/TargetRegisterInfo.h\"\n";
+ OS << "#include <string>\n\n";
+
+ OS << "namespace llvm {\n\n";
+
+ OS << "struct " << ClassName << " : public TargetRegisterInfo {\n"
+ << " explicit " << ClassName
+ << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n"
+ << " virtual int getDwarfRegNumFull(unsigned RegNum, "
+ << "unsigned Flavour) const;\n"
+ << " virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0;\n"
+ << " virtual bool needsStackRealignment(const MachineFunction &) const\n"
+ << " { return false; }\n"
+ << " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n"
+ << " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n"
+ << " unsigned composeSubRegIndices(unsigned, unsigned) const;\n"
+ << "};\n\n";
+
+ const std::vector<CodeGenRegisterClass> &RegisterClasses =
+ Target.getRegisterClasses();
+
+ if (!RegisterClasses.empty()) {
+ OS << "namespace " << RegisterClasses[0].Namespace
+ << " { // Register classes\n";
+
+ OS << " enum {\n";
+ for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
+ if (i) OS << ",\n";
+ OS << " " << RegisterClasses[i].getName() << "RegClassID";
+ OS << " = " << i;
+ }
+ OS << "\n };\n\n";
+
+ for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
+ const std::string &Name = RegisterClasses[i].getName();
+
+ // Output the register class definition.
+ OS << " struct " << Name << "Class : public TargetRegisterClass {\n"
+ << " " << Name << "Class();\n"
+ << RegisterClasses[i].MethodProtos << " };\n";
+
+ // Output the extern for the instance.
+ OS << " extern " << Name << "Class\t" << Name << "RegClass;\n";
+ // Output the extern for the pointer to the instance (should remove).
+ OS << " static TargetRegisterClass * const "<< Name <<"RegisterClass = &"
+ << Name << "RegClass;\n";
+ }
+ OS << "} // end of namespace " << TargetName << "\n\n";
+ }
+ OS << "} // End llvm namespace \n";
+}
+
+static void addSuperReg(Record *R, Record *S,
+ std::map<Record*, std::set<Record*>, LessRecord> &SubRegs,
+ std::map<Record*, std::set<Record*>, LessRecord> &SuperRegs,
+ std::map<Record*, std::set<Record*>, LessRecord> &Aliases) {
+ if (R == S) {
+ errs() << "Error: recursive sub-register relationship between"
+ << " register " << getQualifiedName(R)
+ << " and its sub-registers?\n";
+ abort();
+ }
+ if (!SuperRegs[R].insert(S).second)
+ return;
+ SubRegs[S].insert(R);
+ Aliases[R].insert(S);
+ Aliases[S].insert(R);
+ if (SuperRegs.count(S))
+ for (std::set<Record*>::iterator I = SuperRegs[S].begin(),
+ E = SuperRegs[S].end(); I != E; ++I)
+ addSuperReg(R, *I, SubRegs, SuperRegs, Aliases);
+}
+
+static void addSubSuperReg(Record *R, Record *S,
+ std::map<Record*, std::set<Record*>, LessRecord> &SubRegs,
+ std::map<Record*, std::set<Record*>, LessRecord> &SuperRegs,
+ std::map<Record*, std::set<Record*>, LessRecord> &Aliases) {
+ if (R == S) {
+ errs() << "Error: recursive sub-register relationship between"
+ << " register " << getQualifiedName(R)
+ << " and its sub-registers?\n";
+ abort();
+ }
+
+ if (!SubRegs[R].insert(S).second)
+ return;
+ addSuperReg(S, R, SubRegs, SuperRegs, Aliases);
+ Aliases[R].insert(S);
+ Aliases[S].insert(R);
+ if (SubRegs.count(S))
+ for (std::set<Record*>::iterator I = SubRegs[S].begin(),
+ E = SubRegs[S].end(); I != E; ++I)
+ addSubSuperReg(R, *I, SubRegs, SuperRegs, Aliases);
+}
+
+struct RegisterMaps {
+ // Map SubRegIndex -> Register
+ typedef std::map<Record*, Record*, LessRecord> SubRegMap;
+ // Map Register -> SubRegMap
+ typedef std::map<Record*, SubRegMap> SubRegMaps;
+
+ SubRegMaps SubReg;
+ SubRegMap &inferSubRegIndices(Record *Reg);
+
+ // Composite SubRegIndex instances.
+ // Map (SubRegIndex,SubRegIndex) -> SubRegIndex
+ typedef DenseMap<std::pair<Record*,Record*>,Record*> CompositeMap;
+ CompositeMap Composite;
+
+ // Compute SubRegIndex compositions after inferSubRegIndices has run on all
+ // registers.
+ void computeComposites();
+};
+
+// Calculate all subregindices for Reg. Loopy subregs cause infinite recursion.
+RegisterMaps::SubRegMap &RegisterMaps::inferSubRegIndices(Record *Reg) {
+ SubRegMap &SRM = SubReg[Reg];
+ if (!SRM.empty())
+ return SRM;
+ std::vector<Record*> SubRegs = Reg->getValueAsListOfDefs("SubRegs");
+ std::vector<Record*> Indices = Reg->getValueAsListOfDefs("SubRegIndices");
+ if (SubRegs.size() != Indices.size())
+ throw "Register " + Reg->getName() + " SubRegIndices doesn't match SubRegs";
+
+ // First insert the direct subregs and make sure they are fully indexed.
+ for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) {
+ if (!SRM.insert(std::make_pair(Indices[i], SubRegs[i])).second)
+ throw "SubRegIndex " + Indices[i]->getName()
+ + " appears twice in Register " + Reg->getName();
+ inferSubRegIndices(SubRegs[i]);
+ }
+
+ // Keep track of inherited subregs and how they can be reached.
+ // Register -> (SubRegIndex, SubRegIndex)
+ typedef std::map<Record*, std::pair<Record*,Record*>, LessRecord> OrphanMap;
+ OrphanMap Orphans;
+
+ // Clone inherited subregs. Here the order is important - earlier subregs take
+ // precedence.
+ for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) {
+ SubRegMap &M = SubReg[SubRegs[i]];
+ for (SubRegMap::iterator si = M.begin(), se = M.end(); si != se; ++si)
+ if (!SRM.insert(*si).second)
+ Orphans[si->second] = std::make_pair(Indices[i], si->first);
+ }
+
+ // Finally process the composites.
+ ListInit *Comps = Reg->getValueAsListInit("CompositeIndices");
+ for (unsigned i = 0, e = Comps->size(); i != e; ++i) {
+ DagInit *Pat = dynamic_cast<DagInit*>(Comps->getElement(i));
+ if (!Pat)
+ throw "Invalid dag '" + Comps->getElement(i)->getAsString()
+ + "' in CompositeIndices";
+ DefInit *BaseIdxInit = dynamic_cast<DefInit*>(Pat->getOperator());
+ if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex"))
+ throw "Invalid SubClassIndex in " + Pat->getAsString();
+
+ // Resolve list of subreg indices into R2.
+ Record *R2 = Reg;
+ for (DagInit::const_arg_iterator di = Pat->arg_begin(),
+ de = Pat->arg_end(); di != de; ++di) {
+ DefInit *IdxInit = dynamic_cast<DefInit*>(*di);
+ if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex"))
+ throw "Invalid SubClassIndex in " + Pat->getAsString();
+ SubRegMap::const_iterator ni = SubReg[R2].find(IdxInit->getDef());
+ if (ni == SubReg[R2].end())
+ throw "Composite " + Pat->getAsString() + " refers to bad index in "
+ + R2->getName();
+ R2 = ni->second;
+ }
+
+ // Insert composite index. Allow overriding inherited indices etc.
+ SRM[BaseIdxInit->getDef()] = R2;
+
+ // R2 is now directly addressable, no longer an orphan.
+ Orphans.erase(R2);
+ }
+
+ // Now, Orphans contains the inherited subregisters without a direct index.
+ if (!Orphans.empty()) {
+ errs() << "Error: Register " << getQualifiedName(Reg)
+ << " inherited subregisters without an index:\n";
+ for (OrphanMap::iterator i = Orphans.begin(), e = Orphans.end(); i != e;
+ ++i) {
+ errs() << " " << getQualifiedName(i->first)
+ << " = " << i->second.first->getName()
+ << ", " << i->second.second->getName() << "\n";
+ }
+ abort();
+ }
+ return SRM;
+}
+
+void RegisterMaps::computeComposites() {
+ for (SubRegMaps::const_iterator sri = SubReg.begin(), sre = SubReg.end();
+ sri != sre; ++sri) {
+ Record *Reg1 = sri->first;
+ const SubRegMap &SRM1 = sri->second;
+ for (SubRegMap::const_iterator i1 = SRM1.begin(), e1 = SRM1.end();
+ i1 != e1; ++i1) {
+ Record *Idx1 = i1->first;
+ Record *Reg2 = i1->second;
+ // Ignore identity compositions.
+ if (Reg1 == Reg2)
+ continue;
+ // If Reg2 has no subregs, Idx1 doesn't compose.
+ if (!SubReg.count(Reg2))
+ continue;
+ const SubRegMap &SRM2 = SubReg[Reg2];
+ // Try composing Idx1 with another SubRegIndex.
+ for (SubRegMap::const_iterator i2 = SRM2.begin(), e2 = SRM2.end();
+ i2 != e2; ++i2) {
+ std::pair<Record*,Record*> IdxPair(Idx1, i2->first);
+ Record *Reg3 = i2->second;
+ // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3.
+ for (SubRegMap::const_iterator i1d = SRM1.begin(), e1d = SRM1.end();
+ i1d != e1d; ++i1d) {
+ // Ignore identity compositions.
+ if (Reg2 == Reg3)
+ continue;
+ if (i1d->second == Reg3) {
+ std::pair<CompositeMap::iterator,bool> Ins =
+ Composite.insert(std::make_pair(IdxPair, i1d->first));
+ // Conflicting composition?
+ if (!Ins.second && Ins.first->second != i1d->first) {
+ errs() << "Error: SubRegIndex " << getQualifiedName(Idx1)
+ << " and " << getQualifiedName(IdxPair.second)
+ << " compose ambiguously as "
+ << getQualifiedName(Ins.first->second) << " or "
+ << getQualifiedName(i1d->first) << "\n";
+ abort();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // We don't care about the difference between (Idx1, Idx2) -> Idx2 and invalid
+ // compositions, so remove any mappings of that form.
+ for (CompositeMap::iterator i = Composite.begin(), e = Composite.end();
+ i != e;) {
+ CompositeMap::iterator j = i;
+ ++i;
+ if (j->first.second == j->second)
+ Composite.erase(j);
+ }
+}
+
+class RegisterSorter {
+private:
+ std::map<Record*, std::set<Record*>, LessRecord> &RegisterSubRegs;
+
+public:
+ RegisterSorter(std::map<Record*, std::set<Record*>, LessRecord> &RS)
+ : RegisterSubRegs(RS) {}
+
+ bool operator()(Record *RegA, Record *RegB) {
+ // B is sub-register of A.
+ return RegisterSubRegs.count(RegA) && RegisterSubRegs[RegA].count(RegB);
+ }
+};
+
+// RegisterInfoEmitter::run - Main register file description emitter.
+//
+void RegisterInfoEmitter::run(raw_ostream &OS) {
+ CodeGenTarget Target;
+ EmitSourceFileHeader("Register Information Source Fragment", OS);
+
+ OS << "namespace llvm {\n\n";
+
+ // Start out by emitting each of the register classes... to do this, we build
+ // a set of registers which belong to a register class, this is to ensure that
+ // each register is only in a single register class.
+ //
+ const std::vector<CodeGenRegisterClass> &RegisterClasses =
+ Target.getRegisterClasses();
+
+ // Loop over all of the register classes... emitting each one.
+ OS << "namespace { // Register classes...\n";
+
+ // RegClassesBelongedTo - Keep track of which register classes each reg
+ // belongs to.
+ std::multimap<Record*, const CodeGenRegisterClass*> RegClassesBelongedTo;
+
+ // Emit the register enum value arrays for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RegisterClasses[rc];
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.TheDef->getName();
+
+ // Emit the register list now.
+ OS << " // " << Name << " Register Class...\n"
+ << " static const unsigned " << Name
+ << "[] = {\n ";
+ for (unsigned i = 0, e = RC.Elements.size(); i != e; ++i) {
+ Record *Reg = RC.Elements[i];
+ OS << getQualifiedName(Reg) << ", ";
+
+ // Keep track of which regclasses this register is in.
+ RegClassesBelongedTo.insert(std::make_pair(Reg, &RC));
+ }
+ OS << "\n };\n\n";
+ }
+
+ // Emit the ValueType arrays for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RegisterClasses[rc];
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.TheDef->getName() + "VTs";
+
+ // Emit the register list now.
+ OS << " // " << Name
+ << " Register Class Value Types...\n"
+ << " static const EVT " << Name
+ << "[] = {\n ";
+ for (unsigned i = 0, e = RC.VTs.size(); i != e; ++i)
+ OS << getEnumName(RC.VTs[i]) << ", ";
+ OS << "MVT::Other\n };\n\n";
+ }
+ OS << "} // end anonymous namespace\n\n";
+
+ // Now that all of the structs have been emitted, emit the instances.
+ if (!RegisterClasses.empty()) {
+ OS << "namespace " << RegisterClasses[0].Namespace
+ << " { // Register class instances\n";
+ for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
+ OS << " " << RegisterClasses[i].getName() << "Class\t"
+ << RegisterClasses[i].getName() << "RegClass;\n";
+
+ std::map<unsigned, std::set<unsigned> > SuperClassMap;
+ std::map<unsigned, std::set<unsigned> > SuperRegClassMap;
+ OS << "\n";
+
+ unsigned NumSubRegIndices = Target.getSubRegIndices().size();
+
+ if (NumSubRegIndices) {
+ // Emit the sub-register classes for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ std::vector<Record*> SRC(NumSubRegIndices);
+ for (DenseMap<Record*,Record*>::const_iterator
+ i = RC.SubRegClasses.begin(),
+ e = RC.SubRegClasses.end(); i != e; ++i) {
+ // Build SRC array.
+ unsigned idx = Target.getSubRegIndexNo(i->first);
+ SRC.at(idx-1) = i->second;
+
+ // Find the register class number of i->second for SuperRegClassMap.
+ for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
+ const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
+ if (RC2.TheDef == i->second) {
+ SuperRegClassMap[rc2].insert(rc);
+ break;
+ }
+ }
+ }
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.TheDef->getName();
+
+ OS << " // " << Name
+ << " Sub-register Classes...\n"
+ << " static const TargetRegisterClass* const "
+ << Name << "SubRegClasses[] = {\n ";
+
+ for (unsigned idx = 0; idx != NumSubRegIndices; ++idx) {
+ if (idx)
+ OS << ", ";
+ if (SRC[idx])
+ OS << "&" << getQualifiedName(SRC[idx]) << "RegClass";
+ else
+ OS << "0";
+ }
+ OS << "\n };\n\n";
+ }
+
+ // Emit the super-register classes for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RegisterClasses[rc];
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.TheDef->getName();
+
+ OS << " // " << Name
+ << " Super-register Classes...\n"
+ << " static const TargetRegisterClass* const "
+ << Name << "SuperRegClasses[] = {\n ";
+
+ bool Empty = true;
+ std::map<unsigned, std::set<unsigned> >::iterator I =
+ SuperRegClassMap.find(rc);
+ if (I != SuperRegClassMap.end()) {
+ for (std::set<unsigned>::iterator II = I->second.begin(),
+ EE = I->second.end(); II != EE; ++II) {
+ const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
+ if (!Empty)
+ OS << ", ";
+ OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
+ Empty = false;
+ }
+ }
+
+ OS << (!Empty ? ", " : "") << "NULL";
+ OS << "\n };\n\n";
+ }
+ } else {
+ // No subregindices in this target
+ OS << " static const TargetRegisterClass* const "
+ << "NullRegClasses[] = { NULL };\n\n";
+ }
+
+ // Emit the sub-classes array for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RegisterClasses[rc];
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.TheDef->getName();
+
+ OS << " // " << Name
+ << " Register Class sub-classes...\n"
+ << " static const TargetRegisterClass* const "
+ << Name << "Subclasses[] = {\n ";
+
+ bool Empty = true;
+ for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
+ const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
+
+ // Sub-classes are used to determine if a virtual register can be used
+ // as an instruction operand, or if it must be copied first.
+ if (rc == rc2 || !RC.hasSubClass(&RC2)) continue;
+
+ if (!Empty) OS << ", ";
+ OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
+ Empty = false;
+
+ std::map<unsigned, std::set<unsigned> >::iterator SCMI =
+ SuperClassMap.find(rc2);
+ if (SCMI == SuperClassMap.end()) {
+ SuperClassMap.insert(std::make_pair(rc2, std::set<unsigned>()));
+ SCMI = SuperClassMap.find(rc2);
+ }
+ SCMI->second.insert(rc);
+ }
+
+ OS << (!Empty ? ", " : "") << "NULL";
+ OS << "\n };\n\n";
+ }
+
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RegisterClasses[rc];
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.TheDef->getName();
+
+ OS << " // " << Name
+ << " Register Class super-classes...\n"
+ << " static const TargetRegisterClass* const "
+ << Name << "Superclasses[] = {\n ";
+
+ bool Empty = true;
+ std::map<unsigned, std::set<unsigned> >::iterator I =
+ SuperClassMap.find(rc);
+ if (I != SuperClassMap.end()) {
+ for (std::set<unsigned>::iterator II = I->second.begin(),
+ EE = I->second.end(); II != EE; ++II) {
+ const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
+ if (!Empty) OS << ", ";
+ OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
+ Empty = false;
+ }
+ }
+
+ OS << (!Empty ? ", " : "") << "NULL";
+ OS << "\n };\n\n";
+ }
+
+
+ for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
+ const CodeGenRegisterClass &RC = RegisterClasses[i];
+ OS << RC.MethodBodies << "\n";
+ OS << RC.getName() << "Class::" << RC.getName()
+ << "Class() : TargetRegisterClass("
+ << RC.getName() + "RegClassID" << ", "
+ << '\"' << RC.getName() << "\", "
+ << RC.getName() + "VTs" << ", "
+ << RC.getName() + "Subclasses" << ", "
+ << RC.getName() + "Superclasses" << ", "
+ << (NumSubRegIndices ? RC.getName() + "Sub" : std::string("Null"))
+ << "RegClasses, "
+ << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null"))
+ << "RegClasses, "
+ << RC.SpillSize/8 << ", "
+ << RC.SpillAlignment/8 << ", "
+ << RC.CopyCost << ", "
+ << RC.getName() << ", " << RC.getName() << " + " << RC.Elements.size()
+ << ") {}\n";
+ }
+
+ OS << "}\n";
+ }
+
+ OS << "\nnamespace {\n";
+ OS << " const TargetRegisterClass* const RegisterClasses[] = {\n";
+ for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
+ OS << " &" << getQualifiedName(RegisterClasses[i].TheDef)
+ << "RegClass,\n";
+ OS << " };\n";
+
+ // Emit register sub-registers / super-registers, aliases...
+ std::map<Record*, std::set<Record*>, LessRecord> RegisterSubRegs;
+ std::map<Record*, std::set<Record*>, LessRecord> RegisterSuperRegs;
+ std::map<Record*, std::set<Record*>, LessRecord> RegisterAliases;
+ typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
+ DwarfRegNumsMapTy DwarfRegNums;
+
+ const std::vector<CodeGenRegister> &Regs = Target.getRegisters();
+
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record *R = Regs[i].TheDef;
+ std::vector<Record*> LI = Regs[i].TheDef->getValueAsListOfDefs("Aliases");
+ // Add information that R aliases all of the elements in the list... and
+ // that everything in the list aliases R.
+ for (unsigned j = 0, e = LI.size(); j != e; ++j) {
+ Record *Reg = LI[j];
+ if (RegisterAliases[R].count(Reg))
+ errs() << "Warning: register alias between " << getQualifiedName(R)
+ << " and " << getQualifiedName(Reg)
+ << " specified multiple times!\n";
+ RegisterAliases[R].insert(Reg);
+
+ if (RegisterAliases[Reg].count(R))
+ errs() << "Warning: register alias between " << getQualifiedName(R)
+ << " and " << getQualifiedName(Reg)
+ << " specified multiple times!\n";
+ RegisterAliases[Reg].insert(R);
+ }
+ }
+
+ // Process sub-register sets.
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record *R = Regs[i].TheDef;
+ std::vector<Record*> LI = Regs[i].TheDef->getValueAsListOfDefs("SubRegs");
+ // Process sub-register set and add aliases information.
+ for (unsigned j = 0, e = LI.size(); j != e; ++j) {
+ Record *SubReg = LI[j];
+ if (RegisterSubRegs[R].count(SubReg))
+ errs() << "Warning: register " << getQualifiedName(SubReg)
+ << " specified as a sub-register of " << getQualifiedName(R)
+ << " multiple times!\n";
+ addSubSuperReg(R, SubReg, RegisterSubRegs, RegisterSuperRegs,
+ RegisterAliases);
+ }
+ }
+
+ // Print the SubregHashTable, a simple quadratically probed
+ // hash table for determining if a register is a subregister
+ // of another register.
+ unsigned NumSubRegs = 0;
+ std::map<Record*, unsigned> RegNo;
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ RegNo[Regs[i].TheDef] = i;
+ NumSubRegs += RegisterSubRegs[Regs[i].TheDef].size();
+ }
+
+ unsigned SubregHashTableSize = 2 * NextPowerOf2(2 * NumSubRegs);
+ unsigned* SubregHashTable = new unsigned[2 * SubregHashTableSize];
+ std::fill(SubregHashTable, SubregHashTable + 2 * SubregHashTableSize, ~0U);
+
+ unsigned hashMisses = 0;
+
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record* R = Regs[i].TheDef;
+ for (std::set<Record*>::iterator I = RegisterSubRegs[R].begin(),
+ E = RegisterSubRegs[R].end(); I != E; ++I) {
+ Record* RJ = *I;
+ // We have to increase the indices of both registers by one when
+ // computing the hash because, in the generated code, there
+ // will be an extra empty slot at register 0.
+ size_t index = ((i+1) + (RegNo[RJ]+1) * 37) & (SubregHashTableSize-1);
+ unsigned ProbeAmt = 2;
+ while (SubregHashTable[index*2] != ~0U &&
+ SubregHashTable[index*2+1] != ~0U) {
+ index = (index + ProbeAmt) & (SubregHashTableSize-1);
+ ProbeAmt += 2;
+
+ hashMisses++;
+ }
+
+ SubregHashTable[index*2] = i;
+ SubregHashTable[index*2+1] = RegNo[RJ];
+ }
+ }
+
+ OS << "\n\n // Number of hash collisions: " << hashMisses << "\n";
+
+ if (SubregHashTableSize) {
+ std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace");
+
+ OS << " const unsigned SubregHashTable[] = { ";
+ for (unsigned i = 0; i < SubregHashTableSize - 1; ++i) {
+ if (i != 0)
+ // Insert spaces for nice formatting.
+ OS << " ";
+
+ if (SubregHashTable[2*i] != ~0U) {
+ OS << getQualifiedName(Regs[SubregHashTable[2*i]].TheDef) << ", "
+ << getQualifiedName(Regs[SubregHashTable[2*i+1]].TheDef) << ", \n";
+ } else {
+ OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n";
+ }
+ }
+
+ unsigned Idx = SubregHashTableSize*2-2;
+ if (SubregHashTable[Idx] != ~0U) {
+ OS << " "
+ << getQualifiedName(Regs[SubregHashTable[Idx]].TheDef) << ", "
+ << getQualifiedName(Regs[SubregHashTable[Idx+1]].TheDef) << " };\n";
+ } else {
+ OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n";
+ }
+
+ OS << " const unsigned SubregHashTableSize = "
+ << SubregHashTableSize << ";\n";
+ } else {
+ OS << " const unsigned SubregHashTable[] = { ~0U, ~0U };\n"
+ << " const unsigned SubregHashTableSize = 1;\n";
+ }
+
+ delete [] SubregHashTable;
+
+
+ // Print the AliasHashTable, a simple quadratically probed
+ // hash table for determining if a register aliases another register.
+ unsigned NumAliases = 0;
+ RegNo.clear();
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ RegNo[Regs[i].TheDef] = i;
+ NumAliases += RegisterAliases[Regs[i].TheDef].size();
+ }
+
+ unsigned AliasesHashTableSize = 2 * NextPowerOf2(2 * NumAliases);
+ unsigned* AliasesHashTable = new unsigned[2 * AliasesHashTableSize];
+ std::fill(AliasesHashTable, AliasesHashTable + 2 * AliasesHashTableSize, ~0U);
+
+ hashMisses = 0;
+
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record* R = Regs[i].TheDef;
+ for (std::set<Record*>::iterator I = RegisterAliases[R].begin(),
+ E = RegisterAliases[R].end(); I != E; ++I) {
+ Record* RJ = *I;
+ // We have to increase the indices of both registers by one when
+ // computing the hash because, in the generated code, there
+ // will be an extra empty slot at register 0.
+ size_t index = ((i+1) + (RegNo[RJ]+1) * 37) & (AliasesHashTableSize-1);
+ unsigned ProbeAmt = 2;
+ while (AliasesHashTable[index*2] != ~0U &&
+ AliasesHashTable[index*2+1] != ~0U) {
+ index = (index + ProbeAmt) & (AliasesHashTableSize-1);
+ ProbeAmt += 2;
+
+ hashMisses++;
+ }
+
+ AliasesHashTable[index*2] = i;
+ AliasesHashTable[index*2+1] = RegNo[RJ];
+ }
+ }
+
+ OS << "\n\n // Number of hash collisions: " << hashMisses << "\n";
+
+ if (AliasesHashTableSize) {
+ std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace");
+
+ OS << " const unsigned AliasesHashTable[] = { ";
+ for (unsigned i = 0; i < AliasesHashTableSize - 1; ++i) {
+ if (i != 0)
+ // Insert spaces for nice formatting.
+ OS << " ";
+
+ if (AliasesHashTable[2*i] != ~0U) {
+ OS << getQualifiedName(Regs[AliasesHashTable[2*i]].TheDef) << ", "
+ << getQualifiedName(Regs[AliasesHashTable[2*i+1]].TheDef) << ", \n";
+ } else {
+ OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n";
+ }
+ }
+
+ unsigned Idx = AliasesHashTableSize*2-2;
+ if (AliasesHashTable[Idx] != ~0U) {
+ OS << " "
+ << getQualifiedName(Regs[AliasesHashTable[Idx]].TheDef) << ", "
+ << getQualifiedName(Regs[AliasesHashTable[Idx+1]].TheDef) << " };\n";
+ } else {
+ OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n";
+ }
+
+ OS << " const unsigned AliasesHashTableSize = "
+ << AliasesHashTableSize << ";\n";
+ } else {
+ OS << " const unsigned AliasesHashTable[] = { ~0U, ~0U };\n"
+ << " const unsigned AliasesHashTableSize = 1;\n";
+ }
+
+ delete [] AliasesHashTable;
+
+ if (!RegisterAliases.empty())
+ OS << "\n\n // Register Alias Sets...\n";
+
+ // Emit the empty alias list
+ OS << " const unsigned Empty_AliasSet[] = { 0 };\n";
+ // Loop over all of the registers which have aliases, emitting the alias list
+ // to memory.
+ for (std::map<Record*, std::set<Record*>, LessRecord >::iterator
+ I = RegisterAliases.begin(), E = RegisterAliases.end(); I != E; ++I) {
+ if (I->second.empty())
+ continue;
+ OS << " const unsigned " << I->first->getName() << "_AliasSet[] = { ";
+ for (std::set<Record*>::iterator ASI = I->second.begin(),
+ E = I->second.end(); ASI != E; ++ASI)
+ OS << getQualifiedName(*ASI) << ", ";
+ OS << "0 };\n";
+ }
+
+ if (!RegisterSubRegs.empty())
+ OS << "\n\n // Register Sub-registers Sets...\n";
+
+ // Emit the empty sub-registers list
+ OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n";
+ // Loop over all of the registers which have sub-registers, emitting the
+ // sub-registers list to memory.
+ for (std::map<Record*, std::set<Record*>, LessRecord>::iterator
+ I = RegisterSubRegs.begin(), E = RegisterSubRegs.end(); I != E; ++I) {
+ if (I->second.empty())
+ continue;
+ OS << " const unsigned " << I->first->getName() << "_SubRegsSet[] = { ";
+ std::vector<Record*> SubRegsVector;
+ for (std::set<Record*>::iterator ASI = I->second.begin(),
+ E = I->second.end(); ASI != E; ++ASI)
+ SubRegsVector.push_back(*ASI);
+ RegisterSorter RS(RegisterSubRegs);
+ std::stable_sort(SubRegsVector.begin(), SubRegsVector.end(), RS);
+ for (unsigned i = 0, e = SubRegsVector.size(); i != e; ++i)
+ OS << getQualifiedName(SubRegsVector[i]) << ", ";
+ OS << "0 };\n";
+ }
+
+ if (!RegisterSuperRegs.empty())
+ OS << "\n\n // Register Super-registers Sets...\n";
+
+ // Emit the empty super-registers list
+ OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n";
+ // Loop over all of the registers which have super-registers, emitting the
+ // super-registers list to memory.
+ for (std::map<Record*, std::set<Record*>, LessRecord >::iterator
+ I = RegisterSuperRegs.begin(), E = RegisterSuperRegs.end(); I != E; ++I) {
+ if (I->second.empty())
+ continue;
+ OS << " const unsigned " << I->first->getName() << "_SuperRegsSet[] = { ";
+
+ std::vector<Record*> SuperRegsVector;
+ for (std::set<Record*>::iterator ASI = I->second.begin(),
+ E = I->second.end(); ASI != E; ++ASI)
+ SuperRegsVector.push_back(*ASI);
+ RegisterSorter RS(RegisterSubRegs);
+ std::stable_sort(SuperRegsVector.begin(), SuperRegsVector.end(), RS);
+ for (unsigned i = 0, e = SuperRegsVector.size(); i != e; ++i)
+ OS << getQualifiedName(SuperRegsVector[i]) << ", ";
+ OS << "0 };\n";
+ }
+
+ OS<<"\n const TargetRegisterDesc RegisterDescriptors[] = { // Descriptors\n";
+ OS << " { \"NOREG\",\t0,\t0,\t0 },\n";
+
+ // Now that register alias and sub-registers sets have been emitted, emit the
+ // register descriptors now.
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ const CodeGenRegister &Reg = Regs[i];
+ OS << " { \"";
+ OS << Reg.getName() << "\",\t";
+ if (!RegisterAliases[Reg.TheDef].empty())
+ OS << Reg.getName() << "_AliasSet,\t";
+ else
+ OS << "Empty_AliasSet,\t";
+ if (!RegisterSubRegs[Reg.TheDef].empty())
+ OS << Reg.getName() << "_SubRegsSet,\t";
+ else
+ OS << "Empty_SubRegsSet,\t";
+ if (!RegisterSuperRegs[Reg.TheDef].empty())
+ OS << Reg.getName() << "_SuperRegsSet },\n";
+ else
+ OS << "Empty_SuperRegsSet },\n";
+ }
+ OS << " };\n"; // End of register descriptors...
+
+ // Emit SubRegIndex names, skipping 0
+ const std::vector<Record*> SubRegIndices = Target.getSubRegIndices();
+ OS << "\n const char *const SubRegIndexTable[] = { \"";
+ for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
+ OS << SubRegIndices[i]->getName();
+ if (i+1 != e)
+ OS << "\", \"";
+ }
+ OS << "\" };\n\n";
+ OS << "}\n\n"; // End of anonymous namespace...
+
+ std::string ClassName = Target.getName() + "GenRegisterInfo";
+
+ // Calculate the mapping of subregister+index pairs to physical registers.
+ RegisterMaps RegMaps;
+
+ // Emit the subregister + index mapping function based on the information
+ // calculated above.
+ OS << "unsigned " << ClassName
+ << "::getSubReg(unsigned RegNo, unsigned Index) const {\n"
+ << " switch (RegNo) {\n"
+ << " default:\n return 0;\n";
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ RegisterMaps::SubRegMap &SRM = RegMaps.inferSubRegIndices(Regs[i].TheDef);
+ if (SRM.empty())
+ continue;
+ OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n";
+ OS << " switch (Index) {\n";
+ OS << " default: return 0;\n";
+ for (RegisterMaps::SubRegMap::const_iterator ii = SRM.begin(),
+ ie = SRM.end(); ii != ie; ++ii)
+ OS << " case " << getQualifiedName(ii->first)
+ << ": return " << getQualifiedName(ii->second) << ";\n";
+ OS << " };\n" << " break;\n";
+ }
+ OS << " };\n";
+ OS << " return 0;\n";
+ OS << "}\n\n";
+
+ OS << "unsigned " << ClassName
+ << "::getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const {\n"
+ << " switch (RegNo) {\n"
+ << " default:\n return 0;\n";
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ RegisterMaps::SubRegMap &SRM = RegMaps.SubReg[Regs[i].TheDef];
+ if (SRM.empty())
+ continue;
+ OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n";
+ for (RegisterMaps::SubRegMap::const_iterator ii = SRM.begin(),
+ ie = SRM.end(); ii != ie; ++ii)
+ OS << " if (SubRegNo == " << getQualifiedName(ii->second)
+ << ") return " << getQualifiedName(ii->first) << ";\n";
+ OS << " return 0;\n";
+ }
+ OS << " };\n";
+ OS << " return 0;\n";
+ OS << "}\n\n";
+
+ // Emit composeSubRegIndices
+ RegMaps.computeComposites();
+ OS << "unsigned " << ClassName
+ << "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n"
+ << " switch (IdxA) {\n"
+ << " default:\n return IdxB;\n";
+ for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
+ bool Open = false;
+ for (unsigned j = 0; j != e; ++j) {
+ if (Record *Comp = RegMaps.Composite.lookup(
+ std::make_pair(SubRegIndices[i], SubRegIndices[j]))) {
+ if (!Open) {
+ OS << " case " << getQualifiedName(SubRegIndices[i])
+ << ": switch(IdxB) {\n default: return IdxB;\n";
+ Open = true;
+ }
+ OS << " case " << getQualifiedName(SubRegIndices[j])
+ << ": return " << getQualifiedName(Comp) << ";\n";
+ }
+ }
+ if (Open)
+ OS << " }\n";
+ }
+ OS << " }\n}\n\n";
+
+ // Emit the constructor of the class...
+ OS << ClassName << "::" << ClassName
+ << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n"
+ << " : TargetRegisterInfo(RegisterDescriptors, " << Regs.size()+1
+ << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
+ << " SubRegIndexTable,\n"
+ << " CallFrameSetupOpcode, CallFrameDestroyOpcode,\n"
+ << " SubregHashTable, SubregHashTableSize,\n"
+ << " AliasesHashTable, AliasesHashTableSize) {\n"
+ << "}\n\n";
+
+ // Collect all information about dwarf register numbers
+
+ // First, just pull all provided information to the map
+ unsigned maxLength = 0;
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record *Reg = Regs[i].TheDef;
+ std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
+ maxLength = std::max((size_t)maxLength, RegNums.size());
+ if (DwarfRegNums.count(Reg))
+ errs() << "Warning: DWARF numbers for register " << getQualifiedName(Reg)
+ << "specified multiple times\n";
+ DwarfRegNums[Reg] = RegNums;
+ }
+
+ // Now we know maximal length of number list. Append -1's, where needed
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I)
+ for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
+ I->second.push_back(-1);
+
+ // Emit information about the dwarf register numbers.
+ OS << "int " << ClassName << "::getDwarfRegNumFull(unsigned RegNum, "
+ << "unsigned Flavour) const {\n"
+ << " switch (Flavour) {\n"
+ << " default:\n"
+ << " assert(0 && \"Unknown DWARF flavour\");\n"
+ << " return -1;\n";
+
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << " case " << i << ":\n"
+ << " switch (RegNum) {\n"
+ << " default:\n"
+ << " assert(0 && \"Invalid RegNum\");\n"
+ << " return -1;\n";
+
+ // Sort by name to get a stable order.
+
+
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
+ int RegNo = I->second[i];
+ if (RegNo != -2)
+ OS << " case " << getQualifiedName(I->first) << ":\n"
+ << " return " << RegNo << ";\n";
+ else
+ OS << " case " << getQualifiedName(I->first) << ":\n"
+ << " assert(0 && \"Invalid register for this mode\");\n"
+ << " return -1;\n";
+ }
+ OS << " };\n";
+ }
+
+ OS << " };\n}\n\n";
+
+ OS << "} // End llvm namespace \n";
+}
diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h
new file mode 100644
index 0000000..1456b4f
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h
@@ -0,0 +1,40 @@
+//===- RegisterInfoEmitter.h - Generate a Register File Desc. ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of a target
+// register file for a code generator. It uses instances of the Register,
+// RegisterAliases, and RegisterClass classes to gather this information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef REGISTER_INFO_EMITTER_H
+#define REGISTER_INFO_EMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+
+class RegisterInfoEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ RegisterInfoEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the register file description, returning true on failure.
+ void run(raw_ostream &o);
+
+ // runHeader - Emit a header fragment for the register info emitter.
+ void runHeader(raw_ostream &o);
+
+ // runEnums - Print out enum values for all of the registers.
+ void runEnums(raw_ostream &o);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/StringToOffsetTable.h b/contrib/llvm/utils/TableGen/StringToOffsetTable.h
new file mode 100644
index 0000000..ac9422c
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/StringToOffsetTable.h
@@ -0,0 +1,81 @@
+//===- StringToOffsetTable.h - Emit a big concatenated string ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TBLGEN_STRING_TO_OFFSET_TABLE_H
+#define TBLGEN_STRING_TO_OFFSET_TABLE_H
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+/// StringToOffsetTable - This class uniques a bunch of nul-terminated strings
+/// and keeps track of their offset in a massive contiguous string allocation.
+/// It can then output this string blob and use indexes into the string to
+/// reference each piece.
+class StringToOffsetTable {
+ StringMap<unsigned> StringOffset;
+ std::string AggregateString;
+public:
+
+ unsigned GetOrAddStringOffset(StringRef Str) {
+ unsigned &Entry = StringOffset[Str];
+ if (Entry == 0) {
+ // Add the string to the aggregate if this is the first time found.
+ Entry = AggregateString.size();
+ AggregateString.append(Str.begin(), Str.end());
+ AggregateString += '\0';
+ }
+
+ return Entry;
+ }
+
+ void EmitString(raw_ostream &O) {
+ // Escape the string.
+ SmallString<256> Str;
+ raw_svector_ostream(Str).write_escaped(AggregateString);
+ AggregateString = Str.str();
+
+ O << " \"";
+ unsigned CharsPrinted = 0;
+ for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) {
+ if (CharsPrinted > 70) {
+ O << "\"\n \"";
+ CharsPrinted = 0;
+ }
+ O << AggregateString[i];
+ ++CharsPrinted;
+
+ // Print escape sequences all together.
+ if (AggregateString[i] != '\\')
+ continue;
+
+ assert(i+1 < AggregateString.size() && "Incomplete escape sequence!");
+ if (isdigit(AggregateString[i+1])) {
+ assert(isdigit(AggregateString[i+2]) &&
+ isdigit(AggregateString[i+3]) &&
+ "Expected 3 digit octal escape!");
+ O << AggregateString[++i];
+ O << AggregateString[++i];
+ O << AggregateString[++i];
+ CharsPrinted += 3;
+ } else {
+ O << AggregateString[++i];
+ ++CharsPrinted;
+ }
+ }
+ O << "\"";
+ }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
new file mode 100644
index 0000000..b04eaf8
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -0,0 +1,605 @@
+//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits subtarget enumerations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SubtargetEmitter.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Debug.h"
+#include <algorithm>
+using namespace llvm;
+
+//
+// Enumeration - Emit the specified class as an enumeration.
+//
+void SubtargetEmitter::Enumeration(raw_ostream &OS,
+ const char *ClassName,
+ bool isBits) {
+ // Get all records of class and sort
+ std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
+ std::sort(DefList.begin(), DefList.end(), LessRecord());
+
+ // Open enumeration
+ OS << "enum {\n";
+
+ // For each record
+ for (unsigned i = 0, N = DefList.size(); i < N;) {
+ // Next record
+ Record *Def = DefList[i];
+
+ // Get and emit name
+ OS << " " << Def->getName();
+
+ // If bit flags then emit expression (1 << i)
+ if (isBits) OS << " = " << " 1 << " << i;
+
+ // Depending on 'if more in the list' emit comma
+ if (++i < N) OS << ",";
+
+ OS << "\n";
+ }
+
+ // Close enumeration
+ OS << "};\n";
+}
+
+//
+// FeatureKeyValues - Emit data of all the subtarget features. Used by the
+// command line.
+//
+void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
+ // Gather and sort all the features
+ std::vector<Record*> FeatureList =
+ Records.getAllDerivedDefinitions("SubtargetFeature");
+ std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
+
+ // Begin feature table
+ OS << "// Sorted (by key) array of values for CPU features.\n"
+ << "static const llvm::SubtargetFeatureKV FeatureKV[] = {\n";
+
+ // For each feature
+ for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
+ // Next feature
+ Record *Feature = FeatureList[i];
+
+ const std::string &Name = Feature->getName();
+ const std::string &CommandLineName = Feature->getValueAsString("Name");
+ const std::string &Desc = Feature->getValueAsString("Desc");
+
+ if (CommandLineName.empty()) continue;
+
+ // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
+ OS << " { "
+ << "\"" << CommandLineName << "\", "
+ << "\"" << Desc << "\", "
+ << Name << ", ";
+
+ const std::vector<Record*> &ImpliesList =
+ Feature->getValueAsListOfDefs("Implies");
+
+ if (ImpliesList.empty()) {
+ OS << "0";
+ } else {
+ for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
+ OS << ImpliesList[j]->getName();
+ if (++j < M) OS << " | ";
+ }
+ }
+
+ OS << " }";
+
+ // Depending on 'if more in the list' emit comma
+ if ((i + 1) < N) OS << ",";
+
+ OS << "\n";
+ }
+
+ // End feature table
+ OS << "};\n";
+
+ // Emit size of table
+ OS<<"\nenum {\n";
+ OS<<" FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n";
+ OS<<"};\n";
+}
+
+//
+// CPUKeyValues - Emit data of all the subtarget processors. Used by command
+// line.
+//
+void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
+ // Gather and sort processor information
+ std::vector<Record*> ProcessorList =
+ Records.getAllDerivedDefinitions("Processor");
+ std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
+
+ // Begin processor table
+ OS << "// Sorted (by key) array of values for CPU subtype.\n"
+ << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n";
+
+ // For each processor
+ for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
+ // Next processor
+ Record *Processor = ProcessorList[i];
+
+ const std::string &Name = Processor->getValueAsString("Name");
+ const std::vector<Record*> &FeatureList =
+ Processor->getValueAsListOfDefs("Features");
+
+ // Emit as { "cpu", "description", f1 | f2 | ... fn },
+ OS << " { "
+ << "\"" << Name << "\", "
+ << "\"Select the " << Name << " processor\", ";
+
+ if (FeatureList.empty()) {
+ OS << "0";
+ } else {
+ for (unsigned j = 0, M = FeatureList.size(); j < M;) {
+ OS << FeatureList[j]->getName();
+ if (++j < M) OS << " | ";
+ }
+ }
+
+ // The "0" is for the "implies" section of this data structure.
+ OS << ", 0 }";
+
+ // Depending on 'if more in the list' emit comma
+ if (++i < N) OS << ",";
+
+ OS << "\n";
+ }
+
+ // End processor table
+ OS << "};\n";
+
+ // Emit size of table
+ OS<<"\nenum {\n";
+ OS<<" SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n";
+ OS<<"};\n";
+}
+
+//
+// CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
+// Returns itinerary class count.
+//
+unsigned SubtargetEmitter::CollectAllItinClasses(raw_ostream &OS,
+ std::map<std::string, unsigned> &ItinClassesMap) {
+ // Gather and sort all itinerary classes
+ std::vector<Record*> ItinClassList =
+ Records.getAllDerivedDefinitions("InstrItinClass");
+ std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord());
+
+ // For each itinerary class
+ unsigned N = ItinClassList.size();
+ for (unsigned i = 0; i < N; i++) {
+ // Next itinerary class
+ const Record *ItinClass = ItinClassList[i];
+ // Get name of itinerary class
+ // Assign itinerary class a unique number
+ ItinClassesMap[ItinClass->getName()] = i;
+ }
+
+ // Emit size of table
+ OS<<"\nenum {\n";
+ OS<<" ItinClassesSize = " << N << "\n";
+ OS<<"};\n";
+
+ // Return itinerary class count
+ return N;
+}
+
+//
+// FormItineraryStageString - Compose a string containing the stage
+// data initialization for the specified itinerary. N is the number
+// of stages.
+//
+void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
+ Record *ItinData,
+ std::string &ItinString,
+ unsigned &NStages) {
+ // Get states list
+ const std::vector<Record*> &StageList =
+ ItinData->getValueAsListOfDefs("Stages");
+
+ // For each stage
+ unsigned N = NStages = StageList.size();
+ for (unsigned i = 0; i < N;) {
+ // Next stage
+ const Record *Stage = StageList[i];
+
+ // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
+ int Cycles = Stage->getValueAsInt("Cycles");
+ ItinString += " { " + itostr(Cycles) + ", ";
+
+ // Get unit list
+ const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
+
+ // For each unit
+ for (unsigned j = 0, M = UnitList.size(); j < M;) {
+ // Add name and bitwise or
+ ItinString += Name + "FU::" + UnitList[j]->getName();
+ if (++j < M) ItinString += " | ";
+ }
+
+ int TimeInc = Stage->getValueAsInt("TimeInc");
+ ItinString += ", " + itostr(TimeInc);
+
+ int Kind = Stage->getValueAsInt("Kind");
+ ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
+
+ // Close off stage
+ ItinString += " }";
+ if (++i < N) ItinString += ", ";
+ }
+}
+
+//
+// FormItineraryOperandCycleString - Compose a string containing the
+// operand cycle initialization for the specified itinerary. N is the
+// number of operands that has cycles specified.
+//
+void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
+ std::string &ItinString, unsigned &NOperandCycles) {
+ // Get operand cycle list
+ const std::vector<int64_t> &OperandCycleList =
+ ItinData->getValueAsListOfInts("OperandCycles");
+
+ // For each operand cycle
+ unsigned N = NOperandCycles = OperandCycleList.size();
+ for (unsigned i = 0; i < N;) {
+ // Next operand cycle
+ const int OCycle = OperandCycleList[i];
+
+ ItinString += " " + itostr(OCycle);
+ if (++i < N) ItinString += ", ";
+ }
+}
+
+//
+// EmitStageAndOperandCycleData - Generate unique itinerary stages and
+// operand cycle tables. Record itineraries for processors.
+//
+void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
+ unsigned NItinClasses,
+ std::map<std::string, unsigned> &ItinClassesMap,
+ std::vector<std::vector<InstrItinerary> > &ProcList) {
+ // Gather processor iteraries
+ std::vector<Record*> ProcItinList =
+ Records.getAllDerivedDefinitions("ProcessorItineraries");
+
+ // If just no itinerary then don't bother
+ if (ProcItinList.size() < 2) return;
+
+ // Emit functional units for all the itineraries.
+ for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) {
+ // Next record
+ Record *Proc = ProcItinList[i];
+
+ std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU");
+ if (FUs.empty())
+ continue;
+
+ const std::string &Name = Proc->getName();
+ OS << "\n// Functional units for itineraries \"" << Name << "\"\n"
+ << "namespace " << Name << "FU {\n";
+
+ for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
+ OS << " const unsigned " << FUs[j]->getName()
+ << " = 1 << " << j << ";\n";
+
+ OS << "}\n";
+ }
+
+ // Begin stages table
+ std::string StageTable = "\nstatic const llvm::InstrStage Stages[] = {\n";
+ StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
+
+ // Begin operand cycle table
+ std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n";
+ OperandCycleTable += " 0, // No itinerary\n";
+
+ unsigned StageCount = 1, OperandCycleCount = 1;
+ unsigned ItinStageEnum = 1, ItinOperandCycleEnum = 1;
+ std::map<std::string, unsigned> ItinStageMap, ItinOperandCycleMap;
+ for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
+ // Next record
+ Record *Proc = ProcItinList[i];
+
+ // Get processor itinerary name
+ const std::string &Name = Proc->getName();
+
+ // Skip default
+ if (Name == "NoItineraries") continue;
+
+ // Create and expand processor itinerary to cover all itinerary classes
+ std::vector<InstrItinerary> ItinList;
+ ItinList.resize(NItinClasses);
+
+ // Get itinerary data list
+ std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
+
+ // For each itinerary data
+ for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) {
+ // Next itinerary data
+ Record *ItinData = ItinDataList[j];
+
+ // Get string and stage count
+ std::string ItinStageString;
+ unsigned NStages;
+ FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
+
+ // Get string and operand cycle count
+ std::string ItinOperandCycleString;
+ unsigned NOperandCycles;
+ FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
+ NOperandCycles);
+
+ // Check to see if stage already exists and create if it doesn't
+ unsigned FindStage = 0;
+ if (NStages > 0) {
+ FindStage = ItinStageMap[ItinStageString];
+ if (FindStage == 0) {
+ // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index
+ StageTable += ItinStageString + ", // " + itostr(ItinStageEnum) + "\n";
+ // Record Itin class number.
+ ItinStageMap[ItinStageString] = FindStage = StageCount;
+ StageCount += NStages;
+ ItinStageEnum++;
+ }
+ }
+
+ // Check to see if operand cycle already exists and create if it doesn't
+ unsigned FindOperandCycle = 0;
+ if (NOperandCycles > 0) {
+ FindOperandCycle = ItinOperandCycleMap[ItinOperandCycleString];
+ if (FindOperandCycle == 0) {
+ // Emit as cycle, // index
+ OperandCycleTable += ItinOperandCycleString + ", // " +
+ itostr(ItinOperandCycleEnum) + "\n";
+ // Record Itin class number.
+ ItinOperandCycleMap[ItinOperandCycleString] =
+ FindOperandCycle = OperandCycleCount;
+ OperandCycleCount += NOperandCycles;
+ ItinOperandCycleEnum++;
+ }
+ }
+
+ // Set up itinerary as location and location + stage count
+ InstrItinerary Intinerary = { FindStage, FindStage + NStages,
+ FindOperandCycle, FindOperandCycle + NOperandCycles};
+
+ // Locate where to inject into processor itinerary table
+ const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
+ unsigned Find = ItinClassesMap[Name];
+
+ // Inject - empty slots will be 0, 0
+ ItinList[Find] = Intinerary;
+ }
+
+ // Add process itinerary to list
+ ProcList.push_back(ItinList);
+ }
+
+ // Closing stage
+ StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n";
+ StageTable += "};\n";
+
+ // Closing operand cycles
+ OperandCycleTable += " 0 // End itinerary\n";
+ OperandCycleTable += "};\n";
+
+ // Emit tables.
+ OS << StageTable;
+ OS << OperandCycleTable;
+
+ // Emit size of tables
+ OS<<"\nenum {\n";
+ OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n";
+ OS<<" OperandCyclesSize = sizeof(OperandCycles)/sizeof(unsigned)\n";
+ OS<<"};\n";
+}
+
+//
+// EmitProcessorData - Generate data for processor itineraries.
+//
+void SubtargetEmitter::EmitProcessorData(raw_ostream &OS,
+ std::vector<std::vector<InstrItinerary> > &ProcList) {
+ // Get an iterator for processor itinerary stages
+ std::vector<std::vector<InstrItinerary> >::iterator
+ ProcListIter = ProcList.begin();
+
+ // For each processor itinerary
+ std::vector<Record*> Itins =
+ Records.getAllDerivedDefinitions("ProcessorItineraries");
+ for (unsigned i = 0, N = Itins.size(); i < N; i++) {
+ // Next record
+ Record *Itin = Itins[i];
+
+ // Get processor itinerary name
+ const std::string &Name = Itin->getName();
+
+ // Skip default
+ if (Name == "NoItineraries") continue;
+
+ // Begin processor itinerary table
+ OS << "\n";
+ OS << "static const llvm::InstrItinerary " << Name << "[] = {\n";
+
+ // For each itinerary class
+ std::vector<InstrItinerary> &ItinList = *ProcListIter++;
+ for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
+ InstrItinerary &Intinerary = ItinList[j];
+
+ // Emit in the form of
+ // { firstStage, lastStage, firstCycle, lastCycle } // index
+ if (Intinerary.FirstStage == 0) {
+ OS << " { 0, 0, 0, 0 }";
+ } else {
+ OS << " { " << Intinerary.FirstStage << ", " <<
+ Intinerary.LastStage << ", " <<
+ Intinerary.FirstOperandCycle << ", " <<
+ Intinerary.LastOperandCycle << " }";
+ }
+
+ OS << ", // " << j << "\n";
+ }
+
+ // End processor itinerary table
+ OS << " { ~0U, ~0U, ~0U, ~0U } // end marker\n";
+ OS << "};\n";
+ }
+}
+
+//
+// EmitProcessorLookup - generate cpu name to itinerary lookup table.
+//
+void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
+ // Gather and sort processor information
+ std::vector<Record*> ProcessorList =
+ Records.getAllDerivedDefinitions("Processor");
+ std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
+
+ // Begin processor table
+ OS << "\n";
+ OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
+ << "static const llvm::SubtargetInfoKV ProcItinKV[] = {\n";
+
+ // For each processor
+ for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
+ // Next processor
+ Record *Processor = ProcessorList[i];
+
+ const std::string &Name = Processor->getValueAsString("Name");
+ const std::string &ProcItin =
+ Processor->getValueAsDef("ProcItin")->getName();
+
+ // Emit as { "cpu", procinit },
+ OS << " { "
+ << "\"" << Name << "\", "
+ << "(void *)&" << ProcItin;
+
+ OS << " }";
+
+ // Depending on ''if more in the list'' emit comma
+ if (++i < N) OS << ",";
+
+ OS << "\n";
+ }
+
+ // End processor table
+ OS << "};\n";
+
+ // Emit size of table
+ OS<<"\nenum {\n";
+ OS<<" ProcItinKVSize = sizeof(ProcItinKV)/"
+ "sizeof(llvm::SubtargetInfoKV)\n";
+ OS<<"};\n";
+}
+
+//
+// EmitData - Emits all stages and itineries, folding common patterns.
+//
+void SubtargetEmitter::EmitData(raw_ostream &OS) {
+ std::map<std::string, unsigned> ItinClassesMap;
+ std::vector<std::vector<InstrItinerary> > ProcList;
+
+ // Enumerate all the itinerary classes
+ unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap);
+ // Make sure the rest is worth the effort
+ HasItineraries = NItinClasses != 1; // Ignore NoItinerary.
+
+ if (HasItineraries) {
+ // Emit the stage data
+ EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, ProcList);
+ // Emit the processor itinerary data
+ EmitProcessorData(OS, ProcList);
+ // Emit the processor lookup data
+ EmitProcessorLookup(OS);
+ }
+}
+
+//
+// ParseFeaturesFunction - Produces a subtarget specific function for parsing
+// the subtarget features string.
+//
+void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) {
+ std::vector<Record*> Features =
+ Records.getAllDerivedDefinitions("SubtargetFeature");
+ std::sort(Features.begin(), Features.end(), LessRecord());
+
+ OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
+ << "// subtarget options.\n"
+ << "std::string llvm::";
+ OS << Target;
+ OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n"
+ << " const std::string &CPU) {\n"
+ << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
+ << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n"
+ << " SubtargetFeatures Features(FS);\n"
+ << " Features.setCPUIfNone(CPU);\n"
+ << " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n"
+ << " FeatureKV, FeatureKVSize);\n";
+
+ for (unsigned i = 0; i < Features.size(); i++) {
+ // Next record
+ Record *R = Features[i];
+ const std::string &Instance = R->getName();
+ const std::string &Value = R->getValueAsString("Value");
+ const std::string &Attribute = R->getValueAsString("Attribute");
+
+ if (Value=="true" || Value=="false")
+ OS << " if ((Bits & " << Instance << ") != 0) "
+ << Attribute << " = " << Value << ";\n";
+ else
+ OS << " if ((Bits & " << Instance << ") != 0 && " << Attribute <<
+ " < " << Value << ") " << Attribute << " = " << Value << ";\n";
+ }
+
+ if (HasItineraries) {
+ OS << "\n"
+ << " InstrItinerary *Itinerary = (InstrItinerary *)"
+ << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
+ << " InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n";
+ }
+
+ OS << " return Features.getCPU();\n"
+ << "}\n";
+}
+
+//
+// SubtargetEmitter::run - Main subtarget enumeration emitter.
+//
+void SubtargetEmitter::run(raw_ostream &OS) {
+ Target = CodeGenTarget().getName();
+
+ EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
+
+ OS << "#include \"llvm/Support/Debug.h\"\n";
+ OS << "#include \"llvm/Support/raw_ostream.h\"\n";
+ OS << "#include \"llvm/Target/SubtargetFeature.h\"\n";
+ OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n";
+
+// Enumeration(OS, "FuncUnit", true);
+// OS<<"\n";
+// Enumeration(OS, "InstrItinClass", false);
+// OS<<"\n";
+ Enumeration(OS, "SubtargetFeature", true);
+ OS<<"\n";
+ FeatureKeyValues(OS);
+ OS<<"\n";
+ CPUKeyValues(OS);
+ OS<<"\n";
+ EmitData(OS);
+ OS<<"\n";
+ ParseFeaturesFunction(OS);
+}
diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.h b/contrib/llvm/utils/TableGen/SubtargetEmitter.h
new file mode 100644
index 0000000..f43a443
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.h
@@ -0,0 +1,65 @@
+//===- SubtargetEmitter.h - Generate subtarget enumerations -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits subtarget enumerations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SUBTARGET_EMITTER_H
+#define SUBTARGET_EMITTER_H
+
+#include "TableGenBackend.h"
+#include "llvm/Target/TargetInstrItineraries.h"
+#include <vector>
+#include <map>
+#include <string>
+
+
+namespace llvm {
+
+class SubtargetEmitter : public TableGenBackend {
+
+ RecordKeeper &Records;
+ std::string Target;
+ bool HasItineraries;
+
+ void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
+ void FeatureKeyValues(raw_ostream &OS);
+ void CPUKeyValues(raw_ostream &OS);
+ unsigned CollectAllItinClasses(raw_ostream &OS,
+ std::map<std::string, unsigned> &ItinClassesMap);
+ void FormItineraryStageString(const std::string &Names,
+ Record *ItinData, std::string &ItinString,
+ unsigned &NStages);
+ void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
+ unsigned &NOperandCycles);
+ void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses,
+ std::map<std::string, unsigned> &ItinClassesMap,
+ std::vector<std::vector<InstrItinerary> > &ProcList);
+ void EmitProcessorData(raw_ostream &OS,
+ std::vector<std::vector<InstrItinerary> > &ProcList);
+ void EmitProcessorLookup(raw_ostream &OS);
+ void EmitData(raw_ostream &OS);
+ void ParseFeaturesFunction(raw_ostream &OS);
+
+public:
+ SubtargetEmitter(RecordKeeper &R) : Records(R), HasItineraries(false) {}
+
+ // run - Output the subtarget enumerations, returning true on failure.
+ void run(raw_ostream &o);
+
+};
+
+
+} // End llvm namespace
+
+#endif
+
+
+
diff --git a/contrib/llvm/utils/TableGen/TGLexer.cpp b/contrib/llvm/utils/TableGen/TGLexer.cpp
new file mode 100644
index 0000000..2c7becc
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/TGLexer.cpp
@@ -0,0 +1,450 @@
+//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implement the Lexer for TableGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TGLexer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Config/config.h"
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+using namespace llvm;
+
+TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
+ CurBuffer = 0;
+ CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
+ CurPtr = CurBuf->getBufferStart();
+ TokStart = 0;
+}
+
+SMLoc TGLexer::getLoc() const {
+ return SMLoc::getFromPointer(TokStart);
+}
+
+
+/// ReturnError - Set the error to the specified string at the specified
+/// location. This is defined to always return tgtok::Error.
+tgtok::TokKind TGLexer::ReturnError(const char *Loc, const std::string &Msg) {
+ PrintError(Loc, Msg);
+ return tgtok::Error;
+}
+
+
+void TGLexer::PrintError(const char *Loc, const std::string &Msg) const {
+ SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error");
+}
+
+void TGLexer::PrintError(SMLoc Loc, const std::string &Msg) const {
+ SrcMgr.PrintMessage(Loc, Msg, "error");
+}
+
+
+int TGLexer::getNextChar() {
+ char CurChar = *CurPtr++;
+ switch (CurChar) {
+ default:
+ return (unsigned char)CurChar;
+ case 0: {
+ // A nul character in the stream is either the end of the current buffer or
+ // a random nul in the file. Disambiguate that here.
+ if (CurPtr-1 != CurBuf->getBufferEnd())
+ return 0; // Just whitespace.
+
+ // If this is the end of an included file, pop the parent file off the
+ // include stack.
+ SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
+ if (ParentIncludeLoc != SMLoc()) {
+ CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
+ CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
+ CurPtr = ParentIncludeLoc.getPointer();
+ return getNextChar();
+ }
+
+ // Otherwise, return end of file.
+ --CurPtr; // Another call to lex will return EOF again.
+ return EOF;
+ }
+ case '\n':
+ case '\r':
+ // Handle the newline character by ignoring it and incrementing the line
+ // count. However, be careful about 'dos style' files with \n\r in them.
+ // Only treat a \n\r or \r\n as a single line.
+ if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
+ *CurPtr != CurChar)
+ ++CurPtr; // Eat the two char newline sequence.
+ return '\n';
+ }
+}
+
+tgtok::TokKind TGLexer::LexToken() {
+ TokStart = CurPtr;
+ // This always consumes at least one character.
+ int CurChar = getNextChar();
+
+ switch (CurChar) {
+ default:
+ // Handle letters: [a-zA-Z_]
+ if (isalpha(CurChar) || CurChar == '_' || CurChar == '#')
+ return LexIdentifier();
+
+ // Unknown character, emit an error.
+ return ReturnError(TokStart, "Unexpected character");
+ case EOF: return tgtok::Eof;
+ case ':': return tgtok::colon;
+ case ';': return tgtok::semi;
+ case '.': return tgtok::period;
+ case ',': return tgtok::comma;
+ case '<': return tgtok::less;
+ case '>': return tgtok::greater;
+ case ']': return tgtok::r_square;
+ case '{': return tgtok::l_brace;
+ case '}': return tgtok::r_brace;
+ case '(': return tgtok::l_paren;
+ case ')': return tgtok::r_paren;
+ case '=': return tgtok::equal;
+ case '?': return tgtok::question;
+
+ case 0:
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ // Ignore whitespace.
+ return LexToken();
+ case '/':
+ // If this is the start of a // comment, skip until the end of the line or
+ // the end of the buffer.
+ if (*CurPtr == '/')
+ SkipBCPLComment();
+ else if (*CurPtr == '*') {
+ if (SkipCComment())
+ return tgtok::Error;
+ } else // Otherwise, this is an error.
+ return ReturnError(TokStart, "Unexpected character");
+ return LexToken();
+ case '-': case '+':
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ return LexNumber();
+ case '"': return LexString();
+ case '$': return LexVarName();
+ case '[': return LexBracket();
+ case '!': return LexExclaim();
+ }
+}
+
+/// LexString - Lex "[^"]*"
+tgtok::TokKind TGLexer::LexString() {
+ const char *StrStart = CurPtr;
+
+ CurStrVal = "";
+
+ while (*CurPtr != '"') {
+ // If we hit the end of the buffer, report an error.
+ if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd())
+ return ReturnError(StrStart, "End of file in string literal");
+
+ if (*CurPtr == '\n' || *CurPtr == '\r')
+ return ReturnError(StrStart, "End of line in string literal");
+
+ if (*CurPtr != '\\') {
+ CurStrVal += *CurPtr++;
+ continue;
+ }
+
+ ++CurPtr;
+
+ switch (*CurPtr) {
+ case '\\': case '\'': case '"':
+ // These turn into their literal character.
+ CurStrVal += *CurPtr++;
+ break;
+ case 't':
+ CurStrVal += '\t';
+ ++CurPtr;
+ break;
+ case 'n':
+ CurStrVal += '\n';
+ ++CurPtr;
+ break;
+
+ case '\n':
+ case '\r':
+ return ReturnError(CurPtr, "escaped newlines not supported in tblgen");
+
+ // If we hit the end of the buffer, report an error.
+ case '\0':
+ if (CurPtr == CurBuf->getBufferEnd())
+ return ReturnError(StrStart, "End of file in string literal");
+ // FALL THROUGH
+ default:
+ return ReturnError(CurPtr, "invalid escape in string literal");
+ }
+ }
+
+ ++CurPtr;
+ return tgtok::StrVal;
+}
+
+tgtok::TokKind TGLexer::LexVarName() {
+ if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
+ return ReturnError(TokStart, "Invalid variable name");
+
+ // Otherwise, we're ok, consume the rest of the characters.
+ const char *VarNameStart = CurPtr++;
+
+ while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
+ ++CurPtr;
+
+ CurStrVal.assign(VarNameStart, CurPtr);
+ return tgtok::VarName;
+}
+
+
+tgtok::TokKind TGLexer::LexIdentifier() {
+ // The first letter is [a-zA-Z_].
+ const char *IdentStart = TokStart;
+
+ // Match the rest of the identifier regex: [0-9a-zA-Z_]*
+ while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_'
+ || *CurPtr == '#') {
+ // If this contains a '#', make sure it's value
+ if (*CurPtr == '#') {
+ if (strncmp(CurPtr, "#NAME#", 6) != 0) {
+ return tgtok::Error;
+ }
+ CurPtr += 6;
+ }
+ else {
+ ++CurPtr;
+ }
+ }
+
+
+ // Check to see if this identifier is a keyword.
+ unsigned Len = CurPtr-IdentStart;
+
+ if (Len == 3 && !memcmp(IdentStart, "int", 3)) return tgtok::Int;
+ if (Len == 3 && !memcmp(IdentStart, "bit", 3)) return tgtok::Bit;
+ if (Len == 4 && !memcmp(IdentStart, "bits", 4)) return tgtok::Bits;
+ if (Len == 6 && !memcmp(IdentStart, "string", 6)) return tgtok::String;
+ if (Len == 4 && !memcmp(IdentStart, "list", 4)) return tgtok::List;
+ if (Len == 4 && !memcmp(IdentStart, "code", 4)) return tgtok::Code;
+ if (Len == 3 && !memcmp(IdentStart, "dag", 3)) return tgtok::Dag;
+
+ if (Len == 5 && !memcmp(IdentStart, "class", 5)) return tgtok::Class;
+ if (Len == 3 && !memcmp(IdentStart, "def", 3)) return tgtok::Def;
+ if (Len == 4 && !memcmp(IdentStart, "defm", 4)) return tgtok::Defm;
+ if (Len == 10 && !memcmp(IdentStart, "multiclass", 10))
+ return tgtok::MultiClass;
+ if (Len == 5 && !memcmp(IdentStart, "field", 5)) return tgtok::Field;
+ if (Len == 3 && !memcmp(IdentStart, "let", 3)) return tgtok::Let;
+ if (Len == 2 && !memcmp(IdentStart, "in", 2)) return tgtok::In;
+
+ if (Len == 7 && !memcmp(IdentStart, "include", 7)) {
+ if (LexInclude()) return tgtok::Error;
+ return Lex();
+ }
+
+ CurStrVal.assign(IdentStart, CurPtr);
+ return tgtok::Id;
+}
+
+/// LexInclude - We just read the "include" token. Get the string token that
+/// comes next and enter the include.
+bool TGLexer::LexInclude() {
+ // The token after the include must be a string.
+ tgtok::TokKind Tok = LexToken();
+ if (Tok == tgtok::Error) return true;
+ if (Tok != tgtok::StrVal) {
+ PrintError(getLoc(), "Expected filename after include");
+ return true;
+ }
+
+ // Get the string.
+ std::string Filename = CurStrVal;
+
+
+ CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr));
+ if (CurBuffer == -1) {
+ PrintError(getLoc(), "Could not find include file '" + Filename + "'");
+ return true;
+ }
+
+ // Save the line number and lex buffer of the includer.
+ CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
+ CurPtr = CurBuf->getBufferStart();
+ return false;
+}
+
+void TGLexer::SkipBCPLComment() {
+ ++CurPtr; // skip the second slash.
+ while (1) {
+ switch (*CurPtr) {
+ case '\n':
+ case '\r':
+ return; // Newline is end of comment.
+ case 0:
+ // If this is the end of the buffer, end the comment.
+ if (CurPtr == CurBuf->getBufferEnd())
+ return;
+ break;
+ }
+ // Otherwise, skip the character.
+ ++CurPtr;
+ }
+}
+
+/// SkipCComment - This skips C-style /**/ comments. The only difference from C
+/// is that we allow nesting.
+bool TGLexer::SkipCComment() {
+ ++CurPtr; // skip the star.
+ unsigned CommentDepth = 1;
+
+ while (1) {
+ int CurChar = getNextChar();
+ switch (CurChar) {
+ case EOF:
+ PrintError(TokStart, "Unterminated comment!");
+ return true;
+ case '*':
+ // End of the comment?
+ if (CurPtr[0] != '/') break;
+
+ ++CurPtr; // End the */.
+ if (--CommentDepth == 0)
+ return false;
+ break;
+ case '/':
+ // Start of a nested comment?
+ if (CurPtr[0] != '*') break;
+ ++CurPtr;
+ ++CommentDepth;
+ break;
+ }
+ }
+}
+
+/// LexNumber - Lex:
+/// [-+]?[0-9]+
+/// 0x[0-9a-fA-F]+
+/// 0b[01]+
+tgtok::TokKind TGLexer::LexNumber() {
+ if (CurPtr[-1] == '0') {
+ if (CurPtr[0] == 'x') {
+ ++CurPtr;
+ const char *NumStart = CurPtr;
+ while (isxdigit(CurPtr[0]))
+ ++CurPtr;
+
+ // Requires at least one hex digit.
+ if (CurPtr == NumStart)
+ return ReturnError(TokStart, "Invalid hexadecimal number");
+
+ errno = 0;
+ CurIntVal = strtoll(NumStart, 0, 16);
+ if (errno == EINVAL)
+ return ReturnError(TokStart, "Invalid hexadecimal number");
+ if (errno == ERANGE) {
+ errno = 0;
+ CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
+ if (errno == EINVAL)
+ return ReturnError(TokStart, "Invalid hexadecimal number");
+ if (errno == ERANGE)
+ return ReturnError(TokStart, "Hexadecimal number out of range");
+ }
+ return tgtok::IntVal;
+ } else if (CurPtr[0] == 'b') {
+ ++CurPtr;
+ const char *NumStart = CurPtr;
+ while (CurPtr[0] == '0' || CurPtr[0] == '1')
+ ++CurPtr;
+
+ // Requires at least one binary digit.
+ if (CurPtr == NumStart)
+ return ReturnError(CurPtr-2, "Invalid binary number");
+ CurIntVal = strtoll(NumStart, 0, 2);
+ return tgtok::IntVal;
+ }
+ }
+
+ // Check for a sign without a digit.
+ if (!isdigit(CurPtr[0])) {
+ if (CurPtr[-1] == '-')
+ return tgtok::minus;
+ else if (CurPtr[-1] == '+')
+ return tgtok::plus;
+ }
+
+ while (isdigit(CurPtr[0]))
+ ++CurPtr;
+ CurIntVal = strtoll(TokStart, 0, 10);
+ return tgtok::IntVal;
+}
+
+/// LexBracket - We just read '['. If this is a code block, return it,
+/// otherwise return the bracket. Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
+tgtok::TokKind TGLexer::LexBracket() {
+ if (CurPtr[0] != '{')
+ return tgtok::l_square;
+ ++CurPtr;
+ const char *CodeStart = CurPtr;
+ while (1) {
+ int Char = getNextChar();
+ if (Char == EOF) break;
+
+ if (Char != '}') continue;
+
+ Char = getNextChar();
+ if (Char == EOF) break;
+ if (Char == ']') {
+ CurStrVal.assign(CodeStart, CurPtr-2);
+ return tgtok::CodeFragment;
+ }
+ }
+
+ return ReturnError(CodeStart-2, "Unterminated Code Block");
+}
+
+/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
+tgtok::TokKind TGLexer::LexExclaim() {
+ if (!isalpha(*CurPtr))
+ return ReturnError(CurPtr-1, "Invalid \"!operator\"");
+
+ const char *Start = CurPtr++;
+ while (isalpha(*CurPtr))
+ ++CurPtr;
+
+ // Check to see which operator this is.
+ unsigned Len = CurPtr-Start;
+
+ if (Len == 3 && !memcmp(Start, "con", 3)) return tgtok::XConcat;
+ if (Len == 3 && !memcmp(Start, "sra", 3)) return tgtok::XSRA;
+ if (Len == 3 && !memcmp(Start, "srl", 3)) return tgtok::XSRL;
+ if (Len == 3 && !memcmp(Start, "shl", 3)) return tgtok::XSHL;
+ if (Len == 2 && !memcmp(Start, "eq", 2)) return tgtok::XEq;
+ if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat;
+ if (Len == 10 && !memcmp(Start, "nameconcat", 10)) return tgtok::XNameConcat;
+ if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst;
+ if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
+ if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast;
+ if (Len == 3 && !memcmp(Start, "car", 3)) return tgtok::XCar;
+ if (Len == 3 && !memcmp(Start, "cdr", 3)) return tgtok::XCdr;
+ if (Len == 4 && !memcmp(Start, "null", 4)) return tgtok::XNull;
+ if (Len == 2 && !memcmp(Start, "if", 2)) return tgtok::XIf;
+
+ return ReturnError(Start-1, "Unknown operator");
+}
+
diff --git a/contrib/llvm/utils/TableGen/TGLexer.h b/contrib/llvm/utils/TableGen/TGLexer.h
new file mode 100644
index 0000000..835f351
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/TGLexer.h
@@ -0,0 +1,121 @@
+//===- TGLexer.h - Lexer for TableGen Files ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class represents the Lexer for tablegen files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TGLEXER_H
+#define TGLEXER_H
+
+#include "llvm/System/DataTypes.h"
+#include <vector>
+#include <string>
+#include <cassert>
+
+namespace llvm {
+class MemoryBuffer;
+class SourceMgr;
+class SMLoc;
+
+namespace tgtok {
+ enum TokKind {
+ // Markers
+ Eof, Error,
+
+ // Tokens with no info.
+ minus, plus, // - +
+ l_square, r_square, // [ ]
+ l_brace, r_brace, // { }
+ l_paren, r_paren, // ( )
+ less, greater, // < >
+ colon, semi, // ; :
+ comma, period, // , .
+ equal, question, // = ?
+
+ // Keywords.
+ Bit, Bits, Class, Code, Dag, Def, Defm, Field, In, Int, Let, List,
+ MultiClass, String,
+
+ // !keywords.
+ XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst,
+ XForEach, XCar, XCdr, XNull, XIf, XEq,
+
+ // Integer value.
+ IntVal,
+
+ // String valued tokens.
+ Id, StrVal, VarName, CodeFragment
+ };
+}
+
+/// TGLexer - TableGen Lexer class.
+class TGLexer {
+ SourceMgr &SrcMgr;
+
+ const char *CurPtr;
+ const MemoryBuffer *CurBuf;
+
+ // Information about the current token.
+ const char *TokStart;
+ tgtok::TokKind CurCode;
+ std::string CurStrVal; // This is valid for ID, STRVAL, VARNAME, CODEFRAGMENT
+ int64_t CurIntVal; // This is valid for INTVAL.
+
+ /// CurBuffer - This is the current buffer index we're lexing from as managed
+ /// by the SourceMgr object.
+ int CurBuffer;
+
+public:
+ TGLexer(SourceMgr &SrcMgr);
+ ~TGLexer() {}
+
+ tgtok::TokKind Lex() {
+ return CurCode = LexToken();
+ }
+
+ tgtok::TokKind getCode() const { return CurCode; }
+
+ const std::string &getCurStrVal() const {
+ assert((CurCode == tgtok::Id || CurCode == tgtok::StrVal ||
+ CurCode == tgtok::VarName || CurCode == tgtok::CodeFragment) &&
+ "This token doesn't have a string value");
+ return CurStrVal;
+ }
+ int64_t getCurIntVal() const {
+ assert(CurCode == tgtok::IntVal && "This token isn't an integer");
+ return CurIntVal;
+ }
+
+ SMLoc getLoc() const;
+
+ void PrintError(const char *Loc, const std::string &Msg) const;
+ void PrintError(SMLoc Loc, const std::string &Msg) const;
+
+private:
+ /// LexToken - Read the next token and return its code.
+ tgtok::TokKind LexToken();
+
+ tgtok::TokKind ReturnError(const char *Loc, const std::string &Msg);
+
+ int getNextChar();
+ void SkipBCPLComment();
+ bool SkipCComment();
+ tgtok::TokKind LexIdentifier();
+ bool LexInclude();
+ tgtok::TokKind LexString();
+ tgtok::TokKind LexVarName();
+ tgtok::TokKind LexNumber();
+ tgtok::TokKind LexBracket();
+ tgtok::TokKind LexExclaim();
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/TGParser.cpp b/contrib/llvm/utils/TableGen/TGParser.cpp
new file mode 100644
index 0000000..f81aabe
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/TGParser.cpp
@@ -0,0 +1,2123 @@
+//===- TGParser.cpp - Parser for TableGen Files ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implement the Parser for TableGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TGParser.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include <algorithm>
+#include <sstream>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Support Code for the Semantic Actions.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+struct SubClassReference {
+ SMLoc RefLoc;
+ Record *Rec;
+ std::vector<Init*> TemplateArgs;
+ SubClassReference() : Rec(0) {}
+
+ bool isInvalid() const { return Rec == 0; }
+};
+
+struct SubMultiClassReference {
+ SMLoc RefLoc;
+ MultiClass *MC;
+ std::vector<Init*> TemplateArgs;
+ SubMultiClassReference() : MC(0) {}
+
+ bool isInvalid() const { return MC == 0; }
+ void dump() const;
+};
+
+void SubMultiClassReference::dump() const {
+ errs() << "Multiclass:\n";
+
+ MC->dump();
+
+ errs() << "Template args:\n";
+ for (std::vector<Init *>::const_iterator i = TemplateArgs.begin(),
+ iend = TemplateArgs.end();
+ i != iend;
+ ++i) {
+ (*i)->dump();
+ }
+}
+
+} // end namespace llvm
+
+bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) {
+ if (CurRec == 0)
+ CurRec = &CurMultiClass->Rec;
+
+ if (RecordVal *ERV = CurRec->getValue(RV.getName())) {
+ // The value already exists in the class, treat this as a set.
+ if (ERV->setValue(RV.getValue()))
+ return Error(Loc, "New definition of '" + RV.getName() + "' of type '" +
+ RV.getType()->getAsString() + "' is incompatible with " +
+ "previous definition of type '" +
+ ERV->getType()->getAsString() + "'");
+ } else {
+ CurRec->addValue(RV);
+ }
+ return false;
+}
+
+/// SetValue -
+/// Return true on error, false on success.
+bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName,
+ const std::vector<unsigned> &BitList, Init *V) {
+ if (!V) return false;
+
+ if (CurRec == 0) CurRec = &CurMultiClass->Rec;
+
+ RecordVal *RV = CurRec->getValue(ValName);
+ if (RV == 0)
+ return Error(Loc, "Value '" + ValName + "' unknown!");
+
+ // Do not allow assignments like 'X = X'. This will just cause infinite loops
+ // in the resolution machinery.
+ if (BitList.empty())
+ if (VarInit *VI = dynamic_cast<VarInit*>(V))
+ if (VI->getName() == ValName)
+ return false;
+
+ // If we are assigning to a subset of the bits in the value... then we must be
+ // assigning to a field of BitsRecTy, which must have a BitsInit
+ // initializer.
+ //
+ if (!BitList.empty()) {
+ BitsInit *CurVal = dynamic_cast<BitsInit*>(RV->getValue());
+ if (CurVal == 0)
+ return Error(Loc, "Value '" + ValName + "' is not a bits type");
+
+ // Convert the incoming value to a bits type of the appropriate size...
+ Init *BI = V->convertInitializerTo(new BitsRecTy(BitList.size()));
+ if (BI == 0) {
+ V->convertInitializerTo(new BitsRecTy(BitList.size()));
+ return Error(Loc, "Initializer is not compatible with bit range");
+ }
+
+ // We should have a BitsInit type now.
+ BitsInit *BInit = dynamic_cast<BitsInit*>(BI);
+ assert(BInit != 0);
+
+ BitsInit *NewVal = new BitsInit(CurVal->getNumBits());
+
+ // Loop over bits, assigning values as appropriate.
+ for (unsigned i = 0, e = BitList.size(); i != e; ++i) {
+ unsigned Bit = BitList[i];
+ if (NewVal->getBit(Bit))
+ return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" +
+ ValName + "' more than once");
+ NewVal->setBit(Bit, BInit->getBit(i));
+ }
+
+ for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)
+ if (NewVal->getBit(i) == 0)
+ NewVal->setBit(i, CurVal->getBit(i));
+
+ V = NewVal;
+ }
+
+ if (RV->setValue(V))
+ return Error(Loc, "Value '" + ValName + "' of type '" +
+ RV->getType()->getAsString() +
+ "' is incompatible with initializer '" + V->getAsString() +"'");
+ return false;
+}
+
+/// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template
+/// args as SubClass's template arguments.
+bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
+ Record *SC = SubClass.Rec;
+ // Add all of the values in the subclass into the current class.
+ const std::vector<RecordVal> &Vals = SC->getValues();
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (AddValue(CurRec, SubClass.RefLoc, Vals[i]))
+ return true;
+
+ const std::vector<std::string> &TArgs = SC->getTemplateArgs();
+
+ // Ensure that an appropriate number of template arguments are specified.
+ if (TArgs.size() < SubClass.TemplateArgs.size())
+ return Error(SubClass.RefLoc, "More template args specified than expected");
+
+ // Loop over all of the template arguments, setting them to the specified
+ // value or leaving them as the default if necessary.
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ if (i < SubClass.TemplateArgs.size()) {
+ // If a value is specified for this template arg, set it now.
+ if (SetValue(CurRec, SubClass.RefLoc, TArgs[i], std::vector<unsigned>(),
+ SubClass.TemplateArgs[i]))
+ return true;
+
+ // Resolve it next.
+ CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
+
+ // Now remove it.
+ CurRec->removeValue(TArgs[i]);
+
+ } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
+ return Error(SubClass.RefLoc,"Value not specified for template argument #"
+ + utostr(i) + " (" + TArgs[i] + ") of subclass '" +
+ SC->getName() + "'!");
+ }
+ }
+
+ // Since everything went well, we can now set the "superclass" list for the
+ // current record.
+ const std::vector<Record*> &SCs = SC->getSuperClasses();
+ for (unsigned i = 0, e = SCs.size(); i != e; ++i) {
+ if (CurRec->isSubClassOf(SCs[i]))
+ return Error(SubClass.RefLoc,
+ "Already subclass of '" + SCs[i]->getName() + "'!\n");
+ CurRec->addSuperClass(SCs[i]);
+ }
+
+ if (CurRec->isSubClassOf(SC))
+ return Error(SubClass.RefLoc,
+ "Already subclass of '" + SC->getName() + "'!\n");
+ CurRec->addSuperClass(SC);
+ return false;
+}
+
+/// AddSubMultiClass - Add SubMultiClass as a subclass to
+/// CurMC, resolving its template args as SubMultiClass's
+/// template arguments.
+bool TGParser::AddSubMultiClass(MultiClass *CurMC,
+ SubMultiClassReference &SubMultiClass) {
+ MultiClass *SMC = SubMultiClass.MC;
+ Record *CurRec = &CurMC->Rec;
+
+ const std::vector<RecordVal> &MCVals = CurRec->getValues();
+
+ // Add all of the values in the subclass into the current class.
+ const std::vector<RecordVal> &SMCVals = SMC->Rec.getValues();
+ for (unsigned i = 0, e = SMCVals.size(); i != e; ++i)
+ if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i]))
+ return true;
+
+ int newDefStart = CurMC->DefPrototypes.size();
+
+ // Add all of the defs in the subclass into the current multiclass.
+ for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(),
+ iend = SMC->DefPrototypes.end();
+ i != iend;
+ ++i) {
+ // Clone the def and add it to the current multiclass
+ Record *NewDef = new Record(**i);
+
+ // Add all of the values in the superclass into the current def.
+ for (unsigned i = 0, e = MCVals.size(); i != e; ++i)
+ if (AddValue(NewDef, SubMultiClass.RefLoc, MCVals[i]))
+ return true;
+
+ CurMC->DefPrototypes.push_back(NewDef);
+ }
+
+ const std::vector<std::string> &SMCTArgs = SMC->Rec.getTemplateArgs();
+
+ // Ensure that an appropriate number of template arguments are
+ // specified.
+ if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size())
+ return Error(SubMultiClass.RefLoc,
+ "More template args specified than expected");
+
+ // Loop over all of the template arguments, setting them to the specified
+ // value or leaving them as the default if necessary.
+ for (unsigned i = 0, e = SMCTArgs.size(); i != e; ++i) {
+ if (i < SubMultiClass.TemplateArgs.size()) {
+ // If a value is specified for this template arg, set it in the
+ // superclass now.
+ if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i],
+ std::vector<unsigned>(),
+ SubMultiClass.TemplateArgs[i]))
+ return true;
+
+ // Resolve it next.
+ CurRec->resolveReferencesTo(CurRec->getValue(SMCTArgs[i]));
+
+ // Now remove it.
+ CurRec->removeValue(SMCTArgs[i]);
+
+ // If a value is specified for this template arg, set it in the
+ // new defs now.
+ for (MultiClass::RecordVector::iterator j =
+ CurMC->DefPrototypes.begin() + newDefStart,
+ jend = CurMC->DefPrototypes.end();
+ j != jend;
+ ++j) {
+ Record *Def = *j;
+
+ if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i],
+ std::vector<unsigned>(),
+ SubMultiClass.TemplateArgs[i]))
+ return true;
+
+ // Resolve it next.
+ Def->resolveReferencesTo(Def->getValue(SMCTArgs[i]));
+
+ // Now remove it
+ Def->removeValue(SMCTArgs[i]);
+ }
+ } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) {
+ return Error(SubMultiClass.RefLoc,
+ "Value not specified for template argument #"
+ + utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" +
+ SMC->Rec.getName() + "'!");
+ }
+ }
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Parser Code
+//===----------------------------------------------------------------------===//
+
+/// isObjectStart - Return true if this is a valid first token for an Object.
+static bool isObjectStart(tgtok::TokKind K) {
+ return K == tgtok::Class || K == tgtok::Def ||
+ K == tgtok::Defm || K == tgtok::Let || K == tgtok::MultiClass;
+}
+
+/// ParseObjectName - If an object name is specified, return it. Otherwise,
+/// return an anonymous name.
+/// ObjectName ::= ID
+/// ObjectName ::= /*empty*/
+///
+std::string TGParser::ParseObjectName() {
+ if (Lex.getCode() == tgtok::Id) {
+ std::string Ret = Lex.getCurStrVal();
+ Lex.Lex();
+ return Ret;
+ }
+
+ static unsigned AnonCounter = 0;
+ return "anonymous."+utostr(AnonCounter++);
+}
+
+
+/// ParseClassID - Parse and resolve a reference to a class name. This returns
+/// null on error.
+///
+/// ClassID ::= ID
+///
+Record *TGParser::ParseClassID() {
+ if (Lex.getCode() != tgtok::Id) {
+ TokError("expected name for ClassID");
+ return 0;
+ }
+
+ Record *Result = Records.getClass(Lex.getCurStrVal());
+ if (Result == 0)
+ TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
+
+ Lex.Lex();
+ return Result;
+}
+
+/// ParseMultiClassID - Parse and resolve a reference to a multiclass name.
+/// This returns null on error.
+///
+/// MultiClassID ::= ID
+///
+MultiClass *TGParser::ParseMultiClassID() {
+ if (Lex.getCode() != tgtok::Id) {
+ TokError("expected name for ClassID");
+ return 0;
+ }
+
+ MultiClass *Result = MultiClasses[Lex.getCurStrVal()];
+ if (Result == 0)
+ TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
+
+ Lex.Lex();
+ return Result;
+}
+
+Record *TGParser::ParseDefmID() {
+ if (Lex.getCode() != tgtok::Id) {
+ TokError("expected multiclass name");
+ return 0;
+ }
+
+ MultiClass *MC = MultiClasses[Lex.getCurStrVal()];
+ if (MC == 0) {
+ TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'");
+ return 0;
+ }
+
+ Lex.Lex();
+ return &MC->Rec;
+}
+
+
+/// ParseSubClassReference - Parse a reference to a subclass or to a templated
+/// subclass. This returns a SubClassRefTy with a null Record* on error.
+///
+/// SubClassRef ::= ClassID
+/// SubClassRef ::= ClassID '<' ValueList '>'
+///
+SubClassReference TGParser::
+ParseSubClassReference(Record *CurRec, bool isDefm) {
+ SubClassReference Result;
+ Result.RefLoc = Lex.getLoc();
+
+ if (isDefm)
+ Result.Rec = ParseDefmID();
+ else
+ Result.Rec = ParseClassID();
+ if (Result.Rec == 0) return Result;
+
+ // If there is no template arg list, we're done.
+ if (Lex.getCode() != tgtok::less)
+ return Result;
+ Lex.Lex(); // Eat the '<'
+
+ if (Lex.getCode() == tgtok::greater) {
+ TokError("subclass reference requires a non-empty list of template values");
+ Result.Rec = 0;
+ return Result;
+ }
+
+ Result.TemplateArgs = ParseValueList(CurRec, Result.Rec);
+ if (Result.TemplateArgs.empty()) {
+ Result.Rec = 0; // Error parsing value list.
+ return Result;
+ }
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' in template value list");
+ Result.Rec = 0;
+ return Result;
+ }
+ Lex.Lex();
+
+ return Result;
+}
+
+/// ParseSubMultiClassReference - Parse a reference to a subclass or to a
+/// templated submulticlass. This returns a SubMultiClassRefTy with a null
+/// Record* on error.
+///
+/// SubMultiClassRef ::= MultiClassID
+/// SubMultiClassRef ::= MultiClassID '<' ValueList '>'
+///
+SubMultiClassReference TGParser::
+ParseSubMultiClassReference(MultiClass *CurMC) {
+ SubMultiClassReference Result;
+ Result.RefLoc = Lex.getLoc();
+
+ Result.MC = ParseMultiClassID();
+ if (Result.MC == 0) return Result;
+
+ // If there is no template arg list, we're done.
+ if (Lex.getCode() != tgtok::less)
+ return Result;
+ Lex.Lex(); // Eat the '<'
+
+ if (Lex.getCode() == tgtok::greater) {
+ TokError("subclass reference requires a non-empty list of template values");
+ Result.MC = 0;
+ return Result;
+ }
+
+ Result.TemplateArgs = ParseValueList(&CurMC->Rec, &Result.MC->Rec);
+ if (Result.TemplateArgs.empty()) {
+ Result.MC = 0; // Error parsing value list.
+ return Result;
+ }
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' in template value list");
+ Result.MC = 0;
+ return Result;
+ }
+ Lex.Lex();
+
+ return Result;
+}
+
+/// ParseRangePiece - Parse a bit/value range.
+/// RangePiece ::= INTVAL
+/// RangePiece ::= INTVAL '-' INTVAL
+/// RangePiece ::= INTVAL INTVAL
+bool TGParser::ParseRangePiece(std::vector<unsigned> &Ranges) {
+ if (Lex.getCode() != tgtok::IntVal) {
+ TokError("expected integer or bitrange");
+ return true;
+ }
+ int64_t Start = Lex.getCurIntVal();
+ int64_t End;
+
+ if (Start < 0)
+ return TokError("invalid range, cannot be negative");
+
+ switch (Lex.Lex()) { // eat first character.
+ default:
+ Ranges.push_back(Start);
+ return false;
+ case tgtok::minus:
+ if (Lex.Lex() != tgtok::IntVal) {
+ TokError("expected integer value as end of range");
+ return true;
+ }
+ End = Lex.getCurIntVal();
+ break;
+ case tgtok::IntVal:
+ End = -Lex.getCurIntVal();
+ break;
+ }
+ if (End < 0)
+ return TokError("invalid range, cannot be negative");
+ Lex.Lex();
+
+ // Add to the range.
+ if (Start < End) {
+ for (; Start <= End; ++Start)
+ Ranges.push_back(Start);
+ } else {
+ for (; Start >= End; --Start)
+ Ranges.push_back(Start);
+ }
+ return false;
+}
+
+/// ParseRangeList - Parse a list of scalars and ranges into scalar values.
+///
+/// RangeList ::= RangePiece (',' RangePiece)*
+///
+std::vector<unsigned> TGParser::ParseRangeList() {
+ std::vector<unsigned> Result;
+
+ // Parse the first piece.
+ if (ParseRangePiece(Result))
+ return std::vector<unsigned>();
+ while (Lex.getCode() == tgtok::comma) {
+ Lex.Lex(); // Eat the comma.
+
+ // Parse the next range piece.
+ if (ParseRangePiece(Result))
+ return std::vector<unsigned>();
+ }
+ return Result;
+}
+
+/// ParseOptionalRangeList - Parse either a range list in <>'s or nothing.
+/// OptionalRangeList ::= '<' RangeList '>'
+/// OptionalRangeList ::= /*empty*/
+bool TGParser::ParseOptionalRangeList(std::vector<unsigned> &Ranges) {
+ if (Lex.getCode() != tgtok::less)
+ return false;
+
+ SMLoc StartLoc = Lex.getLoc();
+ Lex.Lex(); // eat the '<'
+
+ // Parse the range list.
+ Ranges = ParseRangeList();
+ if (Ranges.empty()) return true;
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' at end of range list");
+ return Error(StartLoc, "to match this '<'");
+ }
+ Lex.Lex(); // eat the '>'.
+ return false;
+}
+
+/// ParseOptionalBitList - Parse either a bit list in {}'s or nothing.
+/// OptionalBitList ::= '{' RangeList '}'
+/// OptionalBitList ::= /*empty*/
+bool TGParser::ParseOptionalBitList(std::vector<unsigned> &Ranges) {
+ if (Lex.getCode() != tgtok::l_brace)
+ return false;
+
+ SMLoc StartLoc = Lex.getLoc();
+ Lex.Lex(); // eat the '{'
+
+ // Parse the range list.
+ Ranges = ParseRangeList();
+ if (Ranges.empty()) return true;
+
+ if (Lex.getCode() != tgtok::r_brace) {
+ TokError("expected '}' at end of bit list");
+ return Error(StartLoc, "to match this '{'");
+ }
+ Lex.Lex(); // eat the '}'.
+ return false;
+}
+
+
+/// ParseType - Parse and return a tblgen type. This returns null on error.
+///
+/// Type ::= STRING // string type
+/// Type ::= BIT // bit type
+/// Type ::= BITS '<' INTVAL '>' // bits<x> type
+/// Type ::= INT // int type
+/// Type ::= LIST '<' Type '>' // list<x> type
+/// Type ::= CODE // code type
+/// Type ::= DAG // dag type
+/// Type ::= ClassID // Record Type
+///
+RecTy *TGParser::ParseType() {
+ switch (Lex.getCode()) {
+ default: TokError("Unknown token when expecting a type"); return 0;
+ case tgtok::String: Lex.Lex(); return new StringRecTy();
+ case tgtok::Bit: Lex.Lex(); return new BitRecTy();
+ case tgtok::Int: Lex.Lex(); return new IntRecTy();
+ case tgtok::Code: Lex.Lex(); return new CodeRecTy();
+ case tgtok::Dag: Lex.Lex(); return new DagRecTy();
+ case tgtok::Id:
+ if (Record *R = ParseClassID()) return new RecordRecTy(R);
+ return 0;
+ case tgtok::Bits: {
+ if (Lex.Lex() != tgtok::less) { // Eat 'bits'
+ TokError("expected '<' after bits type");
+ return 0;
+ }
+ if (Lex.Lex() != tgtok::IntVal) { // Eat '<'
+ TokError("expected integer in bits<n> type");
+ return 0;
+ }
+ uint64_t Val = Lex.getCurIntVal();
+ if (Lex.Lex() != tgtok::greater) { // Eat count.
+ TokError("expected '>' at end of bits<n> type");
+ return 0;
+ }
+ Lex.Lex(); // Eat '>'
+ return new BitsRecTy(Val);
+ }
+ case tgtok::List: {
+ if (Lex.Lex() != tgtok::less) { // Eat 'bits'
+ TokError("expected '<' after list type");
+ return 0;
+ }
+ Lex.Lex(); // Eat '<'
+ RecTy *SubType = ParseType();
+ if (SubType == 0) return 0;
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' at end of list<ty> type");
+ return 0;
+ }
+ Lex.Lex(); // Eat '>'
+ return new ListRecTy(SubType);
+ }
+ }
+}
+
+/// ParseIDValue - Parse an ID as a value and decode what it means.
+///
+/// IDValue ::= ID [def local value]
+/// IDValue ::= ID [def template arg]
+/// IDValue ::= ID [multiclass local value]
+/// IDValue ::= ID [multiclass template argument]
+/// IDValue ::= ID [def name]
+///
+Init *TGParser::ParseIDValue(Record *CurRec) {
+ assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue");
+ std::string Name = Lex.getCurStrVal();
+ SMLoc Loc = Lex.getLoc();
+ Lex.Lex();
+ return ParseIDValue(CurRec, Name, Loc);
+}
+
+/// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID
+/// has already been read.
+Init *TGParser::ParseIDValue(Record *CurRec,
+ const std::string &Name, SMLoc NameLoc) {
+ if (CurRec) {
+ if (const RecordVal *RV = CurRec->getValue(Name))
+ return new VarInit(Name, RV->getType());
+
+ std::string TemplateArgName = CurRec->getName()+":"+Name;
+ if (CurRec->isTemplateArg(TemplateArgName)) {
+ const RecordVal *RV = CurRec->getValue(TemplateArgName);
+ assert(RV && "Template arg doesn't exist??");
+ return new VarInit(TemplateArgName, RV->getType());
+ }
+ }
+
+ if (CurMultiClass) {
+ std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
+ if (CurMultiClass->Rec.isTemplateArg(MCName)) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
+ assert(RV && "Template arg doesn't exist??");
+ return new VarInit(MCName, RV->getType());
+ }
+ }
+
+ if (Record *D = Records.getDef(Name))
+ return new DefInit(D);
+
+ Error(NameLoc, "Variable not defined: '" + Name + "'");
+ return 0;
+}
+
+/// ParseOperation - Parse an operator. This returns null on error.
+///
+/// Operation ::= XOperator ['<' Type '>'] '(' Args ')'
+///
+Init *TGParser::ParseOperation(Record *CurRec) {
+ switch (Lex.getCode()) {
+ default:
+ TokError("unknown operation");
+ return 0;
+ break;
+ case tgtok::XCar:
+ case tgtok::XCdr:
+ case tgtok::XNull:
+ case tgtok::XCast: { // Value ::= !unop '(' Value ')'
+ UnOpInit::UnaryOp Code;
+ RecTy *Type = 0;
+
+ switch (Lex.getCode()) {
+ default: assert(0 && "Unhandled code!");
+ case tgtok::XCast:
+ Lex.Lex(); // eat the operation
+ Code = UnOpInit::CAST;
+
+ Type = ParseOperatorType();
+
+ if (Type == 0) {
+ TokError("did not get type for unary operator");
+ return 0;
+ }
+
+ break;
+ case tgtok::XCar:
+ Lex.Lex(); // eat the operation
+ Code = UnOpInit::CAR;
+ break;
+ case tgtok::XCdr:
+ Lex.Lex(); // eat the operation
+ Code = UnOpInit::CDR;
+ break;
+ case tgtok::XNull:
+ Lex.Lex(); // eat the operation
+ Code = UnOpInit::LNULL;
+ Type = new IntRecTy;
+ break;
+ }
+ if (Lex.getCode() != tgtok::l_paren) {
+ TokError("expected '(' after unary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the '('
+
+ Init *LHS = ParseValue(CurRec);
+ if (LHS == 0) return 0;
+
+ if (Code == UnOpInit::CAR
+ || Code == UnOpInit::CDR
+ || Code == UnOpInit::LNULL) {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
+ if (LHSl == 0 && LHSs == 0 && LHSt == 0) {
+ TokError("expected list or string type argument in unary operator");
+ return 0;
+ }
+ if (LHSt) {
+ ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
+ StringRecTy *SType = dynamic_cast<StringRecTy*>(LHSt->getType());
+ if (LType == 0 && SType == 0) {
+ TokError("expected list or string type argumnet in unary operator");
+ return 0;
+ }
+ }
+
+ if (Code == UnOpInit::CAR
+ || Code == UnOpInit::CDR) {
+ if (LHSl == 0 && LHSt == 0) {
+ TokError("expected list type argumnet in unary operator");
+ return 0;
+ }
+
+ if (LHSl && LHSl->getSize() == 0) {
+ TokError("empty list argument in unary operator");
+ return 0;
+ }
+ if (LHSl) {
+ Init *Item = LHSl->getElement(0);
+ TypedInit *Itemt = dynamic_cast<TypedInit*>(Item);
+ if (Itemt == 0) {
+ TokError("untyped list element in unary operator");
+ return 0;
+ }
+ if (Code == UnOpInit::CAR) {
+ Type = Itemt->getType();
+ } else {
+ Type = new ListRecTy(Itemt->getType());
+ }
+ } else {
+ assert(LHSt && "expected list type argument in unary operator");
+ ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
+ if (LType == 0) {
+ TokError("expected list type argumnet in unary operator");
+ return 0;
+ }
+ if (Code == UnOpInit::CAR) {
+ Type = LType->getElementType();
+ } else {
+ Type = LType;
+ }
+ }
+ }
+ }
+
+ if (Lex.getCode() != tgtok::r_paren) {
+ TokError("expected ')' in unary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ')'
+ return (new UnOpInit(Code, LHS, Type))->Fold(CurRec, CurMultiClass);
+ }
+
+ case tgtok::XConcat:
+ case tgtok::XSRA:
+ case tgtok::XSRL:
+ case tgtok::XSHL:
+ case tgtok::XEq:
+ case tgtok::XStrConcat:
+ case tgtok::XNameConcat: { // Value ::= !binop '(' Value ',' Value ')'
+ BinOpInit::BinaryOp Code;
+ RecTy *Type = 0;
+
+
+ switch (Lex.getCode()) {
+ default: assert(0 && "Unhandled code!");
+ case tgtok::XConcat:
+ Lex.Lex(); // eat the operation
+ Code = BinOpInit::CONCAT;
+ Type = new DagRecTy();
+ break;
+ case tgtok::XSRA:
+ Lex.Lex(); // eat the operation
+ Code = BinOpInit::SRA;
+ Type = new IntRecTy();
+ break;
+ case tgtok::XSRL:
+ Lex.Lex(); // eat the operation
+ Code = BinOpInit::SRL;
+ Type = new IntRecTy();
+ break;
+ case tgtok::XSHL:
+ Lex.Lex(); // eat the operation
+ Code = BinOpInit::SHL;
+ Type = new IntRecTy();
+ break;
+ case tgtok::XEq:
+ Lex.Lex(); // eat the operation
+ Code = BinOpInit::EQ;
+ Type = new IntRecTy();
+ break;
+ case tgtok::XStrConcat:
+ Lex.Lex(); // eat the operation
+ Code = BinOpInit::STRCONCAT;
+ Type = new StringRecTy();
+ break;
+ case tgtok::XNameConcat:
+ Lex.Lex(); // eat the operation
+ Code = BinOpInit::NAMECONCAT;
+
+ Type = ParseOperatorType();
+
+ if (Type == 0) {
+ TokError("did not get type for binary operator");
+ return 0;
+ }
+
+ break;
+ }
+ if (Lex.getCode() != tgtok::l_paren) {
+ TokError("expected '(' after binary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the '('
+
+ Init *LHS = ParseValue(CurRec);
+ if (LHS == 0) return 0;
+
+ if (Lex.getCode() != tgtok::comma) {
+ TokError("expected ',' in binary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ','
+
+ Init *RHS = ParseValue(CurRec);
+ if (RHS == 0) return 0;
+
+ if (Lex.getCode() != tgtok::r_paren) {
+ TokError("expected ')' in binary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ')'
+ return (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass);
+ }
+
+ case tgtok::XIf:
+ case tgtok::XForEach:
+ case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
+ TernOpInit::TernaryOp Code;
+ RecTy *Type = 0;
+
+
+ tgtok::TokKind LexCode = Lex.getCode();
+ Lex.Lex(); // eat the operation
+ switch (LexCode) {
+ default: assert(0 && "Unhandled code!");
+ case tgtok::XIf:
+ Code = TernOpInit::IF;
+ break;
+ case tgtok::XForEach:
+ Code = TernOpInit::FOREACH;
+ break;
+ case tgtok::XSubst:
+ Code = TernOpInit::SUBST;
+ break;
+ }
+ if (Lex.getCode() != tgtok::l_paren) {
+ TokError("expected '(' after ternary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the '('
+
+ Init *LHS = ParseValue(CurRec);
+ if (LHS == 0) return 0;
+
+ if (Lex.getCode() != tgtok::comma) {
+ TokError("expected ',' in ternary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ','
+
+ Init *MHS = ParseValue(CurRec);
+ if (MHS == 0) return 0;
+
+ if (Lex.getCode() != tgtok::comma) {
+ TokError("expected ',' in ternary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ','
+
+ Init *RHS = ParseValue(CurRec);
+ if (RHS == 0) return 0;
+
+ if (Lex.getCode() != tgtok::r_paren) {
+ TokError("expected ')' in binary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ')'
+
+ switch (LexCode) {
+ default: assert(0 && "Unhandled code!");
+ case tgtok::XIf: {
+ TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
+ TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS);
+ if (MHSt == 0 || RHSt == 0) {
+ TokError("could not get type for !if");
+ return 0;
+ }
+ if (MHSt->getType()->typeIsConvertibleTo(RHSt->getType())) {
+ Type = RHSt->getType();
+ } else if (RHSt->getType()->typeIsConvertibleTo(MHSt->getType())) {
+ Type = MHSt->getType();
+ } else {
+ TokError("inconsistent types for !if");
+ return 0;
+ }
+ break;
+ }
+ case tgtok::XForEach: {
+ TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
+ if (MHSt == 0) {
+ TokError("could not get type for !foreach");
+ return 0;
+ }
+ Type = MHSt->getType();
+ break;
+ }
+ case tgtok::XSubst: {
+ TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS);
+ if (RHSt == 0) {
+ TokError("could not get type for !subst");
+ return 0;
+ }
+ Type = RHSt->getType();
+ break;
+ }
+ }
+ return (new TernOpInit(Code, LHS, MHS, RHS, Type))->Fold(CurRec,
+ CurMultiClass);
+ }
+ }
+ TokError("could not parse operation");
+ return 0;
+}
+
+/// ParseOperatorType - Parse a type for an operator. This returns
+/// null on error.
+///
+/// OperatorType ::= '<' Type '>'
+///
+RecTy *TGParser::ParseOperatorType() {
+ RecTy *Type = 0;
+
+ if (Lex.getCode() != tgtok::less) {
+ TokError("expected type name for operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the <
+
+ Type = ParseType();
+
+ if (Type == 0) {
+ TokError("expected type name for operator");
+ return 0;
+ }
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected type name for operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the >
+
+ return Type;
+}
+
+
+/// ParseSimpleValue - Parse a tblgen value. This returns null on error.
+///
+/// SimpleValue ::= IDValue
+/// SimpleValue ::= INTVAL
+/// SimpleValue ::= STRVAL+
+/// SimpleValue ::= CODEFRAGMENT
+/// SimpleValue ::= '?'
+/// SimpleValue ::= '{' ValueList '}'
+/// SimpleValue ::= ID '<' ValueListNE '>'
+/// SimpleValue ::= '[' ValueList ']'
+/// SimpleValue ::= '(' IDValue DagArgList ')'
+/// SimpleValue ::= CONCATTOK '(' Value ',' Value ')'
+/// SimpleValue ::= SHLTOK '(' Value ',' Value ')'
+/// SimpleValue ::= SRATOK '(' Value ',' Value ')'
+/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
+/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
+///
+Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) {
+ Init *R = 0;
+ switch (Lex.getCode()) {
+ default: TokError("Unknown token when parsing a value"); break;
+ case tgtok::IntVal: R = new IntInit(Lex.getCurIntVal()); Lex.Lex(); break;
+ case tgtok::StrVal: {
+ std::string Val = Lex.getCurStrVal();
+ Lex.Lex();
+
+ // Handle multiple consecutive concatenated strings.
+ while (Lex.getCode() == tgtok::StrVal) {
+ Val += Lex.getCurStrVal();
+ Lex.Lex();
+ }
+
+ R = new StringInit(Val);
+ break;
+ }
+ case tgtok::CodeFragment:
+ R = new CodeInit(Lex.getCurStrVal()); Lex.Lex(); break;
+ case tgtok::question: R = new UnsetInit(); Lex.Lex(); break;
+ case tgtok::Id: {
+ SMLoc NameLoc = Lex.getLoc();
+ std::string Name = Lex.getCurStrVal();
+ if (Lex.Lex() != tgtok::less) // consume the Id.
+ return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue
+
+ // Value ::= ID '<' ValueListNE '>'
+ if (Lex.Lex() == tgtok::greater) {
+ TokError("expected non-empty value list");
+ return 0;
+ }
+
+ // This is a CLASS<initvalslist> expression. This is supposed to synthesize
+ // a new anonymous definition, deriving from CLASS<initvalslist> with no
+ // body.
+ Record *Class = Records.getClass(Name);
+ if (!Class) {
+ Error(NameLoc, "Expected a class name, got '" + Name + "'");
+ return 0;
+ }
+
+ std::vector<Init*> ValueList = ParseValueList(CurRec, Class);
+ if (ValueList.empty()) return 0;
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' at end of value list");
+ return 0;
+ }
+ Lex.Lex(); // eat the '>'
+
+ // Create the new record, set it as CurRec temporarily.
+ static unsigned AnonCounter = 0;
+ Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++),NameLoc);
+ SubClassReference SCRef;
+ SCRef.RefLoc = NameLoc;
+ SCRef.Rec = Class;
+ SCRef.TemplateArgs = ValueList;
+ // Add info about the subclass to NewRec.
+ if (AddSubClass(NewRec, SCRef))
+ return 0;
+ NewRec->resolveReferences();
+ Records.addDef(NewRec);
+
+ // The result of the expression is a reference to the new record.
+ return new DefInit(NewRec);
+ }
+ case tgtok::l_brace: { // Value ::= '{' ValueList '}'
+ SMLoc BraceLoc = Lex.getLoc();
+ Lex.Lex(); // eat the '{'
+ std::vector<Init*> Vals;
+
+ if (Lex.getCode() != tgtok::r_brace) {
+ Vals = ParseValueList(CurRec);
+ if (Vals.empty()) return 0;
+ }
+ if (Lex.getCode() != tgtok::r_brace) {
+ TokError("expected '}' at end of bit list value");
+ return 0;
+ }
+ Lex.Lex(); // eat the '}'
+
+ BitsInit *Result = new BitsInit(Vals.size());
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ Init *Bit = Vals[i]->convertInitializerTo(new BitRecTy());
+ if (Bit == 0) {
+ Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+
+ ") is not convertable to a bit");
+ return 0;
+ }
+ Result->setBit(Vals.size()-i-1, Bit);
+ }
+ return Result;
+ }
+ case tgtok::l_square: { // Value ::= '[' ValueList ']'
+ Lex.Lex(); // eat the '['
+ std::vector<Init*> Vals;
+
+ RecTy *DeducedEltTy = 0;
+ ListRecTy *GivenListTy = 0;
+
+ if (ItemType != 0) {
+ ListRecTy *ListType = dynamic_cast<ListRecTy*>(ItemType);
+ if (ListType == 0) {
+ std::stringstream s;
+ s << "Type mismatch for list, expected list type, got "
+ << ItemType->getAsString();
+ TokError(s.str());
+ }
+ GivenListTy = ListType;
+ }
+
+ if (Lex.getCode() != tgtok::r_square) {
+ Vals = ParseValueList(CurRec, 0,
+ GivenListTy ? GivenListTy->getElementType() : 0);
+ if (Vals.empty()) return 0;
+ }
+ if (Lex.getCode() != tgtok::r_square) {
+ TokError("expected ']' at end of list value");
+ return 0;
+ }
+ Lex.Lex(); // eat the ']'
+
+ RecTy *GivenEltTy = 0;
+ if (Lex.getCode() == tgtok::less) {
+ // Optional list element type
+ Lex.Lex(); // eat the '<'
+
+ GivenEltTy = ParseType();
+ if (GivenEltTy == 0) {
+ // Couldn't parse element type
+ return 0;
+ }
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' at end of list element type");
+ return 0;
+ }
+ Lex.Lex(); // eat the '>'
+ }
+
+ // Check elements
+ RecTy *EltTy = 0;
+ for (std::vector<Init *>::iterator i = Vals.begin(), ie = Vals.end();
+ i != ie;
+ ++i) {
+ TypedInit *TArg = dynamic_cast<TypedInit*>(*i);
+ if (TArg == 0) {
+ TokError("Untyped list element");
+ return 0;
+ }
+ if (EltTy != 0) {
+ EltTy = resolveTypes(EltTy, TArg->getType());
+ if (EltTy == 0) {
+ TokError("Incompatible types in list elements");
+ return 0;
+ }
+ } else {
+ EltTy = TArg->getType();
+ }
+ }
+
+ if (GivenEltTy != 0) {
+ if (EltTy != 0) {
+ // Verify consistency
+ if (!EltTy->typeIsConvertibleTo(GivenEltTy)) {
+ TokError("Incompatible types in list elements");
+ return 0;
+ }
+ }
+ EltTy = GivenEltTy;
+ }
+
+ if (EltTy == 0) {
+ if (ItemType == 0) {
+ TokError("No type for list");
+ return 0;
+ }
+ DeducedEltTy = GivenListTy->getElementType();
+ } else {
+ // Make sure the deduced type is compatible with the given type
+ if (GivenListTy) {
+ if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) {
+ TokError("Element type mismatch for list");
+ return 0;
+ }
+ }
+ DeducedEltTy = EltTy;
+ }
+
+ return new ListInit(Vals, DeducedEltTy);
+ }
+ case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
+ Lex.Lex(); // eat the '('
+ if (Lex.getCode() != tgtok::Id
+ && Lex.getCode() != tgtok::XCast
+ && Lex.getCode() != tgtok::XNameConcat) {
+ TokError("expected identifier in dag init");
+ return 0;
+ }
+
+ Init *Operator = 0;
+ if (Lex.getCode() == tgtok::Id) {
+ Operator = ParseIDValue(CurRec);
+ if (Operator == 0) return 0;
+ } else {
+ Operator = ParseOperation(CurRec);
+ if (Operator == 0) return 0;
+ }
+
+ // If the operator name is present, parse it.
+ std::string OperatorName;
+ if (Lex.getCode() == tgtok::colon) {
+ if (Lex.Lex() != tgtok::VarName) { // eat the ':'
+ TokError("expected variable name in dag operator");
+ return 0;
+ }
+ OperatorName = Lex.getCurStrVal();
+ Lex.Lex(); // eat the VarName.
+ }
+
+ std::vector<std::pair<llvm::Init*, std::string> > DagArgs;
+ if (Lex.getCode() != tgtok::r_paren) {
+ DagArgs = ParseDagArgList(CurRec);
+ if (DagArgs.empty()) return 0;
+ }
+
+ if (Lex.getCode() != tgtok::r_paren) {
+ TokError("expected ')' in dag init");
+ return 0;
+ }
+ Lex.Lex(); // eat the ')'
+
+ return new DagInit(Operator, OperatorName, DagArgs);
+ break;
+ }
+
+ case tgtok::XCar:
+ case tgtok::XCdr:
+ case tgtok::XNull:
+ case tgtok::XCast: // Value ::= !unop '(' Value ')'
+ case tgtok::XConcat:
+ case tgtok::XSRA:
+ case tgtok::XSRL:
+ case tgtok::XSHL:
+ case tgtok::XEq:
+ case tgtok::XStrConcat:
+ case tgtok::XNameConcat: // Value ::= !binop '(' Value ',' Value ')'
+ case tgtok::XIf:
+ case tgtok::XForEach:
+ case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
+ return ParseOperation(CurRec);
+ break;
+ }
+ }
+
+ return R;
+}
+
+/// ParseValue - Parse a tblgen value. This returns null on error.
+///
+/// Value ::= SimpleValue ValueSuffix*
+/// ValueSuffix ::= '{' BitList '}'
+/// ValueSuffix ::= '[' BitList ']'
+/// ValueSuffix ::= '.' ID
+///
+Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) {
+ Init *Result = ParseSimpleValue(CurRec, ItemType);
+ if (Result == 0) return 0;
+
+ // Parse the suffixes now if present.
+ while (1) {
+ switch (Lex.getCode()) {
+ default: return Result;
+ case tgtok::l_brace: {
+ SMLoc CurlyLoc = Lex.getLoc();
+ Lex.Lex(); // eat the '{'
+ std::vector<unsigned> Ranges = ParseRangeList();
+ if (Ranges.empty()) return 0;
+
+ // Reverse the bitlist.
+ std::reverse(Ranges.begin(), Ranges.end());
+ Result = Result->convertInitializerBitRange(Ranges);
+ if (Result == 0) {
+ Error(CurlyLoc, "Invalid bit range for value");
+ return 0;
+ }
+
+ // Eat the '}'.
+ if (Lex.getCode() != tgtok::r_brace) {
+ TokError("expected '}' at end of bit range list");
+ return 0;
+ }
+ Lex.Lex();
+ break;
+ }
+ case tgtok::l_square: {
+ SMLoc SquareLoc = Lex.getLoc();
+ Lex.Lex(); // eat the '['
+ std::vector<unsigned> Ranges = ParseRangeList();
+ if (Ranges.empty()) return 0;
+
+ Result = Result->convertInitListSlice(Ranges);
+ if (Result == 0) {
+ Error(SquareLoc, "Invalid range for list slice");
+ return 0;
+ }
+
+ // Eat the ']'.
+ if (Lex.getCode() != tgtok::r_square) {
+ TokError("expected ']' at end of list slice");
+ return 0;
+ }
+ Lex.Lex();
+ break;
+ }
+ case tgtok::period:
+ if (Lex.Lex() != tgtok::Id) { // eat the .
+ TokError("expected field identifier after '.'");
+ return 0;
+ }
+ if (!Result->getFieldType(Lex.getCurStrVal())) {
+ TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
+ Result->getAsString() + "'");
+ return 0;
+ }
+ Result = new FieldInit(Result, Lex.getCurStrVal());
+ Lex.Lex(); // eat field name
+ break;
+ }
+ }
+}
+
+/// ParseDagArgList - Parse the argument list for a dag literal expression.
+///
+/// ParseDagArgList ::= Value (':' VARNAME)?
+/// ParseDagArgList ::= ParseDagArgList ',' Value (':' VARNAME)?
+std::vector<std::pair<llvm::Init*, std::string> >
+TGParser::ParseDagArgList(Record *CurRec) {
+ std::vector<std::pair<llvm::Init*, std::string> > Result;
+
+ while (1) {
+ Init *Val = ParseValue(CurRec);
+ if (Val == 0) return std::vector<std::pair<llvm::Init*, std::string> >();
+
+ // If the variable name is present, add it.
+ std::string VarName;
+ if (Lex.getCode() == tgtok::colon) {
+ if (Lex.Lex() != tgtok::VarName) { // eat the ':'
+ TokError("expected variable name in dag literal");
+ return std::vector<std::pair<llvm::Init*, std::string> >();
+ }
+ VarName = Lex.getCurStrVal();
+ Lex.Lex(); // eat the VarName.
+ }
+
+ Result.push_back(std::make_pair(Val, VarName));
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat the ','
+ }
+
+ return Result;
+}
+
+
+/// ParseValueList - Parse a comma separated list of values, returning them as a
+/// vector. Note that this always expects to be able to parse at least one
+/// value. It returns an empty list if this is not possible.
+///
+/// ValueList ::= Value (',' Value)
+///
+std::vector<Init*> TGParser::ParseValueList(Record *CurRec, Record *ArgsRec,
+ RecTy *EltTy) {
+ std::vector<Init*> Result;
+ RecTy *ItemType = EltTy;
+ unsigned int ArgN = 0;
+ if (ArgsRec != 0 && EltTy == 0) {
+ const std::vector<std::string> &TArgs = ArgsRec->getTemplateArgs();
+ const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
+ assert(RV && "Template argument record not found??");
+ ItemType = RV->getType();
+ ++ArgN;
+ }
+ Result.push_back(ParseValue(CurRec, ItemType));
+ if (Result.back() == 0) return std::vector<Init*>();
+
+ while (Lex.getCode() == tgtok::comma) {
+ Lex.Lex(); // Eat the comma
+
+ if (ArgsRec != 0 && EltTy == 0) {
+ const std::vector<std::string> &TArgs = ArgsRec->getTemplateArgs();
+ if (ArgN >= TArgs.size()) {
+ TokError("too many template arguments");
+ return std::vector<Init*>();
+ }
+ const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
+ assert(RV && "Template argument record not found??");
+ ItemType = RV->getType();
+ ++ArgN;
+ }
+ Result.push_back(ParseValue(CurRec, ItemType));
+ if (Result.back() == 0) return std::vector<Init*>();
+ }
+
+ return Result;
+}
+
+
+/// ParseDeclaration - Read a declaration, returning the name of field ID, or an
+/// empty string on error. This can happen in a number of different context's,
+/// including within a def or in the template args for a def (which which case
+/// CurRec will be non-null) and within the template args for a multiclass (in
+/// which case CurRec will be null, but CurMultiClass will be set). This can
+/// also happen within a def that is within a multiclass, which will set both
+/// CurRec and CurMultiClass.
+///
+/// Declaration ::= FIELD? Type ID ('=' Value)?
+///
+std::string TGParser::ParseDeclaration(Record *CurRec,
+ bool ParsingTemplateArgs) {
+ // Read the field prefix if present.
+ bool HasField = Lex.getCode() == tgtok::Field;
+ if (HasField) Lex.Lex();
+
+ RecTy *Type = ParseType();
+ if (Type == 0) return "";
+
+ if (Lex.getCode() != tgtok::Id) {
+ TokError("Expected identifier in declaration");
+ return "";
+ }
+
+ SMLoc IdLoc = Lex.getLoc();
+ std::string DeclName = Lex.getCurStrVal();
+ Lex.Lex();
+
+ if (ParsingTemplateArgs) {
+ if (CurRec) {
+ DeclName = CurRec->getName() + ":" + DeclName;
+ } else {
+ assert(CurMultiClass);
+ }
+ if (CurMultiClass)
+ DeclName = CurMultiClass->Rec.getName() + "::" + DeclName;
+ }
+
+ // Add the value.
+ if (AddValue(CurRec, IdLoc, RecordVal(DeclName, Type, HasField)))
+ return "";
+
+ // If a value is present, parse it.
+ if (Lex.getCode() == tgtok::equal) {
+ Lex.Lex();
+ SMLoc ValLoc = Lex.getLoc();
+ Init *Val = ParseValue(CurRec, Type);
+ if (Val == 0 ||
+ SetValue(CurRec, ValLoc, DeclName, std::vector<unsigned>(), Val))
+ return "";
+ }
+
+ return DeclName;
+}
+
+/// ParseTemplateArgList - Read a template argument list, which is a non-empty
+/// sequence of template-declarations in <>'s. If CurRec is non-null, these are
+/// template args for a def, which may or may not be in a multiclass. If null,
+/// these are the template args for a multiclass.
+///
+/// TemplateArgList ::= '<' Declaration (',' Declaration)* '>'
+///
+bool TGParser::ParseTemplateArgList(Record *CurRec) {
+ assert(Lex.getCode() == tgtok::less && "Not a template arg list!");
+ Lex.Lex(); // eat the '<'
+
+ Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec;
+
+ // Read the first declaration.
+ std::string TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
+ if (TemplArg.empty())
+ return true;
+
+ TheRecToAddTo->addTemplateArg(TemplArg);
+
+ while (Lex.getCode() == tgtok::comma) {
+ Lex.Lex(); // eat the ','
+
+ // Read the following declarations.
+ TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
+ if (TemplArg.empty())
+ return true;
+ TheRecToAddTo->addTemplateArg(TemplArg);
+ }
+
+ if (Lex.getCode() != tgtok::greater)
+ return TokError("expected '>' at end of template argument list");
+ Lex.Lex(); // eat the '>'.
+ return false;
+}
+
+
+/// ParseBodyItem - Parse a single item at within the body of a def or class.
+///
+/// BodyItem ::= Declaration ';'
+/// BodyItem ::= LET ID OptionalBitList '=' Value ';'
+bool TGParser::ParseBodyItem(Record *CurRec) {
+ if (Lex.getCode() != tgtok::Let) {
+ if (ParseDeclaration(CurRec, false).empty())
+ return true;
+
+ if (Lex.getCode() != tgtok::semi)
+ return TokError("expected ';' after declaration");
+ Lex.Lex();
+ return false;
+ }
+
+ // LET ID OptionalRangeList '=' Value ';'
+ if (Lex.Lex() != tgtok::Id)
+ return TokError("expected field identifier after let");
+
+ SMLoc IdLoc = Lex.getLoc();
+ std::string FieldName = Lex.getCurStrVal();
+ Lex.Lex(); // eat the field name.
+
+ std::vector<unsigned> BitList;
+ if (ParseOptionalBitList(BitList))
+ return true;
+ std::reverse(BitList.begin(), BitList.end());
+
+ if (Lex.getCode() != tgtok::equal)
+ return TokError("expected '=' in let expression");
+ Lex.Lex(); // eat the '='.
+
+ RecordVal *Field = CurRec->getValue(FieldName);
+ if (Field == 0)
+ return TokError("Value '" + FieldName + "' unknown!");
+
+ RecTy *Type = Field->getType();
+
+ Init *Val = ParseValue(CurRec, Type);
+ if (Val == 0) return true;
+
+ if (Lex.getCode() != tgtok::semi)
+ return TokError("expected ';' after let expression");
+ Lex.Lex();
+
+ return SetValue(CurRec, IdLoc, FieldName, BitList, Val);
+}
+
+/// ParseBody - Read the body of a class or def. Return true on error, false on
+/// success.
+///
+/// Body ::= ';'
+/// Body ::= '{' BodyList '}'
+/// BodyList BodyItem*
+///
+bool TGParser::ParseBody(Record *CurRec) {
+ // If this is a null definition, just eat the semi and return.
+ if (Lex.getCode() == tgtok::semi) {
+ Lex.Lex();
+ return false;
+ }
+
+ if (Lex.getCode() != tgtok::l_brace)
+ return TokError("Expected ';' or '{' to start body");
+ // Eat the '{'.
+ Lex.Lex();
+
+ while (Lex.getCode() != tgtok::r_brace)
+ if (ParseBodyItem(CurRec))
+ return true;
+
+ // Eat the '}'.
+ Lex.Lex();
+ return false;
+}
+
+/// ParseObjectBody - Parse the body of a def or class. This consists of an
+/// optional ClassList followed by a Body. CurRec is the current def or class
+/// that is being parsed.
+///
+/// ObjectBody ::= BaseClassList Body
+/// BaseClassList ::= /*empty*/
+/// BaseClassList ::= ':' BaseClassListNE
+/// BaseClassListNE ::= SubClassRef (',' SubClassRef)*
+///
+bool TGParser::ParseObjectBody(Record *CurRec) {
+ // If there is a baseclass list, read it.
+ if (Lex.getCode() == tgtok::colon) {
+ Lex.Lex();
+
+ // Read all of the subclasses.
+ SubClassReference SubClass = ParseSubClassReference(CurRec, false);
+ while (1) {
+ // Check for error.
+ if (SubClass.Rec == 0) return true;
+
+ // Add it.
+ if (AddSubClass(CurRec, SubClass))
+ return true;
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat ','.
+ SubClass = ParseSubClassReference(CurRec, false);
+ }
+ }
+
+ // Process any variables on the let stack.
+ for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
+ for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
+ if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
+ LetStack[i][j].Bits, LetStack[i][j].Value))
+ return true;
+
+ return ParseBody(CurRec);
+}
+
+/// ParseDef - Parse and return a top level or multiclass def, return the record
+/// corresponding to it. This returns null on error.
+///
+/// DefInst ::= DEF ObjectName ObjectBody
+///
+bool TGParser::ParseDef(MultiClass *CurMultiClass) {
+ SMLoc DefLoc = Lex.getLoc();
+ assert(Lex.getCode() == tgtok::Def && "Unknown tok");
+ Lex.Lex(); // Eat the 'def' token.
+
+ // Parse ObjectName and make a record for it.
+ Record *CurRec = new Record(ParseObjectName(), DefLoc);
+
+ if (!CurMultiClass) {
+ // Top-level def definition.
+
+ // Ensure redefinition doesn't happen.
+ if (Records.getDef(CurRec->getName())) {
+ Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
+ return true;
+ }
+ Records.addDef(CurRec);
+ } else {
+ // Otherwise, a def inside a multiclass, add it to the multiclass.
+ for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i)
+ if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
+ Error(DefLoc, "def '" + CurRec->getName() +
+ "' already defined in this multiclass!");
+ return true;
+ }
+ CurMultiClass->DefPrototypes.push_back(CurRec);
+ }
+
+ if (ParseObjectBody(CurRec))
+ return true;
+
+ if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
+ CurRec->resolveReferences();
+
+ // If ObjectBody has template arguments, it's an error.
+ assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
+
+ if (CurMultiClass) {
+ // Copy the template arguments for the multiclass into the def.
+ const std::vector<std::string> &TArgs =
+ CurMultiClass->Rec.getTemplateArgs();
+
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
+ assert(RV && "Template arg doesn't exist?");
+ CurRec->addValue(*RV);
+ }
+ }
+
+ return false;
+}
+
+
+/// ParseClass - Parse a tblgen class definition.
+///
+/// ClassInst ::= CLASS ID TemplateArgList? ObjectBody
+///
+bool TGParser::ParseClass() {
+ assert(Lex.getCode() == tgtok::Class && "Unexpected token!");
+ Lex.Lex();
+
+ if (Lex.getCode() != tgtok::Id)
+ return TokError("expected class name after 'class' keyword");
+
+ Record *CurRec = Records.getClass(Lex.getCurStrVal());
+ if (CurRec) {
+ // If the body was previously defined, this is an error.
+ if (!CurRec->getValues().empty() ||
+ !CurRec->getSuperClasses().empty() ||
+ !CurRec->getTemplateArgs().empty())
+ return TokError("Class '" + CurRec->getName() + "' already defined");
+ } else {
+ // If this is the first reference to this class, create and add it.
+ CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc());
+ Records.addClass(CurRec);
+ }
+ Lex.Lex(); // eat the name.
+
+ // If there are template args, parse them.
+ if (Lex.getCode() == tgtok::less)
+ if (ParseTemplateArgList(CurRec))
+ return true;
+
+ // Finally, parse the object body.
+ return ParseObjectBody(CurRec);
+}
+
+/// ParseLetList - Parse a non-empty list of assignment expressions into a list
+/// of LetRecords.
+///
+/// LetList ::= LetItem (',' LetItem)*
+/// LetItem ::= ID OptionalRangeList '=' Value
+///
+std::vector<LetRecord> TGParser::ParseLetList() {
+ std::vector<LetRecord> Result;
+
+ while (1) {
+ if (Lex.getCode() != tgtok::Id) {
+ TokError("expected identifier in let definition");
+ return std::vector<LetRecord>();
+ }
+ std::string Name = Lex.getCurStrVal();
+ SMLoc NameLoc = Lex.getLoc();
+ Lex.Lex(); // Eat the identifier.
+
+ // Check for an optional RangeList.
+ std::vector<unsigned> Bits;
+ if (ParseOptionalRangeList(Bits))
+ return std::vector<LetRecord>();
+ std::reverse(Bits.begin(), Bits.end());
+
+ if (Lex.getCode() != tgtok::equal) {
+ TokError("expected '=' in let expression");
+ return std::vector<LetRecord>();
+ }
+ Lex.Lex(); // eat the '='.
+
+ Init *Val = ParseValue(0);
+ if (Val == 0) return std::vector<LetRecord>();
+
+ // Now that we have everything, add the record.
+ Result.push_back(LetRecord(Name, Bits, Val, NameLoc));
+
+ if (Lex.getCode() != tgtok::comma)
+ return Result;
+ Lex.Lex(); // eat the comma.
+ }
+}
+
+/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
+/// different related productions. This works inside multiclasses too.
+///
+/// Object ::= LET LetList IN '{' ObjectList '}'
+/// Object ::= LET LetList IN Object
+///
+bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
+ assert(Lex.getCode() == tgtok::Let && "Unexpected token");
+ Lex.Lex();
+
+ // Add this entry to the let stack.
+ std::vector<LetRecord> LetInfo = ParseLetList();
+ if (LetInfo.empty()) return true;
+ LetStack.push_back(LetInfo);
+
+ if (Lex.getCode() != tgtok::In)
+ return TokError("expected 'in' at end of top-level 'let'");
+ Lex.Lex();
+
+ // If this is a scalar let, just handle it now
+ if (Lex.getCode() != tgtok::l_brace) {
+ // LET LetList IN Object
+ if (ParseObject(CurMultiClass))
+ return true;
+ } else { // Object ::= LETCommand '{' ObjectList '}'
+ SMLoc BraceLoc = Lex.getLoc();
+ // Otherwise, this is a group let.
+ Lex.Lex(); // eat the '{'.
+
+ // Parse the object list.
+ if (ParseObjectList(CurMultiClass))
+ return true;
+
+ if (Lex.getCode() != tgtok::r_brace) {
+ TokError("expected '}' at end of top level let command");
+ return Error(BraceLoc, "to match this '{'");
+ }
+ Lex.Lex();
+ }
+
+ // Outside this let scope, this let block is not active.
+ LetStack.pop_back();
+ return false;
+}
+
+/// ParseMultiClass - Parse a multiclass definition.
+///
+/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
+/// ':' BaseMultiClassList '{' MultiClassDef+ '}'
+///
+bool TGParser::ParseMultiClass() {
+ assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
+ Lex.Lex(); // Eat the multiclass token.
+
+ if (Lex.getCode() != tgtok::Id)
+ return TokError("expected identifier after multiclass for name");
+ std::string Name = Lex.getCurStrVal();
+
+ if (MultiClasses.count(Name))
+ return TokError("multiclass '" + Name + "' already defined");
+
+ CurMultiClass = MultiClasses[Name] = new MultiClass(Name, Lex.getLoc());
+ Lex.Lex(); // Eat the identifier.
+
+ // If there are template args, parse them.
+ if (Lex.getCode() == tgtok::less)
+ if (ParseTemplateArgList(0))
+ return true;
+
+ bool inherits = false;
+
+ // If there are submulticlasses, parse them.
+ if (Lex.getCode() == tgtok::colon) {
+ inherits = true;
+
+ Lex.Lex();
+
+ // Read all of the submulticlasses.
+ SubMultiClassReference SubMultiClass =
+ ParseSubMultiClassReference(CurMultiClass);
+ while (1) {
+ // Check for error.
+ if (SubMultiClass.MC == 0) return true;
+
+ // Add it.
+ if (AddSubMultiClass(CurMultiClass, SubMultiClass))
+ return true;
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat ','.
+ SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
+ }
+ }
+
+ if (Lex.getCode() != tgtok::l_brace) {
+ if (!inherits)
+ return TokError("expected '{' in multiclass definition");
+ else if (Lex.getCode() != tgtok::semi)
+ return TokError("expected ';' in multiclass definition");
+ else
+ Lex.Lex(); // eat the ';'.
+ } else {
+ if (Lex.Lex() == tgtok::r_brace) // eat the '{'.
+ return TokError("multiclass must contain at least one def");
+
+ while (Lex.getCode() != tgtok::r_brace) {
+ switch (Lex.getCode()) {
+ default:
+ return TokError("expected 'let', 'def' or 'defm' in multiclass body");
+ case tgtok::Let:
+ case tgtok::Def:
+ case tgtok::Defm:
+ if (ParseObject(CurMultiClass))
+ return true;
+ break;
+ }
+ }
+ Lex.Lex(); // eat the '}'.
+ }
+
+ CurMultiClass = 0;
+ return false;
+}
+
+/// ParseDefm - Parse the instantiation of a multiclass.
+///
+/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'
+///
+bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
+ assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
+ if (Lex.Lex() != tgtok::Id) // eat the defm.
+ return TokError("expected identifier after defm");
+
+ SMLoc DefmPrefixLoc = Lex.getLoc();
+ std::string DefmPrefix = Lex.getCurStrVal();
+ if (Lex.Lex() != tgtok::colon)
+ return TokError("expected ':' after defm identifier");
+
+ // Keep track of the new generated record definitions.
+ std::vector<Record*> NewRecDefs;
+
+ // This record also inherits from a regular class (non-multiclass)?
+ bool InheritFromClass = false;
+
+ // eat the colon.
+ Lex.Lex();
+
+ SMLoc SubClassLoc = Lex.getLoc();
+ SubClassReference Ref = ParseSubClassReference(0, true);
+
+ while (1) {
+ if (Ref.Rec == 0) return true;
+
+ // To instantiate a multiclass, we need to first get the multiclass, then
+ // instantiate each def contained in the multiclass with the SubClassRef
+ // template parameters.
+ MultiClass *MC = MultiClasses[Ref.Rec->getName()];
+ assert(MC && "Didn't lookup multiclass correctly?");
+ std::vector<Init*> &TemplateVals = Ref.TemplateArgs;
+
+ // Verify that the correct number of template arguments were specified.
+ const std::vector<std::string> &TArgs = MC->Rec.getTemplateArgs();
+ if (TArgs.size() < TemplateVals.size())
+ return Error(SubClassLoc,
+ "more template args specified than multiclass expects");
+
+ // Loop over all the def's in the multiclass, instantiating each one.
+ for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) {
+ Record *DefProto = MC->DefPrototypes[i];
+
+ // Add in the defm name
+ std::string DefName = DefProto->getName();
+ std::string::size_type idx = DefName.find("#NAME#");
+ if (idx != std::string::npos) {
+ DefName.replace(idx, 6, DefmPrefix);
+ } else {
+ // Add the suffix to the defm name to get the new name.
+ DefName = DefmPrefix + DefName;
+ }
+
+ Record *CurRec = new Record(DefName, DefmPrefixLoc);
+
+ SubClassReference Ref;
+ Ref.RefLoc = DefmPrefixLoc;
+ Ref.Rec = DefProto;
+ AddSubClass(CurRec, Ref);
+
+ // Loop over all of the template arguments, setting them to the specified
+ // value or leaving them as the default if necessary.
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ // Check if a value is specified for this temp-arg.
+ if (i < TemplateVals.size()) {
+ // Set it now.
+ if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector<unsigned>(),
+ TemplateVals[i]))
+ return true;
+
+ // Resolve it next.
+ CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
+
+ // Now remove it.
+ CurRec->removeValue(TArgs[i]);
+
+ } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
+ return Error(SubClassLoc,
+ "value not specified for template argument #"+
+ utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" +
+ MC->Rec.getName() + "'");
+ }
+ }
+
+ // If the mdef is inside a 'let' expression, add to each def.
+ for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
+ for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
+ if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
+ LetStack[i][j].Bits, LetStack[i][j].Value)) {
+ Error(DefmPrefixLoc, "when instantiating this defm");
+ return true;
+ }
+
+ // Ensure redefinition doesn't happen.
+ if (Records.getDef(CurRec->getName()))
+ return Error(DefmPrefixLoc, "def '" + CurRec->getName() +
+ "' already defined, instantiating defm with subdef '" +
+ DefProto->getName() + "'");
+
+ // Don't create a top level definition for defm inside multiclasses,
+ // instead, only update the prototypes and bind the template args
+ // with the new created definition.
+ if (CurMultiClass) {
+ for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size();
+ i != e; ++i) {
+ if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
+ Error(DefmPrefixLoc, "defm '" + CurRec->getName() +
+ "' already defined in this multiclass!");
+ return 0;
+ }
+ }
+ CurMultiClass->DefPrototypes.push_back(CurRec);
+
+ // Copy the template arguments for the multiclass into the new def.
+ const std::vector<std::string> &TA =
+ CurMultiClass->Rec.getTemplateArgs();
+
+ for (unsigned i = 0, e = TA.size(); i != e; ++i) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]);
+ assert(RV && "Template arg doesn't exist?");
+ CurRec->addValue(*RV);
+ }
+ } else {
+ Records.addDef(CurRec);
+ }
+
+ NewRecDefs.push_back(CurRec);
+ }
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat ','.
+
+ SubClassLoc = Lex.getLoc();
+
+ // A defm can inherit from regular classes (non-multiclass) as
+ // long as they come in the end of the inheritance list.
+ InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0);
+
+ if (InheritFromClass)
+ break;
+
+ Ref = ParseSubClassReference(0, true);
+ }
+
+ if (InheritFromClass) {
+ // Process all the classes to inherit as if they were part of a
+ // regular 'def' and inherit all record values.
+ SubClassReference SubClass = ParseSubClassReference(0, false);
+ while (1) {
+ // Check for error.
+ if (SubClass.Rec == 0) return true;
+
+ // Get the expanded definition prototypes and teach them about
+ // the record values the current class to inherit has
+ for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) {
+ Record *CurRec = NewRecDefs[i];
+
+ // Add it.
+ if (AddSubClass(CurRec, SubClass))
+ return true;
+
+ // Process any variables on the let stack.
+ for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
+ for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
+ if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
+ LetStack[i][j].Bits, LetStack[i][j].Value))
+ return true;
+ }
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat ','.
+ SubClass = ParseSubClassReference(0, false);
+ }
+ }
+
+ if (!CurMultiClass)
+ for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i)
+ NewRecDefs[i]->resolveReferences();
+
+ if (Lex.getCode() != tgtok::semi)
+ return TokError("expected ';' at end of defm");
+ Lex.Lex();
+
+ return false;
+}
+
+/// ParseObject
+/// Object ::= ClassInst
+/// Object ::= DefInst
+/// Object ::= MultiClassInst
+/// Object ::= DefMInst
+/// Object ::= LETCommand '{' ObjectList '}'
+/// Object ::= LETCommand Object
+bool TGParser::ParseObject(MultiClass *MC) {
+ switch (Lex.getCode()) {
+ default: assert(0 && "This is not an object");
+ case tgtok::Let: return ParseTopLevelLet(MC);
+ case tgtok::Def: return ParseDef(MC);
+ case tgtok::Defm: return ParseDefm(MC);
+ case tgtok::Class: return ParseClass();
+ case tgtok::MultiClass: return ParseMultiClass();
+ }
+}
+
+/// ParseObjectList
+/// ObjectList :== Object*
+bool TGParser::ParseObjectList(MultiClass *MC) {
+ while (isObjectStart(Lex.getCode())) {
+ if (ParseObject(MC))
+ return true;
+ }
+ return false;
+}
+
+bool TGParser::ParseFile() {
+ Lex.Lex(); // Prime the lexer.
+ if (ParseObjectList()) return true;
+
+ // If we have unread input at the end of the file, report it.
+ if (Lex.getCode() == tgtok::Eof)
+ return false;
+
+ return TokError("Unexpected input at top level");
+}
+
diff --git a/contrib/llvm/utils/TableGen/TGParser.h b/contrib/llvm/utils/TableGen/TGParser.h
new file mode 100644
index 0000000..0aee931
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/TGParser.h
@@ -0,0 +1,112 @@
+//===- TGParser.h - Parser for TableGen Files -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class represents the Parser for tablegen files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TGPARSER_H
+#define TGPARSER_H
+
+#include "TGLexer.h"
+#include "llvm/Support/SourceMgr.h"
+#include <map>
+
+namespace llvm {
+ class Record;
+ class RecordVal;
+ struct RecTy;
+ struct Init;
+ struct MultiClass;
+ struct SubClassReference;
+ struct SubMultiClassReference;
+
+ struct LetRecord {
+ std::string Name;
+ std::vector<unsigned> Bits;
+ Init *Value;
+ SMLoc Loc;
+ LetRecord(const std::string &N, const std::vector<unsigned> &B, Init *V,
+ SMLoc L)
+ : Name(N), Bits(B), Value(V), Loc(L) {
+ }
+ };
+
+class TGParser {
+ TGLexer Lex;
+ std::vector<std::vector<LetRecord> > LetStack;
+ std::map<std::string, MultiClass*> MultiClasses;
+
+ /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the
+ /// current value.
+ MultiClass *CurMultiClass;
+public:
+ TGParser(SourceMgr &SrcMgr) : Lex(SrcMgr), CurMultiClass(0) {}
+
+ /// ParseFile - Main entrypoint for parsing a tblgen file. These parser
+ /// routines return true on error, or false on success.
+ bool ParseFile();
+
+ bool Error(SMLoc L, const std::string &Msg) const {
+ Lex.PrintError(L, Msg);
+ return true;
+ }
+ bool TokError(const std::string &Msg) const {
+ return Error(Lex.getLoc(), Msg);
+ }
+private: // Semantic analysis methods.
+ bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV);
+ bool SetValue(Record *TheRec, SMLoc Loc, const std::string &ValName,
+ const std::vector<unsigned> &BitList, Init *V);
+ bool AddSubClass(Record *Rec, SubClassReference &SubClass);
+ bool AddSubMultiClass(MultiClass *CurMC,
+ SubMultiClassReference &SubMultiClass);
+
+private: // Parser methods.
+ bool ParseObjectList(MultiClass *MC = 0);
+ bool ParseObject(MultiClass *MC);
+ bool ParseClass();
+ bool ParseMultiClass();
+ bool ParseDefm(MultiClass *CurMultiClass);
+ bool ParseDef(MultiClass *CurMultiClass);
+ bool ParseTopLevelLet(MultiClass *CurMultiClass);
+ std::vector<LetRecord> ParseLetList();
+
+ bool ParseObjectBody(Record *CurRec);
+ bool ParseBody(Record *CurRec);
+ bool ParseBodyItem(Record *CurRec);
+
+ bool ParseTemplateArgList(Record *CurRec);
+ std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
+
+ SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
+ SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC);
+
+ Init *ParseIDValue(Record *CurRec);
+ Init *ParseIDValue(Record *CurRec, const std::string &Name, SMLoc NameLoc);
+ Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = 0);
+ Init *ParseValue(Record *CurRec, RecTy *ItemType = 0);
+ std::vector<Init*> ParseValueList(Record *CurRec, Record *ArgsRec = 0, RecTy *EltTy = 0);
+ std::vector<std::pair<llvm::Init*, std::string> > ParseDagArgList(Record *);
+ bool ParseOptionalRangeList(std::vector<unsigned> &Ranges);
+ bool ParseOptionalBitList(std::vector<unsigned> &Ranges);
+ std::vector<unsigned> ParseRangeList();
+ bool ParseRangePiece(std::vector<unsigned> &Ranges);
+ RecTy *ParseType();
+ Init *ParseOperation(Record *CurRec);
+ RecTy *ParseOperatorType();
+ std::string ParseObjectName();
+ Record *ParseClassID();
+ MultiClass *ParseMultiClassID();
+ Record *ParseDefmID();
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/TGValueTypes.cpp b/contrib/llvm/utils/TableGen/TGValueTypes.cpp
new file mode 100644
index 0000000..122d085
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/TGValueTypes.cpp
@@ -0,0 +1,106 @@
+//===- ValueTypes.cpp - Tablegen extended ValueType implementation --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The EVT type is used by tablegen as well as in LLVM. In order to handle
+// extended types, the EVT type uses support functions that call into
+// LLVM's type system code. These aren't accessible in tablegen, so this
+// file provides simple replacements.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/ValueTypes.h"
+#include <map>
+#include <vector>
+using namespace llvm;
+
+namespace llvm {
+
+class Type {
+public:
+ virtual unsigned getSizeInBits() const = 0;
+ virtual ~Type() {}
+};
+
+}
+
+class ExtendedIntegerType : public Type {
+ unsigned BitWidth;
+public:
+ explicit ExtendedIntegerType(unsigned bits)
+ : BitWidth(bits) {}
+ unsigned getSizeInBits() const {
+ return getBitWidth();
+ }
+ unsigned getBitWidth() const {
+ return BitWidth;
+ }
+};
+
+class ExtendedVectorType : public Type {
+ EVT ElementType;
+ unsigned NumElements;
+public:
+ ExtendedVectorType(EVT elty, unsigned num)
+ : ElementType(elty), NumElements(num) {}
+ unsigned getSizeInBits() const {
+ return getNumElements() * getElementType().getSizeInBits();
+ }
+ EVT getElementType() const {
+ return ElementType;
+ }
+ unsigned getNumElements() const {
+ return NumElements;
+ }
+};
+
+static std::map<unsigned, const Type *>
+ ExtendedIntegerTypeMap;
+static std::map<std::pair<uintptr_t, uintptr_t>, const Type *>
+ ExtendedVectorTypeMap;
+
+bool EVT::isExtendedFloatingPoint() const {
+ assert(isExtended() && "Type is not extended!");
+ // Extended floating-point types are not supported yet.
+ return false;
+}
+
+bool EVT::isExtendedInteger() const {
+ assert(isExtended() && "Type is not extended!");
+ return dynamic_cast<const ExtendedIntegerType *>(LLVMTy) != 0;
+}
+
+bool EVT::isExtendedVector() const {
+ assert(isExtended() && "Type is not extended!");
+ return dynamic_cast<const ExtendedVectorType *>(LLVMTy) != 0;
+}
+
+bool EVT::isExtended64BitVector() const {
+ assert(isExtended() && "Type is not extended!");
+ return isExtendedVector() && getSizeInBits() == 64;
+}
+
+bool EVT::isExtended128BitVector() const {
+ assert(isExtended() && "Type is not extended!");
+ return isExtendedVector() && getSizeInBits() == 128;
+}
+
+EVT EVT::getExtendedVectorElementType() const {
+ assert(isExtendedVector() && "Type is not an extended vector!");
+ return static_cast<const ExtendedVectorType *>(LLVMTy)->getElementType();
+}
+
+unsigned EVT::getExtendedVectorNumElements() const {
+ assert(isExtendedVector() && "Type is not an extended vector!");
+ return static_cast<const ExtendedVectorType *>(LLVMTy)->getNumElements();
+}
+
+unsigned EVT::getExtendedSizeInBits() const {
+ assert(isExtended() && "Type is not extended!");
+ return LLVMTy->getSizeInBits();
+}
diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp
new file mode 100644
index 0000000..5e3e282
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/TableGen.cpp
@@ -0,0 +1,356 @@
+//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// TableGen is a tool which can be used to build up a description of something,
+// then invoke one or more "tablegen backends" to emit information about the
+// description in some predefined format. In practice, this is used by the LLVM
+// code generators to automate generation of a code generator through a
+// high-level description of the target.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AsmMatcherEmitter.h"
+#include "AsmWriterEmitter.h"
+#include "CallingConvEmitter.h"
+#include "ClangASTNodesEmitter.h"
+#include "ClangAttrEmitter.h"
+#include "ClangDiagnosticsEmitter.h"
+#include "CodeEmitterGen.h"
+#include "DAGISelEmitter.h"
+#include "DisassemblerEmitter.h"
+#include "EDEmitter.h"
+#include "FastISelEmitter.h"
+#include "InstrEnumEmitter.h"
+#include "InstrInfoEmitter.h"
+#include "IntrinsicEmitter.h"
+#include "LLVMCConfigurationEmitter.h"
+#include "NeonEmitter.h"
+#include "OptParserEmitter.h"
+#include "Record.h"
+#include "RegisterInfoEmitter.h"
+#include "ARMDecoderEmitter.h"
+#include "SubtargetEmitter.h"
+#include "TGParser.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Signals.h"
+#include <algorithm>
+#include <cstdio>
+using namespace llvm;
+
+enum ActionType {
+ PrintRecords,
+ GenEmitter,
+ GenRegisterEnums, GenRegister, GenRegisterHeader,
+ GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher,
+ GenARMDecoder,
+ GenDisassembler,
+ GenCallingConv,
+ GenClangAttrClasses,
+ GenClangAttrImpl,
+ GenClangAttrList,
+ GenClangAttrPCHRead,
+ GenClangAttrPCHWrite,
+ GenClangDiagsDefs,
+ GenClangDiagGroups,
+ GenClangDeclNodes,
+ GenClangStmtNodes,
+ GenDAGISel,
+ GenFastISel,
+ GenOptParserDefs, GenOptParserImpl,
+ GenSubtarget,
+ GenIntrinsic,
+ GenTgtIntrinsic,
+ GenLLVMCConf,
+ GenEDInfo,
+ GenArmNeon,
+ GenArmNeonSema,
+ PrintEnums
+};
+
+namespace {
+ cl::opt<ActionType>
+ Action(cl::desc("Action to perform:"),
+ cl::values(clEnumValN(PrintRecords, "print-records",
+ "Print all records to stdout (default)"),
+ clEnumValN(GenEmitter, "gen-emitter",
+ "Generate machine code emitter"),
+ clEnumValN(GenRegisterEnums, "gen-register-enums",
+ "Generate enum values for registers"),
+ clEnumValN(GenRegister, "gen-register-desc",
+ "Generate a register info description"),
+ clEnumValN(GenRegisterHeader, "gen-register-desc-header",
+ "Generate a register info description header"),
+ clEnumValN(GenInstrEnums, "gen-instr-enums",
+ "Generate enum values for instructions"),
+ clEnumValN(GenInstrs, "gen-instr-desc",
+ "Generate instruction descriptions"),
+ clEnumValN(GenCallingConv, "gen-callingconv",
+ "Generate calling convention descriptions"),
+ clEnumValN(GenAsmWriter, "gen-asm-writer",
+ "Generate assembly writer"),
+ clEnumValN(GenARMDecoder, "gen-arm-decoder",
+ "Generate decoders for ARM/Thumb"),
+ clEnumValN(GenDisassembler, "gen-disassembler",
+ "Generate disassembler"),
+ clEnumValN(GenAsmMatcher, "gen-asm-matcher",
+ "Generate assembly instruction matcher"),
+ clEnumValN(GenDAGISel, "gen-dag-isel",
+ "Generate a DAG instruction selector"),
+ clEnumValN(GenFastISel, "gen-fast-isel",
+ "Generate a \"fast\" instruction selector"),
+ clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
+ "Generate option definitions"),
+ clEnumValN(GenOptParserImpl, "gen-opt-parser-impl",
+ "Generate option parser implementation"),
+ clEnumValN(GenSubtarget, "gen-subtarget",
+ "Generate subtarget enumerations"),
+ clEnumValN(GenIntrinsic, "gen-intrinsic",
+ "Generate intrinsic information"),
+ clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic",
+ "Generate target intrinsic information"),
+ clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
+ "Generate clang attribute clases"),
+ clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl",
+ "Generate clang attribute implementations"),
+ clEnumValN(GenClangAttrList, "gen-clang-attr-list",
+ "Generate a clang attribute list"),
+ clEnumValN(GenClangAttrPCHRead, "gen-clang-attr-pch-read",
+ "Generate clang PCH attribute reader"),
+ clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write",
+ "Generate clang PCH attribute writer"),
+ clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
+ "Generate Clang diagnostics definitions"),
+ clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
+ "Generate Clang diagnostic groups"),
+ clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes",
+ "Generate Clang AST statement nodes"),
+ clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
+ "Generate Clang AST statement nodes"),
+ clEnumValN(GenLLVMCConf, "gen-llvmc",
+ "Generate LLVMC configuration library"),
+ clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info",
+ "Generate enhanced disassembly info"),
+ clEnumValN(GenArmNeon, "gen-arm-neon",
+ "Generate arm_neon.h for clang"),
+ clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
+ "Generate ARM NEON sema support for clang"),
+ clEnumValN(PrintEnums, "print-enums",
+ "Print enum values for a class"),
+ clEnumValEnd));
+
+ cl::opt<std::string>
+ Class("class", cl::desc("Print Enum list for this class"),
+ cl::value_desc("class name"));
+
+ cl::opt<std::string>
+ OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
+ cl::init("-"));
+
+ cl::opt<std::string>
+ InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
+
+ cl::list<std::string>
+ IncludeDirs("I", cl::desc("Directory of include files"),
+ cl::value_desc("directory"), cl::Prefix);
+
+ cl::opt<std::string>
+ ClangComponent("clang-component",
+ cl::desc("Only use warnings from specified component"),
+ cl::value_desc("component"), cl::Hidden);
+}
+
+
+// FIXME: Eliminate globals from tblgen.
+RecordKeeper llvm::Records;
+
+static SourceMgr SrcMgr;
+
+void llvm::PrintError(SMLoc ErrorLoc, const std::string &Msg) {
+ SrcMgr.PrintMessage(ErrorLoc, Msg, "error");
+}
+
+
+
+/// ParseFile - this function begins the parsing of the specified tablegen
+/// file.
+static bool ParseFile(const std::string &Filename,
+ const std::vector<std::string> &IncludeDirs,
+ SourceMgr &SrcMgr) {
+ std::string ErrorStr;
+ MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr);
+ if (F == 0) {
+ errs() << "Could not open input file '" << Filename << "': "
+ << ErrorStr <<"\n";
+ return true;
+ }
+
+ // Tell SrcMgr about this buffer, which is what TGParser will pick up.
+ SrcMgr.AddNewSourceBuffer(F, SMLoc());
+
+ // Record the location of the include directory so that the lexer can find
+ // it later.
+ SrcMgr.setIncludeDirs(IncludeDirs);
+
+ TGParser Parser(SrcMgr);
+
+ return Parser.ParseFile();
+}
+
+int main(int argc, char **argv) {
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ cl::ParseCommandLineOptions(argc, argv);
+
+
+ // Parse the input file.
+ if (ParseFile(InputFilename, IncludeDirs, SrcMgr))
+ return 1;
+
+ std::string Error;
+ tool_output_file Out(OutputFilename.c_str(), Error);
+ if (!Error.empty()) {
+ errs() << argv[0] << ": error opening " << OutputFilename
+ << ":" << Error << "\n";
+ return 1;
+ }
+
+ try {
+ switch (Action) {
+ case PrintRecords:
+ Out.os() << Records; // No argument, dump all contents
+ break;
+ case GenEmitter:
+ CodeEmitterGen(Records).run(Out.os());
+ break;
+
+ case GenRegisterEnums:
+ RegisterInfoEmitter(Records).runEnums(Out.os());
+ break;
+ case GenRegister:
+ RegisterInfoEmitter(Records).run(Out.os());
+ break;
+ case GenRegisterHeader:
+ RegisterInfoEmitter(Records).runHeader(Out.os());
+ break;
+ case GenInstrEnums:
+ InstrEnumEmitter(Records).run(Out.os());
+ break;
+ case GenInstrs:
+ InstrInfoEmitter(Records).run(Out.os());
+ break;
+ case GenCallingConv:
+ CallingConvEmitter(Records).run(Out.os());
+ break;
+ case GenAsmWriter:
+ AsmWriterEmitter(Records).run(Out.os());
+ break;
+ case GenARMDecoder:
+ ARMDecoderEmitter(Records).run(Out.os());
+ break;
+ case GenAsmMatcher:
+ AsmMatcherEmitter(Records).run(Out.os());
+ break;
+ case GenClangAttrClasses:
+ ClangAttrClassEmitter(Records).run(Out.os());
+ break;
+ case GenClangAttrImpl:
+ ClangAttrImplEmitter(Records).run(Out.os());
+ break;
+ case GenClangAttrList:
+ ClangAttrListEmitter(Records).run(Out.os());
+ break;
+ case GenClangAttrPCHRead:
+ ClangAttrPCHReadEmitter(Records).run(Out.os());
+ break;
+ case GenClangAttrPCHWrite:
+ ClangAttrPCHWriteEmitter(Records).run(Out.os());
+ break;
+ case GenClangDiagsDefs:
+ ClangDiagsDefsEmitter(Records, ClangComponent).run(Out.os());
+ break;
+ case GenClangDiagGroups:
+ ClangDiagGroupsEmitter(Records).run(Out.os());
+ break;
+ case GenClangDeclNodes:
+ ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out.os());
+ ClangDeclContextEmitter(Records).run(Out.os());
+ break;
+ case GenClangStmtNodes:
+ ClangASTNodesEmitter(Records, "Stmt", "").run(Out.os());
+ break;
+ case GenDisassembler:
+ DisassemblerEmitter(Records).run(Out.os());
+ break;
+ case GenOptParserDefs:
+ OptParserEmitter(Records, true).run(Out.os());
+ break;
+ case GenOptParserImpl:
+ OptParserEmitter(Records, false).run(Out.os());
+ break;
+ case GenDAGISel:
+ DAGISelEmitter(Records).run(Out.os());
+ break;
+ case GenFastISel:
+ FastISelEmitter(Records).run(Out.os());
+ break;
+ case GenSubtarget:
+ SubtargetEmitter(Records).run(Out.os());
+ break;
+ case GenIntrinsic:
+ IntrinsicEmitter(Records).run(Out.os());
+ break;
+ case GenTgtIntrinsic:
+ IntrinsicEmitter(Records, true).run(Out.os());
+ break;
+ case GenLLVMCConf:
+ LLVMCConfigurationEmitter(Records).run(Out.os());
+ break;
+ case GenEDInfo:
+ EDEmitter(Records).run(Out.os());
+ break;
+ case GenArmNeon:
+ NeonEmitter(Records).run(Out.os());
+ break;
+ case GenArmNeonSema:
+ NeonEmitter(Records).runHeader(Out.os());
+ break;
+ case PrintEnums:
+ {
+ std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
+ for (unsigned i = 0, e = Recs.size(); i != e; ++i)
+ Out.os() << Recs[i]->getName() << ", ";
+ Out.os() << "\n";
+ break;
+ }
+ default:
+ assert(1 && "Invalid Action");
+ return 1;
+ }
+
+ // Declare success.
+ Out.keep();
+ return 0;
+
+ } catch (const TGError &Error) {
+ errs() << argv[0] << ": error:\n";
+ PrintError(Error.getLoc(), Error.getMessage());
+
+ } catch (const std::string &Error) {
+ errs() << argv[0] << ": " << Error << "\n";
+ } catch (const char *Error) {
+ errs() << argv[0] << ": " << Error << "\n";
+ } catch (...) {
+ errs() << argv[0] << ": Unknown unexpected exception occurred.\n";
+ }
+
+ return 1;
+}
diff --git a/contrib/llvm/utils/TableGen/TableGenBackend.cpp b/contrib/llvm/utils/TableGen/TableGenBackend.cpp
new file mode 100644
index 0000000..b3e33b5
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/TableGenBackend.cpp
@@ -0,0 +1,25 @@
+//===- TableGenBackend.cpp - Base class for TableGen Backends ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides useful services for TableGen backends...
+//
+//===----------------------------------------------------------------------===//
+
+#include "TableGenBackend.h"
+#include "Record.h"
+using namespace llvm;
+
+void TableGenBackend::EmitSourceFileHeader(const std::string &Desc,
+ raw_ostream &OS) const {
+ OS << "//===- TableGen'erated file -------------------------------------*-"
+ " C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate"
+ "d file, do not edit!\n//\n//===------------------------------------"
+ "----------------------------------===//\n\n";
+}
+
diff --git a/contrib/llvm/utils/TableGen/TableGenBackend.h b/contrib/llvm/utils/TableGen/TableGenBackend.h
new file mode 100644
index 0000000..9c2b948
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/TableGenBackend.h
@@ -0,0 +1,43 @@
+//===- TableGenBackend.h - Base class for TableGen Backends -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The TableGenBackend class is provided as a common interface for all TableGen
+// backends. It provides useful services and an standardized interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TABLEGENBACKEND_H
+#define TABLEGENBACKEND_H
+
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace llvm {
+
+class Record;
+class RecordKeeper;
+
+struct TableGenBackend {
+ virtual ~TableGenBackend() {}
+
+ // run - All TableGen backends should implement the run method, which should
+ // be the main entry point.
+ virtual void run(raw_ostream &OS) = 0;
+
+
+public: // Useful helper routines...
+ /// EmitSourceFileHeader - Output a LLVM style file header to the specified
+ /// ostream.
+ void EmitSourceFileHeader(const std::string &Desc, raw_ostream &OS) const;
+
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerShared.h b/contrib/llvm/utils/TableGen/X86DisassemblerShared.h
new file mode 100644
index 0000000..0417e9d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86DisassemblerShared.h
@@ -0,0 +1,38 @@
+//===- X86DisassemblerShared.h - Emitter shared header ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef X86DISASSEMBLERSHARED_H
+#define X86DISASSEMBLERSHARED_H
+
+#include <string>
+#include <string.h>
+
+#define INSTRUCTION_SPECIFIER_FIELDS \
+ bool filtered; \
+ InstructionContext insnContext; \
+ std::string name; \
+ \
+ InstructionSpecifier() { \
+ filtered = false; \
+ insnContext = IC; \
+ name = ""; \
+ modifierType = MODIFIER_NONE; \
+ modifierBase = 0; \
+ memset(operands, 0, sizeof(operands)); \
+ }
+
+#define INSTRUCTION_IDS \
+ InstrUID instructionIDs[256];
+
+#include "../../lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h"
+
+#undef INSTRUCTION_SPECIFIER_FIELDS
+#undef INSTRUCTION_IDS
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp
new file mode 100644
index 0000000..2176224
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp
@@ -0,0 +1,603 @@
+//===- X86DisassemblerTables.cpp - Disassembler tables ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler Emitter.
+// It contains the implementation of the disassembler tables.
+// Documentation for the disassembler emitter in general can be found in
+// X86DisasemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86DisassemblerShared.h"
+#include "X86DisassemblerTables.h"
+
+#include "TableGenBackend.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace X86Disassembler;
+
+/// inheritsFrom - Indicates whether all instructions in one class also belong
+/// to another class.
+///
+/// @param child - The class that may be the subset
+/// @param parent - The class that may be the superset
+/// @return - True if child is a subset of parent, false otherwise.
+static inline bool inheritsFrom(InstructionContext child,
+ InstructionContext parent) {
+ if (child == parent)
+ return true;
+
+ switch (parent) {
+ case IC:
+ return true;
+ case IC_64BIT:
+ return(inheritsFrom(child, IC_64BIT_REXW) ||
+ inheritsFrom(child, IC_64BIT_OPSIZE) ||
+ inheritsFrom(child, IC_64BIT_XD) ||
+ inheritsFrom(child, IC_64BIT_XS));
+ case IC_OPSIZE:
+ return(inheritsFrom(child, IC_64BIT_OPSIZE));
+ case IC_XD:
+ return(inheritsFrom(child, IC_64BIT_XD));
+ case IC_XS:
+ return(inheritsFrom(child, IC_64BIT_XS));
+ case IC_64BIT_REXW:
+ return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
+ inheritsFrom(child, IC_64BIT_REXW_XD) ||
+ inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
+ case IC_64BIT_OPSIZE:
+ return(inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
+ case IC_64BIT_XD:
+ return(inheritsFrom(child, IC_64BIT_REXW_XD));
+ case IC_64BIT_XS:
+ return(inheritsFrom(child, IC_64BIT_REXW_XS));
+ case IC_64BIT_REXW_XD:
+ return false;
+ case IC_64BIT_REXW_XS:
+ return false;
+ case IC_64BIT_REXW_OPSIZE:
+ return false;
+ default:
+ return false;
+ }
+}
+
+/// outranks - Indicates whether, if an instruction has two different applicable
+/// classes, which class should be preferred when performing decode. This
+/// imposes a total ordering (ties are resolved toward "lower")
+///
+/// @param upper - The class that may be preferable
+/// @param lower - The class that may be less preferable
+/// @return - True if upper is to be preferred, false otherwise.
+static inline bool outranks(InstructionContext upper,
+ InstructionContext lower) {
+ assert(upper < IC_max);
+ assert(lower < IC_max);
+
+#define ENUM_ENTRY(n, r, d) r,
+ static int ranks[IC_max] = {
+ INSTRUCTION_CONTEXTS
+ };
+#undef ENUM_ENTRY
+
+ return (ranks[upper] > ranks[lower]);
+}
+
+/// stringForContext - Returns a string containing the name of a particular
+/// InstructionContext, usually for diagnostic purposes.
+///
+/// @param insnContext - The instruction class to transform to a string.
+/// @return - A statically-allocated string constant that contains the
+/// name of the instruction class.
+static inline const char* stringForContext(InstructionContext insnContext) {
+ switch (insnContext) {
+ default:
+ llvm_unreachable("Unhandled instruction class");
+#define ENUM_ENTRY(n, r, d) case n: return #n; break;
+ INSTRUCTION_CONTEXTS
+#undef ENUM_ENTRY
+ }
+
+ return 0;
+}
+
+/// stringForOperandType - Like stringForContext, but for OperandTypes.
+static inline const char* stringForOperandType(OperandType type) {
+ switch (type) {
+ default:
+ llvm_unreachable("Unhandled type");
+#define ENUM_ENTRY(i, d) case i: return #i;
+ TYPES
+#undef ENUM_ENTRY
+ }
+}
+
+/// stringForOperandEncoding - like stringForContext, but for
+/// OperandEncodings.
+static inline const char* stringForOperandEncoding(OperandEncoding encoding) {
+ switch (encoding) {
+ default:
+ llvm_unreachable("Unhandled encoding");
+#define ENUM_ENTRY(i, d) case i: return #i;
+ ENCODINGS
+#undef ENUM_ENTRY
+ }
+}
+
+void DisassemblerTables::emitOneID(raw_ostream &o,
+ uint32_t &i,
+ InstrUID id,
+ bool addComma) const {
+ if (id)
+ o.indent(i * 2) << format("0x%hx", id);
+ else
+ o.indent(i * 2) << 0;
+
+ if (addComma)
+ o << ", ";
+ else
+ o << " ";
+
+ o << "/* ";
+ o << InstructionSpecifiers[id].name;
+ o << "*/";
+
+ o << "\n";
+}
+
+/// emitEmptyTable - Emits the modRMEmptyTable, which is used as a ID table by
+/// all ModR/M decisions for instructions that are invalid for all possible
+/// ModR/M byte values.
+///
+/// @param o - The output stream on which to emit the table.
+/// @param i - The indentation level for that output stream.
+static void emitEmptyTable(raw_ostream &o, uint32_t &i)
+{
+ o.indent(i * 2) << "static InstrUID modRMEmptyTable[1] = { 0 };" << "\n";
+ o << "\n";
+}
+
+/// getDecisionType - Determines whether a ModRM decision with 255 entries can
+/// be compacted by eliminating redundant information.
+///
+/// @param decision - The decision to be compacted.
+/// @return - The compactest available representation for the decision.
+static ModRMDecisionType getDecisionType(ModRMDecision &decision)
+{
+ bool satisfiesOneEntry = true;
+ bool satisfiesSplitRM = true;
+
+ uint16_t index;
+
+ for (index = 0; index < 256; ++index) {
+ if (decision.instructionIDs[index] != decision.instructionIDs[0])
+ satisfiesOneEntry = false;
+
+ if (((index & 0xc0) == 0xc0) &&
+ (decision.instructionIDs[index] != decision.instructionIDs[0xc0]))
+ satisfiesSplitRM = false;
+
+ if (((index & 0xc0) != 0xc0) &&
+ (decision.instructionIDs[index] != decision.instructionIDs[0x00]))
+ satisfiesSplitRM = false;
+ }
+
+ if (satisfiesOneEntry)
+ return MODRM_ONEENTRY;
+
+ if (satisfiesSplitRM)
+ return MODRM_SPLITRM;
+
+ return MODRM_FULL;
+}
+
+/// stringForDecisionType - Returns a statically-allocated string corresponding
+/// to a particular decision type.
+///
+/// @param dt - The decision type.
+/// @return - A pointer to the statically-allocated string (e.g.,
+/// "MODRM_ONEENTRY" for MODRM_ONEENTRY).
+static const char* stringForDecisionType(ModRMDecisionType dt)
+{
+#define ENUM_ENTRY(n) case n: return #n;
+ switch (dt) {
+ default:
+ llvm_unreachable("Unknown decision type");
+ MODRMTYPES
+ };
+#undef ENUM_ENTRY
+}
+
+/// stringForModifierType - Returns a statically-allocated string corresponding
+/// to an opcode modifier type.
+///
+/// @param mt - The modifier type.
+/// @return - A pointer to the statically-allocated string (e.g.,
+/// "MODIFIER_NONE" for MODIFIER_NONE).
+static const char* stringForModifierType(ModifierType mt)
+{
+#define ENUM_ENTRY(n) case n: return #n;
+ switch(mt) {
+ default:
+ llvm_unreachable("Unknown modifier type");
+ MODIFIER_TYPES
+ };
+#undef ENUM_ENTRY
+}
+
+DisassemblerTables::DisassemblerTables() {
+ unsigned i;
+
+ for (i = 0; i < 4; i++) {
+ Tables[i] = new ContextDecision;
+ memset(Tables[i], 0, sizeof(ContextDecision));
+ }
+
+ HasConflicts = false;
+}
+
+DisassemblerTables::~DisassemblerTables() {
+ unsigned i;
+
+ for (i = 0; i < 4; i++)
+ delete Tables[i];
+}
+
+void DisassemblerTables::emitModRMDecision(raw_ostream &o1,
+ raw_ostream &o2,
+ uint32_t &i1,
+ uint32_t &i2,
+ ModRMDecision &decision)
+ const {
+ static uint64_t sTableNumber = 0;
+ uint64_t thisTableNumber = sTableNumber;
+ ModRMDecisionType dt = getDecisionType(decision);
+ uint16_t index;
+
+ if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0)
+ {
+ o2.indent(i2) << "{ /* ModRMDecision */" << "\n";
+ i2++;
+
+ o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
+ o2.indent(i2) << "modRMEmptyTable";
+
+ i2--;
+ o2.indent(i2) << "}";
+ return;
+ }
+
+ o1.indent(i1) << "static InstrUID modRMTable" << thisTableNumber;
+
+ switch (dt) {
+ default:
+ llvm_unreachable("Unknown decision type");
+ case MODRM_ONEENTRY:
+ o1 << "[1]";
+ break;
+ case MODRM_SPLITRM:
+ o1 << "[2]";
+ break;
+ case MODRM_FULL:
+ o1 << "[256]";
+ break;
+ }
+
+ o1 << " = {" << "\n";
+ i1++;
+
+ switch (dt) {
+ default:
+ llvm_unreachable("Unknown decision type");
+ case MODRM_ONEENTRY:
+ emitOneID(o1, i1, decision.instructionIDs[0], false);
+ break;
+ case MODRM_SPLITRM:
+ emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00
+ emitOneID(o1, i1, decision.instructionIDs[0xc0], false); // mod = 0b11
+ break;
+ case MODRM_FULL:
+ for (index = 0; index < 256; ++index)
+ emitOneID(o1, i1, decision.instructionIDs[index], index < 255);
+ break;
+ }
+
+ i1--;
+ o1.indent(i1) << "};" << "\n";
+ o1 << "\n";
+
+ o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n";
+ i2++;
+
+ o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
+ o2.indent(i2) << "modRMTable" << sTableNumber << "\n";
+
+ i2--;
+ o2.indent(i2) << "}";
+
+ ++sTableNumber;
+}
+
+void DisassemblerTables::emitOpcodeDecision(
+ raw_ostream &o1,
+ raw_ostream &o2,
+ uint32_t &i1,
+ uint32_t &i2,
+ OpcodeDecision &decision) const {
+ uint16_t index;
+
+ o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n";
+ i2++;
+ o2.indent(i2) << "{" << "\n";
+ i2++;
+
+ for (index = 0; index < 256; ++index) {
+ o2.indent(i2);
+
+ o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n";
+
+ emitModRMDecision(o1, o2, i1, i2, decision.modRMDecisions[index]);
+
+ if (index < 255)
+ o2 << ",";
+
+ o2 << "\n";
+ }
+
+ i2--;
+ o2.indent(i2) << "}" << "\n";
+ i2--;
+ o2.indent(i2) << "}" << "\n";
+}
+
+void DisassemblerTables::emitContextDecision(
+ raw_ostream &o1,
+ raw_ostream &o2,
+ uint32_t &i1,
+ uint32_t &i2,
+ ContextDecision &decision,
+ const char* name) const {
+ o2.indent(i2) << "struct ContextDecision " << name << " = {" << "\n";
+ i2++;
+ o2.indent(i2) << "{ /* opcodeDecisions */" << "\n";
+ i2++;
+
+ unsigned index;
+
+ for (index = 0; index < IC_max; ++index) {
+ o2.indent(i2) << "/* ";
+ o2 << stringForContext((InstructionContext)index);
+ o2 << " */";
+ o2 << "\n";
+
+ emitOpcodeDecision(o1, o2, i1, i2, decision.opcodeDecisions[index]);
+
+ if (index + 1 < IC_max)
+ o2 << ", ";
+ }
+
+ i2--;
+ o2.indent(i2) << "}" << "\n";
+ i2--;
+ o2.indent(i2) << "};" << "\n";
+}
+
+void DisassemblerTables::emitInstructionInfo(raw_ostream &o, uint32_t &i)
+ const {
+ o.indent(i * 2) << "struct InstructionSpecifier ";
+ o << INSTRUCTIONS_STR << "[";
+ o << InstructionSpecifiers.size();
+ o << "] = {" << "\n";
+
+ i++;
+
+ uint16_t numInstructions = InstructionSpecifiers.size();
+ uint16_t index, operandIndex;
+
+ for (index = 0; index < numInstructions; ++index) {
+ o.indent(i * 2) << "{ /* " << index << " */" << "\n";
+ i++;
+
+ o.indent(i * 2) <<
+ stringForModifierType(InstructionSpecifiers[index].modifierType);
+ o << "," << "\n";
+
+ o.indent(i * 2) << "0x";
+ o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase);
+ o << "," << "\n";
+
+ o.indent(i * 2) << "{" << "\n";
+ i++;
+
+ for (operandIndex = 0; operandIndex < X86_MAX_OPERANDS; ++operandIndex) {
+ o.indent(i * 2) << "{ ";
+ o << stringForOperandEncoding(InstructionSpecifiers[index]
+ .operands[operandIndex]
+ .encoding);
+ o << ", ";
+ o << stringForOperandType(InstructionSpecifiers[index]
+ .operands[operandIndex]
+ .type);
+ o << " }";
+
+ if (operandIndex < X86_MAX_OPERANDS - 1)
+ o << ",";
+
+ o << "\n";
+ }
+
+ i--;
+ o.indent(i * 2) << "}," << "\n";
+
+ o.indent(i * 2) << "\"" << InstructionSpecifiers[index].name << "\"";
+ o << "\n";
+
+ i--;
+ o.indent(i * 2) << "}";
+
+ if (index + 1 < numInstructions)
+ o << ",";
+
+ o << "\n";
+ }
+
+ i--;
+ o.indent(i * 2) << "};" << "\n";
+}
+
+void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const {
+ uint16_t index;
+
+ o.indent(i * 2) << "InstructionContext ";
+ o << CONTEXTS_STR << "[256] = {" << "\n";
+ i++;
+
+ for (index = 0; index < 256; ++index) {
+ o.indent(i * 2);
+
+ if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
+ o << "IC_64BIT_REXW_XS";
+ else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
+ o << "IC_64BIT_REXW_XD";
+ else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
+ (index & ATTR_OPSIZE))
+ o << "IC_64BIT_REXW_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XS))
+ o << "IC_64BIT_XS";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XD))
+ o << "IC_64BIT_XD";
+ else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE))
+ o << "IC_64BIT_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_REXW))
+ o << "IC_64BIT_REXW";
+ else if ((index & ATTR_64BIT))
+ o << "IC_64BIT";
+ else if (index & ATTR_XS)
+ o << "IC_XS";
+ else if (index & ATTR_XD)
+ o << "IC_XD";
+ else if (index & ATTR_OPSIZE)
+ o << "IC_OPSIZE";
+ else
+ o << "IC";
+
+ if (index < 255)
+ o << ",";
+ else
+ o << " ";
+
+ o << " /* " << index << " */";
+
+ o << "\n";
+ }
+
+ i--;
+ o.indent(i * 2) << "};" << "\n";
+}
+
+void DisassemblerTables::emitContextDecisions(raw_ostream &o1,
+ raw_ostream &o2,
+ uint32_t &i1,
+ uint32_t &i2)
+ const {
+ emitContextDecision(o1, o2, i1, i2, *Tables[0], ONEBYTE_STR);
+ emitContextDecision(o1, o2, i1, i2, *Tables[1], TWOBYTE_STR);
+ emitContextDecision(o1, o2, i1, i2, *Tables[2], THREEBYTE38_STR);
+ emitContextDecision(o1, o2, i1, i2, *Tables[3], THREEBYTE3A_STR);
+}
+
+void DisassemblerTables::emit(raw_ostream &o) const {
+ uint32_t i1 = 0;
+ uint32_t i2 = 0;
+
+ std::string s1;
+ std::string s2;
+
+ raw_string_ostream o1(s1);
+ raw_string_ostream o2(s2);
+
+ emitInstructionInfo(o, i2);
+ o << "\n";
+
+ emitContextTable(o, i2);
+ o << "\n";
+
+ emitEmptyTable(o1, i1);
+ emitContextDecisions(o1, o2, i1, i2);
+
+ o << o1.str();
+ o << "\n";
+ o << o2.str();
+ o << "\n";
+ o << "\n";
+}
+
+void DisassemblerTables::setTableFields(ModRMDecision &decision,
+ const ModRMFilter &filter,
+ InstrUID uid,
+ uint8_t opcode) {
+ unsigned index;
+
+ for (index = 0; index < 256; ++index) {
+ if (filter.accepts(index)) {
+ if (decision.instructionIDs[index] == uid)
+ continue;
+
+ if (decision.instructionIDs[index] != 0) {
+ InstructionSpecifier &newInfo =
+ InstructionSpecifiers[uid];
+ InstructionSpecifier &previousInfo =
+ InstructionSpecifiers[decision.instructionIDs[index]];
+
+ if(newInfo.filtered)
+ continue; // filtered instructions get lowest priority
+
+ if(previousInfo.name == "NOOP")
+ continue; // special case for XCHG32ar and NOOP
+
+ if (outranks(previousInfo.insnContext, newInfo.insnContext))
+ continue;
+
+ if (previousInfo.insnContext == newInfo.insnContext &&
+ !previousInfo.filtered) {
+ errs() << "Error: Primary decode conflict: ";
+ errs() << newInfo.name << " would overwrite " << previousInfo.name;
+ errs() << "\n";
+ errs() << "ModRM " << index << "\n";
+ errs() << "Opcode " << (uint16_t)opcode << "\n";
+ errs() << "Context " << stringForContext(newInfo.insnContext) << "\n";
+ HasConflicts = true;
+ }
+ }
+
+ decision.instructionIDs[index] = uid;
+ }
+ }
+}
+
+void DisassemblerTables::setTableFields(OpcodeType type,
+ InstructionContext insnContext,
+ uint8_t opcode,
+ const ModRMFilter &filter,
+ InstrUID uid) {
+ unsigned index;
+
+ ContextDecision &decision = *Tables[type];
+
+ for (index = 0; index < IC_max; ++index) {
+ if (inheritsFrom((InstructionContext)index,
+ InstructionSpecifiers[uid].insnContext))
+ setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
+ filter,
+ uid,
+ opcode);
+ }
+}
diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.h b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h
new file mode 100644
index 0000000..08eba01
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h
@@ -0,0 +1,291 @@
+//===- X86DisassemblerTables.h - Disassembler tables ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler Emitter.
+// It contains the interface of the disassembler tables.
+// Documentation for the disassembler emitter in general can be found in
+// X86DisasemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef X86DISASSEMBLERTABLES_H
+#define X86DISASSEMBLERTABLES_H
+
+#include "X86DisassemblerShared.h"
+#include "X86ModRMFilters.h"
+
+#include "llvm/Support/raw_ostream.h"
+
+#include <vector>
+
+namespace llvm {
+
+namespace X86Disassembler {
+
+/// DisassemblerTables - Encapsulates all the decode tables being generated by
+/// the table emitter. Contains functions to populate the tables as well as
+/// to emit them as hierarchical C structures suitable for consumption by the
+/// runtime.
+class DisassemblerTables {
+private:
+ /// The decoder tables. There is one for each opcode type:
+ /// [0] one-byte opcodes
+ /// [1] two-byte opcodes of the form 0f __
+ /// [2] three-byte opcodes of the form 0f 38 __
+ /// [3] three-byte opcodes of the form 0f 3a __
+ ContextDecision* Tables[4];
+
+ /// The instruction information table
+ std::vector<InstructionSpecifier> InstructionSpecifiers;
+
+ /// True if there are primary decode conflicts in the instruction set
+ bool HasConflicts;
+
+ /// emitOneID - Emits a table entry for a single instruction entry, at the
+ /// innermost level of the structure hierarchy. The entry is printed out
+ /// in the format "nnnn, /* MNEMONIC */" where nnnn is the ID in decimal,
+ /// the comma is printed if addComma is true, and the menonic is the name
+ /// of the instruction as listed in the LLVM tables.
+ ///
+ /// @param o - The output stream to print the entry on.
+ /// @param i - The indentation level for o.
+ /// @param id - The unique ID of the instruction to print.
+ /// @param addComma - Whether or not to print a comma after the ID. True if
+ /// additional items will follow.
+ void emitOneID(raw_ostream &o,
+ uint32_t &i,
+ InstrUID id,
+ bool addComma) const;
+
+ /// emitModRMDecision - Emits a table of entries corresponding to a single
+ /// ModR/M decision. Compacts the ModR/M decision if possible. ModR/M
+ /// decisions are printed as:
+ ///
+ /// { /* struct ModRMDecision */
+ /// TYPE,
+ /// modRMTablennnn
+ /// }
+ ///
+ /// where nnnn is a unique ID for the corresponding table of IDs.
+ /// TYPE indicates whether the table has one entry that is the same
+ /// regardless of ModR/M byte, two entries - one for bytes 0x00-0xbf and one
+ /// for bytes 0xc0-0xff -, or 256 entries, one for each possible byte.
+ /// nnnn is the number of a table for looking up these values. The tables
+ /// are writen separately so that tables consisting entirely of zeros will
+ /// not be duplicated. (These all have the name modRMEmptyTable.) A table
+ /// is printed as:
+ ///
+ /// InstrUID modRMTablennnn[k] = {
+ /// nnnn, /* MNEMONIC */
+ /// ...
+ /// nnnn /* MNEMONIC */
+ /// };
+ ///
+ /// @param o1 - The output stream to print the ID table to.
+ /// @param o2 - The output stream to print the decision structure to.
+ /// @param i1 - The indentation level to use with stream o1.
+ /// @param i2 - The indentation level to use with stream o2.
+ /// @param decision - The ModR/M decision to emit. This decision has 256
+ /// entries - emitModRMDecision decides how to compact it.
+ void emitModRMDecision(raw_ostream &o1,
+ raw_ostream &o2,
+ uint32_t &i1,
+ uint32_t &i2,
+ ModRMDecision &decision) const;
+
+ /// emitOpcodeDecision - Emits an OpcodeDecision and all its subsidiary ModR/M
+ /// decisions. An OpcodeDecision is printed as:
+ ///
+ /// { /* struct OpcodeDecision */
+ /// /* 0x00 */
+ /// { /* struct ModRMDecision */
+ /// ...
+ /// }
+ /// ...
+ /// }
+ ///
+ /// where the ModRMDecision structure is printed as described in the
+ /// documentation for emitModRMDecision(). emitOpcodeDecision() passes on a
+ /// stream and indent level for the UID tables generated by
+ /// emitModRMDecision(), but does not use them itself.
+ ///
+ /// @param o1 - The output stream to print the ID tables generated by
+ /// emitModRMDecision() to.
+ /// @param o2 - The output stream for the decision structure itself.
+ /// @param i1 - The indent level to use with stream o1.
+ /// @param i2 - The indent level to use with stream o2.
+ /// @param decision - The OpcodeDecision to emit along with its subsidiary
+ /// structures.
+ void emitOpcodeDecision(raw_ostream &o1,
+ raw_ostream &o2,
+ uint32_t &i1,
+ uint32_t &i2,
+ OpcodeDecision &decision) const;
+
+ /// emitContextDecision - Emits a ContextDecision and all its subsidiary
+ /// Opcode and ModRMDecisions. A ContextDecision is printed as:
+ ///
+ /// struct ContextDecision NAME = {
+ /// { /* OpcodeDecisions */
+ /// /* IC */
+ /// { /* struct OpcodeDecision */
+ /// ...
+ /// },
+ /// ...
+ /// }
+ /// }
+ ///
+ /// NAME is the name of the ContextDecision (typically one of the four names
+ /// ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, and THREEBYTE3A_SYM from
+ /// X86DisassemblerDecoderCommon.h).
+ /// IC is one of the contexts in InstructionContext. There is an opcode
+ /// decision for each possible context.
+ /// The OpcodeDecision structures are printed as described in the
+ /// documentation for emitOpcodeDecision.
+ ///
+ /// @param o1 - The output stream to print the ID tables generated by
+ /// emitModRMDecision() to.
+ /// @param o2 - The output stream to print the decision structure to.
+ /// @param i1 - The indent level to use with stream o1.
+ /// @param i2 - The indent level to use with stream o2.
+ /// @param decision - The ContextDecision to emit along with its subsidiary
+ /// structures.
+ /// @param name - The name for the ContextDecision.
+ void emitContextDecision(raw_ostream &o1,
+ raw_ostream &o2,
+ uint32_t &i1,
+ uint32_t &i2,
+ ContextDecision &decision,
+ const char* name) const;
+
+ /// emitInstructionInfo - Prints the instruction specifier table, which has
+ /// one entry for each instruction, and contains name and operand
+ /// information. This table is printed as:
+ ///
+ /// struct InstructionSpecifier CONTEXTS_SYM[k] = {
+ /// {
+ /// /* nnnn */
+ /// "MNEMONIC",
+ /// 0xnn,
+ /// {
+ /// {
+ /// ENCODING,
+ /// TYPE
+ /// },
+ /// ...
+ /// }
+ /// },
+ /// };
+ ///
+ /// k is the total number of instructions.
+ /// nnnn is the ID of the current instruction (0-based). This table
+ /// includes entries for non-instructions like PHINODE.
+ /// 0xnn is the lowest possible opcode for the current instruction, used for
+ /// AddRegFrm instructions to compute the operand's value.
+ /// ENCODING and TYPE describe the encoding and type for a single operand.
+ ///
+ /// @param o - The output stream to which the instruction table should be
+ /// written.
+ /// @param i - The indent level for use with the stream.
+ void emitInstructionInfo(raw_ostream &o, uint32_t &i) const;
+
+ /// emitContextTable - Prints the table that is used to translate from an
+ /// instruction attribute mask to an instruction context. This table is
+ /// printed as:
+ ///
+ /// InstructionContext CONTEXTS_STR[256] = {
+ /// IC, /* 0x00 */
+ /// ...
+ /// };
+ ///
+ /// IC is the context corresponding to the mask 0x00, and there are 256
+ /// possible masks.
+ ///
+ /// @param o - The output stream to which the context table should be written.
+ /// @param i - The indent level for use with the stream.
+ void emitContextTable(raw_ostream &o, uint32_t &i) const;
+
+ /// emitContextDecisions - Prints all four ContextDecision structures using
+ /// emitContextDecision().
+ ///
+ /// @param o1 - The output stream to print the ID tables generated by
+ /// emitModRMDecision() to.
+ /// @param o2 - The output stream to print the decision structures to.
+ /// @param i1 - The indent level to use with stream o1.
+ /// @param i2 - The indent level to use with stream o2.
+ void emitContextDecisions(raw_ostream &o1,
+ raw_ostream &o2,
+ uint32_t &i1,
+ uint32_t &i2) const;
+
+ /// setTableFields - Uses a ModRMFilter to set the appropriate entries in a
+ /// ModRMDecision to refer to a particular instruction ID.
+ ///
+ /// @param decision - The ModRMDecision to populate.
+ /// @param filter - The filter to use in deciding which entries to populate.
+ /// @param uid - The unique ID to set matching entries to.
+ /// @param opcode - The opcode of the instruction, for error reporting.
+ void setTableFields(ModRMDecision &decision,
+ const ModRMFilter &filter,
+ InstrUID uid,
+ uint8_t opcode);
+public:
+ /// Constructor - Allocates space for the class decisions and clears them.
+ DisassemblerTables();
+
+ ~DisassemblerTables();
+
+ /// emit - Emits the instruction table, context table, and class decisions.
+ ///
+ /// @param o - The output stream to print the tables to.
+ void emit(raw_ostream &o) const;
+
+ /// setTableFields - Uses the opcode type, instruction context, opcode, and a
+ /// ModRMFilter as criteria to set a particular set of entries in the
+ /// decode tables to point to a specific uid.
+ ///
+ /// @param type - The opcode type (ONEBYTE, TWOBYTE, etc.)
+ /// @param insnContext - The context to use (IC, IC_64BIT, etc.)
+ /// @param opcode - The last byte of the opcode (not counting any escape
+ /// or extended opcodes).
+ /// @param filter - The ModRMFilter that decides which ModR/M byte values
+ /// correspond to the desired instruction.
+ /// @param uid - The unique ID of the instruction.
+ void setTableFields(OpcodeType type,
+ InstructionContext insnContext,
+ uint8_t opcode,
+ const ModRMFilter &filter,
+ InstrUID uid);
+
+ /// specForUID - Returns the instruction specifier for a given unique
+ /// instruction ID. Used when resolving collisions.
+ ///
+ /// @param uid - The unique ID of the instruction.
+ /// @return - A reference to the instruction specifier.
+ InstructionSpecifier& specForUID(InstrUID uid) {
+ if (uid >= InstructionSpecifiers.size())
+ InstructionSpecifiers.resize(uid + 1);
+
+ return InstructionSpecifiers[uid];
+ }
+
+ // hasConflicts - Reports whether there were primary decode conflicts
+ // from any instructions added to the tables.
+ // @return - true if there were; false otherwise.
+
+ bool hasConflicts() {
+ return HasConflicts;
+ }
+};
+
+} // namespace X86Disassembler
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/X86ModRMFilters.h b/contrib/llvm/utils/TableGen/X86ModRMFilters.h
new file mode 100644
index 0000000..45cb07a
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86ModRMFilters.h
@@ -0,0 +1,197 @@
+//===- X86ModRMFilters.h - Disassembler ModR/M filterss ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler Emitter.
+// It contains ModR/M filters that determine which values of the ModR/M byte
+// are valid for a partiuclar instruction.
+// Documentation for the disassembler emitter in general can be found in
+// X86DisasemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef X86MODRMFILTERS_H
+#define X86MODRMFILTERS_H
+
+#include "llvm/System/DataTypes.h"
+
+namespace llvm {
+
+namespace X86Disassembler {
+
+/// ModRMFilter - Abstract base class for clases that recognize patterns in
+/// ModR/M bytes.
+class ModRMFilter {
+public:
+ /// Destructor - Override as necessary.
+ virtual ~ModRMFilter() { }
+
+ /// isDumb - Indicates whether this filter returns the same value for
+ /// any value of the ModR/M byte.
+ ///
+ /// @result - True if the filter returns the same value for any ModR/M
+ /// byte; false if not.
+ virtual bool isDumb() const { return false; }
+
+ /// accepts - Indicates whether the filter accepts a particular ModR/M
+ /// byte value.
+ ///
+ /// @result - True if the filter accepts the ModR/M byte; false if not.
+ virtual bool accepts(uint8_t modRM) const = 0;
+};
+
+/// DumbFilter - Accepts any ModR/M byte. Used for instructions that do not
+/// require a ModR/M byte or instructions where the entire ModR/M byte is used
+/// for operands.
+class DumbFilter : public ModRMFilter {
+public:
+ bool isDumb() const {
+ return true;
+ }
+
+ bool accepts(uint8_t modRM) const {
+ return true;
+ }
+};
+
+/// ModFilter - Filters based on the mod bits [bits 7-6] of the ModR/M byte.
+/// Some instructions are classified based on whether they are 11 or anything
+/// else. This filter performs that classification.
+class ModFilter : public ModRMFilter {
+private:
+ bool R;
+public:
+ /// Constructor
+ ///
+ /// @r - True if the mod bits of the ModR/M byte must be 11; false
+ /// otherwise. The name r derives from the fact that the mod
+ /// bits indicate whether the R/M bits [bits 2-0] signify a
+ /// register or a memory operand.
+ ModFilter(bool r) :
+ ModRMFilter(),
+ R(r) {
+ }
+
+ bool accepts(uint8_t modRM) const {
+ if (R == ((modRM & 0xc0) == 0xc0))
+ return true;
+ else
+ return false;
+ }
+};
+
+/// EscapeFilter - Filters escape opcodes, which are classified in two ways. If
+/// the ModR/M byte is between 0xc0 and 0xff, then there is one slot for each
+/// possible value. Otherwise, there is one instruction for each value of the
+/// nnn field [bits 5-3], known elsewhere as the reg field.
+class EscapeFilter : public ModRMFilter {
+private:
+ bool C0_FF;
+ uint8_t NNN_or_ModRM;
+public:
+ /// Constructor
+ ///
+ /// @c0_ff - True if the ModR/M byte must fall between 0xc0 and 0xff;
+ /// false otherwise.
+ /// @nnn_or_modRM - If c0_ff is true, the required value of the entire ModR/M
+ /// byte. If c0_ff is false, the required value of the nnn
+ /// field.
+ EscapeFilter(bool c0_ff, uint8_t nnn_or_modRM) :
+ ModRMFilter(),
+ C0_FF(c0_ff),
+ NNN_or_ModRM(nnn_or_modRM) {
+ }
+
+ bool accepts(uint8_t modRM) const {
+ if ((C0_FF && modRM >= 0xc0 && (modRM == NNN_or_ModRM)) ||
+ (!C0_FF && modRM < 0xc0 && ((modRM & 0x38) >> 3) == NNN_or_ModRM))
+ return true;
+ else
+ return false;
+ }
+};
+
+/// AddRegEscapeFilter - Some escape opcodes have one of the register operands
+/// added to the ModR/M byte, meaning that a range of eight ModR/M values
+/// maps to a single instruction. Such instructions require the ModR/M byte
+/// to fall between 0xc0 and 0xff.
+class AddRegEscapeFilter : public ModRMFilter {
+private:
+ uint8_t ModRM;
+public:
+ /// Constructor
+ ///
+ /// @modRM - The value of the ModR/M byte when the register operand
+ /// refers to the first register in the register set.
+ AddRegEscapeFilter(uint8_t modRM) : ModRM(modRM) {
+ }
+
+ bool accepts(uint8_t modRM) const {
+ if (modRM >= ModRM && modRM < ModRM + 8)
+ return true;
+ else
+ return false;
+ }
+};
+
+/// ExtendedFilter - Extended opcodes are classified based on the value of the
+/// mod field [bits 7-6] and the value of the nnn field [bits 5-3].
+class ExtendedFilter : public ModRMFilter {
+private:
+ bool R;
+ uint8_t NNN;
+public:
+ /// Constructor
+ ///
+ /// @r - True if the mod field must be set to 11; false otherwise.
+ /// The name is explained at ModFilter.
+ /// @nnn - The required value of the nnn field.
+ ExtendedFilter(bool r, uint8_t nnn) :
+ ModRMFilter(),
+ R(r),
+ NNN(nnn) {
+ }
+
+ bool accepts(uint8_t modRM) const {
+ if (((R && ((modRM & 0xc0) == 0xc0)) ||
+ (!R && ((modRM & 0xc0) != 0xc0))) &&
+ (((modRM & 0x38) >> 3) == NNN))
+ return true;
+ else
+ return false;
+ }
+};
+
+/// ExactFilter - The occasional extended opcode (such as VMCALL or MONITOR)
+/// requires the ModR/M byte to have a specific value.
+class ExactFilter : public ModRMFilter
+{
+private:
+ uint8_t ModRM;
+public:
+ /// Constructor
+ ///
+ /// @modRM - The required value of the full ModR/M byte.
+ ExactFilter(uint8_t modRM) :
+ ModRMFilter(),
+ ModRM(modRM) {
+ }
+
+ bool accepts(uint8_t modRM) const {
+ if (ModRM == modRM)
+ return true;
+ else
+ return false;
+ }
+};
+
+} // namespace X86Disassembler
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
new file mode 100644
index 0000000..4dba85b
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -0,0 +1,983 @@
+//===- X86RecognizableInstr.cpp - Disassembler instruction spec --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler Emitter.
+// It contains the implementation of a single recognizable instruction.
+// Documentation for the disassembler emitter in general can be found in
+// X86DisasemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86DisassemblerShared.h"
+#include "X86RecognizableInstr.h"
+#include "X86ModRMFilters.h"
+
+#include "llvm/Support/ErrorHandling.h"
+
+#include <string>
+
+using namespace llvm;
+
+#define MRM_MAPPING \
+ MAP(C1, 33) \
+ MAP(C2, 34) \
+ MAP(C3, 35) \
+ MAP(C4, 36) \
+ MAP(C8, 37) \
+ MAP(C9, 38) \
+ MAP(E8, 39) \
+ MAP(F0, 40) \
+ MAP(F8, 41) \
+ MAP(F9, 42)
+
+// A clone of X86 since we can't depend on something that is generated.
+namespace X86Local {
+ enum {
+ Pseudo = 0,
+ RawFrm = 1,
+ AddRegFrm = 2,
+ MRMDestReg = 3,
+ MRMDestMem = 4,
+ MRMSrcReg = 5,
+ MRMSrcMem = 6,
+ MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19,
+ MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23,
+ MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27,
+ MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31,
+ MRMInitReg = 32,
+
+#define MAP(from, to) MRM_##from = to,
+ MRM_MAPPING
+#undef MAP
+ lastMRM
+ };
+
+ enum {
+ TB = 1,
+ REP = 2,
+ D8 = 3, D9 = 4, DA = 5, DB = 6,
+ DC = 7, DD = 8, DE = 9, DF = 10,
+ XD = 11, XS = 12,
+ T8 = 13, P_TA = 14,
+ P_0F_AE = 16, P_0F_01 = 17
+ };
+}
+
+// If rows are added to the opcode extension tables, then corresponding entries
+// must be added here.
+//
+// If the row corresponds to a single byte (i.e., 8f), then add an entry for
+// that byte to ONE_BYTE_EXTENSION_TABLES.
+//
+// If the row corresponds to two bytes where the first is 0f, add an entry for
+// the second byte to TWO_BYTE_EXTENSION_TABLES.
+//
+// If the row corresponds to some other set of bytes, you will need to modify
+// the code in RecognizableInstr::emitDecodePath() as well, and add new prefixes
+// to the X86 TD files, except in two cases: if the first two bytes of such a
+// new combination are 0f 38 or 0f 3a, you just have to add maps called
+// THREE_BYTE_38_EXTENSION_TABLES and THREE_BYTE_3A_EXTENSION_TABLES and add a
+// switch(Opcode) just below the case X86Local::T8: or case X86Local::TA: line
+// in RecognizableInstr::emitDecodePath().
+
+#define ONE_BYTE_EXTENSION_TABLES \
+ EXTENSION_TABLE(80) \
+ EXTENSION_TABLE(81) \
+ EXTENSION_TABLE(82) \
+ EXTENSION_TABLE(83) \
+ EXTENSION_TABLE(8f) \
+ EXTENSION_TABLE(c0) \
+ EXTENSION_TABLE(c1) \
+ EXTENSION_TABLE(c6) \
+ EXTENSION_TABLE(c7) \
+ EXTENSION_TABLE(d0) \
+ EXTENSION_TABLE(d1) \
+ EXTENSION_TABLE(d2) \
+ EXTENSION_TABLE(d3) \
+ EXTENSION_TABLE(f6) \
+ EXTENSION_TABLE(f7) \
+ EXTENSION_TABLE(fe) \
+ EXTENSION_TABLE(ff)
+
+#define TWO_BYTE_EXTENSION_TABLES \
+ EXTENSION_TABLE(00) \
+ EXTENSION_TABLE(01) \
+ EXTENSION_TABLE(18) \
+ EXTENSION_TABLE(71) \
+ EXTENSION_TABLE(72) \
+ EXTENSION_TABLE(73) \
+ EXTENSION_TABLE(ae) \
+ EXTENSION_TABLE(b9) \
+ EXTENSION_TABLE(ba) \
+ EXTENSION_TABLE(c7)
+
+using namespace X86Disassembler;
+
+/// needsModRMForDecode - Indicates whether a particular instruction requires a
+/// ModR/M byte for the instruction to be properly decoded. For example, a
+/// MRMDestReg instruction needs the Mod field in the ModR/M byte to be set to
+/// 0b11.
+///
+/// @param form - The form of the instruction.
+/// @return - true if the form implies that a ModR/M byte is required, false
+/// otherwise.
+static bool needsModRMForDecode(uint8_t form) {
+ if (form == X86Local::MRMDestReg ||
+ form == X86Local::MRMDestMem ||
+ form == X86Local::MRMSrcReg ||
+ form == X86Local::MRMSrcMem ||
+ (form >= X86Local::MRM0r && form <= X86Local::MRM7r) ||
+ (form >= X86Local::MRM0m && form <= X86Local::MRM7m))
+ return true;
+ else
+ return false;
+}
+
+/// isRegFormat - Indicates whether a particular form requires the Mod field of
+/// the ModR/M byte to be 0b11.
+///
+/// @param form - The form of the instruction.
+/// @return - true if the form implies that Mod must be 0b11, false
+/// otherwise.
+static bool isRegFormat(uint8_t form) {
+ if (form == X86Local::MRMDestReg ||
+ form == X86Local::MRMSrcReg ||
+ (form >= X86Local::MRM0r && form <= X86Local::MRM7r))
+ return true;
+ else
+ return false;
+}
+
+/// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit.
+/// Useful for switch statements and the like.
+///
+/// @param init - A reference to the BitsInit to be decoded.
+/// @return - The field, with the first bit in the BitsInit as the lowest
+/// order bit.
+static uint8_t byteFromBitsInit(BitsInit &init) {
+ int width = init.getNumBits();
+
+ assert(width <= 8 && "Field is too large for uint8_t!");
+
+ int index;
+ uint8_t mask = 0x01;
+
+ uint8_t ret = 0;
+
+ for (index = 0; index < width; index++) {
+ if (static_cast<BitInit*>(init.getBit(index))->getValue())
+ ret |= mask;
+
+ mask <<= 1;
+ }
+
+ return ret;
+}
+
+/// byteFromRec - Extract a value at most 8 bits in with from a Record given the
+/// name of the field.
+///
+/// @param rec - The record from which to extract the value.
+/// @param name - The name of the field in the record.
+/// @return - The field, as translated by byteFromBitsInit().
+static uint8_t byteFromRec(const Record* rec, const std::string &name) {
+ BitsInit* bits = rec->getValueAsBitsInit(name);
+ return byteFromBitsInit(*bits);
+}
+
+RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
+ const CodeGenInstruction &insn,
+ InstrUID uid) {
+ UID = uid;
+
+ Rec = insn.TheDef;
+ Name = Rec->getName();
+ Spec = &tables.specForUID(UID);
+
+ if (!Rec->isSubClassOf("X86Inst")) {
+ ShouldBeEmitted = false;
+ return;
+ }
+
+ Prefix = byteFromRec(Rec, "Prefix");
+ Opcode = byteFromRec(Rec, "Opcode");
+ Form = byteFromRec(Rec, "FormBits");
+ SegOvr = byteFromRec(Rec, "SegOvrBits");
+
+ HasOpSizePrefix = Rec->getValueAsBit("hasOpSizePrefix");
+ HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
+ HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix");
+ HasLockPrefix = Rec->getValueAsBit("hasLockPrefix");
+ IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
+
+ Name = Rec->getName();
+ AsmString = Rec->getValueAsString("AsmString");
+
+ Operands = &insn.OperandList;
+
+ IsSSE = HasOpSizePrefix && (Name.find("16") == Name.npos);
+ HasFROperands = false;
+
+ ShouldBeEmitted = true;
+}
+
+void RecognizableInstr::processInstr(DisassemblerTables &tables,
+ const CodeGenInstruction &insn,
+ InstrUID uid)
+{
+ // Ignore "asm parser only" instructions.
+ if (insn.TheDef->getValueAsBit("isAsmParserOnly"))
+ return;
+
+ RecognizableInstr recogInstr(tables, insn, uid);
+
+ recogInstr.emitInstructionSpecifier(tables);
+
+ if (recogInstr.shouldBeEmitted())
+ recogInstr.emitDecodePath(tables);
+}
+
+InstructionContext RecognizableInstr::insnContext() const {
+ InstructionContext insnContext;
+
+ if (Name.find("64") != Name.npos || HasREX_WPrefix) {
+ if (HasREX_WPrefix && HasOpSizePrefix)
+ insnContext = IC_64BIT_REXW_OPSIZE;
+ else if (HasOpSizePrefix)
+ insnContext = IC_64BIT_OPSIZE;
+ else if (HasREX_WPrefix && Prefix == X86Local::XS)
+ insnContext = IC_64BIT_REXW_XS;
+ else if (HasREX_WPrefix && Prefix == X86Local::XD)
+ insnContext = IC_64BIT_REXW_XD;
+ else if (Prefix == X86Local::XD)
+ insnContext = IC_64BIT_XD;
+ else if (Prefix == X86Local::XS)
+ insnContext = IC_64BIT_XS;
+ else if (HasREX_WPrefix)
+ insnContext = IC_64BIT_REXW;
+ else
+ insnContext = IC_64BIT;
+ } else {
+ if (HasOpSizePrefix)
+ insnContext = IC_OPSIZE;
+ else if (Prefix == X86Local::XD)
+ insnContext = IC_XD;
+ else if (Prefix == X86Local::XS)
+ insnContext = IC_XS;
+ else
+ insnContext = IC;
+ }
+
+ return insnContext;
+}
+
+RecognizableInstr::filter_ret RecognizableInstr::filter() const {
+ // Filter out intrinsics
+
+ if (!Rec->isSubClassOf("X86Inst"))
+ return FILTER_STRONG;
+
+ if (Form == X86Local::Pseudo ||
+ IsCodeGenOnly)
+ return FILTER_STRONG;
+
+ if (Form == X86Local::MRMInitReg)
+ return FILTER_STRONG;
+
+
+ // Filter out instructions with a LOCK prefix;
+ // prefer forms that do not have the prefix
+ if (HasLockPrefix)
+ return FILTER_WEAK;
+
+ // Filter out artificial instructions
+
+ if (Name.find("TAILJMP") != Name.npos ||
+ Name.find("_Int") != Name.npos ||
+ Name.find("_int") != Name.npos ||
+ Name.find("Int_") != Name.npos ||
+ Name.find("_NOREX") != Name.npos ||
+ Name.find("_TC") != Name.npos ||
+ Name.find("EH_RETURN") != Name.npos ||
+ Name.find("V_SET") != Name.npos ||
+ Name.find("LOCK_") != Name.npos ||
+ Name.find("WIN") != Name.npos)
+ return FILTER_STRONG;
+
+ // Special cases.
+
+ if (Name.find("PCMPISTRI") != Name.npos && Name != "PCMPISTRI")
+ return FILTER_WEAK;
+ if (Name.find("PCMPESTRI") != Name.npos && Name != "PCMPESTRI")
+ return FILTER_WEAK;
+
+ if (Name.find("MOV") != Name.npos && Name.find("r0") != Name.npos)
+ return FILTER_WEAK;
+ if (Name.find("MOVZ") != Name.npos && Name.find("MOVZX") == Name.npos)
+ return FILTER_WEAK;
+ if (Name.find("Fs") != Name.npos)
+ return FILTER_WEAK;
+ if (Name == "MOVLPDrr" ||
+ Name == "MOVLPSrr" ||
+ Name == "PUSHFQ" ||
+ Name == "BSF16rr" ||
+ Name == "BSF16rm" ||
+ Name == "BSR16rr" ||
+ Name == "BSR16rm" ||
+ Name == "MOVSX16rm8" ||
+ Name == "MOVSX16rr8" ||
+ Name == "MOVZX16rm8" ||
+ Name == "MOVZX16rr8" ||
+ Name == "PUSH32i16" ||
+ Name == "PUSH64i16" ||
+ Name == "MOVPQI2QImr" ||
+ Name == "MOVSDmr" ||
+ Name == "MOVSDrm" ||
+ Name == "MOVSSmr" ||
+ Name == "MOVSSrm" ||
+ Name == "MMX_MOVD64rrv164" ||
+ Name == "CRC32m16" ||
+ Name == "MOV64ri64i32" ||
+ Name == "CRC32r16")
+ return FILTER_WEAK;
+
+ // Filter out instructions with segment override prefixes.
+ // They're too messy to handle now and we'll special case them if needed.
+
+ if (SegOvr)
+ return FILTER_STRONG;
+
+ // Filter out instructions that can't be printed.
+
+ if (AsmString.size() == 0)
+ return FILTER_STRONG;
+
+ // Filter out instructions with subreg operands.
+
+ if (AsmString.find("subreg") != AsmString.npos)
+ return FILTER_STRONG;
+
+ if (HasFROperands && Name.find("MOV") != Name.npos &&
+ ((Name.find("2") != Name.npos && Name.find("32") == Name.npos) ||
+ (Name.find("to") != Name.npos)))
+ return FILTER_WEAK;
+
+ return FILTER_NORMAL;
+}
+
+void RecognizableInstr::handleOperand(
+ bool optional,
+ unsigned &operandIndex,
+ unsigned &physicalOperandIndex,
+ unsigned &numPhysicalOperands,
+ unsigned *operandMapping,
+ OperandEncoding (*encodingFromString)(const std::string&, bool hasOpSizePrefix)) {
+ if (optional) {
+ if (physicalOperandIndex >= numPhysicalOperands)
+ return;
+ } else {
+ assert(physicalOperandIndex < numPhysicalOperands);
+ }
+
+ while (operandMapping[operandIndex] != operandIndex) {
+ Spec->operands[operandIndex].encoding = ENCODING_DUP;
+ Spec->operands[operandIndex].type =
+ (OperandType)(TYPE_DUP0 + operandMapping[operandIndex]);
+ ++operandIndex;
+ }
+
+ const std::string &typeName = (*Operands)[operandIndex].Rec->getName();
+
+ Spec->operands[operandIndex].encoding = encodingFromString(typeName,
+ HasOpSizePrefix);
+ Spec->operands[operandIndex].type = typeFromString(typeName,
+ IsSSE,
+ HasREX_WPrefix,
+ HasOpSizePrefix);
+
+ ++operandIndex;
+ ++physicalOperandIndex;
+}
+
+void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
+ Spec->name = Name;
+
+ if (!Rec->isSubClassOf("X86Inst"))
+ return;
+
+ switch (filter()) {
+ case FILTER_WEAK:
+ Spec->filtered = true;
+ break;
+ case FILTER_STRONG:
+ ShouldBeEmitted = false;
+ return;
+ case FILTER_NORMAL:
+ break;
+ }
+
+ Spec->insnContext = insnContext();
+
+ const std::vector<CodeGenInstruction::OperandInfo> &OperandList = *Operands;
+
+ unsigned operandIndex;
+ unsigned numOperands = OperandList.size();
+ unsigned numPhysicalOperands = 0;
+
+ // operandMapping maps from operands in OperandList to their originals.
+ // If operandMapping[i] != i, then the entry is a duplicate.
+ unsigned operandMapping[X86_MAX_OPERANDS];
+
+ bool hasFROperands = false;
+
+ assert(numOperands < X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough");
+
+ for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
+ if (OperandList[operandIndex].Constraints.size()) {
+ const CodeGenInstruction::ConstraintInfo &Constraint =
+ OperandList[operandIndex].Constraints[0];
+ if (Constraint.isTied()) {
+ operandMapping[operandIndex] = Constraint.getTiedOperand();
+ } else {
+ ++numPhysicalOperands;
+ operandMapping[operandIndex] = operandIndex;
+ }
+ } else {
+ ++numPhysicalOperands;
+ operandMapping[operandIndex] = operandIndex;
+ }
+
+ const std::string &recName = OperandList[operandIndex].Rec->getName();
+
+ if (recName.find("FR") != recName.npos)
+ hasFROperands = true;
+ }
+
+ if (hasFROperands && Name.find("MOV") != Name.npos &&
+ ((Name.find("2") != Name.npos && Name.find("32") == Name.npos) ||
+ (Name.find("to") != Name.npos)))
+ ShouldBeEmitted = false;
+
+ if (!ShouldBeEmitted)
+ return;
+
+#define HANDLE_OPERAND(class) \
+ handleOperand(false, \
+ operandIndex, \
+ physicalOperandIndex, \
+ numPhysicalOperands, \
+ operandMapping, \
+ class##EncodingFromString);
+
+#define HANDLE_OPTIONAL(class) \
+ handleOperand(true, \
+ operandIndex, \
+ physicalOperandIndex, \
+ numPhysicalOperands, \
+ operandMapping, \
+ class##EncodingFromString);
+
+ // operandIndex should always be < numOperands
+ operandIndex = 0;
+ // physicalOperandIndex should always be < numPhysicalOperands
+ unsigned physicalOperandIndex = 0;
+
+ switch (Form) {
+ case X86Local::RawFrm:
+ // Operand 1 (optional) is an address or immediate.
+ // Operand 2 (optional) is an immediate.
+ assert(numPhysicalOperands <= 2 &&
+ "Unexpected number of operands for RawFrm");
+ HANDLE_OPTIONAL(relocation)
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::AddRegFrm:
+ // Operand 1 is added to the opcode.
+ // Operand 2 (optional) is an address.
+ assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 &&
+ "Unexpected number of operands for AddRegFrm");
+ HANDLE_OPERAND(opcodeModifier)
+ HANDLE_OPTIONAL(relocation)
+ break;
+ case X86Local::MRMDestReg:
+ // Operand 1 is a register operand in the R/M field.
+ // Operand 2 is a register operand in the Reg/Opcode field.
+ // Operand 3 (optional) is an immediate.
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMDestRegFrm");
+ HANDLE_OPERAND(rmRegister)
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::MRMDestMem:
+ // Operand 1 is a memory operand (possibly SIB-extended)
+ // Operand 2 is a register operand in the Reg/Opcode field.
+ // Operand 3 (optional) is an immediate.
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMDestMemFrm");
+ HANDLE_OPERAND(memory)
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::MRMSrcReg:
+ // Operand 1 is a register operand in the Reg/Opcode field.
+ // Operand 2 is a register operand in the R/M field.
+ // Operand 3 (optional) is an immediate.
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMSrcRegFrm");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(rmRegister)
+
+ if (HasVEX_4VPrefix)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPTIONAL(rmRegister)
+ else
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::MRMSrcMem:
+ // Operand 1 is a register operand in the Reg/Opcode field.
+ // Operand 2 is a memory operand (possibly SIB-extended)
+ // Operand 3 (optional) is an immediate.
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMSrcMemFrm");
+ HANDLE_OPERAND(roRegister)
+
+ if (HasVEX_4VPrefix)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPTIONAL(rmRegister)
+
+ HANDLE_OPERAND(memory)
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::MRM0r:
+ case X86Local::MRM1r:
+ case X86Local::MRM2r:
+ case X86Local::MRM3r:
+ case X86Local::MRM4r:
+ case X86Local::MRM5r:
+ case X86Local::MRM6r:
+ case X86Local::MRM7r:
+ // Operand 1 is a register operand in the R/M field.
+ // Operand 2 (optional) is an immediate or relocation.
+ assert(numPhysicalOperands <= 2 &&
+ "Unexpected number of operands for MRMnRFrm");
+ HANDLE_OPTIONAL(rmRegister)
+ HANDLE_OPTIONAL(relocation)
+ break;
+ case X86Local::MRM0m:
+ case X86Local::MRM1m:
+ case X86Local::MRM2m:
+ case X86Local::MRM3m:
+ case X86Local::MRM4m:
+ case X86Local::MRM5m:
+ case X86Local::MRM6m:
+ case X86Local::MRM7m:
+ // Operand 1 is a memory operand (possibly SIB-extended)
+ // Operand 2 (optional) is an immediate or relocation.
+ assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 &&
+ "Unexpected number of operands for MRMnMFrm");
+ HANDLE_OPERAND(memory)
+ HANDLE_OPTIONAL(relocation)
+ break;
+ case X86Local::MRMInitReg:
+ // Ignored.
+ break;
+ }
+
+ #undef HANDLE_OPERAND
+ #undef HANDLE_OPTIONAL
+}
+
+void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
+ // Special cases where the LLVM tables are not complete
+
+#define MAP(from, to) \
+ case X86Local::MRM_##from: \
+ filter = new ExactFilter(0x##from); \
+ break;
+
+ OpcodeType opcodeType = (OpcodeType)-1;
+
+ ModRMFilter* filter = NULL;
+ uint8_t opcodeToSet = 0;
+
+ switch (Prefix) {
+ // Extended two-byte opcodes can start with f2 0f, f3 0f, or 0f
+ case X86Local::XD:
+ case X86Local::XS:
+ case X86Local::TB:
+ opcodeType = TWOBYTE;
+
+ switch (Opcode) {
+ default:
+ if (needsModRMForDecode(Form))
+ filter = new ModFilter(isRegFormat(Form));
+ else
+ filter = new DumbFilter();
+ break;
+#define EXTENSION_TABLE(n) case 0x##n:
+ TWO_BYTE_EXTENSION_TABLES
+#undef EXTENSION_TABLE
+ switch (Form) {
+ default:
+ llvm_unreachable("Unhandled two-byte extended opcode");
+ case X86Local::MRM0r:
+ case X86Local::MRM1r:
+ case X86Local::MRM2r:
+ case X86Local::MRM3r:
+ case X86Local::MRM4r:
+ case X86Local::MRM5r:
+ case X86Local::MRM6r:
+ case X86Local::MRM7r:
+ filter = new ExtendedFilter(true, Form - X86Local::MRM0r);
+ break;
+ case X86Local::MRM0m:
+ case X86Local::MRM1m:
+ case X86Local::MRM2m:
+ case X86Local::MRM3m:
+ case X86Local::MRM4m:
+ case X86Local::MRM5m:
+ case X86Local::MRM6m:
+ case X86Local::MRM7m:
+ filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
+ break;
+ MRM_MAPPING
+ } // switch (Form)
+ break;
+ } // switch (Opcode)
+ opcodeToSet = Opcode;
+ break;
+ case X86Local::T8:
+ opcodeType = THREEBYTE_38;
+ if (needsModRMForDecode(Form))
+ filter = new ModFilter(isRegFormat(Form));
+ else
+ filter = new DumbFilter();
+ opcodeToSet = Opcode;
+ break;
+ case X86Local::P_TA:
+ opcodeType = THREEBYTE_3A;
+ if (needsModRMForDecode(Form))
+ filter = new ModFilter(isRegFormat(Form));
+ else
+ filter = new DumbFilter();
+ opcodeToSet = Opcode;
+ break;
+ case X86Local::D8:
+ case X86Local::D9:
+ case X86Local::DA:
+ case X86Local::DB:
+ case X86Local::DC:
+ case X86Local::DD:
+ case X86Local::DE:
+ case X86Local::DF:
+ assert(Opcode >= 0xc0 && "Unexpected opcode for an escape opcode");
+ opcodeType = ONEBYTE;
+ if (Form == X86Local::AddRegFrm) {
+ Spec->modifierType = MODIFIER_MODRM;
+ Spec->modifierBase = Opcode;
+ filter = new AddRegEscapeFilter(Opcode);
+ } else {
+ filter = new EscapeFilter(true, Opcode);
+ }
+ opcodeToSet = 0xd8 + (Prefix - X86Local::D8);
+ break;
+ default:
+ opcodeType = ONEBYTE;
+ switch (Opcode) {
+#define EXTENSION_TABLE(n) case 0x##n:
+ ONE_BYTE_EXTENSION_TABLES
+#undef EXTENSION_TABLE
+ switch (Form) {
+ default:
+ llvm_unreachable("Fell through the cracks of a single-byte "
+ "extended opcode");
+ case X86Local::MRM0r:
+ case X86Local::MRM1r:
+ case X86Local::MRM2r:
+ case X86Local::MRM3r:
+ case X86Local::MRM4r:
+ case X86Local::MRM5r:
+ case X86Local::MRM6r:
+ case X86Local::MRM7r:
+ filter = new ExtendedFilter(true, Form - X86Local::MRM0r);
+ break;
+ case X86Local::MRM0m:
+ case X86Local::MRM1m:
+ case X86Local::MRM2m:
+ case X86Local::MRM3m:
+ case X86Local::MRM4m:
+ case X86Local::MRM5m:
+ case X86Local::MRM6m:
+ case X86Local::MRM7m:
+ filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
+ break;
+ MRM_MAPPING
+ } // switch (Form)
+ break;
+ case 0xd8:
+ case 0xd9:
+ case 0xda:
+ case 0xdb:
+ case 0xdc:
+ case 0xdd:
+ case 0xde:
+ case 0xdf:
+ filter = new EscapeFilter(false, Form - X86Local::MRM0m);
+ break;
+ default:
+ if (needsModRMForDecode(Form))
+ filter = new ModFilter(isRegFormat(Form));
+ else
+ filter = new DumbFilter();
+ break;
+ } // switch (Opcode)
+ opcodeToSet = Opcode;
+ } // switch (Prefix)
+
+ assert(opcodeType != (OpcodeType)-1 &&
+ "Opcode type not set");
+ assert(filter && "Filter not set");
+
+ if (Form == X86Local::AddRegFrm) {
+ if(Spec->modifierType != MODIFIER_MODRM) {
+ assert(opcodeToSet < 0xf9 &&
+ "Not enough room for all ADDREG_FRM operands");
+
+ uint8_t currentOpcode;
+
+ for (currentOpcode = opcodeToSet;
+ currentOpcode < opcodeToSet + 8;
+ ++currentOpcode)
+ tables.setTableFields(opcodeType,
+ insnContext(),
+ currentOpcode,
+ *filter,
+ UID);
+
+ Spec->modifierType = MODIFIER_OPCODE;
+ Spec->modifierBase = opcodeToSet;
+ } else {
+ // modifierBase was set where MODIFIER_MODRM was set
+ tables.setTableFields(opcodeType,
+ insnContext(),
+ opcodeToSet,
+ *filter,
+ UID);
+ }
+ } else {
+ tables.setTableFields(opcodeType,
+ insnContext(),
+ opcodeToSet,
+ *filter,
+ UID);
+
+ Spec->modifierType = MODIFIER_NONE;
+ Spec->modifierBase = opcodeToSet;
+ }
+
+ delete filter;
+
+#undef MAP
+}
+
+#define TYPE(str, type) if (s == str) return type;
+OperandType RecognizableInstr::typeFromString(const std::string &s,
+ bool isSSE,
+ bool hasREX_WPrefix,
+ bool hasOpSizePrefix) {
+ if (isSSE) {
+ // For SSE instructions, we ignore the OpSize prefix and force operand
+ // sizes.
+ TYPE("GR16", TYPE_R16)
+ TYPE("GR32", TYPE_R32)
+ TYPE("GR64", TYPE_R64)
+ }
+ if(hasREX_WPrefix) {
+ // For instructions with a REX_W prefix, a declared 32-bit register encoding
+ // is special.
+ TYPE("GR32", TYPE_R32)
+ }
+ if(!hasOpSizePrefix) {
+ // For instructions without an OpSize prefix, a declared 16-bit register or
+ // immediate encoding is special.
+ TYPE("GR16", TYPE_R16)
+ TYPE("i16imm", TYPE_IMM16)
+ }
+ TYPE("i16mem", TYPE_Mv)
+ TYPE("i16imm", TYPE_IMMv)
+ TYPE("i16i8imm", TYPE_IMMv)
+ TYPE("GR16", TYPE_Rv)
+ TYPE("i32mem", TYPE_Mv)
+ TYPE("i32imm", TYPE_IMMv)
+ TYPE("i32i8imm", TYPE_IMM32)
+ TYPE("GR32", TYPE_Rv)
+ TYPE("i64mem", TYPE_Mv)
+ TYPE("i64i32imm", TYPE_IMM64)
+ TYPE("i64i8imm", TYPE_IMM64)
+ TYPE("GR64", TYPE_R64)
+ TYPE("i8mem", TYPE_M8)
+ TYPE("i8imm", TYPE_IMM8)
+ TYPE("GR8", TYPE_R8)
+ TYPE("VR128", TYPE_XMM128)
+ TYPE("f128mem", TYPE_M128)
+ TYPE("FR64", TYPE_XMM64)
+ TYPE("f64mem", TYPE_M64FP)
+ TYPE("FR32", TYPE_XMM32)
+ TYPE("f32mem", TYPE_M32FP)
+ TYPE("RST", TYPE_ST)
+ TYPE("i128mem", TYPE_M128)
+ TYPE("i64i32imm_pcrel", TYPE_REL64)
+ TYPE("i16imm_pcrel", TYPE_REL16)
+ TYPE("i32imm_pcrel", TYPE_REL32)
+ TYPE("SSECC", TYPE_IMM3)
+ TYPE("brtarget", TYPE_RELv)
+ TYPE("brtarget8", TYPE_REL8)
+ TYPE("f80mem", TYPE_M80FP)
+ TYPE("lea32mem", TYPE_LEA)
+ TYPE("lea64_32mem", TYPE_LEA)
+ TYPE("lea64mem", TYPE_LEA)
+ TYPE("VR64", TYPE_MM64)
+ TYPE("i64imm", TYPE_IMMv)
+ TYPE("opaque32mem", TYPE_M1616)
+ TYPE("opaque48mem", TYPE_M1632)
+ TYPE("opaque80mem", TYPE_M1664)
+ TYPE("opaque512mem", TYPE_M512)
+ TYPE("SEGMENT_REG", TYPE_SEGMENTREG)
+ TYPE("DEBUG_REG", TYPE_DEBUGREG)
+ TYPE("CONTROL_REG", TYPE_CONTROLREG)
+ TYPE("offset8", TYPE_MOFFS8)
+ TYPE("offset16", TYPE_MOFFS16)
+ TYPE("offset32", TYPE_MOFFS32)
+ TYPE("offset64", TYPE_MOFFS64)
+ errs() << "Unhandled type string " << s << "\n";
+ llvm_unreachable("Unhandled type string");
+}
+#undef TYPE
+
+#define ENCODING(str, encoding) if (s == str) return encoding;
+OperandEncoding RecognizableInstr::immediateEncodingFromString
+ (const std::string &s,
+ bool hasOpSizePrefix) {
+ if(!hasOpSizePrefix) {
+ // For instructions without an OpSize prefix, a declared 16-bit register or
+ // immediate encoding is special.
+ ENCODING("i16imm", ENCODING_IW)
+ }
+ ENCODING("i32i8imm", ENCODING_IB)
+ ENCODING("SSECC", ENCODING_IB)
+ ENCODING("i16imm", ENCODING_Iv)
+ ENCODING("i16i8imm", ENCODING_IB)
+ ENCODING("i32imm", ENCODING_Iv)
+ ENCODING("i64i32imm", ENCODING_ID)
+ ENCODING("i64i8imm", ENCODING_IB)
+ ENCODING("i8imm", ENCODING_IB)
+ errs() << "Unhandled immediate encoding " << s << "\n";
+ llvm_unreachable("Unhandled immediate encoding");
+}
+
+OperandEncoding RecognizableInstr::rmRegisterEncodingFromString
+ (const std::string &s,
+ bool hasOpSizePrefix) {
+ ENCODING("GR16", ENCODING_RM)
+ ENCODING("GR32", ENCODING_RM)
+ ENCODING("GR64", ENCODING_RM)
+ ENCODING("GR8", ENCODING_RM)
+ ENCODING("VR128", ENCODING_RM)
+ ENCODING("FR64", ENCODING_RM)
+ ENCODING("FR32", ENCODING_RM)
+ ENCODING("VR64", ENCODING_RM)
+ errs() << "Unhandled R/M register encoding " << s << "\n";
+ llvm_unreachable("Unhandled R/M register encoding");
+}
+
+OperandEncoding RecognizableInstr::roRegisterEncodingFromString
+ (const std::string &s,
+ bool hasOpSizePrefix) {
+ ENCODING("GR16", ENCODING_REG)
+ ENCODING("GR32", ENCODING_REG)
+ ENCODING("GR64", ENCODING_REG)
+ ENCODING("GR8", ENCODING_REG)
+ ENCODING("VR128", ENCODING_REG)
+ ENCODING("FR64", ENCODING_REG)
+ ENCODING("FR32", ENCODING_REG)
+ ENCODING("VR64", ENCODING_REG)
+ ENCODING("SEGMENT_REG", ENCODING_REG)
+ ENCODING("DEBUG_REG", ENCODING_REG)
+ ENCODING("CONTROL_REG", ENCODING_REG)
+ errs() << "Unhandled reg/opcode register encoding " << s << "\n";
+ llvm_unreachable("Unhandled reg/opcode register encoding");
+}
+
+OperandEncoding RecognizableInstr::memoryEncodingFromString
+ (const std::string &s,
+ bool hasOpSizePrefix) {
+ ENCODING("i16mem", ENCODING_RM)
+ ENCODING("i32mem", ENCODING_RM)
+ ENCODING("i64mem", ENCODING_RM)
+ ENCODING("i8mem", ENCODING_RM)
+ ENCODING("f128mem", ENCODING_RM)
+ ENCODING("f64mem", ENCODING_RM)
+ ENCODING("f32mem", ENCODING_RM)
+ ENCODING("i128mem", ENCODING_RM)
+ ENCODING("f80mem", ENCODING_RM)
+ ENCODING("lea32mem", ENCODING_RM)
+ ENCODING("lea64_32mem", ENCODING_RM)
+ ENCODING("lea64mem", ENCODING_RM)
+ ENCODING("opaque32mem", ENCODING_RM)
+ ENCODING("opaque48mem", ENCODING_RM)
+ ENCODING("opaque80mem", ENCODING_RM)
+ ENCODING("opaque512mem", ENCODING_RM)
+ errs() << "Unhandled memory encoding " << s << "\n";
+ llvm_unreachable("Unhandled memory encoding");
+}
+
+OperandEncoding RecognizableInstr::relocationEncodingFromString
+ (const std::string &s,
+ bool hasOpSizePrefix) {
+ if(!hasOpSizePrefix) {
+ // For instructions without an OpSize prefix, a declared 16-bit register or
+ // immediate encoding is special.
+ ENCODING("i16imm", ENCODING_IW)
+ }
+ ENCODING("i16imm", ENCODING_Iv)
+ ENCODING("i16i8imm", ENCODING_IB)
+ ENCODING("i32imm", ENCODING_Iv)
+ ENCODING("i32i8imm", ENCODING_IB)
+ ENCODING("i64i32imm", ENCODING_ID)
+ ENCODING("i64i8imm", ENCODING_IB)
+ ENCODING("i8imm", ENCODING_IB)
+ ENCODING("i64i32imm_pcrel", ENCODING_ID)
+ ENCODING("i16imm_pcrel", ENCODING_IW)
+ ENCODING("i32imm_pcrel", ENCODING_ID)
+ ENCODING("brtarget", ENCODING_Iv)
+ ENCODING("brtarget8", ENCODING_IB)
+ ENCODING("i64imm", ENCODING_IO)
+ ENCODING("offset8", ENCODING_Ia)
+ ENCODING("offset16", ENCODING_Ia)
+ ENCODING("offset32", ENCODING_Ia)
+ ENCODING("offset64", ENCODING_Ia)
+ errs() << "Unhandled relocation encoding " << s << "\n";
+ llvm_unreachable("Unhandled relocation encoding");
+}
+
+OperandEncoding RecognizableInstr::opcodeModifierEncodingFromString
+ (const std::string &s,
+ bool hasOpSizePrefix) {
+ ENCODING("RST", ENCODING_I)
+ ENCODING("GR32", ENCODING_Rv)
+ ENCODING("GR64", ENCODING_RO)
+ ENCODING("GR16", ENCODING_Rv)
+ ENCODING("GR8", ENCODING_RB)
+ errs() << "Unhandled opcode modifier encoding " << s << "\n";
+ llvm_unreachable("Unhandled opcode modifier encoding");
+}
+#undef ENCODING
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
new file mode 100644
index 0000000..db4d96d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
@@ -0,0 +1,239 @@
+//===- X86RecognizableInstr.h - Disassembler instruction spec ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler Emitter.
+// It contains the interface of a single recognizable instruction.
+// Documentation for the disassembler emitter in general can be found in
+// X86DisasemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef X86RECOGNIZABLEINSTR_H
+#define X86RECOGNIZABLEINSTR_H
+
+#include "X86DisassemblerTables.h"
+
+#include "CodeGenTarget.h"
+#include "Record.h"
+
+#include "llvm/System/DataTypes.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+namespace X86Disassembler {
+
+/// RecognizableInstr - Encapsulates all information required to decode a single
+/// instruction, as extracted from the LLVM instruction tables. Has methods
+/// to interpret the information available in the LLVM tables, and to emit the
+/// instruction into DisassemblerTables.
+class RecognizableInstr {
+private:
+ /// The opcode of the instruction, as used in an MCInst
+ InstrUID UID;
+ /// The record from the .td files corresponding to this instruction
+ const Record* Rec;
+ /// The prefix field from the record
+ uint8_t Prefix;
+ /// The opcode field from the record; this is the opcode used in the Intel
+ /// encoding and therefore distinct from the UID
+ uint8_t Opcode;
+ /// The form field from the record
+ uint8_t Form;
+ /// The segment override field from the record
+ uint8_t SegOvr;
+ /// The hasOpSizePrefix field from the record
+ bool HasOpSizePrefix;
+ /// The hasREX_WPrefix field from the record
+ bool HasREX_WPrefix;
+ /// The hasVEX_4VPrefix field from the record
+ bool HasVEX_4VPrefix;
+ /// The hasLockPrefix field from the record
+ bool HasLockPrefix;
+ /// The isCodeGenOnly filed from the record
+ bool IsCodeGenOnly;
+
+ /// The instruction name as listed in the tables
+ std::string Name;
+ /// The AT&T AsmString for the instruction
+ std::string AsmString;
+
+ /// Indicates whether the instruction is SSE
+ bool IsSSE;
+ /// Indicates whether the instruction has FR operands - MOVs with FR operands
+ /// are typically ignored
+ bool HasFROperands;
+ /// Indicates whether the instruction should be emitted into the decode
+ /// tables; regardless, it will be emitted into the instruction info table
+ bool ShouldBeEmitted;
+
+ /// The operands of the instruction, as listed in the CodeGenInstruction.
+ /// They are not one-to-one with operands listed in the MCInst; for example,
+ /// memory operands expand to 5 operands in the MCInst
+ const std::vector<CodeGenInstruction::OperandInfo>* Operands;
+ /// The description of the instruction that is emitted into the instruction
+ /// info table
+ InstructionSpecifier* Spec;
+
+ /// insnContext - Returns the primary context in which the instruction is
+ /// valid.
+ ///
+ /// @return - The context in which the instruction is valid.
+ InstructionContext insnContext() const;
+
+ enum filter_ret {
+ FILTER_STRONG, // instruction has no place in the instruction tables
+ FILTER_WEAK, // instruction may conflict, and should be eliminated if
+ // it does
+ FILTER_NORMAL // instruction should have high priority and generate an
+ // error if it conflcits with any other FILTER_NORMAL
+ // instruction
+ };
+
+ /// filter - Determines whether the instruction should be decodable. Some
+ /// instructions are pure intrinsics and use unencodable operands; many
+ /// synthetic instructions are duplicates of other instructions; other
+ /// instructions only differ in the logical way in which they are used, and
+ /// have the same decoding. Because these would cause decode conflicts,
+ /// they must be filtered out.
+ ///
+ /// @return - The degree of filtering to be applied (see filter_ret).
+ filter_ret filter() const;
+
+ /// typeFromString - Translates an operand type from the string provided in
+ /// the LLVM tables to an OperandType for use in the operand specifier.
+ ///
+ /// @param s - The string, as extracted by calling Rec->getName()
+ /// on a CodeGenInstruction::OperandInfo.
+ /// @param isSSE - Indicates whether the instruction is an SSE
+ /// instruction. For SSE instructions, immediates are
+ /// fixed-size rather than being affected by the
+ /// mandatory OpSize prefix.
+ /// @param hasREX_WPrefix - Indicates whether the instruction has a REX.W
+ /// prefix. If it does, 32-bit register operands stay
+ /// 32-bit regardless of the operand size.
+ /// @param hasOpSizePrefix- Indicates whether the instruction has an OpSize
+ /// prefix. If it does not, then 16-bit register
+ /// operands stay 16-bit.
+ /// @return - The operand's type.
+ static OperandType typeFromString(const std::string& s,
+ bool isSSE,
+ bool hasREX_WPrefix,
+ bool hasOpSizePrefix);
+
+ /// immediateEncodingFromString - Translates an immediate encoding from the
+ /// string provided in the LLVM tables to an OperandEncoding for use in
+ /// the operand specifier.
+ ///
+ /// @param s - See typeFromString().
+ /// @param hasOpSizePrefix - Indicates whether the instruction has an OpSize
+ /// prefix. If it does not, then 16-bit immediate
+ /// operands stay 16-bit.
+ /// @return - The operand's encoding.
+ static OperandEncoding immediateEncodingFromString(const std::string &s,
+ bool hasOpSizePrefix);
+
+ /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but
+ /// handles operands that are in the REG field of the ModR/M byte.
+ static OperandEncoding rmRegisterEncodingFromString(const std::string &s,
+ bool hasOpSizePrefix);
+
+ /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but
+ /// handles operands that are in the REG field of the ModR/M byte.
+ static OperandEncoding roRegisterEncodingFromString(const std::string &s,
+ bool hasOpSizePrefix);
+ static OperandEncoding memoryEncodingFromString(const std::string &s,
+ bool hasOpSizePrefix);
+ static OperandEncoding relocationEncodingFromString(const std::string &s,
+ bool hasOpSizePrefix);
+ static OperandEncoding opcodeModifierEncodingFromString(const std::string &s,
+ bool hasOpSizePrefix);
+
+ /// handleOperand - Converts a single operand from the LLVM table format to
+ /// the emitted table format, handling any duplicate operands it encounters
+ /// and then one non-duplicate.
+ ///
+ /// @param optional - Determines whether to assert that the
+ /// operand exists.
+ /// @param operandIndex - The index into the generated operand table.
+ /// Incremented by this function one or more
+ /// times to reflect possible duplicate
+ /// operands).
+ /// @param physicalOperandIndex - The index of the current operand into the
+ /// set of non-duplicate ('physical') operands.
+ /// Incremented by this function once.
+ /// @param numPhysicalOperands - The number of non-duplicate operands in the
+ /// instructions.
+ /// @param operandMapping - The operand mapping, which has an entry for
+ /// each operand that indicates whether it is a
+ /// duplicate, and of what.
+ void handleOperand(bool optional,
+ unsigned &operandIndex,
+ unsigned &physicalOperandIndex,
+ unsigned &numPhysicalOperands,
+ unsigned *operandMapping,
+ OperandEncoding (*encodingFromString)
+ (const std::string&,
+ bool hasOpSizePrefix));
+
+ /// shouldBeEmitted - Returns the shouldBeEmitted field. Although filter()
+ /// filters out many instructions, at various points in decoding we
+ /// determine that the instruction should not actually be decodable. In
+ /// particular, MMX MOV instructions aren't emitted, but they're only
+ /// identified during operand parsing.
+ ///
+ /// @return - true if at this point we believe the instruction should be
+ /// emitted; false if not. This will return false if filter() returns false
+ /// once emitInstructionSpecifier() has been called.
+ bool shouldBeEmitted() const {
+ return ShouldBeEmitted;
+ }
+
+ /// emitInstructionSpecifier - Loads the instruction specifier for the current
+ /// instruction into a DisassemblerTables.
+ ///
+ /// @arg tables - The DisassemblerTables to populate with the specifier for
+ /// the current instruction.
+ void emitInstructionSpecifier(DisassemblerTables &tables);
+
+ /// emitDecodePath - Populates the proper fields in the decode tables
+ /// corresponding to the decode paths for this instruction.
+ ///
+ /// @arg tables - The DisassemblerTables to populate with the decode
+ /// decode information for the current instruction.
+ void emitDecodePath(DisassemblerTables &tables) const;
+
+ /// Constructor - Initializes a RecognizableInstr with the appropriate fields
+ /// from a CodeGenInstruction.
+ ///
+ /// @arg tables - The DisassemblerTables that the specifier will be added to.
+ /// @arg insn - The CodeGenInstruction to extract information from.
+ /// @arg uid - The unique ID of the current instruction.
+ RecognizableInstr(DisassemblerTables &tables,
+ const CodeGenInstruction &insn,
+ InstrUID uid);
+public:
+ /// processInstr - Accepts a CodeGenInstruction and loads decode information
+ /// for it into a DisassemblerTables if appropriate.
+ ///
+ /// @arg tables - The DiassemblerTables to be populated with decode
+ /// information.
+ /// @arg insn - The CodeGenInstruction to be used as a source for this
+ /// information.
+ /// @uid - The unique ID of the instruction.
+ static void processInstr(DisassemblerTables &tables,
+ const CodeGenInstruction &insn,
+ InstrUID uid);
+};
+
+} // namespace X86Disassembler
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/UpdateCMakeLists.pl b/contrib/llvm/utils/UpdateCMakeLists.pl
new file mode 100755
index 0000000..8f535145
--- /dev/null
+++ b/contrib/llvm/utils/UpdateCMakeLists.pl
@@ -0,0 +1,119 @@
+#!/usr/bin/env perl
+use strict;
+use File::Find;
+use File::Copy;
+use Digest::MD5;
+
+my @fileTypes = ("cpp", "c");
+my %dirFiles;
+my %dirCMake;
+
+sub GetFiles {
+ my $dir = shift;
+ my $x = $dirFiles{$dir};
+ if (!defined $x) {
+ $x = [];
+ $dirFiles{$dir} = $x;
+ }
+ return $x;
+}
+
+sub ProcessFile {
+ my $file = $_;
+ my $dir = $File::Find::dir;
+ # Record if a CMake file was found.
+ if ($file eq "CMakeLists.txt") {
+ $dirCMake{$dir} = $File::Find::name;
+ return 0;
+ }
+ # Grab the extension of the file.
+ $file =~ /\.([^.]+)$/;
+ my $ext = $1;
+ my $files;
+ foreach my $x (@fileTypes) {
+ if ($ext eq $x) {
+ if (!defined $files) {
+ $files = GetFiles($dir);
+ }
+ push @$files, $file;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+sub EmitCMakeList {
+ my $dir = shift;
+ my $files = $dirFiles{$dir};
+
+ if (!defined $files) {
+ return;
+ }
+
+ foreach my $file (sort @$files) {
+ print OUT " ";
+ print OUT $file;
+ print OUT "\n";
+ }
+}
+
+sub UpdateCMake {
+ my $cmakeList = shift;
+ my $dir = shift;
+ my $cmakeListNew = $cmakeList . ".new";
+ open(IN, $cmakeList);
+ open(OUT, ">", $cmakeListNew);
+ my $foundLibrary = 0;
+
+ while(<IN>) {
+ if (!$foundLibrary) {
+ print OUT $_;
+ if (/^add_clang_library\(/ || /^add_llvm_library\(/ || /^add_llvm_target\(/
+ || /^add_executable\(/) {
+ $foundLibrary = 1;
+ EmitCMakeList($dir);
+ }
+ }
+ else {
+ if (/\)/) {
+ print OUT $_;
+ $foundLibrary = 0;
+ }
+ }
+ }
+
+ close(IN);
+ close(OUT);
+
+ open(FILE, $cmakeList) or
+ die("Cannot open $cmakeList when computing digest\n");
+ binmode FILE;
+ my $digestA = Digest::MD5->new->addfile(*FILE)->hexdigest;
+ close(FILE);
+
+ open(FILE, $cmakeListNew) or
+ die("Cannot open $cmakeListNew when computing digest\n");
+ binmode FILE;
+ my $digestB = Digest::MD5->new->addfile(*FILE)->hexdigest;
+ close(FILE);
+
+ if ($digestA ne $digestB) {
+ move($cmakeListNew, $cmakeList);
+ return 1;
+ }
+
+ unlink($cmakeListNew);
+ return 0;
+}
+
+sub UpdateCMakeFiles {
+ foreach my $dir (sort keys %dirCMake) {
+ if (UpdateCMake($dirCMake{$dir}, $dir)) {
+ print "Updated: $dir\n";
+ }
+ }
+}
+
+find({ wanted => \&ProcessFile, follow => 1 }, '.');
+UpdateCMakeFiles();
+
diff --git a/contrib/llvm/utils/bugpoint/RemoteRunSafely.sh b/contrib/llvm/utils/bugpoint/RemoteRunSafely.sh
new file mode 100644
index 0000000..f390e33
--- /dev/null
+++ b/contrib/llvm/utils/bugpoint/RemoteRunSafely.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+#
+# Program: RemoteRunSafely.sh
+#
+# Synopsis: This script simply runs another program remotely using ssh.
+# It always returns the another program exit code or exit with
+# code 255 which indicates that the program could not be executed.
+#
+# Syntax:
+#
+# RemoteRunSafely.sh <hostname> [-l <login_name>] [-p <port>]
+# <program> <args...>
+#
+# where:
+# <hostname> is the remote host to execute the program,
+# <login_name> is the username on the remote host,
+# <port> is the port used by the remote client,
+# <program> is the path to the program to run,
+# <args...> are the arguments to pass to the program.
+#
+
+printUsageAndExit()
+{
+ echo "Usage:"
+ echo "./RemoteRunSafely.sh <hostname> [-l <login_name>] [-p <port>] " \
+ "<program> <args...>"
+ exit 255
+}
+
+moreArgsExpected()
+{
+ # $1 - remaining number of arguments
+ # $2 - number of arguments to shift
+ if [ $1 -lt $2 ]
+ then
+ echo "Error: Wrong number of argumants."
+ printUsageAndExit
+ fi
+}
+
+# Save a copy of the original arguments in a string before we
+# clobber them with the shift command.
+ORIG_ARGS="$*"
+#DEBUG: echo 'GOT: '$ORIG_ARGS
+
+moreArgsExpected $# 1
+RHOST=$1
+shift 1
+
+RUSER=`id -un`
+RCLIENT=ssh
+RPORT=
+WORKING_DIR=
+
+moreArgsExpected $# 1
+if [ $1 = "-l" ]; then
+ moreArgsExpected $# 2
+ RUSER=$2
+ shift 2
+fi
+moreArgsExpected $# 1
+if [ $1 = "-p" ]; then
+ moreArgsExpected $# 2
+ RPORT="-p $2"
+ shift 2
+fi
+
+moreArgsExpected $# 1
+PROGRAM=$(basename $1)
+WORKING_DIR=$(dirname $1)
+shift 1
+
+#DEBUG: echo 'DIR='${0%%`basename $0`}
+#DEBUG: echo 'RHOST='$RHOST
+#DEBUG: echo 'RUSER='$RUSER
+#DEBUG: echo 'PROGRAM='$PROGRAM
+#DEBUG: echo 'WORKING_DIR='$WORKING_DIR
+#DEBUG: echo 'ARGS='$*
+
+# Sanity check
+if [ "$RHOST" = "" -o "$PROGRAM" = "" ]; then
+ printUsageAndExit
+fi
+
+# Local program file must exist and be execuatble
+local_program=$WORKING_DIR"/"$PROGRAM
+if [ ! -x "$local_program" ]; then
+ echo "File "$local_program" does not exist or is not an executable.."
+ exit 255
+fi
+
+connection=$RUSER'@'$RHOST
+remote="./"$PROGRAM
+(
+ cat $local_program | \
+ $RCLIENT $connection $RPORT \
+ 'rm -f '$remote' ; ' \
+ 'cat > '$remote' ; chmod +x '$remote' ; '$remote' '$*' ; ' \
+ 'err=$? ; rm -f '$remote' ; exit $err'
+)
+err=$?
+
+#DEBUG: echo script exit $err
+exit $err
+
diff --git a/contrib/llvm/utils/buildit/GNUmakefile b/contrib/llvm/utils/buildit/GNUmakefile
new file mode 100644
index 0000000..54577e2
--- /dev/null
+++ b/contrib/llvm/utils/buildit/GNUmakefile
@@ -0,0 +1,131 @@
+# LLVM LOCAL file build machinery
+# LLVM Compiler Makefile for use by buildit.
+#
+# This makefile is intended only for use with B&I buildit. For "normal" builds
+# use the conventional top-level makefile.
+#
+# You can specify TARGETS=ppc (or i386) on the buildit command line to limit the
+# build to just one target. The default is for ppc and i386. The compiler
+# targetted at this host gets built anyway, but not installed unless it's listed
+# in TARGETS.
+
+# Include the set of standard Apple makefile definitions.
+ifndef CoreOSMakefiles
+CoreOSMakefiles = $(MAKEFILEPATH)/CoreOS
+endif
+include $(CoreOSMakefiles)/Standard/Standard.make
+
+# Enable Apple extensions to (gnu)make.
+USE_APPLE_PB_SUPPORT = all
+
+RC_ARCHS := ppc i386
+HOSTS = $(RC_ARCHS)
+targets = echo $(RC_ARCHS)
+TARGETS := $(shell $(targets))
+
+SRCROOT = .
+
+SRC = $(shell cd $(SRCROOT) && pwd | sed s,/private,,)
+OBJROOT = $(SRC)/obj
+SYMROOT = $(OBJROOT)/../sym
+DSTROOT = $(OBJROOT)/../dst
+
+#######################################################################
+
+PREFIX = /Developer/usr/local
+
+# Unless assertions are forced on in the GMAKE command line, disable them.
+ifndef ENABLE_ASSERTIONS
+ENABLE_ASSERTIONS := no
+endif
+
+# Default is optimized build.
+ifeq ($(LLVM_DEBUG),1)
+LLVM_OPTIMIZED := no
+else
+LLVM_OPTIMIZED := yes
+endif
+
+# Default to not install libLTO.dylib.
+INSTALL_LIBLTO := no
+
+# Default to do a native build, not a cross-build for an ARM host or simulator.
+ARM_HOSTED_BUILD := no
+IOS_SIM_BUILD := no
+
+ifndef RC_ProjectSourceVersion
+RC_ProjectSourceVersion = 9999
+endif
+
+ifndef RC_ProjectSourceSubversion
+RC_ProjectSourceSubversion = 0
+endif
+
+# NOTE : Always put version numbers at the end because they are optional.
+install: $(OBJROOT) $(SYMROOT) $(DSTROOT)
+ cd $(OBJROOT) && \
+ $(SRC)/utils/buildit/build_llvm "$(RC_ARCHS)" "$(TARGETS)" \
+ $(SRC) $(PREFIX) $(DSTROOT) $(SYMROOT) \
+ $(ENABLE_ASSERTIONS) $(LLVM_OPTIMIZED) $(INSTALL_LIBLTO) \
+ $(ARM_HOSTED_BUILD) $(IOS_SIM_BUILD) \
+ $(RC_ProjectSourceVersion) $(RC_ProjectSourceSubversion)
+
+EmbeddedHosted:
+ $(MAKE) ARM_HOSTED_BUILD=yes PREFIX=/usr/local install
+
+# When building for the iOS simulator, MACOSX_DEPLOYMENT_TARGET is not set
+# by default, but it needs to be set when building tools that run on the host
+# (e.g., tblgen), so set it here.
+EmbeddedSim:
+ export MACOSX_DEPLOYMENT_TARGET=`sw_vers -productVersion`; \
+ $(MAKE) IOS_SIM_BUILD=yes PREFIX=$(SDKROOT)/usr/local install
+
+# installhdrs does nothing, because the headers aren't useful until
+# the compiler is installed.
+installhdrs:
+
+# We build and install in one shell script.
+build:
+
+installsrc:
+ @echo
+ @echo ++++++++++++++++++++++
+ @echo + Installing sources +
+ @echo ++++++++++++++++++++++
+ @echo
+ if [ $(SRCROOT) != . ]; then \
+ $(PAX) -rw . $(SRCROOT); \
+ fi
+ find -d "$(SRCROOT)" \( -type d -a -name .svn -o \
+ -type f -a -name .DS_Store -o \
+ -name \*~ -o -name .\#\* \) \
+ -exec rm -rf {} \;
+ rm -rf "$(SRCROOT)/test"
+
+#######################################################################
+
+clean:
+ @echo
+ @echo ++++++++++++
+ @echo + Cleaning +
+ @echo ++++++++++++
+ @echo
+ @if [ -d $(OBJROOT) -a "$(OBJROOT)" != / ]; then \
+ echo '*** DELETING ' $(OBJROOT); \
+ rm -rf $(OBJROOT); \
+ fi
+ @if [ -d $(SYMROOT) -a "$(SYMROOT)" != / ]; then \
+ echo '*** DELETING ' $(SYMROOT); \
+ rm -rf $(SYMROOT); \
+ fi
+ @if [ -d $(DSTROOT) -a "$(DSTROOT)" != / ]; then \
+ echo '*** DELETING ' $(DSTROOT); \
+ rm -rf $(DSTROOT); \
+ fi
+
+#######################################################################
+
+$(OBJROOT) $(SYMROOT) $(DSTROOT):
+ mkdir -p $@
+
+.PHONY: install installsrc clean EmbeddedHosted EmbeddedSim
diff --git a/contrib/llvm/utils/buildit/build_llvm b/contrib/llvm/utils/buildit/build_llvm
new file mode 100755
index 0000000..39ec1cc
--- /dev/null
+++ b/contrib/llvm/utils/buildit/build_llvm
@@ -0,0 +1,373 @@
+#!/bin/sh
+# LLVM LOCAL file B&I
+
+set -x
+
+# Build LLVM the "Apple way".
+# Parameters:
+
+# The first parameter is a space-separated list of the architectures the
+# compilers will run on. For instance, "ppc i386". If the current machine
+# isn't in the list, it will (effectively) be added.
+HOSTS="$1"
+
+# The second parameter is a space-separated list of the architectures the
+# compilers will generate code for. If the current machine isn't in the list, a
+# compiler for it will get built anyway, but won't be installed.
+# FIXME: The list of targets is currently hard-coded and TARGETS is not used.
+TARGETS="$2"
+
+# The third parameter is the path to the compiler sources. There should be a
+# shell script named 'configure' in this directory. This script makes a copy...
+ORIG_SRC_DIR="$3"
+
+# The fourth parameter is the location where the LLVM will be installed. You can
+# move it once it's built, so this mostly controls the layout of $DEST_DIR.
+DEST_ROOT="$4"
+
+# The fifth parameter is the place where the compiler will be copied once it's
+# built.
+DEST_DIR="$5"
+
+# The sixth parameter is a directory in which to place information (like
+# unstripped executables and generated source files) helpful in debugging the
+# resulting compiler.
+SYM_DIR="$6"
+
+# The seventh parameter is a yes/no that indicates whether assertions should be
+# enabled in the LLVM libs/tools.
+LLVM_ASSERTIONS="$7"
+
+# The eighth parameter is a yes/no that indicates whether this is an optimized
+# build.
+LLVM_OPTIMIZED="$8"
+
+# The ninth parameter is a yes/no that indicates whether libLTO.dylib
+# should be installed.
+INSTALL_LIBLTO="$9"
+
+# A yes/no parameter that controls whether to cross-build for an ARM host.
+ARM_HOSTED_BUILD="${10}"
+
+# A yes/no parameter that controls whether to cross-build for the iOS simulator
+IOS_SIM_BUILD="${11}"
+
+# The version number of the submission, e.g. 1007.
+LLVM_SUBMIT_VERSION="${12}"
+
+# The subversion number of the submission, e.g. 03.
+LLVM_SUBMIT_SUBVERSION="${13}"
+
+# The current working directory is where the build will happen. It may already
+# contain a partial result of an interrupted build, in which case this script
+# will continue where it left off.
+DIR=`pwd`
+
+DARWIN_VERS=`uname -r | sed 's/\..*//'`
+echo DARWIN_VERS = $DARWIN_VERS
+
+################################################################################
+# Run the build.
+
+# Create the source tree we'll actually use to build, deleting
+# tcl since it doesn't actually build properly in a cross environment
+# and we don't really need it.
+SRC_DIR=$DIR/src
+rm -rf $SRC_DIR || exit 1
+mkdir $SRC_DIR || exit 1
+ln -s $ORIG_SRC_DIR/* $SRC_DIR/ || exit 1
+# We can't use the top-level Makefile as-is. Remove the soft link:
+rm $SRC_DIR/Makefile || exit 1
+# Now create our own by editing the top-level Makefile, deleting every line marked "Apple-style":
+sed -e '/[Aa]pple-style/d' -e '/include.*GNUmakefile/d' $ORIG_SRC_DIR/Makefile > $SRC_DIR/Makefile || exit 1
+
+# Build the LLVM tree universal.
+mkdir -p $DIR/obj-llvm || exit 1
+cd $DIR/obj-llvm || exit 1
+
+if [ "$ARM_HOSTED_BUILD" = yes ]; then
+ # The cross-tools' build process expects to find an existing cross toolchain
+ # under names like 'arm-apple-darwin$DARWIN_VERS-as'; so make them.
+ rm -rf $DIR/bin || exit 1
+ mkdir $DIR/bin || exit 1
+ for prog in ar nm ranlib strip lipo ld as ; do
+ P=$DIR/bin/arm-apple-darwin$DARWIN_VERS-${prog}
+ T=`xcrun -sdk $SDKROOT -find ${prog}`
+ echo '#!/bin/sh' > $P || exit 1
+ echo 'exec '$T' "$@"' >> $P || exit 1
+ chmod a+x $P || exit 1
+ done
+ # Try to use the platform llvm-gcc. Fall back to gcc if it's not available.
+ for prog in gcc g++ ; do
+ P=$DIR/bin/arm-apple-darwin$DARWIN_VERS-${prog}
+ T=`xcrun -sdk $SDKROOT -find llvm-${prog}`
+ if [ "x$T" = "x" ] ; then
+ T=`xcrun -sdk $SDKROOT -find ${prog}`
+ fi
+ echo '#!/bin/sh' > $P || exit 1
+ echo 'exec '$T' -arch armv6 -isysroot '${SDKROOT}' "$@"' >> $P || exit 1
+ chmod a+x $P || exit 1
+ done
+
+ PATH=$DIR/bin:$PATH
+# otherwise, try to use llvm-gcc if it's available
+elif [ $DARWIN_VERS -gt 9 ]; then
+ # If the user has set CC or CXX, respect their wishes. If not,
+ # compile with LLVM-GCC/LLVM-G++ if available; if LLVM is not
+ # available, fall back to usual GCC/G++ default.
+ savedPATH=$PATH ; PATH="/Developer/usr/bin:$PATH"
+ XTMPCC=$(which llvm-gcc)
+ if [ x$CC = x -a x$XTMPCC != x ] ; then export CC=$XTMPCC ; fi
+ XTMPCC=$(which llvm-g++)
+ if [ x$CXX = x -a x$XTMPCC != x ] ; then export CXX=$XTMPCC ; fi
+ PATH=$savedPATH
+ unset XTMPCC savedPATH
+fi
+
+if [ "$ARM_HOSTED_BUILD" = yes ]; then
+ configure_opts="--enable-targets=arm --host=arm-apple-darwin10 \
+ --target=arm-apple-darwin10 --build=i686-apple-darwin10"
+elif [ "$IOS_SIM_BUILD" = yes ]; then
+ # Use a non-standard "darwin_sim" host triple to trigger a cross-build.
+ configure_opts="--enable-targets=x86 --host=i686-apple-darwin_sim \
+ --build=i686-apple-darwin10"
+else
+ configure_opts="--enable-targets=arm,x86,powerpc,cbe"
+fi
+
+if [ \! -f Makefile.config ]; then
+ $SRC_DIR/configure --prefix=$DEST_DIR$DEST_ROOT $configure_opts \
+ --enable-assertions=$LLVM_ASSERTIONS \
+ --enable-optimized=$LLVM_OPTIMIZED \
+ --disable-bindings \
+ || exit 1
+fi
+
+SUBVERSION=`echo $RC_ProjectSourceVersion | sed -e 's/[^.]*\.\([0-9]*\).*/\1/'`
+
+if [ "x$SUBVERSION" != "x$RC_ProjectSourceVersion" ]; then
+ LLVM_SUBMIT_SUBVERSION=`printf "%02d" $SUBVERSION`
+ RC_ProjectSourceVersion=`echo $RC_ProjectSourceVersion | sed -e 's/\..*//'`
+ LLVM_SUBMIT_VERSION=$RC_ProjectSourceVersion
+fi
+
+if [ "x$LLVM_SUBMIT_SUBVERSION" = "x00" -o "x$LLVM_SUBMIT_SUBVERSION" = "x0" ]; then
+ LLVM_VERSION="$LLVM_SUBMIT_VERSION"
+else
+ LLVM_VERSION="$LLVM_SUBMIT_VERSION-$LLVM_SUBMIT_SUBVERSION"
+fi
+
+GCC_VER=`cc --version 2>/dev/null | sed 1q`
+
+if echo "$GCC_VER" | grep GCC > /dev/null; then
+ GCC_VER=`echo $GCC_VER | sed -e 's/.*(GCC) \([0-9.][0-9.]*\).*/\1/'`
+ MAJ_VER=`echo $GCC_VER | sed 's/\..*//'`
+ MIN_VER=`echo $GCC_VER | sed 's/[^.]*\.\([0-9]*\).*/\1/'`
+fi
+
+JOBS_FLAG=""
+
+# Note: If compiling with GCC 4.0, don't pass the -jN flag. Building universal
+# already has parallelism and we don't want to make the builders hit swap by
+# firing off too many gccs at the same time.
+if [ "x$MAJ_VER" != "x4" -o "x$MIN_VER" != "x0" ]; then
+ # Figure out how many make processes to run.
+ SYSCTL=`sysctl -n hw.activecpu`
+
+ # hw.activecpu only available in 10.2.6 and later
+ if [ -z "$SYSCTL" ]; then
+ SYSCTL=`sysctl -n hw.ncpu`
+ fi
+
+ # sysctl -n hw.* does not work when invoked via B&I chroot /BuildRoot.
+ # Builders can default to 2, since even if they are single processor,
+ # nothing else is running on the machine.
+ if [ -z "$SYSCTL" ]; then
+ SYSCTL=2
+ fi
+
+ JOBS_FLAG="-j $SYSCTL"
+fi
+
+make $JOBS_FLAG $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$HOSTS" \
+ UNIVERSAL_SDK_PATH=$SDKROOT \
+ NO_RUNTIME_LIBS=1 \
+ DISABLE_EDIS=1 \
+ DEBUG_SYMBOLS=1 \
+ LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \
+ LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \
+ CXXFLAGS="-DLLVM_VERSION_INFO='\" Apple Build #$LLVM_VERSION\"'" \
+ VERBOSE=1
+
+if [ $? != 0 ] ; then
+ echo "error: LLVM 'make' failed!"
+ exit 1
+fi
+
+################################################################################
+# Construct the actual destination root, by copying stuff from $DIR/dst-* to
+# $DEST_DIR, with occasional 'lipo' commands.
+
+cd $DEST_DIR || exit 1
+
+# Clean out DEST_DIR in case -noclean was passed to buildit.
+rm -rf * || exit 1
+
+cd $DIR/obj-llvm || exit 1
+
+# Install the tree into the destination directory.
+make $LOCAL_MAKEFLAGS $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$HOSTS" \
+ NO_RUNTIME_LIBS=1 \
+ DISABLE_EDIS=1 \
+ DEBUG_SYMBOLS=1 \
+ LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \
+ LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \
+ OPTIMIZE_OPTION='-O3' VERBOSE=1 install
+
+if ! test $? == 0 ; then
+ echo "error: LLVM 'make install' failed!"
+ exit 1
+fi
+
+# Install Version.h
+LLVM_MINOR_VERSION=`echo $LLVM_SUBMIT_SUBVERSION | sed -e 's,0*\([1-9][0-9]*\),\1,'`
+if [ "x$LLVM_MINOR_VERSION" = "x" ]; then
+ LLVM_MINOR_VERSION=0
+fi
+RC_ProjectSourceSubversion=`printf "%d" $LLVM_MINOR_VERSION`
+echo "#define LLVM_VERSION ${RC_ProjectSourceVersion}" > $DEST_DIR$DEST_ROOT/include/llvm/Version.h
+echo "#define LLVM_MINOR_VERSION ${RC_ProjectSourceSubversion}" >> $DEST_DIR$DEST_ROOT/include/llvm/Version.h
+
+if [ "x$LLVM_DEBUG" != "x1" ]; then
+ # Strip local symbols from llvm libraries.
+ #
+ # Use '-l' to strip i386 modules. N.B. that flag doesn't work with kext or
+ # PPC objects!
+ strip -Sl $DEST_DIR$DEST_ROOT/lib/*.[oa]
+ for f in `ls $DEST_DIR$DEST_ROOT/lib/*.so`; do
+ strip -Sxl $f
+ done
+fi
+
+# Copy over the tblgen utility.
+cp `find $DIR -name tblgen` $DEST_DIR$DEST_ROOT/bin
+
+# Remove .dir files
+cd $DEST_DIR$DEST_ROOT
+rm -f bin/.dir etc/llvm/.dir lib/.dir
+
+# Remove PPC64 fat slices.
+cd $DEST_DIR$DEST_ROOT/bin
+if [ $MACOSX_DEPLOYMENT_TARGET = "10.4" ]; then
+ find . -perm 755 -type f \! \( -name '*gccas' -o -name '*gccld' -o -name llvm-config \) \
+ -exec lipo -extract ppc -extract i386 {} -output {} \;
+elif [ $MACOSX_DEPLOYMENT_TARGET = "10.5" ]; then
+ find . -perm 755 -type f \! \( -name '*gccas' -o -name '*gccld' -o -name llvm-config \) \
+ -exec lipo -extract ppc7400 -extract i386 {} -output {} \;
+else
+ find . -perm 755 -type f \! \( -name '*gccas' -o -name '*gccld' -o -name llvm-config \) \
+ -exec lipo -extract ppc7400 -extract i386 -extract x86_64 {} -output {} \;
+fi
+
+# The Hello dylib is an example of how to build a pass. No need to install it.
+rm $DEST_DIR$DEST_ROOT/lib/LLVMHello.dylib
+
+# Compress manpages
+MDIR=$DEST_DIR$DEST_ROOT/share/man/man1
+gzip -f $MDIR/*
+
+################################################################################
+# Create SYM_DIR with information required for debugging.
+
+# Figure out how many make processes to run.
+SYSCTL=`sysctl -n hw.activecpu`
+
+# hw.activecpu only available in 10.2.6 and later
+if [ -z "$SYSCTL" ]; then
+ SYSCTL=`sysctl -n hw.ncpu`
+fi
+
+# sysctl -n hw.* does not work when invoked via B&I chroot /BuildRoot. Builders
+# can default to 2, since even if they are single processor, nothing else is
+# running on the machine.
+if [ -z "$SYSCTL" ]; then
+ SYSCTL=2
+fi
+
+cd $SYM_DIR || exit 1
+
+# Clean out SYM_DIR in case -noclean was passed to buildit.
+rm -rf * || exit 1
+
+# Generate .dSYM files
+find $DEST_DIR -perm -0111 -type f \
+ ! \( -name '*.la' -o -name gccas -o -name gccld -o -name llvm-config -o -name '*.a' \) \
+ -print | xargs -n 1 -P ${SYSCTL} dsymutil
+
+# Save .dSYM files and .a archives
+cd $DEST_DIR || exit 1
+find . \( -path \*.dSYM/\* -or -name \*.a \) -print \
+ | cpio -pdml $SYM_DIR || exit 1
+
+# Save source files.
+mkdir $SYM_DIR/src || exit 1
+cd $DIR || exit 1
+find obj-* -name \*.\[chy\] -o -name \*.cpp -print \
+ | cpio -pdml $SYM_DIR/src || exit 1
+
+################################################################################
+# Install and strip libLTO.dylib
+
+cd $DEST_DIR$DEST_ROOT
+if [ "$INSTALL_LIBLTO" = "yes" ]; then
+ DT_HOME="$DEST_DIR/Developer/usr"
+ mkdir -p $DT_HOME/lib
+ mv lib/libLTO.dylib $DT_HOME/lib/libLTO.dylib
+
+ # Save a copy of the unstripped dylib
+ mkdir -p $SYM_DIR/Developer/usr/lib
+ cp $DT_HOME/lib/libLTO.dylib $SYM_DIR/Developer/usr/lib/libLTO.dylib
+
+ # Use '-l' to strip i386 modules. N.B. that flag doesn't work with kext or
+ # PPC objects!
+ strip -arch all -Sl $DT_HOME/lib/libLTO.dylib
+
+ if [ "x$DISABLE_USR_LINKS" == "x" ]; then
+ # Add a symlink in /usr/lib for B&I.
+ mkdir -p $DEST_DIR/usr/lib/
+ (cd $DEST_DIR/usr/lib && \
+ ln -s ../../Developer/usr/lib/libLTO.dylib ./libLTO.dylib)
+ fi
+else
+ rm -f lib/libLTO.dylib
+fi
+rm -f lib/libLTO.a lib/libLTO.la
+
+################################################################################
+# Remove debugging information from DEST_DIR.
+
+cd $DIR || exit 1
+
+find $DEST_DIR -name \*.a -print | xargs ranlib || exit 1
+find $DEST_DIR -name \*.dSYM -print | xargs rm -r || exit 1
+
+# Strip debugging information from files
+#
+# Use '-l' to strip i386 modules. N.B. that flag doesn't work with kext or
+# PPC objects!
+find $DEST_DIR -perm -0111 -type f \
+ ! \( -name '*.la' -o -name gccas -o -name gccld -o -name llvm-config \) \
+ -print | xargs -n 1 -P ${SYSCTL} strip -arch all -Sl
+
+chgrp -h -R wheel $DEST_DIR
+chgrp -R wheel $DEST_DIR
+
+################################################################################
+# Remove the docs directory
+
+rm -rf $DEST_DIR$DEST_ROOT/docs
+
+################################################################################
+# w00t! Done!
+
+exit 0
diff --git a/contrib/llvm/utils/cgiplotNLT.pl b/contrib/llvm/utils/cgiplotNLT.pl
new file mode 100755
index 0000000..0360e41
--- /dev/null
+++ b/contrib/llvm/utils/cgiplotNLT.pl
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+#takes a test and a program from a dp and produces a gnuplot script
+#use like perl plotNLT.pl password Programs/MultiSource/Benchmarks/ASCI_Purple/SMG2000/smg2000 llc
+
+use CGI;
+use DBI;
+my $q = new CGI;
+
+# database information
+$db="llvmalpha";
+$host="localhost";
+$userid="llvmdbuser";
+$passwd=$q->param('pwd');
+$connectionInfo="dbi:mysql:$db;$host";
+
+# make connection to database
+$dbh = DBI->connect($connectionInfo,$userid,$passwd) or die DBI->errstr;
+
+
+$count = 0;
+while ($q->param('n' . $count))
+ {
+ $count++;
+ }
+
+$| = 1;
+print "Content-type: image/png", "\n\n";
+
+open CMDSTREAM, "|gnuplot";
+#open CMDSTREAM, "|echo";
+
+print CMDSTREAM "set terminal png\n";
+print CMDSTREAM "set output\n";
+print CMDSTREAM "set xdata time\n";
+print CMDSTREAM 'set timefmt "%Y-%m-%d"';
+print CMDSTREAM "\nplot";
+for ($iter = 0; $iter < $count; $iter++) {
+ if ($iter)
+ { print CMDSTREAM ","; }
+ print CMDSTREAM " '-' using 1:2 title \"" . $q->param('t' . $iter) . "," . $q->param('n' . $iter) . "\"with lines";
+}
+
+print CMDSTREAM "\n";
+
+for ($iter = 0; $iter < $count; $iter++) {
+
+ $prog = $q->param('n' . $iter);
+ $test = $q->param('t' . $iter);
+
+ $query = "Select RUN, VALUE from Tests where TEST = '$test' AND NAME = '$prog' ORDER BY RUN";
+ #print "\n$query\n";
+
+ my $sth = $dbh->prepare( $query) || die "Can't prepare statement: $DBI::errstr";;
+
+ my $rc = $sth->execute or die DBI->errstr;
+
+ while(($da,$v) = $sth->fetchrow_array)
+ {
+ print CMDSTREAM "$da $v\n";
+ }
+
+ print CMDSTREAM "e\n";
+}
+print CMDSTREAM "exit\n";
+close CMDSTREAM;
+
+# disconnect from database
+$dbh->disconnect;
diff --git a/contrib/llvm/utils/check-each-file b/contrib/llvm/utils/check-each-file
new file mode 100755
index 0000000..bd76333
--- /dev/null
+++ b/contrib/llvm/utils/check-each-file
@@ -0,0 +1,150 @@
+#!/bin/sh
+# check-each-file
+# Used to narrow down a miscompilation to one .o file from a list. Please read
+# the usage procedure, below, for command-line syntax (or run it with --help).
+# This script depends on the llvm-native-gcc script.
+
+if [ x$1 = x--make-linker-script ]
+then
+ program=$2
+ linker=./link-$program
+ echo "Building $program with llvm-native-gcc"
+ rm -f $program
+ gmake -e $program CC=llvm-native-gcc CXX=llvm-native-gxx
+ echo "Erasing $program and re-linking it"
+ rm -f $program
+ echo "rm -f $program" > $linker
+ gmake -n $program >> $linker
+ chmod 755 $linker
+ echo "Linker script created in $linker; testing it out"
+ output=`./$linker 2>&1`
+ case "$output" in
+ *undefined*reference*__main*)
+ echo "$program appears to need a dummy __main function; adding one"
+ echo "void __main () { }" > __main.c
+ gcc -c __main.c
+ echo "Done; rebuilding $linker"
+ echo "rm -f $program" > $linker
+ gmake -n $program 2>&1 | sed '/gcc/s/$/__main.o/' >> $linker
+ ./$linker > /dev/null 2>&1
+ if [ ! -x $program ]
+ then
+ echo "WARNING: linker script didn't work"
+ fi
+ ;;
+ *)
+ if [ ! -x $program ]
+ then
+ echo "WARNING: linker script didn't work"
+ fi
+ ;;
+ esac
+ echo "Linker script created in $linker; please check it manually"
+ exit 0
+fi
+
+checkfiles="$1"
+program="$2"
+linker="$3"
+checker="$4"
+
+usage () {
+ myname=`basename $0`
+ echo "$myname --make-linker-script PROGRAM"
+ echo "$myname OBJECTS-FILE PROGRAM LINKER CHECKER"
+ echo ""
+ echo "OBJECTS-FILE is a text file containing the names of all the .o files"
+ echo "PROGRAM is the name of the executable under test"
+ echo "(there must also exist a Makefile in the current directory which"
+ echo "has PROGRAM as a target)"
+ echo "LINKER is the script that builds PROGRAM; try --make-linker-script"
+ echo "to automatically generate it"
+ echo "CHECKER is the script that exits 0 if PROGRAM is ok, 1 if it is not OK"
+ echo "(LINKER and CHECKER must be in your PATH, or you should specify ./)"
+ echo ""
+ echo "Bugs to <gaeke@uiuc.edu>."
+ exit 1
+}
+
+if [ x$1 = x--help ]
+then
+ usage
+fi
+
+if [ -z "$checkfiles" ]
+then
+ echo "ERROR: Must specify name of file w/ list of objects as 1st arg."
+ echo "(got \"$checkfiles\")"
+ usage
+fi
+if [ ! -f "$checkfiles" ]
+then
+ echo "ERROR: $checkfiles not found"
+ usage
+fi
+if [ -z "$program" ]
+then
+ echo "ERROR: Must specify name of program as 2nd arg."
+ usage
+fi
+if [ -z "$linker" ]
+then
+ echo "ERROR: Must specify name of link script as 3rd arg."
+ usage
+fi
+if [ ! -x "$linker" ]
+then
+ echo "ERROR: $linker not found or not executable"
+ echo "You may wish to try: $0 --make-linker-script $program"
+ usage
+fi
+if [ -z "$checker" ]
+then
+ echo "ERROR: Must specify name of $program check script as 3rd arg."
+ usage
+fi
+if [ ! -x "$checker" ]
+then
+ echo "ERROR: $checker not found or not executable"
+ usage
+fi
+
+files=`cat $checkfiles`
+echo "Recompiling everything with llvm-native-gcc"
+for f in $files
+do
+ rm -f $f
+ gmake $f CC=llvm-native-gcc CXX=llvm-native-gxx
+done
+rm -f $program
+$linker
+if $checker
+then
+ echo "Sorry, I can't help you, $program is OK when compiled with llvm-native-gcc"
+ exit 1
+fi
+for f in $files
+do
+ echo Trying to compile $f with native gcc and rebuild $program
+ mv ${f} ${f}__OLD__
+ gmake ${f} CC=gcc > /dev/null 2>&1
+ $linker
+ echo Checking validity of new $program
+ if $checker
+ then
+ echo Program is OK
+ okfiles="$okfiles $f"
+ else
+ echo Program is not OK
+ notokfiles="$notokfiles $f"
+ fi
+ mv ${f}__OLD__ ${f}
+done
+echo ""
+echo "Program is OK when these files are recompiled with native gcc: "
+echo "$okfiles"
+echo ""
+echo "Program is not OK when these files are recompiled with native gcc: "
+echo "$notokfiles"
+echo ""
+exit 0
diff --git a/contrib/llvm/utils/codegen-diff b/contrib/llvm/utils/codegen-diff
new file mode 100755
index 0000000..2c3ac4c
--- /dev/null
+++ b/contrib/llvm/utils/codegen-diff
@@ -0,0 +1,135 @@
+#!/usr/bin/perl
+
+use Getopt::Std;
+$DEBUG = 0;
+
+sub parse_objdump_file {
+ my ($filename) = @_;
+ my @result;
+ open (INPUT, $filename) or die "$filename: $!\n";
+ print "opened objdump output file $filename\n" if $DEBUG;
+ while (<INPUT>) {
+ if (/\s*([0-9a-f]*):\t(([0-9a-f]{2} )+) *\t(.*)$/) {
+ my ($addr, $bytes, $instr) = ($1, $2, $4);
+ $addr = "0x" . $addr;
+ $bytes =~ s/\s*(.*\S)\s*/$1/; # trim any remaining whitespace
+ $instr =~ s/\s*(.*\S)\s*/$1/;
+ push (@result, {'addr' => $addr, 'bytes' => $bytes, 'instr' => $instr});
+ print "addr=$addr bytes='$bytes' instr='$instr'\n" if $DEBUG;
+ }
+ }
+ close INPUT;
+ return @result;
+}
+
+sub parse_gdb_file {
+ my ($filename) = @_;
+ my @result;
+ my $got_addr;
+ open (INPUT, $filename) or die "$filename: $!\n";
+ print "opened gdb output file $filename\n" if $DEBUG;
+ while (<INPUT>) {
+ if (/^(0x[0-9a-f]*):\t([^\t]*)\t[^:]*:\t((0x[0-9a-f]{2}\s*)+)\s*$/) {
+ my ($addr, $bytes, $instr) = ($1, $3, $2);
+ $bytes =~ s/0x//g;
+ $bytes =~ s/\s+/ /g; # regularize whitespace
+ $bytes =~ s/\s*(.*\S)\s*/$1/; # trim any remaining whitespace
+ $instr =~ s/\s*(.*\S)\s*/$1/;
+ push (@result, {'addr' => $addr, 'bytes' => $bytes, 'instr' => $instr});
+ print "addr=$addr bytes='$bytes' instr='$instr'\n" if $DEBUG;
+ } elsif (/^(0x[0-9a-f]*):\t$/) { # deal with gdb's line breaker
+ $got_addr = $1;
+ } elsif ($got_addr && /^ ([^\t]*)\t[^:]*:\t((0x[0-9a-f]{2}\s*)+)\s*$/) {
+ my ($addr, $bytes, $instr) = ($got_addr, $2, $1);
+ $bytes =~ s/0x//g;
+ $bytes =~ s/\s+/ /g; # regularize whitespace
+ $bytes =~ s/\s*(.*\S)\s*/$1/; # trim any remaining whitespace
+ $instr =~ s/\s*(.*\S)\s*/$1/;
+ push (@result, {'addr' => $addr, 'bytes' => $bytes, 'instr' => $instr});
+ print "addr=$addr bytes='$bytes' instr='$instr'\n" if $DEBUG;
+ undef $got_addr;
+ }
+ }
+ close INPUT;
+ return @result;
+}
+
+sub binary_diffs {
+ my ($objdump_file, $gdb_file) = @_;
+ my @file1 = parse_objdump_file ($objdump_file);
+ my @file2 = parse_gdb_file ($gdb_file);
+ my $lastrecord = ($#file1 >= $#file2) ? ($#file1) : ($#file2);
+ for (my $i = 0; $i <= $lastrecord; ++$i) {
+ my $d1 = $file1[$i];
+ my $d2 = $file2[$i];
+ if ($d1->{'bytes'} ne $d2->{'bytes'}) {
+ next if (($d1->{'instr'} eq $d2->{'instr'}) && $opt_d);
+ printf "0x%08x:\t%30s \t%s\n", 0+$d1->{'addr'}, $d1->{'bytes'}, $d1->{'instr'};
+ printf "0x%08x:\t%30s \t%s\n\n", 0+$d2->{'addr'}, $d2->{'bytes'}, $d2->{'instr'};
+ }
+ }
+}
+
+&getopts('d');
+$objdump_file = $ARGV[0];
+$gdb_file = $ARGV[1];
+binary_diffs ($objdump_file, $gdb_file);
+exit (0);
+__END__
+=pod
+
+=head1 NAME
+
+codegen-diff
+
+=head1 SYNOPSIS
+
+codegen-diff [-d] I<OBJDUMP-OUTPUT-FILE> I<GDB-DISASSEMBLY-FILE>
+
+=head1 DESCRIPTION
+
+B<codegen-diff> is a program that tries to show you the differences
+between the code that B<llc> generated and the code that B<lli> generated.
+
+The way you use it is as follows: first, you create I<OBJDUMP-OUTPUT-FILE>
+by running B<objdump> on the B<llc> compiled and linked binary. You need to
+trim down the result so it contains only the function of interest.
+
+Second, you create I<GDB-DISASSEMBLY-FILE> by running B<gdb>, with my patch
+to print out hex bytes in the B<disassemble> command output, on
+B<lli>. Set a breakpoint in C<Emitter::finishFunction()> and wait until
+the function you want is compiled. Then use the B<disassemble> command
+to print out the assembly dump of the function B<lli> just compiled.
+(Use C<lli -debug> to find out where the function starts and ends in memory.)
+It's easiest to save this output by using B<script>.
+
+Finally, you run B<codegen-diff>, as indicated in the Synopsis section of
+this manpage. It will print out a two-line stanza for each mismatched
+instruction, with the B<llc> version first, and the B<lli> version second.
+
+=head1 OPTIONS
+
+=over 4
+
+=item -d
+
+Don't show instructions where the bytes are different but they
+disassemble to the same thing. This puts a lot of trust in the
+disassembler, but it might help you highlight the more egregious cases
+of misassembly.
+
+=back
+
+=head1 AUTHOR
+
+B<codegen-diff> was written by Brian Gaeke.
+
+=head1 SEE ALSO
+
+L<gdb(1)>, L<objdump(1)>, L<script(1)>.
+
+You will need my B<gdb> patch:
+
+ http://llvm.cs.uiuc.edu/~gaeke/gdb-disassembly-print-bytes.patch
+
+=cut
diff --git a/contrib/llvm/utils/count/CMakeLists.txt b/contrib/llvm/utils/count/CMakeLists.txt
new file mode 100644
index 0000000..e124f61
--- /dev/null
+++ b/contrib/llvm/utils/count/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_executable(count
+ count.c
+ )
diff --git a/contrib/llvm/utils/count/Makefile b/contrib/llvm/utils/count/Makefile
new file mode 100644
index 0000000..8de076a
--- /dev/null
+++ b/contrib/llvm/utils/count/Makefile
@@ -0,0 +1,20 @@
+##===- utils/count/Makefile --------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TOOLNAME = count
+USEDLIBS =
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+# Don't install this utility
+NO_INSTALL = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/contrib/llvm/utils/count/count.c b/contrib/llvm/utils/count/count.c
new file mode 100644
index 0000000..ae96791
--- /dev/null
+++ b/contrib/llvm/utils/count/count.c
@@ -0,0 +1,50 @@
+/*===- count.c - The 'count' testing tool ---------------------------------===*\
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+\*===----------------------------------------------------------------------===*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+ unsigned Count, NumLines, NumRead;
+ char Buffer[4096], *End;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <expected line count>\n", argv[0]);
+ return 2;
+ }
+
+ Count = strtol(argv[1], &End, 10);
+ if (*End != '\0' && End != argv[1]) {
+ fprintf(stderr, "%s: invalid count argument '%s'\n", argv[0], argv[1]);
+ return 2;
+ }
+
+ NumLines = 0;
+ do {
+ unsigned i;
+
+ NumRead = fread(Buffer, 1, sizeof(Buffer), stdin);
+
+ for (i = 0; i != NumRead; ++i)
+ if (Buffer[i] == '\n')
+ ++NumLines;
+ } while (NumRead == sizeof(Buffer));
+
+ if (!feof(stdin)) {
+ fprintf(stderr, "%s: error reading stdin\n", argv[0]);
+ return 3;
+ }
+
+ if (Count != NumLines) {
+ fprintf(stderr, "Expected %d lines, got %d.\n", Count, NumLines);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/contrib/llvm/utils/countloc.sh b/contrib/llvm/utils/countloc.sh
new file mode 100755
index 0000000..4d1b775
--- /dev/null
+++ b/contrib/llvm/utils/countloc.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+##===- utils/countloc.sh - Counts Lines Of Code --------------*- Script -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This script finds all the source code files in the source code directories
+# (excluding certain things), runs "wc -l" on them to get the number of lines in
+# each file and then sums up and prints the total with awk.
+#
+# The script takes one optional option, -topdir, which specifies the top llvm
+# source directory. If it is not specified then the llvm-config tool is
+# consulted to find top source dir.
+#
+# Note that the implementation is based on llvmdo. See that script for more
+# details.
+##===----------------------------------------------------------------------===##
+
+if test $# -gt 1 ; then
+ if test "$1" = "-topdir" ; then
+ TOPDIR="$2"
+ shift; shift;
+ else
+ TOPDIR=`llvm-config --src-root`
+ fi
+fi
+
+if test -d "$TOPDIR" ; then
+ cd $TOPDIR
+ ./utils/llvmdo -topdir "$TOPDIR" -dirs "include lib tools test utils examples" -code-only wc -l | awk '\
+ BEGIN { loc=0; } \
+ { loc += $1; } \
+ END { print loc; }'
+else
+ echo "Can't find LLVM top directory"
+fi
diff --git a/contrib/llvm/utils/crosstool/ARM/README b/contrib/llvm/utils/crosstool/ARM/README
new file mode 100644
index 0000000..ba58583
--- /dev/null
+++ b/contrib/llvm/utils/crosstool/ARM/README
@@ -0,0 +1,37 @@
+HOWTO create an LLVM crosstool from x86_64/Linux to ARM/Linux
+=============================================================
+
+1. % llvm/utils/crosstool/create-snapshots.sh
+
+ This will create llvm-[REV_L].tar.bz2 and llvm-gcc-4.2-[REV_G].tar.bz2,
+ where:
+ REV_L is the revision at which "llvm" was checked out, and
+ REV_G is the revision at which "llvm-gcc-4.2" was checked out
+
+ Note that REV_L might REV_G might not be the same revision.
+
+2. Download CodeSourcery toolchain. The exact location depends on your
+ $CROSS_TARGET but the script will tell you what the location of the file is
+ if you run it without having the file available.
+
+ For example, if you're using $CROSS_TARGET == "arm-none-linux-gnueabi" then
+ you need to download:
+
+ http://www.codesourcery.com/sgpp/lite/arm/portal/package1787/public/arm-none-linux-gnueabi/arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
+
+ NOTE: simply changing $CROSS_TARGET and modifying the URL accordingly will
+ not work -- you'll need to go to http://www.codesourcery.com and find the
+ correct file, as the release number in the file will also be different (e.g.,
+ in the file above, the release number is "51").
+
+3. You can override most values in the script without modifying it, e.g.
+ $INSTALL_ROOT (if you want to install in directory other than /usr/local).
+
+ Run the script as:
+
+ % env INSTALL_ROOT=[dir to install in] \
+ CODE_SOURCERY_PKG_PATH=[dir where you downloaded CodeSourcery tarball] \
+ LLVM_PKG_PATH=[dir where you stored your LLVM and LLVM-GCC snapshots] \
+ LLVM_SVN_REV=${REV_L} \
+ LLVMGCC_SVN_REV=${REV_G} \
+ build-install-linux.sh
diff --git a/contrib/llvm/utils/crosstool/ARM/build-install-linux.sh b/contrib/llvm/utils/crosstool/ARM/build-install-linux.sh
new file mode 100755
index 0000000..f3f8df9
--- /dev/null
+++ b/contrib/llvm/utils/crosstool/ARM/build-install-linux.sh
@@ -0,0 +1,200 @@
+#!/bin/bash
+#
+# Compiles and installs a Linux/x86_64 -> Linux/ARM crosstool based on LLVM and
+# LLVM-GCC-4.2 using SVN snapshots in provided tarballs.
+
+set -o nounset
+set -o errexit
+
+echo -n "Welcome to LLVM Linux/X86_64 -> Linux/ARM crosstool "
+echo "builder/installer; some steps will require sudo privileges."
+
+readonly INSTALL_ROOT="${INSTALL_ROOT:-/usr/local/crosstool}"
+# Both $USER and root *must* have read/write access to this dir.
+readonly SCRATCH_ROOT=$(mktemp -d "${TMPDIR:-/tmp}/llvm-project.XXXXXX")
+readonly SRC_ROOT="${SCRATCH_ROOT}/src"
+readonly OBJ_ROOT="${SCRATCH_ROOT}/obj"
+
+readonly CROSS_HOST="x86_64-unknown-linux-gnu"
+readonly CROSS_TARGET="arm-none-linux-gnueabi"
+readonly CROSS_MARCH="${CROSS_MARCH:-armv6}"
+
+readonly CODE_SOURCERY="${INSTALL_ROOT}/codesourcery"
+readonly CODE_SOURCERY_PKG_PATH="${CODE_SOURCERY_PKG_PATH:-${HOME}/codesourcery}"
+readonly CODE_SOURCERY_HTTP="http://www.codesourcery.com/sgpp/lite/arm/portal/package1787/public"
+readonly CODE_SOURCERY_PKG="arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2"
+readonly CODE_SOURCERY_ROOT="${CODE_SOURCERY}/arm-2007q3"
+readonly CODE_SOURCERY_BIN="${CODE_SOURCERY_ROOT}/bin"
+# Make sure ${CROSS_TARGET}-* binutils are in command path
+export PATH="${CODE_SOURCERY_BIN}:${PATH}"
+
+readonly CROSS_TARGET_AS="${CODE_SOURCERY_BIN}/${CROSS_TARGET}-as"
+readonly CROSS_TARGET_LD="${CODE_SOURCERY_BIN}/${CROSS_TARGET}-ld"
+
+readonly SYSROOT="${CODE_SOURCERY_ROOT}/${CROSS_TARGET}/libc"
+
+readonly LLVM_PKG_PATH="${LLVM_PKG_PATH:-${HOME}/llvm-project/snapshots}"
+
+# Latest SVN revisions known to be working in this configuration.
+readonly LLVM_DEFAULT_REV="74530"
+readonly LLVMGCC_DEFAULT_REV="74535"
+
+readonly LLVM_PKG="llvm-${LLVM_SVN_REV:-${LLVM_DEFAULT_REV}}.tar.bz2"
+readonly LLVM_SRC_DIR="${SRC_ROOT}/llvm"
+readonly LLVM_OBJ_DIR="${OBJ_ROOT}/llvm"
+readonly LLVM_INSTALL_DIR="${INSTALL_ROOT}/${CROSS_TARGET}/llvm"
+
+readonly LLVMGCC_PKG="llvm-gcc-4.2-${LLVMGCC_SVN_REV:-${LLVMGCC_DEFAULT_REV}}.tar.bz2"
+readonly LLVMGCC_SRC_DIR="${SRC_ROOT}/llvm-gcc-4.2"
+readonly LLVMGCC_OBJ_DIR="${OBJ_ROOT}/llvm-gcc-4.2"
+readonly LLVMGCC_INSTALL_DIR="${INSTALL_ROOT}/${CROSS_TARGET}/llvm-gcc-4.2"
+
+readonly MAKE_OPTS="${MAKE_OPTS:--j2}"
+
+# Params:
+# $1: directory to be created
+# $2: optional mkdir command prefix, e.g. "sudo"
+createDir() {
+ if [[ ! -e $1 ]]; then
+ ${2:-} mkdir -p $1
+ elif [[ -e $1 && ! -d $1 ]]; then
+ echo "$1 exists but is not a directory; exiting."
+ exit 3
+ fi
+}
+
+sudoCreateDir() {
+ createDir $1 sudo
+ sudo chown ${USER} $1
+}
+
+# Prints out and runs the command, but without logging -- intended for use with
+# lightweight commands that don't have useful output to parse, e.g. mkdir, tar,
+# etc.
+runCommand() {
+ local message="$1"
+ shift
+ echo "=> $message"
+ echo "==> Running: $*"
+ $*
+}
+
+runAndLog() {
+ local message="$1"
+ local log_file="$2"
+ shift 2
+ echo "=> $message; log in $log_file"
+ echo "==> Running: $*"
+ # Pop-up a terminal with the output of the current command?
+ # e.g.: xterm -e /bin/bash -c "$* >| tee $log_file"
+ $* &> $log_file
+ if [[ $? != 0 ]]; then
+ echo "Error occurred: see most recent log file for details."
+ exit
+ fi
+}
+
+installCodeSourcery() {
+ # Unpack the tarball, creating the CodeSourcery dir, if necessary.
+ if [[ ! -d ${CODE_SOURCERY_ROOT} ]]; then
+ sudoCreateDir ${CODE_SOURCERY}
+ cd ${CODE_SOURCERY}
+ if [[ -e ${CODE_SOURCERY_PKG_PATH}/${CODE_SOURCERY_PKG} ]]; then
+ runCommand "Unpacking CodeSourcery in ${CODE_SOURCERY}" \
+ tar jxf ${CODE_SOURCERY_PKG_PATH}/${CODE_SOURCERY_PKG}
+ else
+ echo -n "CodeSourcery tarball not found in "
+ echo "${CODE_SOURCERY_PKG_PATH}/${CODE_SOURCERY_PKG}"
+ echo -n "Fix the path or download it from "
+ echo "${CODE_SOURCERY_HTTP}/${CROSS_TARGET}/${CODE_SOURCERY_PKG}"
+ exit
+ fi
+ else
+ echo "CodeSourcery install dir already exists; skipping."
+ fi
+
+ # Verify our CodeSourcery toolchain installation.
+ if [[ ! -d "${SYSROOT}" ]]; then
+ echo -n "Error: CodeSourcery does not contain libc for ${CROSS_TARGET}: "
+ echo "${SYSROOT} not found."
+ exit
+ fi
+
+ for tool in ${CROSS_TARGET_AS} ${CROSS_TARGET_LD}; do
+ if [[ ! -e $tool ]]; then
+ echo "${tool} not found; exiting."
+ exit
+ fi
+ done
+}
+
+installLLVM() {
+ if [[ -d ${LLVM_INSTALL_DIR} ]]; then
+ echo "LLVM install dir ${LLVM_INSTALL_DIR} exists; skipping."
+ return
+ fi
+
+ sudoCreateDir ${LLVM_INSTALL_DIR}
+
+ # Unpack LLVM tarball; should create the directory "llvm".
+ cd ${SRC_ROOT}
+ runCommand "Unpacking LLVM" tar jxf ${LLVM_PKG_PATH}/${LLVM_PKG}
+
+ # Configure, build, and install LLVM.
+ createDir ${LLVM_OBJ_DIR}
+ cd ${LLVM_OBJ_DIR}
+ runAndLog "Configuring LLVM" ${LLVM_OBJ_DIR}/llvm-configure.log \
+ ${LLVM_SRC_DIR}/configure \
+ --disable-jit \
+ --enable-optimized \
+ --prefix=${LLVM_INSTALL_DIR} \
+ --target=${CROSS_TARGET} \
+ --with-llvmgccdir=${LLVMGCC_INSTALL_DIR}
+ runAndLog "Building LLVM" ${LLVM_OBJ_DIR}/llvm-build.log \
+ make ${MAKE_OPTS}
+ runAndLog "Installing LLVM" ${LLVM_OBJ_DIR}/llvm-install.log \
+ make ${MAKE_OPTS} install
+}
+
+installLLVMGCC() {
+ if [[ -d ${LLVMGCC_INSTALL_DIR} ]]; then
+ echo "LLVM-GCC install dir ${LLVMGCC_INSTALL_DIR} exists; skipping."
+ return
+ fi
+
+ sudoCreateDir ${LLVMGCC_INSTALL_DIR}
+
+ # Unpack LLVM-GCC tarball; should create the directory "llvm-gcc-4.2".
+ cd ${SRC_ROOT}
+ runCommand "Unpacking LLVM-GCC" tar jxf ${LLVM_PKG_PATH}/${LLVMGCC_PKG}
+
+ # Configure, build, and install LLVM-GCC.
+ createDir ${LLVMGCC_OBJ_DIR}
+ cd ${LLVMGCC_OBJ_DIR}
+ runAndLog "Configuring LLVM-GCC" ${LLVMGCC_OBJ_DIR}/llvmgcc-configure.log \
+ ${LLVMGCC_SRC_DIR}/configure \
+ --enable-languages=c,c++ \
+ --enable-llvm=${LLVM_INSTALL_DIR} \
+ --prefix=${LLVMGCC_INSTALL_DIR} \
+ --program-prefix=llvm- \
+ --target=${CROSS_TARGET} \
+ --with-arch=${CROSS_MARCH} \
+ --with-as=${CROSS_TARGET_AS} \
+ --with-ld=${CROSS_TARGET_LD} \
+ --with-sysroot=${SYSROOT}
+ runAndLog "Building LLVM-GCC" ${LLVMGCC_OBJ_DIR}/llvmgcc-build.log \
+ make
+ runAndLog "Installing LLVM-GCC" ${LLVMGCC_OBJ_DIR}/llvmgcc-install.log \
+ make install
+}
+
+echo "Building in ${SCRATCH_ROOT}; installing in ${INSTALL_ROOT}"
+
+createDir ${SRC_ROOT}
+createDir ${OBJ_ROOT}
+
+installCodeSourcery
+installLLVM
+installLLVMGCC
+
+echo "Done."
diff --git a/contrib/llvm/utils/crosstool/create-snapshots.sh b/contrib/llvm/utils/crosstool/create-snapshots.sh
new file mode 100755
index 0000000..d70232a
--- /dev/null
+++ b/contrib/llvm/utils/crosstool/create-snapshots.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# Creates LLVM SVN snapshots: llvm-$REV.tar.bz2 and llvm-gcc-4.2-$REV.tar.bz2,
+# where $REV is an SVN revision of LLVM. This is used for creating stable
+# tarballs which can be used to build known-to-work crosstools.
+#
+# Syntax:
+# $0 [REV] -- grabs the revision $REV from SVN; if not specified, grabs the
+# latest SVN revision.
+
+set -o nounset
+set -o errexit
+
+readonly LLVM_PROJECT_SVN="http://llvm.org/svn/llvm-project"
+
+getLatestRevisionFromSVN() {
+ svn info ${LLVM_PROJECT_SVN} | egrep ^Revision | sed 's/^Revision: //'
+}
+
+readonly REV="${1:-$(getLatestRevisionFromSVN)}"
+
+createTarballFromSVN() {
+ local module=$1
+ local log="${module}.log"
+ echo "Running: svn export -r ${REV} ${module}; log in ${log}"
+ svn -q export -r ${REV} ${LLVM_PROJECT_SVN}/${module}/trunk \
+ ${module} > ${log} 2>&1
+
+ # Create "module-revision.tar.bz2" packages from the SVN checkout dirs.
+ local tarball="${module}-${REV}.tar.bz2"
+ echo "Creating tarball: ${tarball}"
+ tar cjf ${tarball} ${module}
+
+ echo "Cleaning up '${module}'"
+ rm -rf ${module} ${log}
+}
+
+for module in "llvm" "llvm-gcc-4.2"; do
+ createTarballFromSVN ${module}
+done
+
diff --git a/contrib/llvm/utils/emacs/README b/contrib/llvm/utils/emacs/README
new file mode 100644
index 0000000..e83eeae
--- /dev/null
+++ b/contrib/llvm/utils/emacs/README
@@ -0,0 +1,27 @@
+-*- llvm/utils/emacs/README -*-
+
+These are syntax highlighting files for the Emacs and XEmacs editors. Included
+are:
+
+* llvm-mode.el
+
+ Syntax highlighting mode for LLVM assembly files. To use, add this code to
+ your ~/.emacs :
+
+ (setq load-path
+ (cons (expand-file-name "path-to-llvm/utils/emacs") load-path))
+ (require 'llvm-mode)
+
+* tablegen-mode.el
+
+ Syntax highlighting mode for TableGen description files. To use, add this code
+ to your ~/.emacs:
+
+ (setq load-path
+ (cons (expand-file-name "path-to-llvm/utils/emacs") load-path))
+ (require 'tablegen-mode)
+
+
+Note: If you notice missing or incorrect syntax highlighting, please contact
+<llvmbugs [at] cs.uiuc.edu>; if you wish to provide a patch to improve the
+functionality, it will be most appreciated. Thank you.
diff --git a/contrib/llvm/utils/emacs/emacs.el b/contrib/llvm/utils/emacs/emacs.el
new file mode 100644
index 0000000..969f538
--- /dev/null
+++ b/contrib/llvm/utils/emacs/emacs.el
@@ -0,0 +1,39 @@
+;; LLVM coding style guidelines in emacs
+;; Maintainer: LLVM Team, http://llvm.org/
+;; Modified: 2009-07-28
+
+;; Max 80 cols per line, indent by two spaces, no tabs.
+;; Apparently, this does not affect tabs in Makefiles.
+(custom-set-variables
+ '(fill-column 80)
+ '(c++-indent-level 2)
+ '(c-basic-offset 2)
+ '(indent-tabs-mode nil))
+
+
+;; Alternative to setting the global style. Only files with "llvm" in
+;; their names will automatically set to the llvm.org coding style.
+(c-add-style "llvm.org"
+ '((fill-column . 80)
+ (c++-indent-level . 2)
+ (c-basic-offset . 2)
+ (indent-tabs-mode . nil)
+ (c-offsets-alist . ((innamespace 0)))))
+
+(add-hook 'c-mode-hook
+ (function
+ (lambda nil
+ (if (string-match "llvm" buffer-file-name)
+ (progn
+ (c-set-style "llvm.org")
+ )
+ ))))
+
+(add-hook 'c++-mode-hook
+ (function
+ (lambda nil
+ (if (string-match "llvm" buffer-file-name)
+ (progn
+ (c-set-style "llvm.org")
+ )
+ ))))
diff --git a/contrib/llvm/utils/emacs/llvm-mode.el b/contrib/llvm/utils/emacs/llvm-mode.el
new file mode 100644
index 0000000..b1af853
--- /dev/null
+++ b/contrib/llvm/utils/emacs/llvm-mode.el
@@ -0,0 +1,128 @@
+;; Maintainer: The LLVM team, http://llvm.org/
+;; Description: Major mode for the LLVM assembler language.
+;; Updated: 2007-09-19
+
+;; Create mode-specific tables.
+(defvar llvm-mode-syntax-table nil
+ "Syntax table used while in LLVM mode.")
+
+(defvar llvm-font-lock-keywords
+ (list
+ ;; Comments
+ '(";.*" . font-lock-comment-face)
+ ;; Variables
+ '("%[-a-zA-Z$\._][-a-zA-Z$\._0-9]*" . font-lock-variable-name-face)
+ ;; Labels
+ '("[-a-zA-Z$\._0-9]+:" . font-lock-variable-name-face)
+ ;; Strings
+ '("\"[^\"]+\"" . font-lock-string-face)
+ ;; Unnamed variable slots
+ '("%[-]?[0-9]+" . font-lock-variable-name-face)
+ ;; Types
+ '("\\bvoid\\b\\|\\bi[0-9]+\\b\\|\\float\\b\\|\\bdouble\\b\\|\\btype\\b\\|\\blabel\\b\\|\\bopaque\\b" . font-lock-type-face)
+ ;; Integer literals
+ '("\\b[-]?[0-9]+\\b" . font-lock-preprocessor-face)
+ ;; Floating point constants
+ '("\\b[-+]?[0-9]+\.[0-9]*\([eE][-+]?[0-9]+\)?\\b" . font-lock-preprocessor-face)
+ ;; Hex constants
+ '("\\b0x[0-9A-Fa-f]+\\b" . font-lock-preprocessor-face)
+ ;; Keywords
+ '("\\bbegin\\b\\|\\bend\\b\\|\\btrue\\b\\|\\bfalse\\b\\|\\bzeroinitializer\\b\\|\\bdeclare\\b\\|\\bdefine\\b\\|\\bglobal\\b\\|\\bconstant\\b\\|\\bconst\\b\\|\\binternal\\b\\|\\blinkonce\\b\\|\\blinkonce_odr\\b\\|\\bweak\\b\\|\\bweak_odr\\b\\|\\bappending\\b\\|\\buninitialized\\b\\|\\bimplementation\\b\\|\\b\\.\\.\\.\\b\\|\\bnull\\b\\|\\bundef\\b\\|\\bto\\b\\|\\bexcept\\b\\|\\bnot\\b\\|\\btarget\\b\\|\\bendian\\b\\|\\blittle\\b\\|\\bbig\\b\\|\\bpointersize\\b\\|\\bdeplibs\\b\\|\\bvolatile\\b\\|\\bfastcc\\b\\|\\bcoldcc\\b\\|\\bcc\\b" . font-lock-keyword-face)
+ ;; Arithmetic and Logical Operators
+ '("\\badd\\b\\|\\bsub\\b\\|\\bmul\\b\\|\\bdiv\\b\\|\\brem\\b\\|\\band\\b\\|\\bor\\b\\|\\bxor\\b\\|\\bset\\(ne\\b\\|\\beq\\b\\|\\blt\\b\\|\\bgt\\b\\|\\ble\\b\\|\\bge\\b\\)" . font-lock-keyword-face)
+ ;; Special instructions
+ '("\\bphi\\b\\|\\btail\\b\\|\\bcall\\b\\|\\bcast\\b\\|\\bselect\\b\\|\\bto\\b\\|\\bshl\\b\\|\\bshr\\b\\|\\bvaarg\\b\\|\\bvanext\\b" . font-lock-keyword-face)
+ ;; Control instructions
+ '("\\bret\\b\\|\\bbr\\b\\|\\bswitch\\b\\|\\binvoke\\b\\|\\bunwind\\b\\|\\bunreachable\\b" . font-lock-keyword-face)
+ ;; Memory operators
+ '("\\bmalloc\\b\\|\\balloca\\b\\|\\bfree\\b\\|\\bload\\b\\|\\bstore\\b\\|\\bgetelementptr\\b" . font-lock-keyword-face)
+ )
+ "Syntax highlighting for LLVM"
+ )
+
+;; ---------------------- Syntax table ---------------------------
+;; Shamelessly ripped from jasmin.el
+;; URL: http://www.neilvandyke.org/jasmin-emacs/jasmin.el.html
+
+(if (not llvm-mode-syntax-table)
+ (progn
+ (setq llvm-mode-syntax-table (make-syntax-table))
+ (mapcar (function (lambda (n)
+ (modify-syntax-entry (aref n 0)
+ (aref n 1)
+ llvm-mode-syntax-table)))
+ '(
+ ;; whitespace (` ')
+ [?\^m " "]
+ [?\f " "]
+ [?\n " "]
+ [?\t " "]
+ [?\ " "]
+ ;; word constituents (`w')
+ ;;[?< "w"]
+ ;;[?> "w"]
+ [?\% "w"]
+ ;;[?_ "w "]
+ ;; comments
+ [?\; "< "]
+ [?\n "> "]
+ ;;[?\r "> "]
+ ;;[?\^m "> "]
+ ;; symbol constituents (`_')
+ ;; punctuation (`.')
+ ;; open paren (`(')
+ [?\( "("]
+ [?\[ "("]
+ [?\{ "("]
+ ;; close paren (`)')
+ [?\) ")"]
+ [?\] ")"]
+ [?\} ")"]
+ ;; string quote ('"')
+ [?\" "\""]
+ ))))
+
+;; --------------------- Abbrev table -----------------------------
+
+(defvar llvm-mode-abbrev-table nil
+ "Abbrev table used while in LLVM mode.")
+(define-abbrev-table 'llvm-mode-abbrev-table ())
+
+(defvar llvm-mode-hook nil)
+(defvar llvm-mode-map nil) ; Create a mode-specific keymap.
+
+(if (not llvm-mode-map)
+ () ; Do not change the keymap if it is already set up.
+ (setq llvm-mode-map (make-sparse-keymap))
+ (define-key llvm-mode-map "\t" 'tab-to-tab-stop)
+ (define-key llvm-mode-map "\es" 'center-line)
+ (define-key llvm-mode-map "\eS" 'center-paragraph))
+
+
+(defun llvm-mode ()
+ "Major mode for editing LLVM source files.
+ \\{llvm-mode-map}
+ Runs llvm-mode-hook on startup."
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map llvm-mode-map) ; Provides the local keymap.
+ (setq major-mode 'llvm-mode)
+
+ (make-local-variable 'font-lock-defaults)
+ (setq major-mode 'llvm-mode ; This is how describe-mode
+ ; finds the doc string to print.
+ mode-name "LLVM" ; This name goes into the modeline.
+ font-lock-defaults `(llvm-font-lock-keywords))
+
+ (setq local-abbrev-table llvm-mode-abbrev-table)
+ (set-syntax-table llvm-mode-syntax-table)
+ (setq comment-start ";")
+ (run-hooks 'llvm-mode-hook)) ; Finally, this permits the user to
+ ; customize the mode with a hook.
+
+;; Associate .ll files with llvm-mode
+(setq auto-mode-alist
+ (append '(("\\.ll$" . llvm-mode)) auto-mode-alist))
+
+(provide 'llvm-mode)
+;; end of llvm-mode.el
diff --git a/contrib/llvm/utils/emacs/tablegen-mode.el b/contrib/llvm/utils/emacs/tablegen-mode.el
new file mode 100644
index 0000000..833c16c
--- /dev/null
+++ b/contrib/llvm/utils/emacs/tablegen-mode.el
@@ -0,0 +1,124 @@
+;; Maintainer: The LLVM team, http://llvm.org/
+;; Description: Major mode for TableGen description files (part of LLVM project)
+;; Updated: 2007-12-18
+
+(require 'comint)
+(require 'custom)
+(require 'ansi-color)
+
+;; Create mode-specific tables.
+(defvar td-decorators-face 'td-decorators-face
+ "Face method decorators.")
+(make-face 'td-decorators-face)
+
+(defvar tablegen-font-lock-keywords
+ (let ((kw (mapconcat 'identity
+ '("class" "defm" "def" "field" "include" "in"
+ "let" "multiclass")
+ "\\|"))
+ (type-kw (mapconcat 'identity
+ '("bit" "bits" "code" "dag" "int" "list" "string")
+ "\\|"))
+ )
+ (list
+ ;; Comments
+;; '("\/\/" . font-lock-comment-face)
+ ;; Strings
+ '("\"[^\"]+\"" . font-lock-string-face)
+ ;; Hex constants
+ '("\\<0x[0-9A-Fa-f]+\\>" . font-lock-preprocessor-face)
+ ;; Binary constants
+ '("\\<0b[01]+\\>" . font-lock-preprocessor-face)
+ ;; Integer literals
+ '("\\<[-]?[0-9]+\\>" . font-lock-preprocessor-face)
+ ;; Floating point constants
+ '("\\<[-+]?[0-9]+\.[0-9]*\([eE][-+]?[0-9]+\)?\\>" . font-lock-preprocessor-face)
+
+ '("^[ \t]*\\(@.+\\)" 1 'td-decorators-face)
+ ;; Keywords
+ (cons (concat "\\<\\(" kw "\\)\\>[ \n\t(]") 1)
+
+ ;; Type keywords
+ (cons (concat "\\<\\(" type-kw "\\)[ \n\t(]") 1)
+ ))
+ "Additional expressions to highlight in TableGen mode.")
+(put 'tablegen-mode 'font-lock-defaults '(tablegen-font-lock-keywords))
+
+;; ---------------------- Syntax table ---------------------------
+;; Shamelessly ripped from jasmin.el
+;; URL: http://www.neilvandyke.org/jasmin-emacs/jasmin.el
+
+(defvar tablegen-mode-syntax-table nil
+ "Syntax table used in `tablegen-mode' buffers.")
+(when (not tablegen-mode-syntax-table)
+ (setq tablegen-mode-syntax-table (make-syntax-table))
+ ;; whitespace (` ')
+ (modify-syntax-entry ?\ " " tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\t " " tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\r " " tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\n " " tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\f " " tablegen-mode-syntax-table)
+ ;; word constituents (`w')
+ (modify-syntax-entry ?\% "w" tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\_ "w" tablegen-mode-syntax-table)
+ ;; comments
+ (modify-syntax-entry ?/ ". 124b" tablegen-mode-syntax-table)
+ (modify-syntax-entry ?* ". 23" tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\n "> b" tablegen-mode-syntax-table)
+ ;; open paren (`(')
+ (modify-syntax-entry ?\( "(" tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\[ "(" tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\{ "(" tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\< "(" tablegen-mode-syntax-table)
+ ;; close paren (`)')
+ (modify-syntax-entry ?\) ")" tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\] ")" tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\} ")" tablegen-mode-syntax-table)
+ (modify-syntax-entry ?\> ")" tablegen-mode-syntax-table)
+ ;; string quote ('"')
+ (modify-syntax-entry ?\" "\"" tablegen-mode-syntax-table)
+ )
+
+;; --------------------- Abbrev table -----------------------------
+
+(defvar tablegen-mode-abbrev-table nil
+ "Abbrev table used while in TableGen mode.")
+(define-abbrev-table 'tablegen-mode-abbrev-table ())
+
+(defvar tablegen-mode-hook nil)
+(defvar tablegen-mode-map nil) ; Create a mode-specific keymap.
+
+(if (not tablegen-mode-map)
+ () ; Do not change the keymap if it is already set up.
+ (setq tablegen-mode-map (make-sparse-keymap))
+ (define-key tablegen-mode-map "\t" 'tab-to-tab-stop)
+ (define-key tablegen-mode-map "\es" 'center-line)
+ (define-key tablegen-mode-map "\eS" 'center-paragraph))
+
+(defun tablegen-mode ()
+ "Major mode for editing TableGen description files.
+ \\{tablegen-mode-map}
+ Runs tablegen-mode-hook on startup."
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map tablegen-mode-map) ; Provides the local keymap.
+ (make-local-variable 'font-lock-defaults)
+ (setq major-mode 'tablegen-mode ; This is how describe-mode
+ ; finds the doc string to print.
+ mode-name "TableGen" ; This name goes into the modeline.
+ local-abbrev-table tablegen-mode-abbrev-table
+ font-lock-defaults `(tablegen-font-lock-keywords)
+ require-final-newline t
+ )
+
+ (set-syntax-table tablegen-mode-syntax-table)
+ (make-local-variable 'comment-start)
+ (setq comment-start "//")
+ (run-hooks 'tablegen-mode-hook)) ; Finally, this permits the user to
+ ; customize the mode with a hook.
+
+;; Associate .td files with tablegen-mode
+(setq auto-mode-alist (append '(("\\.td$" . tablegen-mode)) auto-mode-alist))
+
+(provide 'tablegen-mode)
+;; end of tablegen-mode.el
diff --git a/contrib/llvm/utils/findmisopt b/contrib/llvm/utils/findmisopt
new file mode 100755
index 0000000..b7ffbd9
--- /dev/null
+++ b/contrib/llvm/utils/findmisopt
@@ -0,0 +1,178 @@
+#!/bin/bash
+#
+# findmisopt
+#
+# This is a quick and dirty hack to potentially find a misoptimization
+# problem. Mostly its to work around problems in bugpoint that prevent
+# it from finding a problem unless the set of failing optimizations are
+# known and given to it on the command line.
+#
+# Given a bytecode file that produces correct output (or return code),
+# this script will run through all the optimizations passes that gccas
+# uses (in the same order) and will narrow down which optimizations
+# cause the program either generate different output or return a
+# different result code. When the passes have been narrowed down,
+# bugpoint is invoked to further refine the problem to its origin. If a
+# release version of bugpoint is available it will be used, otherwise
+# debug.
+#
+# Usage:
+# findmisopt bcfile outdir progargs [match]
+#
+# Where:
+# bcfile
+# is the bytecode file input (the unoptimized working case)
+# outdir
+# is a directory into which intermediate results are placed
+# progargs
+# is a single argument containing all the arguments the program needs
+# proginput
+# is a file name from which stdin should be directed
+# match
+# if specified to any value causes the result code of the program to
+# be used to determine success/fail. If not specified success/fail is
+# determined by diffing the program's output with the non-optimized
+# output.
+#
+if [ "$#" -lt 3 ] ; then
+ echo "usage: findmisopt bcfile outdir progargs [match]"
+ exit 1
+fi
+
+dir="${0%%/utils/findmisopt}"
+if [ -x "$dir/Release/bin/bugpoint" ] ; then
+ bugpoint="$dir/Release/bin/bugpoint"
+elif [ -x "$dir/Debug/bin/bugpoint" ] ; then
+ bugpoint="$dir/Debug/bin/bugpoint"
+else
+ echo "findmisopt: bugpoint not found"
+ exit 1
+fi
+
+bcfile="$1"
+outdir="$2"
+args="$3"
+input="$4"
+if [ ! -f "$input" ] ; then
+ input="/dev/null"
+fi
+match="$5"
+name=`basename $bcfile .bc`
+ll="$outdir/${name}.ll"
+s="$outdir/${name}.s"
+prog="$outdir/${name}"
+out="$outdir/${name}.out"
+optbc="$outdir/${name}.opt.bc"
+optll="$outdir/${name}.opt.ll"
+opts="$outdir/${name}.opt.s"
+optprog="$outdir/${name}.opt"
+optout="$outdir/${name}.opt.out"
+ldflags="-lstdc++ -lm -ldl -lc"
+
+echo "Test Name: $name"
+echo "Unoptimized program: $prog"
+echo " Optimized program: $optprog"
+
+# Define the list of optimizations to run. This comprises the same set of
+# optimizations that opt -std-compile-opts and gccld run, in the same order.
+opt_switches=`llvm-as < /dev/null -o - | opt -std-compile-opts -disable-output -debug-pass=Arguments 2>&1 | sed 's/Pass Arguments: //'`
+ld_switches=`llvm-as < /dev/null -o - | llvm-ld - -debug-pass=Arguments 2>&1 | sed 's/Pass Arguments: //'`
+all_switches="$opt_switches $ld_switches"
+echo "Passes : $all_switches"
+
+# Create output directory if it doesn't exist
+if [ -f "$outdir" ] ; then
+ echo "$outdir is not a directory"
+ exit 1
+fi
+
+if [ ! -d "$outdir" ] ; then
+ mkdir "$outdir" || exit 1
+fi
+
+# Generate the disassembly
+llvm-dis "$bcfile" -o "$ll" -f || exit 1
+
+# Generate the non-optimized program and its output
+llc "$bcfile" -o "$s" -f || exit 1
+gcc "$s" -o "$prog" $ldflags || exit 1
+"$prog" $args > "$out" 2>&1 <$input
+ex1=$?
+
+# Current set of switches is empty
+function tryit {
+ switches_to_use="$1"
+ opt $switches_to_use "$bcfile" -o "$optbc" -f || exit
+ llvm-dis "$optbc" -o "$optll" -f || exit
+ llc "$optbc" -o "$opts" -f || exit
+ gcc "$opts" -o "$optprog" $ldflags || exit
+ "$optprog" $args > "$optout" 2>&1 <"$input"
+ ex2=$?
+
+ if [ -n "$match" ] ; then
+ if [ "$ex1" -ne "$ex2" ] ; then
+ echo "Return code not the same with these switches:"
+ echo $switches
+ echo "Unoptimized returned: $ex1"
+ echo "Optimized returned: $ex2"
+ return 0
+ fi
+ else
+ diff "$out" "$optout" > /dev/null
+ if [ $? -ne 0 ] ; then
+ echo "Diff fails with these switches:"
+ echo $switches
+ echo "Differences:"
+ diff "$out" "$optout" | head
+ return 0;
+ fi
+ fi
+ return 1
+}
+
+echo "Trying to find optimization that breaks program:"
+for sw in $all_switches ; do
+ echo -n " $sw"
+ switches="$switches $sw"
+ if tryit "$switches" ; then
+ break;
+ fi
+done
+
+# Terminate the previous output with a newline
+echo ""
+
+# Determine if we're done because none of the optimizations broke the program
+if [ "$switches" == " $all_switches" ] ; then
+ echo "The program did not miscompile"
+ exit 0
+fi
+
+final=""
+while [ ! -z "$switches" ] ; do
+ trimmed=`echo "$switches" | sed -e 's/^ *\(-[^ ]*\).*/\1/'`
+ switches=`echo "$switches" | sed -e 's/^ *-[^ ]* *//'`
+ echo "Trimmed $trimmed from left"
+ tryit "$final $switches"
+ if [ "$?" -eq "0" ] ; then
+ echo "Still Failing .. continuing ..."
+ continue
+ else
+ echo "Found required early pass: $trimmed"
+ final="$final $trimmed"
+ continue
+ fi
+ echo "Next Loop"
+done
+
+if [ "$final" == " $all_switches" ] ; then
+ echo "findmisopt: All optimizations pass. Perhaps this isn't a misopt?"
+ exit 0
+fi
+echo "Smallest Optimization list=$final"
+
+bpcmd="$bugpoint -run-llc -disable-loop-extraction --output "$out" --input /dev/null $bcfile $final --args $args"
+
+echo "Running: $bpcmd"
+$bpcmd
+echo "findmisopt finished."
diff --git a/contrib/llvm/utils/findoptdiff b/contrib/llvm/utils/findoptdiff
new file mode 100755
index 0000000..4f8d08d
--- /dev/null
+++ b/contrib/llvm/utils/findoptdiff
@@ -0,0 +1,101 @@
+#!/bin/bash
+#
+# findoptdiff
+#
+# This script helps find the optimization difference between two llvm
+# builds. It is useful when you have a build that is known to work and
+# one that exhibits an optimization problem. Identifying the difference
+# between the two builds can lead to discovery of the source of a
+# mis-optimization.
+#
+# The script takes two llvm build paths as arguments. These specify the
+# the two llvm builds to compare. It is generally expected that they
+# are "close cousins". That is, they are the same except that the
+# second build contains some experimental optimization features that
+# are suspected of producing a misoptimization.
+#
+# The script takes two bytecode files, one from each build. They are
+# presumed to be a compilation of the same program or program fragment
+# with the only difference being the builds.
+#
+# The script operates by iteratively applying the optimizations that gccas
+# and gccld run until there is a difference in the assembly resulting
+# from the optimization. The difference is then reported with the set of
+# optimization passes that produce the difference. The processing
+# continues until all optimization passes have been tried. The differences
+# for each pass, if they do differ, are placed in a diffs.# file.
+#
+# To work around differences in the assembly language format, the script
+# can also take two filter arguments that post-process the assembly
+# so they can be differenced without making false positives for known
+# differences in the two builds. These filters are optional.
+#
+# Usage:
+# findoptdiff llvm1 llvm2 bc1 bc2 filter1 filter2
+#
+# Where:
+# llvm1
+# is the path to the first llvm build dir
+# llvm2
+# is the path to the second llvm build dir
+# bc1
+# is the bytecode file for the first llvm environment
+# bc2
+# is the bytecode file for the second llvm environment
+# filter1
+# is an optional filter for filtering the llvm1 generated assembly
+# filter2
+# is an optional filter for filtering the llvm2 generated assembly
+#
+llvm1=$1
+llvm2=$2
+bc1=$3
+bc2=$4
+filt1=$5
+filt2=$6
+if [ -z "$filt1" ] ; then
+ filt1="cat"
+fi
+if [ -z "$filt2" ] ; then
+ filt2="cat"
+fi
+opt1="${bc1}.opt"
+opt2="${bc2}.opt"
+ll1="${bc1}.ll"
+ll2="${bc2}.ll"
+opt1ll="${bc1}.opt.ll"
+opt2ll="${bc2}.opt.ll"
+dis1="$llvm1/Debug/bin/llvm-dis"
+dis2="$llvm2/Debug/bin/llvm-dis"
+opt1="$llvm1/Debug/bin/opt"
+opt2="$llvm2/Debug/bin/opt"
+
+all_switches="-verify -lowersetjmp -simplifycfg -mem2reg -globalopt -globaldce -ipconstprop -deadargelim -instcombine -simplifycfg -prune-eh -inline -simplify-libcalls -argpromotion -tailduplicate -simplifycfg -scalarrepl -instcombine -predsimplify -condprop -tailcallelim -simplifycfg -reassociate -licm -loop-unswitch -instcombine -indvars -loop-unroll -instcombine -load-vn -gcse -sccp -instcombine -condprop -dse -dce -simplifycfg -deadtypeelim -constmerge -internalize -ipsccp -globalopt -constmerge -deadargelim -inline -prune-eh -globalopt -globaldce -argpromotion -instcombine -predsimplify -scalarrepl -globalsmodref-aa -licm -load-vn -gcse -dse -instcombine -simplifycfg -verify"
+
+#counter=0
+function tryit {
+ switches_to_use="$1"
+ $opt1 $switches_to_use "$bc1" -o - | $dis1 | $filt1 > "$opt1ll"
+ $opt2 $switches_to_use "$bc2" -o - | $dis2 | $filt2 > "$opt2ll"
+ diffs="diffs."$((counter++))
+ diff "$opt1ll" "$opt2ll" > $diffs
+ if [ $? -ne 0 ] ; then
+ echo
+ echo "Diff fails with these switches:"
+ echo $switches
+ echo "Differences:"
+ head $diffs
+ echo 'Switches:' $switches_to_use >> $diffs
+ else
+ rm $diffs
+ fi
+ return 1
+}
+
+for sw in $all_switches ; do
+ echo -n " $sw"
+ switches="$switches $sw"
+ if tryit "$switches" ; then
+ break;
+ fi
+done
diff --git a/contrib/llvm/utils/findsym.pl b/contrib/llvm/utils/findsym.pl
new file mode 100755
index 0000000..9234657
--- /dev/null
+++ b/contrib/llvm/utils/findsym.pl
@@ -0,0 +1,33 @@
+#!/usr/bin/perl -w
+#
+# Program: findsym.pl
+#
+# Synopsis: Generate a list of the libraries in which a symbol is defined or
+# referenced.
+#
+# Syntax: findsym.pl <directory_with_libraries_in_it> <symbol>
+#
+
+# Give first option a name.
+my $Directory = $ARGV[0];
+my $Symbol = $ARGV[1];
+
+# Open the directory and read its contents, sorting by name and differentiating
+# by whether its a library (.a) or an object file (.o)
+opendir DIR,$Directory;
+my @files = readdir DIR;
+closedir DIR;
+@objects = grep(/l?i?b?LLVM.*\.[oa]$/,sort(@files));
+
+# Gather definitions from the libraries
+foreach $lib (@objects) {
+ my $head = 0;
+ open SYMS,
+ "nm $Directory/$lib | grep '$Symbol' | sort --key=3 | uniq |";
+ while (<SYMS>) {
+ if (!$head) { print "$lib:\n"; $head = 1; }
+ chomp($_);
+ print " $_\n";
+ }
+ close SYMS;
+}
diff --git a/contrib/llvm/utils/fpcmp/Makefile b/contrib/llvm/utils/fpcmp/Makefile
new file mode 100644
index 0000000..fd2f747
--- /dev/null
+++ b/contrib/llvm/utils/fpcmp/Makefile
@@ -0,0 +1,16 @@
+##===- utils/fpcmp/Makefile --------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TOOLNAME = fpcmp
+USEDLIBS = LLVMSupport.a LLVMSystem.a
+NO_INSTALL = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/contrib/llvm/utils/fpcmp/fpcmp.cpp b/contrib/llvm/utils/fpcmp/fpcmp.cpp
new file mode 100644
index 0000000..5f6b5e8
--- /dev/null
+++ b/contrib/llvm/utils/fpcmp/fpcmp.cpp
@@ -0,0 +1,43 @@
+//===- fpcmp.cpp - A fuzzy "cmp" that permits floating point noise --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// fpcmp is a tool that basically works like the 'cmp' tool, except that it can
+// tolerate errors due to floating point noise, with the -r and -a options.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+namespace {
+ cl::opt<std::string>
+ File1(cl::Positional, cl::desc("<input file #1>"), cl::Required);
+ cl::opt<std::string>
+ File2(cl::Positional, cl::desc("<input file #2>"), cl::Required);
+
+ cl::opt<double>
+ RelTolerance("r", cl::desc("Relative error tolerated"), cl::init(0));
+ cl::opt<double>
+ AbsTolerance("a", cl::desc("Absolute error tolerated"), cl::init(0));
+}
+
+int main(int argc, char **argv) {
+ cl::ParseCommandLineOptions(argc, argv);
+
+ std::string ErrorMsg;
+ int DF = DiffFilesWithTolerance(sys::PathWithStatus(File1),
+ sys::PathWithStatus(File2),
+ AbsTolerance, RelTolerance, &ErrorMsg);
+ if (!ErrorMsg.empty())
+ errs() << argv[0] << ": " << ErrorMsg << "\n";
+ return DF;
+}
+
diff --git a/contrib/llvm/utils/getsrcs.sh b/contrib/llvm/utils/getsrcs.sh
new file mode 100755
index 0000000..c8bff8c
--- /dev/null
+++ b/contrib/llvm/utils/getsrcs.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+##===- utils/getsrcs.sh - Counts Lines Of Code ---------------*- Script -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This script just prints out the path names for all the source files in LLVM.
+# The optional -topdir option can be used to specify the top LLVM source
+# directory. Without it, the llvm-config command is consulted to find the
+# top source directory.
+#
+# Note that the implementation is based on llvmdo. See that script for more
+# details.
+##===----------------------------------------------------------------------===##
+
+if test "$1" = "-topdir" ; then
+ TOPDIR="$2"
+ shift; shift;
+else
+ TOPDIR=`llvm-config --src-root`
+fi
+
+if test -d "$TOPDIR" ; then
+ cd $TOPDIR
+ ./utils/llvmdo -topdir "$TOPDIR" \
+ -dirs "include lib tools utils examples projects" echo
+else
+ echo "Can't find LLVM top directory"
+fi
diff --git a/contrib/llvm/utils/git/find-rev b/contrib/llvm/utils/git/find-rev
new file mode 100755
index 0000000..a6161db
--- /dev/null
+++ b/contrib/llvm/utils/git/find-rev
@@ -0,0 +1,50 @@
+#!/usr/bin/python
+
+import os, sys, subprocess
+
+def main():
+ from optparse import OptionParser, OptionGroup
+ parser = OptionParser("usage: %prog [options] <repo> <revision>")
+ parser.add_option("", "--dump-section-data", dest="dumpSectionData",
+ help="Dump the contents of sections",
+ action="store_true", default=False)
+ (opts, args) = parser.parse_args()
+
+ if len(args) != 2:
+ parser.error("invalid number of arguments")
+
+ repo,rev = args
+
+ try:
+ rev = int(rev)
+ except:
+ parser.error("invalid revision argument (not an integer)")
+
+ os.chdir(repo)
+ p = subprocess.Popen(['git', 'rev-list', 'git-svn', '--pretty'],
+ stdout=subprocess.PIPE)
+
+ bestRev = bestCommit = None
+ lastCommit = None
+ for ln in p.stdout:
+ if ln.startswith('commit '):
+ lastCommit = ln.split(' ',2)[1]
+ elif ln.startswith(' git-svn-id: '):
+ _,repo,_ = ln.strip().split(' ')
+ _,lrev = repo.rsplit('@',1)
+ lrev = int(lrev)
+ if lrev<=rev:
+ if bestRev is None or lrev>bestRev:
+ assert lastCommit
+ bestCommit = lastCommit
+ bestRev = lrev
+ if lrev == rev:
+ break
+
+ if bestCommit is not None:
+ print bestCommit
+ sys.exit(0)
+ sys.exit(1)
+
+if __name__=='__main__':
+ main()
diff --git a/contrib/llvm/utils/importNLT.pl b/contrib/llvm/utils/importNLT.pl
new file mode 100644
index 0000000..c1b950d
--- /dev/null
+++ b/contrib/llvm/utils/importNLT.pl
@@ -0,0 +1,86 @@
+#!/usr/bin/perl
+#take the output of parseNLT.pl and load it into a database
+# use like: cat file |perl parseNLT.pl |perl importNLT.pl password
+
+use DBI;
+
+# database information
+$db="llvmalpha";
+$host="localhost";
+$userid="llvmdbuser";
+$passwd=shift @ARGV;
+$connectionInfo="dbi:mysql:$db;$host";
+
+# make connection to database
+$dbh = DBI->connect($connectionInfo,$userid,$passwd) or die DBI->errstr;
+my $sth = $dbh->prepare( q{
+ INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES (?, STR_TO_DATE(?, '\%d \%M \%Y'), ?, ?)
+ }) || die "Can't prepare statement: $DBI::errstr";;
+
+while($d = <>)
+{
+ chomp $d;
+ if (18 == scalar split " ", $d)
+ {
+ ($day, $mon, $year, $prog, $gccas, $bc, $llccompile, $llcbetacompile, $jitcompile,
+ $mc, $gcc, $cbe, $llc, $llcbeta, $jit, $foo1, $foo2, $foo3) = split " ", $d;
+ if ($gccas =~ /\d+/)
+ {
+ $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES
+ ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'gccas', $gccas)") || die DBI->errstr;
+ }
+ if ($bc =~ /\d/)
+ {
+ $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES
+ ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'bytecode', $bc)") || die DBI->errstr;
+ }
+ if ($llccompile =~ /\d/)
+ {
+ $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES
+ ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'llc-compile', $llccompile)") || die DBI->errstr;
+ }
+ if ($llcbetacompile =~ /\d/)
+ {
+ $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES
+ ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'llc-beta-compile', $llcbetacompile)") || die DBI->errstr;
+ }
+ if ($jitcompile =~ /\d/)
+ {
+ $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES
+ ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'jit-compile', $jitcompile)") || die DBI->errstr;
+ }
+ if ($mc =~ /\d/)
+ {
+ $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES
+ ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'machine-code', $mc)") || die DBI->errstr;
+ }
+ if ($gcc =~ /\d/)
+ {
+ $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES
+ ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'gcc', $gcc)") || die DBI->errstr;
+ }
+ if ($llc =~ /\d/)
+ {
+ $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES
+ ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'llc', $llc)") || die DBI->errstr;
+ }
+ if ($llcbeta =~ /\d/)
+ {
+ $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES
+ ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'llc-beta', $llcbeta)") || die DBI->errstr;
+ }
+ if ($jit =~ /\d/)
+ {
+ $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES
+ ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'jit', $jit)") || die DBI->errstr;
+ }
+ print ".";
+ }
+ else
+ {
+ print "\nNO: $d\n";
+ }
+}
+print "\n";
+# disconnect from database
+$dbh->disconnect;
diff --git a/contrib/llvm/utils/jedit/README b/contrib/llvm/utils/jedit/README
new file mode 100644
index 0000000..6a6c8c7
--- /dev/null
+++ b/contrib/llvm/utils/jedit/README
@@ -0,0 +1,14 @@
+-*- llvm/utils/jedit/README -*-
+
+These are syntax highlighting files for the jEdit editor. Included are:
+
+* tablegen.xml
+
+ Syntax highlighting mode for TableGen description files. To use, copy this
+ file to ~/.jedit/modes/ and add this code to your ~/.jedit/modes/catalog:
+
+ <MODE NAME="tablegen" FILE="tablegen.xml" FILE_NAME_GLOB="*.td" />
+
+Note: If you notice missing or incorrect syntax highlighting, please contact
+<llvmbugs [at] cs.uiuc.edu>; if you wish to provide a patch to improve the
+functionality, it will be most appreciated. Thank you.
diff --git a/contrib/llvm/utils/jedit/tablegen.xml b/contrib/llvm/utils/jedit/tablegen.xml
new file mode 100644
index 0000000..2d80a3f
--- /dev/null
+++ b/contrib/llvm/utils/jedit/tablegen.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!DOCTYPE MODE SYSTEM "xmode.dtd">
+<MODE>
+ <PROPS>
+ <PROPERTY NAME="lineComment" VALUE="//" />
+ <PROPERTY NAME="commentStart" VALUE="/*" />
+ <PROPERTY NAME="commentEnd" VALUE="*/" />
+ <PROPERTY NAME="indentOpenBrackets" VALUE="{" />
+ <PROPERTY NAME="indentCloseBrackets" VALUE="}" />
+ <PROPERTY NAME="wordBreakChars" VALUE=",+-=&lt;&gt;/?^&amp;*" />
+ <PROPERTY NAME="unalignedOpenBrackets" VALUE="(&lt;" />
+ <PROPERTY NAME="unalignedCloseBrackets" VALUE=")&gt;" />
+ </PROPS>
+ <RULES IGNORE_CASE="FALSE" HIGHLIGHT_DIGITS="TRUE">
+ <EOL_SPAN TYPE="COMMENT1">//</EOL_SPAN>
+ <SPAN TYPE="COMMENT1">
+ <BEGIN>/*</BEGIN>
+ <END>*/</END>
+ </SPAN>
+ <SPAN TYPE="LITERAL1" NO_LINE_BREAK="TRUE" ESCAPE="\">
+ <BEGIN>"</BEGIN>
+ <END>"</END>
+ </SPAN>
+ <KEYWORDS>
+ <KEYWORD1>let</KEYWORD1>
+ <KEYWORD1>def</KEYWORD1>
+ <KEYWORD1>class</KEYWORD1>
+ <KEYWORD1>include</KEYWORD1>
+
+ <KEYWORD3>bit</KEYWORD3>
+ <KEYWORD3>int</KEYWORD3>
+ <KEYWORD3>string</KEYWORD3>
+ <KEYWORD3>bits</KEYWORD3>
+ <KEYWORD3>list</KEYWORD3>
+ <KEYWORD3>dag</KEYWORD3>
+ <KEYWORD3>code</KEYWORD3>
+ </KEYWORDS>
+ </RULES>
+</MODE>
diff --git a/contrib/llvm/utils/lint/common_lint.py b/contrib/llvm/utils/lint/common_lint.py
new file mode 100644
index 0000000..e982680
--- /dev/null
+++ b/contrib/llvm/utils/lint/common_lint.py
@@ -0,0 +1,97 @@
+#!/usr/bin/python
+#
+# Common lint functions applicable to multiple types of files.
+
+import re
+
+def VerifyLineLength(filename, lines, max_length):
+ """Checks to make sure the file has no lines with lines exceeding the length
+ limit.
+
+ Args:
+ filename: the file under consideration as string
+ lines: contents of the file as string array
+ max_length: maximum acceptable line length as number
+
+ Returns:
+ A list of tuples with format [(filename, line number, msg), ...] with any
+ violations found.
+ """
+ lint = []
+ line_num = 1
+ for line in lines:
+ length = len(line.rstrip('\n'))
+ if length > max_length:
+ lint.append((filename, line_num,
+ 'Line exceeds %d chars (%d)' % (max_length, length)))
+ line_num += 1
+ return lint
+
+def VerifyTabs(filename, lines):
+ """Checks to make sure the file has no tab characters.
+
+ Args:
+ filename: the file under consideration as string
+ lines: contents of the file as string array
+
+ Returns:
+ A list of tuples with format [(line_number, msg), ...] with any violations
+ found.
+ """
+ lint = []
+ tab_re = re.compile(r'\t')
+ line_num = 1
+ for line in lines:
+ if tab_re.match(line.rstrip('\n')):
+ lint.append((filename, line_num, 'Tab found instead of whitespace'))
+ line_num += 1
+ return lint
+
+
+def VerifyTrailingWhitespace(filename, lines):
+ """Checks to make sure the file has no lines with trailing whitespace.
+
+ Args:
+ filename: the file under consideration as string
+ lines: contents of the file as string array
+
+ Returns:
+ A list of tuples with format [(filename, line number, msg), ...] with any
+ violations found.
+ """
+ lint = []
+ trailing_whitespace_re = re.compile(r'\s+$')
+ line_num = 1
+ for line in lines:
+ if trailing_whitespace_re.match(line.rstrip('\n')):
+ lint.append((filename, line_num, 'Trailing whitespace'))
+ line_num += 1
+ return lint
+
+
+class BaseLint:
+ def RunOnFile(filename, lines):
+ raise Exception('RunOnFile() unimplemented')
+
+
+def RunLintOverAllFiles(linter, filenames):
+ """Runs linter over the contents of all files.
+
+ Args:
+ lint: subclass of BaseLint, implementing RunOnFile()
+ filenames: list of all files whose contents will be linted
+
+ Returns:
+ A list of tuples with format [(filename, line number, msg), ...] with any
+ violations found.
+ """
+ lint = []
+ for filename in filenames:
+ file = open(filename, 'r')
+ if not file:
+ print 'Cound not open %s' % filename
+ continue
+ lines = file.readlines()
+ lint.extend(linter.RunOnFile(filename, lines))
+
+ return lint
diff --git a/contrib/llvm/utils/lint/cpp_lint.py b/contrib/llvm/utils/lint/cpp_lint.py
new file mode 100755
index 0000000..07fad58
--- /dev/null
+++ b/contrib/llvm/utils/lint/cpp_lint.py
@@ -0,0 +1,94 @@
+#!/usr/bin/python
+#
+# Checks C++ files to make sure they conform to LLVM standards, as specified in
+# http://llvm.org/docs/CodingStandards.html .
+#
+# TODO: add unittests for the verifier functions:
+# http://docs.python.org/library/unittest.html .
+
+import common_lint
+import re
+import sys
+
+def VerifyIncludes(filename, lines):
+ """Makes sure the #includes are in proper order and no disallows files are
+ #included.
+
+ Args:
+ filename: the file under consideration as string
+ lines: contents of the file as string array
+ """
+ lint = []
+
+ include_gtest_re = re.compile(r'^#include "gtest/(.*)"')
+ include_llvm_re = re.compile(r'^#include "llvm/(.*)"')
+ include_support_re = re.compile(r'^#include "(Support/.*)"')
+ include_config_re = re.compile(r'^#include "(Config/.*)"')
+ include_system_re = re.compile(r'^#include <(.*)>')
+
+ DISALLOWED_SYSTEM_HEADERS = ['iostream']
+
+ line_num = 1
+ prev_config_header = None
+ prev_system_header = None
+ for line in lines:
+ # TODO: implement private headers
+ # TODO: implement gtest headers
+ # TODO: implement top-level llvm/* headers
+ # TODO: implement llvm/Support/* headers
+
+ # Process Config/* headers
+ config_header = include_config_re.match(line)
+ if config_header:
+ curr_config_header = config_header.group(1)
+ if prev_config_header:
+ if prev_config_header > curr_config_header:
+ lint.append((filename, line_num,
+ 'Config headers not in order: "%s" before "%s"' % (
+ prev_config_header, curr_config_header)))
+
+ # Process system headers
+ system_header = include_system_re.match(line)
+ if system_header:
+ curr_system_header = system_header.group(1)
+
+ # Is it blacklisted?
+ if curr_system_header in DISALLOWED_SYSTEM_HEADERS:
+ lint.append((filename, line_num,
+ 'Disallowed system header: <%s>' % curr_system_header))
+ elif prev_system_header:
+ # Make sure system headers are alphabetized amongst themselves
+ if prev_system_header > curr_system_header:
+ lint.append((filename, line_num,
+ 'System headers not in order: <%s> before <%s>' % (
+ prev_system_header, curr_system_header)))
+
+ prev_system_header = curr_system_header
+
+ line_num += 1
+
+ return lint
+
+
+class CppLint(common_lint.BaseLint):
+ MAX_LINE_LENGTH = 80
+
+ def RunOnFile(self, filename, lines):
+ lint = []
+ lint.extend(VerifyIncludes(filename, lines))
+ lint.extend(common_lint.VerifyLineLength(filename, lines,
+ CppLint.MAX_LINE_LENGTH))
+ lint.extend(common_lint.VerifyTabs(filename, lines))
+ lint.extend(common_lint.VerifyTrailingWhitespace(filename, lines))
+ return lint
+
+
+def CppLintMain(filenames):
+ all_lint = common_lint.RunLintOverAllFiles(CppLint(), filenames)
+ for lint in all_lint:
+ print '%s:%d:%s' % (lint[0], lint[1], lint[2])
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(CppLintMain(sys.argv[1:]))
diff --git a/contrib/llvm/utils/lint/generic_lint.py b/contrib/llvm/utils/lint/generic_lint.py
new file mode 100755
index 0000000..c8f4835
--- /dev/null
+++ b/contrib/llvm/utils/lint/generic_lint.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+#
+# Checks files to make sure they conform to LLVM standards which can be applied
+# to any programming language: at present, line length and trailing whitespace.
+
+import common_lint
+import sys
+
+class GenericCodeLint(common_lint.BaseLint):
+ MAX_LINE_LENGTH = 80
+
+ def RunOnFile(self, filename, lines):
+ common_lint.VerifyLineLength(filename, lines,
+ GenericCodeLint.MAX_LINE_LENGTH)
+ common_lint.VerifyTrailingWhitespace(filename, lines)
+
+
+def GenericCodeLintMain(filenames):
+ common_lint.RunLintOverAllFiles(GenericCodeLint(), filenames)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(GenericCodeLintMain(sys.argv[1:]))
diff --git a/contrib/llvm/utils/lint/remove_trailing_whitespace.sh b/contrib/llvm/utils/lint/remove_trailing_whitespace.sh
new file mode 100755
index 0000000..6e0c9be
--- /dev/null
+++ b/contrib/llvm/utils/lint/remove_trailing_whitespace.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+# Deletes trailing whitespace in-place in the passed-in files.
+# Sample syntax:
+# $0 *.cpp
+
+perl -pi -e 's/\s+$/\n/' $*
diff --git a/contrib/llvm/utils/lit/TODO b/contrib/llvm/utils/lit/TODO
new file mode 100644
index 0000000..4d00d2c
--- /dev/null
+++ b/contrib/llvm/utils/lit/TODO
@@ -0,0 +1,19 @@
+ - Move temp directory name into local test config.
+
+ - Add --show-unsupported, don't show by default?
+
+ - Finish documentation.
+
+ - Optionally use multiprocessing.
+
+ - Support llvmc and ocaml tests.
+
+ - Support valgrind in all configs, and LLVM style valgrind.
+
+ - Provide test suite config for running unit tests.
+
+ - Support a timeout / ulimit.
+
+ - Support "disabling" tests? The advantage of making this distinct from XFAIL
+ is it makes it more obvious that it is a temporary measure (and lit can put
+ in a separate category).
diff --git a/contrib/llvm/utils/lit/lit.py b/contrib/llvm/utils/lit/lit.py
new file mode 100755
index 0000000..851063b
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+if __name__=='__main__':
+ import lit
+ lit.main()
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests.ObjDir/lit.site.cfg b/contrib/llvm/utils/lit/lit/ExampleTests.ObjDir/lit.site.cfg
new file mode 100644
index 0000000..14b6e01
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests.ObjDir/lit.site.cfg
@@ -0,0 +1,15 @@
+# -*- Python -*-
+
+# Site specific configuration file.
+#
+# Typically this will be generated by the build system to automatically set
+# certain configuration variables which cannot be autodetected, so that 'lit'
+# can easily be used on the command line.
+
+import os
+
+# Preserve the obj_root, for use by the main lit.cfg.
+config.example_obj_root = os.path.dirname(__file__)
+
+lit.load_config(config, os.path.join(config.test_source_root,
+ 'lit.cfg'))
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/Clang/fsyntax-only.c b/contrib/llvm/utils/lit/lit/ExampleTests/Clang/fsyntax-only.c
new file mode 100644
index 0000000..a4a064b
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/Clang/fsyntax-only.c
@@ -0,0 +1,4 @@
+// RUN: clang -fsyntax-only -Xclang -verify %s
+
+int f0(void) {} // expected-warning {{control reaches end of non-void function}}
+
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/Clang/lit.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/Clang/lit.cfg
new file mode 100644
index 0000000..1e1e807
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/Clang/lit.cfg
@@ -0,0 +1,47 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+# name: The name of this test suite.
+config.name = 'Clang'
+
+# testFormat: The test format to use to interpret tests.
+#
+# For now we require '&&' between commands, until they get globally killed and
+# the test runner updated.
+config.test_format = lit.formats.ShTest(execute_external = True)
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = ['.c', '.cpp', '.m', '.mm']
+
+# target_triple: Used by ShTest and TclTest formats for XFAIL checks.
+config.target_triple = 'foo'
+
+###
+
+# Discover the 'clang' and 'clangcc' to use.
+
+import os
+
+def inferClang(PATH):
+ # Determine which clang to use.
+ clang = os.getenv('CLANG')
+
+ # If the user set clang in the environment, definitely use that and don't
+ # try to validate.
+ if clang:
+ return clang
+
+ # Otherwise look in the path.
+ clang = lit.util.which('clang', PATH)
+
+ if not clang:
+ lit.fatal("couldn't find 'clang' program, try setting "
+ "CLANG in your environment")
+
+ return clang
+
+clang = inferClang(config.environment['PATH'])
+if not lit.quiet:
+ lit.note('using clang: %r' % clang)
+config.substitutions.append( (' clang ', ' ' + clang + ' ') )
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/bar-test.ll b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/bar-test.ll
new file mode 100644
index 0000000..3017b13
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/bar-test.ll
@@ -0,0 +1,3 @@
+; RUN: true
+; XFAIL: *
+; XTARGET: darwin
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/dg.exp b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/dg.exp
new file mode 100644
index 0000000..2bda07a
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/dg.exp
@@ -0,0 +1,6 @@
+load_lib llvm.exp
+
+if { [llvm_supports_target X86] } {
+ RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll}]]
+}
+
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg
new file mode 100644
index 0000000..e7ef037
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg
@@ -0,0 +1,151 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+import os
+
+# name: The name of this test suite.
+config.name = 'LLVM'
+
+# testFormat: The test format to use to interpret tests.
+config.test_format = lit.formats.TclTest()
+
+# suffixes: A list of file extensions to treat as test files, this is actually
+# set by on_clone().
+config.suffixes = []
+
+# test_source_root: The root path where tests are located.
+config.test_source_root = os.path.dirname(__file__)
+
+# test_exec_root: The root path where tests should be run.
+llvm_obj_root = getattr(config, 'llvm_obj_root', None)
+if llvm_obj_root is not None:
+ config.test_exec_root = os.path.join(llvm_obj_root, 'test')
+
+###
+
+import os
+
+# Check that the object root is known.
+if config.test_exec_root is None:
+ # Otherwise, we haven't loaded the site specific configuration (the user is
+ # probably trying to run on a test file directly, and either the site
+ # configuration hasn't been created by the build system, or we are in an
+ # out-of-tree build situation).
+
+ # Try to detect the situation where we are using an out-of-tree build by
+ # looking for 'llvm-config'.
+ #
+ # FIXME: I debated (i.e., wrote and threw away) adding logic to
+ # automagically generate the lit.site.cfg if we are in some kind of fresh
+ # build situation. This means knowing how to invoke the build system
+ # though, and I decided it was too much magic.
+
+ llvm_config = lit.util.which('llvm-config', config.environment['PATH'])
+ if not llvm_config:
+ lit.fatal('No site specific configuration available!')
+
+ # Get the source and object roots.
+ llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip()
+ llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip()
+
+ # Validate that we got a tree which points to here.
+ this_src_root = os.path.dirname(config.test_source_root)
+ if os.path.realpath(llvm_src_root) != os.path.realpath(this_src_root):
+ lit.fatal('No site specific configuration available!')
+
+ # Check that the site specific configuration exists.
+ site_cfg = os.path.join(llvm_obj_root, 'test', 'lit.site.cfg')
+ if not os.path.exists(site_cfg):
+ lit.fatal('No site specific configuration available!')
+
+ # Okay, that worked. Notify the user of the automagic, and reconfigure.
+ lit.note('using out-of-tree build at %r' % llvm_obj_root)
+ lit.load_config(config, site_cfg)
+ raise SystemExit
+
+###
+
+# Load site data from DejaGNU's site.exp.
+import re
+site_exp = {}
+# FIXME: Implement lit.site.cfg.
+for line in open(os.path.join(config.llvm_obj_root, 'test', 'site.exp')):
+ m = re.match('set ([^ ]+) "([^"]*)"', line)
+ if m:
+ site_exp[m.group(1)] = m.group(2)
+
+# Add substitutions.
+for sub in ['prcontext', 'llvmgcc', 'llvmgxx', 'compile_cxx', 'compile_c',
+ 'link', 'shlibext', 'ocamlopt', 'llvmdsymutil', 'llvmlibsdir',
+ 'bugpoint_topts']:
+ if sub in ('llvmgcc', 'llvmgxx'):
+ config.substitutions.append(('%' + sub,
+ site_exp[sub] + ' -emit-llvm -w'))
+ else:
+ config.substitutions.append(('%' + sub, site_exp[sub]))
+
+excludes = []
+
+# Provide target_triple for use in XFAIL and XTARGET.
+config.target_triple = site_exp['target_triplet']
+
+# Provide llvm_supports_target for use in local configs.
+targets = set(site_exp["TARGETS_TO_BUILD"].split())
+def llvm_supports_target(name):
+ return name in targets
+
+langs = set(site_exp['llvmgcc_langs'].split(','))
+def llvm_gcc_supports(name):
+ return name in langs
+
+# Provide on_clone hook for reading 'dg.exp'.
+import os
+simpleLibData = re.compile(r"""load_lib llvm.exp
+
+RunLLVMTests \[lsort \[glob -nocomplain \$srcdir/\$subdir/\*\.(.*)\]\]""",
+ re.MULTILINE)
+conditionalLibData = re.compile(r"""load_lib llvm.exp
+
+if.*\[ ?(llvm[^ ]*) ([^ ]*) ?\].*{
+ *RunLLVMTests \[lsort \[glob -nocomplain \$srcdir/\$subdir/\*\.(.*)\]\]
+\}""", re.MULTILINE)
+def on_clone(parent, cfg, for_path):
+ def addSuffixes(match):
+ if match[0] == '{' and match[-1] == '}':
+ cfg.suffixes = ['.' + s for s in match[1:-1].split(',')]
+ else:
+ cfg.suffixes = ['.' + match]
+
+ libPath = os.path.join(os.path.dirname(for_path),
+ 'dg.exp')
+ if not os.path.exists(libPath):
+ cfg.unsupported = True
+ return
+
+ # Reset unsupported, in case we inherited it.
+ cfg.unsupported = False
+ lib = open(libPath).read().strip()
+
+ # Check for a simple library.
+ m = simpleLibData.match(lib)
+ if m:
+ addSuffixes(m.group(1))
+ return
+
+ # Check for a conditional test set.
+ m = conditionalLibData.match(lib)
+ if m:
+ funcname,arg,match = m.groups()
+ addSuffixes(match)
+
+ func = globals().get(funcname)
+ if not func:
+ lit.error('unsupported predicate %r' % funcname)
+ elif not func(arg):
+ cfg.unsupported = True
+ return
+ # Otherwise, give up.
+ lit.error('unable to understand %r:\n%s' % (libPath, lib))
+
+config.on_clone = on_clone
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.site.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.site.cfg
new file mode 100644
index 0000000..3bfee54
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.site.cfg
@@ -0,0 +1,10 @@
+# -*- Python -*-
+
+## Autogenerated by Makefile ##
+# Do not edit!
+
+# Preserve some key paths for use by main LLVM test suite config.
+config.llvm_obj_root = os.path.dirname(os.path.dirname(__file__))
+
+# Let the main config do the real work.
+lit.load_config(config, os.path.join(config.llvm_obj_root, 'test/lit.cfg'))
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp
new file mode 100644
index 0000000..efa839e
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp
@@ -0,0 +1,28 @@
+## these variables are automatically generated by make ##
+# Do not edit here. If you wish to override these values
+# edit the last section
+set target_triplet "x86_64-apple-darwin10"
+set TARGETS_TO_BUILD "X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend MSIL CppBackend"
+set llvmgcc_langs "c,c++,objc,obj-c++"
+set prcontext "/usr/bin/tclsh8.4 /Volumes/Data/ddunbar/llvm/test/Scripts/prcontext.tcl"
+set llvmtoolsdir "/Users/ddunbar/llvm.obj.64/Debug/bin"
+set llvmlibsdir "/Users/ddunbar/llvm.obj.64/Debug/lib"
+set srcroot "/Volumes/Data/ddunbar/llvm"
+set objroot "/Volumes/Data/ddunbar/llvm.obj.64"
+set srcdir "/Volumes/Data/ddunbar/llvm/test"
+set objdir "/Volumes/Data/ddunbar/llvm.obj.64/test"
+set gccpath "/usr/bin/gcc -arch x86_64"
+set gxxpath "/usr/bin/g++ -arch x86_64"
+set compile_c " /usr/bin/gcc -arch x86_64 -I/Users/ddunbar/llvm.obj.64/include -I/Users/ddunbar/llvm.obj.64/test -I/Volumes/Data/ddunbar/llvm.obj.64/include -I/Volumes/Data/ddunbar/llvm/include -I/Volumes/Data/ddunbar/llvm/test -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -m64 -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -c "
+set compile_cxx " /usr/bin/g++ -arch x86_64 -I/Users/ddunbar/llvm.obj.64/include -I/Users/ddunbar/llvm.obj.64/test -I/Volumes/Data/ddunbar/llvm.obj.64/include -I/Volumes/Data/ddunbar/llvm/include -I/Volumes/Data/ddunbar/llvm/test -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -g -fno-exceptions -fno-common -Woverloaded-virtual -m64 -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -c "
+set link " /usr/bin/g++ -arch x86_64 -I/Users/ddunbar/llvm.obj.64/include -I/Users/ddunbar/llvm.obj.64/test -I/Volumes/Data/ddunbar/llvm.obj.64/include -I/Volumes/Data/ddunbar/llvm/include -I/Volumes/Data/ddunbar/llvm/test -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -g -fno-exceptions -fno-common -Woverloaded-virtual -m64 -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -g -L/Users/ddunbar/llvm.obj.64/Debug/lib -L/Volumes/Data/ddunbar/llvm.obj.64/Debug/lib "
+set llvmgcc "/Users/ddunbar/llvm-gcc/install/bin/llvm-gcc -m64 "
+set llvmgxx "/Users/ddunbar/llvm-gcc/install/bin/llvm-gcc -m64 "
+set bugpoint_topts "-gcc-tool-args -m64"
+set shlibext ".dylib"
+set ocamlopt "/sw/bin/ocamlopt -cc \"g++ -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT\" -I /Users/ddunbar/llvm.obj.64/Debug/lib/ocaml"
+set valgrind ""
+set grep "/usr/bin/grep"
+set gas "/usr/bin/as"
+set llvmdsymutil "dsymutil"
+## All variables above are generated by configure. Do Not Edit ##
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/lit.local.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/lit.local.cfg
new file mode 100644
index 0000000..80d0c7e
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/lit.local.cfg
@@ -0,0 +1 @@
+config.excludes = ['src']
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/Foo/lit.local.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/Foo/lit.local.cfg
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/Foo/lit.local.cfg
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg
new file mode 100644
index 0000000..bdcc35e
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg
@@ -0,0 +1,11 @@
+# -*- Python -*-
+
+## Autogenerated by Makefile ##
+# Do not edit!
+
+# Preserve some key paths for use by main LLVM test suite config.
+config.llvm_obj_root = os.path.dirname(os.path.dirname(__file__))
+
+# Let the main config do the real work.
+lit.load_config(config, os.path.join(config.llvm_obj_root,
+ '../src/test/lit.cfg'))
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp
new file mode 100644
index 0000000..efa839e
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp
@@ -0,0 +1,28 @@
+## these variables are automatically generated by make ##
+# Do not edit here. If you wish to override these values
+# edit the last section
+set target_triplet "x86_64-apple-darwin10"
+set TARGETS_TO_BUILD "X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend MSIL CppBackend"
+set llvmgcc_langs "c,c++,objc,obj-c++"
+set prcontext "/usr/bin/tclsh8.4 /Volumes/Data/ddunbar/llvm/test/Scripts/prcontext.tcl"
+set llvmtoolsdir "/Users/ddunbar/llvm.obj.64/Debug/bin"
+set llvmlibsdir "/Users/ddunbar/llvm.obj.64/Debug/lib"
+set srcroot "/Volumes/Data/ddunbar/llvm"
+set objroot "/Volumes/Data/ddunbar/llvm.obj.64"
+set srcdir "/Volumes/Data/ddunbar/llvm/test"
+set objdir "/Volumes/Data/ddunbar/llvm.obj.64/test"
+set gccpath "/usr/bin/gcc -arch x86_64"
+set gxxpath "/usr/bin/g++ -arch x86_64"
+set compile_c " /usr/bin/gcc -arch x86_64 -I/Users/ddunbar/llvm.obj.64/include -I/Users/ddunbar/llvm.obj.64/test -I/Volumes/Data/ddunbar/llvm.obj.64/include -I/Volumes/Data/ddunbar/llvm/include -I/Volumes/Data/ddunbar/llvm/test -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -m64 -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -c "
+set compile_cxx " /usr/bin/g++ -arch x86_64 -I/Users/ddunbar/llvm.obj.64/include -I/Users/ddunbar/llvm.obj.64/test -I/Volumes/Data/ddunbar/llvm.obj.64/include -I/Volumes/Data/ddunbar/llvm/include -I/Volumes/Data/ddunbar/llvm/test -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -g -fno-exceptions -fno-common -Woverloaded-virtual -m64 -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -c "
+set link " /usr/bin/g++ -arch x86_64 -I/Users/ddunbar/llvm.obj.64/include -I/Users/ddunbar/llvm.obj.64/test -I/Volumes/Data/ddunbar/llvm.obj.64/include -I/Volumes/Data/ddunbar/llvm/include -I/Volumes/Data/ddunbar/llvm/test -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -g -fno-exceptions -fno-common -Woverloaded-virtual -m64 -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -g -L/Users/ddunbar/llvm.obj.64/Debug/lib -L/Volumes/Data/ddunbar/llvm.obj.64/Debug/lib "
+set llvmgcc "/Users/ddunbar/llvm-gcc/install/bin/llvm-gcc -m64 "
+set llvmgxx "/Users/ddunbar/llvm-gcc/install/bin/llvm-gcc -m64 "
+set bugpoint_topts "-gcc-tool-args -m64"
+set shlibext ".dylib"
+set ocamlopt "/sw/bin/ocamlopt -cc \"g++ -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT\" -I /Users/ddunbar/llvm.obj.64/Debug/lib/ocaml"
+set valgrind ""
+set grep "/usr/bin/grep"
+set gas "/usr/bin/as"
+set llvmdsymutil "dsymutil"
+## All variables above are generated by configure. Do Not Edit ##
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/data.txt b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/data.txt
new file mode 100644
index 0000000..45b983b
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/data.txt
@@ -0,0 +1 @@
+hi
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/dg.exp b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/dg.exp
new file mode 100644
index 0000000..2bda07a
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/dg.exp
@@ -0,0 +1,6 @@
+load_lib llvm.exp
+
+if { [llvm_supports_target X86] } {
+ RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll}]]
+}
+
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/pct-S.ll b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/pct-S.ll
new file mode 100644
index 0000000..3ff3633
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/pct-S.ll
@@ -0,0 +1 @@
+; RUN: grep "hi" %S/data.txt
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/lit.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/lit.cfg
new file mode 100644
index 0000000..e7ef037
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/lit.cfg
@@ -0,0 +1,151 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+import os
+
+# name: The name of this test suite.
+config.name = 'LLVM'
+
+# testFormat: The test format to use to interpret tests.
+config.test_format = lit.formats.TclTest()
+
+# suffixes: A list of file extensions to treat as test files, this is actually
+# set by on_clone().
+config.suffixes = []
+
+# test_source_root: The root path where tests are located.
+config.test_source_root = os.path.dirname(__file__)
+
+# test_exec_root: The root path where tests should be run.
+llvm_obj_root = getattr(config, 'llvm_obj_root', None)
+if llvm_obj_root is not None:
+ config.test_exec_root = os.path.join(llvm_obj_root, 'test')
+
+###
+
+import os
+
+# Check that the object root is known.
+if config.test_exec_root is None:
+ # Otherwise, we haven't loaded the site specific configuration (the user is
+ # probably trying to run on a test file directly, and either the site
+ # configuration hasn't been created by the build system, or we are in an
+ # out-of-tree build situation).
+
+ # Try to detect the situation where we are using an out-of-tree build by
+ # looking for 'llvm-config'.
+ #
+ # FIXME: I debated (i.e., wrote and threw away) adding logic to
+ # automagically generate the lit.site.cfg if we are in some kind of fresh
+ # build situation. This means knowing how to invoke the build system
+ # though, and I decided it was too much magic.
+
+ llvm_config = lit.util.which('llvm-config', config.environment['PATH'])
+ if not llvm_config:
+ lit.fatal('No site specific configuration available!')
+
+ # Get the source and object roots.
+ llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip()
+ llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip()
+
+ # Validate that we got a tree which points to here.
+ this_src_root = os.path.dirname(config.test_source_root)
+ if os.path.realpath(llvm_src_root) != os.path.realpath(this_src_root):
+ lit.fatal('No site specific configuration available!')
+
+ # Check that the site specific configuration exists.
+ site_cfg = os.path.join(llvm_obj_root, 'test', 'lit.site.cfg')
+ if not os.path.exists(site_cfg):
+ lit.fatal('No site specific configuration available!')
+
+ # Okay, that worked. Notify the user of the automagic, and reconfigure.
+ lit.note('using out-of-tree build at %r' % llvm_obj_root)
+ lit.load_config(config, site_cfg)
+ raise SystemExit
+
+###
+
+# Load site data from DejaGNU's site.exp.
+import re
+site_exp = {}
+# FIXME: Implement lit.site.cfg.
+for line in open(os.path.join(config.llvm_obj_root, 'test', 'site.exp')):
+ m = re.match('set ([^ ]+) "([^"]*)"', line)
+ if m:
+ site_exp[m.group(1)] = m.group(2)
+
+# Add substitutions.
+for sub in ['prcontext', 'llvmgcc', 'llvmgxx', 'compile_cxx', 'compile_c',
+ 'link', 'shlibext', 'ocamlopt', 'llvmdsymutil', 'llvmlibsdir',
+ 'bugpoint_topts']:
+ if sub in ('llvmgcc', 'llvmgxx'):
+ config.substitutions.append(('%' + sub,
+ site_exp[sub] + ' -emit-llvm -w'))
+ else:
+ config.substitutions.append(('%' + sub, site_exp[sub]))
+
+excludes = []
+
+# Provide target_triple for use in XFAIL and XTARGET.
+config.target_triple = site_exp['target_triplet']
+
+# Provide llvm_supports_target for use in local configs.
+targets = set(site_exp["TARGETS_TO_BUILD"].split())
+def llvm_supports_target(name):
+ return name in targets
+
+langs = set(site_exp['llvmgcc_langs'].split(','))
+def llvm_gcc_supports(name):
+ return name in langs
+
+# Provide on_clone hook for reading 'dg.exp'.
+import os
+simpleLibData = re.compile(r"""load_lib llvm.exp
+
+RunLLVMTests \[lsort \[glob -nocomplain \$srcdir/\$subdir/\*\.(.*)\]\]""",
+ re.MULTILINE)
+conditionalLibData = re.compile(r"""load_lib llvm.exp
+
+if.*\[ ?(llvm[^ ]*) ([^ ]*) ?\].*{
+ *RunLLVMTests \[lsort \[glob -nocomplain \$srcdir/\$subdir/\*\.(.*)\]\]
+\}""", re.MULTILINE)
+def on_clone(parent, cfg, for_path):
+ def addSuffixes(match):
+ if match[0] == '{' and match[-1] == '}':
+ cfg.suffixes = ['.' + s for s in match[1:-1].split(',')]
+ else:
+ cfg.suffixes = ['.' + match]
+
+ libPath = os.path.join(os.path.dirname(for_path),
+ 'dg.exp')
+ if not os.path.exists(libPath):
+ cfg.unsupported = True
+ return
+
+ # Reset unsupported, in case we inherited it.
+ cfg.unsupported = False
+ lib = open(libPath).read().strip()
+
+ # Check for a simple library.
+ m = simpleLibData.match(lib)
+ if m:
+ addSuffixes(m.group(1))
+ return
+
+ # Check for a conditional test set.
+ m = conditionalLibData.match(lib)
+ if m:
+ funcname,arg,match = m.groups()
+ addSuffixes(match)
+
+ func = globals().get(funcname)
+ if not func:
+ lit.error('unsupported predicate %r' % funcname)
+ elif not func(arg):
+ cfg.unsupported = True
+ return
+ # Otherwise, give up.
+ lit.error('unable to understand %r:\n%s' % (libPath, lib))
+
+config.on_clone = on_clone
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/ShExternal/lit.local.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/ShExternal/lit.local.cfg
new file mode 100644
index 0000000..1061da6
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/ShExternal/lit.local.cfg
@@ -0,0 +1,6 @@
+# -*- Python -*-
+
+config.test_format = lit.formats.ShTest(execute_external = True)
+
+config.suffixes = ['.c']
+
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/ShInternal/lit.local.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/ShInternal/lit.local.cfg
new file mode 100644
index 0000000..448eaa4
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/ShInternal/lit.local.cfg
@@ -0,0 +1,6 @@
+# -*- Python -*-
+
+config.test_format = lit.formats.ShTest(execute_external = False)
+
+config.suffixes = ['.c']
+
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg
new file mode 100644
index 0000000..6a37129
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg
@@ -0,0 +1,5 @@
+# -*- Python -*-
+
+config.test_format = lit.formats.TclTest()
+
+config.suffixes = ['.ll']
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/TclTest/stderr-pipe.ll b/contrib/llvm/utils/lit/lit/ExampleTests/TclTest/stderr-pipe.ll
new file mode 100644
index 0000000..6c55fe8
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/TclTest/stderr-pipe.ll
@@ -0,0 +1 @@
+; RUN: gcc -### > /dev/null |& grep {gcc version}
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll b/contrib/llvm/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll
new file mode 100644
index 0000000..61240ba
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll
@@ -0,0 +1,7 @@
+; RUN: echo 'hi' > %t.1 | echo 'hello' > %t.2
+; RUN: not grep 'hi' %t.1
+; RUN: grep 'hello' %t.2
+
+
+
+
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/fail.c b/contrib/llvm/utils/lit/lit/ExampleTests/fail.c
new file mode 100644
index 0000000..84db41a
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/fail.c
@@ -0,0 +1,2 @@
+// RUN: echo 'I am some stdout'
+// RUN: false
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/lit.cfg b/contrib/llvm/utils/lit/lit/ExampleTests/lit.cfg
new file mode 100644
index 0000000..20ee37d
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/lit.cfg
@@ -0,0 +1,26 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+# name: The name of this test suite.
+config.name = 'Examples'
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = ['.c', '.cpp', '.m', '.mm', '.ll']
+
+# testFormat: The test format to use to interpret tests.
+config.test_format = lit.formats.ShTest()
+
+# test_source_root: The path where tests are located (default is the test suite
+# root).
+config.test_source_root = None
+
+# test_exec_root: The path where tests are located (default is the test suite
+# root).
+config.test_exec_root = None
+
+# target_triple: Used by ShTest and TclTest formats for XFAIL checks.
+config.target_triple = 'foo'
+
+# available_features: Used by ShTest and TclTest formats for REQUIRES checks.
+config.available_features = ['some-feature-name']
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/pass.c b/contrib/llvm/utils/lit/lit/ExampleTests/pass.c
new file mode 100644
index 0000000..5c1031c
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/pass.c
@@ -0,0 +1 @@
+// RUN: true
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/required-and-missing.c b/contrib/llvm/utils/lit/lit/ExampleTests/required-and-missing.c
new file mode 100644
index 0000000..47ba72e
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/required-and-missing.c
@@ -0,0 +1,4 @@
+// This test shouldn't be run, the required feature is missing.
+//
+// RUN: false
+// REQUIRES: some-missing-feature-name
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/required-and-present.c b/contrib/llvm/utils/lit/lit/ExampleTests/required-and-present.c
new file mode 100644
index 0000000..2a09e08
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/required-and-present.c
@@ -0,0 +1,2 @@
+// RUN: true
+// REQUIRES: some-feature-name
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/xfail.c b/contrib/llvm/utils/lit/lit/ExampleTests/xfail.c
new file mode 100644
index 0000000..b36cd99
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/xfail.c
@@ -0,0 +1,2 @@
+// RUN: false
+// XFAIL: *
diff --git a/contrib/llvm/utils/lit/lit/ExampleTests/xpass.c b/contrib/llvm/utils/lit/lit/ExampleTests/xpass.c
new file mode 100644
index 0000000..ad84990
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ExampleTests/xpass.c
@@ -0,0 +1,2 @@
+// RUN: true
+// XFAIL
diff --git a/contrib/llvm/utils/lit/lit/LitConfig.py b/contrib/llvm/utils/lit/lit/LitConfig.py
new file mode 100644
index 0000000..ac48591
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/LitConfig.py
@@ -0,0 +1,112 @@
+class LitConfig:
+ """LitConfig - Configuration data for a 'lit' test runner instance, shared
+ across all tests.
+
+ The LitConfig object is also used to communicate with client configuration
+ files, it is always passed in as the global variable 'lit' so that
+ configuration files can access common functionality and internal components
+ easily.
+ """
+
+ # Provide access to built-in formats.
+ import LitFormats as formats
+
+ # Provide access to built-in utility functions.
+ import Util as util
+
+ def __init__(self, progname, path, quiet,
+ useValgrind, valgrindLeakCheck, valgrindArgs,
+ useTclAsSh,
+ noExecute, debug, isWindows,
+ params):
+ # The name of the test runner.
+ self.progname = progname
+ # The items to add to the PATH environment variable.
+ self.path = list(map(str, path))
+ self.quiet = bool(quiet)
+ self.useValgrind = bool(useValgrind)
+ self.valgrindLeakCheck = bool(valgrindLeakCheck)
+ self.valgrindUserArgs = list(valgrindArgs)
+ self.useTclAsSh = bool(useTclAsSh)
+ self.noExecute = noExecute
+ self.debug = debug
+ self.isWindows = bool(isWindows)
+ self.params = dict(params)
+ self.bashPath = None
+
+ self.numErrors = 0
+ self.numWarnings = 0
+
+ self.valgrindArgs = []
+ self.valgrindTriple = ""
+ if self.useValgrind:
+ self.valgrindTriple = "-vg"
+ self.valgrindArgs = ['valgrind', '-q', '--run-libc-freeres=no',
+ '--tool=memcheck', '--trace-children=yes',
+ '--error-exitcode=123']
+ if self.valgrindLeakCheck:
+ self.valgrindTriple += "_leak"
+ self.valgrindArgs.append('--leak-check=full')
+ else:
+ # The default is 'summary'.
+ self.valgrindArgs.append('--leak-check=no')
+ self.valgrindArgs.extend(self.valgrindUserArgs)
+
+
+ def load_config(self, config, path):
+ """load_config(config, path) - Load a config object from an alternate
+ path."""
+ from TestingConfig import TestingConfig
+ return TestingConfig.frompath(path, config.parent, self,
+ mustExist = True,
+ config = config)
+
+ def getBashPath(self):
+ """getBashPath - Get the path to 'bash'"""
+ import os, Util
+
+ if self.bashPath is not None:
+ return self.bashPath
+
+ self.bashPath = Util.which('bash', os.pathsep.join(self.path))
+ if self.bashPath is None:
+ # Check some known paths.
+ for path in ('/bin/bash', '/usr/bin/bash', '/usr/local/bin/bash'):
+ if os.path.exists(path):
+ self.bashPath = path
+ break
+
+ if self.bashPath is None:
+ self.warning("Unable to find 'bash', running Tcl tests internally.")
+ self.bashPath = ''
+
+ return self.bashPath
+
+ def _write_message(self, kind, message):
+ import inspect, os, sys
+
+ # Get the file/line where this message was generated.
+ f = inspect.currentframe()
+ # Step out of _write_message, and then out of wrapper.
+ f = f.f_back.f_back
+ file,line,_,_,_ = inspect.getframeinfo(f)
+ location = '%s:%d' % (os.path.basename(file), line)
+
+ print >>sys.stderr, '%s: %s: %s: %s' % (self.progname, location,
+ kind, message)
+
+ def note(self, message):
+ self._write_message('note', message)
+
+ def warning(self, message):
+ self._write_message('warning', message)
+ self.numWarnings += 1
+
+ def error(self, message):
+ self._write_message('error', message)
+ self.numErrors += 1
+
+ def fatal(self, message):
+ import sys
+ self._write_message('fatal', message)
+ sys.exit(2)
diff --git a/contrib/llvm/utils/lit/lit/LitFormats.py b/contrib/llvm/utils/lit/lit/LitFormats.py
new file mode 100644
index 0000000..e86f103
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/LitFormats.py
@@ -0,0 +1,2 @@
+from TestFormats import GoogleTest, ShTest, TclTest
+from TestFormats import SyntaxCheckTest, OneCommandPerFileTest
diff --git a/contrib/llvm/utils/lit/lit/LitTestCase.py b/contrib/llvm/utils/lit/lit/LitTestCase.py
new file mode 100644
index 0000000..8951185
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/LitTestCase.py
@@ -0,0 +1,30 @@
+import unittest
+import Test
+
+"""
+TestCase adaptor for providing a 'unittest' compatible interface to 'lit' tests.
+"""
+
+class UnresolvedError(RuntimeError):
+ pass
+
+class LitTestCase(unittest.TestCase):
+ def __init__(self, test, lit_config):
+ unittest.TestCase.__init__(self)
+ self._test = test
+ self._lit_config = lit_config
+
+ def id(self):
+ return self._test.getFullName()
+
+ def shortDescription(self):
+ return self._test.getFullName()
+
+ def runTest(self):
+ tr, output = self._test.config.test_format.execute(
+ self._test, self._lit_config)
+
+ if tr is Test.UNRESOLVED:
+ raise UnresolvedError(output)
+ elif tr.isFailure:
+ self.fail(output)
diff --git a/contrib/llvm/utils/lit/lit/ProgressBar.py b/contrib/llvm/utils/lit/lit/ProgressBar.py
new file mode 100644
index 0000000..85c95f5
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ProgressBar.py
@@ -0,0 +1,267 @@
+#!/usr/bin/env python
+
+# Source: http://code.activestate.com/recipes/475116/, with
+# modifications by Daniel Dunbar.
+
+import sys, re, time
+
+class TerminalController:
+ """
+ A class that can be used to portably generate formatted output to
+ a terminal.
+
+ `TerminalController` defines a set of instance variables whose
+ values are initialized to the control sequence necessary to
+ perform a given action. These can be simply included in normal
+ output to the terminal:
+
+ >>> term = TerminalController()
+ >>> print 'This is '+term.GREEN+'green'+term.NORMAL
+
+ Alternatively, the `render()` method can used, which replaces
+ '${action}' with the string required to perform 'action':
+
+ >>> term = TerminalController()
+ >>> print term.render('This is ${GREEN}green${NORMAL}')
+
+ If the terminal doesn't support a given action, then the value of
+ the corresponding instance variable will be set to ''. As a
+ result, the above code will still work on terminals that do not
+ support color, except that their output will not be colored.
+ Also, this means that you can test whether the terminal supports a
+ given action by simply testing the truth value of the
+ corresponding instance variable:
+
+ >>> term = TerminalController()
+ >>> if term.CLEAR_SCREEN:
+ ... print 'This terminal supports clearning the screen.'
+
+ Finally, if the width and height of the terminal are known, then
+ they will be stored in the `COLS` and `LINES` attributes.
+ """
+ # Cursor movement:
+ BOL = '' #: Move the cursor to the beginning of the line
+ UP = '' #: Move the cursor up one line
+ DOWN = '' #: Move the cursor down one line
+ LEFT = '' #: Move the cursor left one char
+ RIGHT = '' #: Move the cursor right one char
+
+ # Deletion:
+ CLEAR_SCREEN = '' #: Clear the screen and move to home position
+ CLEAR_EOL = '' #: Clear to the end of the line.
+ CLEAR_BOL = '' #: Clear to the beginning of the line.
+ CLEAR_EOS = '' #: Clear to the end of the screen
+
+ # Output modes:
+ BOLD = '' #: Turn on bold mode
+ BLINK = '' #: Turn on blink mode
+ DIM = '' #: Turn on half-bright mode
+ REVERSE = '' #: Turn on reverse-video mode
+ NORMAL = '' #: Turn off all modes
+
+ # Cursor display:
+ HIDE_CURSOR = '' #: Make the cursor invisible
+ SHOW_CURSOR = '' #: Make the cursor visible
+
+ # Terminal size:
+ COLS = None #: Width of the terminal (None for unknown)
+ LINES = None #: Height of the terminal (None for unknown)
+
+ # Foreground colors:
+ BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = ''
+
+ # Background colors:
+ BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = ''
+ BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = ''
+
+ _STRING_CAPABILITIES = """
+ BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1
+ CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold
+ BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0
+ HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split()
+ _COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split()
+ _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
+
+ def __init__(self, term_stream=sys.stdout):
+ """
+ Create a `TerminalController` and initialize its attributes
+ with appropriate values for the current terminal.
+ `term_stream` is the stream that will be used for terminal
+ output; if this stream is not a tty, then the terminal is
+ assumed to be a dumb terminal (i.e., have no capabilities).
+ """
+ # Curses isn't available on all platforms
+ try: import curses
+ except: return
+
+ # If the stream isn't a tty, then assume it has no capabilities.
+ if not term_stream.isatty(): return
+
+ # Check the terminal type. If we fail, then assume that the
+ # terminal has no capabilities.
+ try: curses.setupterm()
+ except: return
+
+ # Look up numeric capabilities.
+ self.COLS = curses.tigetnum('cols')
+ self.LINES = curses.tigetnum('lines')
+
+ # Look up string capabilities.
+ for capability in self._STRING_CAPABILITIES:
+ (attrib, cap_name) = capability.split('=')
+ setattr(self, attrib, self._tigetstr(cap_name) or '')
+
+ # Colors
+ set_fg = self._tigetstr('setf')
+ if set_fg:
+ for i,color in zip(range(len(self._COLORS)), self._COLORS):
+ setattr(self, color, curses.tparm(set_fg, i) or '')
+ set_fg_ansi = self._tigetstr('setaf')
+ if set_fg_ansi:
+ for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
+ setattr(self, color, curses.tparm(set_fg_ansi, i) or '')
+ set_bg = self._tigetstr('setb')
+ if set_bg:
+ for i,color in zip(range(len(self._COLORS)), self._COLORS):
+ setattr(self, 'BG_'+color, curses.tparm(set_bg, i) or '')
+ set_bg_ansi = self._tigetstr('setab')
+ if set_bg_ansi:
+ for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
+ setattr(self, 'BG_'+color, curses.tparm(set_bg_ansi, i) or '')
+
+ def _tigetstr(self, cap_name):
+ # String capabilities can include "delays" of the form "$<2>".
+ # For any modern terminal, we should be able to just ignore
+ # these, so strip them out.
+ import curses
+ cap = curses.tigetstr(cap_name) or ''
+ return re.sub(r'\$<\d+>[/*]?', '', cap)
+
+ def render(self, template):
+ """
+ Replace each $-substitutions in the given template string with
+ the corresponding terminal control string (if it's defined) or
+ '' (if it's not).
+ """
+ return re.sub(r'\$\$|\${\w+}', self._render_sub, template)
+
+ def _render_sub(self, match):
+ s = match.group()
+ if s == '$$': return s
+ else: return getattr(self, s[2:-1])
+
+#######################################################################
+# Example use case: progress bar
+#######################################################################
+
+class SimpleProgressBar:
+ """
+ A simple progress bar which doesn't need any terminal support.
+
+ This prints out a progress bar like:
+ 'Header: 0 .. 10.. 20.. ...'
+ """
+
+ def __init__(self, header):
+ self.header = header
+ self.atIndex = None
+
+ def update(self, percent, message):
+ if self.atIndex is None:
+ sys.stdout.write(self.header)
+ self.atIndex = 0
+
+ next = int(percent*50)
+ if next == self.atIndex:
+ return
+
+ for i in range(self.atIndex, next):
+ idx = i % 5
+ if idx == 0:
+ sys.stdout.write('%-2d' % (i*2))
+ elif idx == 1:
+ pass # Skip second char
+ elif idx < 4:
+ sys.stdout.write('.')
+ else:
+ sys.stdout.write(' ')
+ sys.stdout.flush()
+ self.atIndex = next
+
+ def clear(self):
+ if self.atIndex is not None:
+ sys.stdout.write('\n')
+ sys.stdout.flush()
+ self.atIndex = None
+
+class ProgressBar:
+ """
+ A 3-line progress bar, which looks like::
+
+ Header
+ 20% [===========----------------------------------]
+ progress message
+
+ The progress bar is colored, if the terminal supports color
+ output; and adjusts to the width of the terminal.
+ """
+ BAR = '%s${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}%s\n'
+ HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
+
+ def __init__(self, term, header, useETA=True):
+ self.term = term
+ if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
+ raise ValueError("Terminal isn't capable enough -- you "
+ "should use a simpler progress dispaly.")
+ self.width = self.term.COLS or 75
+ self.bar = term.render(self.BAR)
+ self.header = self.term.render(self.HEADER % header.center(self.width))
+ self.cleared = 1 #: true if we haven't drawn the bar yet.
+ self.useETA = useETA
+ if self.useETA:
+ self.startTime = time.time()
+ self.update(0, '')
+
+ def update(self, percent, message):
+ if self.cleared:
+ sys.stdout.write(self.header)
+ self.cleared = 0
+ prefix = '%3d%% ' % (percent*100,)
+ suffix = ''
+ if self.useETA:
+ elapsed = time.time() - self.startTime
+ if percent > .0001 and elapsed > 1:
+ total = elapsed / percent
+ eta = int(total - elapsed)
+ h = eta//3600.
+ m = (eta//60) % 60
+ s = eta % 60
+ suffix = ' ETA: %02d:%02d:%02d'%(h,m,s)
+ barWidth = self.width - len(prefix) - len(suffix) - 2
+ n = int(barWidth*percent)
+ if len(message) < self.width:
+ message = message + ' '*(self.width - len(message))
+ else:
+ message = '... ' + message[-(self.width-4):]
+ sys.stdout.write(
+ self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
+ (self.bar % (prefix, '='*n, '-'*(barWidth-n), suffix)) +
+ self.term.CLEAR_EOL + message)
+
+ def clear(self):
+ if not self.cleared:
+ sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
+ self.term.UP + self.term.CLEAR_EOL +
+ self.term.UP + self.term.CLEAR_EOL)
+ self.cleared = 1
+
+def test():
+ import time
+ tc = TerminalController()
+ p = ProgressBar(tc, 'Tests')
+ for i in range(101):
+ p.update(i/100., str(i))
+ time.sleep(.3)
+
+if __name__=='__main__':
+ test()
diff --git a/contrib/llvm/utils/lit/lit/ShCommands.py b/contrib/llvm/utils/lit/lit/ShCommands.py
new file mode 100644
index 0000000..4550437
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ShCommands.py
@@ -0,0 +1,85 @@
+class Command:
+ def __init__(self, args, redirects):
+ self.args = list(args)
+ self.redirects = list(redirects)
+
+ def __repr__(self):
+ return 'Command(%r, %r)' % (self.args, self.redirects)
+
+ def __cmp__(self, other):
+ if not isinstance(other, Command):
+ return -1
+
+ return cmp((self.args, self.redirects),
+ (other.args, other.redirects))
+
+ def toShell(self, file):
+ for arg in self.args:
+ if "'" not in arg:
+ quoted = "'%s'" % arg
+ elif '"' not in arg and '$' not in arg:
+ quoted = '"%s"' % arg
+ else:
+ raise NotImplementedError,'Unable to quote %r' % arg
+ print >>file, quoted,
+
+ # For debugging / validation.
+ import ShUtil
+ dequoted = list(ShUtil.ShLexer(quoted).lex())
+ if dequoted != [arg]:
+ raise NotImplementedError,'Unable to quote %r' % arg
+
+ for r in self.redirects:
+ if len(r[0]) == 1:
+ print >>file, "%s '%s'" % (r[0][0], r[1]),
+ else:
+ print >>file, "%s%s '%s'" % (r[0][1], r[0][0], r[1]),
+
+class Pipeline:
+ def __init__(self, commands, negate=False, pipe_err=False):
+ self.commands = commands
+ self.negate = negate
+ self.pipe_err = pipe_err
+
+ def __repr__(self):
+ return 'Pipeline(%r, %r, %r)' % (self.commands, self.negate,
+ self.pipe_err)
+
+ def __cmp__(self, other):
+ if not isinstance(other, Pipeline):
+ return -1
+
+ return cmp((self.commands, self.negate, self.pipe_err),
+ (other.commands, other.negate, self.pipe_err))
+
+ def toShell(self, file, pipefail=False):
+ if pipefail != self.pipe_err:
+ raise ValueError,'Inconsistent "pipefail" attribute!'
+ if self.negate:
+ print >>file, '!',
+ for cmd in self.commands:
+ cmd.toShell(file)
+ if cmd is not self.commands[-1]:
+ print >>file, '|\n ',
+
+class Seq:
+ def __init__(self, lhs, op, rhs):
+ assert op in (';', '&', '||', '&&')
+ self.op = op
+ self.lhs = lhs
+ self.rhs = rhs
+
+ def __repr__(self):
+ return 'Seq(%r, %r, %r)' % (self.lhs, self.op, self.rhs)
+
+ def __cmp__(self, other):
+ if not isinstance(other, Seq):
+ return -1
+
+ return cmp((self.lhs, self.op, self.rhs),
+ (other.lhs, other.op, other.rhs))
+
+ def toShell(self, file, pipefail=False):
+ self.lhs.toShell(file, pipefail)
+ print >>file, ' %s\n' % self.op
+ self.rhs.toShell(file, pipefail)
diff --git a/contrib/llvm/utils/lit/lit/ShUtil.py b/contrib/llvm/utils/lit/lit/ShUtil.py
new file mode 100644
index 0000000..dda622a
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/ShUtil.py
@@ -0,0 +1,353 @@
+import itertools
+
+import Util
+from ShCommands import Command, Pipeline, Seq
+
+class ShLexer:
+ def __init__(self, data, win32Escapes = False):
+ self.data = data
+ self.pos = 0
+ self.end = len(data)
+ self.win32Escapes = win32Escapes
+
+ def eat(self):
+ c = self.data[self.pos]
+ self.pos += 1
+ return c
+
+ def look(self):
+ return self.data[self.pos]
+
+ def maybe_eat(self, c):
+ """
+ maybe_eat(c) - Consume the character c if it is the next character,
+ returning True if a character was consumed. """
+ if self.data[self.pos] == c:
+ self.pos += 1
+ return True
+ return False
+
+ def lex_arg_fast(self, c):
+ # Get the leading whitespace free section.
+ chunk = self.data[self.pos - 1:].split(None, 1)[0]
+
+ # If it has special characters, the fast path failed.
+ if ('|' in chunk or '&' in chunk or
+ '<' in chunk or '>' in chunk or
+ "'" in chunk or '"' in chunk or
+ '\\' in chunk):
+ return None
+
+ self.pos = self.pos - 1 + len(chunk)
+ return chunk
+
+ def lex_arg_slow(self, c):
+ if c in "'\"":
+ str = self.lex_arg_quoted(c)
+ else:
+ str = c
+ while self.pos != self.end:
+ c = self.look()
+ if c.isspace() or c in "|&":
+ break
+ elif c in '><':
+ # This is an annoying case; we treat '2>' as a single token so
+ # we don't have to track whitespace tokens.
+
+ # If the parse string isn't an integer, do the usual thing.
+ if not str.isdigit():
+ break
+
+ # Otherwise, lex the operator and convert to a redirection
+ # token.
+ num = int(str)
+ tok = self.lex_one_token()
+ assert isinstance(tok, tuple) and len(tok) == 1
+ return (tok[0], num)
+ elif c == '"':
+ self.eat()
+ str += self.lex_arg_quoted('"')
+ elif c == "'":
+ self.eat()
+ str += self.lex_arg_quoted("'")
+ elif not self.win32Escapes and c == '\\':
+ # Outside of a string, '\\' escapes everything.
+ self.eat()
+ if self.pos == self.end:
+ Util.warning("escape at end of quoted argument in: %r" %
+ self.data)
+ return str
+ str += self.eat()
+ else:
+ str += self.eat()
+ return str
+
+ def lex_arg_quoted(self, delim):
+ str = ''
+ while self.pos != self.end:
+ c = self.eat()
+ if c == delim:
+ return str
+ elif c == '\\' and delim == '"':
+ # Inside a '"' quoted string, '\\' only escapes the quote
+ # character and backslash, otherwise it is preserved.
+ if self.pos == self.end:
+ Util.warning("escape at end of quoted argument in: %r" %
+ self.data)
+ return str
+ c = self.eat()
+ if c == '"': #
+ str += '"'
+ elif c == '\\':
+ str += '\\'
+ else:
+ str += '\\' + c
+ else:
+ str += c
+ Util.warning("missing quote character in %r" % self.data)
+ return str
+
+ def lex_arg_checked(self, c):
+ pos = self.pos
+ res = self.lex_arg_fast(c)
+ end = self.pos
+
+ self.pos = pos
+ reference = self.lex_arg_slow(c)
+ if res is not None:
+ if res != reference:
+ raise ValueError,"Fast path failure: %r != %r" % (res, reference)
+ if self.pos != end:
+ raise ValueError,"Fast path failure: %r != %r" % (self.pos, end)
+ return reference
+
+ def lex_arg(self, c):
+ return self.lex_arg_fast(c) or self.lex_arg_slow(c)
+
+ def lex_one_token(self):
+ """
+ lex_one_token - Lex a single 'sh' token. """
+
+ c = self.eat()
+ if c in ';!':
+ return (c,)
+ if c == '|':
+ if self.maybe_eat('|'):
+ return ('||',)
+ return (c,)
+ if c == '&':
+ if self.maybe_eat('&'):
+ return ('&&',)
+ if self.maybe_eat('>'):
+ return ('&>',)
+ return (c,)
+ if c == '>':
+ if self.maybe_eat('&'):
+ return ('>&',)
+ if self.maybe_eat('>'):
+ return ('>>',)
+ return (c,)
+ if c == '<':
+ if self.maybe_eat('&'):
+ return ('<&',)
+ if self.maybe_eat('>'):
+ return ('<<',)
+ return (c,)
+
+ return self.lex_arg(c)
+
+ def lex(self):
+ while self.pos != self.end:
+ if self.look().isspace():
+ self.eat()
+ else:
+ yield self.lex_one_token()
+
+###
+
+class ShParser:
+ def __init__(self, data, win32Escapes = False):
+ self.data = data
+ self.tokens = ShLexer(data, win32Escapes = win32Escapes).lex()
+
+ def lex(self):
+ try:
+ return self.tokens.next()
+ except StopIteration:
+ return None
+
+ def look(self):
+ next = self.lex()
+ if next is not None:
+ self.tokens = itertools.chain([next], self.tokens)
+ return next
+
+ def parse_command(self):
+ tok = self.lex()
+ if not tok:
+ raise ValueError,"empty command!"
+ if isinstance(tok, tuple):
+ raise ValueError,"syntax error near unexpected token %r" % tok[0]
+
+ args = [tok]
+ redirects = []
+ while 1:
+ tok = self.look()
+
+ # EOF?
+ if tok is None:
+ break
+
+ # If this is an argument, just add it to the current command.
+ if isinstance(tok, str):
+ args.append(self.lex())
+ continue
+
+ # Otherwise see if it is a terminator.
+ assert isinstance(tok, tuple)
+ if tok[0] in ('|',';','&','||','&&'):
+ break
+
+ # Otherwise it must be a redirection.
+ op = self.lex()
+ arg = self.lex()
+ if not arg:
+ raise ValueError,"syntax error near token %r" % op[0]
+ redirects.append((op, arg))
+
+ return Command(args, redirects)
+
+ def parse_pipeline(self):
+ negate = False
+ if self.look() == ('!',):
+ self.lex()
+ negate = True
+
+ commands = [self.parse_command()]
+ while self.look() == ('|',):
+ self.lex()
+ commands.append(self.parse_command())
+ return Pipeline(commands, negate)
+
+ def parse(self):
+ lhs = self.parse_pipeline()
+
+ while self.look():
+ operator = self.lex()
+ assert isinstance(operator, tuple) and len(operator) == 1
+
+ if not self.look():
+ raise ValueError, "missing argument to operator %r" % operator[0]
+
+ # FIXME: Operator precedence!!
+ lhs = Seq(lhs, operator[0], self.parse_pipeline())
+
+ return lhs
+
+###
+
+import unittest
+
+class TestShLexer(unittest.TestCase):
+ def lex(self, str, *args, **kwargs):
+ return list(ShLexer(str, *args, **kwargs).lex())
+
+ def test_basic(self):
+ self.assertEqual(self.lex('a|b>c&d<e'),
+ ['a', ('|',), 'b', ('>',), 'c', ('&',), 'd',
+ ('<',), 'e'])
+
+ def test_redirection_tokens(self):
+ self.assertEqual(self.lex('a2>c'),
+ ['a2', ('>',), 'c'])
+ self.assertEqual(self.lex('a 2>c'),
+ ['a', ('>',2), 'c'])
+
+ def test_quoting(self):
+ self.assertEqual(self.lex(""" 'a' """),
+ ['a'])
+ self.assertEqual(self.lex(""" "hello\\"world" """),
+ ['hello"world'])
+ self.assertEqual(self.lex(""" "hello\\'world" """),
+ ["hello\\'world"])
+ self.assertEqual(self.lex(""" "hello\\\\world" """),
+ ["hello\\world"])
+ self.assertEqual(self.lex(""" he"llo wo"rld """),
+ ["hello world"])
+ self.assertEqual(self.lex(""" a\\ b a\\\\b """),
+ ["a b", "a\\b"])
+ self.assertEqual(self.lex(""" "" "" """),
+ ["", ""])
+ self.assertEqual(self.lex(""" a\\ b """, win32Escapes = True),
+ ['a\\', 'b'])
+
+class TestShParse(unittest.TestCase):
+ def parse(self, str):
+ return ShParser(str).parse()
+
+ def test_basic(self):
+ self.assertEqual(self.parse('echo hello'),
+ Pipeline([Command(['echo', 'hello'], [])], False))
+ self.assertEqual(self.parse('echo ""'),
+ Pipeline([Command(['echo', ''], [])], False))
+ self.assertEqual(self.parse("""echo -DFOO='a'"""),
+ Pipeline([Command(['echo', '-DFOO=a'], [])], False))
+ self.assertEqual(self.parse('echo -DFOO="a"'),
+ Pipeline([Command(['echo', '-DFOO=a'], [])], False))
+
+ def test_redirection(self):
+ self.assertEqual(self.parse('echo hello > c'),
+ Pipeline([Command(['echo', 'hello'],
+ [((('>'),), 'c')])], False))
+ self.assertEqual(self.parse('echo hello > c >> d'),
+ Pipeline([Command(['echo', 'hello'], [(('>',), 'c'),
+ (('>>',), 'd')])], False))
+ self.assertEqual(self.parse('a 2>&1'),
+ Pipeline([Command(['a'], [(('>&',2), '1')])], False))
+
+ def test_pipeline(self):
+ self.assertEqual(self.parse('a | b'),
+ Pipeline([Command(['a'], []),
+ Command(['b'], [])],
+ False))
+
+ self.assertEqual(self.parse('a | b | c'),
+ Pipeline([Command(['a'], []),
+ Command(['b'], []),
+ Command(['c'], [])],
+ False))
+
+ self.assertEqual(self.parse('! a'),
+ Pipeline([Command(['a'], [])],
+ True))
+
+ def test_list(self):
+ self.assertEqual(self.parse('a ; b'),
+ Seq(Pipeline([Command(['a'], [])], False),
+ ';',
+ Pipeline([Command(['b'], [])], False)))
+
+ self.assertEqual(self.parse('a & b'),
+ Seq(Pipeline([Command(['a'], [])], False),
+ '&',
+ Pipeline([Command(['b'], [])], False)))
+
+ self.assertEqual(self.parse('a && b'),
+ Seq(Pipeline([Command(['a'], [])], False),
+ '&&',
+ Pipeline([Command(['b'], [])], False)))
+
+ self.assertEqual(self.parse('a || b'),
+ Seq(Pipeline([Command(['a'], [])], False),
+ '||',
+ Pipeline([Command(['b'], [])], False)))
+
+ self.assertEqual(self.parse('a && b || c'),
+ Seq(Seq(Pipeline([Command(['a'], [])], False),
+ '&&',
+ Pipeline([Command(['b'], [])], False)),
+ '||',
+ Pipeline([Command(['c'], [])], False)))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/contrib/llvm/utils/lit/lit/TclUtil.py b/contrib/llvm/utils/lit/lit/TclUtil.py
new file mode 100644
index 0000000..4a3f345
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/TclUtil.py
@@ -0,0 +1,322 @@
+import itertools
+
+from ShCommands import Command, Pipeline
+
+def tcl_preprocess(data):
+ # Tcl has a preprocessing step to replace escaped newlines.
+ i = data.find('\\\n')
+ if i == -1:
+ return data
+
+ # Replace '\\\n' and subsequent whitespace by a single space.
+ n = len(data)
+ str = data[:i]
+ i += 2
+ while i < n and data[i] in ' \t':
+ i += 1
+ return str + ' ' + data[i:]
+
+class TclLexer:
+ """TclLexer - Lex a string into "words", following the Tcl syntax."""
+
+ def __init__(self, data):
+ self.data = tcl_preprocess(data)
+ self.pos = 0
+ self.end = len(self.data)
+
+ def at_end(self):
+ return self.pos == self.end
+
+ def eat(self):
+ c = self.data[self.pos]
+ self.pos += 1
+ return c
+
+ def look(self):
+ return self.data[self.pos]
+
+ def maybe_eat(self, c):
+ """
+ maybe_eat(c) - Consume the character c if it is the next character,
+ returning True if a character was consumed. """
+ if self.data[self.pos] == c:
+ self.pos += 1
+ return True
+ return False
+
+ def escape(self, c):
+ if c == 'a':
+ return '\x07'
+ elif c == 'b':
+ return '\x08'
+ elif c == 'f':
+ return '\x0c'
+ elif c == 'n':
+ return '\n'
+ elif c == 'r':
+ return '\r'
+ elif c == 't':
+ return '\t'
+ elif c == 'v':
+ return '\x0b'
+ elif c in 'uxo':
+ raise ValueError,'Invalid quoted character %r' % c
+ else:
+ return c
+
+ def lex_braced(self):
+ # Lex until whitespace or end of string, the opening brace has already
+ # been consumed.
+
+ str = ''
+ while 1:
+ if self.at_end():
+ raise ValueError,"Unterminated '{' quoted word"
+
+ c = self.eat()
+ if c == '}':
+ break
+ elif c == '{':
+ str += '{' + self.lex_braced() + '}'
+ elif c == '\\' and self.look() in '{}':
+ str += self.eat()
+ else:
+ str += c
+
+ return str
+
+ def lex_quoted(self):
+ str = ''
+
+ while 1:
+ if self.at_end():
+ raise ValueError,"Unterminated '\"' quoted word"
+
+ c = self.eat()
+ if c == '"':
+ break
+ elif c == '\\':
+ if self.at_end():
+ raise ValueError,'Missing quoted character'
+
+ str += self.escape(self.eat())
+ else:
+ str += c
+
+ return str
+
+ def lex_unquoted(self, process_all=False):
+ # Lex until whitespace or end of string.
+ str = ''
+ while not self.at_end():
+ if not process_all:
+ if self.look().isspace() or self.look() == ';':
+ break
+
+ c = self.eat()
+ if c == '\\':
+ if self.at_end():
+ raise ValueError,'Missing quoted character'
+
+ str += self.escape(self.eat())
+ elif c == '[':
+ raise NotImplementedError, ('Command substitution is '
+ 'not supported')
+ elif c == '$' and not self.at_end() and (self.look().isalpha() or
+ self.look() == '{'):
+ raise NotImplementedError, ('Variable substitution is '
+ 'not supported')
+ else:
+ str += c
+
+ return str
+
+ def lex_one_token(self):
+ if self.maybe_eat('"'):
+ return self.lex_quoted()
+ elif self.maybe_eat('{'):
+ # Check for argument substitution.
+ if not self.maybe_eat('*'):
+ return self.lex_braced()
+
+ if not self.maybe_eat('}'):
+ return '*' + self.lex_braced()
+
+ if self.at_end() or self.look().isspace():
+ return '*'
+
+ raise NotImplementedError, "Argument substitution is unsupported"
+ else:
+ return self.lex_unquoted()
+
+ def lex(self):
+ while not self.at_end():
+ c = self.look()
+ if c in ' \t':
+ self.eat()
+ elif c in ';\n':
+ self.eat()
+ yield (';',)
+ else:
+ yield self.lex_one_token()
+
+class TclExecCommand:
+ kRedirectPrefixes1 = ('<', '>')
+ kRedirectPrefixes2 = ('<@', '<<', '2>', '>&', '>>', '>@')
+ kRedirectPrefixes3 = ('2>@', '2>>', '>>&', '>&@')
+ kRedirectPrefixes4 = ('2>@1',)
+
+ def __init__(self, args):
+ self.args = iter(args)
+
+ def lex(self):
+ try:
+ return self.args.next()
+ except StopIteration:
+ return None
+
+ def look(self):
+ next = self.lex()
+ if next is not None:
+ self.args = itertools.chain([next], self.args)
+ return next
+
+ def parse_redirect(self, tok, length):
+ if len(tok) == length:
+ arg = self.lex()
+ if arg is None:
+ raise ValueError,'Missing argument to %r redirection' % tok
+ else:
+ tok,arg = tok[:length],tok[length:]
+
+ if tok[0] == '2':
+ op = (tok[1:],2)
+ else:
+ op = (tok,)
+ return (op, arg)
+
+ def parse_pipeline(self):
+ if self.look() is None:
+ raise ValueError,"Expected at least one argument to exec"
+
+ commands = [Command([],[])]
+ while 1:
+ arg = self.lex()
+ if arg is None:
+ break
+ elif arg == '|':
+ commands.append(Command([],[]))
+ elif arg == '|&':
+ # Write this as a redirect of stderr; it must come first because
+ # stdout may have already been redirected.
+ commands[-1].redirects.insert(0, (('>&',2),'1'))
+ commands.append(Command([],[]))
+ elif arg[:4] in TclExecCommand.kRedirectPrefixes4:
+ commands[-1].redirects.append(self.parse_redirect(arg, 4))
+ elif arg[:3] in TclExecCommand.kRedirectPrefixes3:
+ commands[-1].redirects.append(self.parse_redirect(arg, 3))
+ elif arg[:2] in TclExecCommand.kRedirectPrefixes2:
+ commands[-1].redirects.append(self.parse_redirect(arg, 2))
+ elif arg[:1] in TclExecCommand.kRedirectPrefixes1:
+ commands[-1].redirects.append(self.parse_redirect(arg, 1))
+ else:
+ commands[-1].args.append(arg)
+
+ return Pipeline(commands, False, pipe_err=True)
+
+ def parse(self):
+ ignoreStderr = False
+ keepNewline = False
+
+ # Parse arguments.
+ while 1:
+ next = self.look()
+ if not isinstance(next, str) or next[0] != '-':
+ break
+
+ if next == '--':
+ self.lex()
+ break
+ elif next == '-ignorestderr':
+ ignoreStderr = True
+ elif next == '-keepnewline':
+ keepNewline = True
+ else:
+ raise ValueError,"Invalid exec argument %r" % next
+
+ return (ignoreStderr, keepNewline, self.parse_pipeline())
+
+###
+
+import unittest
+
+class TestTclLexer(unittest.TestCase):
+ def lex(self, str, *args, **kwargs):
+ return list(TclLexer(str, *args, **kwargs).lex())
+
+ def test_preprocess(self):
+ self.assertEqual(tcl_preprocess('a b'), 'a b')
+ self.assertEqual(tcl_preprocess('a\\\nb c'), 'a b c')
+
+ def test_unquoted(self):
+ self.assertEqual(self.lex('a b c'),
+ ['a', 'b', 'c'])
+ self.assertEqual(self.lex(r'a\nb\tc\ '),
+ ['a\nb\tc '])
+ self.assertEqual(self.lex(r'a \\\$b c $\\'),
+ ['a', r'\$b', 'c', '$\\'])
+
+ def test_braced(self):
+ self.assertEqual(self.lex('a {b c} {}'),
+ ['a', 'b c', ''])
+ self.assertEqual(self.lex(r'a {b {c\n}}'),
+ ['a', 'b {c\\n}'])
+ self.assertEqual(self.lex(r'a {b\{}'),
+ ['a', 'b{'])
+ self.assertEqual(self.lex(r'{*}'), ['*'])
+ self.assertEqual(self.lex(r'{*} a'), ['*', 'a'])
+ self.assertEqual(self.lex(r'{*} a'), ['*', 'a'])
+ self.assertEqual(self.lex('{a\\\n b}'),
+ ['a b'])
+
+ def test_quoted(self):
+ self.assertEqual(self.lex('a "b c"'),
+ ['a', 'b c'])
+
+ def test_terminators(self):
+ self.assertEqual(self.lex('a\nb'),
+ ['a', (';',), 'b'])
+ self.assertEqual(self.lex('a;b'),
+ ['a', (';',), 'b'])
+ self.assertEqual(self.lex('a ; b'),
+ ['a', (';',), 'b'])
+
+class TestTclExecCommand(unittest.TestCase):
+ def parse(self, str):
+ return TclExecCommand(list(TclLexer(str).lex())).parse()
+
+ def test_basic(self):
+ self.assertEqual(self.parse('echo hello'),
+ (False, False,
+ Pipeline([Command(['echo', 'hello'], [])],
+ False, True)))
+ self.assertEqual(self.parse('echo hello | grep hello'),
+ (False, False,
+ Pipeline([Command(['echo', 'hello'], []),
+ Command(['grep', 'hello'], [])],
+ False, True)))
+
+ def test_redirect(self):
+ self.assertEqual(self.parse('echo hello > a >b >>c 2> d |& e'),
+ (False, False,
+ Pipeline([Command(['echo', 'hello'],
+ [(('>&',2),'1'),
+ (('>',),'a'),
+ (('>',),'b'),
+ (('>>',),'c'),
+ (('>',2),'d')]),
+ Command(['e'], [])],
+ False, True)))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/contrib/llvm/utils/lit/lit/Test.py b/contrib/llvm/utils/lit/lit/Test.py
new file mode 100644
index 0000000..db2e032
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/Test.py
@@ -0,0 +1,79 @@
+import os
+
+# Test results.
+
+class TestResult:
+ def __init__(self, name, isFailure):
+ self.name = name
+ self.isFailure = isFailure
+
+PASS = TestResult('PASS', False)
+XFAIL = TestResult('XFAIL', False)
+FAIL = TestResult('FAIL', True)
+XPASS = TestResult('XPASS', True)
+UNRESOLVED = TestResult('UNRESOLVED', True)
+UNSUPPORTED = TestResult('UNSUPPORTED', False)
+
+# Test classes.
+
+class TestFormat:
+ """TestFormat - Test information provider."""
+
+ def __init__(self, name):
+ self.name = name
+
+class TestSuite:
+ """TestSuite - Information on a group of tests.
+
+ A test suite groups together a set of logically related tests.
+ """
+
+ def __init__(self, name, source_root, exec_root, config):
+ self.name = name
+ self.source_root = source_root
+ self.exec_root = exec_root
+ # The test suite configuration.
+ self.config = config
+
+ def getSourcePath(self, components):
+ return os.path.join(self.source_root, *components)
+
+ def getExecPath(self, components):
+ return os.path.join(self.exec_root, *components)
+
+class Test:
+ """Test - Information on a single test instance."""
+
+ def __init__(self, suite, path_in_suite, config):
+ self.suite = suite
+ self.path_in_suite = path_in_suite
+ self.config = config
+ # The test result code, once complete.
+ self.result = None
+ # Any additional output from the test, once complete.
+ self.output = None
+ # The wall time to execute this test, if timing and once complete.
+ self.elapsed = None
+ # The repeat index of this test, or None.
+ self.index = None
+
+ def copyWithIndex(self, index):
+ import copy
+ res = copy.copy(self)
+ res.index = index
+ return res
+
+ def setResult(self, result, output, elapsed):
+ assert self.result is None, "Test result already set!"
+ self.result = result
+ self.output = output
+ self.elapsed = elapsed
+
+ def getFullName(self):
+ return self.suite.config.name + ' :: ' + '/'.join(self.path_in_suite)
+
+ def getSourcePath(self):
+ return self.suite.getSourcePath(self.path_in_suite)
+
+ def getExecPath(self):
+ return self.suite.getExecPath(self.path_in_suite)
diff --git a/contrib/llvm/utils/lit/lit/TestFormats.py b/contrib/llvm/utils/lit/lit/TestFormats.py
new file mode 100644
index 0000000..7ffbd2b
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/TestFormats.py
@@ -0,0 +1,221 @@
+import os
+import platform
+
+import Test
+import TestRunner
+import Util
+
+kIsWindows = platform.system() == 'Windows'
+
+class GoogleTest(object):
+ def __init__(self, test_sub_dir, test_suffix):
+ self.test_sub_dir = str(test_sub_dir)
+ self.test_suffix = str(test_suffix)
+
+ # On Windows, assume tests will also end in '.exe'.
+ if kIsWindows:
+ self.test_suffix += '.exe'
+
+ def getGTestTests(self, path, litConfig, localConfig):
+ """getGTestTests(path) - [name]
+
+ Return the tests available in gtest executable.
+
+ Args:
+ path: String path to a gtest executable
+ litConfig: LitConfig instance
+ localConfig: TestingConfig instance"""
+
+ try:
+ lines = Util.capture([path, '--gtest_list_tests'],
+ env=localConfig.environment).split('\n')
+ except:
+ litConfig.error("unable to discover google-tests in %r" % path)
+ raise StopIteration
+
+ nested_tests = []
+ for ln in lines:
+ if not ln.strip():
+ continue
+
+ prefix = ''
+ index = 0
+ while ln[index*2:index*2+2] == ' ':
+ index += 1
+ while len(nested_tests) > index:
+ nested_tests.pop()
+
+ ln = ln[index*2:]
+ if ln.endswith('.'):
+ nested_tests.append(ln)
+ else:
+ yield ''.join(nested_tests) + ln
+
+ def getTestsInDirectory(self, testSuite, path_in_suite,
+ litConfig, localConfig):
+ source_path = testSuite.getSourcePath(path_in_suite)
+ for filename in os.listdir(source_path):
+ # Check for the one subdirectory (build directory) tests will be in.
+ if filename != self.test_sub_dir:
+ continue
+
+ filepath = os.path.join(source_path, filename)
+ for subfilename in os.listdir(filepath):
+ if subfilename.endswith(self.test_suffix):
+ execpath = os.path.join(filepath, subfilename)
+
+ # Discover the tests in this executable.
+ for name in self.getGTestTests(execpath, litConfig,
+ localConfig):
+ testPath = path_in_suite + (filename, subfilename, name)
+ yield Test.Test(testSuite, testPath, localConfig)
+
+ def execute(self, test, litConfig):
+ testPath,testName = os.path.split(test.getSourcePath())
+ while not os.path.exists(testPath):
+ # Handle GTest parametrized and typed tests, whose name includes
+ # some '/'s.
+ testPath, namePrefix = os.path.split(testPath)
+ testName = os.path.join(namePrefix, testName)
+
+ cmd = [testPath, '--gtest_filter=' + testName]
+ if litConfig.useValgrind:
+ cmd = litConfig.valgrindArgs + cmd
+
+ out, err, exitCode = TestRunner.executeCommand(
+ cmd, env=test.config.environment)
+
+ if not exitCode:
+ return Test.PASS,''
+
+ return Test.FAIL, out + err
+
+###
+
+class FileBasedTest(object):
+ def getTestsInDirectory(self, testSuite, path_in_suite,
+ litConfig, localConfig):
+ source_path = testSuite.getSourcePath(path_in_suite)
+ for filename in os.listdir(source_path):
+ # Ignore dot files and excluded tests.
+ if (filename.startswith('.') or
+ filename in localConfig.excludes):
+ continue
+
+ filepath = os.path.join(source_path, filename)
+ if not os.path.isdir(filepath):
+ base,ext = os.path.splitext(filename)
+ if ext in localConfig.suffixes:
+ yield Test.Test(testSuite, path_in_suite + (filename,),
+ localConfig)
+
+class ShTest(FileBasedTest):
+ def __init__(self, execute_external = False):
+ self.execute_external = execute_external
+
+ def execute(self, test, litConfig):
+ return TestRunner.executeShTest(test, litConfig,
+ self.execute_external)
+
+class TclTest(FileBasedTest):
+ def execute(self, test, litConfig):
+ return TestRunner.executeTclTest(test, litConfig)
+
+###
+
+import re
+import tempfile
+
+class OneCommandPerFileTest:
+ # FIXME: Refactor into generic test for running some command on a directory
+ # of inputs.
+
+ def __init__(self, command, dir, recursive=False,
+ pattern=".*", useTempInput=False):
+ if isinstance(command, str):
+ self.command = [command]
+ else:
+ self.command = list(command)
+ if dir is not None:
+ dir = str(dir)
+ self.dir = dir
+ self.recursive = bool(recursive)
+ self.pattern = re.compile(pattern)
+ self.useTempInput = useTempInput
+
+ def getTestsInDirectory(self, testSuite, path_in_suite,
+ litConfig, localConfig):
+ dir = self.dir
+ if dir is None:
+ dir = testSuite.getSourcePath(path_in_suite)
+
+ for dirname,subdirs,filenames in os.walk(dir):
+ if not self.recursive:
+ subdirs[:] = []
+
+ subdirs[:] = [d for d in subdirs
+ if (d != '.svn' and
+ d not in localConfig.excludes)]
+
+ for filename in filenames:
+ if (filename.startswith('.') or
+ not self.pattern.match(filename) or
+ filename in localConfig.excludes):
+ continue
+
+ path = os.path.join(dirname,filename)
+ suffix = path[len(dir):]
+ if suffix.startswith(os.sep):
+ suffix = suffix[1:]
+ test = Test.Test(testSuite,
+ path_in_suite + tuple(suffix.split(os.sep)),
+ localConfig)
+ # FIXME: Hack?
+ test.source_path = path
+ yield test
+
+ def createTempInput(self, tmp, test):
+ abstract
+
+ def execute(self, test, litConfig):
+ if test.config.unsupported:
+ return (Test.UNSUPPORTED, 'Test is unsupported')
+
+ cmd = list(self.command)
+
+ # If using temp input, create a temporary file and hand it to the
+ # subclass.
+ if self.useTempInput:
+ tmp = tempfile.NamedTemporaryFile(suffix='.cpp')
+ self.createTempInput(tmp, test)
+ tmp.flush()
+ cmd.append(tmp.name)
+ elif hasattr(test, 'source_path'):
+ cmd.append(test.source_path)
+ else:
+ cmd.append(test.getSourcePath())
+
+ out, err, exitCode = TestRunner.executeCommand(cmd)
+
+ diags = out + err
+ if not exitCode and not diags.strip():
+ return Test.PASS,''
+
+ # Try to include some useful information.
+ report = """Command: %s\n""" % ' '.join(["'%s'" % a
+ for a in cmd])
+ if self.useTempInput:
+ report += """Temporary File: %s\n""" % tmp.name
+ report += "--\n%s--\n""" % open(tmp.name).read()
+ report += """Output:\n--\n%s--""" % diags
+
+ return Test.FAIL, report
+
+class SyntaxCheckTest(OneCommandPerFileTest):
+ def __init__(self, compiler, dir, extra_cxx_args=[], *args, **kwargs):
+ cmd = [compiler, '-x', 'c++', '-fsyntax-only'] + extra_cxx_args
+ OneCommandPerFileTest.__init__(self, cmd, dir,
+ useTempInput=1, *args, **kwargs)
+
+ def createTempInput(self, tmp, test):
+ print >>tmp, '#include "%s"' % test.source_path
diff --git a/contrib/llvm/utils/lit/lit/TestRunner.py b/contrib/llvm/utils/lit/lit/TestRunner.py
new file mode 100644
index 0000000..0eb51a8
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/TestRunner.py
@@ -0,0 +1,586 @@
+import os, signal, subprocess, sys
+import StringIO
+
+import ShUtil
+import Test
+import Util
+
+import platform
+import tempfile
+
+class InternalShellError(Exception):
+ def __init__(self, command, message):
+ self.command = command
+ self.message = message
+
+kIsWindows = platform.system() == 'Windows'
+
+# Don't use close_fds on Windows.
+kUseCloseFDs = not kIsWindows
+
+# Use temporary files to replace /dev/null on Windows.
+kAvoidDevNull = kIsWindows
+
+def executeCommand(command, cwd=None, env=None):
+ p = subprocess.Popen(command, cwd=cwd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ env=env)
+ out,err = p.communicate()
+ exitCode = p.wait()
+
+ # Detect Ctrl-C in subprocess.
+ if exitCode == -signal.SIGINT:
+ raise KeyboardInterrupt
+
+ return out, err, exitCode
+
+def executeShCmd(cmd, cfg, cwd, results):
+ if isinstance(cmd, ShUtil.Seq):
+ if cmd.op == ';':
+ res = executeShCmd(cmd.lhs, cfg, cwd, results)
+ return executeShCmd(cmd.rhs, cfg, cwd, results)
+
+ if cmd.op == '&':
+ raise NotImplementedError,"unsupported test command: '&'"
+
+ if cmd.op == '||':
+ res = executeShCmd(cmd.lhs, cfg, cwd, results)
+ if res != 0:
+ res = executeShCmd(cmd.rhs, cfg, cwd, results)
+ return res
+ if cmd.op == '&&':
+ res = executeShCmd(cmd.lhs, cfg, cwd, results)
+ if res is None:
+ return res
+
+ if res == 0:
+ res = executeShCmd(cmd.rhs, cfg, cwd, results)
+ return res
+
+ raise ValueError,'Unknown shell command: %r' % cmd.op
+
+ assert isinstance(cmd, ShUtil.Pipeline)
+ procs = []
+ input = subprocess.PIPE
+ stderrTempFiles = []
+ opened_files = []
+ named_temp_files = []
+ # To avoid deadlock, we use a single stderr stream for piped
+ # output. This is null until we have seen some output using
+ # stderr.
+ for i,j in enumerate(cmd.commands):
+ # Apply the redirections, we use (N,) as a sentinal to indicate stdin,
+ # stdout, stderr for N equal to 0, 1, or 2 respectively. Redirects to or
+ # from a file are represented with a list [file, mode, file-object]
+ # where file-object is initially None.
+ redirects = [(0,), (1,), (2,)]
+ for r in j.redirects:
+ if r[0] == ('>',2):
+ redirects[2] = [r[1], 'w', None]
+ elif r[0] == ('>>',2):
+ redirects[2] = [r[1], 'a', None]
+ elif r[0] == ('>&',2) and r[1] in '012':
+ redirects[2] = redirects[int(r[1])]
+ elif r[0] == ('>&',) or r[0] == ('&>',):
+ redirects[1] = redirects[2] = [r[1], 'w', None]
+ elif r[0] == ('>',):
+ redirects[1] = [r[1], 'w', None]
+ elif r[0] == ('>>',):
+ redirects[1] = [r[1], 'a', None]
+ elif r[0] == ('<',):
+ redirects[0] = [r[1], 'r', None]
+ else:
+ raise NotImplementedError,"Unsupported redirect: %r" % (r,)
+
+ # Map from the final redirections to something subprocess can handle.
+ final_redirects = []
+ for index,r in enumerate(redirects):
+ if r == (0,):
+ result = input
+ elif r == (1,):
+ if index == 0:
+ raise NotImplementedError,"Unsupported redirect for stdin"
+ elif index == 1:
+ result = subprocess.PIPE
+ else:
+ result = subprocess.STDOUT
+ elif r == (2,):
+ if index != 2:
+ raise NotImplementedError,"Unsupported redirect on stdout"
+ result = subprocess.PIPE
+ else:
+ if r[2] is None:
+ if kAvoidDevNull and r[0] == '/dev/null':
+ r[2] = tempfile.TemporaryFile(mode=r[1])
+ else:
+ r[2] = open(r[0], r[1])
+ # Workaround a Win32 and/or subprocess bug when appending.
+ #
+ # FIXME: Actually, this is probably an instance of PR6753.
+ if r[1] == 'a':
+ r[2].seek(0, 2)
+ opened_files.append(r[2])
+ result = r[2]
+ final_redirects.append(result)
+
+ stdin, stdout, stderr = final_redirects
+
+ # If stderr wants to come from stdout, but stdout isn't a pipe, then put
+ # stderr on a pipe and treat it as stdout.
+ if (stderr == subprocess.STDOUT and stdout != subprocess.PIPE):
+ stderr = subprocess.PIPE
+ stderrIsStdout = True
+ else:
+ stderrIsStdout = False
+
+ # Don't allow stderr on a PIPE except for the last
+ # process, this could deadlock.
+ #
+ # FIXME: This is slow, but so is deadlock.
+ if stderr == subprocess.PIPE and j != cmd.commands[-1]:
+ stderr = tempfile.TemporaryFile(mode='w+b')
+ stderrTempFiles.append((i, stderr))
+
+ # Resolve the executable path ourselves.
+ args = list(j.args)
+ args[0] = Util.which(args[0], cfg.environment['PATH'])
+ if not args[0]:
+ raise InternalShellError(j, '%r: command not found' % j.args[0])
+
+ # Replace uses of /dev/null with temporary files.
+ if kAvoidDevNull:
+ for i,arg in enumerate(args):
+ if arg == "/dev/null":
+ f = tempfile.NamedTemporaryFile(delete=False)
+ f.close()
+ named_temp_files.append(f.name)
+ args[i] = f.name
+
+ procs.append(subprocess.Popen(args, cwd=cwd,
+ stdin = stdin,
+ stdout = stdout,
+ stderr = stderr,
+ env = cfg.environment,
+ close_fds = kUseCloseFDs))
+
+ # Immediately close stdin for any process taking stdin from us.
+ if stdin == subprocess.PIPE:
+ procs[-1].stdin.close()
+ procs[-1].stdin = None
+
+ # Update the current stdin source.
+ if stdout == subprocess.PIPE:
+ input = procs[-1].stdout
+ elif stderrIsStdout:
+ input = procs[-1].stderr
+ else:
+ input = subprocess.PIPE
+
+ # FIXME: There is probably still deadlock potential here. Yawn.
+ procData = [None] * len(procs)
+ procData[-1] = procs[-1].communicate()
+
+ for i in range(len(procs) - 1):
+ if procs[i].stdout is not None:
+ out = procs[i].stdout.read()
+ else:
+ out = ''
+ if procs[i].stderr is not None:
+ err = procs[i].stderr.read()
+ else:
+ err = ''
+ procData[i] = (out,err)
+
+ # Read stderr out of the temp files.
+ for i,f in stderrTempFiles:
+ f.seek(0, 0)
+ procData[i] = (procData[i][0], f.read())
+
+ exitCode = None
+ for i,(out,err) in enumerate(procData):
+ res = procs[i].wait()
+ # Detect Ctrl-C in subprocess.
+ if res == -signal.SIGINT:
+ raise KeyboardInterrupt
+
+ results.append((cmd.commands[i], out, err, res))
+ if cmd.pipe_err:
+ # Python treats the exit code as a signed char.
+ if res < 0:
+ exitCode = min(exitCode, res)
+ else:
+ exitCode = max(exitCode, res)
+ else:
+ exitCode = res
+
+ # Explicitly close any redirected files.
+ for f in opened_files:
+ f.close()
+
+ # Remove any named temporary files we created.
+ for f in named_temp_files:
+ try:
+ os.remove(f)
+ except OSError:
+ pass
+
+ if cmd.negate:
+ exitCode = not exitCode
+
+ return exitCode
+
+def executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
+ ln = ' &&\n'.join(commands)
+ try:
+ cmd = ShUtil.ShParser(ln, litConfig.isWindows).parse()
+ except:
+ return (Test.FAIL, "shell parser error on: %r" % ln)
+
+ results = []
+ try:
+ exitCode = executeShCmd(cmd, test.config, cwd, results)
+ except InternalShellError,e:
+ out = ''
+ err = e.message
+ exitCode = 255
+
+ out = err = ''
+ for i,(cmd, cmd_out,cmd_err,res) in enumerate(results):
+ out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args))
+ out += 'Command %d Result: %r\n' % (i, res)
+ out += 'Command %d Output:\n%s\n\n' % (i, cmd_out)
+ out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err)
+
+ return out, err, exitCode
+
+def executeTclScriptInternal(test, litConfig, tmpBase, commands, cwd):
+ import TclUtil
+ cmds = []
+ for ln in commands:
+ # Given the unfortunate way LLVM's test are written, the line gets
+ # backslash substitution done twice.
+ ln = TclUtil.TclLexer(ln).lex_unquoted(process_all = True)
+
+ try:
+ tokens = list(TclUtil.TclLexer(ln).lex())
+ except:
+ return (Test.FAIL, "Tcl lexer error on: %r" % ln)
+
+ # Validate there are no control tokens.
+ for t in tokens:
+ if not isinstance(t, str):
+ return (Test.FAIL,
+ "Invalid test line: %r containing %r" % (ln, t))
+
+ try:
+ cmds.append(TclUtil.TclExecCommand(tokens).parse_pipeline())
+ except:
+ return (Test.FAIL, "Tcl 'exec' parse error on: %r" % ln)
+
+ if litConfig.useValgrind:
+ for pipeline in cmds:
+ if pipeline.commands:
+ # Only valgrind the first command in each pipeline, to avoid
+ # valgrinding things like grep, not, and FileCheck.
+ cmd = pipeline.commands[0]
+ cmd.args = litConfig.valgrindArgs + cmd.args
+
+ cmd = cmds[0]
+ for c in cmds[1:]:
+ cmd = ShUtil.Seq(cmd, '&&', c)
+
+ # FIXME: This is lame, we shouldn't need bash. See PR5240.
+ bashPath = litConfig.getBashPath()
+ if litConfig.useTclAsSh and bashPath:
+ script = tmpBase + '.script'
+
+ # Write script file
+ f = open(script,'w')
+ print >>f, 'set -o pipefail'
+ cmd.toShell(f, pipefail = True)
+ f.close()
+
+ if 0:
+ print >>sys.stdout, cmd
+ print >>sys.stdout, open(script).read()
+ print >>sys.stdout
+ return '', '', 0
+
+ command = [litConfig.getBashPath(), script]
+ out,err,exitCode = executeCommand(command, cwd=cwd,
+ env=test.config.environment)
+
+ return out,err,exitCode
+ else:
+ results = []
+ try:
+ exitCode = executeShCmd(cmd, test.config, cwd, results)
+ except InternalShellError,e:
+ results.append((e.command, '', e.message + '\n', 255))
+ exitCode = 255
+
+ out = err = ''
+
+ for i,(cmd, cmd_out, cmd_err, res) in enumerate(results):
+ out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args))
+ out += 'Command %d Result: %r\n' % (i, res)
+ out += 'Command %d Output:\n%s\n\n' % (i, cmd_out)
+ out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err)
+
+ return out, err, exitCode
+
+def executeScript(test, litConfig, tmpBase, commands, cwd):
+ script = tmpBase + '.script'
+ if litConfig.isWindows:
+ script += '.bat'
+
+ # Write script file
+ f = open(script,'w')
+ if litConfig.isWindows:
+ f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands))
+ else:
+ f.write(' &&\n'.join(commands))
+ f.write('\n')
+ f.close()
+
+ if litConfig.isWindows:
+ command = ['cmd','/c', script]
+ else:
+ command = ['/bin/sh', script]
+ if litConfig.useValgrind:
+ # FIXME: Running valgrind on sh is overkill. We probably could just
+ # run on clang with no real loss.
+ command = litConfig.valgrindArgs + command
+
+ return executeCommand(command, cwd=cwd, env=test.config.environment)
+
+def isExpectedFail(xfails, xtargets, target_triple):
+ # Check if any xfail matches this target.
+ for item in xfails:
+ if item == '*' or item in target_triple:
+ break
+ else:
+ return False
+
+ # If so, see if it is expected to pass on this target.
+ #
+ # FIXME: Rename XTARGET to something that makes sense, like XPASS.
+ for item in xtargets:
+ if item == '*' or item in target_triple:
+ return False
+
+ return True
+
+def parseIntegratedTestScript(test, normalize_slashes=False):
+ """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test
+ script and extract the lines to 'RUN' as well as 'XFAIL' and 'XTARGET'
+ information. The RUN lines also will have variable substitution performed.
+ """
+
+ # Get the temporary location, this is always relative to the test suite
+ # root, not test source root.
+ #
+ # FIXME: This should not be here?
+ sourcepath = test.getSourcePath()
+ sourcedir = os.path.dirname(sourcepath)
+ execpath = test.getExecPath()
+ execdir,execbase = os.path.split(execpath)
+ tmpBase = os.path.join(execdir, 'Output', execbase)
+ if test.index is not None:
+ tmpBase += '_%d' % test.index
+
+ # Normalize slashes, if requested.
+ if normalize_slashes:
+ sourcepath = sourcepath.replace('\\', '/')
+ sourcedir = sourcedir.replace('\\', '/')
+ tmpBase = tmpBase.replace('\\', '/')
+
+ # We use #_MARKER_# to hide %% while we do the other substitutions.
+ substitutions = [('%%', '#_MARKER_#')]
+ substitutions.extend(test.config.substitutions)
+ substitutions.extend([('%s', sourcepath),
+ ('%S', sourcedir),
+ ('%p', sourcedir),
+ ('%t', tmpBase + '.tmp'),
+ # FIXME: Remove this once we kill DejaGNU.
+ ('%abs_tmp', tmpBase + '.tmp'),
+ ('#_MARKER_#', '%')])
+
+ # Collect the test lines from the script.
+ script = []
+ xfails = []
+ xtargets = []
+ requires = []
+ for ln in open(sourcepath):
+ if 'RUN:' in ln:
+ # Isolate the command to run.
+ index = ln.index('RUN:')
+ ln = ln[index+4:]
+
+ # Trim trailing whitespace.
+ ln = ln.rstrip()
+
+ # Collapse lines with trailing '\\'.
+ if script and script[-1][-1] == '\\':
+ script[-1] = script[-1][:-1] + ln
+ else:
+ script.append(ln)
+ elif 'XFAIL:' in ln:
+ items = ln[ln.index('XFAIL:') + 6:].split(',')
+ xfails.extend([s.strip() for s in items])
+ elif 'XTARGET:' in ln:
+ items = ln[ln.index('XTARGET:') + 8:].split(',')
+ xtargets.extend([s.strip() for s in items])
+ elif 'REQUIRES:' in ln:
+ items = ln[ln.index('REQUIRES:') + 9:].split(',')
+ requires.extend([s.strip() for s in items])
+ elif 'END.' in ln:
+ # Check for END. lines.
+ if ln[ln.index('END.'):].strip() == 'END.':
+ break
+
+ # Apply substitutions to the script.
+ def processLine(ln):
+ # Apply substitutions
+ for a,b in substitutions:
+ ln = ln.replace(a,b)
+
+ # Strip the trailing newline and any extra whitespace.
+ return ln.strip()
+ script = map(processLine, script)
+
+ # Verify the script contains a run line.
+ if not script:
+ return (Test.UNRESOLVED, "Test has no run line!")
+
+ # Check for unterminated run lines.
+ if script[-1][-1] == '\\':
+ return (Test.UNRESOLVED, "Test has unterminated run lines (with '\\')")
+
+ # Check that we have the required features:
+ missing_required_features = [f for f in requires
+ if f not in test.config.available_features]
+ if missing_required_features:
+ msg = ', '.join(missing_required_features)
+ return (Test.UNSUPPORTED,
+ "Test requires the following features: %s" % msg)
+
+ isXFail = isExpectedFail(xfails, xtargets, test.suite.config.target_triple)
+ return script,isXFail,tmpBase,execdir
+
+def formatTestOutput(status, out, err, exitCode, failDueToStderr, script):
+ output = StringIO.StringIO()
+ print >>output, "Script:"
+ print >>output, "--"
+ print >>output, '\n'.join(script)
+ print >>output, "--"
+ print >>output, "Exit Code: %r" % exitCode,
+ if failDueToStderr:
+ print >>output, "(but there was output on stderr)"
+ else:
+ print >>output
+ if out:
+ print >>output, "Command Output (stdout):"
+ print >>output, "--"
+ output.write(out)
+ print >>output, "--"
+ if err:
+ print >>output, "Command Output (stderr):"
+ print >>output, "--"
+ output.write(err)
+ print >>output, "--"
+ return (status, output.getvalue())
+
+def executeTclTest(test, litConfig):
+ if test.config.unsupported:
+ return (Test.UNSUPPORTED, 'Test is unsupported')
+
+ # Parse the test script, normalizing slashes in substitutions on Windows
+ # (since otherwise Tcl style lexing will treat them as escapes).
+ res = parseIntegratedTestScript(test, normalize_slashes=kIsWindows)
+ if len(res) == 2:
+ return res
+
+ script, isXFail, tmpBase, execdir = res
+
+ if litConfig.noExecute:
+ return (Test.PASS, '')
+
+ # Create the output directory if it does not already exist.
+ Util.mkdir_p(os.path.dirname(tmpBase))
+
+ res = executeTclScriptInternal(test, litConfig, tmpBase, script, execdir)
+ if len(res) == 2:
+ return res
+
+ # Test for failure. In addition to the exit code, Tcl commands are
+ # considered to fail if there is any standard error output.
+ out,err,exitCode = res
+ if isXFail:
+ ok = exitCode != 0 or err
+ if ok:
+ status = Test.XFAIL
+ else:
+ status = Test.XPASS
+ else:
+ ok = exitCode == 0 and not err
+ if ok:
+ status = Test.PASS
+ else:
+ status = Test.FAIL
+
+ if ok:
+ return (status,'')
+
+ # Set a flag for formatTestOutput so it can explain why the test was
+ # considered to have failed, despite having an exit code of 0.
+ failDueToStderr = exitCode == 0 and err
+
+ return formatTestOutput(status, out, err, exitCode, failDueToStderr, script)
+
+def executeShTest(test, litConfig, useExternalSh):
+ if test.config.unsupported:
+ return (Test.UNSUPPORTED, 'Test is unsupported')
+
+ res = parseIntegratedTestScript(test)
+ if len(res) == 2:
+ return res
+
+ script, isXFail, tmpBase, execdir = res
+
+ if litConfig.noExecute:
+ return (Test.PASS, '')
+
+ # Create the output directory if it does not already exist.
+ Util.mkdir_p(os.path.dirname(tmpBase))
+
+ if useExternalSh:
+ res = executeScript(test, litConfig, tmpBase, script, execdir)
+ else:
+ res = executeScriptInternal(test, litConfig, tmpBase, script, execdir)
+ if len(res) == 2:
+ return res
+
+ out,err,exitCode = res
+ if isXFail:
+ ok = exitCode != 0
+ if ok:
+ status = Test.XFAIL
+ else:
+ status = Test.XPASS
+ else:
+ ok = exitCode == 0
+ if ok:
+ status = Test.PASS
+ else:
+ status = Test.FAIL
+
+ if ok:
+ return (status,'')
+
+ # Sh tests are not considered to fail just from stderr output.
+ failDueToStderr = False
+
+ return formatTestOutput(status, out, err, exitCode, failDueToStderr, script)
diff --git a/contrib/llvm/utils/lit/lit/TestingConfig.py b/contrib/llvm/utils/lit/lit/TestingConfig.py
new file mode 100644
index 0000000..5c1b273
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/TestingConfig.py
@@ -0,0 +1,101 @@
+import os
+
+class TestingConfig:
+ """"
+ TestingConfig - Information on the tests inside a suite.
+ """
+
+ @staticmethod
+ def frompath(path, parent, litConfig, mustExist, config = None):
+ if config is None:
+ # Set the environment based on the command line arguments.
+ environment = {
+ 'LD_LIBRARY_PATH' : os.environ.get('LD_LIBRARY_PATH',''),
+ 'PATH' : os.pathsep.join(litConfig.path +
+ [os.environ.get('PATH','')]),
+ 'PATHEXT' : os.environ.get('PATHEXT',''),
+ 'SYSTEMROOT' : os.environ.get('SYSTEMROOT',''),
+ 'LLVM_DISABLE_CRT_DEBUG' : '1',
+ }
+
+ config = TestingConfig(parent,
+ name = '<unnamed>',
+ suffixes = set(),
+ test_format = None,
+ environment = environment,
+ substitutions = [],
+ unsupported = False,
+ on_clone = None,
+ test_exec_root = None,
+ test_source_root = None,
+ excludes = [],
+ available_features = [])
+
+ if os.path.exists(path):
+ # FIXME: Improve detection and error reporting of errors in the
+ # config file.
+ f = open(path)
+ cfg_globals = dict(globals())
+ cfg_globals['config'] = config
+ cfg_globals['lit'] = litConfig
+ cfg_globals['__file__'] = path
+ try:
+ exec f in cfg_globals
+ except SystemExit,status:
+ # We allow normal system exit inside a config file to just
+ # return control without error.
+ if status.args:
+ raise
+ f.close()
+ elif mustExist:
+ litConfig.fatal('unable to load config from %r ' % path)
+
+ config.finish(litConfig)
+ return config
+
+ def __init__(self, parent, name, suffixes, test_format,
+ environment, substitutions, unsupported, on_clone,
+ test_exec_root, test_source_root, excludes,
+ available_features):
+ self.parent = parent
+ self.name = str(name)
+ self.suffixes = set(suffixes)
+ self.test_format = test_format
+ self.environment = dict(environment)
+ self.substitutions = list(substitutions)
+ self.unsupported = unsupported
+ self.on_clone = on_clone
+ self.test_exec_root = test_exec_root
+ self.test_source_root = test_source_root
+ self.excludes = set(excludes)
+ self.available_features = set(available_features)
+
+ def clone(self, path):
+ # FIXME: Chain implementations?
+ #
+ # FIXME: Allow extra parameters?
+ cfg = TestingConfig(self, self.name, self.suffixes, self.test_format,
+ self.environment, self.substitutions,
+ self.unsupported, self.on_clone,
+ self.test_exec_root, self.test_source_root,
+ self.excludes, self.available_features)
+ if cfg.on_clone:
+ cfg.on_clone(self, cfg, path)
+ return cfg
+
+ def finish(self, litConfig):
+ """finish() - Finish this config object, after loading is complete."""
+
+ self.name = str(self.name)
+ self.suffixes = set(self.suffixes)
+ self.environment = dict(self.environment)
+ self.substitutions = list(self.substitutions)
+ if self.test_exec_root is not None:
+ # FIXME: This should really only be suite in test suite config
+ # files. Should we distinguish them?
+ self.test_exec_root = str(self.test_exec_root)
+ if self.test_source_root is not None:
+ # FIXME: This should really only be suite in test suite config
+ # files. Should we distinguish them?
+ self.test_source_root = str(self.test_source_root)
+ self.excludes = set(self.excludes)
diff --git a/contrib/llvm/utils/lit/lit/Util.py b/contrib/llvm/utils/lit/lit/Util.py
new file mode 100644
index 0000000..414b714
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/Util.py
@@ -0,0 +1,125 @@
+import os, sys
+
+def detectCPUs():
+ """
+ Detects the number of CPUs on a system. Cribbed from pp.
+ """
+ # Linux, Unix and MacOS:
+ if hasattr(os, "sysconf"):
+ if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"):
+ # Linux & Unix:
+ ncpus = os.sysconf("SC_NPROCESSORS_ONLN")
+ if isinstance(ncpus, int) and ncpus > 0:
+ return ncpus
+ else: # OSX:
+ return int(os.popen2("sysctl -n hw.ncpu")[1].read())
+ # Windows:
+ if os.environ.has_key("NUMBER_OF_PROCESSORS"):
+ ncpus = int(os.environ["NUMBER_OF_PROCESSORS"])
+ if ncpus > 0:
+ return ncpus
+ return 1 # Default
+
+def mkdir_p(path):
+ """mkdir_p(path) - Make the "path" directory, if it does not exist; this
+ will also make directories for any missing parent directories."""
+ import errno
+
+ if not path or os.path.exists(path):
+ return
+
+ parent = os.path.dirname(path)
+ if parent != path:
+ mkdir_p(parent)
+
+ try:
+ os.mkdir(path)
+ except OSError,e:
+ # Ignore EEXIST, which may occur during a race condition.
+ if e.errno != errno.EEXIST:
+ raise
+
+def capture(args, env=None):
+ import subprocess
+ """capture(command) - Run the given command (or argv list) in a shell and
+ return the standard output."""
+ p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ env=env)
+ out,_ = p.communicate()
+ return out
+
+def which(command, paths = None):
+ """which(command, [paths]) - Look up the given command in the paths string
+ (or the PATH environment variable, if unspecified)."""
+
+ if paths is None:
+ paths = os.environ.get('PATH','')
+
+ # Check for absolute match first.
+ if os.path.exists(command):
+ return command
+
+ # Would be nice if Python had a lib function for this.
+ if not paths:
+ paths = os.defpath
+
+ # Get suffixes to search.
+ pathext = os.environ.get('PATHEXT', '').split(os.pathsep)
+
+ # Search the paths...
+ for path in paths.split(os.pathsep):
+ for ext in pathext:
+ p = os.path.join(path, command + ext)
+ if os.path.exists(p):
+ return p
+
+ return None
+
+def printHistogram(items, title = 'Items'):
+ import itertools, math
+
+ items.sort(key = lambda (_,v): v)
+
+ maxValue = max([v for _,v in items])
+
+ # Select first "nice" bar height that produces more than 10 bars.
+ power = int(math.ceil(math.log(maxValue, 10)))
+ for inc in itertools.cycle((5, 2, 2.5, 1)):
+ barH = inc * 10**power
+ N = int(math.ceil(maxValue / barH))
+ if N > 10:
+ break
+ elif inc == 1:
+ power -= 1
+
+ histo = [set() for i in range(N)]
+ for name,v in items:
+ bin = min(int(N * v/maxValue), N-1)
+ histo[bin].add(name)
+
+ barW = 40
+ hr = '-' * (barW + 34)
+ print '\nSlowest %s:' % title
+ print hr
+ for name,value in items[-20:]:
+ print '%.2fs: %s' % (value, name)
+ print '\n%s Times:' % title
+ print hr
+ pDigits = int(math.ceil(math.log(maxValue, 10)))
+ pfDigits = max(0, 3-pDigits)
+ if pfDigits:
+ pDigits += pfDigits + 1
+ cDigits = int(math.ceil(math.log(len(items), 10)))
+ print "[%s] :: [%s] :: [%s]" % ('Range'.center((pDigits+1)*2 + 3),
+ 'Percentage'.center(barW),
+ 'Count'.center(cDigits*2 + 1))
+ print hr
+ for i,row in enumerate(histo):
+ pct = float(len(row)) / len(items)
+ w = int(barW * pct)
+ print "[%*.*fs,%*.*fs)" % (pDigits, pfDigits, i*barH,
+ pDigits, pfDigits, (i+1)*barH),
+ print ":: [%s%s] :: [%*d/%*d]" % ('*'*w, ' '*(barW-w),
+ cDigits, len(row),
+ cDigits, len(items))
+
diff --git a/contrib/llvm/utils/lit/lit/__init__.py b/contrib/llvm/utils/lit/lit/__init__.py
new file mode 100644
index 0000000..0102602
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/__init__.py
@@ -0,0 +1,10 @@
+"""'lit' Testing Tool"""
+
+from lit import main
+
+__author__ = 'Daniel Dunbar'
+__email__ = 'daniel@zuster.org'
+__versioninfo__ = (0, 1, 0)
+__version__ = '.'.join(map(str, __versioninfo__))
+
+__all__ = []
diff --git a/contrib/llvm/utils/lit/lit/lit.py b/contrib/llvm/utils/lit/lit/lit.py
new file mode 100755
index 0000000..13d2630
--- /dev/null
+++ b/contrib/llvm/utils/lit/lit/lit.py
@@ -0,0 +1,648 @@
+#!/usr/bin/env python
+
+"""
+lit - LLVM Integrated Tester.
+
+See lit.pod for more information.
+"""
+
+import math, os, platform, random, re, sys, time, threading, traceback
+
+import ProgressBar
+import TestRunner
+import Util
+
+from TestingConfig import TestingConfig
+import LitConfig
+import Test
+
+# Configuration files to look for when discovering test suites. These can be
+# overridden with --config-prefix.
+#
+# FIXME: Rename to 'config.lit', 'site.lit', and 'local.lit' ?
+gConfigName = 'lit.cfg'
+gSiteConfigName = 'lit.site.cfg'
+
+kLocalConfigName = 'lit.local.cfg'
+
+class TestingProgressDisplay:
+ def __init__(self, opts, numTests, progressBar=None):
+ self.opts = opts
+ self.numTests = numTests
+ self.current = None
+ self.lock = threading.Lock()
+ self.progressBar = progressBar
+ self.completed = 0
+
+ def update(self, test):
+ # Avoid locking overhead in quiet mode
+ if self.opts.quiet and not test.result.isFailure:
+ self.completed += 1
+ return
+
+ # Output lock.
+ self.lock.acquire()
+ try:
+ self.handleUpdate(test)
+ finally:
+ self.lock.release()
+
+ def finish(self):
+ if self.progressBar:
+ self.progressBar.clear()
+ elif self.opts.quiet:
+ pass
+ elif self.opts.succinct:
+ sys.stdout.write('\n')
+
+ def handleUpdate(self, test):
+ self.completed += 1
+ if self.progressBar:
+ self.progressBar.update(float(self.completed)/self.numTests,
+ test.getFullName())
+
+ if self.opts.succinct and not test.result.isFailure:
+ return
+
+ if self.progressBar:
+ self.progressBar.clear()
+
+ print '%s: %s (%d of %d)' % (test.result.name, test.getFullName(),
+ self.completed, self.numTests)
+
+ if test.result.isFailure and self.opts.showOutput:
+ print "%s TEST '%s' FAILED %s" % ('*'*20, test.getFullName(),
+ '*'*20)
+ print test.output
+ print "*" * 20
+
+ sys.stdout.flush()
+
+class TestProvider:
+ def __init__(self, tests, maxTime):
+ self.maxTime = maxTime
+ self.iter = iter(tests)
+ self.lock = threading.Lock()
+ self.startTime = time.time()
+
+ def get(self):
+ # Check if we have run out of time.
+ if self.maxTime is not None:
+ if time.time() - self.startTime > self.maxTime:
+ return None
+
+ # Otherwise take the next test.
+ self.lock.acquire()
+ try:
+ item = self.iter.next()
+ except StopIteration:
+ item = None
+ self.lock.release()
+ return item
+
+class Tester(threading.Thread):
+ def __init__(self, litConfig, provider, display):
+ threading.Thread.__init__(self)
+ self.litConfig = litConfig
+ self.provider = provider
+ self.display = display
+
+ def run(self):
+ while 1:
+ item = self.provider.get()
+ if item is None:
+ break
+ self.runTest(item)
+
+ def runTest(self, test):
+ result = None
+ startTime = time.time()
+ try:
+ result, output = test.config.test_format.execute(test,
+ self.litConfig)
+ except KeyboardInterrupt:
+ # This is a sad hack. Unfortunately subprocess goes
+ # bonkers with ctrl-c and we start forking merrily.
+ print '\nCtrl-C detected, goodbye.'
+ os.kill(0,9)
+ except:
+ if self.litConfig.debug:
+ raise
+ result = Test.UNRESOLVED
+ output = 'Exception during script execution:\n'
+ output += traceback.format_exc()
+ output += '\n'
+ elapsed = time.time() - startTime
+
+ test.setResult(result, output, elapsed)
+ self.display.update(test)
+
+def dirContainsTestSuite(path):
+ cfgpath = os.path.join(path, gSiteConfigName)
+ if os.path.exists(cfgpath):
+ return cfgpath
+ cfgpath = os.path.join(path, gConfigName)
+ if os.path.exists(cfgpath):
+ return cfgpath
+
+def getTestSuite(item, litConfig, cache):
+ """getTestSuite(item, litConfig, cache) -> (suite, relative_path)
+
+ Find the test suite containing @arg item.
+
+ @retval (None, ...) - Indicates no test suite contains @arg item.
+ @retval (suite, relative_path) - The suite that @arg item is in, and its
+ relative path inside that suite.
+ """
+ def search1(path):
+ # Check for a site config or a lit config.
+ cfgpath = dirContainsTestSuite(path)
+
+ # If we didn't find a config file, keep looking.
+ if not cfgpath:
+ parent,base = os.path.split(path)
+ if parent == path:
+ return (None, ())
+
+ ts, relative = search(parent)
+ return (ts, relative + (base,))
+
+ # We found a config file, load it.
+ if litConfig.debug:
+ litConfig.note('loading suite config %r' % cfgpath)
+
+ cfg = TestingConfig.frompath(cfgpath, None, litConfig, mustExist = True)
+ source_root = os.path.realpath(cfg.test_source_root or path)
+ exec_root = os.path.realpath(cfg.test_exec_root or path)
+ return Test.TestSuite(cfg.name, source_root, exec_root, cfg), ()
+
+ def search(path):
+ # Check for an already instantiated test suite.
+ res = cache.get(path)
+ if res is None:
+ cache[path] = res = search1(path)
+ return res
+
+ # Canonicalize the path.
+ item = os.path.realpath(item)
+
+ # Skip files and virtual components.
+ components = []
+ while not os.path.isdir(item):
+ parent,base = os.path.split(item)
+ if parent == item:
+ return (None, ())
+ components.append(base)
+ item = parent
+ components.reverse()
+
+ ts, relative = search(item)
+ return ts, tuple(relative + tuple(components))
+
+def getLocalConfig(ts, path_in_suite, litConfig, cache):
+ def search1(path_in_suite):
+ # Get the parent config.
+ if not path_in_suite:
+ parent = ts.config
+ else:
+ parent = search(path_in_suite[:-1])
+
+ # Load the local configuration.
+ source_path = ts.getSourcePath(path_in_suite)
+ cfgpath = os.path.join(source_path, kLocalConfigName)
+ if litConfig.debug:
+ litConfig.note('loading local config %r' % cfgpath)
+ return TestingConfig.frompath(cfgpath, parent, litConfig,
+ mustExist = False,
+ config = parent.clone(cfgpath))
+
+ def search(path_in_suite):
+ key = (ts, path_in_suite)
+ res = cache.get(key)
+ if res is None:
+ cache[key] = res = search1(path_in_suite)
+ return res
+
+ return search(path_in_suite)
+
+def getTests(path, litConfig, testSuiteCache, localConfigCache):
+ # Find the test suite for this input and its relative path.
+ ts,path_in_suite = getTestSuite(path, litConfig, testSuiteCache)
+ if ts is None:
+ litConfig.warning('unable to find test suite for %r' % path)
+ return (),()
+
+ if litConfig.debug:
+ litConfig.note('resolved input %r to %r::%r' % (path, ts.name,
+ path_in_suite))
+
+ return ts, getTestsInSuite(ts, path_in_suite, litConfig,
+ testSuiteCache, localConfigCache)
+
+def getTestsInSuite(ts, path_in_suite, litConfig,
+ testSuiteCache, localConfigCache):
+ # Check that the source path exists (errors here are reported by the
+ # caller).
+ source_path = ts.getSourcePath(path_in_suite)
+ if not os.path.exists(source_path):
+ return
+
+ # Check if the user named a test directly.
+ if not os.path.isdir(source_path):
+ lc = getLocalConfig(ts, path_in_suite[:-1], litConfig, localConfigCache)
+ yield Test.Test(ts, path_in_suite, lc)
+ return
+
+ # Otherwise we have a directory to search for tests, start by getting the
+ # local configuration.
+ lc = getLocalConfig(ts, path_in_suite, litConfig, localConfigCache)
+
+ # Search for tests.
+ if lc.test_format is not None:
+ for res in lc.test_format.getTestsInDirectory(ts, path_in_suite,
+ litConfig, lc):
+ yield res
+
+ # Search subdirectories.
+ for filename in os.listdir(source_path):
+ # FIXME: This doesn't belong here?
+ if filename in ('Output', '.svn') or filename in lc.excludes:
+ continue
+
+ # Ignore non-directories.
+ file_sourcepath = os.path.join(source_path, filename)
+ if not os.path.isdir(file_sourcepath):
+ continue
+
+ # Check for nested test suites, first in the execpath in case there is a
+ # site configuration and then in the source path.
+ file_execpath = ts.getExecPath(path_in_suite + (filename,))
+ if dirContainsTestSuite(file_execpath):
+ sub_ts, subiter = getTests(file_execpath, litConfig,
+ testSuiteCache, localConfigCache)
+ elif dirContainsTestSuite(file_sourcepath):
+ sub_ts, subiter = getTests(file_sourcepath, litConfig,
+ testSuiteCache, localConfigCache)
+ else:
+ # Otherwise, continue loading from inside this test suite.
+ subiter = getTestsInSuite(ts, path_in_suite + (filename,),
+ litConfig, testSuiteCache,
+ localConfigCache)
+ sub_ts = None
+
+ N = 0
+ for res in subiter:
+ N += 1
+ yield res
+ if sub_ts and not N:
+ litConfig.warning('test suite %r contained no tests' % sub_ts.name)
+
+def runTests(numThreads, litConfig, provider, display):
+ # If only using one testing thread, don't use threads at all; this lets us
+ # profile, among other things.
+ if numThreads == 1:
+ t = Tester(litConfig, provider, display)
+ t.run()
+ return
+
+ # Otherwise spin up the testing threads and wait for them to finish.
+ testers = [Tester(litConfig, provider, display)
+ for i in range(numThreads)]
+ for t in testers:
+ t.start()
+ try:
+ for t in testers:
+ t.join()
+ except KeyboardInterrupt:
+ sys.exit(2)
+
+def load_test_suite(inputs):
+ import unittest
+
+ # Create the global config object.
+ litConfig = LitConfig.LitConfig(progname = 'lit',
+ path = [],
+ quiet = False,
+ useValgrind = False,
+ valgrindLeakCheck = False,
+ valgrindArgs = [],
+ useTclAsSh = False,
+ noExecute = False,
+ debug = False,
+ isWindows = (platform.system()=='Windows'),
+ params = {})
+
+ # Load the tests from the inputs.
+ tests = []
+ testSuiteCache = {}
+ localConfigCache = {}
+ for input in inputs:
+ prev = len(tests)
+ tests.extend(getTests(input, litConfig,
+ testSuiteCache, localConfigCache)[1])
+ if prev == len(tests):
+ litConfig.warning('input %r contained no tests' % input)
+
+ # If there were any errors during test discovery, exit now.
+ if litConfig.numErrors:
+ print >>sys.stderr, '%d errors, exiting.' % litConfig.numErrors
+ sys.exit(2)
+
+ # Return a unittest test suite which just runs the tests in order.
+ def get_test_fn(test):
+ return unittest.FunctionTestCase(
+ lambda: test.config.test_format.execute(
+ test, litConfig),
+ description = test.getFullName())
+
+ from LitTestCase import LitTestCase
+ return unittest.TestSuite([LitTestCase(test, litConfig) for test in tests])
+
+def main(builtinParameters = {}): # Bump the GIL check interval, its more important to get any one thread to a
+ # blocking operation (hopefully exec) than to try and unblock other threads.
+ #
+ # FIXME: This is a hack.
+ import sys
+ sys.setcheckinterval(1000)
+
+ global options
+ from optparse import OptionParser, OptionGroup
+ parser = OptionParser("usage: %prog [options] {file-or-path}")
+
+ parser.add_option("-j", "--threads", dest="numThreads", metavar="N",
+ help="Number of testing threads",
+ type=int, action="store", default=None)
+ parser.add_option("", "--config-prefix", dest="configPrefix",
+ metavar="NAME", help="Prefix for 'lit' config files",
+ action="store", default=None)
+ parser.add_option("", "--param", dest="userParameters",
+ metavar="NAME=VAL",
+ help="Add 'NAME' = 'VAL' to the user defined parameters",
+ type=str, action="append", default=[])
+
+ group = OptionGroup(parser, "Output Format")
+ # FIXME: I find these names very confusing, although I like the
+ # functionality.
+ group.add_option("-q", "--quiet", dest="quiet",
+ help="Suppress no error output",
+ action="store_true", default=False)
+ group.add_option("-s", "--succinct", dest="succinct",
+ help="Reduce amount of output",
+ action="store_true", default=False)
+ group.add_option("-v", "--verbose", dest="showOutput",
+ help="Show all test output",
+ action="store_true", default=False)
+ group.add_option("", "--no-progress-bar", dest="useProgressBar",
+ help="Do not use curses based progress bar",
+ action="store_false", default=True)
+ parser.add_option_group(group)
+
+ group = OptionGroup(parser, "Test Execution")
+ group.add_option("", "--path", dest="path",
+ help="Additional paths to add to testing environment",
+ action="append", type=str, default=[])
+ group.add_option("", "--vg", dest="useValgrind",
+ help="Run tests under valgrind",
+ action="store_true", default=False)
+ group.add_option("", "--vg-leak", dest="valgrindLeakCheck",
+ help="Check for memory leaks under valgrind",
+ action="store_true", default=False)
+ group.add_option("", "--vg-arg", dest="valgrindArgs", metavar="ARG",
+ help="Specify an extra argument for valgrind",
+ type=str, action="append", default=[])
+ group.add_option("", "--time-tests", dest="timeTests",
+ help="Track elapsed wall time for each test",
+ action="store_true", default=False)
+ group.add_option("", "--no-execute", dest="noExecute",
+ help="Don't execute any tests (assume PASS)",
+ action="store_true", default=False)
+ parser.add_option_group(group)
+
+ group = OptionGroup(parser, "Test Selection")
+ group.add_option("", "--max-tests", dest="maxTests", metavar="N",
+ help="Maximum number of tests to run",
+ action="store", type=int, default=None)
+ group.add_option("", "--max-time", dest="maxTime", metavar="N",
+ help="Maximum time to spend testing (in seconds)",
+ action="store", type=float, default=None)
+ group.add_option("", "--shuffle", dest="shuffle",
+ help="Run tests in random order",
+ action="store_true", default=False)
+ parser.add_option_group(group)
+
+ group = OptionGroup(parser, "Debug and Experimental Options")
+ group.add_option("", "--debug", dest="debug",
+ help="Enable debugging (for 'lit' development)",
+ action="store_true", default=False)
+ group.add_option("", "--show-suites", dest="showSuites",
+ help="Show discovered test suites",
+ action="store_true", default=False)
+ group.add_option("", "--no-tcl-as-sh", dest="useTclAsSh",
+ help="Don't run Tcl scripts using 'sh'",
+ action="store_false", default=True)
+ group.add_option("", "--repeat", dest="repeatTests", metavar="N",
+ help="Repeat tests N times (for timing)",
+ action="store", default=None, type=int)
+ parser.add_option_group(group)
+
+ (opts, args) = parser.parse_args()
+
+ if not args:
+ parser.error('No inputs specified')
+
+ if opts.configPrefix is not None:
+ global gConfigName, gSiteConfigName
+ gConfigName = '%s.cfg' % opts.configPrefix
+ gSiteConfigName = '%s.site.cfg' % opts.configPrefix
+
+ if opts.numThreads is None:
+# Python <2.5 has a race condition causing lit to always fail with numThreads>1
+# http://bugs.python.org/issue1731717
+# I haven't seen this bug occur with 2.5.2 and later, so only enable multiple
+# threads by default there.
+ if sys.hexversion >= 0x2050200:
+ opts.numThreads = Util.detectCPUs()
+ else:
+ opts.numThreads = 1
+
+ inputs = args
+
+ # Create the user defined parameters.
+ userParams = dict(builtinParameters)
+ for entry in opts.userParameters:
+ if '=' not in entry:
+ name,val = entry,''
+ else:
+ name,val = entry.split('=', 1)
+ userParams[name] = val
+
+ # Create the global config object.
+ litConfig = LitConfig.LitConfig(progname = os.path.basename(sys.argv[0]),
+ path = opts.path,
+ quiet = opts.quiet,
+ useValgrind = opts.useValgrind,
+ valgrindLeakCheck = opts.valgrindLeakCheck,
+ valgrindArgs = opts.valgrindArgs,
+ useTclAsSh = opts.useTclAsSh,
+ noExecute = opts.noExecute,
+ debug = opts.debug,
+ isWindows = (platform.system()=='Windows'),
+ params = userParams)
+
+ # Expand '@...' form in inputs.
+ actual_inputs = []
+ for input in inputs:
+ if os.path.exists(input) or not input.startswith('@'):
+ actual_inputs.append(input)
+ else:
+ f = open(input[1:])
+ try:
+ for ln in f:
+ ln = ln.strip()
+ if ln:
+ actual_inputs.append(ln)
+ finally:
+ f.close()
+
+
+ # Load the tests from the inputs.
+ tests = []
+ testSuiteCache = {}
+ localConfigCache = {}
+ for input in actual_inputs:
+ prev = len(tests)
+ tests.extend(getTests(input, litConfig,
+ testSuiteCache, localConfigCache)[1])
+ if prev == len(tests):
+ litConfig.warning('input %r contained no tests' % input)
+
+ # If there were any errors during test discovery, exit now.
+ if litConfig.numErrors:
+ print >>sys.stderr, '%d errors, exiting.' % litConfig.numErrors
+ sys.exit(2)
+
+ if opts.showSuites:
+ suitesAndTests = dict([(ts,[])
+ for ts,_ in testSuiteCache.values()
+ if ts])
+ for t in tests:
+ suitesAndTests[t.suite].append(t)
+
+ print '-- Test Suites --'
+ suitesAndTests = suitesAndTests.items()
+ suitesAndTests.sort(key = lambda (ts,_): ts.name)
+ for ts,ts_tests in suitesAndTests:
+ print ' %s - %d tests' %(ts.name, len(ts_tests))
+ print ' Source Root: %s' % ts.source_root
+ print ' Exec Root : %s' % ts.exec_root
+
+ # Select and order the tests.
+ numTotalTests = len(tests)
+ if opts.shuffle:
+ random.shuffle(tests)
+ else:
+ tests.sort(key = lambda t: t.getFullName())
+ if opts.maxTests is not None:
+ tests = tests[:opts.maxTests]
+
+ extra = ''
+ if len(tests) != numTotalTests:
+ extra = ' of %d' % numTotalTests
+ header = '-- Testing: %d%s tests, %d threads --'%(len(tests),extra,
+ opts.numThreads)
+
+ if opts.repeatTests:
+ tests = [t.copyWithIndex(i)
+ for t in tests
+ for i in range(opts.repeatTests)]
+
+ progressBar = None
+ if not opts.quiet:
+ if opts.succinct and opts.useProgressBar:
+ try:
+ tc = ProgressBar.TerminalController()
+ progressBar = ProgressBar.ProgressBar(tc, header)
+ except ValueError:
+ print header
+ progressBar = ProgressBar.SimpleProgressBar('Testing: ')
+ else:
+ print header
+
+ # Don't create more threads than tests.
+ opts.numThreads = min(len(tests), opts.numThreads)
+
+ startTime = time.time()
+ display = TestingProgressDisplay(opts, len(tests), progressBar)
+ provider = TestProvider(tests, opts.maxTime)
+ runTests(opts.numThreads, litConfig, provider, display)
+ display.finish()
+
+ if not opts.quiet:
+ print 'Testing Time: %.2fs'%(time.time() - startTime)
+
+ # Update results for any tests which weren't run.
+ for t in tests:
+ if t.result is None:
+ t.setResult(Test.UNRESOLVED, '', 0.0)
+
+ # List test results organized by kind.
+ hasFailures = False
+ byCode = {}
+ for t in tests:
+ if t.result not in byCode:
+ byCode[t.result] = []
+ byCode[t.result].append(t)
+ if t.result.isFailure:
+ hasFailures = True
+
+ # FIXME: Show unresolved and (optionally) unsupported tests.
+ for title,code in (('Unexpected Passing Tests', Test.XPASS),
+ ('Failing Tests', Test.FAIL)):
+ elts = byCode.get(code)
+ if not elts:
+ continue
+ print '*'*20
+ print '%s (%d):' % (title, len(elts))
+ for t in elts:
+ print ' %s' % t.getFullName()
+ print
+
+ if opts.timeTests:
+ # Collate, in case we repeated tests.
+ times = {}
+ for t in tests:
+ key = t.getFullName()
+ times[key] = times.get(key, 0.) + t.elapsed
+
+ byTime = list(times.items())
+ byTime.sort(key = lambda (name,elapsed): elapsed)
+ if byTime:
+ Util.printHistogram(byTime, title='Tests')
+
+ for name,code in (('Expected Passes ', Test.PASS),
+ ('Expected Failures ', Test.XFAIL),
+ ('Unsupported Tests ', Test.UNSUPPORTED),
+ ('Unresolved Tests ', Test.UNRESOLVED),
+ ('Unexpected Passes ', Test.XPASS),
+ ('Unexpected Failures', Test.FAIL),):
+ if opts.quiet and not code.isFailure:
+ continue
+ N = len(byCode.get(code,[]))
+ if N:
+ print ' %s: %d' % (name,N)
+
+ # If we encountered any additional errors, exit abnormally.
+ if litConfig.numErrors:
+ print >>sys.stderr, '\n%d error(s), exiting.' % litConfig.numErrors
+ sys.exit(2)
+
+ # Warn about warnings.
+ if litConfig.numWarnings:
+ print >>sys.stderr, '\n%d warning(s) in tests.' % litConfig.numWarnings
+
+ if hasFailures:
+ sys.exit(1)
+ sys.exit(0)
+
+if __name__=='__main__':
+ main()
diff --git a/contrib/llvm/utils/lit/setup.py b/contrib/llvm/utils/lit/setup.py
new file mode 100644
index 0000000..e6ae3d8
--- /dev/null
+++ b/contrib/llvm/utils/lit/setup.py
@@ -0,0 +1,69 @@
+import lit
+
+# FIXME: Support distutils?
+from setuptools import setup, find_packages
+setup(
+ name = "Lit",
+ version = lit.__version__,
+
+ author = lit.__author__,
+ author_email = lit.__email__,
+ url = 'http://llvm.org',
+ license = 'BSD',
+
+ description = "A Software Testing Tool",
+ keywords = 'test C++ automatic discovery',
+ long_description = """\
+Lit
++++
+
+About
+=====
+
+Lit is a portable tool for executing LLVM and Clang style test suites,
+summarizing their results, and providing indication of failures. Lit is designed
+to be a lightweight testing tool with as simple a user interface as possible.
+
+
+Features
+========
+
+ * Portable!
+ * Flexible test discovery.
+ * Parallel test execution.
+ * Support for multiple test formats and test suite designs.
+
+
+Documentation
+=============
+
+The offical Lit documentation is in the man page, available online in the `LLVM
+Command Guide http://llvm.org/cmds/lit.html`_.
+
+
+Source
+======
+
+The Lit source is available as part of LLVM, in the `LLVM SVN repository
+<http://llvm.org/svn/llvm-project/llvm/trunk/utils/lit`_.
+""",
+
+ classifiers=[
+ 'Development Status :: 3 - Alpha',
+ 'Environment :: Console',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: University of Illinois/NCSA Open Source License',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Progamming Language :: Python',
+ 'Topic :: Software Development :: Testing',
+ ],
+
+ zip_safe = False,
+ packages = find_packages(),
+ entry_points = {
+ 'console_scripts': [
+ 'lit = lit:main',
+ ],
+ }
+)
diff --git a/contrib/llvm/utils/llvm-lit/Makefile b/contrib/llvm/utils/llvm-lit/Makefile
new file mode 100644
index 0000000..702591f
--- /dev/null
+++ b/contrib/llvm/utils/llvm-lit/Makefile
@@ -0,0 +1,21 @@
+##===- utils/llvm-lit/Makefile -----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+
+include $(LEVEL)/Makefile.common
+
+all:: $(ToolDir)/llvm-lit
+
+$(ToolDir)/llvm-lit: llvm-lit.in $(ToolDir)/.dir
+ $(Echo) "Creating 'llvm-lit' script..."
+ $(Verb)sed -e "s#@LLVM_SOURCE_DIR@#$(LLVM_SRC_ROOT)#g" \
+ -e "s#@LLVM_BINARY_DIR@#$(LLVM_OBJ_ROOT)#g" \
+ $< > $@
+ $(Verb)chmod +x $@
diff --git a/contrib/llvm/utils/llvm-lit/llvm-lit.in b/contrib/llvm/utils/llvm-lit/llvm-lit.in
new file mode 100644
index 0000000..3ff2c24
--- /dev/null
+++ b/contrib/llvm/utils/llvm-lit/llvm-lit.in
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+import os
+import sys
+
+# Variables configured at build time.
+llvm_source_root = "@LLVM_SOURCE_DIR@"
+llvm_obj_root = "@LLVM_BINARY_DIR@"
+
+# Make sure we can find the lit package.
+sys.path.append(os.path.join(llvm_source_root, 'utils', 'lit'))
+
+# Set up some builtin parameters, so that by default the LLVM test suite
+# configuration file knows how to find the object tree.
+builtin_parameters = {
+ 'llvm_site_config' : os.path.join(llvm_obj_root, 'test', 'lit.site.cfg')
+ }
+
+if __name__=='__main__':
+ import lit
+ lit.main(builtin_parameters)
diff --git a/contrib/llvm/utils/llvm-native-gcc b/contrib/llvm/utils/llvm-native-gcc
new file mode 100755
index 0000000..b3cecb1
--- /dev/null
+++ b/contrib/llvm/utils/llvm-native-gcc
@@ -0,0 +1,249 @@
+#!/usr/bin/perl
+# Wrapper around LLVM tools to generate a native .o from llvm-gcc using an
+# LLVM back-end (CBE by default).
+
+# set up defaults.
+$Verbose = 0;
+$SaveTemps = 1;
+$PreprocessOnly = 0;
+$CompileDontLink = 0;
+$Backend = 'cbe';
+chomp ($ProgramName = `basename $0`);
+
+sub boldprint {
+ print "", @_, "";
+}
+
+# process command-line options.
+# most of these are passed on to llvm-gcc.
+$GCCOptions = "";
+for ($i = 0; $i <= $#ARGV; ++$i) {
+ if ($ARGV[$i] =~ /-mllvm-backend=([a-z0-9]*)/) {
+ $Backend = $1;
+ if ($ProgramName =~ /llvm-native-gcc/) {
+ splice (@ARGV, $i, 1);
+ --$i;
+ }
+ } elsif ($ARGV[$i] eq "-E") {
+ $PreprocessOnly = 1;
+ } elsif ($ARGV[$i] eq "-c") {
+ $GCCOptions .= " " . $ARGV[$i];
+ $CompileDontLink = 1;
+ } elsif ($ARGV[$i] eq "-v") {
+ $GCCOptions .= " " . $ARGV[$i];
+ $Verbose = 1;
+ } elsif ($ARGV[$i] eq "-o") {
+ $OutputFile = $ARGV[$i + 1];
+ } elsif ($ARGV[$i] eq "-save-temps") {
+ $GCCOptions .= " " . $ARGV[$i];
+ $SaveTemps = 1;
+ } elsif ($ARGV[$i] =~ /\.bc$/) {
+ push (@BytecodeFiles, $ARGV[$i]);
+ } elsif ($ARGV[$i] =~ /^-L/) {
+ $GCCOptions .= " " . $ARGV[$i];
+ push (@LibDirs, $ARGV[$i]);
+ } elsif ($ARGV[$i] =~ /^-l/) {
+ $GCCOptions .= " " . $ARGV[$i];
+ push (@Libs, $ARGV[$i]);
+ } elsif ($ARGV[$i] =~ /\.(c|cpp|cc|i|ii|C)$/) {
+ $LastCFile = $ARGV[$i];
+ }
+}
+
+sub GetDefaultOutputFileName {
+ my $DefaultOutputFileBase;
+
+ if ($ProgramName =~ /llvm-native-gcc/) {
+ $DefaultOutputFileBase = $LastCFile;
+ } elsif ($ProgramName =~ /native-build/) {
+ $DefaultOutputFileBase = $BytecodeFiles[0];
+ }
+
+ my $def = $DefaultOutputFileBase;
+
+ die "Can't figure out name of output file.\n"
+ unless $DefaultOutputFileBase
+ && (($ProgramName !~ /native-build/)
+ || $#BytecodeFiles == 0);
+
+ print "Warning: defaulting output file name ",
+ "based on '$DefaultOutputFileBase'\n" if $Verbose;
+
+ if ($ProgramName =~ /llvm-native-gcc/) {
+ $def =~ s/\.(c|cpp|cc|i|ii|C)$/.o/;
+ } elsif ($ProgramName =~ /native-build/) {
+ $def =~ s/\.bc$/.$Backend/;
+ if ($CompileDontLink) {
+ $def .= ".o";
+ }
+ }
+
+ return $def;
+}
+
+# run a command, optionally echoing, and quitting if it fails:
+sub run {
+ my $command = join(" ", @_);
+ print "$command\n" if $Verbose;
+ $command =~ s/\"/\\\"/g;
+ system $command and die "$0: $command failed";
+}
+
+sub LinkBytecodeFilesIntoTemporary {
+ my $FinalOutputFileName = shift @_;
+ my @BytecodeFiles = @_;
+
+ my $BCFiles = join (" ", @BytecodeFiles);
+ my $LinkedBCFile;
+ if ($SaveTemps) {
+ $LinkedBCFile = "${FinalOutputFileName}.llvm.bc";
+ } else {
+ $LinkedBCFile = "/tmp/nativebuild-$$.llvm.bc";
+ }
+ run "llvm-link -o $LinkedBCFile $BCFiles";
+ return $LinkedBCFile;
+}
+
+sub CompileBytecodeToNative {
+ my ($BCFile, $Backend, $OutputFile) = @_;
+
+ my $GeneratedCode;
+ if ($Backend eq 'cbe') {
+ if ($SaveTemps) {
+ $GeneratedCode = "${OutputFile}.c";
+ } else {
+ $GeneratedCode = "/tmp/nativebuild-$$.c";
+ }
+ run "llc -enable-correct-eh-support -march=c -f -o $GeneratedCode $BCFile";
+ } elsif ($Backend eq 'llc') {
+ if ($SaveTemps) {
+ $GeneratedCode = "${OutputFile}.s";
+ } else {
+ $GeneratedCode = "/tmp/nativebuild-$$.s";
+ }
+ run "llc -enable-correct-eh-support -f -o $GeneratedCode $BCFile";
+ }
+ my $LibDirs = join (" ", @LibDirs);
+ my $Libs = join (" ", @Libs);
+ run "gcc $GCCOptions $GeneratedCode -o $OutputFile $LibDirs $Libs";
+ run "rm $BCFile $GeneratedCode"
+ unless $SaveTemps;
+}
+
+sub CompileCToNative {
+ my ($LLVMGCCCommand, $Backend, $OutputFile) = @_;
+ run $LLVMGCCCommand;
+ if ($PreprocessOnly) {
+ return;
+ }
+ my $BCFile = "${OutputFile}.llvm.bc";
+ if ($CompileDontLink) {
+ run "mv ${OutputFile} $BCFile";
+ } else { # gccld messes with the output file name
+ run "mv ${OutputFile}.bc $BCFile";
+ }
+ my $GeneratedCode;
+ if ($Backend eq 'cbe') {
+ $GeneratedCode = "${OutputFile}.cbe.c";
+ run "llc -enable-correct-eh-support -march=c -f -o $GeneratedCode $BCFile";
+ } elsif ($Backend eq 'llc') {
+ $GeneratedCode = "${OutputFile}.llc.s";
+ run "llc -enable-correct-eh-support -f -o $GeneratedCode $BCFile";
+ }
+ my $NativeGCCOptions = "";
+ if ($CompileDontLink) {
+ $NativeGCCOptions = "-c";
+ }
+ run "gcc $NativeGCCOptions $GeneratedCode -o $OutputFile";
+ run "rm ${OutputFile}.llvm.bc $GeneratedCode"
+ unless $SaveTemps;
+}
+
+# guess the name of the output file, if -o was not specified.
+$OutputFile = GetDefaultOutputFileName () unless $OutputFile;
+print "Output file is $OutputFile\n" if $Verbose;
+# do all the dirty work:
+if ($ProgramName eq /native-build/) {
+ my $LinkedBCFile = LinkBytecodeFilesIntoTemporary (@BytecodeFiles);
+ CompileBytecodeToNative ($LinkedBCFile, $Backend, $OutputFile);
+} elsif ($ProgramName =~ /llvm-native-gcc/) {
+ # build the llvm-gcc command line.
+ $LLVMGCCCommand = join (" ", ("llvm-gcc", @ARGV));
+ CompileCToNative ($LLVMGCCCommand, $Backend, $OutputFile);
+}
+
+# we're done.
+exit 0;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+llvm-native-gcc
+
+=head1 SYNOPSIS
+
+llvm-native-gcc [OPTIONS...] FILE
+
+native-build [OPTIONS...] FILE
+
+=head1 DESCRIPTION
+
+llvm-native-gcc is a wrapper around the LLVM command-line tools which generates
+a native object (.o) file by compiling FILE with llvm-gcc, and then running
+an LLVM back-end (CBE by default) over the resulting bytecode, and then
+compiling the resulting code to a native object file.
+
+If called as "native-build", it compiles bytecode to native code, and takes
+different options.
+
+=head1 OPTIONS
+
+llvm-native-gcc takes the same options as llvm-gcc. All options
+except -mllvm-backend=... are passed on to llvm-gcc.
+
+=over 4
+
+=item -mllvm-backend=BACKEND
+
+Use BACKEND for native code generation.
+
+=item -v
+
+Print command lines that llvm-native-gcc runs.
+
+=item -o FILE
+
+llvm-native-gcc tries to guess the name of the llvm-gcc output file by looking
+for this option in the command line. If it can't find it, it finds the last C
+or C++ source file named on the command line, and turns its suffix into .o. See
+BUGS.
+
+=item -save-temps
+
+Save temporary files used by llvm-native-gcc (and llvm-gcc, and gcc).
+
+=back
+
+=head1 BUGS
+
+llvm-native-gcc only handles the case where llvm-gcc compiles a single
+file per invocation. llvm-native-gcc has weak command-line argument
+parsing and is a poor substitute for making gcc/gcc.c do this stuff.
+
+This manual page does not adequately document native-build mode.
+
+llvm-native-gcc is pretty gross because it represents the blind merging of two
+other scripts that predated it. It could use some code clean-up.
+
+=head1 SEE ALSO
+
+gcc(1)
+
+=head1 AUTHOR
+
+Brian R. Gaeke
+
+=cut
diff --git a/contrib/llvm/utils/llvm-native-gxx b/contrib/llvm/utils/llvm-native-gxx
new file mode 100755
index 0000000..75164af
--- /dev/null
+++ b/contrib/llvm/utils/llvm-native-gxx
@@ -0,0 +1,249 @@
+#!/usr/bin/perl
+# Wrapper around LLVM tools to generate a native .o from llvm-gxx using an
+# LLVM back-end (CBE by default).
+
+# set up defaults.
+$Verbose = 0;
+$SaveTemps = 1;
+$PreprocessOnly = 0;
+$CompileDontLink = 0;
+$Backend = 'cbe';
+chomp ($ProgramName = `basename $0`);
+
+sub boldprint {
+ print "", @_, "";
+}
+
+# process command-line options.
+# most of these are passed on to llvm-gxx.
+$GCCOptions = "";
+for ($i = 0; $i <= $#ARGV; ++$i) {
+ if ($ARGV[$i] =~ /-mllvm-backend=([a-z0-9]*)/) {
+ $Backend = $1;
+ if ($ProgramName =~ /llvm-native-gxx/) {
+ splice (@ARGV, $i, 1);
+ --$i;
+ }
+ } elsif ($ARGV[$i] eq "-E") {
+ $PreprocessOnly = 1;
+ } elsif ($ARGV[$i] eq "-c") {
+ $GCCOptions .= " " . $ARGV[$i];
+ $CompileDontLink = 1;
+ } elsif ($ARGV[$i] eq "-v") {
+ $GCCOptions .= " " . $ARGV[$i];
+ $Verbose = 1;
+ } elsif ($ARGV[$i] eq "-o") {
+ $OutputFile = $ARGV[$i + 1];
+ } elsif ($ARGV[$i] eq "-save-temps") {
+ $GCCOptions .= " " . $ARGV[$i];
+ $SaveTemps = 1;
+ } elsif ($ARGV[$i] =~ /\.bc$/) {
+ push (@BytecodeFiles, $ARGV[$i]);
+ } elsif ($ARGV[$i] =~ /^-L/) {
+ $GCCOptions .= " " . $ARGV[$i];
+ push (@LibDirs, $ARGV[$i]);
+ } elsif ($ARGV[$i] =~ /^-l/) {
+ $GCCOptions .= " " . $ARGV[$i];
+ push (@Libs, $ARGV[$i]);
+ } elsif ($ARGV[$i] =~ /\.(c|cpp|cc|i|ii|C)$/) {
+ $LastCFile = $ARGV[$i];
+ }
+}
+
+sub GetDefaultOutputFileName {
+ my $DefaultOutputFileBase;
+
+ if ($ProgramName =~ /llvm-native-gxx/) {
+ $DefaultOutputFileBase = $LastCFile;
+ } elsif ($ProgramName =~ /native-build/) {
+ $DefaultOutputFileBase = $BytecodeFiles[0];
+ }
+
+ my $def = $DefaultOutputFileBase;
+
+ die "Can't figure out name of output file.\n"
+ unless $DefaultOutputFileBase
+ && (($ProgramName !~ /native-build/)
+ || $#BytecodeFiles == 0);
+
+ print "Warning: defaulting output file name ",
+ "based on '$DefaultOutputFileBase'\n" if $Verbose;
+
+ if ($ProgramName =~ /llvm-native-gxx/) {
+ $def =~ s/\.(c|cpp|cc|i|ii|C)$/.o/;
+ } elsif ($ProgramName =~ /native-build/) {
+ $def =~ s/\.bc$/.$Backend/;
+ if ($CompileDontLink) {
+ $def .= ".o";
+ }
+ }
+
+ return $def;
+}
+
+# run a command, optionally echoing, and quitting if it fails:
+sub run {
+ my $command = join(" ", @_);
+ print "$command\n" if $Verbose;
+ $command =~ s/\"/\\\"/g;
+ system $command and die "$0: $command failed";
+}
+
+sub LinkBytecodeFilesIntoTemporary {
+ my $FinalOutputFileName = shift @_;
+ my @BytecodeFiles = @_;
+
+ my $BCFiles = join (" ", @BytecodeFiles);
+ my $LinkedBCFile;
+ if ($SaveTemps) {
+ $LinkedBCFile = "${FinalOutputFileName}.llvm.bc";
+ } else {
+ $LinkedBCFile = "/tmp/nativebuild-$$.llvm.bc";
+ }
+ run "llvm-link -o $LinkedBCFile $BCFiles";
+ return $LinkedBCFile;
+}
+
+sub CompileBytecodeToNative {
+ my ($BCFile, $Backend, $OutputFile) = @_;
+
+ my $GeneratedCode;
+ if ($Backend eq 'cbe') {
+ if ($SaveTemps) {
+ $GeneratedCode = "${OutputFile}.c";
+ } else {
+ $GeneratedCode = "/tmp/nativebuild-$$.c";
+ }
+ run "llc -march=c -f -o $GeneratedCode $BCFile";
+ } elsif ($Backend eq 'llc') {
+ if ($SaveTemps) {
+ $GeneratedCode = "${OutputFile}.s";
+ } else {
+ $GeneratedCode = "/tmp/nativebuild-$$.s";
+ }
+ run "llc -f -o $GeneratedCode $BCFile";
+ }
+ my $LibDirs = join (" ", @LibDirs);
+ my $Libs = join (" ", @Libs);
+ run "gcc $GCCOptions $GeneratedCode -o $OutputFile $LibDirs $Libs";
+ run "rm $BCFile $GeneratedCode"
+ unless $SaveTemps;
+}
+
+sub CompileCToNative {
+ my ($LLVMGCCCommand, $Backend, $OutputFile) = @_;
+ run $LLVMGCCCommand;
+ if ($PreprocessOnly) {
+ return;
+ }
+ my $BCFile = "${OutputFile}.llvm.bc";
+ if ($CompileDontLink) {
+ run "mv ${OutputFile} $BCFile";
+ } else { # gccld messes with the output file name
+ run "mv ${OutputFile}.bc $BCFile";
+ }
+ my $GeneratedCode;
+ if ($Backend eq 'cbe') {
+ $GeneratedCode = "${OutputFile}.cbe.c";
+ run "llc -march=c -f -o $GeneratedCode $BCFile";
+ } elsif ($Backend eq 'llc') {
+ $GeneratedCode = "${OutputFile}.llc.s";
+ run "llc -f -o $GeneratedCode $BCFile";
+ }
+ my $NativeGCCOptions = "";
+ if ($CompileDontLink) {
+ $NativeGCCOptions = "-c";
+ }
+ run "gcc $NativeGCCOptions $GeneratedCode -o $OutputFile";
+ run "rm ${OutputFile}.llvm.bc $GeneratedCode"
+ unless $SaveTemps;
+}
+
+# guess the name of the output file, if -o was not specified.
+$OutputFile = GetDefaultOutputFileName () unless $OutputFile;
+print "Output file is $OutputFile\n" if $Verbose;
+# do all the dirty work:
+if ($ProgramName eq /native-build/) {
+ my $LinkedBCFile = LinkBytecodeFilesIntoTemporary (@BytecodeFiles);
+ CompileBytecodeToNative ($LinkedBCFile, $Backend, $OutputFile);
+} elsif ($ProgramName =~ /llvm-native-gxx/) {
+ # build the llvm-gxx command line.
+ $LLVMGCCCommand = join (" ", ("llvm-g++", @ARGV));
+ CompileCToNative ($LLVMGCCCommand, $Backend, $OutputFile);
+}
+
+# we're done.
+exit 0;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+llvm-native-gxx
+
+=head1 SYNOPSIS
+
+llvm-native-g++ [OPTIONS...] FILE
+
+native-build [OPTIONS...] FILE
+
+=head1 DESCRIPTION
+
+llvm-native-g++ is a wrapper around the LLVM command-line tools which generates
+a native object (.o) file by compiling FILE with llvm-g++, and then running
+an LLVM back-end (CBE by default) over the resulting bytecode, and then
+compiling the resulting code to a native object file.
+
+If called as "native-build", it compiles bytecode to native code, and takes
+different options.
+
+=head1 OPTIONS
+
+llvm-native-g++ takes the same options as llvm-gcc. All options
+except -mllvm-backend=... are passed on to llvm-g++.
+
+=over 4
+
+=item -mllvm-backend=BACKEND
+
+Use BACKEND for native code generation.
+
+=item -v
+
+Print command lines that llvm-native-g++ runs.
+
+=item -o FILE
+
+llvm-native-g++ tries to guess the name of the llvm-g++ output file by looking
+for this option in the command line. If it can't find it, it finds the last C
+or C++ source file named on the command line, and turns its suffix into .o. See
+BUGS.
+
+=item -save-temps
+
+Save temporary files used by llvm-native-g++ (and llvm-g++, and g++).
+
+=back
+
+=head1 BUGS
+
+llvm-native-g++ only handles the case where llvm-g++ compiles a single
+file per invocation. llvm-native-g++ has weak command-line argument
+parsing and is a poor substitute for making g++/g++.c do this stuff.
+
+This manual page does not adequately document native-build mode.
+
+llvm-native-g++ is pretty gross because it represents the blind merging of two
+other scripts that predated it. It could use some code clean-up.
+
+=head1 SEE ALSO
+
+g++(1)
+
+=head1 AUTHOR
+
+Brian R. Gaeke
+
+=cut
diff --git a/contrib/llvm/utils/llvm.grm b/contrib/llvm/utils/llvm.grm
new file mode 100644
index 0000000..9d6bdf7
--- /dev/null
+++ b/contrib/llvm/utils/llvm.grm
@@ -0,0 +1,418 @@
+(*
+
+polygen grammar for LLVM assembly language.
+
+This file defines an LLVM assembly language grammar for polygen,
+which is a tool for generating random text based on a grammar.
+It is strictly syntax-based, and makes no attempt to generate
+IR that is semantically valid. Most of the IR produced doesn't
+pass the Verifier.
+
+TODO: Metadata, in all its forms
+
+*)
+
+I ::= "title: LLVM assembly language\n"
+ ^ "status: experimental\n"
+ ^ "audience: LLVM developers\n"
+;
+
+S ::= Module ;
+
+(*
+Define rules for non-keyword tokens. This is currently just a bunch
+of hacks. They don't cover many valid forms of tokens, and they also
+generate some invalid forms of tokens. The LLVM parser has custom
+C++ code to lex these; custom C++ code for emitting them would be
+convenient, but polygen doesn't support that.
+*)
+NonZeroDecimalDigit ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ;
+DecimalDigit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ;
+DecimalDigitSeq ::= DecimalDigit [^ DecimalDigitSeq ];
+HexDigit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
+ | a | b | c | d | e | f ;
+HexDigitSeq ::= HexDigit [^ HexDigitSeq ];
+StringChar ::= a | b | c | d | e | f | g | h | i | j | k | l | m
+ | n | o | p | q | r | s | t | u | v | w | x | y | z ;
+StringConstantSeq ::= StringChar [^ StringConstantSeq ];
+StringConstant ::= StringChar [^ StringConstantSeq ];
+EUINT64VAL ::= NonZeroDecimalDigit [^ DecimalDigitSeq ];
+ESINT64VAL ::= [ "-" ] ^ EUINT64VAL ;
+EUAPINTVAL ::= EUINT64VAL ;
+ESAPINTVAL ::= ESINT64VAL ;
+LOCALVALID ::= "%" ^ DecimalDigitSeq ;
+GLOBALVALID ::= "@" ^ DecimalDigitSeq ;
+INTTYPE ::= "i" ^ EUINT64VAL ;
+GLOBALVAR ::= "@" ^ StringConstant ;
+LOCALVAR ::= "%" ^ StringConstant ;
+STRINGCONSTANT ::= "\"" ^ StringConstant ^ "\"" ;
+ATSTRINGCONSTANT ::= "@" ^ STRINGCONSTANT ;
+PCTSTRINGCONSTANT ::= "%" ^ STRINGCONSTANT ;
+LABELSTR ::= StringConstant ;
+FPVAL ::= ESAPINTVAL ^ "." ^ EUAPINTVAL | "0x" ^ HexDigitSeq ;
+
+(*
+The rest of this file is derived directly from llvmAsmParser.y.
+*)
+
+ArithmeticOps ::= + OptNW add | fadd | OptNW sub | fsub | OptNW mul | fmul |
+ udiv | OptExact sdiv | fdiv | urem | srem | frem ;
+LogicalOps ::= shl | lshr | ashr | and | or | xor;
+CastOps ::= trunc | zext | sext | fptrunc | fpext | bitcast |
+ uitofp | sitofp | fptoui | fptosi | inttoptr | ptrtoint ;
+
+IPredicates ::= eq | ne | slt | sgt | sle | sge | ult | ugt | ule | uge ;
+
+FPredicates ::= oeq | one | olt | ogt | ole | oge | ord | uno | ueq | une
+ | ult | ugt | ule | uge | true | false ;
+
+IntType ::= INTTYPE;
+FPType ::= float | double | "ppc_fp128" | fp128 | "x86_fp80";
+
+LocalName ::= LOCALVAR | STRINGCONSTANT | PCTSTRINGCONSTANT ;
+OptLocalName ::= LocalName | _ ;
+
+OptAddrSpace ::= - addrspace ^ "(" ^ EUINT64VAL ^ ")" | _ ;
+
+OptLocalAssign ::= LocalName "=" | _ ;
+
+GlobalName ::= GLOBALVAR | ATSTRINGCONSTANT ;
+
+OptGlobalAssign ::= GlobalAssign | _ ;
+
+GlobalAssign ::= GlobalName "=" ;
+
+GVInternalLinkage
+ ::= + internal
+ | weak
+ | "weak_odr"
+ | linkonce
+ | "linkonce_odr"
+ | appending
+ | dllexport
+ | common
+ | private
+ | "linker_private"
+ | "linker_private_weak"
+ ;
+
+GVExternalLinkage
+ ::= dllimport
+ | "extern_weak"
+ | + external
+ ;
+
+GVVisibilityStyle
+ ::= + _
+ | default
+ | hidden
+ | protected
+ ;
+
+FunctionDeclareLinkage
+ ::= + _
+ | dllimport
+ | "extern_weak"
+ ;
+
+FunctionDefineLinkage
+ ::= + _
+ | internal
+ | linkonce
+ | "linkonce_odr"
+ | weak
+ | "weak_odr"
+ | dllexport
+ ;
+
+AliasLinkage ::= + _ | weak | "weak_odr" | internal ;
+
+OptCallingConv ::= + _ |
+ ccc |
+ fastcc |
+ coldcc |
+ "x86_stdcallcc" |
+ "x86_fastcallcc" |
+ cc EUINT64VAL ;
+
+ParamAttr ::= zeroext
+ | signext
+ | inreg
+ | sret
+ | noalias
+ | nocapture
+ | byval
+ | nest
+ | align EUINT64VAL
+ ;
+
+OptParamAttrs ::= + _ | OptParamAttrs ParamAttr ;
+
+RetAttr ::= inreg
+ | zeroext
+ | signext
+ | noalias
+ ;
+
+OptRetAttrs ::= _
+ | OptRetAttrs RetAttr
+ ;
+
+FuncAttr ::= noreturn
+ | nounwind
+ | inreg
+ | zeroext
+ | signext
+ | readnone
+ | readonly
+ | inlinehint
+ | alignstack
+ | noinline
+ | alwaysinline
+ | optsize
+ | ssp
+ | sspreq
+ ;
+
+OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ;
+
+OptGC ::= + _ | gc STRINGCONSTANT ;
+
+OptAlign ::= + _ | align EUINT64VAL ;
+OptCAlign ::= + _ | ^ "," align EUINT64VAL ;
+
+SectionString ::= section STRINGCONSTANT ;
+
+OptSection ::= + _ | SectionString ;
+
+GlobalVarAttributes ::= + _ | ^ "," GlobalVarAttribute GlobalVarAttributes ;
+GlobalVarAttribute ::= SectionString | align EUINT64VAL ;
+
+PrimType ::= INTTYPE | float | double | "ppc_fp128" | fp128 | "x86_fp80"
+ | - label ;
+
+Types
+ ::= opaque
+ | PrimType
+ | Types OptAddrSpace ^ "*"
+ | SymbolicValueRef
+ | "\\" ^ EUINT64VAL
+ | Types "(" ^ ArgTypeListI ^ ")" OptFuncAttrs
+ | void "(" ^ ArgTypeListI ^ ")" OptFuncAttrs
+ | "[" ^ EUINT64VAL "x" Types ^ "]"
+ | "<" ^ EUINT64VAL "x" Types ^ ">"
+ | "{" TypeListI "}"
+ | "{" ^ "}"
+ | "<" ^ "{" TypeListI "}" ^ ">"
+ | "<" ^ "{" ^ "}" ^ ">"
+ ;
+
+ArgType ::= Types OptParamAttrs ;
+
+ResultTypes ::= Types | void ;
+
+ArgTypeList ::= ArgType | ArgTypeList ^ "," ArgType ;
+
+ArgTypeListI ::= ArgTypeList | ArgTypeList ^ "," "..." | "..." | _ ;
+
+TypeListI ::= Types | TypeListI ^ "," Types ;
+
+ConstVal::= Types "[" ^ ConstVector ^ "]"
+ | Types "[" ^ "]"
+ | Types "c" ^ STRINGCONSTANT
+ | Types "<" ^ ConstVector ^ ">"
+ | Types "{" ConstVector "}"
+ | Types "{" ^ "}"
+ | Types "<" ^ "{" ConstVector "}" ^ ">"
+ | Types "<" ^ "{" ^ "}" ^ ">"
+ | Types null
+ | Types undef
+ | Types SymbolicValueRef
+ | Types ConstExpr
+ | Types zeroinitializer
+ | Types ESINT64VAL
+ | Types ESAPINTVAL
+ | Types EUINT64VAL
+ | Types EUAPINTVAL
+ | Types true
+ | Types false
+ | Types FPVAL ;
+
+ConstExpr::= CastOps "(" ^ ConstVal to Types ^ ")"
+ | getelementptr OptInBounds "(" ^ ConstVal IndexList ^ ")"
+ | select "(" ^ ConstVal ^ "," ConstVal ^ "," ConstVal ^ ")"
+ | ArithmeticOps "(" ^ ConstVal ^ "," ConstVal ^ ")"
+ | LogicalOps "(" ^ ConstVal ^ "," ConstVal ^ ")"
+ | icmp IPredicates "(" ^ ConstVal ^ "," ConstVal ^ ")"
+ | fcmp FPredicates "(" ^ ConstVal ^ "," ConstVal ^ ")"
+ | extractelement "(" ^ ConstVal ^ "," ConstVal ^ ")"
+ | insertelement "(" ^ ConstVal ^ "," ConstVal ^ "," ConstVal ^ ")"
+ | shufflevector "(" ^ ConstVal ^ "," ConstVal ^ "," ConstVal ^ ")"
+ | extractvalue "(" ^ ConstVal ^ ConstantIndexList ^ ")"
+ | insertvalue "(" ^ ConstVal ^ "," ConstVal ^ ConstantIndexList ^ ")" ;
+
+ConstVector ::= ConstVector ^ "," ConstVal | ConstVal ;
+
+GlobalType ::= global | constant ;
+
+ThreadLocal ::= - "thread_local" | _ ;
+
+AliaseeRef ::= ResultTypes SymbolicValueRef
+ | bitcast "(" ^ AliaseeRef to Types ^ ")" ;
+
+Module ::= +++ DefinitionList | --- _ ;
+
+DefinitionList ::= - Definition | + DefinitionList Definition ;
+
+Definition
+ ::= ^ ( +++++ define Function
+ | declare FunctionProto
+ | - module asm AsmBlock
+ | OptLocalAssign type Types
+ | OptGlobalAssign GVVisibilityStyle ThreadLocal OptAddrSpace GlobalType
+ ConstVal GlobalVarAttributes
+ | OptGlobalAssign GVInternalLinkage GVVisibilityStyle ThreadLocal OptAddrSpace
+ GlobalType ConstVal GlobalVarAttributes
+ | OptGlobalAssign GVExternalLinkage GVVisibilityStyle ThreadLocal OptAddrSpace
+ GlobalType Types GlobalVarAttributes
+ | OptGlobalAssign GVVisibilityStyle alias AliasLinkage AliaseeRef
+ | target TargetDefinition
+ | deplibs "=" LibrariesDefinition
+ ) ^ "\n";
+
+AsmBlock ::= STRINGCONSTANT ;
+
+TargetDefinition ::= triple "=" STRINGCONSTANT
+ | datalayout "=" STRINGCONSTANT ;
+
+LibrariesDefinition ::= "[" ( LibList | _ ) "]";
+
+LibList ::= LibList ^ "," STRINGCONSTANT | STRINGCONSTANT ;
+
+ArgListH ::= ArgListH ^ "," Types OptParamAttrs OptLocalName
+ | Types OptParamAttrs OptLocalName ;
+
+ArgList ::= ArgListH | ArgListH ^ "," "..." | "..." | _ ;
+
+FunctionHeaderH ::= OptCallingConv OptRetAttrs ResultTypes
+ GlobalName ^ "(" ^ ArgList ^ ")"
+ OptFuncAttrs OptSection OptAlign OptGC ;
+
+BEGIN ::= ( begin | "{" ) ^ "\n";
+
+FunctionHeader ::=
+ FunctionDefineLinkage GVVisibilityStyle FunctionHeaderH BEGIN ;
+
+END ::= ^ ( end | "}" ) ^ "\n";
+
+Function ::= BasicBlockList END ;
+
+FunctionProto ::= FunctionDeclareLinkage GVVisibilityStyle FunctionHeaderH ;
+
+OptSideEffect ::= _ | sideeffect ;
+
+ConstValueRef ::= ESINT64VAL
+ | EUINT64VAL
+ | FPVAL
+ | true
+ | false
+ | null
+ | undef
+ | zeroinitializer
+ | "<" ConstVector ">"
+ | "[" ConstVector "]"
+ | "[" ^ "]"
+ | "c" ^ STRINGCONSTANT
+ | "{" ConstVector "}"
+ | "{" ^ "}"
+ | "<" ^ "{" ConstVector "}" ^ ">"
+ | "<" ^ "{" ^ "}" ^ ">"
+ | ConstExpr
+ | asm OptSideEffect STRINGCONSTANT ^ "," STRINGCONSTANT ;
+
+SymbolicValueRef ::= LOCALVALID
+ | GLOBALVALID
+ | LocalName
+ | GlobalName ;
+
+ValueRef ::= SymbolicValueRef | ConstValueRef;
+
+ResolvedVal ::= Types ValueRef ;
+
+ReturnedVal ::= ResolvedVal | ReturnedVal ^ "," ResolvedVal ;
+
+BasicBlockList ::= BasicBlockList BasicBlock | FunctionHeader BasicBlock ;
+
+BasicBlock ::= InstructionList OptLocalAssign BBTerminatorInst ;
+
+InstructionList ::= +++ InstructionList Inst
+ | - _
+ | ^ LABELSTR ^ ":\n" ;
+
+BBTerminatorInst ::= ^ " " ^
+ ( ret ReturnedVal
+ | ret void
+ | br label ValueRef
+ | br INTTYPE ValueRef ^ "," label ValueRef ^ "," label ValueRef
+ | switch IntType ValueRef ^ "," label ValueRef "[" JumpTable "]"
+ | switch IntType ValueRef ^ "," label ValueRef "[" ^ "]"
+ | invoke OptCallingConv ResultTypes ValueRef ^ "(" ^ ParamList ^ ")"
+ OptFuncAttrs
+ to label ValueRef unwind label ValueRef
+ | unwind
+ | unreachable ) ^ "\n";
+
+JumpTable ::= JumpTable IntType ConstValueRef ^ "," label ValueRef
+ | IntType ConstValueRef ^ "," label ValueRef ;
+
+Inst ::= ^ " " ^ OptLocalAssign InstVal ^ "\n";
+
+PHIList ::= Types "[" ValueRef ^ "," ValueRef "]"
+ | PHIList ^ "," "[" ValueRef ^ "," ValueRef "]" ;
+
+ParamList ::= Types OptParamAttrs ValueRef OptParamAttrs
+ | label OptParamAttrs ValueRef OptParamAttrs
+ | ParamList ^ "," Types OptParamAttrs ValueRef OptParamAttrs
+ | ParamList ^ "," label OptParamAttrs ValueRef OptParamAttrs
+ | - _ ;
+
+IndexList ::= _ | IndexList ^ "," ResolvedVal ;
+
+ConstantIndexList ::= "," EUINT64VAL | ConstantIndexList ^ "," EUINT64VAL ;
+
+OptTailCall ::= tail call | call ;
+
+InstVal ::=
+ ArithmeticOps Types ValueRef ^ "," ValueRef
+ | LogicalOps Types ValueRef ^ "," ValueRef
+ | icmp IPredicates Types ValueRef ^ "," ValueRef
+ | fcmp FPredicates Types ValueRef ^ "," ValueRef
+ | CastOps ResolvedVal to Types
+ | select ResolvedVal ^ "," ResolvedVal ^ "," ResolvedVal
+ | "va_arg" ResolvedVal ^ "," Types
+ | extractelement ResolvedVal ^ "," ResolvedVal
+ | insertelement ResolvedVal ^ "," ResolvedVal ^ "," ResolvedVal
+ | shufflevector ResolvedVal ^ "," ResolvedVal ^ "," ResolvedVal
+ | phi PHIList
+ | OptTailCall OptCallingConv ResultTypes ValueRef ^ "(" ^ ParamList ^ ")"
+ OptFuncAttrs
+ | MemoryInst ;
+
+OptVolatile ::= - volatile | _ ;
+OptExact ::= - exact | _ ;
+OptNSW ::= - nsw | _ ;
+OptNUW ::= - nuw | _ ;
+OptNW ::= OptNUW OptNSW | OptNSW OptNUW ;
+OptInBounds ::= - inbounds | _ ;
+
+MemoryInst ::= malloc Types OptCAlign
+ | malloc Types ^ "," INTTYPE ValueRef OptCAlign
+ | alloca Types OptCAlign
+ | alloca Types ^ "," INTTYPE ValueRef OptCAlign
+ | free ResolvedVal
+ | OptVolatile load Types ValueRef OptCAlign
+ | OptVolatile store ResolvedVal ^ "," Types ValueRef OptCAlign
+ | getresult Types ValueRef ^ "," EUINT64VAL
+ | getelementptr OptInBounds Types ValueRef IndexList
+ | extractvalue Types ValueRef ^ ConstantIndexList
+ | insertvalue Types ValueRef ^ "," Types ValueRef ^ ConstantIndexList ;
diff --git a/contrib/llvm/utils/llvmdo b/contrib/llvm/utils/llvmdo
new file mode 100755
index 0000000..bcfc221
--- /dev/null
+++ b/contrib/llvm/utils/llvmdo
@@ -0,0 +1,184 @@
+#!/bin/sh
+##===- utils/llvmdo - Counts Lines Of Code -------------------*- Script -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This script is a general purpose "apply" function for the source files in LLVM
+# It uses "find" to locate all the source files and then applies the user's
+# command to them. As such, this command is often not used by itself much but
+# the other find related tools (countloc.sh,llvmgrep,getsrcs.sh,userloc.sh) are
+# all based on this script. This script defines "what is a source file" in
+# LLVM and so should be maintained if new directories, new file extensions,
+# etc. are used in LLVM as it progresses.
+#
+# Usage:
+# llvmdo [-topdir DIR] [-dirs "DIRNAMES..."] [-code-only] PROGRAM ARGS...
+#
+# The -topdir option allows you to specify the llvm source root directly. If it
+# is not specified then it will be obtained with llvm-config which must be built
+# and in your path.
+#
+# The -dirs argument allows you to specify the set of directories that are
+# searched. The default list of directories searched is:
+# include lib tools utils runtime autoconf docs test examples projects
+# Note that you must use quotes around the list of directory names.
+#
+# The -code-only option specifies that only those files that are considered
+# "code" should be visited. HTML documentation is considered code, but things
+# like README files, etc. are not.
+#
+# Finally, you simply specify whatever program you want to run against each
+# file and the arguments to give it. The PROGRAM will be given the file name
+# as its last argument.
+##===----------------------------------------------------------------------===##
+
+if test $# -lt 1 ; then
+ echo "Usage: llvmdo [-topdir DIR] [-dirs "DIRNAMES..."] [-code-only] PROGRAM ARGS..."
+ exit 1
+fi
+
+if test "$1" = "-topdir" ; then
+ TOPDIR="$2"
+ shift; shift;
+else
+ TOPDIR=`llvm-config --src-root`
+fi
+
+if test "$1" = "-dirs" ; then
+ LLVMDO_DIRS="$2"
+ shift ; shift
+elif test -z "$LLVMDO_DIRS" ; then
+ LLVMDO_DIRS="include lib tools utils runtime autoconf docs test examples projects cmake"
+fi
+
+if test "$1" = "-code-only" ; then
+ CODE_ONLY="set"
+ shift
+else
+ CODE_ONLY=""
+fi
+
+if test "$1" = "" ; then
+ echo "Missing program name to run"
+ exit 1
+fi
+
+PROGRAM=`which $1`
+if test ! -x "$PROGRAM" ; then
+ echo "Can't execute $1"
+ exit 1
+fi
+shift;
+
+paths_to_ignore="\
+ -path */.svn/ -o \
+ -path */.svn/* -o \
+ -path docs/doxygen/* -o \
+ -path docs/CommandGuide/html/* -o \
+ -path docs/CommandGuide/man/* -o \
+ -path docs/CommandGuide/ps/* -o \
+ -path docs/CommandGuide/man/* -o \
+ -path docs/HistoricalNotes/* -o \
+ -path docs/img/* -o \
+ -path */.libs/* -o \
+ -path lib/Support/bzip2/* -o \
+ -path projects/llvm-test/* \
+"
+files_to_match="\
+ -name *.ac \
+ -o -name *.b \
+ -o -name *.c \
+ -o -name *.cc \
+ -o -name *.cfg \
+ -o -name *.cpp \
+ -o -name *.css \
+ -o -name *.def \
+ -o -name *.el \
+ -o -name *.exp \
+ -o -name *.footer \
+ -o -name *.gnuplot' \
+ -o -name *.h \
+ -o -name *.header \
+ -o -name *.html \
+ -o -name *.in \
+ -o -name *.inc \
+ -o -name *.intro \
+ -o -name *.l \
+ -o -name *.ll \
+ -o -name *.lst \
+ -o -name *.m4 \
+ -o -name *.pod \
+ -o -name *.pl \
+ -o -name *.py \
+ -o -name *.sh \
+ -o -name *.schema \
+ -o -name *.st \
+ -o -name *.tcl \
+ -o -name *.td \
+ -o -name *.tr \
+ -o -name *.y \
+ -o -name Make* \
+ -o -name *.cmake \
+ -o -name llvmdo \
+ -o -name llvmgrep \
+ -o -name check-each-file \
+ -o -name codgen-diff \
+ -o -name llvm-native-gcc \
+ -o -name llvm-native-gxx \
+ -o -name makellvm \
+ -o -path include/llvm/ADT/ilist \
+ -o -path test/\*.ll \
+ -o -path test/Scripts/not \
+ -o -path runtime/\*.ll \
+"
+if test -z "$CODE_ONLY" ; then
+ files_to_match="$files_to_match \
+ -o -name *.txt \
+ -o -name *.TXT \
+ -o -name *.vim \
+ -o -name vimrc \
+ -o -name README \
+ -o -name COPYING.LIB \
+ -o -name LICENSE* "
+fi
+files_to_ignore="\
+ -name \.* \
+ -o -name *~ \
+ -o -name #* \
+ -o -name configure \
+ -o -name slow.ll \
+ -o -name *libtool* \
+ -o -name ltdl* \
+ -o -name ltdl.m4 \
+ -o -name ltmain.m4 \
+ -o -name ltmain.sh \
+ -o -name aclocal.m4 \
+ -o -name acinclude.m4 \
+ -o -name *LoopSimplifyCrash.ll \
+ -o -name *AST-Remove.ll \
+ -o -name PPCPerfectShuffle.h \
+"
+
+if test -d "$TOPDIR" ; then
+ cd $TOPDIR
+ # Have to use the right "find" on a per-platform basis. Most platforms have
+ # Gnu find as "find", but Solaris does not.
+ case `uname -s` in
+ SunOS) find_prog=gfind ;;
+ *) find_prog=find ;;
+ esac
+ # Turn off file name generation (globbing) so that substitution of the
+ # variables doesn't cause the shell to create lists of file names
+ set -f
+ $find_prog $LLVMDO_DIRS -type f \
+ \( $paths_to_ignore \) -prune \
+ -o \( \( $files_to_match \) \! \( $files_to_ignore \) \
+ -exec $PROGRAM "$@" {} \; \)
+else
+ echo "Can't find LLVM top directory in $TOPDIR"
+fi
diff --git a/contrib/llvm/utils/llvmgrep b/contrib/llvm/utils/llvmgrep
new file mode 100755
index 0000000..540f059
--- /dev/null
+++ b/contrib/llvm/utils/llvmgrep
@@ -0,0 +1,39 @@
+#!/bin/sh
+##===- utils/llvmgrep - Counts Lines Of Code -----------------*- Script -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This script searches your srcdir for an egrep style pattern. This can quickly
+# help you build a list of the places you need to modify when changing a header
+# or other "global" name. The only argument is the pattern you want to search
+# for. It should be quoted to escape shell interpretation of the pattern's
+# special characters.
+#
+# Note that the implementation is based on llvmdo. See that script for more
+# details.
+##===----------------------------------------------------------------------===##
+
+if test "$1" = "-topdir" ; then
+ TOPDIR="$2"
+ shift; shift;
+else
+ TOPDIR=`llvm-config --src-root`
+fi
+
+if test -d "$TOPDIR" ; then
+ cd $TOPDIR
+ case `uname -s` in
+ SunOS) grep_cmd="ggrep -H -n" ;;
+ Linux) grep_cmd="egrep -H -n" ;;
+ *) grep_cmd="egrep -l -n" ;;
+ esac
+ ./utils/llvmdo -topdir "$TOPDIR" \
+ -dirs "include lib tools utils docs examples test unittests projects cmake" $grep_cmd "$*"
+else
+ echo "Can't find LLVM top directory"
+fi
diff --git a/contrib/llvm/utils/makellvm b/contrib/llvm/utils/makellvm
new file mode 100755
index 0000000..ae77712
--- /dev/null
+++ b/contrib/llvm/utils/makellvm
@@ -0,0 +1,145 @@
+#!/bin/csh -f
+
+set pstatus = 0
+onintr cleanup
+alias usage 'echo "USAGE: $0:t [-h] [-n] [-obj obj-root] [gmake-flags] [VAR=...] [toolname (default: opt)]"; set pstatus = 1; goto cleanup'
+
+set EXEC = opt
+set GMAKE_OPTS = ""
+set DEBUG = 0
+
+## Search path for automatically finding the obj-root to use.
+## Note: The src root directory ${LLVMDIR} will be prepended to this path later.
+##
+set OBJROOTDIRLIST = ( )
+
+set doit = 1
+unset options_done
+while ( !( $?options_done ) && ($#argv > 0))
+ switch ($argv[1])
+ case -h :
+ usage
+ case -f :
+ if ($#argv < 2) usage
+ shift argv; set MFILE = $argv[1]; shift argv; breaksw
+ case -n :
+ set doit = 0; shift argv; breaksw
+ case -obj :
+ set OBJROOT = $argv[2]; shift argv; shift argv
+ if (! -d "$OBJROOT") then
+ echo "FATAL: Illegal obj-root directory ${OBJROOT}"
+ exit 1
+ endif
+ breaksw
+ case -d :
+ set doit = 0; set DEBUG = 1; shift argv; breaksw
+ case -* :
+ set GMAKE_OPTS = ( $GMAKE_OPTS $argv[1] ); shift argv; breaksw
+ default :
+ set optarg = `echo -n $argv[1] | sed 's/^[^=]*$//'`
+ if ($#optarg) then
+ set GMAKE_OPTS = ( $GMAKE_OPTS $optarg )
+ shift argv
+ else
+ set options_done
+ endif
+ breaksw
+ endsw
+end
+
+if ($#argv > 1) then
+ echo 'ERROR: More than one tool is not supported by "makellvm"'
+ usage
+endif
+if ($#argv > 0) then
+ set EXEC = $argv[1]
+endif
+if ($DEBUG) then
+ echo "DEBUG: EXEC = $EXEC"
+endif
+
+## Compute LLVMDIR: the root of the current LLVM tree.
+## It is recorded in the variable LEVEL in Makefile, to compute it
+##
+if (! $?MFILE) then
+ if (-f GNUmakefile) then
+ set MFILE = GNUmakefile
+ else if (-f makefile) then
+ set MFILE = makefile
+ else
+ set MFILE = Makefile
+ endif
+endif
+if ($DEBUG) then
+ echo "DEBUG: MFILE = $MFILE"
+endif
+if (! -f $MFILE) then
+ echo "Missing or invalid makefile: $MFILE"
+ exit 1
+endif
+
+set LLVMDIR = `awk '/LEVEL[ ]*=/ {print $NF}' $MFILE`
+if ($DEBUG) then
+ echo "DEBUG: LLVMDIR = $LLVMDIR"
+endif
+
+if ($#LLVMDIR == 0 || ! -d "$LLVMDIR") then
+ echo "Unable to find LLVM src-root directory or directory is invalid."
+ echo "Are you within a valid LLVM directory for running gmake?"
+ exit 1
+endif
+
+## Try to determine the obj-root directory automatically if not specified
+##
+set OBJROOTDIRLIST = ( ${LLVMDIR} $OBJROOTDIRLIST ) ## add src dir
+if ($?OBJROOT == 0) then
+ ## Try to determine object root directory by looking for Makefile.config
+ foreach objdir ( $OBJROOTDIRLIST )
+ if (-f "${objdir}/Makefile.config") then
+ set OBJROOT = ${objdir}
+ break
+ endif
+ end
+ if ($?OBJROOT == 0) then
+ echo "FATAL: Could not choose an obj-root directory from these choices:"
+ echo " ${OBJROOTDIRLIST}."
+ echo " You can specify it explicitly using '-obj obj-root'."
+ exit 1
+ endif
+ echo "Using OBJ-ROOT = ${OBJROOT} (specify '-obj obj-root' to override)."
+endif
+if (${OBJROOT} == ${LLVMDIR}) then
+ # run make in the source directory itself
+ set BUILDROOT = .
+else
+ # run make in the in the obj-root tree, in the directory for $cwd
+ set SRCROOT = `sh -c "cd $LLVMDIR; pwd | sed 's/\//\\\//g'"`
+ set CURSRCDIR = `echo $cwd | sed -e "s/${SRCROOT}//"`
+ set BUILDROOT = ${OBJROOT}/${CURSRCDIR}
+ unset SRCROOT CURSRCDIR
+endif
+if ($DEBUG) then
+ echo "DEBUG: BUILDROOT = $BUILDROOT"
+endif
+if (! -d $BUILDROOT) then
+ echo "FATAL: Invalid build directory: ${BUILDROOT}"
+ exit 1
+endif
+cd $BUILDROOT
+
+set CMD = "make $GMAKE_OPTS && (cd $LLVMDIR/tools/$EXEC && make $GMAKE_OPTS)"
+
+if ($doit == 1) then
+ csh -f -c "$CMD"
+ set pstatus = $?
+else
+ echo '(NOT EXECUTING) COMMAND:'
+ echo " $CMD"
+endif
+
+
+#=========================================================
+# CODE TO BE EXECUTED IF INTERRUPT IS RECEIVED
+#=========================================================
+cleanup:
+ exit($pstatus)
diff --git a/contrib/llvm/utils/not/CMakeLists.txt b/contrib/llvm/utils/not/CMakeLists.txt
new file mode 100644
index 0000000..407c82e
--- /dev/null
+++ b/contrib/llvm/utils/not/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_executable(not
+ not.cpp
+ )
+
+target_link_libraries(not LLVMSystem)
+if( MINGW )
+ target_link_libraries(not imagehlp psapi)
+endif( MINGW )
+if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD )
+ target_link_libraries(not pthread)
+endif()
diff --git a/contrib/llvm/utils/not/Makefile b/contrib/llvm/utils/not/Makefile
new file mode 100644
index 0000000..fef4802
--- /dev/null
+++ b/contrib/llvm/utils/not/Makefile
@@ -0,0 +1,21 @@
+##===- utils/not/Makefile ----------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TOOLNAME = not
+USEDLIBS = LLVMSupport.a LLVMSystem.a
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+# Don't install this utility
+NO_INSTALL = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/contrib/llvm/utils/not/not.cpp b/contrib/llvm/utils/not/not.cpp
new file mode 100644
index 0000000..dd89b8f
--- /dev/null
+++ b/contrib/llvm/utils/not/not.cpp
@@ -0,0 +1,17 @@
+//===- not.cpp - The 'not' testing tool -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/System/Path.h"
+#include "llvm/System/Program.h"
+using namespace llvm;
+
+int main(int argc, const char **argv) {
+ sys::Path Program = sys::Program::FindProgramByName(argv[1]);
+ return !sys::Program::ExecuteAndWait(Program, argv + 1);
+}
diff --git a/contrib/llvm/utils/parseNLT.pl b/contrib/llvm/utils/parseNLT.pl
new file mode 100644
index 0000000..95afca7
--- /dev/null
+++ b/contrib/llvm/utils/parseNLT.pl
@@ -0,0 +1,34 @@
+#!/usr/bin/perl
+# a first attempt to parse the nightly tester pages into something
+# one can reason about, namely import into a database
+# USE: perl parseNLT.pl <2005-03-31.html
+# for example
+
+while(<>)
+ {
+ if (/LLVM Test Results for (\w+) (\d+), (\d+)</)
+ {
+ $mon = $1;
+ $day = $2;
+ $year = $3;
+ }
+ if (/<td>([^<]+)<\/td>/)
+ {
+ if ($prefix)
+ { $output .= "$1 "; $count++; }
+ }
+ if (/<tr/)
+ {
+ if ($output and $count > 3)
+ { print "\n$day $mon $year $prefix/$output"; }
+ $output = "";
+ $count = 0;
+ }
+ if (/<h2>(Programs.+)<\/h2>/)
+ {
+ $prefix = $1;
+ }
+ }
+
+if ($output)
+ { print "\n$day $mon $year $prefix/$output"; $output = ""; }
diff --git a/contrib/llvm/utils/plotNLT.pl b/contrib/llvm/utils/plotNLT.pl
new file mode 100644
index 0000000..55d503d
--- /dev/null
+++ b/contrib/llvm/utils/plotNLT.pl
@@ -0,0 +1,53 @@
+#!/usr/bin/perl
+#takes a test and a program from a dp and produces a gnuplot script
+#use like perl plotNLT.pl password Programs/MultiSource/Benchmarks/ASCI_Purple/SMG2000/smg2000 llc
+
+use DBI;
+
+# database information
+$db="llvmalpha";
+$host="localhost";
+$userid="llvmdbuser";
+$passwd=shift @ARGV;
+$connectionInfo="dbi:mysql:$db;$host";
+
+# make connection to database
+$dbh = DBI->connect($connectionInfo,$userid,$passwd) or die DBI->errstr;
+
+
+$count = @ARGV / 2;
+
+print "set xdata time\n";
+print 'set timefmt "%Y-%m-%d"';
+print "\nplot";
+for ($iter = 0; $iter < $count; $iter++) {
+ if ($iter)
+ { print ","; }
+ print " '-' using 1:2 with lines";
+}
+
+print "\n";
+
+for ($iter = 0; $iter < $count; $iter++) {
+
+ $prog = shift @ARGV;
+ $test = shift @ARGV;
+
+ $query = "Select RUN, VALUE from Tests where TEST = '$test' AND NAME = '$prog' ORDER BY RUN";
+ #print "\n$query\n";
+
+ my $sth = $dbh->prepare( $query) || die "Can't prepare statement: $DBI::errstr";;
+
+ my $rc = $sth->execute or die DBI->errstr;
+
+ while(($da,$v) = $sth->fetchrow_array)
+ {
+ print "$da $v\n";
+ }
+
+ print "e\n";
+}
+
+
+# disconnect from database
+$dbh->disconnect;
diff --git a/contrib/llvm/utils/profile.pl b/contrib/llvm/utils/profile.pl
new file mode 100755
index 0000000..f9950f9
--- /dev/null
+++ b/contrib/llvm/utils/profile.pl
@@ -0,0 +1,74 @@
+#!/usr/bin/perl -w
+#
+# Program: profile.pl
+#
+# Synopsis: Insert instrumentation code into a program, run it with the JIT,
+# then print out a profile report.
+#
+# Syntax: profile.pl [OPTIONS] bytecodefile <arguments>
+#
+# OPTIONS may include one or more of the following:
+# -block - Enable basicblock profiling
+# -edge - Enable edge profiling
+# -function - Enable function profiling
+# -o <filename> - Emit profiling information to the specified file, instead
+# of llvmprof.out
+#
+# Any unrecognized options are passed into the invocation of llvm-prof
+#
+
+my $ProfilePass = "-insert-edge-profiling";
+
+my $LLVMProfOpts = "";
+my $ProgramOpts = "";
+my $ProfileFile = "";
+
+# Parse arguments...
+while (scalar(@ARGV) and ($_ = $ARGV[0], /^[-+]/)) {
+ shift;
+ last if /^--$/; # Stop processing arguments on --
+
+ # List command line options here...
+ if (/^-?-block$/) { $ProfilePass = "-insert-block-profiling"; next; }
+ if (/^-?-edge$/) { $ProfilePass = "-insert-edge-profiling"; next; }
+ if (/^-?-function$/) { $ProfilePass = "-insert-function-profiling"; next; }
+ if (/^-?-o$/) { # Read -o filename...
+ die "-o option requires a filename argument!" if (!scalar(@ARGV));
+ $ProgramOpts .= " -llvmprof-output $ARGV[0]";
+ $ProfileFile = $ARGV[0];
+ shift;
+ next;
+ }
+ if (/^-?-help$/) {
+ print "OVERVIEW: profile.pl - Instrumentation and profile printer.\n\n";
+ print "USAGE: profile.pl [options] program.bc <program args>\n\n";
+ print "OPTIONS:\n";
+ print " -block - Enable basicblock profiling\n";
+ print " -edge - Enable edge profiling\n";
+ print " -function - Enable function profiling\n";
+ print " -o <file> - Specify an output file other than llvm-prof.out.\n";
+ print " -help - Print this usage information\n";
+ print "\nAll other options are passed into llvm-prof.\n";
+ exit 1;
+ }
+
+ # Otherwise, pass the option on to llvm-prof
+ $LLVMProfOpts .= " " . $_;
+}
+
+die "Must specify LLVM bytecode file as first argument!" if (@ARGV == 0);
+
+my $BytecodeFile = $ARGV[0];
+
+shift @ARGV;
+
+my $libdir = `llvm-config --libdir`;
+chomp $libdir;
+
+my $LibProfPath = $libdir . "/profile_rt.so";
+
+system "opt -q -f $ProfilePass $BytecodeFile -o $BytecodeFile.inst";
+system "lli -fake-argv0 '$BytecodeFile' -load $LibProfPath " .
+ "$BytecodeFile.inst $ProgramOpts " . (join ' ', @ARGV);
+system "rm $BytecodeFile.inst";
+system "llvm-prof $LLVMProfOpts $BytecodeFile $ProfileFile";
diff --git a/contrib/llvm/utils/unittest/Makefile b/contrib/llvm/utils/unittest/Makefile
new file mode 100644
index 0000000..6a09341
--- /dev/null
+++ b/contrib/llvm/utils/unittest/Makefile
@@ -0,0 +1,13 @@
+##===- utils/unittest/Makefile -----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+PARALLEL_DIRS = googletest UnitTestMain
+
+include $(LEVEL)/Makefile.common
diff --git a/contrib/llvm/utils/unittest/UnitTestMain/Makefile b/contrib/llvm/utils/unittest/UnitTestMain/Makefile
new file mode 100644
index 0000000..cec654f
--- /dev/null
+++ b/contrib/llvm/utils/unittest/UnitTestMain/Makefile
@@ -0,0 +1,30 @@
+##===- utils/unittest/UnitTestMain/Makefile ----------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+
+include $(LEVEL)/Makefile.config
+
+LIBRARYNAME = UnitTestMain
+BUILD_ARCHIVE = 1
+REQUIRES_RTTI = 1
+
+CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include
+CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS)
+CPP.Flags += -DGTEST_HAS_RTTI=0
+# libstdc++'s TR1 <tuple> header depends on RTTI and uses C++'0x features not
+# supported by Clang, so force googletest to use its own tuple implementation.
+CPP.Flags += -DGTEST_USE_OWN_TR1_TUPLE
+
+# Disable pthreads if LLVM was configured without them.
+ifneq ($(HAVE_PTHREAD), 1)
+ CPP.Flags += -DGTEST_HAS_PTHREAD=0
+endif
+
+include $(LEVEL)/Makefile.common
diff --git a/contrib/llvm/utils/unittest/UnitTestMain/TestMain.cpp b/contrib/llvm/utils/unittest/UnitTestMain/TestMain.cpp
new file mode 100644
index 0000000..d97dca8
--- /dev/null
+++ b/contrib/llvm/utils/unittest/UnitTestMain/TestMain.cpp
@@ -0,0 +1,15 @@
+//===--- utils/unittest/UnitTestMain/TestMain.cpp - unittest driver -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+int main(int argc, char **argv) {
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/contrib/llvm/utils/unittest/googletest/LICENSE.TXT b/contrib/llvm/utils/unittest/googletest/LICENSE.TXT
new file mode 100644
index 0000000..1941a11
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/LICENSE.TXT
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/contrib/llvm/utils/unittest/googletest/Makefile b/contrib/llvm/utils/unittest/googletest/Makefile
new file mode 100644
index 0000000..21b29ff
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/Makefile
@@ -0,0 +1,39 @@
+##===- utils/unittest/googletest/Makefile ------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL := ../../..
+
+include $(LEVEL)/Makefile.config
+
+LIBRARYNAME = GoogleTest
+BUILD_ARCHIVE = 1
+REQUIRES_RTTI = 1
+
+# Note that these flags are duplicated when building individual tests in
+# unittests/Makefile.unittest and ../UnitTestMain/Makefile; ensure that any
+# changes are made to both.
+CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include
+CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS)
+CPP.Flags += -DGTEST_HAS_RTTI=0
+# libstdc++'s TR1 <tuple> header depends on RTTI and uses C++'0x features not
+# supported by Clang, so force googletest to use its own tuple implementation.
+CPP.Flags += -DGTEST_USE_OWN_TR1_TUPLE
+
+# Disable pthreads if LLVM was configured without them.
+ifneq ($(HAVE_PTHREAD), 1)
+ CPP.Flags += -DGTEST_HAS_PTHREAD=0
+endif
+
+ifeq ($(HOST_OS),MingW)
+ CPP.Flags += -DGTEST_OS_WINDOWS=1
+endif
+
+NO_INSTALL = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/contrib/llvm/utils/unittest/googletest/README.LLVM b/contrib/llvm/utils/unittest/googletest/README.LLVM
new file mode 100644
index 0000000..d6e6f98
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/README.LLVM
@@ -0,0 +1,31 @@
+LLVM notes
+----------
+
+This directory contains Google Test 1.5.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 -f `find . -name \*\.pump`
+
+# Move all the source files to the current directory
+$ mv src/* .
+$ rmdir src
+
+# Move extra headers into the already-existing internal headers dir
+$ mv *.h include/gtest/internal/
+
+# Update paths to the included files
+$ perl -pi -e 's|^#include "src/|#include "gtest/internal/|' *.cc
+
+$ mv COPYING LICENSE.TXT
+
+
+Modified as follows:
+* To GTestStreamToHelper in include/gtest/internal/gtest-internal.h,
+ added the ability to stream with raw_os_ostream.
+* To refresh Haiku support in include/gtest/internal/gtest-port.h,
+ see http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20100621/102898.html
diff --git a/contrib/llvm/utils/unittest/googletest/gtest-death-test.cc b/contrib/llvm/utils/unittest/googletest/gtest-death-test.cc
new file mode 100644
index 0000000..e4199de
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/gtest-death-test.cc
@@ -0,0 +1,1172 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
+//
+// This file implements death tests.
+
+#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
+
+#endif // GTEST_HAS_DEATH_TEST
+
+#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
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "gtest/internal/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+// Constants.
+
+// The default death test style.
+static const char kDefaultDeathTestStyle[] = "fast";
+
+GTEST_DEFINE_string_(
+ death_test_style,
+ internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
+ "Indicates how to run a death test in a forked child process: "
+ "\"threadsafe\" (child process re-executes the test binary "
+ "from the beginning, running only the specific death test) or "
+ "\"fast\" (child process runs the death test immediately "
+ "after forking).");
+
+GTEST_DEFINE_bool_(
+ death_test_use_fork,
+ internal::BoolFromGTestEnv("death_test_use_fork", false),
+ "Instructs to use fork()/_exit() instead of clone() in death tests. "
+ "Ignored and always uses fork() on POSIX systems where clone() is not "
+ "implemented. Useful when running under valgrind or similar tools if "
+ "those do not support clone(). Valgrind 3.3.1 will just fail if "
+ "it sees an unsupported combination of clone() flags. "
+ "It is not recommended to use this flag w/o valgrind though it will "
+ "work in 99% of the cases. Once valgrind is fixed, this flag will "
+ "most likely be removed.");
+
+namespace internal {
+GTEST_DEFINE_string_(
+ internal_run_death_test, "",
+ "Indicates the file, line number, temporal index of "
+ "the single death test to run, and a file descriptor to "
+ "which a success code may be sent, all separated by "
+ "colons. This flag is specified if and only if the current "
+ "process is a sub-process launched for running a thread-safe "
+ "death test. FOR INTERNAL USE ONLY.");
+} // namespace internal
+
+#if GTEST_HAS_DEATH_TEST
+
+// ExitedWithCode constructor.
+ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
+}
+
+// ExitedWithCode function-call operator.
+bool ExitedWithCode::operator()(int exit_status) const {
+#if GTEST_OS_WINDOWS
+ return exit_status == exit_code_;
+#else
+ return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
+#endif // GTEST_OS_WINDOWS
+}
+
+#if !GTEST_OS_WINDOWS
+// KilledBySignal constructor.
+KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
+}
+
+// KilledBySignal function-call operator.
+bool KilledBySignal::operator()(int exit_status) const {
+ return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
+}
+#endif // !GTEST_OS_WINDOWS
+
+namespace internal {
+
+// Utilities needed for death tests.
+
+// Generates a textual description of a given exit code, in the format
+// specified by wait(2).
+static String ExitSummary(int exit_code) {
+ Message m;
+#if GTEST_OS_WINDOWS
+ m << "Exited with exit status " << exit_code;
+#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
+ if (WCOREDUMP(exit_code)) {
+ m << " (core dumped)";
+ }
+#endif
+#endif // GTEST_OS_WINDOWS
+ return m.GetString();
+}
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+bool ExitedUnsuccessfully(int exit_status) {
+ return !ExitedWithCode(0)(exit_status);
+}
+
+#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
+// caller not to pass a thread_count of 1.
+static String DeathTestThreadWarning(size_t thread_count) {
+ Message msg;
+ msg << "Death tests use fork(), which is unsafe particularly"
+ << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
+ if (thread_count == 0)
+ msg << "couldn't detect the number of threads.";
+ else
+ msg << "detected " << thread_count << " threads.";
+ return msg.GetString();
+}
+#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 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 };
+
+// Routine for aborting the program which is safe to call from an
+// exec-style death test child process, in which case the error
+// message is propagated back to the parent process. Otherwise, the
+// message is simply printed to stderr. In either case, the program
+// then exits with status 1.
+void DeathTestAbort(const String& message) {
+ // On a POSIX system, this function may be called from a threadsafe-style
+ // death test child process, which operates on a very small stack. Use
+ // the heap for any additional non-minuscule memory requirements.
+ const InternalRunDeathTestFlag* const flag =
+ GetUnitTestImpl()->internal_run_death_test_flag();
+ if (flag != NULL) {
+ FILE* parent = posix::FDOpen(flag->write_fd(), "w");
+ fputc(kDeathTestInternalError, parent);
+ fprintf(parent, "%s", message.c_str());
+ fflush(parent);
+ _exit(1);
+ } else {
+ fprintf(stderr, "%s", message.c_str());
+ fflush(stderr);
+ abort();
+ }
+}
+
+// A replacement for CHECK that calls DeathTestAbort if the assertion
+// fails.
+#define GTEST_DEATH_TEST_CHECK_(expression) \
+ do { \
+ if (!::testing::internal::IsTrue(expression)) { \
+ DeathTestAbort(::testing::internal::String::Format( \
+ "CHECK failed: File %s, line %d: %s", \
+ __FILE__, __LINE__, #expression)); \
+ } \
+ } while (::testing::internal::AlwaysFalse())
+
+// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
+// evaluating any system call that fulfills two conditions: it must return
+// -1 on failure, and set errno to EINTR when it is interrupted and
+// should be tried again. The macro expands to a loop that repeatedly
+// 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) \
+ do { \
+ int gtest_retval; \
+ do { \
+ gtest_retval = (expression); \
+ } while (gtest_retval == -1 && errno == EINTR); \
+ if (gtest_retval == -1) { \
+ DeathTestAbort(::testing::internal::String::Format( \
+ "CHECK failed: File %s, line %d: %s != -1", \
+ __FILE__, __LINE__, #expression)); \
+ } \
+ } while (::testing::internal::AlwaysFalse())
+
+// Returns the message describing the last system error in errno.
+String GetLastErrnoDescription() {
+ return String(errno == 0 ? "" : posix::StrError(errno));
+}
+
+// This is called from a death test parent process to read a failure
+// message from the death test child process and log it with the FATAL
+// severity. On Windows, the message is read from a pipe handle. On other
+// platforms, it is read from a file descriptor.
+static void FailFromInternalError(int fd) {
+ Message error;
+ char buffer[256];
+ int num_read;
+
+ do {
+ while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
+ buffer[num_read] = '\0';
+ error << buffer;
+ }
+ } while (num_read == -1 && errno == EINTR);
+
+ if (num_read == 0) {
+ GTEST_LOG_(FATAL) << error.GetString();
+ } else {
+ const int last_error = errno;
+ GTEST_LOG_(FATAL) << "Error while reading death test internal: "
+ << GetLastErrnoDescription() << " [" << last_error << "]";
+ }
+}
+
+// Death test constructor. Increments the running death test count
+// for the current test.
+DeathTest::DeathTest() {
+ TestInfo* const info = GetUnitTestImpl()->current_test_info();
+ if (info == NULL) {
+ DeathTestAbort("Cannot run a death test outside of a TEST or "
+ "TEST_F construct");
+ }
+}
+
+// Creates and returns a death test by dispatching to the current
+// death test factory.
+bool DeathTest::Create(const char* statement, const RE* regex,
+ const char* file, int line, DeathTest** test) {
+ return GetUnitTestImpl()->death_test_factory()->Create(
+ statement, regex, file, line, test);
+}
+
+const char* DeathTest::LastMessage() {
+ return last_death_test_message_.c_str();
+}
+
+void DeathTest::set_last_death_test_message(const String& message) {
+ last_death_test_message_ = message;
+}
+
+String DeathTest::last_death_test_message_;
+
+// Provides cross platform implementation for some death functionality.
+class DeathTestImpl : public DeathTest {
+ protected:
+ DeathTestImpl(const char* a_statement, const RE* a_regex)
+ : statement_(a_statement),
+ regex_(a_regex),
+ spawned_(false),
+ status_(-1),
+ outcome_(IN_PROGRESS),
+ read_fd_(-1),
+ write_fd_(-1) {}
+
+ // read_fd_ is expected to be closed and cleared by a derived class.
+ ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+
+ void Abort(AbortReason reason);
+ virtual bool Passed(bool status_ok);
+
+ const char* statement() const { return statement_; }
+ const RE* regex() const { return regex_; }
+ bool spawned() const { return spawned_; }
+ void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
+ int status() const { return status_; }
+ void set_status(int a_status) { status_ = a_status; }
+ DeathTestOutcome outcome() const { return outcome_; }
+ void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
+ int read_fd() const { return read_fd_; }
+ void set_read_fd(int fd) { read_fd_ = fd; }
+ int write_fd() const { return write_fd_; }
+ void set_write_fd(int fd) { write_fd_ = fd; }
+
+ // Called in the parent process only. Reads the result code of the death
+ // test child process via a pipe, interprets it to set the outcome_
+ // member, and closes read_fd_. Outputs diagnostics and terminates in
+ // case of unexpected codes.
+ void ReadAndInterpretStatusByte();
+
+ private:
+ // The textual content of the code this object is testing. This class
+ // doesn't own this string and should not attempt to delete it.
+ const char* const statement_;
+ // The regular expression which test output must match. DeathTestImpl
+ // doesn't own this object and should not attempt to delete it.
+ const RE* const regex_;
+ // True if the death test child process has been successfully spawned.
+ bool spawned_;
+ // The exit status of the child process.
+ int status_;
+ // How the death test concluded.
+ DeathTestOutcome outcome_;
+ // Descriptor to the read end of the pipe to the child process. It is
+ // always -1 in the child process. The child keeps its write end of the
+ // pipe in write_fd_.
+ int read_fd_;
+ // Descriptor to the child's write end of the pipe to the parent process.
+ // It is always -1 in the parent process. The parent keeps its end of the
+ // pipe in read_fd_.
+ int write_fd_;
+};
+
+// Called in the parent process only. Reads the result code of the death
+// test child process via a pipe, interprets it to set the outcome_
+// member, and closes read_fd_. Outputs diagnostics and terminates in
+// case of unexpected codes.
+void DeathTestImpl::ReadAndInterpretStatusByte() {
+ char flag;
+ int bytes_read;
+
+ // The read() here blocks until data is available (signifying the
+ // failure of the death test) or until the pipe is closed (signifying
+ // its success), so it's okay to call this in the parent before
+ // the child process has exited.
+ do {
+ bytes_read = posix::Read(read_fd(), &flag, 1);
+ } while (bytes_read == -1 && errno == EINTR);
+
+ if (bytes_read == 0) {
+ set_outcome(DIED);
+ } else if (bytes_read == 1) {
+ switch (flag) {
+ case kDeathTestReturned:
+ set_outcome(RETURNED);
+ break;
+ case kDeathTestLived:
+ set_outcome(LIVED);
+ break;
+ case kDeathTestInternalError:
+ FailFromInternalError(read_fd()); // Does not return.
+ break;
+ default:
+ GTEST_LOG_(FATAL) << "Death test child process reported "
+ << "unexpected status byte ("
+ << static_cast<unsigned int>(flag) << ")";
+ }
+ } else {
+ GTEST_LOG_(FATAL) << "Read from death test child process failed: "
+ << GetLastErrnoDescription();
+ }
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
+ set_read_fd(-1);
+}
+
+// Signals that the death test code which should have exited, didn't.
+// Should be called only in a death test child process.
+// Writes a status byte to the child's status file descriptor, then
+// calls _exit(1).
+void DeathTestImpl::Abort(AbortReason reason) {
+ // The parent process considers the death test to be a failure if
+ // 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;
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(write_fd()));
+ _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash)
+}
+
+// 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.
+// 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
+// of the exception that terminated the program.
+// regex: A regular expression object to be applied to
+// the test's captured standard error output; the death test
+// fails if it does not match.
+//
+// Argument:
+// status_ok: true if exit_status is acceptable in the context of
+// this particular death test, which fails if it is false
+//
+// Returns true iff all of the above conditions are met. Otherwise, the
+// first failing condition, in the order given above, is the one that is
+// reported. Also sets the last death test message string.
+bool DeathTestImpl::Passed(bool status_ok) {
+ if (!spawned())
+ return false;
+
+ const String error_message = GetCapturedStderr();
+
+ bool success = false;
+ Message buffer;
+
+ buffer << "Death test: " << statement() << "\n";
+ switch (outcome()) {
+ case LIVED:
+ buffer << " Result: failed to die.\n"
+ << " Error msg: " << error_message;
+ break;
+ case RETURNED:
+ buffer << " Result: illegal return in test statement.\n"
+ << " Error msg: " << error_message;
+ break;
+ case DIED:
+ if (status_ok) {
+ const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
+ if (matched) {
+ success = true;
+ } else {
+ buffer << " Result: died but not with expected error.\n"
+ << " Expected: " << regex()->pattern() << "\n"
+ << "Actual msg: " << error_message;
+ }
+ } else {
+ buffer << " Result: died but not with expected exit code:\n"
+ << " " << ExitSummary(status()) << "\n";
+ }
+ break;
+ case IN_PROGRESS:
+ default:
+ GTEST_LOG_(FATAL)
+ << "DeathTest::Passed somehow called before conclusion of test";
+ }
+
+ DeathTest::set_last_death_test_message(buffer.GetString());
+ return success;
+}
+
+#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
+// --gtest_death_test_style=fast setting to be equivalent to
+// --gtest_death_test_style=threadsafe there.
+//
+// A few implementation notes: Like the Linux version, the Windows
+// implementation uses pipes for child-to-parent communication. But due to
+// the specifics of pipes on Windows, some extra steps are required:
+//
+// 1. The parent creates a communication pipe and stores handles to both
+// ends of it.
+// 2. The parent starts the child and provides it with the information
+// necessary to acquire the handle to the write end of the pipe.
+// 3. The child acquires the write end of the pipe and signals the parent
+// using a Windows event.
+// 4. Now the parent can release the write end of the pipe on its side. If
+// this is done before step 3, the object's reference count goes down to
+// 0 and it is destroyed, preventing the child from acquiring it. The
+// parent now has to release it, or read operations on the read end of
+// the pipe will not return when the child terminates.
+// 5. The parent reads child's output through the pipe (outcome code and
+// any possible error messages) from the pipe, and its stderr and then
+// determines whether to fail the test.
+//
+// Note: to distinguish Win32 API calls from the local method and function
+// calls, the former are explicitly resolved in the global namespace.
+//
+class WindowsDeathTest : public DeathTestImpl {
+ public:
+ WindowsDeathTest(const char* statement,
+ const RE* regex,
+ const char* file,
+ int line)
+ : DeathTestImpl(statement, regex), file_(file), line_(line) {}
+
+ // All of these virtual functions are inherited from DeathTest.
+ virtual int Wait();
+ virtual TestRole AssumeRole();
+
+ private:
+ // The name of the file in which the death test is located.
+ const char* const file_;
+ // The line number on which the death test is located.
+ const int line_;
+ // Handle to the write end of the pipe to the child process.
+ AutoHandle write_handle_;
+ // Child process handle.
+ AutoHandle child_handle_;
+ // Event the child process uses to signal the parent that it has
+ // acquired the handle to the write end of the pipe. After seeing this
+ // event the parent can release its own handles to make sure its
+ // ReadFile() calls return when the child terminates.
+ AutoHandle event_handle_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists. As a side effect, sets the
+// outcome data member.
+int WindowsDeathTest::Wait() {
+ if (!spawned())
+ return 0;
+
+ // Wait until the child either signals that it has acquired the write end
+ // of the pipe or it dies.
+ const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
+ switch (::WaitForMultipleObjects(2,
+ wait_handles,
+ FALSE, // Waits for any of the handles.
+ INFINITE)) {
+ case WAIT_OBJECT_0:
+ case WAIT_OBJECT_0 + 1:
+ break;
+ default:
+ GTEST_DEATH_TEST_CHECK_(false); // Should not get here.
+ }
+
+ // The child has acquired the write end of the pipe or exited.
+ // We release the handle on our side and continue.
+ write_handle_.Reset();
+ event_handle_.Reset();
+
+ ReadAndInterpretStatusByte();
+
+ // Waits for the child process to exit if it haven't already. This
+ // returns immediately if the child has already exited, regardless of
+ // whether previous calls to WaitForMultipleObjects synchronized on this
+ // handle or not.
+ GTEST_DEATH_TEST_CHECK_(
+ WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
+ INFINITE));
+ DWORD status;
+ GTEST_DEATH_TEST_CHECK_(::GetExitCodeProcess(child_handle_.Get(), &status)
+ != FALSE);
+ child_handle_.Reset();
+ set_status(static_cast<int>(status));
+ return this->status();
+}
+
+// The AssumeRole process for a Windows death test. It creates a child
+// process with the same executable as the current process to run the
+// death test. The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole WindowsDeathTest::AssumeRole() {
+ const UnitTestImpl* const impl = GetUnitTestImpl();
+ const InternalRunDeathTestFlag* const flag =
+ impl->internal_run_death_test_flag();
+ const TestInfo* const info = impl->current_test_info();
+ const int death_test_index = info->result()->death_test_count();
+
+ if (flag != NULL) {
+ // ParseInternalRunDeathTestFlag() has performed all the necessary
+ // processing.
+ set_write_fd(flag->write_fd());
+ return EXECUTE_TEST;
+ }
+
+ // WindowsDeathTest uses an anonymous pipe to communicate results of
+ // a death test.
+ SECURITY_ATTRIBUTES handles_are_inheritable = {
+ sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+ HANDLE read_handle, write_handle;
+ GTEST_DEATH_TEST_CHECK_(
+ ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
+ 0) // Default buffer size.
+ != FALSE);
+ set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
+ O_RDONLY));
+ write_handle_.Reset(write_handle);
+ event_handle_.Reset(::CreateEvent(
+ &handles_are_inheritable,
+ TRUE, // The event will automatically reset to non-signaled state.
+ FALSE, // The initial state is non-signalled.
+ NULL)); // The even is unnamed.
+ GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
+ const String filter_flag = String::Format("--%s%s=%s.%s",
+ GTEST_FLAG_PREFIX_, kFilterFlag,
+ info->test_case_name(),
+ info->name());
+ const String internal_flag = String::Format(
+ "--%s%s=%s|%d|%d|%u|%Iu|%Iu",
+ GTEST_FLAG_PREFIX_,
+ kInternalRunDeathTestFlag,
+ file_, line_,
+ death_test_index,
+ static_cast<unsigned int>(::GetCurrentProcessId()),
+ // size_t has the same with as pointers on both 32-bit and 64-bit
+ // Windows platforms.
+ // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
+ reinterpret_cast<size_t>(write_handle),
+ reinterpret_cast<size_t>(event_handle_.Get()));
+
+ char executable_path[_MAX_PATH + 1]; // NOLINT
+ GTEST_DEATH_TEST_CHECK_(
+ _MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
+ executable_path,
+ _MAX_PATH));
+
+ String command_line = String::Format("%s %s \"%s\"",
+ ::GetCommandLineA(),
+ filter_flag.c_str(),
+ internal_flag.c_str());
+
+ DeathTest::set_last_death_test_message("");
+
+ CaptureStderr();
+ // Flush the log buffers since the log streams are shared with the child.
+ FlushInfoLog();
+
+ // The child process will share the standard handles with the parent.
+ STARTUPINFOA startup_info;
+ memset(&startup_info, 0, sizeof(STARTUPINFO));
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+ startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+ startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+ startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+
+ PROCESS_INFORMATION process_info;
+ GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
+ executable_path,
+ const_cast<char*>(command_line.c_str()),
+ NULL, // Retuned process handle is not inheritable.
+ NULL, // Retuned thread handle is not inheritable.
+ TRUE, // Child inherits all inheritable handles (for write_handle_).
+ 0x0, // Default creation flags.
+ NULL, // Inherit the parent's environment.
+ UnitTest::GetInstance()->original_working_dir(),
+ &startup_info,
+ &process_info) != FALSE);
+ child_handle_.Reset(process_info.hProcess);
+ ::CloseHandle(process_info.hThread);
+ set_spawned(true);
+ return OVERSEE_TEST;
+}
+#else // We are not on Windows.
+
+// ForkingDeathTest provides implementations for most of the abstract
+// methods of the DeathTest interface. Only the AssumeRole method is
+// left undefined.
+class ForkingDeathTest : public DeathTestImpl {
+ public:
+ ForkingDeathTest(const char* statement, const RE* regex);
+
+ // All of these virtual functions are inherited from DeathTest.
+ virtual int Wait();
+
+ protected:
+ void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
+
+ private:
+ // PID of child process during death test; 0 in the child process itself.
+ pid_t child_pid_;
+};
+
+// Constructs a ForkingDeathTest.
+ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
+ : DeathTestImpl(a_statement, a_regex),
+ child_pid_(-1) {}
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists. As a side effect, sets the
+// outcome data member.
+int ForkingDeathTest::Wait() {
+ if (!spawned())
+ return 0;
+
+ ReadAndInterpretStatusByte();
+
+ int status_value;
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
+ set_status(status_value);
+ return status_value;
+}
+
+// A concrete death test class that forks, then immediately runs the test
+// in the child process.
+class NoExecDeathTest : public ForkingDeathTest {
+ public:
+ NoExecDeathTest(const char* a_statement, const RE* a_regex) :
+ ForkingDeathTest(a_statement, a_regex) { }
+ virtual TestRole AssumeRole();
+};
+
+// The AssumeRole process for a fork-and-run death test. It implements a
+// straightforward fork, with a simple pipe to transmit the status byte.
+DeathTest::TestRole NoExecDeathTest::AssumeRole() {
+ const size_t thread_count = GetThreadCount();
+ if (thread_count != 1) {
+ GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
+ }
+
+ int pipe_fd[2];
+ GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+
+ DeathTest::set_last_death_test_message("");
+ CaptureStderr();
+ // When we fork the process below, the log file buffers are copied, but the
+ // file descriptors are shared. We flush all log files here so that closing
+ // the file descriptors in the child process doesn't throw off the
+ // synchronization between descriptors and buffers in the parent process.
+ // This is as close to the fork as possible to avoid a race condition in case
+ // there are multiple threads running before the death test, and another
+ // thread writes to the log file.
+ FlushInfoLog();
+
+ const pid_t child_pid = fork();
+ GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+ set_child_pid(child_pid);
+ if (child_pid == 0) {
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
+ set_write_fd(pipe_fd[1]);
+ // Redirects all logging to stderr in the child process to prevent
+ // concurrent writes to the log files. We capture stderr in the parent
+ // process and append the child process' output to a log.
+ LogToStderr();
+ // Event forwarding to the listeners of event listener API mush be shut
+ // down in death test subprocesses.
+ GetUnitTestImpl()->listeners()->SuppressEventForwarding();
+ return EXECUTE_TEST;
+ } else {
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+ set_read_fd(pipe_fd[0]);
+ set_spawned(true);
+ return OVERSEE_TEST;
+ }
+}
+
+// A concrete death test class that forks and re-executes the main
+// program from the beginning, with command-line flags set that cause
+// only this specific death test to be run.
+class ExecDeathTest : public ForkingDeathTest {
+ public:
+ ExecDeathTest(const char* a_statement, const RE* a_regex,
+ const char* file, int line) :
+ ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
+ virtual TestRole AssumeRole();
+ private:
+ // The name of the file in which the death test is located.
+ const char* const file_;
+ // The line number on which the death test is located.
+ const int line_;
+};
+
+// Utility class for accumulating command-line arguments.
+class Arguments {
+ public:
+ Arguments() {
+ args_.push_back(NULL);
+ }
+
+ ~Arguments() {
+ for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
+ ++i) {
+ free(*i);
+ }
+ }
+ void AddArgument(const char* argument) {
+ args_.insert(args_.end() - 1, posix::StrDup(argument));
+ }
+
+ template <typename Str>
+ void AddArguments(const ::std::vector<Str>& arguments) {
+ for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
+ i != arguments.end();
+ ++i) {
+ args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
+ }
+ }
+ char* const* Argv() {
+ return &args_[0];
+ }
+ private:
+ std::vector<char*> args_;
+};
+
+// A struct that encompasses the arguments to the child process of a
+// threadsafe-style death test process.
+struct ExecDeathTestArgs {
+ char* const* argv; // Command-line arguments for the child's call to exec
+ int close_fd; // File descriptor to close; the read end of a pipe
+};
+
+#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
+// 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
+
+// The main function for a threadsafe-style death test child process.
+// This function is called in a clone()-ed process and thus must avoid
+// any potentially unsafe operations like malloc or libc functions.
+static int ExecDeathTestChildMain(void* child_arg) {
+ ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
+
+ // We need to execute the test program in the same environment where
+ // it was originally invoked. Therefore we change to the original
+ // working directory first.
+ const char* const original_dir =
+ UnitTest::GetInstance()->original_working_dir();
+ // We can safely call chdir() as it's a direct system call.
+ if (chdir(original_dir) != 0) {
+ DeathTestAbort(String::Format("chdir(\"%s\") failed: %s",
+ original_dir,
+ GetLastErrnoDescription().c_str()));
+ return EXIT_FAILURE;
+ }
+
+ // We can safely call execve() as it's a direct system call. We
+ // cannot use execvp() as it's a libc function and thus potentially
+ // unsafe. Since execve() doesn't search the PATH, the user must
+ // invoke the test program via a valid path that contains at least
+ // one path separator.
+ execve(args->argv[0], args->argv, GetEnviron());
+ DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s",
+ args->argv[0],
+ original_dir,
+ GetLastErrnoDescription().c_str()));
+ return EXIT_FAILURE;
+}
+
+// Two utility routines that together determine the direction the stack
+// grows.
+// 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.
+bool StackLowerThanAddress(const void* ptr) {
+ int dummy;
+ return &dummy < ptr;
+}
+
+bool StackGrowsDown() {
+ int dummy;
+ return StackLowerThanAddress(&dummy);
+}
+
+// A threadsafe implementation of fork(2) for threadsafe-style death tests
+// that uses clone(2). It dies with an error message if anything goes
+// wrong.
+static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
+ ExecDeathTestArgs args = { argv, close_fd };
+ pid_t child_pid = -1;
+
+#if GTEST_HAS_CLONE
+ const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+ if (!use_fork) {
+ static const bool stack_grows_down = StackGrowsDown();
+ const size_t stack_size = getpagesize();
+ // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+ void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+ void* const stack_top =
+ static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0);
+
+ child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+ GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+ }
+#else
+ const bool use_fork = true;
+#endif // GTEST_HAS_CLONE
+
+ if (use_fork && (child_pid = fork()) == 0) {
+ ExecDeathTestChildMain(&args);
+ _exit(0);
+ }
+
+ GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+ return child_pid;
+}
+
+// The AssumeRole process for a fork-and-exec death test. It re-executes the
+// main program from the beginning, setting the --gtest_filter
+// and --gtest_internal_run_death_test flags to cause only the current
+// death test to be re-run.
+DeathTest::TestRole ExecDeathTest::AssumeRole() {
+ const UnitTestImpl* const impl = GetUnitTestImpl();
+ const InternalRunDeathTestFlag* const flag =
+ impl->internal_run_death_test_flag();
+ const TestInfo* const info = impl->current_test_info();
+ const int death_test_index = info->result()->death_test_count();
+
+ if (flag != NULL) {
+ set_write_fd(flag->write_fd());
+ return EXECUTE_TEST;
+ }
+
+ int pipe_fd[2];
+ GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+ // Clear the close-on-exec flag on the write end of the pipe, lest
+ // it be closed when the child process does an exec:
+ GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
+
+ const String filter_flag =
+ String::Format("--%s%s=%s.%s",
+ GTEST_FLAG_PREFIX_, kFilterFlag,
+ info->test_case_name(), info->name());
+ const String internal_flag =
+ String::Format("--%s%s=%s|%d|%d|%d",
+ GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag,
+ file_, line_, death_test_index, pipe_fd[1]);
+ Arguments args;
+ args.AddArguments(GetArgvs());
+ args.AddArgument(filter_flag.c_str());
+ args.AddArgument(internal_flag.c_str());
+
+ DeathTest::set_last_death_test_message("");
+
+ CaptureStderr();
+ // See the comment in NoExecDeathTest::AssumeRole for why the next line
+ // is necessary.
+ FlushInfoLog();
+
+ const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]);
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+ set_child_pid(child_pid);
+ set_read_fd(pipe_fd[0]);
+ set_spawned(true);
+ return OVERSEE_TEST;
+}
+
+#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
+// by the "test" argument to its address. If the test should be
+// skipped, sets that pointer to NULL. Returns true, unless the
+// flag is set to an invalid value.
+bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
+ const char* file, int line,
+ DeathTest** test) {
+ UnitTestImpl* const impl = GetUnitTestImpl();
+ const InternalRunDeathTestFlag* const flag =
+ impl->internal_run_death_test_flag();
+ const int death_test_index = impl->current_test_info()
+ ->increment_death_test_count();
+
+ if (flag != NULL) {
+ if (death_test_index > flag->index()) {
+ DeathTest::set_last_death_test_message(String::Format(
+ "Death test count (%d) somehow exceeded expected maximum (%d)",
+ death_test_index, flag->index()));
+ return false;
+ }
+
+ if (!(flag->file() == file && flag->line() == line &&
+ flag->index() == death_test_index)) {
+ *test = NULL;
+ return true;
+ }
+ }
+
+#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
+ 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
+ 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",
+ GTEST_FLAG(death_test_style).c_str()));
+ return false;
+ }
+
+ return true;
+}
+
+// Splits a given string on a given delimiter, populating a given
+// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have
+// ::std::string, so we can use it here.
+static void SplitString(const ::std::string& str, char delimiter,
+ ::std::vector< ::std::string>* dest) {
+ ::std::vector< ::std::string> parsed;
+ ::std::string::size_type pos = 0;
+ while (::testing::internal::AlwaysTrue()) {
+ const ::std::string::size_type colon = str.find(delimiter, pos);
+ if (colon == ::std::string::npos) {
+ parsed.push_back(str.substr(pos));
+ break;
+ } else {
+ parsed.push_back(str.substr(pos, colon - pos));
+ pos = colon + 1;
+ }
+ }
+ dest->swap(parsed);
+}
+
+#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.
+int GetStatusFileDescriptor(unsigned int parent_process_id,
+ size_t write_handle_as_size_t,
+ size_t event_handle_as_size_t) {
+ AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
+ FALSE, // Non-inheritable.
+ parent_process_id));
+ if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
+ DeathTestAbort(String::Format("Unable to open parent process %u",
+ parent_process_id));
+ }
+
+ // TODO(vladl@google.com): Replace the following check with a
+ // compile-time assertion when available.
+ GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
+
+ const HANDLE write_handle =
+ reinterpret_cast<HANDLE>(write_handle_as_size_t);
+ HANDLE dup_write_handle;
+
+ // The newly initialized handle is accessible only in in the parent
+ // process. To obtain one accessible within the child, we need to use
+ // DuplicateHandle.
+ if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
+ ::GetCurrentProcess(), &dup_write_handle,
+ 0x0, // Requested privileges ignored since
+ // DUPLICATE_SAME_ACCESS is used.
+ FALSE, // Request non-inheritable handler.
+ DUPLICATE_SAME_ACCESS)) {
+ DeathTestAbort(String::Format(
+ "Unable to duplicate the pipe handle %Iu from the parent process %u",
+ write_handle_as_size_t, parent_process_id));
+ }
+
+ const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
+ HANDLE dup_event_handle;
+
+ if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
+ ::GetCurrentProcess(), &dup_event_handle,
+ 0x0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ DeathTestAbort(String::Format(
+ "Unable to duplicate the event handle %Iu from the parent process %u",
+ event_handle_as_size_t, parent_process_id));
+ }
+
+ const int write_fd =
+ ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
+ if (write_fd == -1) {
+ DeathTestAbort(String::Format(
+ "Unable to convert pipe handle %Iu to a file descriptor",
+ write_handle_as_size_t));
+ }
+
+ // Signals the parent that the write end of the pipe has been acquired
+ // so the parent can release its own write end.
+ ::SetEvent(dup_event_handle);
+
+ return write_fd;
+}
+#endif // GTEST_OS_WINDOWS
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
+ if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
+
+ // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
+ // can use it here.
+ int line = -1;
+ int index = -1;
+ ::std::vector< ::std::string> fields;
+ SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
+ int write_fd = -1;
+
+#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;
+
+ if (fields.size() != 6
+ || !ParseNaturalNumber(fields[1], &line)
+ || !ParseNaturalNumber(fields[2], &index)
+ || !ParseNaturalNumber(fields[3], &parent_process_id)
+ || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
+ || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
+ DeathTestAbort(String::Format(
+ "Bad --gtest_internal_run_death_test flag: %s",
+ GTEST_FLAG(internal_run_death_test).c_str()));
+ }
+ write_fd = GetStatusFileDescriptor(parent_process_id,
+ write_handle_as_size_t,
+ event_handle_as_size_t);
+#else
+ if (fields.size() != 4
+ || !ParseNaturalNumber(fields[1], &line)
+ || !ParseNaturalNumber(fields[2], &index)
+ || !ParseNaturalNumber(fields[3], &write_fd)) {
+ DeathTestAbort(String::Format(
+ "Bad --gtest_internal_run_death_test flag: %s",
+ GTEST_FLAG(internal_run_death_test).c_str()));
+ }
+#endif // GTEST_OS_WINDOWS
+ return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
+}
+
+} // namespace internal
+
+#endif // GTEST_HAS_DEATH_TEST
+
+} // namespace testing
diff --git a/contrib/llvm/utils/unittest/googletest/gtest-filepath.cc b/contrib/llvm/utils/unittest/googletest/gtest-filepath.cc
new file mode 100644
index 0000000..c1ef918
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/gtest-filepath.cc
@@ -0,0 +1,380 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+
+#include <gtest/internal/gtest-filepath.h>
+#include <gtest/internal/gtest-port.h>
+
+#include <stdlib.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+#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>
+#else
+#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
+#elif defined(PATH_MAX)
+#define GTEST_PATH_MAX_ PATH_MAX
+#elif defined(_XOPEN_PATH_MAX)
+#define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+#else
+#define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+#endif // GTEST_OS_WINDOWS
+
+#include <gtest/internal/gtest-string.h>
+
+namespace testing {
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+// On Windows, '\\' is the standard path separator, but many tools and the
+// Windows API also accept '/' as an alternate path separator. Unless otherwise
+// noted, a file path can contain either kind of path separators, or a mixture
+// of them.
+const char kPathSeparator = '\\';
+const char kAlternatePathSeparator = '/';
+const char kPathSeparatorString[] = "\\";
+const char kAlternatePathSeparatorString[] = "/";
+#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
+const char kCurrentDirectoryString[] = ".\\";
+#endif // GTEST_OS_WINDOWS_MOBILE
+#else
+const char kPathSeparator = '/';
+const char kPathSeparatorString[] = "/";
+const char kCurrentDirectoryString[] = "./";
+#endif // GTEST_OS_WINDOWS
+
+// Returns whether the given character is a valid path separator.
+static bool IsPathSeparator(char c) {
+#if GTEST_HAS_ALT_PATH_SEP_
+ return (c == kPathSeparator) || (c == kAlternatePathSeparator);
+#else
+ return c == kPathSeparator;
+#endif
+}
+
+// Returns the current working directory, or "" if unsuccessful.
+FilePath FilePath::GetCurrentDir() {
+#if GTEST_OS_WINDOWS_MOBILE
+ // Windows CE doesn't have a current directory, so we just return
+ // something reasonable.
+ return FilePath(kCurrentDirectoryString);
+#elif GTEST_OS_WINDOWS
+ char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+ return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#else
+ char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+ return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#endif // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns a copy of the FilePath with the case-insensitive extension removed.
+// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+// FilePath("dir/file"). If a case-insensitive extension is not
+// found, returns a copy of the original FilePath.
+FilePath FilePath::RemoveExtension(const char* extension) const {
+ String dot_extension(String::Format(".%s", extension));
+ if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) {
+ return FilePath(String(pathname_.c_str(), pathname_.length() - 4));
+ }
+ return *this;
+}
+
+// Returns a pointer to the last occurence of a valid path separator in
+// the FilePath. On Windows, for example, both '/' and '\' are valid path
+// separators. Returns NULL if no path separator was found.
+const char* FilePath::FindLastPathSeparator() const {
+ const char* const last_sep = strrchr(c_str(), kPathSeparator);
+#if GTEST_HAS_ALT_PATH_SEP_
+ const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
+ // Comparing two pointers of which only one is NULL is undefined.
+ if (last_alt_sep != NULL &&
+ (last_sep == NULL || last_alt_sep > last_sep)) {
+ return last_alt_sep;
+ }
+#endif
+ return last_sep;
+}
+
+// Returns a copy of the FilePath with the directory part removed.
+// Example: FilePath("path/to/file").RemoveDirectoryName() returns
+// FilePath("file"). If there is no directory part ("just_a_file"), it returns
+// the FilePath unmodified. If there is no file part ("just_a_dir/") it
+// returns an empty FilePath ("").
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveDirectoryName() const {
+ const char* const last_sep = FindLastPathSeparator();
+ return last_sep ? FilePath(String(last_sep + 1)) : *this;
+}
+
+// RemoveFileName returns the directory path with the filename removed.
+// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveFileName() const {
+ const char* const last_sep = FindLastPathSeparator();
+ String dir;
+ if (last_sep) {
+ dir = String(c_str(), last_sep + 1 - c_str());
+ } else {
+ dir = kCurrentDirectoryString;
+ }
+ return FilePath(dir);
+}
+
+// Helper functions for naming files in a directory for xml output.
+
+// Given directory = "dir", base_name = "test", number = 0,
+// extension = "xml", returns "dir/test.xml". If number is greater
+// than zero (e.g., 12), returns "dir/test_12.xml".
+// On Windows platform, uses \ as the separator rather than /.
+FilePath FilePath::MakeFileName(const FilePath& directory,
+ const FilePath& base_name,
+ int number,
+ const char* extension) {
+ String file;
+ if (number == 0) {
+ file = String::Format("%s.%s", base_name.c_str(), extension);
+ } else {
+ file = String::Format("%s_%d.%s", base_name.c_str(), number, extension);
+ }
+ return ConcatPaths(directory, FilePath(file));
+}
+
+// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
+// On Windows, uses \ as the separator rather than /.
+FilePath FilePath::ConcatPaths(const FilePath& directory,
+ const FilePath& relative_path) {
+ if (directory.IsEmpty())
+ return relative_path;
+ const FilePath dir(directory.RemoveTrailingPathSeparator());
+ return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator,
+ relative_path.c_str()));
+}
+
+// Returns true if pathname describes something findable in the file-system,
+// either a file, directory, or whatever.
+bool FilePath::FileOrDirectoryExists() const {
+#if GTEST_OS_WINDOWS_MOBILE
+ LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
+ const DWORD attributes = GetFileAttributes(unicode);
+ delete [] unicode;
+ return attributes != kInvalidFileAttributes;
+#else
+ posix::StatStruct file_stat;
+ return posix::Stat(pathname_.c_str(), &file_stat) == 0;
+#endif // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns true if pathname describes a directory in the file-system
+// that exists.
+bool FilePath::DirectoryExists() const {
+ bool result = false;
+#if GTEST_OS_WINDOWS
+ // Don't strip off trailing separator if path is a root directory on
+ // Windows (like "C:\\").
+ const FilePath& path(IsRootDirectory() ? *this :
+ RemoveTrailingPathSeparator());
+#else
+ const FilePath& path(*this);
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+ LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
+ const DWORD attributes = GetFileAttributes(unicode);
+ delete [] unicode;
+ if ((attributes != kInvalidFileAttributes) &&
+ (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ result = true;
+ }
+#else
+ posix::StatStruct file_stat;
+ result = posix::Stat(path.c_str(), &file_stat) == 0 &&
+ posix::IsDir(file_stat);
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+ return result;
+}
+
+// Returns true if pathname describes a root directory. (Windows has one
+// root directory per disk drive.)
+bool FilePath::IsRootDirectory() const {
+#if GTEST_OS_WINDOWS
+ // TODO(wan@google.com): on Windows a network share like
+ // \\server\share can be a root directory, although it cannot be the
+ // current directory. Handle this properly.
+ return pathname_.length() == 3 && IsAbsolutePath();
+#else
+ return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
+#endif
+}
+
+// Returns true if pathname describes an absolute path.
+bool FilePath::IsAbsolutePath() const {
+ const char* const name = pathname_.c_str();
+#if GTEST_OS_WINDOWS
+ return pathname_.length() >= 3 &&
+ ((name[0] >= 'a' && name[0] <= 'z') ||
+ (name[0] >= 'A' && name[0] <= 'Z')) &&
+ name[1] == ':' &&
+ IsPathSeparator(name[2]);
+#else
+ return IsPathSeparator(name[0]);
+#endif
+}
+
+// Returns a pathname for a file that does not currently exist. The pathname
+// will be directory/base_name.extension or
+// directory/base_name_<number>.extension if directory/base_name.extension
+// already exists. The number will be incremented until a pathname is found
+// that does not already exist.
+// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+// There could be a race condition if two or more processes are calling this
+// function at the same time -- they could both pick the same filename.
+FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
+ const FilePath& base_name,
+ const char* extension) {
+ FilePath full_pathname;
+ int number = 0;
+ do {
+ full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
+ } while (full_pathname.FileOrDirectoryExists());
+ return full_pathname;
+}
+
+// Returns true if FilePath ends with a path separator, which indicates that
+// it is intended to represent a directory. Returns false otherwise.
+// This does NOT check that a directory (or file) actually exists.
+bool FilePath::IsDirectory() const {
+ return !pathname_.empty() &&
+ IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
+}
+
+// Create directories so that path exists. Returns true if successful or if
+// the directories already exist; returns false if unable to create directories
+// for any reason.
+bool FilePath::CreateDirectoriesRecursively() const {
+ if (!this->IsDirectory()) {
+ return false;
+ }
+
+ if (pathname_.length() == 0 || this->DirectoryExists()) {
+ return true;
+ }
+
+ const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
+ return parent.CreateDirectoriesRecursively() && this->CreateFolder();
+}
+
+// Create the directory so that path exists. Returns true if successful or
+// if the directory already exists; returns false if unable to create the
+// directory for any reason, including if the parent directory does not
+// exist. Not named "CreateDirectory" because that's a macro on Windows.
+bool FilePath::CreateFolder() const {
+#if GTEST_OS_WINDOWS_MOBILE
+ FilePath removed_sep(this->RemoveTrailingPathSeparator());
+ LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
+ int result = CreateDirectory(unicode, NULL) ? 0 : -1;
+ delete [] unicode;
+#elif GTEST_OS_WINDOWS
+ int result = _mkdir(pathname_.c_str());
+#else
+ int result = mkdir(pathname_.c_str(), 0777);
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+ if (result == -1) {
+ return this->DirectoryExists(); // An error is OK if the directory exists.
+ }
+ return true; // No error.
+}
+
+// If input name has a trailing separator character, remove it and return the
+// name, otherwise return the name string unmodified.
+// On Windows platform, uses \ as the separator, other platforms use /.
+FilePath FilePath::RemoveTrailingPathSeparator() const {
+ return IsDirectory()
+ ? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
+ : *this;
+}
+
+// Removes any redundant separators that might be in the pathname.
+// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+// redundancies that might be in a pathname involving "." or "..".
+// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
+void FilePath::Normalize() {
+ if (pathname_.c_str() == NULL) {
+ pathname_ = "";
+ return;
+ }
+ const char* src = pathname_.c_str();
+ char* const dest = new char[pathname_.length() + 1];
+ char* dest_ptr = dest;
+ memset(dest_ptr, 0, pathname_.length() + 1);
+
+ while (*src != '\0') {
+ *dest_ptr = *src;
+ if (!IsPathSeparator(*src)) {
+ src++;
+ } else {
+#if GTEST_HAS_ALT_PATH_SEP_
+ if (*dest_ptr == kAlternatePathSeparator) {
+ *dest_ptr = kPathSeparator;
+ }
+#endif
+ while (IsPathSeparator(*src))
+ src++;
+ }
+ dest_ptr++;
+ }
+ *dest_ptr = '\0';
+ pathname_ = dest;
+ delete[] dest;
+}
+
+} // namespace internal
+} // namespace testing
diff --git a/contrib/llvm/utils/unittest/googletest/gtest-port.cc b/contrib/llvm/utils/unittest/googletest/gtest-port.cc
new file mode 100644
index 0000000..5609599
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/gtest-port.cc
@@ -0,0 +1,711 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include <gtest/internal/gtest-port.h>
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+#include <windows.h> // For TerminateProcess()
+#elif GTEST_OS_WINDOWS
+#include <io.h>
+#include <sys/stat.h>
+#else
+#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>
+#endif // GTEST_OS_MAC
+
+#include <gtest/gtest-spi.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
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "gtest/internal/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
+const int kStdOutFileno = 1;
+const int kStdErrFileno = 2;
+#else
+const int kStdOutFileno = STDOUT_FILENO;
+const int kStdErrFileno = STDERR_FILENO;
+#endif // _MSC_VER
+
+#if GTEST_OS_MAC
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+ const task_t task = mach_task_self();
+ mach_msg_type_number_t thread_count;
+ thread_act_array_t thread_list;
+ const kern_return_t status = task_threads(task, &thread_list, &thread_count);
+ if (status == KERN_SUCCESS) {
+ // task_threads allocates resources in thread_list and we need to free them
+ // to avoid leaks.
+ vm_deallocate(task,
+ reinterpret_cast<vm_address_t>(thread_list),
+ sizeof(thread_t) * thread_count);
+ return static_cast<size_t>(thread_count);
+ } else {
+ return 0;
+ }
+}
+
+#else
+
+size_t GetThreadCount() {
+ // There's no portable way to detect the number of threads, so we just
+ // return 0 to indicate that we cannot detect it.
+ return 0;
+}
+
+#endif // GTEST_OS_MAC
+
+#if GTEST_USES_POSIX_RE
+
+// Implements RE. Currently only needed for death tests.
+
+RE::~RE() {
+ if (is_valid_) {
+ // regfree'ing an invalid regex might crash because the content
+ // of the regex is undefined. Since the regex's are essentially
+ // the same, one cannot be valid (or invalid) without the other
+ // being so too.
+ regfree(&partial_regex_);
+ regfree(&full_regex_);
+ }
+ free(const_cast<char*>(pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+ if (!re.is_valid_) return false;
+
+ regmatch_t match;
+ return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+ if (!re.is_valid_) return false;
+
+ regmatch_t match;
+ return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+ pattern_ = posix::StrDup(regex);
+
+ // Reserves enough bytes to hold the regular expression used for a
+ // full match.
+ const size_t full_regex_len = strlen(regex) + 10;
+ char* const full_pattern = new char[full_regex_len];
+
+ snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
+ is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
+ // We want to call regcomp(&partial_regex_, ...) even if the
+ // previous expression returns false. Otherwise partial_regex_ may
+ // not be properly initialized can may cause trouble when it's
+ // freed.
+ //
+ // Some implementation of POSIX regex (e.g. on at least some
+ // versions of Cygwin) doesn't accept the empty string as a valid
+ // regex. We change it to an equivalent form "()" to be safe.
+ if (is_valid_) {
+ const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+ is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+ }
+ EXPECT_TRUE(is_valid_)
+ << "Regular expression \"" << regex
+ << "\" is not a valid POSIX Extended regular expression.";
+
+ delete[] full_pattern;
+}
+
+#elif GTEST_USES_SIMPLE_RE
+
+// Returns true iff ch appears anywhere in str (excluding the
+// terminating '\0' character).
+bool IsInSet(char ch, const char* str) {
+ return ch != '\0' && strchr(str, ch) != NULL;
+}
+
+// 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) {
+ 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) {
+ 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"));
+}
+
+// Returns true iff the given atom (specified by escaped and pattern)
+// matches ch. The result is undefined if the atom is invalid.
+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 '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 't': return ch == '\t';
+ case 'v': return ch == '\v';
+ case 'w': return IsWordChar(ch);
+ case 'W': return !IsWordChar(ch);
+ }
+ return IsPunct(pattern_char) && pattern_char == ch;
+ }
+
+ return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
+}
+
+// Helper function used by ValidateRegex() to format error messages.
+String FormatRegexSyntaxError(const char* regex, int index) {
+ return (Message() << "Syntax error at index " << index
+ << " in simple regular expression \"" << regex << "\": ").GetString();
+}
+
+// Generates non-fatal failures and returns false if regex is invalid;
+// otherwise returns true.
+bool ValidateRegex(const char* regex) {
+ if (regex == NULL) {
+ // TODO(wan@google.com): fix the source file location in the
+ // assertion failures to match where the regex is used in user
+ // code.
+ ADD_FAILURE() << "NULL is not a valid simple regular expression.";
+ return false;
+ }
+
+ bool is_valid = true;
+
+ // True iff ?, *, or + can follow the previous atom.
+ bool prev_repeatable = false;
+ for (int i = 0; regex[i]; i++) {
+ if (regex[i] == '\\') { // An escape sequence
+ i++;
+ if (regex[i] == '\0') {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+ << "'\\' cannot appear at the end.";
+ return false;
+ }
+
+ if (!IsValidEscape(regex[i])) {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+ << "invalid escape sequence \"\\" << regex[i] << "\".";
+ is_valid = false;
+ }
+ prev_repeatable = true;
+ } else { // Not an escape sequence.
+ const char ch = regex[i];
+
+ if (ch == '^' && i > 0) {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+ << "'^' can only appear at the beginning.";
+ is_valid = false;
+ } else if (ch == '$' && regex[i + 1] != '\0') {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+ << "'$' can only appear at the end.";
+ is_valid = false;
+ } else if (IsInSet(ch, "()[]{}|")) {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+ << "'" << ch << "' is unsupported.";
+ is_valid = false;
+ } else if (IsRepeat(ch) && !prev_repeatable) {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+ << "'" << ch << "' can only follow a repeatable token.";
+ is_valid = false;
+ }
+
+ prev_repeatable = !IsInSet(ch, "^$?*+");
+ }
+ }
+
+ return is_valid;
+}
+
+// Matches a repeated regex atom followed by a valid simple regular
+// expression. The regex atom is defined as c if escaped is false,
+// or \c otherwise. repeat is the repetition meta character (?, *,
+// or +). The behavior is undefined if str contains too many
+// characters to be indexable by size_t, in which case the test will
+// probably time out anyway. We are fine with this limitation as
+// std::string has it too.
+bool MatchRepetitionAndRegexAtHead(
+ bool escaped, char c, char repeat, const char* regex,
+ const char* str) {
+ const size_t min_count = (repeat == '+') ? 1 : 0;
+ const size_t max_count = (repeat == '?') ? 1 :
+ static_cast<size_t>(-1) - 1;
+ // We cannot call numeric_limits::max() as it conflicts with the
+ // max() macro on Windows.
+
+ for (size_t i = 0; i <= max_count; ++i) {
+ // We know that the atom matches each of the first i characters in str.
+ if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
+ // We have enough matches at the head, and the tail matches too.
+ // Since we only care about *whether* the pattern matches str
+ // (as opposed to *how* it matches), there is no need to find a
+ // greedy match.
+ return true;
+ }
+ if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
+ return false;
+ }
+ return false;
+}
+
+// Returns true iff regex matches a prefix of str. regex must be a
+// valid simple regular expression and not start with "^", or the
+// result is undefined.
+bool MatchRegexAtHead(const char* regex, const char* str) {
+ if (*regex == '\0') // An empty regex matches a prefix of anything.
+ return true;
+
+ // "$" only matches the end of a string. Note that regex being
+ // valid guarantees that there's nothing after "$" in it.
+ if (*regex == '$')
+ return *str == '\0';
+
+ // Is the first thing in regex an escape sequence?
+ const bool escaped = *regex == '\\';
+ if (escaped)
+ ++regex;
+ if (IsRepeat(regex[1])) {
+ // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
+ // here's an indirect recursion. It terminates as the regex gets
+ // shorter in each recursion.
+ return MatchRepetitionAndRegexAtHead(
+ escaped, regex[0], regex[1], regex + 2, str);
+ } else {
+ // regex isn't empty, isn't "$", and doesn't start with a
+ // repetition. We match the first atom of regex with the first
+ // character of str and recurse.
+ return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
+ MatchRegexAtHead(regex + 1, str + 1);
+ }
+}
+
+// Returns true iff regex matches any substring of str. regex must be
+// a valid simple regular expression, or the result is undefined.
+//
+// The algorithm is recursive, but the recursion depth doesn't exceed
+// the regex length, so we won't need to worry about running out of
+// stack space normally. In rare cases the time complexity can be
+// exponential with respect to the regex length + the string length,
+// but usually it's must faster (often close to linear).
+bool MatchRegexAnywhere(const char* regex, const char* str) {
+ if (regex == NULL || str == NULL)
+ return false;
+
+ if (*regex == '^')
+ return MatchRegexAtHead(regex + 1, str);
+
+ // A successful match can be anywhere in str.
+ do {
+ if (MatchRegexAtHead(regex, str))
+ return true;
+ } while (*str++ != '\0');
+ return false;
+}
+
+// Implements the RE class.
+
+RE::~RE() {
+ free(const_cast<char*>(pattern_));
+ free(const_cast<char*>(full_pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+ return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+ return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+ pattern_ = full_pattern_ = NULL;
+ if (regex != NULL) {
+ pattern_ = posix::StrDup(regex);
+ }
+
+ is_valid_ = ValidateRegex(regex);
+ if (!is_valid_) {
+ // No need to calculate the full pattern when the regex is invalid.
+ return;
+ }
+
+ const size_t len = strlen(regex);
+ // Reserves enough bytes to hold the regular expression used for a
+ // full match: we need space to prepend a '^', append a '$', and
+ // terminate the string with '\0'.
+ char* buffer = static_cast<char*>(malloc(len + 3));
+ full_pattern_ = buffer;
+
+ if (*regex != '^')
+ *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'.
+
+ // We don't use snprintf or strncpy, as they trigger a warning when
+ // compiled with VC++ 8.0.
+ memcpy(buffer, regex, len);
+ buffer += len;
+
+ if (len == 0 || regex[len - 1] != '$')
+ *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'.
+
+ *buffer = '\0';
+}
+
+#endif // GTEST_USES_POSIX_RE
+
+
+GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
+ : severity_(severity) {
+ const char* const marker =
+ severity == GTEST_INFO ? "[ INFO ]" :
+ severity == GTEST_WARNING ? "[WARNING]" :
+ severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
+ GetStream() << ::std::endl << marker << " "
+ << FormatFileLocation(file, line).c_str() << ": ";
+}
+
+// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+GTestLog::~GTestLog() {
+ GetStream() << ::std::endl;
+ if (severity_ == GTEST_FATAL) {
+ fflush(stderr);
+ posix::Abort();
+ }
+}
+// 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)
+#endif // _MSC_VER
+
+#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
+ char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
+ char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
+
+ ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+ const UINT success = ::GetTempFileNameA(temp_dir_path,
+ "gtest_redir",
+ 0, // Generate unique file name.
+ temp_file_path);
+ GTEST_CHECK_(success != 0)
+ << "Unable to create a temporary file in " << temp_dir_path;
+ const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+ GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
+ << temp_file_path;
+ filename_ = temp_file_path;
+#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
+ fflush(NULL);
+ dup2(captured_fd, fd_);
+ close(captured_fd);
+ }
+
+ ~CapturedStream() {
+ remove(filename_.c_str());
+ }
+
+ String GetCapturedString() {
+ if (uncaptured_fd_ != -1) {
+ // Restores the original stream.
+ fflush(NULL);
+ dup2(uncaptured_fd_, fd_);
+ close(uncaptured_fd_);
+ uncaptured_fd_ = -1;
+ }
+
+ FILE* const file = posix::FOpen(filename_.c_str(), "r");
+ const String content = ReadEntireFile(file);
+ posix::FClose(file);
+ return content;
+ }
+
+ private:
+ // Reads the entire content of a file as a String.
+ static String ReadEntireFile(FILE* file);
+
+ // Returns the size (in bytes) of a file.
+ static size_t GetFileSize(FILE* file);
+
+ const int fd_; // A stream to capture.
+ int uncaptured_fd_;
+ // Name of the temporary file holding the stderr output.
+ ::std::string filename_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
+};
+
+// Returns the size (in bytes) of a file.
+size_t CapturedStream::GetFileSize(FILE* file) {
+ fseek(file, 0, SEEK_END);
+ return static_cast<size_t>(ftell(file));
+}
+
+// Reads the entire content of a file as a string.
+String CapturedStream::ReadEntireFile(FILE* file) {
+ const size_t file_size = GetFileSize(file);
+ char* const buffer = new char[file_size];
+
+ size_t bytes_last_read = 0; // # of bytes read in the last fread()
+ size_t bytes_read = 0; // # of bytes read so far
+
+ fseek(file, 0, SEEK_SET);
+
+ // Keeps reading the file until we cannot read further or the
+ // pre-determined file size is reached.
+ do {
+ bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
+ bytes_read += bytes_last_read;
+ } while (bytes_last_read > 0 && bytes_read < file_size);
+
+ const String content(buffer, bytes_read);
+ delete[] buffer;
+
+ return content;
+}
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
+static CapturedStream* g_captured_stderr = NULL;
+static CapturedStream* g_captured_stdout = NULL;
+
+// Starts capturing an output stream (stdout/stderr).
+void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
+ if (*stream != NULL) {
+ GTEST_LOG_(FATAL) << "Only one " << stream_name
+ << " capturer can exist at a time.";
+ }
+ *stream = new CapturedStream(fd);
+}
+
+// Stops capturing the output stream and returns the captured string.
+String GetCapturedStream(CapturedStream** captured_stream) {
+ const String content = (*captured_stream)->GetCapturedString();
+
+ delete *captured_stream;
+ *captured_stream = NULL;
+
+ return content;
+}
+
+// Starts capturing stdout.
+void CaptureStdout() {
+ CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
+}
+
+// Starts capturing stderr.
+void CaptureStderr() {
+ CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
+}
+
+// Stops capturing stdout and returns the captured string.
+String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); }
+
+// Stops capturing stderr and returns the captured string.
+String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
+
+#endif // GTEST_HAS_STREAM_REDIRECTION_
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments. Set by InitGoogleTest().
+::std::vector<String> g_argvs;
+
+// Returns the command line as a vector of strings.
+const ::std::vector<String>& GetArgvs() { return g_argvs; }
+
+#endif // GTEST_HAS_DEATH_TEST
+
+#if GTEST_OS_WINDOWS_MOBILE
+namespace posix {
+void Abort() {
+ DebugBreak();
+ TerminateProcess(GetCurrentProcess(), 1);
+}
+} // namespace posix
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+// Returns the name of the environment variable corresponding to the
+// given flag. For example, FlagToEnvVar("foo") will return
+// "GTEST_FOO" in the open-source version.
+static String FlagToEnvVar(const char* flag) {
+ const String full_flag =
+ (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
+
+ Message env_var;
+ for (size_t i = 0; i != full_flag.length(); i++) {
+ env_var << static_cast<char>(toupper(full_flag.c_str()[i]));
+ }
+
+ return env_var.GetString();
+}
+
+// Parses 'str' for a 32-bit signed integer. If successful, writes
+// the result to *value and returns true; otherwise leaves *value
+// unchanged and returns false.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
+ // Parses the environment variable as a decimal integer.
+ char* end = NULL;
+ const long long_value = strtol(str, &end, 10); // NOLINT
+
+ // Has strtol() consumed all characters in the string?
+ if (*end != '\0') {
+ // No - an invalid character was encountered.
+ Message msg;
+ msg << "WARNING: " << src_text
+ << " is expected to be a 32-bit integer, but actually"
+ << " has value \"" << str << "\".\n";
+ printf("%s", msg.GetString().c_str());
+ fflush(stdout);
+ return false;
+ }
+
+ // Is the parsed value in the range of an Int32?
+ const Int32 result = static_cast<Int32>(long_value);
+ if (long_value == LONG_MAX || long_value == LONG_MIN ||
+ // The parsed value overflows as a long. (strtol() returns
+ // LONG_MAX or LONG_MIN when the input overflows.)
+ result != long_value
+ // The parsed value overflows as an Int32.
+ ) {
+ Message msg;
+ msg << "WARNING: " << src_text
+ << " is expected to be a 32-bit integer, but actually"
+ << " has value " << str << ", which overflows.\n";
+ printf("%s", msg.GetString().c_str());
+ fflush(stdout);
+ return false;
+ }
+
+ *value = result;
+ return true;
+}
+
+// Reads and returns the Boolean environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+//
+// The value is considered true iff it's not "0".
+bool BoolFromGTestEnv(const char* flag, bool default_value) {
+ const String env_var = FlagToEnvVar(flag);
+ const char* const string_value = posix::GetEnv(env_var.c_str());
+ return string_value == NULL ?
+ default_value : strcmp(string_value, "0") != 0;
+}
+
+// Reads and returns a 32-bit integer stored in the environment
+// variable corresponding to the given flag; if it isn't set or
+// doesn't represent a valid 32-bit integer, returns default_value.
+Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
+ const String env_var = FlagToEnvVar(flag);
+ const char* const string_value = posix::GetEnv(env_var.c_str());
+ if (string_value == NULL) {
+ // The environment variable is not set.
+ return default_value;
+ }
+
+ Int32 result = default_value;
+ if (!ParseInt32(Message() << "Environment variable " << env_var,
+ string_value, &result)) {
+ printf("The default value %s is used.\n",
+ (Message() << default_value).GetString().c_str());
+ fflush(stdout);
+ return default_value;
+ }
+
+ return result;
+}
+
+// Reads and returns the string environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+const char* StringFromGTestEnv(const char* flag, const char* default_value) {
+ const String env_var = FlagToEnvVar(flag);
+ const char* const value = posix::GetEnv(env_var.c_str());
+ return value == NULL ? default_value : value;
+}
+
+} // namespace internal
+} // namespace testing
diff --git a/contrib/llvm/utils/unittest/googletest/gtest-test-part.cc b/contrib/llvm/utils/unittest/googletest/gtest-test-part.cc
new file mode 100644
index 0000000..8249afe
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/gtest-test-part.cc
@@ -0,0 +1,110 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#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
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "gtest/internal/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+using internal::GetUnitTestImpl;
+
+// Gets the summary of the failure message by omitting the stack trace
+// in it.
+internal::String TestPartResult::ExtractSummary(const char* message) {
+ const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
+ return stack_trace == NULL ? internal::String(message) :
+ internal::String(message, stack_trace - message);
+}
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
+ return os
+ << result.file_name() << ":" << result.line_number() << ": "
+ << (result.type() == TestPartResult::kSuccess ? "Success" :
+ result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
+ "Non-fatal failure") << ":\n"
+ << result.message() << std::endl;
+}
+
+// Appends a TestPartResult to the array.
+void TestPartResultArray::Append(const TestPartResult& result) {
+ array_.push_back(result);
+}
+
+// Returns the TestPartResult at the given index (0-based).
+const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
+ if (index < 0 || index >= size()) {
+ printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
+ internal::posix::Abort();
+ }
+
+ return array_[index];
+}
+
+// Returns the number of TestPartResult objects in the array.
+int TestPartResultArray::size() const {
+ return static_cast<int>(array_.size());
+}
+
+namespace internal {
+
+HasNewFatalFailureHelper::HasNewFatalFailureHelper()
+ : has_new_fatal_failure_(false),
+ original_reporter_(GetUnitTestImpl()->
+ GetTestPartResultReporterForCurrentThread()) {
+ GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
+}
+
+HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
+ GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
+ original_reporter_);
+}
+
+void HasNewFatalFailureHelper::ReportTestPartResult(
+ const TestPartResult& result) {
+ if (result.fatally_failed())
+ has_new_fatal_failure_ = true;
+ original_reporter_->ReportTestPartResult(result);
+}
+
+} // namespace internal
+
+} // namespace testing
diff --git a/contrib/llvm/utils/unittest/googletest/gtest-typed-test.cc b/contrib/llvm/utils/unittest/googletest/gtest-typed-test.cc
new file mode 100644
index 0000000..3cc4b5d
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/gtest-typed-test.cc
@@ -0,0 +1,110 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include <gtest/gtest-typed-test.h>
+#include <gtest/gtest.h>
+
+namespace testing {
+namespace internal {
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// 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))
+ str++;
+ return str;
+}
+
+// Verifies that registered_tests match the test names in
+// defined_test_names_; returns registered_tests if successful, or
+// aborts the program otherwise.
+const char* TypedTestCasePState::VerifyRegisteredTestNames(
+ const char* file, int line, const char* registered_tests) {
+ typedef ::std::set<const char*>::const_iterator DefinedTestIter;
+ registered_ = true;
+
+ // Skip initial whitespace in registered_tests since some
+ // preprocessors prefix stringizied literals with whitespace.
+ registered_tests = SkipSpaces(registered_tests);
+
+ Message errors;
+ ::std::set<String> tests;
+ for (const char* names = registered_tests; names != NULL;
+ names = SkipComma(names)) {
+ const String name = GetPrefixUntilComma(names);
+ if (tests.count(name) != 0) {
+ errors << "Test " << name << " is listed more than once.\n";
+ continue;
+ }
+
+ bool found = false;
+ for (DefinedTestIter it = defined_test_names_.begin();
+ it != defined_test_names_.end();
+ ++it) {
+ if (name == *it) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ tests.insert(name);
+ } else {
+ errors << "No test named " << name
+ << " can be found in this test case.\n";
+ }
+ }
+
+ for (DefinedTestIter it = defined_test_names_.begin();
+ it != defined_test_names_.end();
+ ++it) {
+ if (tests.count(*it) == 0) {
+ errors << "You forgot to list test " << *it << ".\n";
+ }
+ }
+
+ const String& errors_str = errors.GetString();
+ if (errors_str != "") {
+ fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+ errors_str.c_str());
+ fflush(stderr);
+ posix::Abort();
+ }
+
+ return registered_tests;
+}
+
+#endif // GTEST_HAS_TYPED_TEST_P
+
+} // namespace internal
+} // namespace testing
diff --git a/contrib/llvm/utils/unittest/googletest/gtest.cc b/contrib/llvm/utils/unittest/googletest/gtest.cc
new file mode 100644
index 0000000..aa2d5bb
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/gtest.cc
@@ -0,0 +1,4704 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include <gtest/gtest.h>
+#include <gtest/gtest-spi.h>
+
+#include <ctype.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <algorithm>
+#include <ostream>
+#include <sstream>
+#include <vector>
+
+#if GTEST_OS_LINUX
+
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+#define GTEST_HAS_GETTIMEOFDAY_ 1
+
+#include <fcntl.h>
+#include <limits.h>
+#include <sched.h>
+// 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>
+
+#elif GTEST_OS_SYMBIAN
+#define GTEST_HAS_GETTIMEOFDAY_ 1
+#include <sys/time.h> // NOLINT
+
+#elif GTEST_OS_ZOS
+#define GTEST_HAS_GETTIMEOFDAY_ 1
+#include <sys/time.h> // NOLINT
+
+// On z/OS we additionally need strings.h for strcasecmp.
+#include <strings.h> // NOLINT
+
+#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE.
+
+#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
+
+#if GTEST_OS_WINDOWS_MINGW
+// MinGW has gettimeofday() but not _ftime64().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+// TODO(kenton@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
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+#include <windows.h> // NOLINT
+
+#else
+
+// Assume other platforms have gettimeofday().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+#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
+
+#endif // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+#include <stdexcept>
+#endif
+
+// Indicates that this translation unit is part of Google Test's
+// implementation. It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "gtest/internal/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_WINDOWS
+#define vsnprintf _vsnprintf
+#endif // GTEST_OS_WINDOWS
+
+namespace testing {
+
+using internal::CountIf;
+using internal::ForEach;
+using internal::GetElementOr;
+using internal::Shuffle;
+
+// Constants.
+
+// A test whose test case name or test name matches this filter is
+// disabled and not run.
+static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
+
+// A test case whose name matches this filter is considered a death
+// test case and will be run before test cases whose name doesn't
+// match this filter.
+static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*";
+
+// A test filter that matches everything.
+static const char kUniversalFilter[] = "*";
+
+// The default output file for XML output.
+static const char kDefaultOutputFile[] = "test_detail.xml";
+
+// The environment variable name for the test shard index.
+static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
+// The environment variable name for the total number of test shards.
+static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
+// The environment variable name for the test shard status file.
+static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+
+namespace internal {
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+const char kStackTraceMarker[] = "\nStack trace:\n";
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+bool g_help_flag = false;
+
+} // namespace internal
+
+GTEST_DEFINE_bool_(
+ also_run_disabled_tests,
+ internal::BoolFromGTestEnv("also_run_disabled_tests", false),
+ "Run disabled tests too, in addition to the tests normally being run.");
+
+GTEST_DEFINE_bool_(
+ break_on_failure,
+ internal::BoolFromGTestEnv("break_on_failure", false),
+ "True iff a failed assertion should be a debugger break-point.");
+
+GTEST_DEFINE_bool_(
+ catch_exceptions,
+ internal::BoolFromGTestEnv("catch_exceptions", false),
+ "True iff " GTEST_NAME_
+ " should catch exceptions and treat them as test failures.");
+
+GTEST_DEFINE_string_(
+ color,
+ internal::StringFromGTestEnv("color", "auto"),
+ "Whether to use colors in the output. Valid values: yes, no, "
+ "and auto. 'auto' means to use colors if the output is "
+ "being sent to a terminal and the TERM environment variable "
+ "is set to xterm, xterm-color, xterm-256color, linux or cygwin.");
+
+GTEST_DEFINE_string_(
+ filter,
+ internal::StringFromGTestEnv("filter", kUniversalFilter),
+ "A colon-separated list of glob (not regex) patterns "
+ "for filtering the tests to run, optionally followed by a "
+ "'-' and a : separated list of negative patterns (tests to "
+ "exclude). A test is run if it matches one of the positive "
+ "patterns and does not match any of the negative patterns.");
+
+GTEST_DEFINE_bool_(list_tests, false,
+ "List all tests without running them.");
+
+GTEST_DEFINE_string_(
+ output,
+ internal::StringFromGTestEnv("output", ""),
+ "A format (currently must be \"xml\"), optionally followed "
+ "by a colon and an output file name or directory. A directory "
+ "is indicated by a trailing pathname separator. "
+ "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
+ "If a directory is specified, output files will be created "
+ "within that directory, with file-names based on the test "
+ "executable's name and, if necessary, made unique by adding "
+ "digits.");
+
+GTEST_DEFINE_bool_(
+ print_time,
+ internal::BoolFromGTestEnv("print_time", true),
+ "True iff " GTEST_NAME_
+ " should display elapsed time in text output.");
+
+GTEST_DEFINE_int32_(
+ random_seed,
+ internal::Int32FromGTestEnv("random_seed", 0),
+ "Random number seed to use when shuffling test orders. Must be in range "
+ "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
+ repeat,
+ internal::Int32FromGTestEnv("repeat", 1),
+ "How many times to repeat each test. Specify a negative number "
+ "for repeating forever. Useful for shaking out flaky tests.");
+
+GTEST_DEFINE_bool_(
+ show_internal_stack_frames, false,
+ "True iff " GTEST_NAME_ " should include internal stack frames when "
+ "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(
+ shuffle,
+ internal::BoolFromGTestEnv("shuffle", false),
+ "True iff " GTEST_NAME_
+ " should randomize tests' order on every run.");
+
+GTEST_DEFINE_int32_(
+ stack_trace_depth,
+ internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
+ "The maximum number of stack frames to print when an "
+ "assertion fails. The valid range is 0 through 100, inclusive.");
+
+GTEST_DEFINE_bool_(
+ throw_on_failure,
+ internal::BoolFromGTestEnv("throw_on_failure", false),
+ "When this flag is specified, a failed assertion will throw an exception "
+ "if exceptions are enabled or exit the program with a non-zero code "
+ "otherwise.");
+
+namespace internal {
+
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG). Crashes if 'range' is 0 or greater
+// than kMaxRange.
+UInt32 Random::Generate(UInt32 range) {
+ // These constants are the same as are used in glibc's rand(3).
+ state_ = (1103515245U*state_ + 12345U) % kMaxRange;
+
+ GTEST_CHECK_(range > 0)
+ << "Cannot generate a number in the range [0, 0).";
+ GTEST_CHECK_(range <= kMaxRange)
+ << "Generation of a number in [0, " << range << ") was requested, "
+ << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+ // Converting via modulus introduces a bit of downward bias, but
+ // it's simple, and a linear congruential generator isn't too good
+ // to begin with.
+ return state_ % range;
+}
+
+// GTestIsInitialized() returns true iff the user has initialized
+// Google Test. Useful for catching the user mistake of not initializing
+// Google Test before calling RUN_ALL_TESTS().
+//
+// A user must call testing::InitGoogleTest() to initialize Google
+// Test. g_init_gtest_count is set to the number of times
+// InitGoogleTest() has been called. We don't protect this variable
+// under a mutex as it is only accessed in the main thread.
+int g_init_gtest_count = 0;
+static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
+
+// Iterates over a vector of TestCases, keeping a running sum of the
+// results of calling a given int-returning method on each.
+// Returns the sum.
+static int SumOverTestCaseList(const std::vector<TestCase*>& case_list,
+ int (TestCase::*method)() const) {
+ int sum = 0;
+ for (size_t i = 0; i < case_list.size(); i++) {
+ sum += (case_list[i]->*method)();
+ }
+ return sum;
+}
+
+// Returns true iff the test case passed.
+static bool TestCasePassed(const TestCase* test_case) {
+ return test_case->should_run() && test_case->Passed();
+}
+
+// Returns true iff the test case failed.
+static bool TestCaseFailed(const TestCase* test_case) {
+ return test_case->should_run() && test_case->Failed();
+}
+
+// Returns true iff test_case contains at least one test that should
+// run.
+static bool ShouldRunTestCase(const TestCase* test_case) {
+ return test_case->should_run();
+}
+
+// AssertHelper constructor.
+AssertHelper::AssertHelper(TestPartResult::Type type,
+ const char* file,
+ int line,
+ const char* message)
+ : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+ delete data_;
+}
+
+// Message assignment, for assertion streaming support.
+void AssertHelper::operator=(const Message& message) const {
+ UnitTest::GetInstance()->
+ AddTestPartResult(data_->type, data_->file, data_->line,
+ AppendUserMessage(data_->message, message),
+ UnitTest::GetInstance()->impl()
+ ->CurrentOsStackTraceExceptTop(1)
+ // Skips the stack frame for this function itself.
+ ); // NOLINT
+}
+
+// Mutex for linked pointers.
+GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// Application pathname gotten in InitGoogleTest.
+String g_executable_path;
+
+// Returns the current application's name, removing directory path if that
+// is present.
+FilePath GetCurrentExecutableName() {
+ FilePath result;
+
+#if GTEST_OS_WINDOWS
+ result.Set(FilePath(g_executable_path).RemoveExtension("exe"));
+#else
+ result.Set(FilePath(g_executable_path));
+#endif // GTEST_OS_WINDOWS
+
+ return result.RemoveDirectoryName();
+}
+
+// Functions for processing the gtest_output flag.
+
+// Returns the output format, or "" for normal printed output.
+String UnitTestOptions::GetOutputFormat() {
+ const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+ if (gtest_output_flag == NULL) return String("");
+
+ const char* const colon = strchr(gtest_output_flag, ':');
+ return (colon == NULL) ?
+ String(gtest_output_flag) :
+ String(gtest_output_flag, colon - gtest_output_flag);
+}
+
+// Returns the name of the requested output file, or the default if none
+// was explicitly specified.
+String UnitTestOptions::GetAbsolutePathToOutputFile() {
+ const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+ if (gtest_output_flag == NULL)
+ return String("");
+
+ const char* const colon = strchr(gtest_output_flag, ':');
+ if (colon == NULL)
+ return String(internal::FilePath::ConcatPaths(
+ internal::FilePath(
+ UnitTest::GetInstance()->original_working_dir()),
+ internal::FilePath(kDefaultOutputFile)).ToString() );
+
+ internal::FilePath output_name(colon + 1);
+ if (!output_name.IsAbsolutePath())
+ // TODO(wan@google.com): on Windows \some\path is not an absolute
+ // path (as its meaning depends on the current drive), yet the
+ // following logic for turning it into an absolute path is wrong.
+ // Fix it.
+ output_name = internal::FilePath::ConcatPaths(
+ internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
+ internal::FilePath(colon + 1));
+
+ if (!output_name.IsDirectory())
+ return output_name.ToString();
+
+ internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
+ output_name, internal::GetCurrentExecutableName(),
+ GetOutputFormat().c_str()));
+ return result.ToString();
+}
+
+// Returns true iff the wildcard pattern matches the string. The
+// first ':' or '\0' character in pattern marks the end of it.
+//
+// This recursive algorithm isn't very efficient, but is clear and
+// works well enough for matching test names, which are short.
+bool UnitTestOptions::PatternMatchesString(const char *pattern,
+ const char *str) {
+ switch (*pattern) {
+ case '\0':
+ case ':': // Either ':' or '\0' marks the end of the pattern.
+ return *str == '\0';
+ case '?': // Matches any single character.
+ return *str != '\0' && PatternMatchesString(pattern + 1, str + 1);
+ case '*': // Matches any string (possibly empty) of characters.
+ return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
+ PatternMatchesString(pattern + 1, str);
+ default: // Non-special character. Matches itself.
+ return *pattern == *str &&
+ PatternMatchesString(pattern + 1, str + 1);
+ }
+}
+
+bool UnitTestOptions::MatchesFilter(const String& name, const char* filter) {
+ const char *cur_pattern = filter;
+ for (;;) {
+ if (PatternMatchesString(cur_pattern, name.c_str())) {
+ return true;
+ }
+
+ // Finds the next pattern in the filter.
+ cur_pattern = strchr(cur_pattern, ':');
+
+ // Returns if no more pattern can be found.
+ if (cur_pattern == NULL) {
+ return false;
+ }
+
+ // Skips the pattern separater (the ':' character).
+ cur_pattern++;
+ }
+}
+
+// TODO(keithray): move String function implementations to gtest-string.cc.
+
+// Returns true iff the user-specified filter matches the test case
+// name and the test name.
+bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
+ const String &test_name) {
+ const String& full_name = String::Format("%s.%s",
+ test_case_name.c_str(),
+ test_name.c_str());
+
+ // Split --gtest_filter at '-', if there is one, to separate into
+ // positive filter and negative filter portions
+ const char* const p = GTEST_FLAG(filter).c_str();
+ const char* const dash = strchr(p, '-');
+ String positive;
+ String negative;
+ if (dash == NULL) {
+ positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter
+ negative = String("");
+ } else {
+ positive = String(p, dash - p); // Everything up to the dash
+ negative = String(dash+1); // Everything after the dash
+ if (positive.empty()) {
+ // Treat '-test1' as the same as '*-test1'
+ positive = kUniversalFilter;
+ }
+ }
+
+ // A filter is a colon-separated list of patterns. It matches a
+ // test if any pattern in it matches the test.
+ return (MatchesFilter(full_name, positive.c_str()) &&
+ !MatchesFilter(full_name, negative.c_str()));
+}
+
+#if GTEST_OS_WINDOWS
+// 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:
+ // 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;
+}
+#endif // GTEST_OS_WINDOWS
+
+} // namespace internal
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test. The 'result' parameter specifies where to report the
+// results. Intercepts only failures from the current thread.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+ TestPartResultArray* result)
+ : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD),
+ result_(result) {
+ Init();
+}
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test. The 'result' parameter specifies where to report the
+// results.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+ InterceptMode intercept_mode, TestPartResultArray* result)
+ : intercept_mode_(intercept_mode),
+ result_(result) {
+ Init();
+}
+
+void ScopedFakeTestPartResultReporter::Init() {
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+ old_reporter_ = impl->GetGlobalTestPartResultReporter();
+ impl->SetGlobalTestPartResultReporter(this);
+ } else {
+ old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
+ impl->SetTestPartResultReporterForCurrentThread(this);
+ }
+}
+
+// The d'tor restores the test part result reporter used by Google Test
+// before.
+ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+ impl->SetGlobalTestPartResultReporter(old_reporter_);
+ } else {
+ impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
+ }
+}
+
+// Increments the test part result count and remembers the result.
+// This method is from the TestPartResultReporterInterface interface.
+void ScopedFakeTestPartResultReporter::ReportTestPartResult(
+ const TestPartResult& result) {
+ result_->Append(result);
+}
+
+namespace internal {
+
+// Returns the type ID of ::testing::Test. We should always call this
+// instead of GetTypeId< ::testing::Test>() to get the type ID of
+// testing::Test. This is to work around a suspected linker bug when
+// using Google Test as a framework on Mac OS X. The bug causes
+// GetTypeId< ::testing::Test>() to return different values depending
+// on whether the call is from the Google Test framework itself or
+// from user test code. GetTestTypeId() is guaranteed to always
+// return the same value, as it always calls GetTypeId<>() from the
+// gtest.cc, which is within the Google Test framework.
+TypeId GetTestTypeId() {
+ return GetTypeId<Test>();
+}
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library. This is solely for testing GetTestTypeId().
+const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
+
+// This predicate-formatter checks that 'results' contains a test part
+// failure of the given type and that the failure message contains the
+// given substring.
+AssertionResult HasOneFailure(const char* /* results_expr */,
+ const char* /* type_expr */,
+ const char* /* substr_expr */,
+ const TestPartResultArray& results,
+ TestPartResult::Type type,
+ const char* substr) {
+ const String expected(type == TestPartResult::kFatalFailure ?
+ "1 fatal failure" :
+ "1 non-fatal failure");
+ Message msg;
+ if (results.size() != 1) {
+ msg << "Expected: " << expected << "\n"
+ << " Actual: " << results.size() << " failures";
+ for (int i = 0; i < results.size(); i++) {
+ msg << "\n" << results.GetTestPartResult(i);
+ }
+ return AssertionFailure(msg);
+ }
+
+ const TestPartResult& r = results.GetTestPartResult(0);
+ if (r.type() != type) {
+ msg << "Expected: " << expected << "\n"
+ << " Actual:\n"
+ << r;
+ return AssertionFailure(msg);
+ }
+
+ if (strstr(r.message(), substr) == NULL) {
+ msg << "Expected: " << expected << " containing \""
+ << substr << "\"\n"
+ << " Actual:\n"
+ << r;
+ return AssertionFailure(msg);
+ }
+
+ return AssertionSuccess();
+}
+
+// The constructor of SingleFailureChecker remembers where to look up
+// test part results, what type of failure we expect, and what
+// substring the failure message should contain.
+SingleFailureChecker:: SingleFailureChecker(
+ const TestPartResultArray* results,
+ TestPartResult::Type type,
+ const char* substr)
+ : results_(results),
+ type_(type),
+ substr_(substr) {}
+
+// The destructor of SingleFailureChecker verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// 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());
+}
+
+DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
+ UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
+ const TestPartResult& result) {
+ unit_test_->current_test_result()->AddTestPartResult(result);
+ unit_test_->listeners()->repeater()->OnTestPartResult(result);
+}
+
+DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
+ UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
+ const TestPartResult& result) {
+ unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
+}
+
+// Returns the global test part result reporter.
+TestPartResultReporterInterface*
+UnitTestImpl::GetGlobalTestPartResultReporter() {
+ internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+ return global_test_part_result_repoter_;
+}
+
+// Sets the global test part result reporter.
+void UnitTestImpl::SetGlobalTestPartResultReporter(
+ TestPartResultReporterInterface* reporter) {
+ internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+ global_test_part_result_repoter_ = reporter;
+}
+
+// Returns the test part result reporter for the current thread.
+TestPartResultReporterInterface*
+UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
+ return per_thread_test_part_result_reporter_.get();
+}
+
+// Sets the test part result reporter for the current thread.
+void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
+ TestPartResultReporterInterface* reporter) {
+ per_thread_test_part_result_reporter_.set(reporter);
+}
+
+// Gets the number of successful test cases.
+int UnitTestImpl::successful_test_case_count() const {
+ return CountIf(test_cases_, TestCasePassed);
+}
+
+// Gets the number of failed test cases.
+int UnitTestImpl::failed_test_case_count() const {
+ return CountIf(test_cases_, TestCaseFailed);
+}
+
+// Gets the number of all test cases.
+int UnitTestImpl::total_test_case_count() const {
+ return static_cast<int>(test_cases_.size());
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTestImpl::test_case_to_run_count() const {
+ return CountIf(test_cases_, ShouldRunTestCase);
+}
+
+// Gets the number of successful tests.
+int UnitTestImpl::successful_test_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count);
+}
+
+// Gets the number of failed tests.
+int UnitTestImpl::failed_test_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count);
+}
+
+// Gets the number of disabled tests.
+int UnitTestImpl::disabled_test_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count);
+}
+
+// Gets the number of all tests.
+int UnitTestImpl::total_test_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::total_test_count);
+}
+
+// Gets the number of tests that should run.
+int UnitTestImpl::test_to_run_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count);
+}
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag. The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+String UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
+ (void)skip_count;
+ return String("");
+}
+
+// Returns the current time in milliseconds.
+TimeInMillis GetTimeInMillis() {
+#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
+ // Difference between 1970-01-01 and 1601-01-01 in milliseconds.
+ // http://analogous.blogspot.com/2005/04/epoch.html
+ const TimeInMillis kJavaEpochToWinFileTimeDelta =
+ static_cast<TimeInMillis>(116444736UL) * 100000UL;
+ const DWORD kTenthMicrosInMilliSecond = 10000;
+
+ SYSTEMTIME now_systime;
+ FILETIME now_filetime;
+ ULARGE_INTEGER now_int64;
+ // TODO(kenton@google.com): Shouldn't this just use
+ // GetSystemTimeAsFileTime()?
+ GetSystemTime(&now_systime);
+ if (SystemTimeToFileTime(&now_systime, &now_filetime)) {
+ now_int64.LowPart = now_filetime.dwLowDateTime;
+ now_int64.HighPart = now_filetime.dwHighDateTime;
+ now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) -
+ kJavaEpochToWinFileTimeDelta;
+ return now_int64.QuadPart;
+ }
+ return 0;
+#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
+ __timeb64 now;
+#ifdef _MSC_VER
+ // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
+ // (deprecated function) there.
+ // TODO(kenton@google.com): Use GetTickCount()? Or use
+ // SystemTimeToFileTime()
+#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
+ _ftime64(&now);
+#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."
+#endif
+}
+
+// Utilities
+
+// class String
+
+// Returns the input enclosed in double quotes if it's not NULL;
+// otherwise returns "(null)". For example, "\"Hello\"" is returned
+// for input "Hello".
+//
+// This is useful for printing a C string in the syntax of a literal.
+//
+// Known issue: escape sequences are not handled yet.
+String String::ShowCStringQuoted(const char* c_str) {
+ return c_str ? String::Format("\"%s\"", c_str) : String("(null)");
+}
+
+// Copies at most length characters from str into a newly-allocated
+// piece of memory of size length+1. The memory is allocated with new[].
+// A terminating null byte is written to the memory, and a pointer to it
+// is returned. If str is NULL, NULL is returned.
+static char* CloneString(const char* str, size_t length) {
+ if (str == NULL) {
+ return NULL;
+ } else {
+ char* const clone = new char[length + 1];
+ posix::StrNCpy(clone, str, length);
+ clone[length] = '\0';
+ return clone;
+ }
+}
+
+// Clones a 0-terminated C string, allocating memory using new. The
+// caller is responsible for deleting[] the return value. Returns the
+// cloned string, or NULL if the input is NULL.
+const char * String::CloneCString(const char* c_str) {
+ return (c_str == NULL) ?
+ NULL : CloneString(c_str, strlen(c_str));
+}
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Creates a UTF-16 wide string from the given ANSI string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the wide string, or NULL if the
+// input is NULL.
+LPCWSTR String::AnsiToUtf16(const char* ansi) {
+ if (!ansi) return NULL;
+ const int length = strlen(ansi);
+ const int unicode_length =
+ MultiByteToWideChar(CP_ACP, 0, ansi, length,
+ NULL, 0);
+ WCHAR* unicode = new WCHAR[unicode_length + 1];
+ MultiByteToWideChar(CP_ACP, 0, ansi, length,
+ unicode, unicode_length);
+ unicode[unicode_length] = 0;
+ return unicode;
+}
+
+// Creates an ANSI string from the given wide string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the ANSI string, or NULL if the
+// input is NULL.
+const char* String::Utf16ToAnsi(LPCWSTR utf16_str) {
+ if (!utf16_str) return NULL;
+ const int ansi_length =
+ WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+ NULL, 0, NULL, NULL);
+ char* ansi = new char[ansi_length + 1];
+ WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+ ansi, ansi_length, NULL, NULL);
+ ansi[ansi_length] = 0;
+ return ansi;
+}
+
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+// Compares two C strings. Returns true iff they have the same content.
+//
+// Unlike strcmp(), this function can handle NULL argument(s). A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CStringEquals(const char * lhs, const char * rhs) {
+ if ( lhs == NULL ) return rhs == NULL;
+
+ if ( rhs == NULL ) return false;
+
+ return strcmp(lhs, rhs) == 0;
+}
+
+#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+// Converts an array of wide chars to a narrow string using the UTF-8
+// encoding, and streams the result to the given Message object.
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
+ Message* msg) {
+ // TODO(wan): consider allowing a testing::String object to
+ // contain '\0'. This will make it behave more like std::string,
+ // and will allow ToUtf8String() to return the correct encoding
+ // for '\0' s.t. we can get rid of the conditional here (and in
+ // several other places).
+ for (size_t i = 0; i != length; ) { // NOLINT
+ if (wstr[i] != L'\0') {
+ *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+ while (i != length && wstr[i] != L'\0')
+ i++;
+ } else {
+ *msg << '\0';
+ i++;
+ }
+ }
+}
+
+#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+} // namespace internal
+
+#if GTEST_HAS_STD_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::std::wstring& wstr) {
+ internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+ return *this;
+}
+#endif // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::wstring& wstr) {
+ internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+ return *this;
+}
+#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)) {
+}
+
+// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+AssertionResult AssertionResult::operator!() const {
+ AssertionResult negation(!success_);
+ if (message_.get() != NULL)
+ negation << *message_;
+ return negation;
+}
+
+// Makes a successful assertion result.
+AssertionResult AssertionSuccess() {
+ return AssertionResult(true);
+}
+
+// Makes a failed assertion result.
+AssertionResult AssertionFailure() {
+ return AssertionResult(false);
+}
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << message.
+AssertionResult AssertionFailure(const Message& message) {
+ return AssertionFailure() << message;
+}
+
+namespace internal {
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings. For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+// expected_expression: "foo"
+// actual_expression: "bar"
+// expected_value: "5"
+// actual_value: "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+AssertionResult EqFailure(const char* expected_expression,
+ const char* actual_expression,
+ const String& expected_value,
+ const String& actual_value,
+ bool ignoring_case) {
+ Message msg;
+ msg << "Value of: " << actual_expression;
+ if (actual_value != actual_expression) {
+ msg << "\n Actual: " << actual_value;
+ }
+
+ msg << "\nExpected: " << expected_expression;
+ if (ignoring_case) {
+ msg << " (ignoring case)";
+ }
+ if (expected_value != expected_expression) {
+ msg << "\nWhich is: " << expected_value;
+ }
+
+ return AssertionFailure(msg);
+}
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+String GetBoolAssertionFailureMessage(const AssertionResult& assertion_result,
+ const char* expression_text,
+ const char* actual_predicate_value,
+ const char* expected_predicate_value) {
+ const char* actual_message = assertion_result.message();
+ Message msg;
+ msg << "Value of: " << expression_text
+ << "\n Actual: " << actual_predicate_value;
+ if (actual_message[0] != '\0')
+ msg << " (" << actual_message << ")";
+ msg << "\nExpected: " << expected_predicate_value;
+ return msg.GetString();
+}
+
+// Helper function for implementing ASSERT_NEAR.
+AssertionResult DoubleNearPredFormat(const char* expr1,
+ const char* expr2,
+ const char* abs_error_expr,
+ double val1,
+ double val2,
+ double abs_error) {
+ const double diff = fabs(val1 - val2);
+ if (diff <= abs_error) return AssertionSuccess();
+
+ // 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
+ << " 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);
+}
+
+
+// Helper template for implementing FloatLE() and DoubleLE().
+template <typename RawType>
+AssertionResult FloatingPointLE(const char* expr1,
+ const char* expr2,
+ RawType val1,
+ RawType val2) {
+ // Returns success if val1 is less than val2,
+ if (val1 < val2) {
+ return AssertionSuccess();
+ }
+
+ // or if val1 is almost equal to val2.
+ const FloatingPoint<RawType> lhs(val1), rhs(val2);
+ if (lhs.AlmostEquals(rhs)) {
+ return AssertionSuccess();
+ }
+
+ // Note that the above two checks will both fail if either val1 or
+ // val2 is NaN, as the IEEE floating-point standard requires that
+ // any predicate involving a NaN must return false.
+
+ StrStream val1_ss;
+ val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+ << val1;
+
+ StrStream 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);
+}
+
+} // namespace internal
+
+// Asserts that val1 is less than, or almost equal to, val2. Fails
+// otherwise. In particular, it fails if either val1 or val2 is NaN.
+AssertionResult FloatLE(const char* expr1, const char* expr2,
+ float val1, float val2) {
+ return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
+}
+
+// Asserts that val1 is less than, or almost equal to, val2. Fails
+// otherwise. In particular, it fails if either val1 or val2 is NaN.
+AssertionResult DoubleLE(const char* expr1, const char* expr2,
+ double val1, double val2) {
+ return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
+}
+
+namespace internal {
+
+// The helper function for {ASSERT|EXPECT}_EQ with int or enum
+// arguments.
+AssertionResult CmpHelperEQ(const char* expected_expression,
+ const char* actual_expression,
+ BiggestInt expected,
+ BiggestInt actual) {
+ if (expected == actual) {
+ return AssertionSuccess();
+ }
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ FormatForComparisonFailureMessage(expected, actual),
+ FormatForComparisonFailureMessage(actual, expected),
+ false);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here
+// just to avoid copy-and-paste of similar code.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+ BiggestInt val1, BiggestInt val2) {\
+ if (val1 op val2) {\
+ return AssertionSuccess();\
+ } else {\
+ Message msg;\
+ msg << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+ << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+ return AssertionFailure(msg);\
+ }\
+}
+
+// Implements the helper function for {ASSERT|EXPECT}_NE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(NE, !=)
+// Implements the helper function for {ASSERT|EXPECT}_LE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LE, <=)
+// Implements the helper function for {ASSERT|EXPECT}_LT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LT, < )
+// Implements the helper function for {ASSERT|EXPECT}_GE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GE, >=)
+// Implements the helper function for {ASSERT|EXPECT}_GT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GT, > )
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+ const char* actual_expression,
+ const char* expected,
+ const char* actual) {
+ if (String::CStringEquals(expected, actual)) {
+ return AssertionSuccess();
+ }
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ String::ShowCStringQuoted(expected),
+ String::ShowCStringQuoted(actual),
+ false);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+ const char* actual_expression,
+ const char* expected,
+ const char* actual) {
+ if (String::CaseInsensitiveCStringEquals(expected, actual)) {
+ return AssertionSuccess();
+ }
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ String::ShowCStringQuoted(expected),
+ String::ShowCStringQuoted(actual),
+ true);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+ const char* s2_expression,
+ const char* s1,
+ const char* s2) {
+ if (!String::CStringEquals(s1, s2)) {
+ return AssertionSuccess();
+ } else {
+ Message msg;
+ msg << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: \""
+ << s1 << "\" vs \"" << s2 << "\"";
+ return AssertionFailure(msg);
+ }
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+ const char* s2_expression,
+ const char* s1,
+ const char* s2) {
+ if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
+ return AssertionSuccess();
+ } else {
+ Message msg;
+ msg << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << ") (ignoring case), actual: \""
+ << s1 << "\" vs \"" << s2 << "\"";
+ return AssertionFailure(msg);
+ }
+}
+
+} // namespace internal
+
+namespace {
+
+// Helper functions for implementing IsSubString() and IsNotSubstring().
+
+// This group of overloaded functions return true iff needle is a
+// substring of haystack. NULL is considered a substring of itself
+// only.
+
+bool IsSubstringPred(const char* needle, const char* haystack) {
+ if (needle == NULL || haystack == NULL)
+ return needle == haystack;
+
+ return strstr(haystack, needle) != NULL;
+}
+
+bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
+ if (needle == NULL || haystack == NULL)
+ return needle == haystack;
+
+ return wcsstr(haystack, needle) != NULL;
+}
+
+// StringType here can be either ::std::string or ::std::wstring.
+template <typename StringType>
+bool IsSubstringPred(const StringType& needle,
+ const StringType& haystack) {
+ return haystack.find(needle) != StringType::npos;
+}
+
+// This function implements either IsSubstring() or IsNotSubstring(),
+// depending on the value of the expected_to_be_substring parameter.
+// StringType here can be const char*, const wchar_t*, ::std::string,
+// or ::std::wstring.
+template <typename StringType>
+AssertionResult IsSubstringImpl(
+ bool expected_to_be_substring,
+ const char* needle_expr, const char* haystack_expr,
+ const StringType& needle, const StringType& haystack) {
+ if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
+ return AssertionSuccess();
+
+ const bool is_wide_string = sizeof(needle[0]) > 1;
+ const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+ return AssertionFailure(
+ Message()
+ << "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 << "\"");
+}
+
+} // namespace
+
+// IsSubstring() and IsNotSubstring() check whether needle is a
+// substring of haystack (NULL is considered a substring of itself
+// only), and return an appropriate error message when they fail.
+
+AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const char* needle, const char* haystack) {
+ return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const wchar_t* needle, const wchar_t* haystack) {
+ return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const char* needle, const char* haystack) {
+ return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const wchar_t* needle, const wchar_t* haystack) {
+ return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::string& needle, const ::std::string& haystack) {
+ return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::string& needle, const ::std::string& haystack) {
+ return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+#if GTEST_HAS_STD_WSTRING
+AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::wstring& needle, const ::std::wstring& haystack) {
+ return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::wstring& needle, const ::std::wstring& haystack) {
+ return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+#endif // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+
+namespace {
+
+// Helper function for IsHRESULT{SuccessFailure} predicates
+AssertionResult HRESULTFailureHelper(const char* expr,
+ const char* expected,
+ long hr) { // NOLINT
+#if GTEST_OS_WINDOWS_MOBILE
+ // Windows CE doesn't support FormatMessage.
+ const char error_text[] = "";
+#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.
+ const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS;
+ const DWORD kBufSize = 4096; // String::Format can't exceed this length.
+ // Gets the system's human readable message string for this HRESULT.
+ char error_text[kBufSize] = { '\0' };
+ DWORD message_length = ::FormatMessageA(kFlags,
+ 0, // no source, we're asking system
+ hr, // the error
+ 0, // no line width restrictions
+ error_text, // output buffer
+ 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]);
+ --message_length) {
+ error_text[message_length - 1] = '\0';
+ }
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+ const String error_hex(String::Format("0x%08X ", hr));
+ Message msg;
+ msg << "Expected: " << expr << " " << expected << ".\n"
+ << " Actual: " << error_hex << error_text << "\n";
+
+ return ::testing::AssertionFailure(msg);
+}
+
+} // namespace
+
+AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT
+ if (SUCCEEDED(hr)) {
+ return AssertionSuccess();
+ }
+ return HRESULTFailureHelper(expr, "succeeds", hr);
+}
+
+AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT
+ if (FAILED(hr)) {
+ return AssertionSuccess();
+ }
+ return HRESULTFailureHelper(expr, "fails", hr);
+}
+
+#endif // GTEST_OS_WINDOWS
+
+// Utility functions for encoding Unicode text (wide strings) in
+// UTF-8.
+
+// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8
+// like this:
+//
+// Code-point length Encoding
+// 0 - 7 bits 0xxxxxxx
+// 8 - 11 bits 110xxxxx 10xxxxxx
+// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx
+// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+// The maximum code-point a one-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint1 = (static_cast<UInt32>(1) << 7) - 1;
+
+// The maximum code-point a two-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint2 = (static_cast<UInt32>(1) << (5 + 6)) - 1;
+
+// The maximum code-point a three-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint3 = (static_cast<UInt32>(1) << (4 + 2*6)) - 1;
+
+// The maximum code-point a four-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint4 = (static_cast<UInt32>(1) << (3 + 3*6)) - 1;
+
+// Chops off the n lowest bits from a bit pattern. Returns the n
+// lowest bits. As a side effect, the original bit pattern will be
+// shifted to the right by n bits.
+inline UInt32 ChopLowBits(UInt32* bits, int n) {
+ const UInt32 low_bits = *bits & ((static_cast<UInt32>(1) << n) - 1);
+ *bits >>= n;
+ return low_bits;
+}
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// The output buffer str must containt at least 32 characters.
+// The function returns the address of the output buffer.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'.
+char* CodePointToUtf8(UInt32 code_point, char* str) {
+ if (code_point <= kMaxCodePoint1) {
+ str[1] = '\0';
+ str[0] = static_cast<char>(code_point); // 0xxxxxxx
+ } else if (code_point <= kMaxCodePoint2) {
+ str[2] = '\0';
+ str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[0] = static_cast<char>(0xC0 | code_point); // 110xxxxx
+ } else if (code_point <= kMaxCodePoint3) {
+ str[3] = '\0';
+ str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[0] = static_cast<char>(0xE0 | code_point); // 1110xxxx
+ } else if (code_point <= kMaxCodePoint4) {
+ str[4] = '\0';
+ str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[0] = static_cast<char>(0xF0 | code_point); // 11110xxx
+ } else {
+ // The longest string String::Format can produce when invoked
+ // with these parameters is 28 character long (not including
+ // the terminating nul character). We are asking for 32 character
+ // buffer just in case. This is also enough for strncpy to
+ // null-terminate the destination string.
+ posix::StrNCpy(
+ str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(), 32);
+ str[31] = '\0'; // Makes sure no change in the format to strncpy leaves
+ // the result unterminated.
+ }
+ return str;
+}
+
+// The following two functions only make sense if the the system
+// uses UTF-16 for wide string encoding. All supported systems
+// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16.
+
+// Determines if the arguments constitute UTF-16 surrogate pair
+// and thus should be combined into a single Unicode code point
+// using CreateCodePointFromUtf16SurrogatePair.
+inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
+ return sizeof(wchar_t) == 2 &&
+ (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00;
+}
+
+// Creates a Unicode code point from UTF16 surrogate pair.
+inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first,
+ wchar_t second) {
+ const UInt32 mask = (1 << 10) - 1;
+ return (sizeof(wchar_t) == 2) ?
+ (((first & mask) << 10) | (second & mask)) + 0x10000 :
+ // This function should not be called when the condition is
+ // false, but we provide a sensible default in case it is.
+ static_cast<UInt32>(first);
+}
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+// UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+String WideStringToUtf8(const wchar_t* str, int num_chars) {
+ if (num_chars == -1)
+ num_chars = static_cast<int>(wcslen(str));
+
+ StrStream stream;
+ for (int i = 0; i < num_chars; ++i) {
+ UInt32 unicode_code_point;
+
+ if (str[i] == L'\0') {
+ break;
+ } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
+ unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i],
+ str[i + 1]);
+ i++;
+ } else {
+ unicode_code_point = static_cast<UInt32>(str[i]);
+ }
+
+ char buffer[32]; // CodePointToUtf8 requires a buffer this big.
+ stream << CodePointToUtf8(unicode_code_point, buffer);
+ }
+ return StrStreamToString(&stream);
+}
+
+// Converts a wide C string to a String using the UTF-8 encoding.
+// NULL will be converted to "(null)".
+String String::ShowWideCString(const wchar_t * wide_c_str) {
+ if (wide_c_str == NULL) return String("(null)");
+
+ return String(internal::WideStringToUtf8(wide_c_str, -1).c_str());
+}
+
+// Similar to ShowWideCString(), except that this function encloses
+// the converted string in double quotes.
+String String::ShowWideCStringQuoted(const wchar_t* wide_c_str) {
+ if (wide_c_str == NULL) return String("(null)");
+
+ return String::Format("L\"%s\"",
+ String::ShowWideCString(wide_c_str).c_str());
+}
+
+// Compares two wide C strings. Returns true iff they have the same
+// content.
+//
+// Unlike wcscmp(), this function can handle NULL argument(s). A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) {
+ if (lhs == NULL) return rhs == NULL;
+
+ if (rhs == NULL) return false;
+
+ return wcscmp(lhs, rhs) == 0;
+}
+
+// Helper function for *_STREQ on wide strings.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+ const char* actual_expression,
+ const wchar_t* expected,
+ const wchar_t* actual) {
+ if (String::WideCStringEquals(expected, actual)) {
+ return AssertionSuccess();
+ }
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ String::ShowWideCStringQuoted(expected),
+ String::ShowWideCStringQuoted(actual),
+ false);
+}
+
+// Helper function for *_STRNE on wide strings.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+ const char* s2_expression,
+ const wchar_t* s1,
+ const wchar_t* s2) {
+ if (!String::WideCStringEquals(s1, s2)) {
+ return AssertionSuccess();
+ }
+
+ Message msg;
+ msg << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: "
+ << String::ShowWideCStringQuoted(s1)
+ << " vs " << String::ShowWideCStringQuoted(s2);
+ return AssertionFailure(msg);
+}
+
+// Compares two C strings, ignoring case. Returns true iff they have
+// the same content.
+//
+// Unlike strcasecmp(), this function can handle NULL argument(s). A
+// NULL C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
+ if (lhs == NULL)
+ return rhs == NULL;
+ if (rhs == NULL)
+ return false;
+ return posix::StrCaseCmp(lhs, rhs) == 0;
+}
+
+ // Compares two wide C strings, ignoring case. Returns true iff they
+ // have the same content.
+ //
+ // Unlike wcscasecmp(), this function can handle NULL argument(s).
+ // A NULL C string is considered different to any non-NULL wide C string,
+ // including the empty string.
+ // NB: The implementations on different platforms slightly differ.
+ // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+ // environment variable. On GNU platform this method uses wcscasecmp
+ // which compares according to LC_CTYPE category of the current locale.
+ // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+ // current locale.
+bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+ const wchar_t* rhs) {
+ if ( lhs == NULL ) return rhs == NULL;
+
+ if ( rhs == NULL ) return false;
+
+#if GTEST_OS_WINDOWS
+ return _wcsicmp(lhs, rhs) == 0;
+#elif GTEST_OS_LINUX
+ return wcscasecmp(lhs, rhs) == 0;
+#else
+ // 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++);
+ right = towlower(*rhs++);
+ } while (left && left == right);
+ return left == right;
+#endif // OS selector
+}
+
+// Compares this with another String.
+// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
+// if this is greater than rhs.
+int String::Compare(const String & rhs) const {
+ const char* const lhs_c_str = c_str();
+ const char* const rhs_c_str = rhs.c_str();
+
+ if (lhs_c_str == NULL) {
+ return rhs_c_str == NULL ? 0 : -1; // NULL < anything except NULL
+ } else if (rhs_c_str == NULL) {
+ return 1;
+ }
+
+ const size_t shorter_str_len =
+ length() <= rhs.length() ? length() : rhs.length();
+ for (size_t i = 0; i != shorter_str_len; i++) {
+ if (lhs_c_str[i] < rhs_c_str[i]) {
+ return -1;
+ } else if (lhs_c_str[i] > rhs_c_str[i]) {
+ return 1;
+ }
+ }
+ return (length() < rhs.length()) ? -1 :
+ (length() > rhs.length()) ? 1 : 0;
+}
+
+// Returns true iff this String ends with the given suffix. *Any*
+// String is considered to end with a NULL or empty suffix.
+bool String::EndsWith(const char* suffix) const {
+ if (suffix == NULL || CStringEquals(suffix, "")) return true;
+
+ if (c_str() == NULL) return false;
+
+ const size_t this_len = strlen(c_str());
+ const size_t suffix_len = strlen(suffix);
+ return (this_len >= suffix_len) &&
+ CStringEquals(c_str() + this_len - suffix_len, suffix);
+}
+
+// Returns true iff this String ends with the given suffix, ignoring case.
+// Any String is considered to end with a NULL or empty suffix.
+bool String::EndsWithCaseInsensitive(const char* suffix) const {
+ if (suffix == NULL || CStringEquals(suffix, "")) return true;
+
+ if (c_str() == NULL) return false;
+
+ const size_t this_len = strlen(c_str());
+ const size_t suffix_len = strlen(suffix);
+ return (this_len >= suffix_len) &&
+ CaseInsensitiveCStringEquals(c_str() + this_len - suffix_len, suffix);
+}
+
+// Formats a list of arguments to a String, using the same format
+// spec string as for printf.
+//
+// We do not use the StringPrintf class as it is not universally
+// available.
+//
+// The result is limited to 4096 characters (including the tailing 0).
+// If 4096 characters are not enough to format the input, or if
+// there's an error, "<formatting error or buffer exceeded>" is
+// returned.
+String String::Format(const char * format, ...) {
+ va_list args;
+ va_start(args, format);
+
+ char buffer[4096];
+ const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]);
+
+ // 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.
+ const int size = vsnprintf(buffer, kBufferSize, format, args);
+#pragma warning(pop) // Restores the warning state.
+#else // We are not using MSVC.
+ const int size = vsnprintf(buffer, kBufferSize, format, args);
+#endif // _MSC_VER
+ va_end(args);
+
+ // vsnprintf()'s behavior is not portable. When the buffer is not
+ // big enough, it returns a negative value in MSVC, and returns the
+ // needed buffer size on Linux. When there is an output error, it
+ // always returns a negative value. For simplicity, we lump the two
+ // error cases together.
+ if (size < 0 || size >= kBufferSize) {
+ return String("<formatting error or buffer exceeded>");
+ } else {
+ return String(buffer, size);
+ }
+}
+
+// Converts the buffer in a StrStream to a String, converting NUL
+// bytes to "\\0" along the way.
+String StrStreamToString(StrStream* 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
+ // because String doesn't support push_back().
+ StrStream helper;
+ for (const char* ch = start; ch != end; ++ch) {
+ if (*ch == '\0') {
+ helper << "\\0"; // Replaces NUL with "\\0";
+ } else {
+ helper.put(*ch);
+ }
+ }
+
+ return String(helper.str().c_str());
+}
+
+// Appends the user-supplied message to the Google-Test-generated message.
+String AppendUserMessage(const String& gtest_msg,
+ const Message& user_msg) {
+ // Appends the user message if it's non-empty.
+ const String user_msg_string = user_msg.GetString();
+ if (user_msg_string.empty()) {
+ return gtest_msg;
+ }
+
+ Message msg;
+ msg << gtest_msg << "\n" << user_msg_string;
+
+ return msg.GetString();
+}
+
+} // namespace internal
+
+// class TestResult
+
+// Creates an empty TestResult.
+TestResult::TestResult()
+ : death_test_count_(0),
+ elapsed_time_(0) {
+}
+
+// D'tor.
+TestResult::~TestResult() {
+}
+
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+ if (i < 0 || i >= total_part_count())
+ internal::posix::Abort();
+ return test_part_results_.at(i);
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+ if (i < 0 || i >= test_property_count())
+ internal::posix::Abort();
+ return test_properties_.at(i);
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() {
+ test_part_results_.clear();
+}
+
+// Adds a test part result to the list.
+void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
+ test_part_results_.push_back(test_part_result);
+}
+
+// Adds a test property to the list. If a property with the same key as the
+// supplied property is already represented, the value of this test_property
+// replaces the old value for that key.
+void TestResult::RecordProperty(const TestProperty& test_property) {
+ if (!ValidateTestProperty(test_property)) {
+ return;
+ }
+ internal::MutexLock lock(&test_properites_mutex_);
+ const std::vector<TestProperty>::iterator property_with_matching_key =
+ std::find_if(test_properties_.begin(), test_properties_.end(),
+ internal::TestPropertyKeyIs(test_property.key()));
+ if (property_with_matching_key == test_properties_.end()) {
+ test_properties_.push_back(test_property);
+ return;
+ }
+ property_with_matching_key->SetValue(test_property.value());
+}
+
+// Adds a failure if the key is a reserved attribute of Google Test
+// testcase tags. Returns true if the property is valid.
+bool TestResult::ValidateTestProperty(const TestProperty& test_property) {
+ internal::String key(test_property.key());
+ if (key == "name" || key == "status" || key == "time" || key == "classname") {
+ ADD_FAILURE()
+ << "Reserved key used in RecordProperty(): "
+ << key
+ << " ('name', 'status', 'time', and 'classname' are reserved by "
+ << GTEST_NAME_ << ")";
+ return false;
+ }
+ return true;
+}
+
+// Clears the object.
+void TestResult::Clear() {
+ test_part_results_.clear();
+ test_properties_.clear();
+ death_test_count_ = 0;
+ elapsed_time_ = 0;
+}
+
+// Returns true iff the test failed.
+bool TestResult::Failed() const {
+ for (int i = 0; i < total_part_count(); ++i) {
+ if (GetTestPartResult(i).failed())
+ return true;
+ }
+ return false;
+}
+
+// Returns true iff the test part fatally failed.
+static bool TestPartFatallyFailed(const TestPartResult& result) {
+ return result.fatally_failed();
+}
+
+// Returns true iff the test fatally failed.
+bool TestResult::HasFatalFailure() const {
+ return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
+}
+
+// Returns true iff the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+ return result.nonfatally_failed();
+}
+
+// Returns true iff the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+ return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
+}
+
+// Gets the number of all test parts. This is the sum of the number
+// of successful test parts and the number of failed test parts.
+int TestResult::total_part_count() const {
+ return static_cast<int>(test_part_results_.size());
+}
+
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+ return static_cast<int>(test_properties_.size());
+}
+
+// class Test
+
+// Creates a Test object.
+
+// The c'tor saves the values of all Google Test flags.
+Test::Test()
+ : gtest_flag_saver_(new internal::GTestFlagSaver) {
+}
+
+// The d'tor restores the values of all Google Test flags.
+Test::~Test() {
+ delete gtest_flag_saver_;
+}
+
+// Sets up the test fixture.
+//
+// A sub-class may override this.
+void Test::SetUp() {
+}
+
+// Tears down the test fixture.
+//
+// A sub-class may override this.
+void Test::TearDown() {
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const char* key, const char* value) {
+ UnitTest::GetInstance()->RecordPropertyForCurrentTest(key, value);
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const char* key, int value) {
+ Message value_message;
+ value_message << value;
+ RecordProperty(key, value_message.GetString().c_str());
+}
+
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+ const String& message) {
+ // This function is a friend of UnitTest and as such has access to
+ // AddTestPartResult.
+ UnitTest::GetInstance()->AddTestPartResult(
+ result_type,
+ NULL, // No info about the source file where the exception occurred.
+ -1, // We have no info on which line caused the exception.
+ message,
+ String()); // No stack trace, either.
+}
+
+} // namespace internal
+
+#if GTEST_OS_WINDOWS
+// We are on Windows.
+
+// 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_OS_WINDOWS
+
+// 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
+// yes, it returns true; otherwise it generates a Google Test failure and
+// returns false.
+bool Test::HasSameFixtureClass() {
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ 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 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 char* const this_test_name = this_test_info->name();
+
+ if (this_fixture_id != first_fixture_id) {
+ // Is the first test defined using TEST?
+ const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
+ // Is this test defined using TEST?
+ const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
+
+ if (first_is_TEST || this_is_TEST) {
+ // The user mixed TEST and TEST_F in this test case - we'll tell
+ // him/her how to fix it.
+
+ // Gets the name of the TEST and the name of the TEST_F. Note
+ // that first_is_TEST and this_is_TEST cannot both be true, as
+ // the fixture IDs are different for the two tests.
+ const char* const TEST_name =
+ first_is_TEST ? first_test_name : this_test_name;
+ const char* const TEST_F_name =
+ first_is_TEST ? this_test_name : first_test_name;
+
+ ADD_FAILURE()
+ << "All tests in the same test case must use the same test fixture\n"
+ << "class, so mixing TEST_F and TEST in the same test case is\n"
+ << "illegal. In test case " << this_test_info->test_case_name()
+ << ",\n"
+ << "test " << TEST_F_name << " is defined using TEST_F but\n"
+ << "test " << TEST_name << " is defined using TEST. You probably\n"
+ << "want to change the TEST to TEST_F or move it to another test\n"
+ << "case.";
+ } else {
+ // The user defined two fixture classes with the same name in
+ // two namespaces - we'll tell him/her how to fix it.
+ ADD_FAILURE()
+ << "All tests in the same test case must use the same test fixture\n"
+ << "class. However, in test case "
+ << this_test_info->test_case_name() << ",\n"
+ << "you defined test " << first_test_name
+ << " and test " << this_test_name << "\n"
+ << "using two different test fixture classes. This can happen if\n"
+ << "the two classes are from different namespaces or translation\n"
+ << "units and have the same name. You should probably rename one\n"
+ << "of the classes to put the tests into different test cases.";
+ }
+ return false;
+ }
+
+ return true;
+}
+
+// Runs the test and updates the test result.
+void Test::Run() {
+ if (!HasSameFixtureClass()) return;
+
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+#if GTEST_HAS_SEH
+ // Catch SEH-style exceptions.
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ __try {
+ SetUp();
+ } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
+ GetExceptionCode())) {
+ AddExceptionThrownFailure(GetExceptionCode(), "SetUp()");
+ }
+
+ // 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");
+ }
+ }
+
+ // 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()");
+ }
+
+#else // We are on a compiler or platform that doesn't support SEH.
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ SetUp();
+
+ // We will run the test only if SetUp() was successful.
+ if (!HasFatalFailure()) {
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ TestBody();
+ }
+
+ // 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
+}
+
+
+// Returns true iff the current test has a fatal failure.
+bool Test::HasFatalFailure() {
+ return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
+}
+
+// Returns true iff the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+ return internal::GetUnitTestImpl()->current_test_result()->
+ HasNonfatalFailure();
+}
+
+// class TestInfo
+
+// Constructs a TestInfo object. It assumes ownership of the test factory
+// object via impl_.
+TestInfo::TestInfo(const char* a_test_case_name,
+ const char* a_name,
+ const char* a_test_case_comment,
+ const char* a_comment,
+ 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);
+}
+
+// Destructs a TestInfo object.
+TestInfo::~TestInfo() {
+ delete impl_;
+}
+
+namespace internal {
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+// 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
+// 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
+// factory: pointer to the factory that creates a test object.
+// The newly created TestInfo instance will assume
+// ownership of the factory object.
+TestInfo* MakeAndRegisterTestInfo(
+ const char* test_case_name, const char* name,
+ const char* test_case_comment, const char* comment,
+ 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,
+ fixture_class_id, factory);
+ GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
+ return test_info;
+}
+
+#if GTEST_HAS_PARAM_TEST
+void ReportInvalidTestCaseType(const char* test_case_name,
+ const char* file, int line) {
+ Message errors;
+ errors
+ << "Attempted redefinition of test case " << test_case_name << ".\n"
+ << "All tests in the same test case must use the same test fixture\n"
+ << "class. However, in test case " << test_case_name << ", you tried\n"
+ << "to define a test using a fixture class different from the one\n"
+ << "used earlier. This can happen if the two fixture classes are\n"
+ << "from different namespaces and have the same name. You should\n"
+ << "probably rename one of the classes to put the tests into different\n"
+ << "test cases.";
+
+ fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+ errors.GetString().c_str());
+}
+#endif // GTEST_HAS_PARAM_TEST
+
+} // 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 {
+
+// A predicate that checks the test name of a TestInfo against a known
+// value.
+//
+// This is used for implementation of the TestCase class only. We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestNameIs is copyable.
+class TestNameIs {
+ public:
+ // Constructor.
+ //
+ // TestNameIs has NO default constructor.
+ explicit TestNameIs(const char* name)
+ : name_(name) {}
+
+ // Returns true iff the test name of test_info matches name_.
+ bool operator()(const TestInfo * test_info) const {
+ return test_info && internal::String(test_info->name()).Compare(name_) == 0;
+ }
+
+ private:
+ internal::String name_;
+};
+
+} // namespace
+
+namespace internal {
+
+// This method expands all parameterized tests registered with macros TEST_P
+// and INSTANTIATE_TEST_CASE_P into regular tests and registers those.
+// This will be done just once during the program runtime.
+void UnitTestImpl::RegisterParameterizedTests() {
+#if GTEST_HAS_PARAM_TEST
+ if (!parameterized_tests_registered_) {
+ parameterized_test_registry_.RegisterTests();
+ parameterized_tests_registered_ = true;
+ }
+#endif
+}
+
+// Creates the test object, runs it, records its result, and then
+// deletes it.
+void TestInfoImpl::Run() {
+ if (!should_run_) return;
+
+ // Tells UnitTest where to store test result.
+ UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->set_current_test_info(parent_);
+
+ TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+ // Notifies the unit test event listeners that a test is about to start.
+ repeater->OnTestStart(*parent_);
+
+ const TimeInMillis start = 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->Run();
+ }
+
+ // Deletes the test object.
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ delete test;
+ test = NULL;
+
+ result_.set_elapsed_time(GetTimeInMillis() - start);
+
+ // Notifies the unit test event listener that a test has just finished.
+ repeater->OnTestEnd(*parent_);
+
+ // 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.
+int TestCase::successful_test_count() const {
+ return CountIf(test_info_list_, TestPassed);
+}
+
+// Gets the number of failed tests in this test case.
+int TestCase::failed_test_count() const {
+ return CountIf(test_info_list_, TestFailed);
+}
+
+int TestCase::disabled_test_count() const {
+ return CountIf(test_info_list_, TestDisabled);
+}
+
+// Get the number of tests in this test case that should run.
+int TestCase::test_to_run_count() const {
+ return CountIf(test_info_list_, ShouldRunTest);
+}
+
+// Gets the number of all tests.
+int TestCase::total_test_count() const {
+ return static_cast<int>(test_info_list_.size());
+}
+
+// Creates a TestCase with the given name.
+//
+// Arguments:
+//
+// name: name of the 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,
+ Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc)
+ : name_(a_name),
+ comment_(a_comment),
+ set_up_tc_(set_up_tc),
+ tear_down_tc_(tear_down_tc),
+ should_run_(false),
+ elapsed_time_(0) {
+}
+
+// Destructor of TestCase.
+TestCase::~TestCase() {
+ // Deletes every Test in the collection.
+ ForEach(test_info_list_, internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestCase::GetTestInfo(int i) const {
+ const int index = GetElementOr(test_indices_, i, -1);
+ return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestCase::GetMutableTestInfo(int i) {
+ const int index = GetElementOr(test_indices_, i, -1);
+ return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Adds a test to this test case. Will delete the test upon
+// destruction of the TestCase object.
+void TestCase::AddTestInfo(TestInfo * test_info) {
+ test_info_list_.push_back(test_info);
+ test_indices_.push_back(static_cast<int>(test_indices_.size()));
+}
+
+// Runs every test in this TestCase.
+void TestCase::Run() {
+ if (!should_run_) return;
+
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->set_current_test_case(this);
+
+ TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+ repeater->OnTestCaseStart(*this);
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ set_up_tc_();
+
+ const internal::TimeInMillis start = internal::GetTimeInMillis();
+ for (int i = 0; i < total_test_count(); i++) {
+ GetMutableTestInfo(i)->impl()->Run();
+ }
+ elapsed_time_ = internal::GetTimeInMillis() - start;
+
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ tear_down_tc_();
+ 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();
+}
+
+// Shuffles the tests in this test case.
+void TestCase::ShuffleTests(internal::Random* random) {
+ Shuffle(random, &test_indices_);
+}
+
+// Restores the test order to before the first shuffle.
+void TestCase::UnshuffleTests() {
+ for (size_t i = 0; i < test_indices_.size(); i++) {
+ test_indices_[i] = static_cast<int>(i);
+ }
+}
+
+// Formats a countable noun. Depending on its quantity, either the
+// singular form or the plural form is used. e.g.
+//
+// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
+// FormatCountableNoun(5, "book", "books") returns "5 books".
+static internal::String FormatCountableNoun(int count,
+ const char * singular_form,
+ const char * plural_form) {
+ return internal::String::Format("%d %s", count,
+ count == 1 ? singular_form : plural_form);
+}
+
+// Formats the count of tests.
+static internal::String FormatTestCount(int test_count) {
+ return FormatCountableNoun(test_count, "test", "tests");
+}
+
+// Formats the count of test cases.
+static internal::String FormatTestCaseCount(int test_case_count) {
+ return FormatCountableNoun(test_case_count, "test case", "test cases");
+}
+
+// Converts a TestPartResult::Type enum to human-friendly string
+// representation. Both kNonFatalFailure and kFatalFailure are translated
+// to "Failure", as the user usually doesn't care about the difference
+// between the two when viewing the test result.
+static const char * TestPartResultTypeToString(TestPartResult::Type type) {
+ switch (type) {
+ case TestPartResult::kSuccess:
+ return "Success";
+
+ case TestPartResult::kNonFatalFailure:
+ case TestPartResult::kFatalFailure:
+#ifdef _MSC_VER
+ return "error: ";
+#else
+ return "Failure\n";
+#endif
+ }
+
+ return "Unknown result type";
+}
+
+// Prints a TestPartResult to a String.
+static internal::String PrintTestPartResultToString(
+ const TestPartResult& test_part_result) {
+ return (Message()
+ << internal::FormatFileLocation(test_part_result.file_name(),
+ test_part_result.line_number())
+ << " " << TestPartResultTypeToString(test_part_result.type())
+ << test_part_result.message()).GetString();
+}
+
+// Prints a TestPartResult.
+static void PrintTestPartResult(const TestPartResult& test_part_result) {
+ const internal::String& result =
+ PrintTestPartResultToString(test_part_result);
+ printf("%s\n", result.c_str());
+ fflush(stdout);
+ // If the test program runs in Visual Studio or a debugger, the
+ // following statements add the test part result message to the Output
+ // window such that the user can double-click on it to jump to the
+ // corresponding source code location; otherwise they do nothing.
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+ // We don't call OutputDebugString*() on Windows Mobile, as printing
+ // to stdout is done by OutputDebugString() there already - we don't
+ // want the same message printed twice.
+ ::OutputDebugStringA(result.c_str());
+ ::OutputDebugStringA("\n");
+#endif
+}
+
+// class PrettyUnitTestResultPrinter
+
+namespace internal {
+
+enum GTestColor {
+ COLOR_DEFAULT,
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_YELLOW
+};
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns the character attribute for the given color.
+WORD GetColorAttribute(GTestColor color) {
+ switch (color) {
+ case COLOR_RED: return FOREGROUND_RED;
+ case COLOR_GREEN: return FOREGROUND_GREEN;
+ case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
+ default: return 0;
+ }
+}
+
+#else
+
+// Returns the ANSI color code for the given color. COLOR_DEFAULT is
+// an invalid input.
+const char* GetAnsiColorCode(GTestColor color) {
+ switch (color) {
+ case COLOR_RED: return "1";
+ case COLOR_GREEN: return "2";
+ case COLOR_YELLOW: return "3";
+ default: return NULL;
+ };
+}
+
+#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns true iff Google Test should use colors in the output.
+bool ShouldUseColor(bool stdout_is_tty) {
+ const char* const gtest_color = GTEST_FLAG(color).c_str();
+
+ if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
+#if GTEST_OS_WINDOWS
+ // On Windows the TERM variable is usually not set, but the
+ // console there does support colors.
+ return stdout_is_tty;
+#else
+ // On non-Windows platforms, we rely on the TERM variable.
+ const char* const term = posix::GetEnv("TERM");
+ const bool term_supports_color =
+ String::CStringEquals(term, "xterm") ||
+ String::CStringEquals(term, "xterm-color") ||
+ String::CStringEquals(term, "xterm-256color") ||
+ String::CStringEquals(term, "linux") ||
+ String::CStringEquals(term, "cygwin");
+ return stdout_is_tty && term_supports_color;
+#endif // GTEST_OS_WINDOWS
+ }
+
+ return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
+ String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
+ String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
+ String::CStringEquals(gtest_color, "1");
+ // We take "yes", "true", "t", and "1" as meaning "yes". If the
+ // value is neither one of these nor "auto", we treat it as "no" to
+ // be conservative.
+}
+
+// Helpers for printing colored strings to stdout. Note that on Windows, we
+// cannot simply emit special characters and have the terminal change colors.
+// This routine must actually emit the characters rather than return a string
+// that would be colored when printed, as can be done on Linux.
+void ColoredPrintf(GTestColor color, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+ const bool use_color = false;
+#else
+ static const bool in_color_mode =
+ ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
+ const bool use_color = in_color_mode && (color != COLOR_DEFAULT);
+#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+ // The '!= 0' comparison is necessary to satisfy MSVC 7.1.
+
+ if (!use_color) {
+ vprintf(fmt, args);
+ va_end(args);
+ return;
+ }
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+ const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ // Gets the current text color.
+ CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+ GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
+ const WORD old_color_attrs = buffer_info.wAttributes;
+
+ // We need to flush the stream buffers into the console before each
+ // SetConsoleTextAttribute call lest it affect the text that is already
+ // printed but has not yet reached the console.
+ fflush(stdout);
+ SetConsoleTextAttribute(stdout_handle,
+ GetColorAttribute(color) | FOREGROUND_INTENSITY);
+ vprintf(fmt, args);
+
+ fflush(stdout);
+ // Restores the text color.
+ SetConsoleTextAttribute(stdout_handle, old_color_attrs);
+#else
+ printf("\033[0;3%sm", GetAnsiColorCode(color));
+ vprintf(fmt, args);
+ printf("\033[m"); // Resets the terminal to default.
+#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+ va_end(args);
+}
+
+// This class implements the TestEventListener interface.
+//
+// Class PrettyUnitTestResultPrinter is copyable.
+class PrettyUnitTestResultPrinter : public TestEventListener {
+ public:
+ PrettyUnitTestResultPrinter() {}
+ static void PrintTestName(const char * test_case, const char * test) {
+ printf("%s.%s", test_case, test);
+ }
+
+ // The following methods override what's in the TestEventListener class.
+ virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+ virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+ virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestCaseStart(const TestCase& test_case);
+ virtual void OnTestStart(const TestInfo& test_info);
+ virtual void OnTestPartResult(const TestPartResult& result);
+ virtual void OnTestEnd(const TestInfo& test_info);
+ virtual void OnTestCaseEnd(const TestCase& test_case);
+ virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+ virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+ virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+
+ private:
+ static void PrintFailedTests(const UnitTest& unit_test);
+
+ internal::String test_case_name_;
+};
+
+ // Fired before each iteration of tests starts.
+void PrettyUnitTestResultPrinter::OnTestIterationStart(
+ const UnitTest& unit_test, int iteration) {
+ if (GTEST_FLAG(repeat) != 1)
+ printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
+
+ const char* const filter = GTEST_FLAG(filter).c_str();
+
+ // Prints the filter if it's not *. This reminds the user that some
+ // tests may be skipped.
+ if (!internal::String::CStringEquals(filter, kUniversalFilter)) {
+ ColoredPrintf(COLOR_YELLOW,
+ "Note: %s filter = %s\n", GTEST_NAME_, filter);
+ }
+
+ if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+ ColoredPrintf(COLOR_YELLOW,
+ "Note: This is test shard %s of %s.\n",
+ internal::posix::GetEnv(kTestShardIndex),
+ internal::posix::GetEnv(kTestTotalShards));
+ }
+
+ if (GTEST_FLAG(shuffle)) {
+ ColoredPrintf(COLOR_YELLOW,
+ "Note: Randomizing tests' orders with a seed of %d .\n",
+ unit_test.random_seed());
+ }
+
+ ColoredPrintf(COLOR_GREEN, "[==========] ");
+ printf("Running %s from %s.\n",
+ FormatTestCount(unit_test.test_to_run_count()).c_str(),
+ FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
+ const UnitTest& /*unit_test*/) {
+ ColoredPrintf(COLOR_GREEN, "[----------] ");
+ printf("Global test environment set-up.\n");
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
+ test_case_name_ = test_case.name();
+ const internal::String counts =
+ 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') {
+ printf("\n");
+ } else {
+ printf(", where %s\n", test_case.comment());
+ }
+ fflush(stdout);
+}
+
+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());
+ }
+ fflush(stdout);
+}
+
+// Called after an assertion failure.
+void PrettyUnitTestResultPrinter::OnTestPartResult(
+ const TestPartResult& result) {
+ // If the test part succeeded, we don't need to do anything.
+ if (result.type() == TestPartResult::kSuccess)
+ return;
+
+ // Print failure message from the assertion (e.g. expected this and got that).
+ PrintTestPartResult(result);
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+ if (test_info.result()->Passed()) {
+ ColoredPrintf(COLOR_GREEN, "[ OK ] ");
+ } else {
+ ColoredPrintf(COLOR_RED, "[ FAILED ] ");
+ }
+ PrintTestName(test_case_name_.c_str(), test_info.name());
+ if (GTEST_FLAG(print_time)) {
+ printf(" (%s ms)\n", internal::StreamableToString(
+ test_info.result()->elapsed_time()).c_str());
+ } else {
+ printf("\n");
+ }
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
+ if (!GTEST_FLAG(print_time)) return;
+
+ test_case_name_ = test_case.name();
+ const internal::String counts =
+ FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+ ColoredPrintf(COLOR_GREEN, "[----------] ");
+ printf("%s from %s (%s ms total)\n\n",
+ counts.c_str(), test_case_name_.c_str(),
+ internal::StreamableToString(test_case.elapsed_time()).c_str());
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
+ const UnitTest& /*unit_test*/) {
+ ColoredPrintf(COLOR_GREEN, "[----------] ");
+ printf("Global test environment tear-down\n");
+ fflush(stdout);
+}
+
+// Internal helper for printing the list of failed tests.
+void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
+ const int failed_test_count = unit_test.failed_test_count();
+ if (failed_test_count == 0) {
+ return;
+ }
+
+ for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+ const TestCase& test_case = *unit_test.GetTestCase(i);
+ if (!test_case.should_run() || (test_case.failed_test_count() == 0)) {
+ continue;
+ }
+ for (int j = 0; j < test_case.total_test_count(); ++j) {
+ const TestInfo& test_info = *test_case.GetTestInfo(j);
+ if (!test_info.should_run() || test_info.result()->Passed()) {
+ continue;
+ }
+ 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());
+ }
+ }
+}
+
+ 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(),
+ FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+ if (GTEST_FLAG(print_time)) {
+ printf(" (%s ms total)",
+ internal::StreamableToString(unit_test.elapsed_time()).c_str());
+ }
+ printf("\n");
+ ColoredPrintf(COLOR_GREEN, "[ PASSED ] ");
+ printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+ int num_failures = unit_test.failed_test_count();
+ if (!unit_test.Passed()) {
+ const int failed_test_count = unit_test.failed_test_count();
+ ColoredPrintf(COLOR_RED, "[ FAILED ] ");
+ printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
+ PrintFailedTests(unit_test);
+ printf("\n%2d FAILED %s\n", num_failures,
+ num_failures == 1 ? "TEST" : "TESTS");
+ }
+
+ int num_disabled = unit_test.disabled_test_count();
+ if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
+ if (!num_failures) {
+ printf("\n"); // Add a spacer if no FAILURE banner is displayed.
+ }
+ ColoredPrintf(COLOR_YELLOW,
+ " YOU HAVE %d DISABLED %s\n\n",
+ num_disabled,
+ num_disabled == 1 ? "TEST" : "TESTS");
+ }
+ // Ensure that Google Test output is printed before, e.g., heapchecker output.
+ fflush(stdout);
+}
+
+// End PrettyUnitTestResultPrinter
+
+// class TestEventRepeater
+//
+// This class forwards events to other event listeners.
+class TestEventRepeater : public TestEventListener {
+ public:
+ TestEventRepeater() : forwarding_enabled_(true) {}
+ virtual ~TestEventRepeater();
+ void Append(TestEventListener *listener);
+ TestEventListener* Release(TestEventListener* listener);
+
+ // Controls whether events will be forwarded to listeners_. Set to false
+ // in death test child processes.
+ bool forwarding_enabled() const { return forwarding_enabled_; }
+ void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
+
+ virtual void OnTestProgramStart(const UnitTest& unit_test);
+ virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+ virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+ virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test);
+ virtual void OnTestCaseStart(const TestCase& test_case);
+ virtual void OnTestStart(const TestInfo& test_info);
+ virtual void OnTestPartResult(const TestPartResult& result);
+ virtual void OnTestEnd(const TestInfo& test_info);
+ virtual void OnTestCaseEnd(const TestCase& test_case);
+ virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+ virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test);
+ virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+ virtual void OnTestProgramEnd(const UnitTest& unit_test);
+
+ private:
+ // Controls whether events will be forwarded to listeners_. Set to false
+ // in death test child processes.
+ bool forwarding_enabled_;
+ // The list of listeners that receive events.
+ std::vector<TestEventListener*> listeners_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
+};
+
+TestEventRepeater::~TestEventRepeater() {
+ ForEach(listeners_, Delete<TestEventListener>);
+}
+
+void TestEventRepeater::Append(TestEventListener *listener) {
+ listeners_.push_back(listener);
+}
+
+// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
+TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
+ for (size_t i = 0; i < listeners_.size(); ++i) {
+ if (listeners_[i] == listener) {
+ listeners_.erase(listeners_.begin() + i);
+ return listener;
+ }
+ }
+
+ return NULL;
+}
+
+// Since most methods are very similar, use macros to reduce boilerplate.
+// This defines a member that forwards the call to all listeners.
+#define GTEST_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+ if (forwarding_enabled_) { \
+ for (size_t i = 0; i < listeners_.size(); i++) { \
+ listeners_[i]->Name(parameter); \
+ } \
+ } \
+}
+// This defines a member that forwards the call to all listeners in reverse
+// order.
+#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+ if (forwarding_enabled_) { \
+ for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
+ listeners_[i]->Name(parameter); \
+ } \
+ } \
+}
+
+GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase)
+GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
+GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
+
+#undef GTEST_REPEATER_METHOD_
+#undef GTEST_REVERSE_REPEATER_METHOD_
+
+void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
+ int iteration) {
+ if (forwarding_enabled_) {
+ for (size_t i = 0; i < listeners_.size(); i++) {
+ listeners_[i]->OnTestIterationStart(unit_test, iteration);
+ }
+ }
+}
+
+void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
+ int iteration) {
+ if (forwarding_enabled_) {
+ for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) {
+ listeners_[i]->OnTestIterationEnd(unit_test, iteration);
+ }
+ }
+}
+
+// End TestEventRepeater
+
+// This class generates an XML output file.
+class XmlUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+ explicit XmlUnitTestResultPrinter(const char* output_file);
+
+ virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+
+ private:
+ // Is c a whitespace character that is normalized to a space character
+ // when it appears in an XML attribute value?
+ static bool IsNormalizableWhitespace(char c) {
+ return c == 0x9 || c == 0xA || c == 0xD;
+ }
+
+ // May c appear in a well-formed XML document?
+ static bool IsValidXmlCharacter(char c) {
+ return IsNormalizableWhitespace(c) || c >= 0x20;
+ }
+
+ // Returns an XML-escaped copy of the input string str. If
+ // is_attribute is true, the text is meant to appear as an attribute
+ // value, and normalizable whitespace is preserved by replacing it
+ // with character references.
+ 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);
+
+ // Convenience wrapper around EscapeXml when str is an attribute value.
+ static String EscapeXmlAttribute(const char* str) {
+ return EscapeXml(str, true);
+ }
+
+ // Convenience wrapper around EscapeXml when str is not an attribute value.
+ static String EscapeXmlText(const char* str) { return EscapeXml(str, false); }
+
+ // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+ static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
+
+ // Streams an XML representation of a TestInfo object.
+ static void OutputXmlTestInfo(::std::ostream* stream,
+ const char* test_case_name,
+ const TestInfo& test_info);
+
+ // Prints an XML representation of a TestCase object
+ static void PrintXmlTestCase(FILE* out, const TestCase& test_case);
+
+ // Prints an XML summary of unit_test to output stream out.
+ static void PrintXmlUnitTest(FILE* out, const UnitTest& unit_test);
+
+ // Produces a string representing the test properties in a result as space
+ // delimited XML attributes based on the property key="value" pairs.
+ // When the String is not empty, it includes a space at the beginning,
+ // to delimit this attribute from prior attributes.
+ static String TestPropertiesAsXmlAttributes(const TestResult& result);
+
+ // The output file.
+ const String output_file_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
+};
+
+// Creates a new XmlUnitTestResultPrinter.
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
+ : output_file_(output_file) {
+ if (output_file_.c_str() == NULL || output_file_.empty()) {
+ fprintf(stderr, "XML output file may not be null\n");
+ fflush(stderr);
+ exit(EXIT_FAILURE);
+ }
+}
+
+// Called after the unit test ends.
+void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+ int /*iteration*/) {
+ FILE* xmlout = NULL;
+ FilePath output_file(output_file_);
+ FilePath output_dir(output_file.RemoveFileName());
+
+ if (output_dir.CreateDirectoriesRecursively()) {
+ xmlout = posix::FOpen(output_file_.c_str(), "w");
+ }
+ if (xmlout == NULL) {
+ // TODO(wan): report the reason of the failure.
+ //
+ // We don't do it for now as:
+ //
+ // 1. There is no urgent need for it.
+ // 2. It's a bit involved to make the errno variable thread-safe on
+ // all three operating systems (Linux, Windows, and Mac OS).
+ // 3. To interpret the meaning of errno in a thread-safe way,
+ // we need the strerror_r() function, which is not available on
+ // Windows.
+ fprintf(stderr,
+ "Unable to open file \"%s\"\n",
+ output_file_.c_str());
+ fflush(stderr);
+ exit(EXIT_FAILURE);
+ }
+ PrintXmlUnitTest(xmlout, unit_test);
+ fclose(xmlout);
+}
+
+// Returns an XML-escaped copy of the input string str. If is_attribute
+// is true, the text is meant to appear as an attribute value, and
+// normalizable whitespace is preserved by replacing it with character
+// references.
+//
+// Invalid XML characters in str, if any, are stripped from the output.
+// It is expected that most, if not all, of the text processed by this
+// module will consist of ordinary English text.
+// If this module is ever modified to produce version 1.1 XML output,
+// most invalid characters can be retained using character references.
+// TODO(wan): It might be nice to have a minimally invasive, human-readable
+// escaping scheme for invalid characters, rather than dropping them.
+String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) {
+ Message m;
+
+ if (str != NULL) {
+ for (const char* src = str; *src; ++src) {
+ switch (*src) {
+ case '<':
+ m << "&lt;";
+ break;
+ case '>':
+ m << "&gt;";
+ break;
+ case '&':
+ m << "&amp;";
+ break;
+ case '\'':
+ if (is_attribute)
+ m << "&apos;";
+ else
+ m << '\'';
+ break;
+ case '"':
+ if (is_attribute)
+ m << "&quot;";
+ else
+ m << '"';
+ break;
+ default:
+ if (IsValidXmlCharacter(*src)) {
+ if (is_attribute && IsNormalizableWhitespace(*src))
+ m << String::Format("&#x%02X;", unsigned(*src));
+ else
+ m << *src;
+ }
+ break;
+ }
+ }
+ }
+
+ return m.GetString();
+}
+
+// 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;
+}
+
+// The following routines generate an XML representation of a UnitTest
+// object.
+//
+// This is how Google Test concepts map to the DTD:
+//
+// <testsuites name="AllTests"> <-- corresponds to a UnitTest object
+// <testsuite name="testcase-name"> <-- corresponds to a TestCase object
+// <testcase name="test-name"> <-- corresponds to a TestInfo object
+// <failure message="...">...</failure>
+// <failure message="...">...</failure>
+// <failure message="...">...</failure>
+// <-- individual assertion failures
+// </testcase>
+// </testsuite>
+// </testsuites>
+
+// Formats the given time in milliseconds as seconds.
+std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
+ ::std::stringstream ss;
+ ss << ms/1000.0;
+ return ss.str();
+}
+
+// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
+ const char* data) {
+ const char* segment = data;
+ *stream << "<![CDATA[";
+ for (;;) {
+ const char* const next_segment = strstr(segment, "]]>");
+ if (next_segment != NULL) {
+ stream->write(
+ segment, static_cast<std::streamsize>(next_segment - segment));
+ *stream << "]]>]]&gt;<![CDATA[";
+ segment = next_segment + strlen("]]>");
+ } else {
+ *stream << segment;
+ break;
+ }
+ }
+ *stream << "]]>";
+}
+
+// Prints an XML representation of a TestInfo object.
+// TODO(wan): There is also value in printing properties with the plain printer.
+void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
+ const char* test_case_name,
+ const TestInfo& test_info) {
+ const TestResult& result = *test_info.result();
+ *stream << " <testcase name=\""
+ << EscapeXmlAttribute(test_info.name()).c_str()
+ << "\" status=\""
+ << (test_info.should_run() ? "run" : "notrun")
+ << "\" time=\""
+ << FormatTimeInMillisAsSeconds(result.elapsed_time())
+ << "\" classname=\"" << EscapeXmlAttribute(test_case_name).c_str()
+ << "\"" << TestPropertiesAsXmlAttributes(result).c_str();
+
+ int failures = 0;
+ for (int i = 0; i < result.total_part_count(); ++i) {
+ const TestPartResult& part = result.GetTestPartResult(i);
+ if (part.failed()) {
+ if (++failures == 1)
+ *stream << ">\n";
+ *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());
+ *stream << "</failure>\n";
+ }
+ }
+
+ if (failures == 0)
+ *stream << " />\n";
+ else
+ *stream << " </testcase>\n";
+}
+
+// Prints an XML representation of a TestCase object
+void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
+ const TestCase& test_case) {
+ fprintf(out,
+ " <testsuite name=\"%s\" tests=\"%d\" failures=\"%d\" "
+ "disabled=\"%d\" ",
+ EscapeXmlAttribute(test_case.name()).c_str(),
+ test_case.total_test_count(),
+ test_case.failed_test_count(),
+ test_case.disabled_test_count());
+ fprintf(out,
+ "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;
+ OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i));
+ fprintf(out, "%s", StrStreamToString(&stream).c_str());
+ }
+ fprintf(out, " </testsuite>\n");
+}
+
+// Prints an XML summary of unit_test to output stream out.
+void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
+ const UnitTest& unit_test) {
+ fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ fprintf(out,
+ "<testsuites tests=\"%d\" failures=\"%d\" disabled=\"%d\" "
+ "errors=\"0\" time=\"%s\" ",
+ unit_test.total_test_count(),
+ unit_test.failed_test_count(),
+ unit_test.disabled_test_count(),
+ FormatTimeInMillisAsSeconds(unit_test.elapsed_time()).c_str());
+ if (GTEST_FLAG(shuffle)) {
+ fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
+ }
+ fprintf(out, "name=\"AllTests\">\n");
+ for (int i = 0; i < unit_test.total_test_case_count(); ++i)
+ PrintXmlTestCase(out, *unit_test.GetTestCase(i));
+ fprintf(out, "</testsuites>\n");
+}
+
+// Produces a string representing the test properties in a result as space
+// delimited XML attributes based on the property key="value" pairs.
+String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+ const TestResult& result) {
+ Message attributes;
+ for (int i = 0; i < result.test_property_count(); ++i) {
+ const TestProperty& property = result.GetTestProperty(i);
+ attributes << " " << property.key() << "="
+ << "\"" << EscapeXmlAttribute(property.value()) << "\"";
+ }
+ return attributes.GetString();
+}
+
+// End XmlUnitTestResultPrinter
+
+// Class ScopedTrace
+
+// Pushes the given source file location and message onto a per-thread
+// trace stack maintained by Google Test.
+// L < UnitTest::mutex_
+ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) {
+ TraceInfo trace;
+ trace.file = file;
+ trace.line = line;
+ trace.message = message.GetString();
+
+ UnitTest::GetInstance()->PushGTestTrace(trace);
+}
+
+// Pops the info pushed by the c'tor.
+// L < UnitTest::mutex_
+ScopedTrace::~ScopedTrace() {
+ UnitTest::GetInstance()->PopGTestTrace();
+}
+
+
+// class OsStackTraceGetter
+
+// Returns the current OS stack trace as a String. Parameters:
+//
+// max_depth - the maximum number of stack frames to be included
+// in the trace.
+// skip_count - the number of top frames to be skipped; doesn't count
+// against max_depth.
+//
+// L < mutex_
+// We use "L < mutex_" to denote that the function may acquire mutex_.
+String OsStackTraceGetter::CurrentStackTrace(int, int) {
+ return String("");
+}
+
+// L < mutex_
+void OsStackTraceGetter::UponLeavingGTest() {
+}
+
+const char* const
+OsStackTraceGetter::kElidedFramesMarker =
+ "... " GTEST_NAME_ " internal frames ...";
+
+} // namespace internal
+
+// class TestEventListeners
+
+TestEventListeners::TestEventListeners()
+ : repeater_(new internal::TestEventRepeater()),
+ default_result_printer_(NULL),
+ default_xml_generator_(NULL) {
+}
+
+TestEventListeners::~TestEventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output. Can be removed from the listeners list to shut down default
+// console output. Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void TestEventListeners::Append(TestEventListener* listener) {
+ repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it. It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
+ if (listener == default_result_printer_)
+ default_result_printer_ = NULL;
+ else if (listener == default_xml_generator_)
+ default_xml_generator_ = NULL;
+ return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the TestEventListener events to all
+// subscribers.
+TestEventListener* TestEventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
+ if (default_result_printer_ != listener) {
+ // It is an error to pass this method a listener that is already in the
+ // list.
+ delete Release(default_result_printer_);
+ default_result_printer_ = listener;
+ if (listener != NULL)
+ Append(listener);
+ }
+}
+
+// Sets the default_xml_generator attribute to the provided listener. The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
+ if (default_xml_generator_ != listener) {
+ // It is an error to pass this method a listener that is already in the
+ // list.
+ delete Release(default_xml_generator_);
+ default_xml_generator_ = listener;
+ if (listener != NULL)
+ Append(listener);
+ }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool TestEventListeners::EventForwardingEnabled() const {
+ return repeater_->forwarding_enabled();
+}
+
+void TestEventListeners::SuppressEventForwarding() {
+ repeater_->set_forwarding_enabled(false);
+}
+
+// class UnitTest
+
+// Gets the singleton UnitTest object. The first time this method is
+// called, a UnitTest object is constructed and returned. Consecutive
+// calls will return the same object.
+//
+// We don't protect this under mutex_ as a user is not supposed to
+// call this before main() starts, from which point on the return
+// value will never change.
+UnitTest * UnitTest::GetInstance() {
+ // When compiled with MSVC 7.1 in optimized mode, destroying the
+ // UnitTest object upon exiting the program messes up the exit code,
+ // causing successful tests to appear failed. We have to use a
+ // different implementation in this case to bypass the compiler bug.
+ // This implementation makes the compiler happy, at the cost of
+ // leaking the UnitTest object.
+
+ // CodeGear C++Builder insists on a public destructor for the
+ // default implementation. Use this implementation to keep good OO
+ // design with private destructor.
+
+#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+ static UnitTest* const instance = new UnitTest;
+ return instance;
+#else
+ static UnitTest instance;
+ return &instance;
+#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+}
+
+// Gets the number of successful test cases.
+int UnitTest::successful_test_case_count() const {
+ return impl()->successful_test_case_count();
+}
+
+// Gets the number of failed test cases.
+int UnitTest::failed_test_case_count() const {
+ return impl()->failed_test_case_count();
+}
+
+// Gets the number of all test cases.
+int UnitTest::total_test_case_count() const {
+ return impl()->total_test_case_count();
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTest::test_case_to_run_count() const {
+ return impl()->test_case_to_run_count();
+}
+
+// Gets the number of successful tests.
+int UnitTest::successful_test_count() const {
+ return impl()->successful_test_count();
+}
+
+// Gets the number of failed tests.
+int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
+
+// Gets the number of disabled tests.
+int UnitTest::disabled_test_count() const {
+ return impl()->disabled_test_count();
+}
+
+// Gets the number of all tests.
+int UnitTest::total_test_count() const { return impl()->total_test_count(); }
+
+// Gets the number of tests that should run.
+int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+
+// Gets the elapsed time, in milliseconds.
+internal::TimeInMillis UnitTest::elapsed_time() const {
+ return impl()->elapsed_time();
+}
+
+// Returns true iff the unit test passed (i.e. all test cases passed).
+bool UnitTest::Passed() const { return impl()->Passed(); }
+
+// Returns true iff the unit test failed (i.e. some test case failed
+// or something outside of all tests failed).
+bool UnitTest::Failed() const { return impl()->Failed(); }
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+const TestCase* UnitTest::GetTestCase(int i) const {
+ return impl()->GetTestCase(i);
+}
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+TestCase* UnitTest::GetMutableTestCase(int i) {
+ return impl()->GetMutableTestCase(i);
+}
+
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+TestEventListeners& UnitTest::listeners() {
+ return *impl()->listeners();
+}
+
+// Registers and returns a global test environment. When a test
+// program is run, all global test environments will be set-up in the
+// order they were registered. After all tests in the program have
+// finished, all global test environments will be torn-down in the
+// *reverse* order they were registered.
+//
+// The UnitTest object takes ownership of the given environment.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+Environment* UnitTest::AddEnvironment(Environment* env) {
+ if (env == NULL) {
+ return NULL;
+ }
+
+ impl_->environments().push_back(env);
+ 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
+// assertion macros instead of calling this directly.
+// L < mutex_
+void UnitTest::AddTestPartResult(TestPartResult::Type result_type,
+ const char* file_name,
+ int line_number,
+ const internal::String& message,
+ const internal::String& os_stack_trace) {
+ Message msg;
+ msg << message;
+
+ internal::MutexLock lock(&mutex_);
+ if (impl_->gtest_trace_stack().size() > 0) {
+ msg << "\n" << GTEST_NAME_ << " trace:";
+
+ for (int i = static_cast<int>(impl_->gtest_trace_stack().size());
+ i > 0; --i) {
+ const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
+ msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
+ << " " << trace.message;
+ }
+ }
+
+ if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) {
+ msg << internal::kStackTraceMarker << os_stack_trace;
+ }
+
+ const TestPartResult result =
+ TestPartResult(result_type, file_name, line_number,
+ msg.GetString().c_str());
+ impl_->GetTestPartResultReporterForCurrentThread()->
+ ReportTestPartResult(result);
+
+ if (result_type != TestPartResult::kSuccess) {
+ // gtest_break_on_failure takes precedence over
+ // gtest_throw_on_failure. This allows a user to set the latter
+ // in the code (perhaps in order to use Google Test assertions
+ // with another testing framework) and specify the former on the
+ // command line for debugging.
+ if (GTEST_FLAG(break_on_failure)) {
+#if GTEST_OS_WINDOWS
+ // Using DebugBreak on Windows allows gtest to still break into a debugger
+ // when a failure happens and both the --gtest_break_on_failure and
+ // the --gtest_catch_exceptions flags are specified.
+ DebugBreak();
+#else
+ abort();
+#endif // GTEST_OS_WINDOWS
+ } else if (GTEST_FLAG(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+ throw GoogleTestFailureException(result);
+#else
+ // We cannot call abort() as it generates a pop-up in debug mode
+ // that cannot be suppressed in VC 7.1 or below.
+ exit(1);
+#endif
+ }
+ }
+}
+
+// Creates and adds a property to the current TestResult. If a property matching
+// the supplied value already exists, updates its value instead.
+void UnitTest::RecordPropertyForCurrentTest(const char* key,
+ const char* value) {
+ const TestProperty test_property(key, value);
+ impl_->current_test_result()->RecordProperty(test_property);
+}
+
+// Runs all tests in this UnitTest object and prints the result.
+// Returns 0 if successful, or 1 otherwise.
+//
+// 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.
+
+ 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
+ // SetErrorMode doesn't exist on CE.
+ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+ SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+#endif // !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
+
+#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
+ // executed. Google Test will notify the user of any unexpected
+ // failure via stderr.
+ //
+ // VC++ doesn't define _set_abort_behavior() prior to the version 8.0.
+ // Users of prior VC versions shall suffer the agony and pain of
+ // clicking through the countless debug dialogs.
+ // TODO(vladl@google.com): find a way to suppress the abort dialog() in the
+ // debug mode when compiled with VC 7.1 or lower.
+ if (!GTEST_FLAG(break_on_failure))
+ _set_abort_behavior(
+ 0x0, // Clear the following flags:
+ _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump.
+#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
+}
+
+// Returns the working directory when the first TEST() or TEST_F() was
+// executed.
+const char* UnitTest::original_working_dir() const {
+ return impl_->original_working_dir_.c_str();
+}
+
+// Returns the TestCase object for the test that's currently running,
+// or NULL if no test is running.
+// L < mutex_
+const TestCase* UnitTest::current_test_case() const {
+ internal::MutexLock lock(&mutex_);
+ return impl_->current_test_case();
+}
+
+// Returns the TestInfo object for the test that's currently running,
+// or NULL if no test is running.
+// L < mutex_
+const TestInfo* UnitTest::current_test_info() const {
+ internal::MutexLock lock(&mutex_);
+ return impl_->current_test_info();
+}
+
+// Returns the random seed used at the start of the current test run.
+int UnitTest::random_seed() const { return impl_->random_seed(); }
+
+#if GTEST_HAS_PARAM_TEST
+// Returns ParameterizedTestCaseRegistry object used to keep track of
+// value-parameterized tests and instantiate and register them.
+// L < mutex_
+internal::ParameterizedTestCaseRegistry&
+ UnitTest::parameterized_test_registry() {
+ return impl_->parameterized_test_registry();
+}
+#endif // GTEST_HAS_PARAM_TEST
+
+// Creates an empty UnitTest.
+UnitTest::UnitTest() {
+ impl_ = new internal::UnitTestImpl(this);
+}
+
+// Destructor of UnitTest.
+UnitTest::~UnitTest() {
+ delete impl_;
+}
+
+// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+// Google Test trace stack.
+// L < mutex_
+void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) {
+ internal::MutexLock lock(&mutex_);
+ impl_->gtest_trace_stack().push_back(trace);
+}
+
+// Pops a trace from the per-thread Google Test trace stack.
+// L < mutex_
+void UnitTest::PopGTestTrace() {
+ internal::MutexLock lock(&mutex_);
+ impl_->gtest_trace_stack().pop_back();
+}
+
+namespace internal {
+
+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
+ // (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.
+#else
+ default_global_test_part_result_reporter_(this),
+ default_per_thread_test_part_result_reporter_(this),
+#endif // _MSC_VER
+ global_test_part_result_repoter_(
+ &default_global_test_part_result_reporter_),
+ per_thread_test_part_result_reporter_(
+ &default_per_thread_test_part_result_reporter_),
+#if GTEST_HAS_PARAM_TEST
+ parameterized_test_registry_(),
+ parameterized_tests_registered_(false),
+#endif // GTEST_HAS_PARAM_TEST
+ last_death_test_case_(-1),
+ current_test_case_(NULL),
+ current_test_info_(NULL),
+ ad_hoc_test_result_(),
+ os_stack_trace_getter_(NULL),
+ 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),
+ internal_run_death_test_flag_(NULL),
+ death_test_factory_(new DefaultDeathTestFactory) {
+#else
+ elapsed_time_(0) {
+#endif // GTEST_HAS_DEATH_TEST
+ listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
+}
+
+UnitTestImpl::~UnitTestImpl() {
+ // Deletes every TestCase.
+ ForEach(test_cases_, internal::Delete<TestCase>);
+
+ // Deletes every Environment.
+ ForEach(environments_, internal::Delete<Environment>);
+
+ delete os_stack_trace_getter_;
+}
+
+#if GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+ if (internal_run_death_test_flag_.get() != NULL)
+ listeners()->SuppressEventForwarding();
+}
+#endif // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+ const String& output_format = UnitTestOptions::GetOutputFormat();
+ if (output_format == "xml") {
+ listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+ UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+ } else if (output_format != "") {
+ printf("WARNING: unrecognized output format \"%s\" ignored.\n",
+ output_format.c_str());
+ fflush(stdout);
+ }
+}
+
+// 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
+// this function is also called from RunAllTests. Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+ // Ensures that this function does not execute more than once.
+ if (!post_flag_parse_init_performed_) {
+ post_flag_parse_init_performed_ = true;
+
+#if GTEST_HAS_DEATH_TEST
+ InitDeathTestSubprocessControlInfo();
+ SuppressTestEventsIfInSubprocess();
+#endif // GTEST_HAS_DEATH_TEST
+
+ // Registers parameterized tests. This makes parameterized tests
+ // available to the UnitTest reflection API without running
+ // RUN_ALL_TESTS.
+ RegisterParameterizedTests();
+
+ // Configures listeners for XML output. This makes it possible for users
+ // to shut down the default XML output before invoking RUN_ALL_TESTS.
+ ConfigureXmlOutput();
+ }
+}
+
+// A predicate that checks the name of a TestCase against a known
+// value.
+//
+// This is used for implementation of the UnitTest class only. We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestCaseNameIs is copyable.
+class TestCaseNameIs {
+ public:
+ // Constructor.
+ explicit TestCaseNameIs(const String& name)
+ : name_(name) {}
+
+ // Returns true iff the name of test_case matches name_.
+ bool operator()(const TestCase* test_case) const {
+ return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0;
+ }
+
+ private:
+ String name_;
+};
+
+// Finds and returns a TestCase with the given name. If one doesn't
+// exist, creates one and returns it. It's the CALLER'S
+// RESPONSIBILITY to ensure that this function is only called WHEN THE
+// TESTS ARE NOT SHUFFLED.
+//
+// Arguments:
+//
+// test_case_name: name of the 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,
+ Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc) {
+ // Can we find a TestCase with the given name?
+ const std::vector<TestCase*>::const_iterator test_case =
+ std::find_if(test_cases_.begin(), test_cases_.end(),
+ TestCaseNameIs(test_case_name));
+
+ if (test_case != test_cases_.end())
+ return *test_case;
+
+ // No. Let's create one.
+ TestCase* const new_test_case =
+ new TestCase(test_case_name, comment, set_up_tc, tear_down_tc);
+
+ // Is this a death test case?
+ if (internal::UnitTestOptions::MatchesFilter(String(test_case_name),
+ kDeathTestCaseFilter)) {
+ // Yes. Inserts the test case after the last death test case
+ // defined so far. This only works when the test cases haven't
+ // been shuffled. Otherwise we may end up running a death test
+ // after a non-death test.
+ ++last_death_test_case_;
+ test_cases_.insert(test_cases_.begin() + last_death_test_case_,
+ new_test_case);
+ } else {
+ // No. Appends to the end of the list.
+ test_cases_.push_back(new_test_case);
+ }
+
+ test_case_indices_.push_back(static_cast<int>(test_case_indices_.size()));
+ return new_test_case;
+}
+
+// Helpers for setting up / tearing down the given environment. They
+// are for use in the ForEach() function.
+static void SetUpEnvironment(Environment* env) { env->SetUp(); }
+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.)
+// 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() {
+ // 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;
+ }
+
+ // Do not run any test if the --help flag was specified.
+ if (g_help_flag)
+ return 0;
+
+ // Repeats the call to the post-flag parsing initialization in case the
+ // user didn't call InitGoogleTest.
+ PostFlagParsingInit();
+
+ // Even if sharding is not on, test runners may want to use the
+ // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
+ // protocol.
+ internal::WriteToShardStatusFileIfNeeded();
+
+ // True iff we are in a subprocess for running a thread-safe-style
+ // death test.
+ bool in_subprocess_for_death_test = false;
+
+#if GTEST_HAS_DEATH_TEST
+ in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
+#endif // GTEST_HAS_DEATH_TEST
+
+ const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
+ in_subprocess_for_death_test);
+
+ // Compares the full test names with the filter to decide which
+ // tests to run.
+ const bool has_tests_to_run = FilterTests(should_shard
+ ? HONOR_SHARDING_PROTOCOL
+ : IGNORE_SHARDING_PROTOCOL) > 0;
+
+ // Lists the tests and exits if the --gtest_list_tests flag was specified.
+ if (GTEST_FLAG(list_tests)) {
+ // This must be called *after* FilterTests() has been called.
+ ListTestsMatchingFilter();
+ return 0;
+ }
+
+ random_seed_ = GTEST_FLAG(shuffle) ?
+ GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;
+
+ // True iff at least one test has failed.
+ bool failed = false;
+
+ TestEventListener* repeater = listeners()->repeater();
+
+ repeater->OnTestProgramStart(*parent_);
+
+ // How many times to repeat the tests? We don't want to repeat them
+ // when we are inside the subprocess of a death test.
+ const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
+ // Repeats forever if the repeat count is negative.
+ const bool forever = repeat < 0;
+ for (int i = 0; forever || i != repeat; i++) {
+ ClearResult();
+
+ const TimeInMillis start = GetTimeInMillis();
+
+ // Shuffles test cases and tests if requested.
+ if (has_tests_to_run && GTEST_FLAG(shuffle)) {
+ random()->Reseed(random_seed_);
+ // This should be done before calling OnTestIterationStart(),
+ // such that a test event listener can see the actual test order
+ // in the event.
+ ShuffleTests();
+ }
+
+ // Tells the unit test event listeners that the tests are about to start.
+ repeater->OnTestIterationStart(*parent_, i);
+
+ // Runs each test case if there is at least one test to run.
+ if (has_tests_to_run) {
+ // Sets up all environments beforehand.
+ repeater->OnEnvironmentsSetUpStart(*parent_);
+ ForEach(environments_, SetUpEnvironment);
+ repeater->OnEnvironmentsSetUpEnd(*parent_);
+
+ // Runs the tests only if there was no fatal failure during global
+ // set-up.
+ if (!Test::HasFatalFailure()) {
+ for (int test_index = 0; test_index < total_test_case_count();
+ test_index++) {
+ GetMutableTestCase(test_index)->Run();
+ }
+ }
+
+ // Tears down all environments in reverse order afterwards.
+ repeater->OnEnvironmentsTearDownStart(*parent_);
+ std::for_each(environments_.rbegin(), environments_.rend(),
+ TearDownEnvironment);
+ repeater->OnEnvironmentsTearDownEnd(*parent_);
+ }
+
+ elapsed_time_ = GetTimeInMillis() - start;
+
+ // Tells the unit test event listener that the tests have just finished.
+ repeater->OnTestIterationEnd(*parent_, i);
+
+ // Gets the result and clears it.
+ if (!Passed()) {
+ failed = true;
+ }
+
+ // Restores the original test order after the iteration. This
+ // allows the user to quickly repro a failure that happens in the
+ // N-th iteration without repeating the first (N - 1) iterations.
+ // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
+ // case the user somehow changes the value of the flag somewhere
+ // (it's always safe to unshuffle the tests).
+ UnshuffleTests();
+
+ if (GTEST_FLAG(shuffle)) {
+ // Picks a new random seed for each iteration.
+ random_seed_ = GetNextRandomSeed(random_seed_);
+ }
+ }
+
+ repeater->OnTestProgramEnd(*parent_);
+
+ // Returns 0 if all tests passed, or 1 other wise.
+ return failed ? 1 : 0;
+}
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded() {
+ const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
+ if (test_shard_file != NULL) {
+ FILE* const file = posix::FOpen(test_shard_file, "w");
+ if (file == NULL) {
+ ColoredPrintf(COLOR_RED,
+ "Could not write to the test shard status file \"%s\" "
+ "specified by the %s environment variable.\n",
+ test_shard_file, kTestShardStatusFile);
+ fflush(stdout);
+ exit(EXIT_FAILURE);
+ }
+ fclose(file);
+ }
+}
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (i.e., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+bool ShouldShard(const char* total_shards_env,
+ const char* shard_index_env,
+ bool in_subprocess_for_death_test) {
+ if (in_subprocess_for_death_test) {
+ return false;
+ }
+
+ const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1);
+ const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1);
+
+ if (total_shards == -1 && shard_index == -1) {
+ return false;
+ } else if (total_shards == -1 && shard_index != -1) {
+ const Message msg = Message()
+ << "Invalid environment variables: you have "
+ << kTestShardIndex << " = " << shard_index
+ << ", but have left " << kTestTotalShards << " unset.\n";
+ ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+ fflush(stdout);
+ exit(EXIT_FAILURE);
+ } else if (total_shards != -1 && shard_index == -1) {
+ const Message msg = Message()
+ << "Invalid environment variables: you have "
+ << kTestTotalShards << " = " << total_shards
+ << ", but have left " << kTestShardIndex << " unset.\n";
+ ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+ fflush(stdout);
+ exit(EXIT_FAILURE);
+ } else if (shard_index < 0 || shard_index >= total_shards) {
+ const Message msg = Message()
+ << "Invalid environment variables: we require 0 <= "
+ << kTestShardIndex << " < " << kTestTotalShards
+ << ", but you have " << kTestShardIndex << "=" << shard_index
+ << ", " << kTestTotalShards << "=" << total_shards << ".\n";
+ ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+ fflush(stdout);
+ exit(EXIT_FAILURE);
+ }
+
+ return total_shards > 1;
+}
+
+// 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) {
+ const char* str_val = posix::GetEnv(var);
+ if (str_val == NULL) {
+ return default_val;
+ }
+
+ Int32 result;
+ if (!ParseInt32(Message() << "The value of environment variable " << var,
+ str_val, &result)) {
+ exit(EXIT_FAILURE);
+ }
+ return result;
+}
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
+ return (test_id % total_shards) == shard_index;
+}
+
+// Compares the name of each test with the user-specified filter to
+// decide whether the test should be run, then records the result in
+// each TestCase and TestInfo object.
+// If shard_tests == true, further filters tests based on sharding
+// variables in the environment - see
+// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide.
+// Returns the number of tests that should run.
+int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
+ const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
+ Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
+ const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ?
+ Int32FromEnvOrDie(kTestShardIndex, -1) : -1;
+
+ // num_runnable_tests are the number of tests that will
+ // run across all shards (i.e., match filter and are not disabled).
+ // num_selected_tests are the number of tests to be run on
+ // this shard.
+ int num_runnable_tests = 0;
+ int num_selected_tests = 0;
+ for (size_t i = 0; i < test_cases_.size(); i++) {
+ TestCase* const test_case = test_cases_[i];
+ const String &test_case_name = test_case->name();
+ test_case->set_should_run(false);
+
+ for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+ TestInfo* const test_info = test_case->test_info_list()[j];
+ const String test_name(test_info->name());
+ // A test is disabled if test case name or test name matches
+ // kDisableTestFilter.
+ const bool is_disabled =
+ internal::UnitTestOptions::MatchesFilter(test_case_name,
+ kDisableTestFilter) ||
+ internal::UnitTestOptions::MatchesFilter(test_name,
+ kDisableTestFilter);
+ test_info->impl()->set_is_disabled(is_disabled);
+
+ const bool matches_filter =
+ internal::UnitTestOptions::FilterMatchesTest(test_case_name,
+ test_name);
+ test_info->impl()->set_matches_filter(matches_filter);
+
+ const bool is_runnable =
+ (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
+ matches_filter;
+
+ const bool is_selected = is_runnable &&
+ (shard_tests == IGNORE_SHARDING_PROTOCOL ||
+ ShouldRunTestOnShard(total_shards, shard_index,
+ num_runnable_tests));
+
+ num_runnable_tests += is_runnable;
+ num_selected_tests += is_selected;
+
+ test_info->impl()->set_should_run(is_selected);
+ test_case->set_should_run(test_case->should_run() || is_selected);
+ }
+ }
+ return num_selected_tests;
+}
+
+// Prints the names of the tests matching the user-specified filter flag.
+void UnitTestImpl::ListTestsMatchingFilter() {
+ for (size_t i = 0; i < test_cases_.size(); i++) {
+ const TestCase* const test_case = test_cases_[i];
+ bool printed_test_case_name = false;
+
+ 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 (!printed_test_case_name) {
+ printed_test_case_name = true;
+ printf("%s.\n", test_case->name());
+ }
+ printf(" %s\n", test_info->name());
+ }
+ }
+ }
+ fflush(stdout);
+}
+
+// Sets the OS stack trace getter.
+//
+// Does nothing if the input and the current OS stack trace getter are
+// the same; otherwise, deletes the old getter and makes the input the
+// current getter.
+void UnitTestImpl::set_os_stack_trace_getter(
+ OsStackTraceGetterInterface* getter) {
+ if (os_stack_trace_getter_ != getter) {
+ delete os_stack_trace_getter_;
+ os_stack_trace_getter_ = getter;
+ }
+}
+
+// Returns the current OS stack trace getter if it is not NULL;
+// otherwise, creates an OsStackTraceGetter, makes it the current
+// getter, and returns it.
+OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
+ if (os_stack_trace_getter_ == NULL) {
+ os_stack_trace_getter_ = new OsStackTraceGetter;
+ }
+
+ return os_stack_trace_getter_;
+}
+
+// Returns the TestResult for the test that's currently running, or
+// 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_;
+}
+
+// Shuffles all test cases, and the tests within each test case,
+// making sure that death tests are still run first.
+void UnitTestImpl::ShuffleTests() {
+ // Shuffles the death test cases.
+ ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_);
+
+ // Shuffles the non-death test cases.
+ ShuffleRange(random(), last_death_test_case_ + 1,
+ static_cast<int>(test_cases_.size()), &test_case_indices_);
+
+ // Shuffles the tests inside each test case.
+ for (size_t i = 0; i < test_cases_.size(); i++) {
+ test_cases_[i]->ShuffleTests(random());
+ }
+}
+
+// Restores the test cases and tests to their order before the first shuffle.
+void UnitTestImpl::UnshuffleTests() {
+ for (size_t i = 0; i < test_cases_.size(); i++) {
+ // Unshuffles the tests in each test case.
+ test_cases_[i]->UnshuffleTests();
+ // Resets the index of each test case.
+ test_case_indices_[i] = static_cast<int>(i);
+ }
+}
+
+// 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
+// the gtest_stack_trace_depth flag. The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+String GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
+ int skip_count) {
+ // We pass skip_count + 1 to skip this wrapper function in addition
+ // to what the user really wants to skip.
+ return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
+}
+
+// Used by the GTEST_HIDE_UNREACHABLE_CODE_ macro to suppress unreachable
+// code warnings.
+namespace {
+class ClassUniqueToAlwaysTrue {};
+}
+
+bool IsTrue(bool condition) { return condition; }
+
+bool AlwaysTrue() {
+#if GTEST_HAS_EXCEPTIONS
+ // This condition is always false so AlwaysTrue() never actually throws,
+ // but it makes the compiler think that it may throw.
+ if (IsTrue(false))
+ throw ClassUniqueToAlwaysTrue();
+#endif // GTEST_HAS_EXCEPTIONS
+ return true;
+}
+
+// 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) {
+ const size_t prefix_len = strlen(prefix);
+ if (strncmp(*pstr, prefix, prefix_len) == 0) {
+ *pstr += prefix_len;
+ return true;
+ }
+ return false;
+}
+
+// Parses a string as a command line flag. The string should have
+// the format "--flag=value". When def_optional is true, the "=value"
+// part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+const char* ParseFlagValue(const char* str,
+ const char* flag,
+ bool def_optional) {
+ // str and flag must not be NULL.
+ if (str == NULL || flag == NULL) return NULL;
+
+ // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
+ const String flag_str = String::Format("--%s%s", GTEST_FLAG_PREFIX_, flag);
+ const size_t flag_len = flag_str.length();
+ if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+ // Skips the flag name.
+ const char* flag_end = str + flag_len;
+
+ // When def_optional is true, it's OK to not have a "=value" part.
+ if (def_optional && (flag_end[0] == '\0')) {
+ return flag_end;
+ }
+
+ // If def_optional is true and there are more characters after the
+ // flag name, or if def_optional is false, there must be a '=' after
+ // the flag name.
+ if (flag_end[0] != '=') return NULL;
+
+ // Returns the string after "=".
+ return flag_end + 1;
+}
+
+// Parses a string for a bool flag, in the form of either
+// "--flag=value" or "--flag".
+//
+// In the former case, the value is taken as true as long as it does
+// not start with '0', 'f', or 'F'.
+//
+// In the latter case, the value is taken as true.
+//
+// On success, stores the value of the flag in *value, and returns
+// true. On failure, returns false without changing *value.
+bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
+ // Gets the value of the flag as a string.
+ const char* const value_str = ParseFlagValue(str, flag, true);
+
+ // Aborts if the parsing failed.
+ if (value_str == NULL) return false;
+
+ // Converts the string value to a bool.
+ *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+ return true;
+}
+
+// Parses a string for an Int32 flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true. On failure, returns false without changing *value.
+bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
+ // Gets the value of the flag as a string.
+ const char* const value_str = ParseFlagValue(str, flag, false);
+
+ // Aborts if the parsing failed.
+ if (value_str == NULL) return false;
+
+ // Sets *value to the value of the flag.
+ return ParseInt32(Message() << "The value of flag --" << flag,
+ value_str, value);
+}
+
+// Parses a string for a string flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true. On failure, returns false without changing *value.
+bool ParseStringFlag(const char* str, const char* flag, String* value) {
+ // Gets the value of the flag as a string.
+ const char* const value_str = ParseFlagValue(str, flag, false);
+
+ // Aborts if the parsing failed.
+ if (value_str == NULL) return false;
+
+ // Sets *value to the value of the flag.
+ *value = value_str;
+ return true;
+}
+
+// Determines whether a string has a prefix that Google Test uses for its
+// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
+// If Google Test detects that a command line flag has its prefix but is not
+// recognized, it will print its help message. Flags starting with
+// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
+// internal flags and do not trigger the help message.
+static bool HasGoogleTestFlagPrefix(const char* str) {
+ return (SkipPrefix("--", &str) ||
+ SkipPrefix("-", &str) ||
+ SkipPrefix("/", &str)) &&
+ !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
+ (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
+ SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
+}
+
+// Prints a string containing code-encoded text. The following escape
+// sequences can be used in the string to control the text color:
+//
+// @@ prints a single '@' character.
+// @R changes the color to red.
+// @G changes the color to green.
+// @Y changes the color to yellow.
+// @D changes to the default terminal text color.
+//
+// TODO(wan@google.com): Write tests for this once we add stdout
+// capturing to Google Test.
+static void PrintColorEncoded(const char* str) {
+ GTestColor color = COLOR_DEFAULT; // The current color.
+
+ // Conceptually, we split the string into segments divided by escape
+ // sequences. Then we print one segment at a time. At the end of
+ // each iteration, the str pointer advances to the beginning of the
+ // next segment.
+ for (;;) {
+ const char* p = strchr(str, '@');
+ if (p == NULL) {
+ ColoredPrintf(color, "%s", str);
+ return;
+ }
+
+ ColoredPrintf(color, "%s", String(str, p - str).c_str());
+
+ const char ch = p[1];
+ str = p + 2;
+ if (ch == '@') {
+ ColoredPrintf(color, "@");
+ } else if (ch == 'D') {
+ color = COLOR_DEFAULT;
+ } else if (ch == 'R') {
+ color = COLOR_RED;
+ } else if (ch == 'G') {
+ color = COLOR_GREEN;
+ } else if (ch == 'Y') {
+ color = COLOR_YELLOW;
+ } else {
+ --str;
+ }
+ }
+}
+
+static const char kColorEncodedHelpMessage[] =
+"This program contains tests written using " GTEST_NAME_ ". You can use the\n"
+"following command line flags to control its behavior:\n"
+"\n"
+"Test Selection:\n"
+" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n"
+" List the names of all tests instead of running them. The name of\n"
+" TEST(Foo, Bar) is \"Foo.Bar\".\n"
+" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS"
+ "[@G-@YNEGATIVE_PATTERNS]@D\n"
+" Run only the tests whose name matches one of the positive patterns but\n"
+" none of the negative patterns. '?' matches any single character; '*'\n"
+" matches any substring; ':' separates two patterns.\n"
+" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n"
+" Run all disabled tests too.\n"
+"\n"
+"Test Execution:\n"
+" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n"
+" Run the tests repeatedly; use a negative count to repeat forever.\n"
+" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n"
+" Randomize tests' orders on every iteration.\n"
+" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n"
+" Random number seed to use for shuffling test orders (between 1 and\n"
+" 99999, or 0 to use a seed based on the current time).\n"
+"\n"
+"Test Output:\n"
+" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
+" Enable/disable colored output. The default is @Gauto@D.\n"
+" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n"
+" Don't print the elapsed time of each test.\n"
+" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G"
+ 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@D defaults to @Gtest_details.xml@D.\n"
+"\n"
+"Assertion Behavior:\n"
+#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
+" Set the default death test style.\n"
+#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
+" Turn assertion failures into debugger break-points.\n"
+" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
+" Turn assertion failures into C++ exceptions.\n"
+#if GTEST_OS_WINDOWS
+" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions@D\n"
+" Suppress pop-ups caused by exceptions.\n"
+#endif // GTEST_OS_WINDOWS
+"\n"
+"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set "
+ "the corresponding\n"
+"environment variable of a flag (all letters in upper-case). For example, to\n"
+"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_
+ "color=no@D or set\n"
+"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n"
+"\n"
+"For more information, please read the " GTEST_NAME_ " documentation at\n"
+"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n"
+"(not one in your own code or tests), please report it to\n"
+"@G<" GTEST_DEV_EMAIL_ ">@D.\n";
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test. The type parameter CharType can be
+// instantiated to either char or wchar_t.
+template <typename CharType>
+void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
+ for (int i = 1; i < *argc; i++) {
+ const String arg_string = StreamableToString(argv[i]);
+ const char* const arg = arg_string.c_str();
+
+ using internal::ParseBoolFlag;
+ using internal::ParseInt32Flag;
+ using internal::ParseStringFlag;
+
+ // Do we see a Google Test flag?
+ if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
+ &GTEST_FLAG(also_run_disabled_tests)) ||
+ ParseBoolFlag(arg, kBreakOnFailureFlag,
+ &GTEST_FLAG(break_on_failure)) ||
+ ParseBoolFlag(arg, kCatchExceptionsFlag,
+ &GTEST_FLAG(catch_exceptions)) ||
+ ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
+ ParseStringFlag(arg, kDeathTestStyleFlag,
+ &GTEST_FLAG(death_test_style)) ||
+ ParseBoolFlag(arg, kDeathTestUseFork,
+ &GTEST_FLAG(death_test_use_fork)) ||
+ ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
+ ParseStringFlag(arg, kInternalRunDeathTestFlag,
+ &GTEST_FLAG(internal_run_death_test)) ||
+ ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
+ ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
+ ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
+ ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
+ ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
+ ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
+ ParseInt32Flag(arg, kStackTraceDepthFlag,
+ &GTEST_FLAG(stack_trace_depth)) ||
+ ParseBoolFlag(arg, kThrowOnFailureFlag, &GTEST_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
+ // NULL. The following loop moves the trailing NULL element as
+ // well.
+ for (int j = i; j != *argc; j++) {
+ argv[j] = argv[j + 1];
+ }
+
+ // Decrements the argument count.
+ (*argc)--;
+
+ // We also need to decrement the iterator as we just removed
+ // an element.
+ i--;
+ } else if (arg_string == "--help" || arg_string == "-h" ||
+ arg_string == "-?" || arg_string == "/?" ||
+ HasGoogleTestFlagPrefix(arg)) {
+ // Both help flag and unrecognized Google Test flags (excluding
+ // internal ones) trigger help display.
+ g_help_flag = true;
+ }
+ }
+
+ if (g_help_flag) {
+ // We print the help here instead of in RUN_ALL_TESTS(), as the
+ // latter may not be called at all if the user is using Google
+ // Test with another testing framework.
+ PrintColorEncoded(kColorEncodedHelpMessage);
+ }
+}
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
+ ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
+ ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+
+// The internal implementation of InitGoogleTest().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleTestImpl(int* argc, CharType** argv) {
+ g_init_gtest_count++;
+
+ // We don't want to run the initialization code twice.
+ if (g_init_gtest_count != 1) return;
+
+ if (*argc <= 0) return;
+
+ 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);
+ GetUnitTestImpl()->PostFlagParsingInit();
+}
+
+} // namespace internal
+
+// Initializes Google Test. This must be called before calling
+// RUN_ALL_TESTS(). In particular, it parses a command line for the
+// flags that Google Test recognizes. Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned. Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+void InitGoogleTest(int* argc, char** argv) {
+ internal::InitGoogleTestImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleTest(int* argc, wchar_t** argv) {
+ internal::InitGoogleTestImpl(argc, argv);
+}
+
+} // namespace testing
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-death-test.h b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-death-test.h
new file mode 100644
index 0000000..121dc1f
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-death-test.h
@@ -0,0 +1,283 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for death tests. It is
+// #included by gtest.h so a user doesn't need to include this
+// directly.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+
+#include <gtest/internal/gtest-death-test-internal.h>
+
+namespace testing {
+
+// This flag controls the style of death tests. Valid values are "threadsafe",
+// meaning that the death test child process will re-execute the test binary
+// from the start, running only a single death test, or "fast",
+// meaning that the child process will execute the test logic immediately
+// after forking.
+GTEST_DECLARE_string_(death_test_style);
+
+#if GTEST_HAS_DEATH_TEST
+
+// The following macros are useful for writing death tests.
+
+// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
+// executed:
+//
+// 1. It generates a warning if there is more than one active
+// thread. This is because it's safe to fork() or clone() only
+// when there is a single thread.
+//
+// 2. The parent process clone()s a sub-process and runs the death
+// test in it; the sub-process exits with code 0 at the end of the
+// death test, if it hasn't exited already.
+//
+// 3. The parent process waits for the sub-process to terminate.
+//
+// 4. The parent process checks the exit code and error message of
+// the sub-process.
+//
+// Examples:
+//
+// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
+// for (int i = 0; i < 5; i++) {
+// EXPECT_DEATH(server.ProcessRequest(i),
+// "Invalid request .* in ProcessRequest()")
+// << "Failed to die on request " << i);
+// }
+//
+// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
+//
+// bool KilledBySIGHUP(int exit_code) {
+// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
+// }
+//
+// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
+//
+// On the regular expressions used in death tests:
+//
+// On POSIX-compliant systems (*nix), we use the <regex.h> library,
+// which uses the POSIX extended regex syntax.
+//
+// On other platforms (e.g. Windows), we only support a simple regex
+// syntax implemented as part of Google Test. This limited
+// implementation should be enough most of the time when writing
+// death tests; though it lacks many features you can find in PCRE
+// or POSIX extended regex syntax. For example, we don't support
+// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
+// repetition count ("x{5,7}"), among others.
+//
+// Below is the syntax that we do support. We chose it to be a
+// subset of both PCRE and POSIX extended regex, so it's easy to
+// learn wherever you come from. In the following: 'A' denotes a
+// literal character, period (.), or a single \\ escape sequence;
+// 'x' and 'y' denote regular expressions; 'm' and 'n' are for
+// natural numbers.
+//
+// c matches any literal character c
+// \\d matches any decimal digit
+// \\D matches any character that's not a decimal digit
+// \\f matches \f
+// \\n matches \n
+// \\r matches \r
+// \\s matches any ASCII whitespace, including \n
+// \\S matches any character that's not a whitespace
+// \\t matches \t
+// \\v matches \v
+// \\w matches any letter, _, or decimal digit
+// \\W matches any character that \\w doesn't match
+// \\c matches any literal character c, which must be a punctuation
+// . matches any single character except \n
+// A? matches 0 or 1 occurrences of A
+// A* matches 0 or many occurrences of A
+// A+ matches 1 or many occurrences of A
+// ^ matches the beginning of a string (not that of each line)
+// $ matches the end of a string (not that of each line)
+// xy matches x followed by y
+//
+// If you accidentally use PCRE or POSIX extended regex features
+// not implemented by us, you will get a run-time failure. In that
+// case, please try to rewrite your regular expression within the
+// above syntax.
+//
+// This implementation is *not* meant to be as highly tuned or robust
+// as a compiled regex library, but should perform well enough for a
+// death test, which already incurs significant overhead by launching
+// a child process.
+//
+// Known caveats:
+//
+// A "threadsafe" style death test obtains the path to the test
+// program from argv[0] and re-executes it in the sub-process. For
+// simplicity, the current implementation doesn't search the PATH
+// when launching the sub-process. This means that the user must
+// invoke the test program via a path that contains at least one
+// path separator (e.g. path/to/foo_test and
+// /absolute/path/to/bar_test are fine, but foo_test is not). This
+// is rarely a problem as people usually don't put the test binary
+// directory in PATH.
+//
+// TODO(wan@google.com): make thread-safe death tests search the PATH.
+
+// 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_)
+
+// 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_)
+
+// 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)
+
+// 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)
+
+// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
+
+// Tests that an exit code describes a normal exit with a given exit code.
+class GTEST_API_ ExitedWithCode {
+ public:
+ explicit ExitedWithCode(int exit_code);
+ bool operator()(int exit_status) const;
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ExitedWithCode& other);
+
+ const int exit_code_;
+};
+
+#if !GTEST_OS_WINDOWS
+// Tests that an exit code describes an exit due to termination by a
+// given signal.
+class GTEST_API_ KilledBySignal {
+ public:
+ explicit KilledBySignal(int signum);
+ bool operator()(int exit_status) const;
+ private:
+ const int signum_;
+};
+#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,
+// since the sideeffects of the call are only visible in opt mode, and not
+// in debug mode.
+//
+// In practice, this can be used to test functions that utilize the
+// LOG(DFATAL) macro using the following style:
+//
+// int DieInDebugOr12(int* sideeffect) {
+// if (sideeffect) {
+// *sideeffect = 12;
+// }
+// LOG(DFATAL) << "death";
+// return 12;
+// }
+//
+// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
+// int sideeffect = 0;
+// // Only asserts in dbg.
+// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
+//
+// #ifdef NDEBUG
+// // opt-mode has sideeffect visible.
+// EXPECT_EQ(12, sideeffect);
+// #else
+// // dbg-mode no visible sideeffect.
+// EXPECT_EQ(0, sideeffect);
+// #endif
+// }
+//
+// This will assert that DieInDebugReturn12InOpt() crashes in debug
+// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
+// appropriate fallback value (12 in this case) in opt mode. If you
+// need to test that a function has appropriate side-effects in opt
+// mode, include assertions against the side-effects. A general
+// pattern for this is:
+//
+// EXPECT_DEBUG_DEATH({
+// // Side-effects here will have an effect after this statement in
+// // opt mode, but none in debug mode.
+// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
+// }, "death");
+//
+#ifdef NDEBUG
+
+#define EXPECT_DEBUG_DEATH(statement, regex) \
+ do { statement; } while (::testing::internal::AlwaysFalse())
+
+#define ASSERT_DEBUG_DEATH(statement, regex) \
+ do { statement; } while (::testing::internal::AlwaysFalse())
+
+#else
+
+#define EXPECT_DEBUG_DEATH(statement, regex) \
+ EXPECT_DEATH(statement, regex)
+
+#define ASSERT_DEBUG_DEATH(statement, regex) \
+ ASSERT_DEATH(statement, regex)
+
+#endif // NDEBUG for EXPECT_DEBUG_DEATH
+#endif // GTEST_HAS_DEATH_TEST
+
+// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
+// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
+// death tests are supported; otherwise they just issue a warning. This is
+// 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) \
+ EXPECT_DEATH(statement, regex)
+#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+ ASSERT_DEATH(statement, regex)
+#else
+#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+ GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
+#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+ GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
+#endif
+
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-message.h b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-message.h
new file mode 100644
index 0000000..f135b69
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-message.h
@@ -0,0 +1,230 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the Message class.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
+// program!
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+
+#include <limits>
+
+#include <gtest/internal/gtest-string.h>
+#include <gtest/internal/gtest-internal.h>
+
+namespace testing {
+
+// The Message class works like an ostream repeater.
+//
+// Typical usage:
+//
+// 1. You stream a bunch of values to a Message object.
+// It will remember the text in a StrStream.
+// 2. Then you stream the Message object to an ostream.
+// This causes the text in the Message to be streamed
+// to the ostream.
+//
+// For example;
+//
+// testing::Message foo;
+// foo << 1 << " != " << 2;
+// std::cout << foo;
+//
+// will print "1 != 2".
+//
+// 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
+// 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
+// "(null)".
+class GTEST_API_ Message {
+ private:
+ // The type of basic IO manipulators (endl, ends, and flush) for
+ // narrow streams.
+ typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
+
+ public:
+ // Constructs an empty Message.
+ // We allocate the StrStream separately because it 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) {
+ // 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
+ *ss_ << msg.GetString();
+ }
+
+ // Constructs a Message from a C-string.
+ explicit Message(const char* str) : ss_(new internal::StrStream) {
+ *ss_ << str;
+ }
+
+ ~Message() { delete ss_; }
+#if GTEST_OS_SYMBIAN
+ // Streams a value (either a pointer or not) to this object.
+ template <typename T>
+ inline Message& operator <<(const T& value) {
+ StreamHelper(typename internal::is_pointer<T>::type(), value);
+ return *this;
+ }
+#else
+ // Streams a non-pointer value to this object.
+ template <typename T>
+ inline Message& operator <<(const T& val) {
+ ::GTestStreamToHelper(ss_, val);
+ return *this;
+ }
+
+ // Streams a pointer value to this object.
+ //
+ // This function is an overload of the previous one. When you
+ // stream a pointer to a Message, this definition will be used as it
+ // is more specialized. (The C++ Standard, section
+ // [temp.func.order].) If you stream a non-pointer, then the
+ // previous definition will be used.
+ //
+ // The reason for this overload is that streaming a NULL pointer to
+ // ostream is undefined behavior. Depending on the compiler, you
+ // may get "0", "(nil)", "(null)", or an access violation. To
+ // ensure consistent result across compilers, we always treat NULL
+ // as "(null)".
+ template <typename T>
+ inline Message& operator <<(T* const& pointer) { // NOLINT
+ if (pointer == NULL) {
+ *ss_ << "(null)";
+ } else {
+ ::GTestStreamToHelper(ss_, pointer);
+ }
+ return *this;
+ }
+#endif // GTEST_OS_SYMBIAN
+
+ // Since the basic IO manipulators are overloaded for both narrow
+ // and wide streams, we have to provide this specialized definition
+ // of operator <<, even though its body is the same as the
+ // templatized version above. Without this definition, streaming
+ // endl or other basic IO manipulators to Message will confuse the
+ // compiler.
+ Message& operator <<(BasicNarrowIoManip val) {
+ *ss_ << val;
+ return *this;
+ }
+
+ // Instead of 1/0, we want to see true/false for bool values.
+ Message& operator <<(bool b) {
+ return *this << (b ? "true" : "false");
+ }
+
+ // These two overloads allow streaming a wide C string to a Message
+ // using the UTF-8 encoding.
+ Message& operator <<(const wchar_t* wide_c_str) {
+ return *this << internal::String::ShowWideCString(wide_c_str);
+ }
+ Message& operator <<(wchar_t* wide_c_str) {
+ return *this << internal::String::ShowWideCString(wide_c_str);
+ }
+
+#if GTEST_HAS_STD_WSTRING
+ // Converts the given wide string to a narrow string using the UTF-8
+ // encoding, and streams the result to this Message object.
+ Message& operator <<(const ::std::wstring& wstr);
+#endif // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+ // Converts the given wide string to a narrow string using the UTF-8
+ // encoding, and streams the result to this Message object.
+ Message& operator <<(const ::wstring& wstr);
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+ // Gets the text streamed to this object so far as a String.
+ // Each '\0' character in the buffer is replaced with "\\0".
+ //
+ // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+ internal::String GetString() const {
+ return internal::StrStreamToString(ss_);
+ }
+
+ 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_
+ // decide between class template specializations for T and T*, so a
+ // tr1::type_traits-like is_pointer works, and we can overload on that.
+ template <typename T>
+ inline void StreamHelper(internal::true_type /*dummy*/, T* pointer) {
+ if (pointer == NULL) {
+ *ss_ << "(null)";
+ } else {
+ ::GTestStreamToHelper(ss_, pointer);
+ }
+ }
+ template <typename T>
+ inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
+ ::GTestStreamToHelper(ss_, value);
+ }
+#endif // GTEST_OS_SYMBIAN
+
+ // We'll hold the text streamed to this object here.
+ internal::StrStream* const ss_;
+
+ // We declare (but don't implement) this to prevent the compiler
+ // from implementing the assignment operator.
+ void operator=(const Message&);
+};
+
+// Streams a Message to an ostream.
+inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
+ return os << sb.GetString();
+}
+
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-param-test.h b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-param-test.h
new file mode 100644
index 0000000..3184d07
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-param-test.h
@@ -0,0 +1,1397 @@
+// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#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 FooTest : public ::testing::TestWithParam<const char*> {
+ // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+ // Inside a test, access the test parameter with the GetParam() method
+ // of the TestWithParam<T> class:
+ EXPECT_TRUE(foo.Blah(GetParam()));
+ ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+ ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a summary of them, which
+// are all in the testing namespace:
+//
+//
+// Range(begin, end [, step]) - Yields values {begin, begin+step,
+// begin+step+step, ...}. The values do not
+// include end. step defaults to 1.
+// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}.
+// ValuesIn(container) - Yields values from a C-style array, an STL
+// ValuesIn(begin,end) container, or an iterator range [begin, end).
+// Bool() - Yields sequence {false, true}.
+// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product
+// for the math savvy) of the values generated
+// by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+ FooTest,
+ Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+// * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+// * InstantiationName/FooTest.DoesBlah/1 for "miny"
+// * InstantiationName/FooTest.DoesBlah/2 for "moe"
+// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+// * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+// * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// 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.
+
+#endif // 0
+
+#include <gtest/internal/gtest-port.h>
+
+#if !GTEST_OS_SYMBIAN
+#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>
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+// - returns a generator producing a sequence of values {start, start+1,
+// start+2, ..., }.
+// Range(start, end, step)
+// - returns a generator producing a sequence of values {start, start+step,
+// start+step+step, ..., }.
+// Notes:
+// * The generated sequences never include end. For example, Range(1, 5)
+// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+// returns a generator producing {1, 3, 5, 7}.
+// * start and end must have the same type. That type may be any integral or
+// floating-point type or a user defined type satisfying these conditions:
+// * It must be assignable (have operator=() defined).
+// * It must have operator+() (operator+(int-compatible type) for
+// two-operand version).
+// * It must have operator<() defined.
+// Elements in the resulting sequences will also have that type.
+// * Condition start < end must be satisfied in order for resulting sequences
+// to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+ return internal::ParamGenerator<T>(
+ new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+ return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+// - returns a generator producing sequences with elements from
+// a C-style array.
+// ValuesIn(const Container& container)
+// - returns a generator producing sequences with elements from
+// an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+// - returns a generator producing sequences with elements from
+// a range [begin, end) defined by a pair of STL-style iterators. These
+// iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+// ::std::vector< ::std::string> v;
+// v.push_back("a");
+// v.push_back("b");
+// return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+// StlStringTest,
+// ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+// ::std::list<char> list;
+// list.push_back('a');
+// list.push_back('b');
+// return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+// CharTest,
+// ValuesIn(l.begin(), l.end()));
+//
+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;
+ return internal::ParamGenerator<ParamType>(
+ new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+ return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+ const Container& container) {
+ return ValuesIn(container.begin(), container.end());
+}
+
+} // namespace testing
+
+#include <gtest/internal/gtest-param-util-generated.h>
+
+namespace testing {
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+// - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to 50 parameters.
+//
+template <typename T1>
+internal::ValueArray1<T1> Values(T1 v1) {
+ return internal::ValueArray1<T1>(v1);
+}
+
+template <typename T1, typename T2>
+internal::ValueArray2<T1, T2> Values(T1 v1, T2 v2) {
+ return internal::ValueArray2<T1, T2>(v1, v2);
+}
+
+template <typename T1, typename T2, typename T3>
+internal::ValueArray3<T1, T2, T3> Values(T1 v1, T2 v2, T3 v3) {
+ return internal::ValueArray3<T1, T2, T3>(v1, v2, v3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+internal::ValueArray4<T1, T2, T3, T4> Values(T1 v1, T2 v2, T3 v3, T4 v4) {
+ return internal::ValueArray4<T1, T2, T3, T4>(v1, v2, v3, v4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+internal::ValueArray5<T1, T2, T3, T4, T5> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5) {
+ return internal::ValueArray5<T1, T2, T3, T4, T5>(v1, v2, v3, v4, v5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+internal::ValueArray6<T1, T2, T3, T4, T5, T6> Values(T1 v1, T2 v2, T3 v3,
+ T4 v4, T5 v5, T6 v6) {
+ return internal::ValueArray6<T1, T2, T3, T4, T5, T6>(v1, v2, v3, v4, v5, v6);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7> Values(T1 v1, T2 v2, T3 v3,
+ T4 v4, T5 v5, T6 v6, T7 v7) {
+ return internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7>(v1, v2, v3, v4, v5,
+ v6, v7);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) {
+ return internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8>(v1, v2, v3, v4,
+ v5, v6, v7, v8);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) {
+ return internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(v1, v2, v3,
+ v4, v5, v6, v7, v8, v9);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Values(T1 v1,
+ T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) {
+ return internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(v1,
+ v2, v3, v4, v5, v6, v7, v8, v9, v10);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11>
+internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+ T11> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11) {
+ return internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+ T11>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12>
+internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12) {
+ return internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13>
+internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13) {
+ return internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14>
+internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) {
+ return internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+ v14);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15>
+internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+ T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) {
+ return internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+ v13, v14, v15);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16>
+internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16) {
+ return internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+ v12, v13, v14, v15, v16);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17>
+internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17) {
+ return internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+ v11, v12, v13, v14, v15, v16, v17);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18>
+internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+ T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18) {
+ return internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+ v10, v11, v12, v13, v14, v15, v16, v17, v18);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19>
+internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+ T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+ T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) {
+ return internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19>(v1, v2, v3, v4, v5, v6, v7, v8,
+ v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20>
+internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+ T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) {
+ return internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20>(v1, v2, v3, v4, v5, v6, v7,
+ v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21>
+internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+ T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) {
+ return internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(v1, v2, v3, v4, v5, v6,
+ v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22>
+internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22> Values(T1 v1, T2 v2, T3 v3,
+ T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22) {
+ return internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>(v1, v2, v3, v4,
+ v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+ v20, v21, v22);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23>
+internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22, T23 v23) {
+ return internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23>(v1, v2, v3,
+ v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+ v20, v21, v22, v23);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24>
+internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22, T23 v23, T24 v24) {
+ return internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24>(v1, v2,
+ v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+ v19, v20, v21, v22, v23, v24);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25>
+internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Values(T1 v1,
+ T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+ T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+ T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) {
+ return internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25>(v1,
+ v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+ v18, v19, v20, v21, v22, v23, v24, v25);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26>
+internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26) {
+ return internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+ v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27>
+internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27) {
+ return internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+ v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28>
+internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28) {
+ return internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+ v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+ v28);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29>
+internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29) {
+ return internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+ v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+ v27, v28, v29);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30>
+internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+ T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+ T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+ T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) {
+ return internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+ v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+ v26, v27, v28, v29, v30);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31>
+internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) {
+ return internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+ v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+ v25, v26, v27, v28, v29, v30, v31);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32>
+internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+ T32 v32) {
+ return internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+ v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+ v24, v25, v26, v27, v28, v29, v30, v31, v32);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33>
+internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+ T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+ T32 v32, T33 v33) {
+ return internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33>(v1, v2, v3, v4, v5, v6, v7, v8,
+ v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+ v24, v25, v26, v27, v28, v29, v30, v31, v32, v33);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34>
+internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+ T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+ T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+ T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+ T31 v31, T32 v32, T33 v33, T34 v34) {
+ return internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34>(v1, v2, v3, v4, v5, v6, v7,
+ v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+ v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35>
+internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+ T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+ T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+ T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) {
+ return internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35>(v1, v2, v3, v4, v5, v6,
+ v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+ v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36>
+internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+ T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+ T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+ T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) {
+ return internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36>(v1, v2, v3, v4,
+ v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+ v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+ v34, v35, v36);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37>
+internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37> Values(T1 v1, T2 v2, T3 v3,
+ T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+ T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+ T37 v37) {
+ return internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37>(v1, v2, v3,
+ v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+ v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+ v34, v35, v36, v37);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38>
+internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+ T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+ T37 v37, T38 v38) {
+ return internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38>(v1, v2,
+ v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+ v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32,
+ v33, v34, v35, v36, v37, v38);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39>
+internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+ T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+ T37 v37, T38 v38, T39 v39) {
+ return internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39>(v1,
+ v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+ v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
+ v32, v33, v34, v35, v36, v37, v38, v39);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40>
+internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Values(T1 v1,
+ T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+ T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+ T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27,
+ T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35,
+ T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) {
+ return internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+ v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29,
+ v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41>
+internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) {
+ return internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+ v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28,
+ v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42>
+internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42) {
+ return internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+ v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+ v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41,
+ v42);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43>
+internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43) {
+ return internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+ v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+ v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+ v41, v42, v43);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44>
+internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44) {
+ return internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+ v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+ v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39,
+ v40, v41, v42, v43, v44);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45>
+internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+ T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+ T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+ T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+ T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+ T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) {
+ return internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+ v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+ v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38,
+ v39, v40, v41, v42, v43, v44, v45);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46>
+internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+ T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+ T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) {
+ return internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45, T46>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+ v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+ v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+ v38, v39, v40, v41, v42, v43, v44, v45, v46);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47>
+internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+ T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+ T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) {
+ return internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45, T46, T47>(v1, v2, v3, v4, v5, v6, v7, v8,
+ v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+ v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+ v38, v39, v40, v41, v42, v43, v44, v45, v46, v47);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48>
+internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+ T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+ T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+ T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47,
+ T48 v48) {
+ return internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45, T46, T47, T48>(v1, v2, v3, v4, v5, v6, v7,
+ v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+ v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36,
+ v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49>
+internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48, T49> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+ T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+ T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+ T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+ T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38,
+ T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46,
+ T47 v47, T48 v48, T49 v49) {
+ return internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45, T46, T47, T48, T49>(v1, v2, v3, v4, v5, v6,
+ v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+ v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35,
+ v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49, typename T50>
+internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48, T49, T50> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+ T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+ T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+ T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37,
+ T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45,
+ T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) {
+ return internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>(v1, v2, v3, v4,
+ v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+ v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+ v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47,
+ v48, v49, v50);
+}
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+// - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+// virtual void SetUp() {
+// external_flag = GetParam();
+// }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+ return Values(false, true);
+}
+
+#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.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+// - returns a generator producing sequences with elements coming from
+// the Cartesian product of elements from the sequences generated by
+// gen1, gen2, ..., genN. The sequence elements will have a type of
+// tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+// of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to 10 arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+// : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+// Combine(Values("cat", "dog"),
+// Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+// : public testing::TestWithParam<tuple(bool, bool)> > {
+// virtual void SetUp() {
+// // Assigns external_flag_1 and external_flag_2 values from the tuple.
+// tie(external_flag_1, external_flag_2) = GetParam();
+// }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+// // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+// Combine(Bool(), Bool()));
+//
+template <typename Generator1, typename Generator2>
+internal::CartesianProductHolder2<Generator1, Generator2> Combine(
+ const Generator1& g1, const Generator2& g2) {
+ return internal::CartesianProductHolder2<Generator1, Generator2>(
+ g1, g2);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3>
+internal::CartesianProductHolder3<Generator1, Generator2, Generator3> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3) {
+ return internal::CartesianProductHolder3<Generator1, Generator2, Generator3>(
+ g1, g2, g3);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4>
+internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+ Generator4> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4) {
+ return internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+ Generator4>(
+ g1, g2, g3, g4);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5>
+internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+ Generator4, Generator5> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5) {
+ return internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+ Generator4, Generator5>(
+ g1, g2, g3, g4, g5);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5, typename Generator6>
+internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5, const Generator6& g6) {
+ return internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6>(
+ g1, g2, g3, g4, g5, g6);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5, typename Generator6,
+ typename Generator7>
+internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5, const Generator6& g6,
+ const Generator7& g7) {
+ return internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7>(
+ g1, g2, g3, g4, g5, g6, g7);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5, typename Generator6,
+ typename Generator7, typename Generator8>
+internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5, const Generator6& g6,
+ const Generator7& g7, const Generator8& g8) {
+ return internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8>(
+ g1, g2, g3, g4, g5, g6, g7, g8);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5, typename Generator6,
+ typename Generator7, typename Generator8, typename Generator9>
+internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8,
+ Generator9> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5, const Generator6& g6,
+ const Generator7& g7, const Generator8& g8, const Generator9& g9) {
+ return internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8, Generator9>(
+ g1, g2, g3, g4, g5, g6, g7, g8, g9);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5, typename Generator6,
+ typename Generator7, typename Generator8, typename Generator9,
+ typename Generator10>
+internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+ Generator10> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5, const Generator6& g6,
+ const Generator7& g7, const Generator8& g8, const Generator9& g9,
+ const Generator10& g10) {
+ return internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+ Generator10>(
+ g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
+}
+#endif // GTEST_HAS_COMBINE
+
+
+
+#define TEST_P(test_case_name, test_name) \
+ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+ : public test_case_name { \
+ public: \
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+ virtual void TestBody(); \
+ private: \
+ static int AddToRegistry() { \
+ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+ GetTestCasePatternHolder<test_case_name>(\
+ #test_case_name, __FILE__, __LINE__)->AddTestPattern(\
+ #test_case_name, \
+ #test_name, \
+ new ::testing::internal::TestMetaFactory< \
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
+ return 0; \
+ } \
+ static int gtest_registering_dummy_; \
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+ }; \
+ int GTEST_TEST_CLASS_NAME_(test_case_name, \
+ test_name)::gtest_registering_dummy_ = \
+ 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) \
+ ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+ gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+ int gtest_##prefix##test_case_name##_dummy_ = \
+ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+ GetTestCasePatternHolder<test_case_name>(\
+ #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
+ #prefix, \
+ &gtest_##prefix##test_case_name##_EvalGenerator_, \
+ __FILE__, __LINE__)
+
+} // namespace testing
+
+#endif // GTEST_HAS_PARAM_TEST
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-spi.h b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-spi.h
new file mode 100644
index 0000000..c41da48
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-spi.h
@@ -0,0 +1,232 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Utilities for testing Google Test itself and code that uses Google Test
+// (e.g. frameworks built on top of Google Test).
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+#include <gtest/gtest.h>
+
+namespace testing {
+
+// This helper class can be used to mock out Google Test failure reporting
+// so that we can test Google Test or code that builds on Google Test.
+//
+// An object of this class appends a TestPartResult object to the
+// TestPartResultArray object given in the constructor whenever a Google Test
+// failure is reported. It can either intercept only failures that are
+// generated in the same thread that created this object or it can intercept
+// all generated failures. The scope of this mock object can be controlled with
+// the second argument to the two arguments constructor.
+class GTEST_API_ ScopedFakeTestPartResultReporter
+ : public TestPartResultReporterInterface {
+ public:
+ // The two possible mocking modes of this object.
+ enum InterceptMode {
+ INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures.
+ INTERCEPT_ALL_THREADS // Intercepts all failures.
+ };
+
+ // The c'tor sets this object as the test part result reporter used
+ // by Google Test. The 'result' parameter specifies where to report the
+ // results. This reporter will only catch failures generated in the current
+ // thread. DEPRECATED
+ explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
+
+ // Same as above, but you can choose the interception scope of this object.
+ ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
+ TestPartResultArray* result);
+
+ // The d'tor restores the previous test part result reporter.
+ virtual ~ScopedFakeTestPartResultReporter();
+
+ // Appends the TestPartResult object to the TestPartResultArray
+ // received in the constructor.
+ //
+ // This method is from the TestPartResultReporterInterface
+ // interface.
+ virtual void ReportTestPartResult(const TestPartResult& result);
+ private:
+ void Init();
+
+ const InterceptMode intercept_mode_;
+ TestPartResultReporterInterface* old_reporter_;
+ TestPartResultArray* const result_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
+};
+
+namespace internal {
+
+// A helper class for implementing EXPECT_FATAL_FAILURE() and
+// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring. If that's not the case, a
+// non-fatal failure will be generated.
+class GTEST_API_ SingleFailureChecker {
+ public:
+ // The constructor remembers the arguments.
+ SingleFailureChecker(const TestPartResultArray* results,
+ TestPartResult::Type type,
+ const char* substr);
+ ~SingleFailureChecker();
+ private:
+ const TestPartResultArray* const results_;
+ const TestPartResult::Type type_;
+ const String substr_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
+};
+
+} // namespace internal
+
+} // namespace testing
+
+// A set of macros for testing Google Test assertions or code that's expected
+// to generate Google Test fatal failures. It verifies that the given
+// statement will cause exactly one fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+// - 'statement' cannot reference local non-static variables or
+// non-static members of the current object.
+// - 'statement' cannot return a value.
+// - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works. The AcceptsMacroThatExpandsToUnprotectedComma test in
+// gtest_unittest.cc will fail to compile if we do that.
+#define EXPECT_FATAL_FAILURE(statement, substr) \
+ do { \
+ class GTestExpectFatalFailureHelper {\
+ public:\
+ static void Execute() { statement; }\
+ };\
+ ::testing::TestPartResultArray gtest_failures;\
+ ::testing::internal::SingleFailureChecker gtest_checker(\
+ &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+ {\
+ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+ ::testing::ScopedFakeTestPartResultReporter:: \
+ INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+ GTestExpectFatalFailureHelper::Execute();\
+ }\
+ } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+ do { \
+ class GTestExpectFatalFailureHelper {\
+ public:\
+ static void Execute() { statement; }\
+ };\
+ ::testing::TestPartResultArray gtest_failures;\
+ ::testing::internal::SingleFailureChecker gtest_checker(\
+ &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+ {\
+ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+ ::testing::ScopedFakeTestPartResultReporter:: \
+ INTERCEPT_ALL_THREADS, &gtest_failures);\
+ GTestExpectFatalFailureHelper::Execute();\
+ }\
+ } while (::testing::internal::AlwaysFalse())
+
+// A macro for testing Google Test assertions or code that's expected to
+// generate Google Test non-fatal failures. It asserts that the given
+// statement will cause exactly one non-fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// 'statement' is allowed to reference local variables and members of
+// the current object.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+// - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works. If we do that, the code won't compile when the user gives
+// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
+// expands to code containing an unprotected comma. The
+// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
+// catches that.
+//
+// For the same reason, we have to write
+// if (::testing::internal::AlwaysTrue()) { statement; }
+// instead of
+// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+// to avoid an MSVC warning on unreachable code.
+#define EXPECT_NONFATAL_FAILURE(statement, substr) \
+ do {\
+ ::testing::TestPartResultArray gtest_failures;\
+ ::testing::internal::SingleFailureChecker gtest_checker(\
+ &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+ (substr));\
+ {\
+ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+ ::testing::ScopedFakeTestPartResultReporter:: \
+ INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+ if (::testing::internal::AlwaysTrue()) { statement; }\
+ }\
+ } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+ do {\
+ ::testing::TestPartResultArray gtest_failures;\
+ ::testing::internal::SingleFailureChecker gtest_checker(\
+ &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+ (substr));\
+ {\
+ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+ ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS,\
+ &gtest_failures);\
+ if (::testing::internal::AlwaysTrue()) { statement; }\
+ }\
+ } while (::testing::internal::AlwaysFalse())
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-test-part.h b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-test-part.h
new file mode 100644
index 0000000..f714759
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-test-part.h
@@ -0,0 +1,176 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+#include <iosfwd>
+#include <vector>
+#include <gtest/internal/gtest-internal.h>
+#include <gtest/internal/gtest-string.h>
+
+namespace testing {
+
+// A copyable object representing the result of a test part (i.e. an
+// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
+//
+// Don't inherit from TestPartResult as its destructor is not virtual.
+class GTEST_API_ TestPartResult {
+ public:
+ // The possible outcomes of a test part (i.e. an assertion or an
+ // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+ enum Type {
+ kSuccess, // Succeeded.
+ kNonFatalFailure, // Failed but the test can continue.
+ kFatalFailure // Failed and the test should be terminated.
+ };
+
+ // C'tor. TestPartResult does NOT have a default constructor.
+ // Always use this constructor (with parameters) to create a
+ // TestPartResult object.
+ TestPartResult(Type a_type,
+ const char* a_file_name,
+ int a_line_number,
+ const char* a_message)
+ : type_(a_type),
+ file_name_(a_file_name),
+ line_number_(a_line_number),
+ summary_(ExtractSummary(a_message)),
+ message_(a_message) {
+ }
+
+ // Gets the outcome of the test part.
+ Type type() const { return type_; }
+
+ // Gets the name of the source file where the test part took place, or
+ // NULL if it's unknown.
+ const char* file_name() const { return file_name_.c_str(); }
+
+ // Gets the line in the source file where the test part took place,
+ // or -1 if it's unknown.
+ int line_number() const { return line_number_; }
+
+ // Gets the summary of the failure message.
+ const char* summary() const { return summary_.c_str(); }
+
+ // Gets the message associated with the test part.
+ const char* message() const { return message_.c_str(); }
+
+ // Returns true iff the test part passed.
+ bool passed() const { return type_ == kSuccess; }
+
+ // Returns true iff the test part failed.
+ bool failed() const { return type_ != kSuccess; }
+
+ // Returns true iff the test part non-fatally failed.
+ bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
+
+ // Returns true iff the test part fatally failed.
+ bool fatally_failed() const { return type_ == kFatalFailure; }
+ private:
+ Type type_;
+
+ // Gets the summary of the failure message by omitting the stack
+ // trace in it.
+ static internal::String ExtractSummary(const char* message);
+
+ // The name of the source file where the test part took place, or
+ // NULL if the source file is unknown.
+ internal::String file_name_;
+ // The line in the source file where the test part took place, or -1
+ // if the line number is unknown.
+ int line_number_;
+ internal::String summary_; // The test failure summary.
+ internal::String message_; // The test failure message.
+};
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
+
+// An array of TestPartResult objects.
+//
+// Don't inherit from TestPartResultArray as its destructor is not
+// virtual.
+class GTEST_API_ TestPartResultArray {
+ public:
+ TestPartResultArray() {}
+
+ // Appends the given TestPartResult to the array.
+ void Append(const TestPartResult& result);
+
+ // Returns the TestPartResult at the given index (0-based).
+ const TestPartResult& GetTestPartResult(int index) const;
+
+ // Returns the number of TestPartResult objects in the array.
+ int size() const;
+
+ private:
+ std::vector<TestPartResult> array_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
+};
+
+// This interface knows how to report a test part result.
+class TestPartResultReporterInterface {
+ public:
+ virtual ~TestPartResultReporterInterface() {}
+
+ virtual void ReportTestPartResult(const TestPartResult& result) = 0;
+};
+
+namespace internal {
+
+// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
+// statement generates new fatal failures. To do so it registers itself as the
+// current test part result reporter. Besides checking if fatal failures were
+// reported, it only delegates the reporting to the former result reporter.
+// The original result reporter is restored in the destructor.
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+class GTEST_API_ HasNewFatalFailureHelper
+ : public TestPartResultReporterInterface {
+ public:
+ HasNewFatalFailureHelper();
+ virtual ~HasNewFatalFailureHelper();
+ virtual void ReportTestPartResult(const TestPartResult& result);
+ bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
+ private:
+ bool has_new_fatal_failure_;
+ TestPartResultReporterInterface* original_reporter_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
+};
+
+} // namespace internal
+
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-typed-test.h b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-typed-test.h
new file mode 100644
index 0000000..1ec8eb8
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest-typed-test.h
@@ -0,0 +1,259 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+// This header implements typed tests and type-parameterized tests.
+
+// Typed (aka type-driven) tests repeat the same test for types in a
+// list. You must know which types you want to test with when writing
+// typed tests. Here's how you do it:
+
+#if 0
+
+// First, define a fixture class template. It should be parameterized
+// by a type. Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+ ...
+ typedef std::list<T> List;
+ static T shared_;
+ T value_;
+};
+
+// Next, associate a list of types with the test case, which will be
+// repeated for each type in the list. The typedef is necessary for
+// the macro to parse correctly.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+// TYPED_TEST_CASE(FooTest, int);
+
+// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
+// tests for this test case as you want.
+TYPED_TEST(FooTest, DoesBlah) {
+ // Inside a test, refer to TypeParam to get the type parameter.
+ // Since we are inside a derived class template, C++ requires use to
+ // visit the members of FooTest via 'this'.
+ TypeParam n = this->value_;
+
+ // To visit static members of the fixture, add the TestFixture::
+ // prefix.
+ n += TestFixture::shared_;
+
+ // To refer to typedefs in the fixture, add the "typename
+ // TestFixture::" prefix.
+ typename TestFixture::List values;
+ values.push_back(n);
+ ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+
+#endif // 0
+
+// Type-parameterized tests are abstract test patterns parameterized
+// by a type. Compared with typed tests, type-parameterized tests
+// allow you to define the test pattern without knowing what the type
+// parameters are. The defined pattern can be instantiated with
+// different types any number of times, in any number of translation
+// units.
+//
+// If you are designing an interface or concept, you can define a
+// suite of type-parameterized tests to verify properties that any
+// valid implementation of the interface/concept should have. Then,
+// each implementation can easily instantiate the test suite to verify
+// that it conforms to the requirements, without having to write
+// similar tests repeatedly. Here's an example:
+
+#if 0
+
+// First, define a fixture class template. It should be parameterized
+// by a type. Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ ...
+};
+
+// Next, declare that you will define a type-parameterized test case
+// (the _P suffix is for "parameterized" or "pattern", whichever you
+// prefer):
+TYPED_TEST_CASE_P(FooTest);
+
+// Then, use TYPED_TEST_P() to define as many type-parameterized tests
+// for this type-parameterized test case as you want.
+TYPED_TEST_P(FooTest, DoesBlah) {
+ // Inside a test, refer to TypeParam to get the type parameter.
+ TypeParam n = 0;
+ ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+
+// Now the tricky part: you need to register all test patterns before
+// you can instantiate them. The first argument of the macro is the
+// test case name; the rest are the names of the tests in this test
+// case.
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+ DoesBlah, HasPropertyA);
+
+// Finally, you are free to instantiate the pattern with the types you
+// want. If you put the above code in a header file, you can #include
+// it in multiple C++ source files and instantiate it multiple times.
+//
+// To distinguish different instances of the pattern, the first
+// argument to the INSTANTIATE_* macro is a prefix that will be added
+// to the actual test case name. Remember to pick unique prefixes for
+// different instances.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+
+#endif // 0
+
+#include <gtest/internal/gtest-port.h>
+#include <gtest/internal/gtest-type-util.h>
+
+// Implements typed tests.
+
+#if GTEST_HAS_TYPED_TEST
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// 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##_
+
+// 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) \
+ typedef ::testing::internal::TypeList< Types >::type \
+ GTEST_TYPE_PARAMS_(CaseName)
+
+#define TYPED_TEST(CaseName, TestName) \
+ template <typename gtest_TypeParam_> \
+ class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
+ : public CaseName<gtest_TypeParam_> { \
+ private: \
+ typedef CaseName<gtest_TypeParam_> TestFixture; \
+ typedef gtest_TypeParam_ TypeParam; \
+ virtual void TestBody(); \
+ }; \
+ bool gtest_##CaseName##_##TestName##_registered_ = \
+ ::testing::internal::TypeParameterizedTest< \
+ CaseName, \
+ ::testing::internal::TemplateSel< \
+ GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
+ GTEST_TYPE_PARAMS_(CaseName)>::Register(\
+ "", #CaseName, #TestName, 0); \
+ template <typename gtest_TypeParam_> \
+ void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
+
+#endif // GTEST_HAS_TYPED_TEST
+
+// Implements type-parameterized tests.
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// 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) \
+ 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) \
+ 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) \
+ 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) \
+ static ::testing::internal::TypedTestCasePState \
+ GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
+
+#define TYPED_TEST_P(CaseName, TestName) \
+ namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+ template <typename gtest_TypeParam_> \
+ class TestName : public CaseName<gtest_TypeParam_> { \
+ private: \
+ typedef CaseName<gtest_TypeParam_> TestFixture; \
+ typedef gtest_TypeParam_ TypeParam; \
+ virtual void TestBody(); \
+ }; \
+ static bool gtest_##TestName##_defined_ = \
+ 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, ...) \
+ namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+ typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
+ } \
+ static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
+ GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
+ __FILE__, __LINE__, #__VA_ARGS__)
+
+// 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 = \
+ ::testing::internal::TypeParameterizedTestCase<CaseName, \
+ GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
+ ::testing::internal::TypeList< Types >::type>::Register(\
+ #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
+
+#endif // GTEST_HAS_TYPED_TEST_P
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/gtest.h b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest.h
new file mode 100644
index 0000000..921fad1
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest.h
@@ -0,0 +1,2052 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for Google Test. It should be
+// included by any test program that uses Google Test.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
+// program!
+//
+// Acknowledgment: Google Test borrowed the idea of automatic test
+// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
+// easyUnit framework.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_H_
+
+#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>
+
+// Depending on the platform, different string classes are available.
+// On Linux, in addition to ::std::string, Google also makes use of
+// class ::string, which has the same interface as ::std::string, but
+// has a different implementation.
+//
+// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that
+// ::string is available AND is a distinct type to ::std::string, or
+// define it to 0 to indicate otherwise.
+//
+// If the user's ::std::string and ::string are the same class due to
+// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0.
+//
+// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined
+// heuristically.
+
+namespace testing {
+
+// Declares the flags.
+
+// This flag temporary enables the disabled tests.
+GTEST_DECLARE_bool_(also_run_disabled_tests);
+
+// This flag brings the debugger on an assertion failure.
+GTEST_DECLARE_bool_(break_on_failure);
+
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
+GTEST_DECLARE_bool_(catch_exceptions);
+
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// to let Google Test decide.
+GTEST_DECLARE_string_(color);
+
+// This flag sets up the filter to select by name using a glob pattern
+// the tests to run. If the filter is not given all tests are executed.
+GTEST_DECLARE_string_(filter);
+
+// This flag causes the Google Test to list tests. None of the tests listed
+// are actually run if the flag is provided.
+GTEST_DECLARE_bool_(list_tests);
+
+// This flag controls whether Google Test emits a detailed XML report to a file
+// in addition to its normal textual output.
+GTEST_DECLARE_string_(output);
+
+// This flags control whether Google Test prints the elapsed time for each
+// test.
+GTEST_DECLARE_bool_(print_time);
+
+// This flag specifies the random number seed.
+GTEST_DECLARE_int32_(random_seed);
+
+// This flag sets how many times the tests are repeated. The default value
+// is 1. If the value is -1 the tests are repeating forever.
+GTEST_DECLARE_int32_(repeat);
+
+// This flag controls whether Google Test includes Google Test internal
+// stack frames in failure stack traces.
+GTEST_DECLARE_bool_(show_internal_stack_frames);
+
+// When this flag is specified, tests' order is randomized on every iteration.
+GTEST_DECLARE_bool_(shuffle);
+
+// This flag specifies the maximum number of stack frames to be
+// printed in a failure message.
+GTEST_DECLARE_int32_(stack_trace_depth);
+
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise.
+GTEST_DECLARE_bool_(throw_on_failure);
+
+// The upper limit for valid stack trace depths.
+const int kMaxStackTraceDepth = 100;
+
+namespace internal {
+
+class AssertHelper;
+class DefaultGlobalTestPartResultReporter;
+class ExecDeathTest;
+class NoExecDeathTest;
+class FinalSuccessChecker;
+class GTestFlagSaver;
+class TestInfoImpl;
+class TestResultAccessor;
+class TestEventListenersAccessor;
+class TestEventRepeater;
+class WindowsDeathTest;
+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,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+// Declared in gtest-internal.h but defined here, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable) {
+ return (Message() << streamable).GetString();
+}
+
+} // namespace internal
+
+// 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.
+//
+// To create an instance of this class, use one of the factory functions
+// (AssertionSuccess() and AssertionFailure()).
+//
+// This class is useful for two purposes:
+// 1. Defining predicate functions to be used with Boolean test assertions
+// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
+// 2. Defining predicate-format functions to be
+// used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
+//
+// For example, if you define IsEven predicate:
+//
+// testing::AssertionResult IsEven(int n) {
+// if ((n % 2) == 0)
+// return testing::AssertionSuccess();
+// else
+// return testing::AssertionFailure() << n << " is odd";
+// }
+//
+// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
+// will print the message
+//
+// Value of: IsEven(Fib(5))
+// Actual: false (5 is odd)
+// Expected: true
+//
+// instead of a more opaque
+//
+// Value of: IsEven(Fib(5))
+// Actual: false
+// Expected: true
+//
+// in case IsEven is a simple Boolean predicate.
+//
+// If you expect your predicate to be reused and want to support informative
+// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
+// about half as often as positive ones in our tests), supply messages for
+// both success and failure cases:
+//
+// testing::AssertionResult IsEven(int n) {
+// if ((n % 2) == 0)
+// return testing::AssertionSuccess() << n << " is even";
+// else
+// return testing::AssertionFailure() << n << " is odd";
+// }
+//
+// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
+//
+// Value of: IsEven(Fib(6))
+// Actual: true (8 is even)
+// Expected: false
+//
+// NB: Predicates that support negative Boolean assertions have reduced
+// performance in positive ones so be careful not to use them in tests
+// that have lots (tens of thousands) of positive Boolean assertions.
+//
+// To use this class with EXPECT_PRED_FORMAT assertions such as:
+//
+// // Verifies that Foo() returns an even number.
+// EXPECT_PRED_FORMAT1(IsEven, Foo());
+//
+// you need to define:
+//
+// testing::AssertionResult IsEven(const char* expr, int n) {
+// if ((n % 2) == 0)
+// return testing::AssertionSuccess();
+// else
+// return testing::AssertionFailure()
+// << "Expected: " << expr << " is even\n Actual: it's " << n;
+// }
+//
+// If Foo() returns 5, you will see the following message:
+//
+// Expected: Foo() is even
+// Actual: it's 5
+//
+class GTEST_API_ AssertionResult {
+ public:
+ // Copy constructor.
+ // Used in EXPECT_TRUE/FALSE(assertion_result).
+ AssertionResult(const AssertionResult& other);
+ // Used in the EXPECT_TRUE/FALSE(bool_expression).
+ explicit AssertionResult(bool success) : success_(success) {}
+
+ // Returns true iff the assertion succeeded.
+ operator bool() const { return success_; } // NOLINT
+
+ // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+ AssertionResult operator!() const;
+
+ // Returns the text streamed into this AssertionResult. Test assertions
+ // use it when they fail (i.e., the predicate's outcome doesn't match the
+ // 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() : "";
+ }
+ // TODO(vladl@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);
+
+ private:
+ // No implementation - we want AssertionResult to be
+ // copy-constructible but not assignable.
+ void operator=(const AssertionResult& other);
+
+ // Stores result of the assertion predicate.
+ bool success_;
+ // Stores the message describing the condition in case the expectation
+ // 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
+
+// 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;
+}
+
+// Makes a successful assertion result.
+GTEST_API_ AssertionResult AssertionSuccess();
+
+// Makes a failed assertion result.
+GTEST_API_ AssertionResult AssertionFailure();
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << msg.
+GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
+
+// The abstract class that all tests inherit from.
+//
+// In Google Test, a unit test program contains one or many TestCases, and
+// each TestCase contains one or many Tests.
+//
+// When you define a test using the TEST macro, you don't need to
+// explicitly derive from Test - the TEST macro automatically does
+// this for you.
+//
+// The only time you derive from Test is when defining a test fixture
+// to be used a TEST_F. For example:
+//
+// class FooTest : public testing::Test {
+// protected:
+// virtual void SetUp() { ... }
+// virtual void TearDown() { ... }
+// ...
+// };
+//
+// TEST_F(FooTest, Bar) { ... }
+// TEST_F(FooTest, Baz) { ... }
+//
+// Test is not copyable.
+class GTEST_API_ Test {
+ public:
+ friend class internal::TestInfoImpl;
+
+ // Defines types for pointers to functions that set up and tear down
+ // a test case.
+ typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc;
+ typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc;
+
+ // The d'tor is virtual as we intend to inherit from Test.
+ virtual ~Test();
+
+ // Sets up the stuff shared by all tests in this test case.
+ //
+ // Google Test will call Foo::SetUpTestCase() before running the first
+ // test in test case Foo. Hence a sub-class can define its own
+ // SetUpTestCase() method to shadow the one defined in the super
+ // class.
+ static void SetUpTestCase() {}
+
+ // Tears down the stuff shared by all tests in this test case.
+ //
+ // Google Test will call Foo::TearDownTestCase() after running the last
+ // test in test case Foo. Hence a sub-class can define its own
+ // TearDownTestCase() method to shadow the one defined in the super
+ // class.
+ static void TearDownTestCase() {}
+
+ // Returns true iff the current test has a fatal failure.
+ static bool HasFatalFailure();
+
+ // Returns true iff the current test has a non-fatal failure.
+ static bool HasNonfatalFailure();
+
+ // Returns true iff the current test has a (either fatal or
+ // non-fatal) failure.
+ static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
+ // Logs a property for the current test. Only the last value for a given
+ // key is remembered.
+ // These are public static so they can be called from utility functions
+ // that are not members of the test fixture.
+ // The arguments are const char* instead strings, as Google Test is used
+ // on platforms where string doesn't compile.
+ //
+ // Note that a driving consideration for these RecordProperty methods
+ // was to produce xml output suited to the Greenspan charting utility,
+ // which at present will only chart values that fit in a 32-bit int. It
+ // is the user's responsibility to restrict their values to 32-bit ints
+ // if they intend them to be used with Greenspan.
+ static void RecordProperty(const char* key, const char* value);
+ static void RecordProperty(const char* key, int value);
+
+ protected:
+ // Creates a Test object.
+ Test();
+
+ // Sets up the test fixture.
+ virtual void SetUp();
+
+ // Tears down the test fixture.
+ virtual void TearDown();
+
+ private:
+ // Returns true iff the current test has the same fixture class as
+ // the first test in the current test case.
+ static bool HasSameFixtureClass();
+
+ // Runs the test after the test fixture has been set up.
+ //
+ // A sub-class must implement this to define the test logic.
+ //
+ // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
+ // Instead, use the TEST or TEST_F macro.
+ virtual void TestBody() = 0;
+
+ // Sets up, executes, and tears down the test.
+ void Run();
+
+ // Uses a GTestFlagSaver to save and restore all Google Test flags.
+ const internal::GTestFlagSaver* const gtest_flag_saver_;
+
+ // Often a user mis-spells SetUp() as Setup() and spends a long time
+ // wondering why it is never called by Google Test. The declaration of
+ // the following method is solely for catching such an error at
+ // compile time:
+ //
+ // - The return type is deliberately chosen to be not void, so it
+ // will be a conflict if a user declares void Setup() in his test
+ // fixture.
+ //
+ // - This method is private, so it will be another compiler error
+ // if a user calls it from his test fixture.
+ //
+ // DO NOT OVERRIDE THIS FUNCTION.
+ //
+ // If you see an error about overriding the following function or
+ // about it being private, you have mis-spelled SetUp() as Setup().
+ struct Setup_should_be_spelled_SetUp {};
+ virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+
+ // We disallow copying Tests.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
+};
+
+typedef internal::TimeInMillis TimeInMillis;
+
+// A copyable object representing a user specified test property which can be
+// output as a key/value string pair.
+//
+// Don't inherit from TestProperty as its destructor is not virtual.
+class TestProperty {
+ public:
+ // C'tor. TestProperty does NOT have a default constructor.
+ // Always use this constructor (with parameters) to create a
+ // TestProperty object.
+ TestProperty(const char* a_key, const char* a_value) :
+ key_(a_key), value_(a_value) {
+ }
+
+ // Gets the user supplied key.
+ const char* key() const {
+ return key_.c_str();
+ }
+
+ // Gets the user supplied value.
+ const char* value() const {
+ return value_.c_str();
+ }
+
+ // Sets a new value, overriding the one supplied in the constructor.
+ void SetValue(const char* new_value) {
+ value_ = new_value;
+ }
+
+ private:
+ // The key supplied by the user.
+ internal::String key_;
+ // The value supplied by the user.
+ internal::String value_;
+};
+
+// The result of a single Test. This includes a list of
+// TestPartResults, a list of TestProperties, a count of how many
+// death tests there are in the Test, and how much time it took to run
+// the Test.
+//
+// TestResult is not copyable.
+class GTEST_API_ TestResult {
+ public:
+ // Creates an empty TestResult.
+ TestResult();
+
+ // D'tor. Do not inherit from TestResult.
+ ~TestResult();
+
+ // Gets the number of all test parts. This is the sum of the number
+ // of successful test parts and the number of failed test parts.
+ int total_part_count() const;
+
+ // Returns the number of the test properties.
+ int test_property_count() const;
+
+ // Returns true iff the test passed (i.e. no test part failed).
+ bool Passed() const { return !Failed(); }
+
+ // Returns true iff the test failed.
+ bool Failed() const;
+
+ // Returns true iff the test fatally failed.
+ bool HasFatalFailure() const;
+
+ // Returns true iff the test has a non-fatal failure.
+ bool HasNonfatalFailure() const;
+
+ // Returns the elapsed time, in milliseconds.
+ TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+ // Returns the i-th test part result among all the results. i can range
+ // from 0 to test_property_count() - 1. If i is not in that range, aborts
+ // the program.
+ const TestPartResult& GetTestPartResult(int i) const;
+
+ // Returns the i-th test property. i can range from 0 to
+ // test_property_count() - 1. If i is not in that range, aborts the
+ // program.
+ const TestProperty& GetTestProperty(int i) const;
+
+ private:
+ friend class TestInfo;
+ 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;
+
+ // Gets the vector of TestPartResults.
+ const std::vector<TestPartResult>& test_part_results() const {
+ return test_part_results_;
+ }
+
+ // Gets the vector of TestProperties.
+ const std::vector<TestProperty>& test_properties() const {
+ return test_properties_;
+ }
+
+ // Sets the elapsed time.
+ void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
+
+ // Adds a test property to the list. The property is validated and may add
+ // a non-fatal failure if invalid (e.g., if it conflicts with reserved
+ // key names). If a property is already recorded for the same key, the
+ // value will be updated, rather than storing multiple values for the same
+ // key.
+ void RecordProperty(const TestProperty& test_property);
+
+ // Adds a failure if the key is a reserved attribute of Google Test
+ // testcase tags. Returns true if the property is valid.
+ // TODO(russr): Validate attribute names are legal and human readable.
+ static bool ValidateTestProperty(const TestProperty& test_property);
+
+ // Adds a test part result to the list.
+ void AddTestPartResult(const TestPartResult& test_part_result);
+
+ // Returns the death test count.
+ int death_test_count() const { return death_test_count_; }
+
+ // Increments the death test count, returning the new count.
+ int increment_death_test_count() { return ++death_test_count_; }
+
+ // Clears the test part results.
+ void ClearTestPartResults();
+
+ // Clears the object.
+ void Clear();
+
+ // Protects mutable state of the property vector and of owned
+ // properties, whose values may be updated.
+ internal::Mutex test_properites_mutex_;
+
+ // The vector of TestPartResults
+ std::vector<TestPartResult> test_part_results_;
+ // The vector of TestProperties
+ std::vector<TestProperty> test_properties_;
+ // Running count of death tests.
+ int death_test_count_;
+ // The elapsed time, in milliseconds.
+ TimeInMillis elapsed_time_;
+
+ // We disallow copying TestResult.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
+}; // class TestResult
+
+// A TestInfo object stores the following information about a test:
+//
+// Test case name
+// Test name
+// Whether the test should be run
+// A function pointer that creates the test object when invoked
+// Test result
+//
+// The constructor of TestInfo registers itself with the UnitTest
+// singleton such that the RUN_ALL_TESTS() macro knows which tests to
+// run.
+class GTEST_API_ TestInfo {
+ public:
+ // Destructs a TestInfo object. This function is not virtual, so
+ // don't inherit from TestInfo.
+ ~TestInfo();
+
+ // Returns the test case name.
+ const char* test_case_name() const;
+
+ // Returns the test name.
+ const char* name() const;
+
+ // Returns the test case comment.
+ const char* test_case_comment() const;
+
+ // Returns the test comment.
+ const char* comment() const;
+
+ // 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)
+ // and its full name matches the user-specified filter.
+ //
+ // Google Test allows the user to filter the tests by their full names.
+ // The full name of a test Bar in test case Foo is defined as
+ // "Foo.Bar". Only the tests that match the filter will run.
+ //
+ // A filter is a colon-separated list of glob (not regex) patterns,
+ // optionally followed by a '-' and a colon-separated list of
+ // negative patterns (tests to exclude). A test is run if it
+ // matches one of the positive patterns and does not match any of
+ // the negative patterns.
+ //
+ // For example, *A*:Foo.* is a filter that matches any string that
+ // contains the character 'A' or starts with "Foo.".
+ bool should_run() const;
+
+ // Returns the result of the test.
+ const TestResult* result() const;
+
+ 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,
+ 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,
+ internal::TypeId fixture_class_id,
+ internal::TestFactoryBase* factory);
+
+ // An opaque implementation object.
+ internal::TestInfoImpl* impl_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
+};
+
+// A test case, which consists of a vector of TestInfos.
+//
+// TestCase is not copyable.
+class GTEST_API_ TestCase {
+ public:
+ // Creates a TestCase with the given name.
+ //
+ // TestCase does NOT have a default constructor. Always use this
+ // constructor to create a TestCase object.
+ //
+ // Arguments:
+ //
+ // name: name of the 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(const char* name, const char* comment,
+ Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc);
+
+ // Destructor of TestCase.
+ virtual ~TestCase();
+
+ // 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 true if any test in this test case should run.
+ bool should_run() const { return should_run_; }
+
+ // Gets the number of successful tests in this test case.
+ int successful_test_count() const;
+
+ // Gets the number of failed tests in this test case.
+ int failed_test_count() const;
+
+ // Gets the number of disabled tests in this test case.
+ int disabled_test_count() const;
+
+ // Get the number of tests in this test case that should run.
+ int test_to_run_count() const;
+
+ // Gets the number of all tests in this test case.
+ int total_test_count() const;
+
+ // Returns true iff the test case passed.
+ bool Passed() const { return !Failed(); }
+
+ // Returns true iff the test case failed.
+ bool Failed() const { return failed_test_count() > 0; }
+
+ // Returns the elapsed time, in milliseconds.
+ TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+ // Returns the i-th test among all the tests. i can range from 0 to
+ // total_test_count() - 1. If i is not in that range, returns NULL.
+ const TestInfo* GetTestInfo(int i) const;
+
+ private:
+ friend class Test;
+ friend class internal::UnitTestImpl;
+
+ // Gets the (mutable) vector of TestInfos in this TestCase.
+ std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
+
+ // Gets the (immutable) vector of TestInfos in this TestCase.
+ const std::vector<TestInfo*>& test_info_list() const {
+ return test_info_list_;
+ }
+
+ // Returns the i-th test among all the tests. i can range from 0 to
+ // total_test_count() - 1. If i is not in that range, returns NULL.
+ TestInfo* GetMutableTestInfo(int i);
+
+ // Sets the should_run member.
+ void set_should_run(bool should) { should_run_ = should; }
+
+ // Adds a TestInfo to this test case. Will delete the TestInfo upon
+ // destruction of the TestCase object.
+ void AddTestInfo(TestInfo * test_info);
+
+ // Clears the results of all tests in this test case.
+ void ClearResult();
+
+ // Clears the results of all tests in the given test case.
+ static void ClearTestCaseResult(TestCase* test_case) {
+ test_case->ClearResult();
+ }
+
+ // Runs every test in this TestCase.
+ void Run();
+
+ // Returns true iff test passed.
+ static bool TestPassed(const TestInfo * test_info);
+
+ // Returns true iff test failed.
+ static bool TestFailed(const TestInfo * test_info);
+
+ // Returns true iff test is disabled.
+ static bool TestDisabled(const TestInfo * test_info);
+
+ // Returns true if the given test should run.
+ static bool ShouldRunTest(const TestInfo *test_info);
+
+ // Shuffles the tests in this test case.
+ void ShuffleTests(internal::Random* random);
+
+ // Restores the test order to before the first shuffle.
+ void UnshuffleTests();
+
+ // Name of the test case.
+ internal::String name_;
+ // Comment on the test case.
+ internal::String comment_;
+ // The vector of TestInfos in their original order. It owns the
+ // elements in the vector.
+ std::vector<TestInfo*> test_info_list_;
+ // Provides a level of indirection for the test list to allow easy
+ // shuffling and restoring the test order. The i-th element in this
+ // vector is the index of the i-th test in the shuffled test list.
+ std::vector<int> test_indices_;
+ // Pointer to the function that sets up the test case.
+ Test::SetUpTestCaseFunc set_up_tc_;
+ // Pointer to the function that tears down the test case.
+ Test::TearDownTestCaseFunc tear_down_tc_;
+ // True iff any test in this test case should run.
+ bool should_run_;
+ // Elapsed time, in milliseconds.
+ TimeInMillis elapsed_time_;
+
+ // We disallow copying TestCases.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase);
+};
+
+// An Environment object is capable of setting up and tearing down an
+// environment. The user should subclass this to define his own
+// environment(s).
+//
+// An Environment object does the set-up and tear-down in virtual
+// methods SetUp() and TearDown() instead of the constructor and the
+// destructor, as:
+//
+// 1. You cannot safely throw from a destructor. This is a problem
+// as in some cases Google Test is used where exceptions are enabled, and
+// we may want to implement ASSERT_* using exceptions where they are
+// available.
+// 2. You cannot use ASSERT_* directly in a constructor or
+// destructor.
+class Environment {
+ public:
+ // The d'tor is virtual as we need to subclass Environment.
+ virtual ~Environment() {}
+
+ // Override this to define how to set up the environment.
+ virtual void SetUp() {}
+
+ // Override this to define how to tear down the environment.
+ virtual void TearDown() {}
+ private:
+ // If you see an error about overriding the following function or
+ // about it being private, you have mis-spelled SetUp() as Setup().
+ struct Setup_should_be_spelled_SetUp {};
+ virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+};
+
+// The interface for tracing execution of tests. The methods are organized in
+// the order the corresponding events are fired.
+class TestEventListener {
+ public:
+ virtual ~TestEventListener() {}
+
+ // Fired before any test activity starts.
+ virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
+
+ // Fired before each iteration of tests starts. There may be more than
+ // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
+ // index, starting from 0.
+ virtual void OnTestIterationStart(const UnitTest& unit_test,
+ int iteration) = 0;
+
+ // Fired before environment set-up for each iteration of tests starts.
+ virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
+
+ // Fired after environment set-up for each iteration of tests ends.
+ virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
+
+ // Fired before the test case starts.
+ virtual void OnTestCaseStart(const TestCase& test_case) = 0;
+
+ // Fired before the test starts.
+ virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+ // Fired after a failed assertion or a SUCCESS().
+ virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
+
+ // Fired after the test ends.
+ virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+ // Fired after the test case ends.
+ virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
+
+ // Fired before environment tear-down for each iteration of tests starts.
+ virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
+
+ // Fired after environment tear-down for each iteration of tests ends.
+ virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
+
+ // Fired after each iteration of tests finishes.
+ virtual void OnTestIterationEnd(const UnitTest& unit_test,
+ int iteration) = 0;
+
+ // Fired after all test activities have ended.
+ virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build. For
+// comments about each method please see the definition of TestEventListener
+// above.
+class EmptyTestEventListener : public TestEventListener {
+ public:
+ virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+ int /*iteration*/) {}
+ virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {}
+ virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+ virtual void OnTestStart(const TestInfo& /*test_info*/) {}
+ virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {}
+ virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
+ virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
+ virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {}
+ virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+ int /*iteration*/) {}
+ virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+};
+
+// TestEventListeners lets users add listeners to track events in Google Test.
+class GTEST_API_ TestEventListeners {
+ public:
+ TestEventListeners();
+ ~TestEventListeners();
+
+ // Appends an event listener to the end of the list. Google Test assumes
+ // the ownership of the listener (i.e. it will delete the listener when
+ // the test program finishes).
+ void Append(TestEventListener* listener);
+
+ // Removes the given event listener from the list and returns it. It then
+ // becomes the caller's responsibility to delete the listener. Returns
+ // NULL if the listener is not found in the list.
+ TestEventListener* Release(TestEventListener* listener);
+
+ // Returns the standard listener responsible for the default console
+ // output. Can be removed from the listeners list to shut down default
+ // console output. Note that removing this object from the listener list
+ // with Release transfers its ownership to the caller and makes this
+ // function return NULL the next time.
+ TestEventListener* default_result_printer() const {
+ return default_result_printer_;
+ }
+
+ // Returns the standard listener responsible for the default XML output
+ // controlled by the --gtest_output=xml flag. Can be removed from the
+ // listeners list by users who want to shut down the default XML output
+ // controlled by this flag and substitute it with custom one. Note that
+ // removing this object from the listener list with Release transfers its
+ // ownership to the caller and makes this function return NULL the next
+ // time.
+ TestEventListener* default_xml_generator() const {
+ return default_xml_generator_;
+ }
+
+ private:
+ friend class TestCase;
+ 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
+ // subscribers.
+ TestEventListener* repeater();
+
+ // Sets the default_result_printer attribute to the provided listener.
+ // The listener is also added to the listener list and previous
+ // default_result_printer is removed from it and deleted. The listener can
+ // also be NULL in which case it will not be added to the list. Does
+ // nothing if the previous and the current listener objects are the same.
+ void SetDefaultResultPrinter(TestEventListener* listener);
+
+ // Sets the default_xml_generator attribute to the provided listener. The
+ // listener is also added to the listener list and previous
+ // default_xml_generator is removed from it and deleted. The listener can
+ // also be NULL in which case it will not be added to the list. Does
+ // nothing if the previous and the current listener objects are the same.
+ void SetDefaultXmlGenerator(TestEventListener* listener);
+
+ // Controls whether events will be forwarded by the repeater to the
+ // listeners in the list.
+ bool EventForwardingEnabled() const;
+ void SuppressEventForwarding();
+
+ // The actual list of listeners.
+ internal::TestEventRepeater* repeater_;
+ // Listener responsible for the standard result output.
+ TestEventListener* default_result_printer_;
+ // Listener responsible for the creation of the XML output file.
+ TestEventListener* default_xml_generator_;
+
+ // We disallow copying TestEventListeners.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
+};
+
+// A UnitTest consists of a vector of TestCases.
+//
+// This is a singleton class. The only instance of UnitTest is
+// created when UnitTest::GetInstance() is first called. This
+// instance is never deleted.
+//
+// UnitTest is not copyable.
+//
+// This class is thread-safe as long as the methods are called
+// according to their specification.
+class GTEST_API_ UnitTest {
+ public:
+ // Gets the singleton UnitTest object. The first time this method
+ // is called, a UnitTest object is constructed and returned.
+ // Consecutive calls will return the same object.
+ static UnitTest* GetInstance();
+
+ // Runs all tests in this UnitTest object and prints the result.
+ // Returns 0 if successful, or 1 otherwise.
+ //
+ // This method can only be called from the main thread.
+ //
+ // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+ int Run() GTEST_MUST_USE_RESULT_;
+
+ // Returns the working directory when the first TEST() or TEST_F()
+ // was executed. The UnitTest object owns the string.
+ const char* original_working_dir() const;
+
+ // Returns the TestCase object for the test that's currently running,
+ // or NULL if no test is running.
+ const TestCase* current_test_case() const;
+
+ // Returns the TestInfo object for the test that's currently running,
+ // or NULL if no test is running.
+ const TestInfo* current_test_info() const;
+
+ // Returns the random seed used at the start of the current test run.
+ int random_seed() const;
+
+#if GTEST_HAS_PARAM_TEST
+ // Returns the ParameterizedTestCaseRegistry object used to keep track of
+ // value-parameterized tests and instantiate and register them.
+ //
+ // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+ internal::ParameterizedTestCaseRegistry& parameterized_test_registry();
+#endif // GTEST_HAS_PARAM_TEST
+
+ // Gets the number of successful test cases.
+ int successful_test_case_count() const;
+
+ // Gets the number of failed test cases.
+ int failed_test_case_count() const;
+
+ // Gets the number of all test cases.
+ int total_test_case_count() const;
+
+ // Gets the number of all test cases that contain at least one test
+ // that should run.
+ int test_case_to_run_count() const;
+
+ // Gets the number of successful tests.
+ int successful_test_count() const;
+
+ // Gets the number of failed tests.
+ int failed_test_count() const;
+
+ // Gets the number of disabled tests.
+ int disabled_test_count() const;
+
+ // Gets the number of all tests.
+ int total_test_count() const;
+
+ // Gets the number of tests that should run.
+ int test_to_run_count() const;
+
+ // Gets the elapsed time, in milliseconds.
+ TimeInMillis elapsed_time() const;
+
+ // Returns true iff the unit test passed (i.e. all test cases passed).
+ bool Passed() const;
+
+ // Returns true iff the unit test failed (i.e. some test case failed
+ // or something outside of all tests failed).
+ bool Failed() const;
+
+ // Gets the i-th test case among all the test cases. i can range from 0 to
+ // total_test_case_count() - 1. If i is not in that range, returns NULL.
+ const TestCase* GetTestCase(int i) const;
+
+ // Returns the list of event listeners that can be used to track events
+ // inside Google Test.
+ TestEventListeners& listeners();
+
+ private:
+ // Registers and returns a global test environment. When a test
+ // program is run, all global test environments will be set-up in
+ // the order they were registered. After all tests in the program
+ // have finished, all global test environments will be torn-down in
+ // the *reverse* order they were registered.
+ //
+ // The UnitTest object takes ownership of the given environment.
+ //
+ // This method can only be called from the main thread.
+ Environment* AddEnvironment(Environment* env);
+
+ // 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 assertion macros instead of calling this directly.
+ void AddTestPartResult(TestPartResult::Type result_type,
+ const char* file_name,
+ int line_number,
+ const internal::String& message,
+ const internal::String& os_stack_trace);
+
+ // Adds a TestProperty to the current TestResult object. If the result already
+ // contains a property with the same key, the value will be updated.
+ void RecordPropertyForCurrentTest(const char* key, const char* value);
+
+ // Gets the i-th test case among all the test cases. i can range from 0 to
+ // total_test_case_count() - 1. If i is not in that range, returns NULL.
+ TestCase* GetMutableTestCase(int i);
+
+ // Accessors for the implementation object.
+ internal::UnitTestImpl* impl() { return impl_; }
+ const internal::UnitTestImpl* impl() const { return impl_; }
+
+ // These classes and funcions are friends as they need to access private
+ // members of UnitTest.
+ friend class Test;
+ friend class internal::AssertHelper;
+ friend class internal::ScopedTrace;
+ friend Environment* AddGlobalTestEnvironment(Environment* env);
+ friend internal::UnitTestImpl* internal::GetUnitTestImpl();
+ friend void internal::ReportFailureInUnknownLocation(
+ TestPartResult::Type result_type,
+ const internal::String& message);
+
+ // Creates an empty UnitTest.
+ UnitTest();
+
+ // D'tor
+ virtual ~UnitTest();
+
+ // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+ // Google Test trace stack.
+ void PushGTestTrace(const internal::TraceInfo& trace);
+
+ // Pops a trace from the per-thread Google Test trace stack.
+ void PopGTestTrace();
+
+ // Protects mutable state in *impl_. This is mutable as some const
+ // methods need to lock it too.
+ mutable internal::Mutex mutex_;
+
+ // Opaque implementation object. This field is never changed once
+ // the object is constructed. We don't mark it as const here, as
+ // doing so will cause a warning in the constructor of UnitTest.
+ // Mutable state in *impl_ is protected by mutex_.
+ internal::UnitTestImpl* impl_;
+
+ // We disallow copying UnitTest.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
+};
+
+// A convenient wrapper for adding an environment for the test
+// program.
+//
+// You should call this before RUN_ALL_TESTS() is called, probably in
+// main(). If you use gtest_main, you need to call this before main()
+// starts for it to take effect. For example, you can define a global
+// variable like this:
+//
+// testing::Environment* const foo_env =
+// testing::AddGlobalTestEnvironment(new FooEnvironment);
+//
+// However, we strongly recommend you to write your own main() and
+// call AddGlobalTestEnvironment() there, as relying on initialization
+// of global variables makes the code harder to read and may cause
+// problems when you register multiple environments from different
+// translation units and the environments have dependencies among them
+// (remember that the compiler doesn't guarantee the order in which
+// global variables from different translation units are initialized).
+inline Environment* AddGlobalTestEnvironment(Environment* env) {
+ return UnitTest::GetInstance()->AddEnvironment(env);
+}
+
+// Initializes Google Test. This must be called before calling
+// RUN_ALL_TESTS(). In particular, it parses a command line for the
+// flags that Google Test recognizes. Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned. Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+GTEST_API_ void InitGoogleTest(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
+
+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
+// print a char* as a raw pointer when it is compared against another
+// char*, and print it as a C string when it is compared against an
+// std::string object, for example.
+//
+// The default implementation ignores the type of the other operand.
+// Some specialized versions are used to handle formatting wide or
+// narrow C strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename T1, typename T2>
+String FormatForComparisonFailureMessage(const T1& value,
+ const T2& /* other_operand */) {
+ return FormatForFailureMessage(value);
+}
+
+// The helper function for {ASSERT|EXPECT}_EQ.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQ(const char* expected_expression,
+ const char* actual_expression,
+ 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
+ // signed/unsigned mismatch.
+#endif
+
+ if (expected == actual) {
+ return AssertionSuccess();
+ }
+
+#ifdef _MSC_VER
+#pragma warning(pop) // Restores the warning state.
+#endif
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ FormatForComparisonFailureMessage(expected, actual),
+ FormatForComparisonFailureMessage(actual, expected),
+ false);
+}
+
+// With this overloaded version, we allow anonymous enums to be used
+// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums
+// can be implicitly cast to BiggestInt.
+GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression,
+ const char* actual_expression,
+ BiggestInt expected,
+ BiggestInt actual);
+
+// The helper class for {ASSERT|EXPECT}_EQ. The template argument
+// lhs_is_null_literal is true iff the first argument to ASSERT_EQ()
+// is a null pointer literal. The following default implementation is
+// for lhs_is_null_literal being false.
+template <bool lhs_is_null_literal>
+class EqHelper {
+ public:
+ // This templatized version is for the general case.
+ template <typename T1, typename T2>
+ static AssertionResult Compare(const char* expected_expression,
+ const char* actual_expression,
+ const T1& expected,
+ const T2& actual) {
+ return CmpHelperEQ(expected_expression, actual_expression, expected,
+ actual);
+ }
+
+ // With this overloaded version, we allow anonymous enums to be used
+ // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
+ // enums can be implicitly cast to BiggestInt.
+ //
+ // Even though its body looks the same as the above version, we
+ // cannot merge the two, as it will make anonymous enums unhappy.
+ static AssertionResult Compare(const char* expected_expression,
+ const char* actual_expression,
+ BiggestInt expected,
+ BiggestInt actual) {
+ return CmpHelperEQ(expected_expression, actual_expression, expected,
+ actual);
+ }
+};
+
+// This specialization is used when the first argument to ASSERT_EQ()
+// is a null pointer literal.
+template <>
+class EqHelper<true> {
+ public:
+ // We define two overloaded versions of Compare(). The first
+ // version will be picked when the second argument to ASSERT_EQ() is
+ // 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) {
+ 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) {
+ // We already know that 'expected' is a null pointer.
+ return CmpHelperEQ(expected_expression, actual_expression,
+ static_cast<T2*>(NULL), actual);
+ }
+};
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste
+// of similar code.
+//
+// For each templatized helper function, we also define an overloaded
+// version for BiggestInt in order to reduce code bloat and allow
+// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled
+// with gcc 4.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+template <typename T1, typename T2>\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+ const T1& val1, const T2& val2) {\
+ if (val1 op val2) {\
+ return AssertionSuccess();\
+ } else {\
+ Message msg;\
+ msg << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+ << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+ return AssertionFailure(msg);\
+ }\
+}\
+GTEST_API_ AssertionResult CmpHelper##op_name(\
+ const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// Implements the helper function for {ASSERT|EXPECT}_NE
+GTEST_IMPL_CMP_HELPER_(NE, !=);
+// Implements the helper function for {ASSERT|EXPECT}_LE
+GTEST_IMPL_CMP_HELPER_(LE, <=);
+// Implements the helper function for {ASSERT|EXPECT}_LT
+GTEST_IMPL_CMP_HELPER_(LT, < );
+// Implements the helper function for {ASSERT|EXPECT}_GE
+GTEST_IMPL_CMP_HELPER_(GE, >=);
+// Implements the helper function for {ASSERT|EXPECT}_GT
+GTEST_IMPL_CMP_HELPER_(GT, > );
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+ const char* actual_expression,
+ const char* expected,
+ const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+ const char* actual_expression,
+ const char* expected,
+ const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+ const char* s2_expression,
+ const char* s1,
+ const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+ const char* s2_expression,
+ const char* s1,
+ const char* s2);
+
+
+// Helper function for *_STREQ on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+ const char* actual_expression,
+ const wchar_t* expected,
+ const wchar_t* actual);
+
+// Helper function for *_STRNE on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+ const char* s2_expression,
+ const wchar_t* s1,
+ const wchar_t* s2);
+
+} // namespace internal
+
+// IsSubstring() and IsNotSubstring() are intended to be used as the
+// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
+// themselves. They check whether needle is a substring of haystack
+// (NULL is considered a substring of itself only), and return an
+// appropriate error message when they fail.
+//
+// The {needle,haystack}_expr arguments are the stringified
+// expressions that generated the two real arguments.
+GTEST_API_ AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::string& needle, const ::std::string& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::string& needle, const ::std::string& haystack);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::wstring& needle, const ::std::wstring& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::wstring& needle, const ::std::wstring& haystack);
+#endif // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+// Helper template function for comparing floating-points.
+//
+// Template parameter:
+//
+// RawType: the raw floating-point type (either float or double)
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename RawType>
+AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression,
+ const char* actual_expression,
+ RawType expected,
+ RawType actual) {
+ const FloatingPoint<RawType> lhs(expected), rhs(actual);
+
+ if (lhs.AlmostEquals(rhs)) {
+ return AssertionSuccess();
+ }
+
+ StrStream expected_ss;
+ expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+ << expected;
+
+ StrStream 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),
+ false);
+}
+
+// Helper function for implementing ASSERT_NEAR.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
+ const char* expr2,
+ const char* abs_error_expr,
+ double val1,
+ double val2,
+ double abs_error);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// A class that enables one to stream messages to assertion macros
+class GTEST_API_ AssertHelper {
+ public:
+ // Constructor.
+ AssertHelper(TestPartResult::Type type,
+ const char* file,
+ int line,
+ const char* message);
+ ~AssertHelper();
+
+ // Message assignment is a semantic trick to enable assertion
+ // streaming; see the GTEST_MESSAGE_ macro below.
+ void operator=(const Message& message) const;
+
+ private:
+ // We put our data in a struct so that the size of the AssertHelper class can
+ // be as small as possible. This is important because gcc is incapable of
+ // re-using stack space even for temporary variables, so every EXPECT_EQ
+ // reserves stack space for another AssertHelper.
+ struct AssertHelperData {
+ AssertHelperData(TestPartResult::Type t,
+ const char* srcfile,
+ int line_num,
+ const char* msg)
+ : type(t), file(srcfile), line(line_num), message(msg) { }
+
+ TestPartResult::Type const type;
+ const char* const file;
+ int const line;
+ String const message;
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
+ };
+
+ AssertHelperData* const data_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
+};
+
+} // namespace internal
+
+#if GTEST_HAS_PARAM_TEST
+// The abstract base class that all value-parameterized tests inherit from.
+//
+// This class adds support for accessing the test parameter value via
+// the GetParam() method.
+//
+// Use it with one of the parameter generator defining functions, like Range(),
+// Values(), ValuesIn(), Bool(), and Combine().
+//
+// class FooTest : public ::testing::TestWithParam<int> {
+// protected:
+// FooTest() {
+// // Can use GetParam() here.
+// }
+// virtual ~FooTest() {
+// // Can use GetParam() here.
+// }
+// virtual void SetUp() {
+// // Can use GetParam() here.
+// }
+// virtual void TearDown {
+// // Can use GetParam() here.
+// }
+// };
+// TEST_P(FooTest, DoesBar) {
+// // Can use GetParam() method here.
+// Foo foo;
+// ASSERT_TRUE(foo.DoesBar(GetParam()));
+// }
+// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
+
+template <typename T>
+class TestWithParam : public Test {
+ public:
+ typedef T ParamType;
+
+ // The current parameter value. Is also available in the test fixture's
+ // constructor.
+ const ParamType& GetParam() const { return *parameter_; }
+
+ private:
+ // Sets parameter value. The caller is responsible for making sure the value
+ // remains alive and unchanged throughout the current test.
+ static void SetParam(const ParamType* parameter) {
+ parameter_ = parameter;
+ }
+
+ // Static value used for accessing parameter during a test lifetime.
+ static const ParamType* parameter_;
+
+ // TestClass must be a subclass of TestWithParam<T>.
+ template <class TestClass> friend class internal::ParameterizedTestFactory;
+};
+
+template <typename T>
+const T* TestWithParam<T>::parameter_ = NULL;
+
+#endif // GTEST_HAS_PARAM_TEST
+
+// Macros for indicating success/failure in test code.
+
+// ADD_FAILURE unconditionally adds a failure to the current test.
+// SUCCEED generates a success - it doesn't automatically make the
+// current test successful, as a test is only successful when it has
+// no failure.
+//
+// EXPECT_* verifies that a certain condition is satisfied. If not,
+// it behaves like ADD_FAILURE. In particular:
+//
+// EXPECT_TRUE verifies that a Boolean condition is true.
+// EXPECT_FALSE verifies that a Boolean condition is false.
+//
+// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
+// that they will also abort the current function on failure. People
+// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
+// writing data-driven tests often find themselves using ADD_FAILURE
+// and EXPECT_* more.
+//
+// Examples:
+//
+// EXPECT_TRUE(server.StatusIsOK());
+// ASSERT_FALSE(server.HasPendingRequest(port))
+// << "There are still pending requests " << "on port " << port;
+
+// Generates a nonfatal failure with a generic message.
+#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+
+// 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()
+#endif
+
+// Generates a success with a generic message.
+#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
+
+// 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()
+#endif
+
+// Macros for testing exceptions.
+//
+// * {ASSERT|EXPECT}_THROW(statement, expected_exception):
+// Tests that the statement throws the expected exception.
+// * {ASSERT|EXPECT}_NO_THROW(statement):
+// Tests that the statement doesn't throw any exception.
+// * {ASSERT|EXPECT}_ANY_THROW(statement):
+// Tests that the statement throws an exception.
+
+#define EXPECT_THROW(statement, expected_exception) \
+ GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_NO_THROW(statement) \
+ GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_ANY_THROW(statement) \
+ GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_THROW(statement, expected_exception) \
+ GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
+#define ASSERT_NO_THROW(statement) \
+ GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
+#define ASSERT_ANY_THROW(statement) \
+ GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
+
+// Boolean assertions. Condition can be either a Boolean expression or an
+// AssertionResult. For more information on how to use AssertionResult with
+// these macros see comments on that class.
+#define EXPECT_TRUE(condition) \
+ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+ GTEST_NONFATAL_FAILURE_)
+#define EXPECT_FALSE(condition) \
+ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+ GTEST_NONFATAL_FAILURE_)
+#define ASSERT_TRUE(condition) \
+ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+ GTEST_FATAL_FAILURE_)
+#define ASSERT_FALSE(condition) \
+ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+ GTEST_FATAL_FAILURE_)
+
+// Includes the auto-generated header that implements a family of
+// generic predicate assertion macros.
+#include <gtest/gtest_pred_impl.h>
+
+// Macros for testing equalities and inequalities.
+//
+// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
+// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2
+// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2
+// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2
+// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2
+// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2
+//
+// When they are not, Google Test prints both the tested expressions and
+// their actual values. The values must be compatible built-in types,
+// or you will get a compiler error. By "compatible" we mean that the
+// values can be compared by the respective operator.
+//
+// Note:
+//
+// 1. It is possible to make a user-defined type work with
+// {ASSERT|EXPECT}_??(), but that requires overloading the
+// comparison operators and is thus discouraged by the Google C++
+// Usage Guide. Therefore, you are advised to use the
+// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
+// equal.
+//
+// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
+// pointers (in particular, C strings). Therefore, if you use it
+// with two C strings, you are testing how their locations in memory
+// are related, not how their content is related. To compare two C
+// strings by content, use {ASSERT|EXPECT}_STR*().
+//
+// 3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to
+// {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you
+// what the actual value is when it fails, and similarly for the
+// other comparisons.
+//
+// 4. Do not depend on the order in which {ASSERT|EXPECT}_??()
+// evaluate their arguments, which is undefined.
+//
+// 5. These macros evaluate their arguments exactly once.
+//
+// Examples:
+//
+// EXPECT_NE(5, Foo());
+// EXPECT_EQ(NULL, a_pointer);
+// ASSERT_LT(i, array_size);
+// ASSERT_GT(records.size(), 0) << "There is no record left.";
+
+#define EXPECT_EQ(expected, actual) \
+ EXPECT_PRED_FORMAT2(::testing::internal:: \
+ EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+ expected, actual)
+#define EXPECT_NE(expected, actual) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual)
+#define EXPECT_LE(val1, val2) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define EXPECT_LT(val1, val2) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define EXPECT_GE(val1, val2) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define EXPECT_GT(val1, val2) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+#define ASSERT_EQ(expected, actual) \
+ ASSERT_PRED_FORMAT2(::testing::internal:: \
+ EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+ expected, actual)
+#define ASSERT_NE(val1, val2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define ASSERT_LE(val1, val2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define ASSERT_LT(val1, val2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define ASSERT_GE(val1, val2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define ASSERT_GT(val1, val2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+// C String Comparisons. All tests treat NULL and any non-NULL string
+// as different. Two NULLs are equal.
+//
+// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2
+// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2
+// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
+// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
+//
+// For wide or narrow string objects, you can use the
+// {ASSERT|EXPECT}_??() macros.
+//
+// Don't depend on the order in which the arguments are evaluated,
+// which is undefined.
+//
+// These macros evaluate their arguments exactly once.
+
+#define EXPECT_STREQ(expected, actual) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define EXPECT_STRNE(s1, s2) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define EXPECT_STRCASEEQ(expected, actual) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define EXPECT_STRCASENE(s1, s2)\
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+#define ASSERT_STREQ(expected, actual) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define ASSERT_STRNE(s1, s2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define ASSERT_STRCASEEQ(expected, actual) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define ASSERT_STRCASENE(s1, s2)\
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+// Macros for comparing floating-point numbers.
+//
+// * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual):
+// Tests that two float values are almost equal.
+// * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual):
+// Tests that two double values are almost equal.
+// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
+// Tests that v1 and v2 are within the given distance to each other.
+//
+// Google Test uses ULP-based comparison to automatically pick a default
+// error bound that is appropriate for the operands. See the
+// FloatingPoint template class in gtest-internal.h if you are
+// interested in the implementation details.
+
+#define EXPECT_FLOAT_EQ(expected, actual)\
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+ expected, actual)
+
+#define EXPECT_DOUBLE_EQ(expected, actual)\
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+ expected, actual)
+
+#define ASSERT_FLOAT_EQ(expected, actual)\
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+ expected, actual)
+
+#define ASSERT_DOUBLE_EQ(expected, actual)\
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+ expected, actual)
+
+#define EXPECT_NEAR(val1, val2, abs_error)\
+ EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+ val1, val2, abs_error)
+
+#define ASSERT_NEAR(val1, val2, abs_error)\
+ ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+ val1, val2, abs_error)
+
+// These predicate format functions work on floating-point values, and
+// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
+//
+// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
+
+// Asserts that val1 is less than, or almost equal to, val2. Fails
+// otherwise. In particular, it fails if either val1 or val2 is NaN.
+GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
+ float val1, float val2);
+GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
+ double val1, double val2);
+
+
+#if GTEST_OS_WINDOWS
+
+// Macros that test for HRESULT failure and success, these are only useful
+// on Windows, and rely on Windows SDK macros and APIs to compile.
+//
+// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
+//
+// When expr unexpectedly fails or succeeds, Google Test prints the
+// 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) \
+ EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+#define ASSERT_HRESULT_SUCCEEDED(expr) \
+ ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+#define EXPECT_HRESULT_FAILED(expr) \
+ EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#define ASSERT_HRESULT_FAILED(expr) \
+ ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#endif // GTEST_OS_WINDOWS
+
+// Macros that execute statement and check that it doesn't generate new fatal
+// failures in the current thread.
+//
+// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
+//
+// Examples:
+//
+// EXPECT_NO_FATAL_FAILURE(Process());
+// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
+//
+#define ASSERT_NO_FATAL_FAILURE(statement) \
+ GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
+#define EXPECT_NO_FATAL_FAILURE(statement) \
+ GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
+
+// Causes a trace (including the source file path, the current line
+// number, and the given message) to be included in every test failure
+// message generated by code in the current scope. The effect is
+// undone when the control leaves the current scope.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// In the implementation, we include the current line number as part
+// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
+// to appear in the same block - as long as they are on different
+// lines.
+#define SCOPED_TRACE(message) \
+ ::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.
+//
+// Instead of making StaticAssertTypeEq a class template, we make it a
+// function template that invokes a helper class template. This
+// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
+// defining objects of that type.
+//
+// CAVEAT:
+//
+// When used inside a method of a class template,
+// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
+// instantiated. For example, given:
+//
+// template <typename T> class Foo {
+// public:
+// void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+// };
+//
+// the code:
+//
+// void Test1() { Foo<bool> foo; }
+//
+// will NOT generate a compiler error, as Foo<bool>::Bar() is never
+// actually instantiated. Instead, you need:
+//
+// void Test2() { Foo<bool> foo; foo.Bar(); }
+//
+// to cause a compiler error.
+template <typename T1, typename T2>
+bool StaticAssertTypeEq() {
+ internal::StaticAssertTypeEqHelper<T1, T2>();
+ return true;
+}
+
+// Defines a test.
+//
+// The first parameter is the name of the test case, and the second
+// parameter is the name of the test within the test case.
+//
+// The convention is to end the test case name with "Test". For
+// example, a test case for the Foo class can be named FooTest.
+//
+// The user should put his test code between braces after using this
+// macro. Example:
+//
+// TEST(FooTest, InitializesCorrectly) {
+// Foo foo;
+// EXPECT_TRUE(foo.StatusIsOK());
+// }
+
+// Note that we call GetTestTypeId() instead of GetTypeId<
+// ::testing::Test>() here to get the type ID of testing::Test. This
+// is to work around a suspected linker bug when using Google Test as
+// a framework on Mac OS X. The bug causes GetTypeId<
+// ::testing::Test>() to return different values depending on whether
+// the call is from the Google Test framework itself or from user test
+// code. GetTestTypeId() is guaranteed to always return the same
+// value, as it always calls GetTypeId<>() from the Google Test
+// framework.
+#define GTEST_TEST(test_case_name, test_name)\
+ GTEST_TEST_(test_case_name, test_name, \
+ ::testing::Test, ::testing::internal::GetTestTypeId())
+
+// 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)
+#endif
+
+// Defines a test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test case name. The second parameter is the
+// name of the test within the test case.
+//
+// A test fixture class must be declared earlier. The user should put
+// his test code between braces after using this macro. Example:
+//
+// class FooTest : public testing::Test {
+// protected:
+// virtual void SetUp() { b_.AddElement(3); }
+//
+// Foo a_;
+// Foo b_;
+// };
+//
+// TEST_F(FooTest, InitializesCorrectly) {
+// EXPECT_TRUE(a_.StatusIsOK());
+// }
+//
+// TEST_F(FooTest, ReturnsElementCountCorrectly) {
+// EXPECT_EQ(0, a_.size());
+// EXPECT_EQ(1, b_.size());
+// }
+
+#define TEST_F(test_fixture, test_name)\
+ GTEST_TEST_(test_fixture, test_name, test_fixture, \
+ ::testing::internal::GetTypeId<test_fixture>())
+
+// Use this macro in main() to run all tests. It returns 0 if all
+// tests are successful, or 1 otherwise.
+//
+// RUN_ALL_TESTS() should be invoked after the command line has been
+// parsed by InitGoogleTest().
+
+#define RUN_ALL_TESTS()\
+ (::testing::UnitTest::GetInstance()->Run())
+
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/gtest_pred_impl.h b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest_pred_impl.h
new file mode 100644
index 0000000..e1e2f8c
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest_pred_impl.h
@@ -0,0 +1,368 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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
+// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// 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.
+#endif // GTEST_INCLUDE_GTEST_GTEST_H_
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+// ASSERT_PRED_FORMAT1(pred_format, v1)
+// ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+// ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult. See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+// ASSERT_PRED1(pred, v1)
+// ASSERT_PRED2(pred, v1, v2)
+// ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most 5.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce. Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const ::testing::AssertionResult gtest_ar = (expression)) \
+ ; \
+ else \
+ on_failure(gtest_ar.failure_message())
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
+// this in your code.
+template <typename Pred,
+ typename T1>
+AssertionResult AssertPred1Helper(const char* pred_text,
+ const char* e1,
+ Pred pred,
+ 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);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
+ GTEST_ASSERT_(pred_format(#v1, v1),\
+ on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
+// this in your code.
+#define GTEST_PRED1_(pred, v1, on_failure)\
+ GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
+ #v1, \
+ pred, \
+ v1), on_failure)
+
+// Unary predicate assertion macros.
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+ GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED1(pred, v1) \
+ GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+ GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED1(pred, v1) \
+ GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
+// this in your code.
+template <typename Pred,
+ typename T1,
+ typename T2>
+AssertionResult AssertPred2Helper(const char* pred_text,
+ const char* e1,
+ const char* e2,
+ Pred pred,
+ const T1& v1,
+ 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);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
+ GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2),\
+ on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
+// this in your code.
+#define GTEST_PRED2_(pred, v1, v2, on_failure)\
+ GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
+ #v1, \
+ #v2, \
+ pred, \
+ v1, \
+ v2), on_failure)
+
+// Binary predicate assertion macros.
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+ GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED2(pred, v1, v2) \
+ GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+ GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED2(pred, v1, v2) \
+ GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
+// this in your code.
+template <typename Pred,
+ typename T1,
+ typename T2,
+ typename T3>
+AssertionResult AssertPred3Helper(const char* pred_text,
+ const char* e1,
+ const char* e2,
+ const char* e3,
+ Pred pred,
+ const T1& v1,
+ const T2& v2,
+ 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);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
+ GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3),\
+ on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
+// this in your code.
+#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
+ GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
+ #v1, \
+ #v2, \
+ #v3, \
+ pred, \
+ v1, \
+ v2, \
+ v3), on_failure)
+
+// Ternary predicate assertion macros.
+#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+ GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED3(pred, v1, v2, v3) \
+ GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+ GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED3(pred, v1, v2, v3) \
+ GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
+// this in your code.
+template <typename Pred,
+ typename T1,
+ typename T2,
+ typename T3,
+ typename T4>
+AssertionResult AssertPred4Helper(const char* pred_text,
+ const char* e1,
+ const char* e2,
+ const char* e3,
+ const char* e4,
+ Pred pred,
+ const T1& v1,
+ const T2& v2,
+ const T3& v3,
+ 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);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
+ GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4),\
+ on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
+// this in your code.
+#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
+ GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
+ #v1, \
+ #v2, \
+ #v3, \
+ #v4, \
+ pred, \
+ v1, \
+ v2, \
+ v3, \
+ v4), on_failure)
+
+// 4-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+ GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
+ GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+ GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
+ GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
+// this in your code.
+template <typename Pred,
+ typename T1,
+ typename T2,
+ typename T3,
+ typename T4,
+ typename T5>
+AssertionResult AssertPred5Helper(const char* pred_text,
+ const char* e1,
+ const char* e2,
+ const char* e3,
+ const char* e4,
+ const char* e5,
+ Pred pred,
+ const T1& v1,
+ const T2& v2,
+ const T3& v3,
+ const T4& v4,
+ 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);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
+ GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5),\
+ on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
+// this in your code.
+#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
+ GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
+ #v1, \
+ #v2, \
+ #v3, \
+ #v4, \
+ #v5, \
+ pred, \
+ v1, \
+ v2, \
+ v3, \
+ v4, \
+ v5), on_failure)
+
+// 5-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+ GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
+ GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+ GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
+ GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+
+
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/gtest_prod.h b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest_prod.h
new file mode 100644
index 0000000..da80ddc
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/gtest_prod.h
@@ -0,0 +1,58 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Google C++ Testing Framework definitions useful in production code.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+
+// When you need to test the private or protected members of a class,
+// use the FRIEND_TEST macro to declare your tests as friends of the
+// class. For example:
+//
+// class MyClass {
+// private:
+// void MyMethod();
+// FRIEND_TEST(MyClassTest, MyMethod);
+// };
+//
+// class MyClassTest : public testing::Test {
+// // ...
+// };
+//
+// TEST_F(MyClassTest, MyMethod) {
+// // Can call MyClass::MyMethod() here.
+// }
+
+#define FRIEND_TEST(test_case_name, test_name)\
+friend class test_case_name##_##test_name##_Test
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
new file mode 100644
index 0000000..e433084
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
@@ -0,0 +1,275 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines internal utilities needed for implementing
+// death tests. They are subject to change without notice.
+
+#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>
+
+namespace testing {
+namespace internal {
+
+GTEST_DECLARE_string_(internal_run_death_test);
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kDeathTestStyleFlag[] = "death_test_style";
+const char kDeathTestUseFork[] = "death_test_use_fork";
+const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
+
+#if GTEST_HAS_DEATH_TEST
+
+// DeathTest is a class that hides much of the complexity of the
+// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method
+// returns a concrete class that depends on the prevailing death test
+// style, as defined by the --gtest_death_test_style and/or
+// --gtest_internal_run_death_test flags.
+
+// In describing the results of death tests, these terms are used with
+// the corresponding definitions:
+//
+// exit status: The integer exit information in the format specified
+// by wait(2)
+// exit code: The integer code passed to exit(3), _exit(2), or
+// returned from main()
+class GTEST_API_ DeathTest {
+ public:
+ // Create returns false if there was an error determining the
+ // appropriate action to take for the current death test; for example,
+ // if the gtest_death_test_style flag is set to an invalid value.
+ // The LastMessage method will return a more detailed message in that
+ // case. Otherwise, the DeathTest pointer pointed to by the "test"
+ // argument is set. If the death test should be skipped, the pointer
+ // is set to NULL; otherwise, it is set to the address of a new concrete
+ // DeathTest object that controls the execution of the current test.
+ static bool Create(const char* statement, const RE* regex,
+ const char* file, int line, DeathTest** test);
+ DeathTest();
+ virtual ~DeathTest() { }
+
+ // A helper class that aborts a death test when it's deleted.
+ class ReturnSentinel {
+ public:
+ explicit ReturnSentinel(DeathTest* test) : test_(test) { }
+ ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
+ private:
+ DeathTest* const test_;
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
+ } GTEST_ATTRIBUTE_UNUSED_;
+
+ // An enumeration of possible roles that may be taken when a death
+ // test is encountered. EXECUTE means that the death test logic should
+ // be executed immediately. OVERSEE means that the program should prepare
+ // the appropriate environment for a child process to execute the death
+ // 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 };
+
+ // Assumes one of the above roles.
+ virtual TestRole AssumeRole() = 0;
+
+ // Waits for the death test to finish and returns its status.
+ virtual int Wait() = 0;
+
+ // Returns true if the death test passed; that is, the test process
+ // exited during the test, its exit status matches a user-supplied
+ // predicate, and its stderr output matches a user-supplied regular
+ // expression.
+ // The user-supplied predicate may be a macro expression rather
+ // than a function pointer or functor, or else Wait and Passed could
+ // be combined.
+ virtual bool Passed(bool exit_status_ok) = 0;
+
+ // Signals that the death test did not die as expected.
+ virtual void Abort(AbortReason reason) = 0;
+
+ // Returns a human-readable outcome message regarding the outcome of
+ // the last death test.
+ static const char* LastMessage();
+
+ static void set_last_death_test_message(const String& message);
+
+ private:
+ // A string containing a description of the outcome of the last death test.
+ static String last_death_test_message_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
+};
+
+// Factory interface for death tests. May be mocked out for testing.
+class DeathTestFactory {
+ public:
+ virtual ~DeathTestFactory() { }
+ virtual bool Create(const char* statement, const RE* regex,
+ const char* file, int line, DeathTest** test) = 0;
+};
+
+// A concrete DeathTestFactory implementation for normal use.
+class DefaultDeathTestFactory : public DeathTestFactory {
+ public:
+ virtual bool Create(const char* statement, const RE* regex,
+ const char* file, int line, DeathTest** test);
+};
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+
+// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
+// ASSERT_EXIT*, and EXPECT_EXIT*.
+#define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::AlwaysTrue()) { \
+ const ::testing::internal::RE& gtest_regex = (regex); \
+ ::testing::internal::DeathTest* gtest_dt; \
+ if (!::testing::internal::DeathTest::Create(#statement, &gtest_regex, \
+ __FILE__, __LINE__, &gtest_dt)) { \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+ } \
+ if (gtest_dt != NULL) { \
+ ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
+ gtest_dt_ptr(gtest_dt); \
+ switch (gtest_dt->AssumeRole()) { \
+ case ::testing::internal::DeathTest::OVERSEE_TEST: \
+ if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+ } \
+ break; \
+ case ::testing::internal::DeathTest::EXECUTE_TEST: { \
+ ::testing::internal::DeathTest::ReturnSentinel \
+ gtest_sentinel(gtest_dt); \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
+ break; \
+ } \
+ } \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
+ fail(::testing::internal::DeathTest::LastMessage())
+// The symbol "fail" here expands to something into which a message
+// can be streamed.
+
+// A class representing the parsed contents of the
+// --gtest_internal_run_death_test flag, as it existed when
+// RUN_ALL_TESTS was called.
+class InternalRunDeathTestFlag {
+ public:
+ InternalRunDeathTestFlag(const String& a_file,
+ int a_line,
+ int an_index,
+ int a_write_fd)
+ : file_(a_file), line_(a_line), index_(an_index),
+ write_fd_(a_write_fd) {}
+
+ ~InternalRunDeathTestFlag() {
+ if (write_fd_ >= 0)
+ posix::Close(write_fd_);
+ }
+
+ String file() const { return file_; }
+ int line() const { return line_; }
+ int index() const { return index_; }
+ int write_fd() const { return write_fd_; }
+
+ private:
+ String file_;
+ int line_;
+ int index_;
+ int write_fd_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
+};
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
+
+#else // GTEST_HAS_DEATH_TEST
+
+// This macro is used for implementing macros such as
+// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
+// death tests are not supported. Those macros must compile on such systems
+// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
+// systems that support death tests. This allows one to write such a macro
+// on a system that does not support death tests and be sure that it will
+// compile on a death-test supporting system.
+//
+// Parameters:
+// statement - A statement that a macro such as EXPECT_DEATH would test
+// for program termination. This macro has to make sure this
+// statement is compiled but not executed, to ensure that
+// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
+// parameter iff EXPECT_DEATH compiles with it.
+// regex - A regex that a macro such as EXPECT_DEATH would use to test
+// the output of statement. This parameter has to be
+// compiled but not evaluated by this macro, to ensure that
+// this macro only accepts expressions that a macro such as
+// EXPECT_DEATH would accept.
+// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
+// and a return statement for ASSERT_DEATH_IF_SUPPORTED.
+// This ensures that ASSERT_DEATH_IF_SUPPORTED will not
+// compile inside functions where ASSERT_DEATH doesn't
+// compile.
+//
+// The branch that has an always false condition is used to ensure that
+// statement and regex are compiled (and thus syntactically correct) but
+// never executed. The unreachable code macro protects the terminator
+// statement from generating an 'unreachable code' warning in case
+// 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) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::AlwaysTrue()) { \
+ GTEST_LOG_(WARNING) \
+ << "Death tests are not supported on this platform.\n" \
+ << "Statement '" #statement "' cannot be verified."; \
+ } else if (::testing::internal::AlwaysFalse()) { \
+ ::testing::internal::RE::PartialMatch(".*", (regex)); \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ terminator; \
+ } else \
+ ::testing::Message()
+
+#endif // GTEST_HAS_DEATH_TEST
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h
new file mode 100644
index 0000000..4b76d79
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h
@@ -0,0 +1,210 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test filepath utilities
+//
+// This header file declares classes and functions used internally by
+// Google Test. They are subject to change without notice.
+//
+// This file is #included in <gtest/internal/gtest-internal.h>.
+// Do not include this header file separately!
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+
+#include <gtest/internal/gtest-string.h>
+
+namespace testing {
+namespace internal {
+
+// FilePath - a class for file and directory pathname manipulation which
+// handles platform-specific conventions (like the pathname separator).
+// Used for helper functions for naming files in a directory for xml output.
+// Except for Set methods, all methods are const or static, which provides an
+// "immutable value object" -- useful for peace of mind.
+// A FilePath with a value ending in a path separator ("like/this/") represents
+// a directory, otherwise it is assumed to represent a file. In either case,
+// it may or may not represent an actual file or directory in the file system.
+// Names are NOT checked for syntax correctness -- no checking for illegal
+// characters, malformed paths, etc.
+
+class GTEST_API_ FilePath {
+ public:
+ FilePath() : pathname_("") { }
+ FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
+
+ explicit FilePath(const char* pathname) : pathname_(pathname) {
+ Normalize();
+ }
+
+ explicit FilePath(const String& pathname) : pathname_(pathname) {
+ Normalize();
+ }
+
+ FilePath& operator=(const FilePath& rhs) {
+ Set(rhs);
+ return *this;
+ }
+
+ void Set(const FilePath& rhs) {
+ pathname_ = rhs.pathname_;
+ }
+
+ String ToString() const { return pathname_; }
+ const char* c_str() const { return pathname_.c_str(); }
+
+ // Returns the current working directory, or "" if unsuccessful.
+ static FilePath GetCurrentDir();
+
+ // Given directory = "dir", base_name = "test", number = 0,
+ // extension = "xml", returns "dir/test.xml". If number is greater
+ // than zero (e.g., 12), returns "dir/test_12.xml".
+ // On Windows platform, uses \ as the separator rather than /.
+ static FilePath MakeFileName(const FilePath& directory,
+ const FilePath& base_name,
+ int number,
+ const char* extension);
+
+ // Given directory = "dir", relative_path = "test.xml",
+ // returns "dir/test.xml".
+ // On Windows, uses \ as the separator rather than /.
+ static FilePath ConcatPaths(const FilePath& directory,
+ const FilePath& relative_path);
+
+ // Returns a pathname for a file that does not currently exist. The pathname
+ // will be directory/base_name.extension or
+ // directory/base_name_<number>.extension if directory/base_name.extension
+ // already exists. The number will be incremented until a pathname is found
+ // that does not already exist.
+ // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+ // There could be a race condition if two or more processes are calling this
+ // function at the same time -- they could both pick the same filename.
+ static FilePath GenerateUniqueFileName(const FilePath& directory,
+ const FilePath& base_name,
+ const char* extension);
+
+ // Returns true iff the path is NULL or "".
+ bool IsEmpty() const { return c_str() == NULL || *c_str() == '\0'; }
+
+ // If input name has a trailing separator character, removes it and returns
+ // the name, otherwise return the name string unmodified.
+ // On Windows platform, uses \ as the separator, other platforms use /.
+ FilePath RemoveTrailingPathSeparator() const;
+
+ // Returns a copy of the FilePath with the directory part removed.
+ // Example: FilePath("path/to/file").RemoveDirectoryName() returns
+ // FilePath("file"). If there is no directory part ("just_a_file"), it returns
+ // the FilePath unmodified. If there is no file part ("just_a_dir/") it
+ // returns an empty FilePath ("").
+ // On Windows platform, '\' is the path separator, otherwise it is '/'.
+ FilePath RemoveDirectoryName() const;
+
+ // RemoveFileName returns the directory path with the filename removed.
+ // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+ // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+ // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+ // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+ // On Windows platform, '\' is the path separator, otherwise it is '/'.
+ FilePath RemoveFileName() const;
+
+ // Returns a copy of the FilePath with the case-insensitive extension removed.
+ // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+ // FilePath("dir/file"). If a case-insensitive extension is not
+ // found, returns a copy of the original FilePath.
+ FilePath RemoveExtension(const char* extension) const;
+
+ // Creates directories so that path exists. Returns true if successful or if
+ // the directories already exist; returns false if unable to create
+ // directories for any reason. Will also return false if the FilePath does
+ // not represent a directory (that is, it doesn't end with a path separator).
+ bool CreateDirectoriesRecursively() const;
+
+ // Create the directory so that path exists. Returns true if successful or
+ // if the directory already exists; returns false if unable to create the
+ // directory for any reason, including if the parent directory does not
+ // exist. Not named "CreateDirectory" because that's a macro on Windows.
+ bool CreateFolder() const;
+
+ // Returns true if FilePath describes something in the file-system,
+ // either a file, directory, or whatever, and that something exists.
+ bool FileOrDirectoryExists() const;
+
+ // Returns true if pathname describes a directory in the file-system
+ // that exists.
+ bool DirectoryExists() const;
+
+ // Returns true if FilePath ends with a path separator, which indicates that
+ // it is intended to represent a directory. Returns false otherwise.
+ // This does NOT check that a directory (or file) actually exists.
+ bool IsDirectory() const;
+
+ // Returns true if pathname describes a root directory. (Windows has one
+ // root directory per disk drive.)
+ bool IsRootDirectory() const;
+
+ // Returns true if pathname describes an absolute path.
+ bool IsAbsolutePath() const;
+
+ private:
+ // Replaces multiple consecutive separators with a single separator.
+ // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+ // redundancies that might be in a pathname involving "." or "..".
+ //
+ // A pathname with multiple consecutive separators may occur either through
+ // user error or as a result of some scripts or APIs that generate a pathname
+ // with a trailing separator. On other platforms the same API or script
+ // may NOT generate a pathname with a trailing "/". Then elsewhere that
+ // pathname may have another "/" and pathname components added to it,
+ // without checking for the separator already being there.
+ // The script language and operating system may allow paths like "foo//bar"
+ // but some of the functions in FilePath will not handle that correctly. In
+ // particular, RemoveTrailingPathSeparator() only removes one separator, and
+ // it is called in CreateDirectoriesRecursively() assuming that it will change
+ // a pathname from directory syntax (trailing separator) to filename syntax.
+ //
+ // On Windows this method also replaces the alternate path separator '/' with
+ // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
+ // "bar\\foo".
+
+ void Normalize();
+
+ // Returns a pointer to the last occurence of a valid path separator in
+ // the FilePath. On Windows, for example, both '/' and '\' are valid path
+ // separators. Returns NULL if no path separator was found.
+ const char* FindLastPathSeparator() const;
+
+ String pathname_;
+}; // class FilePath
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h
new file mode 100644
index 0000000..855b215
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h
@@ -0,0 +1,1074 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility functions and classes used by the Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// This file contains purely Google Test's internal implementation. Please
+// DO NOT #INCLUDE IT IN A USER PROGRAM.
+
+#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
+#define GTEST_SRC_GTEST_INTERNAL_INL_H_
+
+// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
+// 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."
+#endif // GTEST_IMPLEMENTATION_
+
+#ifndef _WIN32_WCE
+#include <errno.h>
+#endif // !_WIN32_WCE
+#include <stddef.h>
+#include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
+#include <string.h> // For memmove.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include <gtest/internal/gtest-port.h>
+
+#if GTEST_OS_WINDOWS
+#include <windows.h> // For DWORD.
+#endif // GTEST_OS_WINDOWS
+
+#include <gtest/gtest.h> // NOLINT
+#include <gtest/gtest-spi.h>
+
+namespace testing {
+
+// Declares the flags.
+//
+// We don't want the users to modify this flag in the code, but want
+// Google Test's own unit tests to be able to access it. Therefore we
+// declare it here as opposed to in gtest.h.
+GTEST_DECLARE_bool_(death_test_use_fork);
+
+namespace internal {
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library. This is solely for testing GetTestTypeId().
+GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
+const char kBreakOnFailureFlag[] = "break_on_failure";
+const char kCatchExceptionsFlag[] = "catch_exceptions";
+const char kColorFlag[] = "color";
+const char kFilterFlag[] = "filter";
+const char kListTestsFlag[] = "list_tests";
+const char kOutputFlag[] = "output";
+const char kPrintTimeFlag[] = "print_time";
+const char kRandomSeedFlag[] = "random_seed";
+const char kRepeatFlag[] = "repeat";
+const char kShuffleFlag[] = "shuffle";
+const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kThrowOnFailureFlag[] = "throw_on_failure";
+
+// A valid random seed must be in [1, kMaxRandomSeed].
+const int kMaxRandomSeed = 99999;
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+GTEST_API_ extern bool g_help_flag;
+
+// Returns the current time in milliseconds.
+GTEST_API_ TimeInMillis GetTimeInMillis();
+
+// Returns true iff Google Test should use colors in the output.
+GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
+
+// Formats the given time in milliseconds as seconds.
+GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+
+// Parses a string for an Int32 flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true. On failure, returns false without changing *value.
+GTEST_API_ bool ParseInt32Flag(
+ const char* str, const char* flag, Int32* value);
+
+// Returns a random seed in range [1, kMaxRandomSeed] based on the
+// given --gtest_random_seed flag value.
+inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
+ const unsigned int raw_seed = (random_seed_flag == 0) ?
+ static_cast<unsigned int>(GetTimeInMillis()) :
+ static_cast<unsigned int>(random_seed_flag);
+
+ // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
+ // it's easy to type.
+ const int normalized_seed =
+ static_cast<int>((raw_seed - 1U) %
+ static_cast<unsigned int>(kMaxRandomSeed)) + 1;
+ return normalized_seed;
+}
+
+// Returns the first valid random seed after 'seed'. The behavior is
+// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is
+// considered to be 1.
+inline int GetNextRandomSeed(int seed) {
+ GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
+ << "Invalid random seed " << seed << " - must be in [1, "
+ << kMaxRandomSeed << "].";
+ const int next_seed = seed + 1;
+ return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
+}
+
+// This class saves the values of all Google Test flags in its c'tor, and
+// restores them in its d'tor.
+class GTestFlagSaver {
+ public:
+ // The c'tor.
+ GTestFlagSaver() {
+ also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
+ break_on_failure_ = GTEST_FLAG(break_on_failure);
+ catch_exceptions_ = GTEST_FLAG(catch_exceptions);
+ color_ = GTEST_FLAG(color);
+ death_test_style_ = GTEST_FLAG(death_test_style);
+ death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
+ filter_ = GTEST_FLAG(filter);
+ internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
+ list_tests_ = GTEST_FLAG(list_tests);
+ output_ = GTEST_FLAG(output);
+ print_time_ = GTEST_FLAG(print_time);
+ random_seed_ = GTEST_FLAG(random_seed);
+ repeat_ = GTEST_FLAG(repeat);
+ shuffle_ = GTEST_FLAG(shuffle);
+ stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+ throw_on_failure_ = GTEST_FLAG(throw_on_failure);
+ }
+
+ // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS.
+ ~GTestFlagSaver() {
+ GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
+ GTEST_FLAG(break_on_failure) = break_on_failure_;
+ GTEST_FLAG(catch_exceptions) = catch_exceptions_;
+ GTEST_FLAG(color) = color_;
+ GTEST_FLAG(death_test_style) = death_test_style_;
+ GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
+ GTEST_FLAG(filter) = filter_;
+ GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
+ GTEST_FLAG(list_tests) = list_tests_;
+ GTEST_FLAG(output) = output_;
+ GTEST_FLAG(print_time) = print_time_;
+ GTEST_FLAG(random_seed) = random_seed_;
+ GTEST_FLAG(repeat) = repeat_;
+ GTEST_FLAG(shuffle) = shuffle_;
+ GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+ GTEST_FLAG(throw_on_failure) = throw_on_failure_;
+ }
+ private:
+ // Fields for saving the original values of flags.
+ bool also_run_disabled_tests_;
+ bool break_on_failure_;
+ bool catch_exceptions_;
+ String color_;
+ String death_test_style_;
+ bool death_test_use_fork_;
+ String filter_;
+ String internal_run_death_test_;
+ bool list_tests_;
+ String output_;
+ bool print_time_;
+ bool pretty_;
+ internal::Int32 random_seed_;
+ internal::Int32 repeat_;
+ bool shuffle_;
+ internal::Int32 stack_trace_depth_;
+ bool throw_on_failure_;
+} GTEST_ATTRIBUTE_UNUSED_;
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// The output buffer str must containt at least 32 characters.
+// The function returns the address of the output buffer.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'.
+GTEST_API_ char* CodePointToUtf8(UInt32 code_point, char* str);
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+// UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+GTEST_API_ String WideStringToUtf8(const wchar_t* str, int num_chars);
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded();
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (e.g., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+GTEST_API_ bool ShouldShard(const char* total_shards_str,
+ const char* shard_index_str,
+ bool in_subprocess_for_death_test);
+
+// 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
+// and aborts.
+GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+GTEST_API_ bool ShouldRunTestOnShard(
+ int total_shards, int shard_index, int test_id);
+
+// STL container utilities.
+
+// Returns the number of elements in the given container that satisfy
+// 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));
+}
+
+// Applies a function/functor to each element in the container.
+template <class Container, typename Functor>
+void ForEach(const Container& c, Functor functor) {
+ std::for_each(c.begin(), c.end(), functor);
+}
+
+// Returns the i-th element of the vector, or default_value if i is not
+// in range [0, v.size()).
+template <typename E>
+inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
+ return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
+}
+
+// Performs an in-place shuffle of a range of the vector's elements.
+// 'begin' and 'end' are element indices as an STL-style range;
+// i.e. [begin, end) are shuffled, where 'end' == size() means to
+// shuffle to the end of the vector.
+template <typename E>
+void ShuffleRange(internal::Random* random, int begin, int end,
+ std::vector<E>* v) {
+ const int size = static_cast<int>(v->size());
+ GTEST_CHECK_(0 <= begin && begin <= size)
+ << "Invalid shuffle range start " << begin << ": must be in range [0, "
+ << size << "].";
+ GTEST_CHECK_(begin <= end && end <= size)
+ << "Invalid shuffle range finish " << end << ": must be in range ["
+ << begin << ", " << size << "].";
+
+ // Fisher-Yates shuffle, from
+ // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+ for (int range_width = end - begin; range_width >= 2; range_width--) {
+ const int last_in_range = begin + range_width - 1;
+ const int selected = begin + random->Generate(range_width);
+ std::swap((*v)[selected], (*v)[last_in_range]);
+ }
+}
+
+// Performs an in-place shuffle of the vector's elements.
+template <typename E>
+inline void Shuffle(internal::Random* random, std::vector<E>* v) {
+ ShuffleRange(random, 0, static_cast<int>(v->size()), v);
+}
+
+// A function for deleting an object. Handy for being used as a
+// functor.
+template <typename T>
+static void Delete(T* x) {
+ delete x;
+}
+
+// A predicate that checks the key of a TestProperty against a known key.
+//
+// TestPropertyKeyIs is copyable.
+class TestPropertyKeyIs {
+ public:
+ // Constructor.
+ //
+ // TestPropertyKeyIs has NO default constructor.
+ explicit TestPropertyKeyIs(const char* key)
+ : key_(key) {}
+
+ // Returns true iff the test name of test property matches on key_.
+ bool operator()(const TestProperty& test_property) const {
+ return String(test_property.key()).Compare(key_) == 0;
+ }
+
+ private:
+ 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
+// specifies when running the tests. It has only static members.
+//
+// In most cases, the user can specify an option using either an
+// environment variable or a command line flag. E.g. you can set the
+// test filter using either GTEST_FILTER or --gtest_filter. If both
+// the variable and the flag are present, the latter overrides the
+// former.
+class GTEST_API_ UnitTestOptions {
+ public:
+ // Functions for processing the gtest_output flag.
+
+ // Returns the output format, or "" for normal printed output.
+ static String GetOutputFormat();
+
+ // Returns the absolute path of the requested output file, or the
+ // default (test_detail.xml in the original working directory) if
+ // none was explicitly specified.
+ static String GetAbsolutePathToOutputFile();
+
+ // Functions for processing the gtest_filter flag.
+
+ // Returns true iff the wildcard pattern matches the string. The
+ // first ':' or '\0' character in pattern marks the end of it.
+ //
+ // This recursive algorithm isn't very efficient, but is clear and
+ // works well enough for matching test names, which are short.
+ static bool PatternMatchesString(const char *pattern, const char *str);
+
+ // Returns true iff the user-specified filter matches the test case
+ // name and the test name.
+ static bool FilterMatchesTest(const String &test_case_name,
+ const String &test_name);
+
+#if GTEST_OS_WINDOWS
+ // Function for supporting the gtest_catch_exception flag.
+
+ // 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.
+ static int GTestShouldProcessSEH(DWORD exception_code);
+#endif // GTEST_OS_WINDOWS
+
+ // Returns true if "name" matches the ':' separated list of glob-style
+ // filters in "filter".
+ static bool MatchesFilter(const String& name, const char* filter);
+};
+
+// Returns the current application's name, removing directory path if that
+// is present. Used by UnitTestOptions::GetOutputFile.
+GTEST_API_ FilePath GetCurrentExecutableName();
+
+// The role interface for getting the OS stack trace as a string.
+class OsStackTraceGetterInterface {
+ public:
+ OsStackTraceGetterInterface() {}
+ virtual ~OsStackTraceGetterInterface() {}
+
+ // Returns the current OS stack trace as a String. Parameters:
+ //
+ // max_depth - the maximum number of stack frames to be included
+ // in the trace.
+ // skip_count - the number of top frames to be skipped; doesn't count
+ // against max_depth.
+ virtual String CurrentStackTrace(int max_depth, int skip_count) = 0;
+
+ // UponLeavingGTest() should be called immediately before Google Test calls
+ // user code. It saves some information about the current stack that
+ // CurrentStackTrace() will use to find and hide Google Test stack frames.
+ virtual void UponLeavingGTest() = 0;
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
+};
+
+// A working implementation of the OsStackTraceGetterInterface interface.
+class OsStackTraceGetter : public OsStackTraceGetterInterface {
+ public:
+ OsStackTraceGetter() : caller_frame_(NULL) {}
+ virtual String CurrentStackTrace(int max_depth, int skip_count);
+ virtual void UponLeavingGTest();
+
+ // This string is inserted in place of stack frames that are part of
+ // Google Test's implementation.
+ static const char* const kElidedFramesMarker;
+
+ private:
+ Mutex mutex_; // protects all internal state
+
+ // We save the stack frame below the frame that calls user code.
+ // We do this because the address of the frame immediately below
+ // the user code changes between the call to UponLeavingGTest()
+ // and any calls to CurrentStackTrace() from within the user code.
+ void* caller_frame_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
+};
+
+// Information about a Google Test trace point.
+struct TraceInfo {
+ const char* file;
+ int line;
+ String message;
+};
+
+// This is the default global test part result reporter used in UnitTestImpl.
+// This class should only be used by UnitTestImpl.
+class DefaultGlobalTestPartResultReporter
+ : public TestPartResultReporterInterface {
+ public:
+ explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
+ // Implements the TestPartResultReporterInterface. Reports the test part
+ // result in the current test.
+ virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+ UnitTestImpl* const unit_test_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
+};
+
+// This is the default per thread test part result reporter used in
+// UnitTestImpl. This class should only be used by UnitTestImpl.
+class DefaultPerThreadTestPartResultReporter
+ : public TestPartResultReporterInterface {
+ public:
+ explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
+ // Implements the TestPartResultReporterInterface. The implementation just
+ // delegates to the current global test part result reporter of *unit_test_.
+ virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+ UnitTestImpl* const unit_test_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
+};
+
+// The private implementation of the UnitTest class. We don't protect
+// the methods under a mutex, as this class is not accessible by a
+// user and the UnitTest class that delegates work to this class does
+// proper locking.
+class GTEST_API_ UnitTestImpl {
+ public:
+ explicit UnitTestImpl(UnitTest* parent);
+ virtual ~UnitTestImpl();
+
+ // There are two different ways to register your own TestPartResultReporter.
+ // You can register your own repoter to listen either only for test results
+ // from the current thread or for results from all threads.
+ // By default, each per-thread test result repoter just passes a new
+ // TestPartResult to the global test result reporter, which registers the
+ // test part result for the currently running test.
+
+ // Returns the global test part result reporter.
+ TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
+
+ // Sets the global test part result reporter.
+ void SetGlobalTestPartResultReporter(
+ TestPartResultReporterInterface* reporter);
+
+ // Returns the test part result reporter for the current thread.
+ TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
+
+ // Sets the test part result reporter for the current thread.
+ void SetTestPartResultReporterForCurrentThread(
+ TestPartResultReporterInterface* reporter);
+
+ // Gets the number of successful test cases.
+ int successful_test_case_count() const;
+
+ // Gets the number of failed test cases.
+ int failed_test_case_count() const;
+
+ // Gets the number of all test cases.
+ int total_test_case_count() const;
+
+ // Gets the number of all test cases that contain at least one test
+ // that should run.
+ int test_case_to_run_count() const;
+
+ // Gets the number of successful tests.
+ int successful_test_count() const;
+
+ // Gets the number of failed tests.
+ int failed_test_count() const;
+
+ // Gets the number of disabled tests.
+ int disabled_test_count() const;
+
+ // Gets the number of all tests.
+ int total_test_count() const;
+
+ // Gets the number of tests that should run.
+ int test_to_run_count() const;
+
+ // Gets the elapsed time, in milliseconds.
+ TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+ // Returns true iff the unit test passed (i.e. all test cases passed).
+ bool Passed() const { return !Failed(); }
+
+ // Returns true iff the unit test failed (i.e. some test case failed
+ // or something outside of all tests failed).
+ bool Failed() const {
+ return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed();
+ }
+
+ // Gets the i-th test case among all the test cases. i can range from 0 to
+ // total_test_case_count() - 1. If i is not in that range, returns NULL.
+ const TestCase* GetTestCase(int i) const {
+ const int index = GetElementOr(test_case_indices_, i, -1);
+ return index < 0 ? NULL : test_cases_[i];
+ }
+
+ // Gets the i-th test case among all the test cases. i can range from 0 to
+ // total_test_case_count() - 1. If i is not in that range, returns NULL.
+ TestCase* GetMutableTestCase(int i) {
+ const int index = GetElementOr(test_case_indices_, i, -1);
+ return index < 0 ? NULL : test_cases_[index];
+ }
+
+ // Provides access to the event listener list.
+ TestEventListeners* listeners() { return &listeners_; }
+
+ // Returns the TestResult for the test that's currently running, or
+ // the TestResult for the ad hoc test if no test is running.
+ TestResult* current_test_result();
+
+ // Returns the TestResult for the ad hoc test.
+ const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
+
+ // Sets the OS stack trace getter.
+ //
+ // Does nothing if the input and the current OS stack trace getter
+ // are the same; otherwise, deletes the old getter and makes the
+ // input the current getter.
+ void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
+
+ // Returns the current OS stack trace getter if it is not NULL;
+ // otherwise, creates an OsStackTraceGetter, makes it the current
+ // getter, and returns it.
+ OsStackTraceGetterInterface* os_stack_trace_getter();
+
+ // Returns the current OS stack trace as a String.
+ //
+ // The maximum number of stack frames to be included is specified by
+ // the gtest_stack_trace_depth flag. The skip_count parameter
+ // specifies the number of top frames to be skipped, which doesn't
+ // count against the number of frames to be included.
+ //
+ // For example, if Foo() calls Bar(), which in turn calls
+ // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+ // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+ String CurrentOsStackTraceExceptTop(int skip_count);
+
+ // Finds and returns a TestCase with the given name. If one doesn't
+ // exist, creates one and returns it.
+ //
+ // Arguments:
+ //
+ // test_case_name: name of the 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* GetTestCase(const char* test_case_name,
+ const char* comment,
+ Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc);
+
+ // Adds a TestInfo to the unit test.
+ //
+ // Arguments:
+ //
+ // 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
+ // test_info: the TestInfo object
+ void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc,
+ 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
+ // the user may have changed the current directory before calling
+ // RUN_ALL_TESTS(). Therefore we capture the current directory in
+ // AddTestInfo(), which is called to register a TEST or TEST_F
+ // before main() is reached.
+ if (original_working_dir_.IsEmpty()) {
+ original_working_dir_.Set(FilePath::GetCurrentDir());
+ GTEST_CHECK_(!original_working_dir_.IsEmpty())
+ << "Failed to get the current working directory.";
+ }
+
+ GetTestCase(test_info->test_case_name(),
+ test_info->test_case_comment(),
+ set_up_tc,
+ tear_down_tc)->AddTestInfo(test_info);
+ }
+
+#if GTEST_HAS_PARAM_TEST
+ // Returns ParameterizedTestCaseRegistry object used to keep track of
+ // value-parameterized tests and instantiate and register them.
+ internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
+ return parameterized_test_registry_;
+ }
+#endif // GTEST_HAS_PARAM_TEST
+
+ // Sets the TestCase object for the test that's currently running.
+ void set_current_test_case(TestCase* a_current_test_case) {
+ current_test_case_ = a_current_test_case;
+ }
+
+ // Sets the TestInfo object for the test that's currently running. If
+ // current_test_info is NULL, the assertion results will be stored in
+ // ad_hoc_test_result_.
+ void set_current_test_info(TestInfo* a_current_test_info) {
+ current_test_info_ = a_current_test_info;
+ }
+
+ // 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.
+ 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();
+
+ // Clears the results of all tests, including the ad hoc test.
+ void ClearResult() {
+ ForEach(test_cases_, TestCase::ClearTestCaseResult);
+ ad_hoc_test_result_.Clear();
+ }
+
+ enum ReactionToSharding {
+ HONOR_SHARDING_PROTOCOL,
+ IGNORE_SHARDING_PROTOCOL
+ };
+
+ // Matches the full name of each test against the user-specified
+ // filter to decide whether the test should run, then records the
+ // result in each TestCase and TestInfo object.
+ // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
+ // based on sharding variables in the environment.
+ // Returns the number of tests that should run.
+ int FilterTests(ReactionToSharding shard_tests);
+
+ // Prints the names of the tests matching the user-specified filter flag.
+ void ListTestsMatchingFilter();
+
+ const TestCase* current_test_case() const { return current_test_case_; }
+ TestInfo* current_test_info() { return current_test_info_; }
+ const TestInfo* current_test_info() const { return current_test_info_; }
+
+ // Returns the vector of environments that need to be set-up/torn-down
+ // before/after the tests are run.
+ std::vector<Environment*>& environments() { return environments_; }
+
+ // Getters for the per-thread Google Test trace stack.
+ std::vector<TraceInfo>& gtest_trace_stack() {
+ return *(gtest_trace_stack_.pointer());
+ }
+ const std::vector<TraceInfo>& gtest_trace_stack() const {
+ return gtest_trace_stack_.get();
+ }
+
+#if GTEST_HAS_DEATH_TEST
+ void InitDeathTestSubprocessControlInfo() {
+ internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+ }
+ // Returns a pointer to the parsed --gtest_internal_run_death_test
+ // flag, or NULL if that flag was not specified.
+ // This information is useful only in a death test child process.
+ // Must not be called before a call to InitGoogleTest.
+ const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
+ return internal_run_death_test_flag_.get();
+ }
+
+ // Returns a pointer to the current death test factory.
+ internal::DeathTestFactory* death_test_factory() {
+ return death_test_factory_.get();
+ }
+
+ void SuppressTestEventsIfInSubprocess();
+
+ friend class ReplaceDeathTestFactory;
+#endif // GTEST_HAS_DEATH_TEST
+
+ // Initializes the event listener performing XML output as specified by
+ // UnitTestOptions. Must not be called before InitGoogleTest.
+ void ConfigureXmlOutput();
+
+ // 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
+ // this function is also called from RunAllTests. Since this function can be
+ // called more than once, it has to be idempotent.
+ void PostFlagParsingInit();
+
+ // Gets the random seed used at the start of the current test iteration.
+ int random_seed() const { return random_seed_; }
+
+ // Gets the random number generator.
+ internal::Random* random() { return &random_; }
+
+ // Shuffles all test cases, and the tests within each test case,
+ // making sure that death tests are still run first.
+ void ShuffleTests();
+
+ // Restores the test cases and tests to their order before the first shuffle.
+ void UnshuffleTests();
+
+ private:
+ friend class ::testing::UnitTest;
+
+ // The UnitTest object that owns this implementation object.
+ UnitTest* const parent_;
+
+ // The working directory when the first TEST() or TEST_F() was
+ // executed.
+ internal::FilePath original_working_dir_;
+
+ // The default test part result reporters.
+ DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
+ DefaultPerThreadTestPartResultReporter
+ default_per_thread_test_part_result_reporter_;
+
+ // Points to (but doesn't own) the global test part result reporter.
+ TestPartResultReporterInterface* global_test_part_result_repoter_;
+
+ // Protects read and write access to global_test_part_result_reporter_.
+ internal::Mutex global_test_part_result_reporter_mutex_;
+
+ // Points to (but doesn't own) the per-thread test part result reporter.
+ internal::ThreadLocal<TestPartResultReporterInterface*>
+ per_thread_test_part_result_reporter_;
+
+ // The vector of environments that need to be set-up/torn-down
+ // before/after the tests are run.
+ std::vector<Environment*> environments_;
+
+ // The vector of TestCases in their original order. It owns the
+ // elements in the vector.
+ std::vector<TestCase*> test_cases_;
+
+ // Provides a level of indirection for the test case list to allow
+ // easy shuffling and restoring the test case order. The i-th
+ // element of this vector is the index of the i-th test case in the
+ // shuffled order.
+ std::vector<int> test_case_indices_;
+
+#if GTEST_HAS_PARAM_TEST
+ // ParameterizedTestRegistry object used to register value-parameterized
+ // tests.
+ internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
+
+ // Indicates whether RegisterParameterizedTests() has been called already.
+ bool parameterized_tests_registered_;
+#endif // GTEST_HAS_PARAM_TEST
+
+ // Index of the last death test case registered. Initially -1.
+ int last_death_test_case_;
+
+ // This points to the TestCase for the currently running test. It
+ // changes as Google Test goes through one test case after another.
+ // When no test is running, this is set to NULL and Google Test
+ // stores assertion results in ad_hoc_test_result_. Initially NULL.
+ TestCase* current_test_case_;
+
+ // This points to the TestInfo for the currently running test. It
+ // changes as Google Test goes through one test after another. When
+ // no test is running, this is set to NULL and Google Test stores
+ // assertion results in ad_hoc_test_result_. Initially NULL.
+ TestInfo* current_test_info_;
+
+ // Normally, a user only writes assertions inside a TEST or TEST_F,
+ // or inside a function called by a TEST or TEST_F. Since Google
+ // Test keeps track of which test is current running, it can
+ // associate such an assertion with the test it belongs to.
+ //
+ // If an assertion is encountered when no TEST or TEST_F is running,
+ // Google Test attributes the assertion result to an imaginary "ad hoc"
+ // test, and records the result in ad_hoc_test_result_.
+ TestResult ad_hoc_test_result_;
+
+ // The list of event listeners that can be used to track events inside
+ // Google Test.
+ TestEventListeners listeners_;
+
+ // The OS stack trace getter. Will be deleted when the UnitTest
+ // object is destructed. By default, an OsStackTraceGetter is used,
+ // but the user can set this field to use a custom getter if that is
+ // desired.
+ OsStackTraceGetterInterface* os_stack_trace_getter_;
+
+ // True iff PostFlagParsingInit() has been called.
+ bool post_flag_parse_init_performed_;
+
+ // The random number seed used at the beginning of the test run.
+ int random_seed_;
+
+ // Our random number generator.
+ internal::Random random_;
+
+ // How long the test took to run, in milliseconds.
+ TimeInMillis elapsed_time_;
+
+#if GTEST_HAS_DEATH_TEST
+ // The decomposed components of the gtest_internal_run_death_test flag,
+ // parsed when RUN_ALL_TESTS is called.
+ internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
+ internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
+#endif // GTEST_HAS_DEATH_TEST
+
+ // A per-thread stack of traces created by the SCOPED_TRACE() macro.
+ internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
+}; // class UnitTestImpl
+
+// Convenience function for accessing the global UnitTest
+// implementation object.
+inline UnitTestImpl* GetUnitTestImpl() {
+ return UnitTest::GetInstance()->impl();
+}
+
+// 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 IsRepeat(char ch);
+GTEST_API_ bool IsWhiteSpace(char ch);
+GTEST_API_ bool IsWordChar(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);
+GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
+GTEST_API_ bool MatchRepetitionAndRegexAtHead(
+ bool escaped, char ch, char repeat, const char* regex, const char* str);
+GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+
+#if GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+String GetLastErrnoDescription();
+
+#if GTEST_OS_WINDOWS
+// Provides leak-safe Windows kernel handle ownership.
+class AutoHandle {
+ public:
+ AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
+ explicit AutoHandle(HANDLE handle) : handle_(handle) {}
+
+ ~AutoHandle() { Reset(); }
+
+ HANDLE Get() const { return handle_; }
+ void Reset() { Reset(INVALID_HANDLE_VALUE); }
+ void Reset(HANDLE handle) {
+ if (handle != handle_) {
+ if (handle_ != INVALID_HANDLE_VALUE)
+ ::CloseHandle(handle_);
+ handle_ = handle;
+ }
+ }
+
+ private:
+ HANDLE handle_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
+};
+#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.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+ // 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])) {
+ return false;
+ }
+ errno = 0;
+
+ char* end;
+ // BiggestConvertible is the largest integer type that system-provided
+ // string-to-number conversion routines can return.
+#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
+ typedef unsigned long long BiggestConvertible; // NOLINT
+ const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
+#endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
+ const bool parse_success = *end == '\0' && errno == 0;
+
+ // TODO(vladl@google.com): Convert this to compile time assertion when it is
+ // available.
+ GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+ const Integer result = static_cast<Integer>(parsed);
+ if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+ *number = result;
+ return true;
+ }
+ return false;
+}
+#endif // GTEST_HAS_DEATH_TEST
+
+// TestResult contains some private methods that should be hidden from
+// Google Test user but are required for testing. This class allow our tests
+// to access them.
+//
+// This class is supplied only for the purpose of testing Google Test's own
+// constructs. Do not use it in user tests, either directly or indirectly.
+class TestResultAccessor {
+ public:
+ static void RecordProperty(TestResult* test_result,
+ const TestProperty& property) {
+ test_result->RecordProperty(property);
+ }
+
+ static void ClearTestPartResults(TestResult* test_result) {
+ test_result->ClearTestPartResults();
+ }
+
+ static const std::vector<testing::TestPartResult>& test_part_results(
+ const TestResult& test_result) {
+ return test_result.test_part_results();
+ }
+};
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-internal.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
new file mode 100644
index 0000000..0b90132
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
@@ -0,0 +1,943 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test. They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_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>
+#endif // GTEST_OS_LINUX
+
+#include <ctype.h>
+#include <string.h>
+#include <iomanip>
+#include <limits>
+#include <set>
+
+#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"
+
+// Due to C++ preprocessor weirdness, we need double indirection to
+// concatenate two tokens when one of them is __LINE__. Writing
+//
+// foo ## __LINE__
+//
+// will result in the token foo__LINE__, instead of foo followed by
+// the current line number. For more details, see
+// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
+#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
+#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
+
+// Google Test defines the testing::Message class to allow construction of
+// test messages via the << operator. The idea is that anything
+// streamable to std::ostream can be streamed to a testing::Message.
+// This allows a user to use his own types in Google Test assertions by
+// overloading the << operator.
+//
+// util/gtl/stl_logging-inl.h overloads << for STL containers. These
+// overloads cannot be defined in the std namespace, as that will be
+// undefined behavior. Therefore, they are defined in the global
+// namespace instead.
+//
+// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+// overloads are visible in either the std namespace or the global
+// namespace, but not other namespaces, including the testing
+// namespace which Google Test's Message class is in.
+//
+// To allow STL containers (and other types that has a << operator
+// defined in the global namespace) to be used in Google Test assertions,
+// testing::Message must access the custom << operator from the global
+// namespace. Hence this helper function.
+//
+// Note: Jeffrey Yasskin suggested an alternative fix by "using
+// ::operator<<;" in the definition of Message's operator<<. That fix
+// doesn't require a helper function, but unfortunately doesn't
+// compile with MSVC.
+
+// LLVM INTERNAL CHANGE: To allow operator<< to work with both
+// std::ostreams and LLVM's raw_ostreams, we define a special
+// std::ostream with an implicit conversion to raw_ostream& and stream
+// to that. This causes the compiler to prefer std::ostream overloads
+// but still find raw_ostream& overloads.
+namespace llvm {
+class convertible_fwd_ostream : public std::ostream {
+ std::ostream& os_;
+ raw_os_ostream ros_;
+
+public:
+ convertible_fwd_ostream(std::ostream& os)
+ : std::ostream(os.rdbuf()), os_(os), ros_(*this) {}
+ operator raw_ostream&() { return ros_; }
+};
+}
+template <typename T>
+inline void GTestStreamToHelper(std::ostream* os, const T& val) {
+ llvm::convertible_fwd_ostream cos(*os);
+ cos << val;
+}
+
+namespace testing {
+
+// Forward declaration of classes.
+
+class AssertionResult; // Result of an assertion.
+class Message; // Represents a failure message.
+class Test; // Represents a test.
+class TestInfo; // Information about a test.
+class TestPartResult; // Result of a test part.
+class UnitTest; // A collection of test cases.
+
+namespace internal {
+
+struct TraceInfo; // Information about a trace point.
+class ScopedTrace; // Implements scoped trace.
+class TestInfoImpl; // Opaque implementation of TestInfo
+class UnitTestImpl; // Opaque implementation of UnitTest
+
+// How many times InitGoogleTest() has been called.
+extern int g_init_gtest_count;
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+GTEST_API_ extern const char kStackTraceMarker[];
+
+// A secret type that Google Test users don't know about. It has no
+// definition on purpose. Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret;
+
+// Two overloaded helpers for checking at compile time whether an
+// expression is a null pointer literal (i.e. NULL or any 0-valued
+// compile-time integral constant). Their return values have
+// different sizes, so we can use sizeof() to test which version is
+// picked by the compiler. These helpers have no implementations, as
+// we only need their signatures.
+//
+// Given IsNullLiteralHelper(x), the compiler will pick the first
+// version if x can be implicitly converted to Secret*, and pick the
+// second version otherwise. Since Secret is a secret and incomplete
+// type, the only expression a user can write that has type Secret* is
+// a null pointer literal. Therefore, we know that x is a null
+// pointer literal if and only if the first version is picked by the
+// compiler.
+char IsNullLiteralHelper(Secret* p);
+char (&IsNullLiteralHelper(...))[2]; // NOLINT
+
+// A compile-time bool constant that is true if and only if x is a
+// null pointer literal (i.e. NULL or any 0-valued compile-time
+// integral constant).
+#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
+#else
+#define GTEST_IS_NULL_LITERAL_(x) \
+ (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
+#endif // GTEST_ELLIPSIS_NEEDS_POD_
+
+// Appends the user-supplied message to the Google-Test-generated message.
+GTEST_API_ String AppendUserMessage(const String& gtest_msg,
+ const Message& user_msg);
+
+// A helper class for creating scoped traces in user programs.
+class GTEST_API_ ScopedTrace {
+ public:
+ // The c'tor pushes the given source file location and message onto
+ // a trace stack maintained by Google Test.
+ ScopedTrace(const char* file, int line, const Message& message);
+
+ // The d'tor pops the info pushed by the c'tor.
+ //
+ // Note that the d'tor is not virtual in order to be efficient.
+ // Don't inherit from ScopedTrace!
+ ~ScopedTrace();
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
+} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its
+ // c'tor and d'tor. Therefore it doesn't
+ // need to be used otherwise.
+
+// Converts a streamable value to a String. A NULL pointer is
+// converted to "(null)". When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+// Declared here but defined in gtest.h, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+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);
+}
+
+#else
+
+// 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
+// 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.
+
+// 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*/) {\
+ return operand1_printer(str);\
+}\
+inline String FormatForComparisonFailureMessage(\
+ const operand2_type::value_type* str, const operand2_type& /*operand2*/) {\
+ return operand1_printer(str);\
+}
+
+GTEST_FORMAT_IMPL_(::std::string, String::ShowCStringQuoted)
+#if GTEST_HAS_STD_WSTRING
+GTEST_FORMAT_IMPL_(::std::wstring, String::ShowWideCStringQuoted)
+#endif // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_FORMAT_IMPL_(::string, String::ShowCStringQuoted)
+#endif // GTEST_HAS_GLOBAL_STRING
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted)
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+#undef GTEST_FORMAT_IMPL_
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings. For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+// expected_expression: "foo"
+// actual_expression: "bar"
+// expected_value: "5"
+// actual_value: "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
+ const char* actual_expression,
+ const String& expected_value,
+ const String& actual_value,
+ bool ignoring_case);
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+GTEST_API_ String GetBoolAssertionFailureMessage(
+ const AssertionResult& assertion_result,
+ const char* expression_text,
+ const char* actual_predicate_value,
+ const char* expected_predicate_value);
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison. (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly. Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+// The most-significant bit being the leftmost, an IEEE
+// floating-point looks like
+//
+// sign_bit exponent_bits fraction_bits
+//
+// Here, sign_bit is a single bit that designates the sign of the
+// number.
+//
+// For float, there are 8 exponent bits and 23 fraction bits.
+//
+// For double, there are 11 exponent bits and 52 fraction bits.
+//
+// More details can be found at
+// http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+// RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+ // Defines the unsigned integer type that has the same size as the
+ // floating point number.
+ typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+ // Constants.
+
+ // # of bits in a number.
+ static const size_t kBitCount = 8*sizeof(RawType);
+
+ // # of fraction bits in a number.
+ static const size_t kFractionBitCount =
+ std::numeric_limits<RawType>::digits - 1;
+
+ // # of exponent bits in a number.
+ static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+ // The mask for the sign bit.
+ static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+ // The mask for the fraction bits.
+ static const Bits kFractionBitMask =
+ ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+ // The mask for the exponent bits.
+ static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+ // How many ULP's (Units in the Last Place) we want to tolerate when
+ // comparing two numbers. The larger the value, the more error we
+ // allow. A 0 value means that two numbers must be exactly the same
+ // to be considered equal.
+ //
+ // The maximum error of a single floating-point operation is 0.5
+ // units in the last place. On Intel CPU's, all floating-point
+ // calculations are done with 80-bit precision, while double has 64
+ // bits. Therefore, 4 should be enough for ordinary use.
+ //
+ // See the following article for more details on ULP:
+ // http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm.
+ static const size_t kMaxUlps = 4;
+
+ // Constructs a FloatingPoint from a raw floating-point number.
+ //
+ // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+ // around may change its bits, although the new value is guaranteed
+ // to be also a NAN. Therefore, don't expect this constructor to
+ // preserve the bits in x when x is a NAN.
+ explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+ // Static methods
+
+ // Reinterprets a bit pattern as a floating-point number.
+ //
+ // This function is needed to test the AlmostEquals() method.
+ static RawType ReinterpretBits(const Bits bits) {
+ FloatingPoint fp(0);
+ fp.u_.bits_ = bits;
+ return fp.u_.value_;
+ }
+
+ // Returns the floating-point number that represent positive infinity.
+ static RawType Infinity() {
+ return ReinterpretBits(kExponentBitMask);
+ }
+
+ // Non-static methods
+
+ // Returns the bits that represents this number.
+ const Bits &bits() const { return u_.bits_; }
+
+ // Returns the exponent bits of this number.
+ Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+ // Returns the fraction bits of this number.
+ Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+ // Returns the sign bit of this number.
+ Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+ // Returns true iff this is NAN (not a number).
+ bool is_nan() const {
+ // It's a NAN if the exponent bits are all ones and the fraction
+ // bits are not entirely zeros.
+ return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+ }
+
+ // Returns true iff this number is at most kMaxUlps ULP's away from
+ // rhs. In particular, this function:
+ //
+ // - returns false if either number is (or both are) NAN.
+ // - treats really large numbers as almost equal to infinity.
+ // - thinks +0.0 and -0.0 are 0 DLP's apart.
+ bool AlmostEquals(const FloatingPoint& rhs) const {
+ // The IEEE standard says that any comparison operation involving
+ // a NAN must return false.
+ if (is_nan() || rhs.is_nan()) return false;
+
+ return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
+ <= kMaxUlps;
+ }
+
+ private:
+ // The data type used to store the actual floating-point number.
+ union FloatingPointUnion {
+ RawType value_; // The raw floating-point number.
+ Bits bits_; // The bits that represent the number.
+ };
+
+ // Converts an integer from the sign-and-magnitude representation to
+ // the biased representation. More precisely, let N be 2 to the
+ // power of (kBitCount - 1), an integer x is represented by the
+ // unsigned number x + N.
+ //
+ // For instance,
+ //
+ // -N + 1 (the most negative number representable using
+ // sign-and-magnitude) is represented by 1;
+ // 0 is represented by N; and
+ // N - 1 (the biggest number representable using
+ // sign-and-magnitude) is represented by 2N - 1.
+ //
+ // Read http://en.wikipedia.org/wiki/Signed_number_representations
+ // for more details on signed number representations.
+ static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+ if (kSignBitMask & sam) {
+ // sam represents a negative number.
+ return ~sam + 1;
+ } else {
+ // sam represents a positive number.
+ return kSignBitMask | sam;
+ }
+ }
+
+ // Given two numbers in the sign-and-magnitude representation,
+ // returns the distance between them as an unsigned number.
+ static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+ const Bits &sam2) {
+ const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+ const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+ return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+ }
+
+ FloatingPointUnion u_;
+};
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+// In order to catch the mistake of putting tests that use different
+// test fixture classes in the same test case, we need to assign
+// unique IDs to fixture classes and compare them. The TypeId type is
+// used to hold such IDs. The user should treat TypeId as an opaque
+// type: the only operation allowed on TypeId values is to compare
+// them for equality using the == operator.
+typedef const void* TypeId;
+
+template <typename T>
+class TypeIdHelper {
+ public:
+ // dummy_ must not have a const type. Otherwise an overly eager
+ // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
+ // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
+ static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
+
+// GetTypeId<T>() returns the ID of type T. Different values will be
+// returned for different types. Calling the function twice with the
+// same type argument is guaranteed to return the same ID.
+template <typename T>
+TypeId GetTypeId() {
+ // The compiler is required to allocate a different
+ // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
+ // the template. Therefore, the address of dummy_ is guaranteed to
+ // be unique.
+ return &(TypeIdHelper<T>::dummy_);
+}
+
+// Returns the type ID of ::testing::Test. Always call this instead
+// of GetTypeId< ::testing::Test>() to get the type ID of
+// ::testing::Test, as the latter may give the wrong result due to a
+// suspected linker bug when compiling Google Test as a Mac OS X
+// framework.
+GTEST_API_ TypeId GetTestTypeId();
+
+// Defines the abstract factory interface that creates instances
+// of a Test object.
+class TestFactoryBase {
+ public:
+ virtual ~TestFactoryBase() {}
+
+ // Creates a test instance to run. The instance is both created and destroyed
+ // within TestInfoImpl::Run()
+ virtual Test* CreateTest() = 0;
+
+ protected:
+ TestFactoryBase() {}
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
+};
+
+// This class provides implementation of TeastFactoryBase interface.
+// It is used in TEST and TEST_F macros.
+template <class TestClass>
+class TestFactoryImpl : public TestFactoryBase {
+ public:
+ virtual Test* CreateTest() { return new TestClass; }
+};
+
+#if GTEST_OS_WINDOWS
+
+// Predicate-formatters for implementing the HRESULT checking macros
+// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
+// We pass a long instead of HRESULT to avoid causing an
+// include dependency for the HRESULT type.
+GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
+ long hr); // NOLINT
+GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
+ long hr); // NOLINT
+
+#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)();
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+// 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
+// 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
+// factory: pointer to the factory that creates a test object.
+// The newly created TestInfo instance will assume
+// 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,
+ TypeId fixture_class_id,
+ SetUpTestCaseFunc set_up_tc,
+ TearDownTestCaseFunc tear_down_tc,
+ TestFactoryBase* factory);
+
+// 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);
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// State of the definition of a type-parameterized test case.
+class GTEST_API_ TypedTestCasePState {
+ public:
+ TypedTestCasePState() : registered_(false) {}
+
+ // Adds the given test name to defined_test_names_ and return true
+ // if the test case hasn't been registered; otherwise aborts the
+ // program.
+ bool AddTestName(const char* file, int line, const char* case_name,
+ const char* test_name) {
+ if (registered_) {
+ fprintf(stderr, "%s Test %s must be defined before "
+ "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
+ FormatFileLocation(file, line).c_str(), test_name, case_name);
+ fflush(stderr);
+ posix::Abort();
+ }
+ defined_test_names_.insert(test_name);
+ return true;
+ }
+
+ // Verifies that registered_tests match the test names in
+ // defined_test_names_; returns registered_tests if successful, or
+ // aborts the program otherwise.
+ const char* VerifyRegisteredTestNames(
+ const char* file, int line, const char* registered_tests);
+
+ private:
+ bool registered_;
+ ::std::set<const char*> defined_test_names_;
+};
+
+// Skips to the first non-space char after the first comma in 'str';
+// returns NULL if no comma is found in 'str'.
+inline const char* SkipComma(const char* str) {
+ const char* comma = strchr(str, ',');
+ if (comma == NULL) {
+ return NULL;
+ }
+ while (isspace(*(++comma))) {}
+ return comma;
+}
+
+// Returns the prefix of 'str' before the first comma in it; returns
+// the entire string if it contains no comma.
+inline String GetPrefixUntilComma(const char* str) {
+ const char* comma = strchr(str, ',');
+ return comma == NULL ? String(str) : String(str, comma - str);
+}
+
+// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
+// registers a list of type-parameterized tests with Google Test. The
+// return value is insignificant - we just need to return something
+// such that we can call this function in a namespace scope.
+//
+// Implementation note: The GTEST_TEMPLATE_ macro declares a template
+// template parameter. It's defined in gtest-type-util.h.
+template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
+class TypeParameterizedTest {
+ public:
+ // 'index' is the index of the test in the type list 'Types'
+ // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
+ // Types). Valid values for 'index' are [0, N - 1] where N is the
+ // length of Types.
+ static bool Register(const char* prefix, const char* case_name,
+ const char* test_names, int index) {
+ typedef typename Types::Head Type;
+ typedef Fixture<Type> FixtureClass;
+ typedef typename GTEST_BIND_(TestSel, Type) TestClass;
+
+ // First, registers the first type-parameterized test in the type
+ // list.
+ MakeAndRegisterTestInfo(
+ 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(),
+ "",
+ GetTypeId<FixtureClass>(),
+ TestClass::SetUpTestCase,
+ TestClass::TearDownTestCase,
+ new TestFactoryImpl<TestClass>);
+
+ // Next, recurses (at compile time) with the tail of the type list.
+ return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
+ ::Register(prefix, case_name, test_names, index + 1);
+ }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, class TestSel>
+class TypeParameterizedTest<Fixture, TestSel, Types0> {
+ public:
+ static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+ const char* /*test_names*/, int /*index*/) {
+ return true;
+ }
+};
+
+// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
+// registers *all combinations* of 'Tests' and 'Types' with Google
+// Test. The return value is insignificant - we just need to return
+// something such that we can call this function in a namespace scope.
+template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
+class TypeParameterizedTestCase {
+ public:
+ static bool Register(const char* prefix, const char* case_name,
+ const char* test_names) {
+ typedef typename Tests::Head Head;
+
+ // First, register the first test in 'Test' for each type in 'Types'.
+ TypeParameterizedTest<Fixture, Head, Types>::Register(
+ prefix, case_name, test_names, 0);
+
+ // Next, recurses (at compile time) with the tail of the test list.
+ return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
+ ::Register(prefix, case_name, SkipComma(test_names));
+ }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, typename Types>
+class TypeParameterizedTestCase<Fixture, Templates0, Types> {
+ public:
+ static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+ const char* /*test_names*/) {
+ return true;
+ }
+};
+
+#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag. The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_API_ String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test,
+ int skip_count);
+
+// Helpers for suppressing warnings on unreachable code or constant
+// condition.
+
+// Always returns true.
+GTEST_API_ bool AlwaysTrue();
+
+// Always returns false.
+inline bool AlwaysFalse() { return !AlwaysTrue(); }
+
+// 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
+// code). Unlike rand_r(), it's portable. An LCG isn't very random,
+// but it's good enough for our purposes.
+class GTEST_API_ Random {
+ public:
+ static const UInt32 kMaxRange = 1u << 31;
+
+ explicit Random(UInt32 seed) : state_(seed) {}
+
+ void Reseed(UInt32 seed) { state_ = seed; }
+
+ // Generates a random number from [0, range). Crashes if 'range' is
+ // 0 or greater than kMaxRange.
+ UInt32 Generate(UInt32 range);
+
+ private:
+ UInt32 state_;
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
+};
+
+} // namespace internal
+} // namespace testing
+
+#define GTEST_MESSAGE_(message, result_type) \
+ ::testing::internal::AssertHelper(result_type, __FILE__, __LINE__, message) \
+ = ::testing::Message()
+
+#define GTEST_FATAL_FAILURE_(message) \
+ return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+ GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define GTEST_SUCCESS_(message) \
+ GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
+
+// Suppresses MSVC warnings 4072 (unreachable code) for the code following
+// statement if it returns or throws (or doesn't return or throw in some
+// situations).
+#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
+ if (::testing::internal::AlwaysTrue()) { statement; }
+
+#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const char* gtest_msg = "") { \
+ bool gtest_caught_expected = false; \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } \
+ catch (expected_exception const&) { \
+ gtest_caught_expected = true; \
+ } \
+ catch (...) { \
+ gtest_msg = "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."; \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
+ fail(gtest_msg)
+
+#define GTEST_TEST_NO_THROW_(statement, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const char* gtest_msg = "") { \
+ 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)
+
+#define GTEST_TEST_ANY_THROW_(statement, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const char* gtest_msg = "") { \
+ bool gtest_caught_any = false; \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } \
+ catch (...) { \
+ 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)
+
+
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
+// either a boolean expression or an AssertionResult. text is a textual
+// represenation of expression as it was passed into the EXPECT_TRUE.
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const ::testing::AssertionResult gtest_ar_ = \
+ ::testing::AssertionResult(expression)) \
+ ; \
+ else \
+ fail(::testing::internal::GetBoolAssertionFailureMessage(\
+ gtest_ar_, text, #actual, #expected).c_str())
+
+#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const char* gtest_msg = "") { \
+ ::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)
+
+// Expands to the name of the class that implements the given test.
+#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+ test_case_name##_##test_name##_Test
+
+// Helper macro for defining tests.
+#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
+class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
+ public:\
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
+ private:\
+ virtual void TestBody();\
+ static ::testing::TestInfo* const test_info_;\
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
+};\
+\
+::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
+ ::test_info_ =\
+ ::testing::internal::MakeAndRegisterTestInfo(\
+ #test_case_name, #test_name, "", "", \
+ (parent_id), \
+ parent_class::SetUpTestCase, \
+ parent_class::TearDownTestCase, \
+ new ::testing::internal::TestFactoryImpl<\
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
+void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h
new file mode 100644
index 0000000..2404ea8
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h
@@ -0,0 +1,243 @@
+// Copyright 2003 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Dan Egnor (egnor@google.com)
+//
+// A "smart" pointer type with reference tracking. Every pointer to a
+// particular object is kept on a circular linked list. When the last pointer
+// to an object is destroyed or reassigned, the object is deleted.
+//
+// Used properly, this deletes the object when the last reference goes away.
+// There are several caveats:
+// - Like all reference counting schemes, cycles lead to leaks.
+// - Each smart pointer is actually two pointers (8 bytes instead of 4).
+// - Every time a pointer is assigned, the entire list of pointers to that
+// object is traversed. This class is therefore NOT SUITABLE when there
+// will often be more than two or three pointers to a particular object.
+// - References are only tracked as long as linked_ptr<> objects are copied.
+// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
+// will happen (double deletion).
+//
+// A good use of this class is storing object references in STL containers.
+// You can safely put linked_ptr<> in a vector<>.
+// Other uses may not be as good.
+//
+// Note: If you use an incomplete type with linked_ptr<>, the class
+// *containing* linked_ptr<> must have a constructor and destructor (even
+// if they do nothing!).
+//
+// Bill Gibbons suggested we use something like this.
+//
+// Thread Safety:
+// Unlike other linked_ptr implementations, in this implementation
+// a linked_ptr object is thread-safe in the sense that:
+// - it's safe to copy linked_ptr objects concurrently,
+// - it's safe to copy *from* a linked_ptr and read its underlying
+// raw pointer (e.g. via get()) concurrently, and
+// - it's safe to write to two linked_ptrs that point to the same
+// shared object concurrently.
+// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
+// confusion with normal linked_ptr.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include <gtest/internal/gtest-port.h>
+
+namespace testing {
+namespace internal {
+
+// Protects copying of all linked_ptr objects.
+GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// This is used internally by all instances of linked_ptr<>. It needs to be
+// a non-template class because different types of linked_ptr<> can refer to
+// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
+// So, it needs to be possible for different types of linked_ptr to participate
+// in the same circular linked list, so we need a single class type here.
+//
+// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr<T>.
+class linked_ptr_internal {
+ public:
+ // Create a new circle that includes only this instance.
+ void join_new() {
+ next_ = this;
+ }
+
+ // Many linked_ptr operations may change p.link_ for some linked_ptr
+ // variable p in the same circle as this object. Therefore we need
+ // to prevent two such operations from occurring concurrently.
+ //
+ // Note that different types of linked_ptr objects can coexist in a
+ // circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
+ // linked_ptr<Derived2>). Therefore we must use a single mutex to
+ // protect all linked_ptr objects. This can create serious
+ // contention in production code, but is acceptable in a testing
+ // framework.
+
+ // Join an existing circle.
+ // L < g_linked_ptr_mutex
+ void join(linked_ptr_internal const* ptr) {
+ MutexLock lock(&g_linked_ptr_mutex);
+
+ linked_ptr_internal const* p = ptr;
+ while (p->next_ != ptr) p = p->next_;
+ p->next_ = this;
+ next_ = ptr;
+ }
+
+ // Leave whatever circle we're part of. Returns true if we were the
+ // last member of the circle. Once this is done, you can join() another.
+ // L < g_linked_ptr_mutex
+ bool depart() {
+ MutexLock lock(&g_linked_ptr_mutex);
+
+ if (next_ == this) return true;
+ linked_ptr_internal const* p = next_;
+ while (p->next_ != this) p = p->next_;
+ p->next_ = next_;
+ return false;
+ }
+
+ private:
+ mutable linked_ptr_internal const* next_;
+};
+
+template <typename T>
+class linked_ptr {
+ public:
+ typedef T element_type;
+
+ // Take over ownership of a raw pointer. This should happen as soon as
+ // possible after the object is created.
+ explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
+ ~linked_ptr() { depart(); }
+
+ // Copy an existing linked_ptr<>, adding ourselves to the list of references.
+ template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
+ linked_ptr(linked_ptr const& ptr) { // NOLINT
+ assert(&ptr != this);
+ copy(&ptr);
+ }
+
+ // Assignment releases the old value and acquires the new.
+ template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
+ depart();
+ copy(&ptr);
+ return *this;
+ }
+
+ linked_ptr& operator=(linked_ptr const& ptr) {
+ if (&ptr != this) {
+ depart();
+ copy(&ptr);
+ }
+ return *this;
+ }
+
+ // Smart pointer members.
+ void reset(T* ptr = NULL) {
+ depart();
+ capture(ptr);
+ }
+ 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; }
+ template <typename U>
+ bool operator==(linked_ptr<U> const& ptr) const {
+ return value_ == ptr.get();
+ }
+ template <typename U>
+ bool operator!=(linked_ptr<U> const& ptr) const {
+ return value_ != ptr.get();
+ }
+
+ private:
+ template <typename U>
+ friend class linked_ptr;
+
+ T* value_;
+ linked_ptr_internal link_;
+
+ void depart() {
+ if (link_.depart()) delete value_;
+ }
+
+ void capture(T* ptr) {
+ value_ = ptr;
+ link_.join_new();
+ }
+
+ template <typename U> void copy(linked_ptr<U> const* ptr) {
+ value_ = ptr->get();
+ if (value_)
+ link_.join(&ptr->link_);
+ else
+ link_.join_new();
+ }
+};
+
+template<typename T> inline
+bool operator==(T* ptr, const linked_ptr<T>& x) {
+ return ptr == x.get();
+}
+
+template<typename T> inline
+bool operator!=(T* ptr, const linked_ptr<T>& x) {
+ return ptr != x.get();
+}
+
+// A function to convert T* into linked_ptr<T>
+// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
+// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
+template <typename T>
+linked_ptr<T> make_linked_ptr(T* ptr) {
+ return linked_ptr<T>(ptr);
+}
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
new file mode 100644
index 0000000..ab4ab56
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
@@ -0,0 +1,4820 @@
+// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most 50 arguments in Values,
+// and at most 10 arguments in Combine. Please contact
+// googletestframework@googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tr1::tuple which is
+// currently set at 10.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// 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>
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+ typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
+ ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+ const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+ explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray1& other);
+
+ const T1 v1_;
+};
+
+template <typename T1, typename T2>
+class ValueArray2 {
+ public:
+ ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray2& other);
+
+ const T1 v1_;
+ const T2 v2_;
+};
+
+template <typename T1, typename T2, typename T3>
+class ValueArray3 {
+ public:
+ ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray3& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+class ValueArray4 {
+ public:
+ ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray4& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class ValueArray5 {
+ public:
+ ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray5& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+class ValueArray6 {
+ public:
+ ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray6& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+class ValueArray7 {
+ public:
+ ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray7& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+class ValueArray8 {
+ public:
+ ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray8& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+class ValueArray9 {
+ public:
+ ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+ T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray9& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+class ValueArray10 {
+ public:
+ ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray10& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11>
+class ValueArray11 {
+ public:
+ ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+ v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray11& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12>
+class ValueArray12 {
+ public:
+ ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+ v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray12& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13>
+class ValueArray13 {
+ public:
+ ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+ v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+ v12_(v12), v13_(v13) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray13& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14>
+class ValueArray14 {
+ public:
+ ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray14& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15>
+class ValueArray15 {
+ public:
+ ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray15& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16>
+class ValueArray16 {
+ public:
+ ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+ v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+ v16_(v16) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray16& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17>
+class ValueArray17 {
+ public:
+ ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+ T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray17& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18>
+class ValueArray18 {
+ public:
+ ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray18& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19>
+class ValueArray19 {
+ public:
+ ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+ v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+ v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray19& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20>
+class ValueArray20 {
+ public:
+ ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+ v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+ v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+ v19_(v19), v20_(v20) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray20& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21>
+class ValueArray21 {
+ public:
+ ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+ v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+ v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+ v18_(v18), v19_(v19), v20_(v20), v21_(v21) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray21& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22>
+class ValueArray22 {
+ public:
+ ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray22& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23>
+class ValueArray23 {
+ public:
+ ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_,
+ v23_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray23& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24>
+class ValueArray24 {
+ public:
+ ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+ v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+ v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+ v22_(v22), v23_(v23), v24_(v24) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray24& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25>
+class ValueArray25 {
+ public:
+ ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+ T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray25& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26>
+class ValueArray26 {
+ public:
+ ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray26& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27>
+class ValueArray27 {
+ public:
+ ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+ v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+ v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+ v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+ v26_(v26), v27_(v27) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray27& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28>
+class ValueArray28 {
+ public:
+ ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+ v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+ v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+ v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+ v25_(v25), v26_(v26), v27_(v27), v28_(v28) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray28& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29>
+class ValueArray29 {
+ public:
+ ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+ v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+ v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+ v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+ v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray29& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30>
+class ValueArray30 {
+ public:
+ ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray30& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31>
+class ValueArray31 {
+ public:
+ ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30), v31_(v31) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray31& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32>
+class ValueArray32 {
+ public:
+ ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+ v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+ v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+ v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+ v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray32& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33>
+class ValueArray33 {
+ public:
+ ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+ T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray33& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34>
+class ValueArray34 {
+ public:
+ ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33), v34_(v34) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray34& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35>
+class ValueArray35 {
+ public:
+ ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+ v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+ v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+ v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+ v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+ v32_(v32), v33_(v33), v34_(v34), v35_(v35) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_,
+ v35_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray35& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36>
+class ValueArray36 {
+ public:
+ ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+ v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+ v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+ v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+ v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+ v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray36& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37>
+class ValueArray37 {
+ public:
+ ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+ v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+ v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+ v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+ v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+ v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+ v36_(v36), v37_(v37) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray37& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38>
+class ValueArray38 {
+ public:
+ ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+ v35_(v35), v36_(v36), v37_(v37), v38_(v38) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray38& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39>
+class ValueArray39 {
+ public:
+ ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+ v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray39& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40>
+class ValueArray40 {
+ public:
+ ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+ v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+ v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+ v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+ v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+ v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+ v40_(v40) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray40& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41>
+class ValueArray41 {
+ public:
+ ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+ T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+ v39_(v39), v40_(v40), v41_(v41) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_, v41_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray41& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42>
+class ValueArray42 {
+ public:
+ ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+ v39_(v39), v40_(v40), v41_(v41), v42_(v42) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_, v41_, v42_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray42& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43>
+class ValueArray43 {
+ public:
+ ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+ v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+ v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+ v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+ v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+ v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37),
+ v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray43& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44>
+class ValueArray44 {
+ public:
+ ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+ v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+ v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+ v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+ v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+ v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36),
+ v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42),
+ v43_(v43), v44_(v44) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray44& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45>
+class ValueArray45 {
+ public:
+ ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+ v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+ v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+ v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+ v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+ v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+ v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41),
+ v42_(v42), v43_(v43), v44_(v44), v45_(v45) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray45& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46>
+class ValueArray46 {
+ public:
+ ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+ v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+ v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray46& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+ const T46 v46_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47>
+class ValueArray47 {
+ public:
+ ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+ v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+ v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46),
+ v47_(v47) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_,
+ v47_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray47& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+ const T46 v46_;
+ const T47 v47_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48>
+class ValueArray48 {
+ public:
+ ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+ v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+ v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+ v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+ v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+ v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+ v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45),
+ v46_(v46), v47_(v47), v48_(v48) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+ v48_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray48& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+ const T46 v46_;
+ const T47 v47_;
+ const T48 v48_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49>
+class ValueArray49 {
+ public:
+ ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48,
+ T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+ v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+ v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+ v48_, v49_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray49& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+ const T46 v46_;
+ const T47 v47_;
+ const T48 v48_;
+ const T49 v49_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49, typename T50>
+class ValueArray50 {
+ public:
+ ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49,
+ T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+ v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+ v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+ v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+ v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+ v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+ v48_, v49_, v50_};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray50& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+ const T46 v46_;
+ const T47 v47_;
+ const T48 v48_;
+ const T49 v49_;
+ const T50 v50_;
+};
+
+#if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+template <typename T1, typename T2>
+class CartesianProductGenerator2
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2> ParamType;
+
+ CartesianProductGenerator2(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2)
+ : g1_(g1), g2_(g2) {}
+ virtual ~CartesianProductGenerator2() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current2_;
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator2::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator2& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+}; // class CartesianProductGenerator2
+
+
+template <typename T1, typename T2, typename T3>
+class CartesianProductGenerator3
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3> ParamType;
+
+ CartesianProductGenerator3(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
+ : g1_(g1), g2_(g2), g3_(g3) {}
+ virtual ~CartesianProductGenerator3() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current3_;
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator3::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator3& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+}; // class CartesianProductGenerator3
+
+
+template <typename T1, typename T2, typename T3, typename T4>
+class CartesianProductGenerator4
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4> ParamType;
+
+ CartesianProductGenerator4(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+ virtual ~CartesianProductGenerator4() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current4_;
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator4::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator4& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+}; // class CartesianProductGenerator4
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class CartesianProductGenerator5
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5> ParamType;
+
+ CartesianProductGenerator5(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+ virtual ~CartesianProductGenerator5() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current5_;
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator5::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator5& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+}; // class CartesianProductGenerator5
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+class CartesianProductGenerator6
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5,
+ T6> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> ParamType;
+
+ CartesianProductGenerator6(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+ const ParamGenerator<T6>& g6)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+ virtual ~CartesianProductGenerator6() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5,
+ const ParamGenerator<T6>& g6,
+ const typename ParamGenerator<T6>::iterator& current6)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+ begin6_(g6.begin()), end6_(g6.end()), current6_(current6) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current6_;
+ if (current6_ == end6_) {
+ current6_ = begin6_;
+ ++current5_;
+ }
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_ &&
+ current6_ == typed_other->current6_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_),
+ begin6_(other.begin6_),
+ end6_(other.end6_),
+ current6_(other.current6_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_, *current6_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_ ||
+ current6_ == end6_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ const typename ParamGenerator<T6>::iterator begin6_;
+ const typename ParamGenerator<T6>::iterator end6_;
+ typename ParamGenerator<T6>::iterator current6_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator6::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator6& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+ const ParamGenerator<T6> g6_;
+}; // class CartesianProductGenerator6
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+class CartesianProductGenerator7
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+ T7> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
+
+ CartesianProductGenerator7(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+ const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+ virtual ~CartesianProductGenerator7() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+ g7_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5,
+ const ParamGenerator<T6>& g6,
+ const typename ParamGenerator<T6>::iterator& current6,
+ const ParamGenerator<T7>& g7,
+ const typename ParamGenerator<T7>::iterator& current7)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+ begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+ begin7_(g7.begin()), end7_(g7.end()), current7_(current7) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current7_;
+ if (current7_ == end7_) {
+ current7_ = begin7_;
+ ++current6_;
+ }
+ if (current6_ == end6_) {
+ current6_ = begin6_;
+ ++current5_;
+ }
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_ &&
+ current6_ == typed_other->current6_ &&
+ current7_ == typed_other->current7_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_),
+ begin6_(other.begin6_),
+ end6_(other.end6_),
+ current6_(other.current6_),
+ begin7_(other.begin7_),
+ end7_(other.end7_),
+ current7_(other.current7_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_, *current6_, *current7_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_ ||
+ current6_ == end6_ ||
+ current7_ == end7_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ const typename ParamGenerator<T6>::iterator begin6_;
+ const typename ParamGenerator<T6>::iterator end6_;
+ typename ParamGenerator<T6>::iterator current6_;
+ const typename ParamGenerator<T7>::iterator begin7_;
+ const typename ParamGenerator<T7>::iterator end7_;
+ typename ParamGenerator<T7>::iterator current7_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator7::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator7& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+ const ParamGenerator<T6> g6_;
+ const ParamGenerator<T7> g7_;
+}; // class CartesianProductGenerator7
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+class CartesianProductGenerator8
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+ T7, T8> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
+
+ CartesianProductGenerator8(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+ const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+ const ParamGenerator<T8>& g8)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+ g8_(g8) {}
+ virtual ~CartesianProductGenerator8() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+ g7_.begin(), g8_, g8_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+ g8_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5,
+ const ParamGenerator<T6>& g6,
+ const typename ParamGenerator<T6>::iterator& current6,
+ const ParamGenerator<T7>& g7,
+ const typename ParamGenerator<T7>::iterator& current7,
+ const ParamGenerator<T8>& g8,
+ const typename ParamGenerator<T8>::iterator& current8)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+ begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+ begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+ begin8_(g8.begin()), end8_(g8.end()), current8_(current8) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current8_;
+ if (current8_ == end8_) {
+ current8_ = begin8_;
+ ++current7_;
+ }
+ if (current7_ == end7_) {
+ current7_ = begin7_;
+ ++current6_;
+ }
+ if (current6_ == end6_) {
+ current6_ = begin6_;
+ ++current5_;
+ }
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_ &&
+ current6_ == typed_other->current6_ &&
+ current7_ == typed_other->current7_ &&
+ current8_ == typed_other->current8_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_),
+ begin6_(other.begin6_),
+ end6_(other.end6_),
+ current6_(other.current6_),
+ begin7_(other.begin7_),
+ end7_(other.end7_),
+ current7_(other.current7_),
+ begin8_(other.begin8_),
+ end8_(other.end8_),
+ current8_(other.current8_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_, *current6_, *current7_, *current8_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_ ||
+ current6_ == end6_ ||
+ current7_ == end7_ ||
+ current8_ == end8_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ const typename ParamGenerator<T6>::iterator begin6_;
+ const typename ParamGenerator<T6>::iterator end6_;
+ typename ParamGenerator<T6>::iterator current6_;
+ const typename ParamGenerator<T7>::iterator begin7_;
+ const typename ParamGenerator<T7>::iterator end7_;
+ typename ParamGenerator<T7>::iterator current7_;
+ const typename ParamGenerator<T8>::iterator begin8_;
+ const typename ParamGenerator<T8>::iterator end8_;
+ typename ParamGenerator<T8>::iterator current8_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator8::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator8& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+ const ParamGenerator<T6> g6_;
+ const ParamGenerator<T7> g7_;
+ const ParamGenerator<T8> g8_;
+}; // class CartesianProductGenerator8
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+class CartesianProductGenerator9
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+ T7, T8, T9> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
+
+ CartesianProductGenerator9(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+ const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+ const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+ g9_(g9) {}
+ virtual ~CartesianProductGenerator9() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+ g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+ g8_.end(), g9_, g9_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5,
+ const ParamGenerator<T6>& g6,
+ const typename ParamGenerator<T6>::iterator& current6,
+ const ParamGenerator<T7>& g7,
+ const typename ParamGenerator<T7>::iterator& current7,
+ const ParamGenerator<T8>& g8,
+ const typename ParamGenerator<T8>::iterator& current8,
+ const ParamGenerator<T9>& g9,
+ const typename ParamGenerator<T9>::iterator& current9)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+ begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+ begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+ begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+ begin9_(g9.begin()), end9_(g9.end()), current9_(current9) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current9_;
+ if (current9_ == end9_) {
+ current9_ = begin9_;
+ ++current8_;
+ }
+ if (current8_ == end8_) {
+ current8_ = begin8_;
+ ++current7_;
+ }
+ if (current7_ == end7_) {
+ current7_ = begin7_;
+ ++current6_;
+ }
+ if (current6_ == end6_) {
+ current6_ = begin6_;
+ ++current5_;
+ }
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_ &&
+ current6_ == typed_other->current6_ &&
+ current7_ == typed_other->current7_ &&
+ current8_ == typed_other->current8_ &&
+ current9_ == typed_other->current9_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_),
+ begin6_(other.begin6_),
+ end6_(other.end6_),
+ current6_(other.current6_),
+ begin7_(other.begin7_),
+ end7_(other.end7_),
+ current7_(other.current7_),
+ begin8_(other.begin8_),
+ end8_(other.end8_),
+ current8_(other.current8_),
+ begin9_(other.begin9_),
+ end9_(other.end9_),
+ current9_(other.current9_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_, *current6_, *current7_, *current8_,
+ *current9_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_ ||
+ current6_ == end6_ ||
+ current7_ == end7_ ||
+ current8_ == end8_ ||
+ current9_ == end9_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ const typename ParamGenerator<T6>::iterator begin6_;
+ const typename ParamGenerator<T6>::iterator end6_;
+ typename ParamGenerator<T6>::iterator current6_;
+ const typename ParamGenerator<T7>::iterator begin7_;
+ const typename ParamGenerator<T7>::iterator end7_;
+ typename ParamGenerator<T7>::iterator current7_;
+ const typename ParamGenerator<T8>::iterator begin8_;
+ const typename ParamGenerator<T8>::iterator end8_;
+ typename ParamGenerator<T8>::iterator current8_;
+ const typename ParamGenerator<T9>::iterator begin9_;
+ const typename ParamGenerator<T9>::iterator end9_;
+ typename ParamGenerator<T9>::iterator current9_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator9::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator9& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+ const ParamGenerator<T6> g6_;
+ const ParamGenerator<T7> g7_;
+ const ParamGenerator<T8> g8_;
+ const ParamGenerator<T9> g9_;
+}; // class CartesianProductGenerator9
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+class CartesianProductGenerator10
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+ T7, T8, T9, T10> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
+
+ CartesianProductGenerator10(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+ const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+ const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9,
+ const ParamGenerator<T10>& g10)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+ g9_(g9), g10_(g10) {}
+ virtual ~CartesianProductGenerator10() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+ g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+ g8_.end(), g9_, g9_.end(), g10_, g10_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5,
+ const ParamGenerator<T6>& g6,
+ const typename ParamGenerator<T6>::iterator& current6,
+ const ParamGenerator<T7>& g7,
+ const typename ParamGenerator<T7>::iterator& current7,
+ const ParamGenerator<T8>& g8,
+ const typename ParamGenerator<T8>::iterator& current8,
+ const ParamGenerator<T9>& g9,
+ const typename ParamGenerator<T9>::iterator& current9,
+ const ParamGenerator<T10>& g10,
+ const typename ParamGenerator<T10>::iterator& current10)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+ begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+ begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+ begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+ begin9_(g9.begin()), end9_(g9.end()), current9_(current9),
+ begin10_(g10.begin()), end10_(g10.end()), current10_(current10) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current10_;
+ if (current10_ == end10_) {
+ current10_ = begin10_;
+ ++current9_;
+ }
+ if (current9_ == end9_) {
+ current9_ = begin9_;
+ ++current8_;
+ }
+ if (current8_ == end8_) {
+ current8_ = begin8_;
+ ++current7_;
+ }
+ if (current7_ == end7_) {
+ current7_ = begin7_;
+ ++current6_;
+ }
+ if (current6_ == end6_) {
+ current6_ = begin6_;
+ ++current5_;
+ }
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_ &&
+ current6_ == typed_other->current6_ &&
+ current7_ == typed_other->current7_ &&
+ current8_ == typed_other->current8_ &&
+ current9_ == typed_other->current9_ &&
+ current10_ == typed_other->current10_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_),
+ begin6_(other.begin6_),
+ end6_(other.end6_),
+ current6_(other.current6_),
+ begin7_(other.begin7_),
+ end7_(other.end7_),
+ current7_(other.current7_),
+ begin8_(other.begin8_),
+ end8_(other.end8_),
+ current8_(other.current8_),
+ begin9_(other.begin9_),
+ end9_(other.end9_),
+ current9_(other.current9_),
+ begin10_(other.begin10_),
+ end10_(other.end10_),
+ current10_(other.current10_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_, *current6_, *current7_, *current8_,
+ *current9_, *current10_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_ ||
+ current6_ == end6_ ||
+ current7_ == end7_ ||
+ current8_ == end8_ ||
+ current9_ == end9_ ||
+ current10_ == end10_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ const typename ParamGenerator<T6>::iterator begin6_;
+ const typename ParamGenerator<T6>::iterator end6_;
+ typename ParamGenerator<T6>::iterator current6_;
+ const typename ParamGenerator<T7>::iterator begin7_;
+ const typename ParamGenerator<T7>::iterator end7_;
+ typename ParamGenerator<T7>::iterator current7_;
+ const typename ParamGenerator<T8>::iterator begin8_;
+ const typename ParamGenerator<T8>::iterator end8_;
+ typename ParamGenerator<T8>::iterator current8_;
+ const typename ParamGenerator<T9>::iterator begin9_;
+ const typename ParamGenerator<T9>::iterator end9_;
+ typename ParamGenerator<T9>::iterator current9_;
+ const typename ParamGenerator<T10>::iterator begin10_;
+ const typename ParamGenerator<T10>::iterator end10_;
+ typename ParamGenerator<T10>::iterator current10_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator10::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator10& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+ const ParamGenerator<T6> g6_;
+ const ParamGenerator<T7> g7_;
+ const ParamGenerator<T8> g8_;
+ const ParamGenerator<T9> g9_;
+ const ParamGenerator<T10> g10_;
+}; // class CartesianProductGenerator10
+
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+template <class Generator1, class Generator2>
+class CartesianProductHolder2 {
+ public:
+CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
+ : g1_(g1), g2_(g2) {}
+ template <typename T1, typename T2>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2> >(
+ new CartesianProductGenerator2<T1, T2>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder2& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+}; // class CartesianProductHolder2
+
+template <class Generator1, class Generator2, class Generator3>
+class CartesianProductHolder3 {
+ public:
+CartesianProductHolder3(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3)
+ : g1_(g1), g2_(g2), g3_(g3) {}
+ template <typename T1, typename T2, typename T3>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >(
+ new CartesianProductGenerator3<T1, T2, T3>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder3& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+}; // class CartesianProductHolder3
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4>
+class CartesianProductHolder4 {
+ public:
+CartesianProductHolder4(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+ template <typename T1, typename T2, typename T3, typename T4>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >(
+ new CartesianProductGenerator4<T1, T2, T3, T4>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder4& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+}; // class CartesianProductHolder4
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5>
+class CartesianProductHolder5 {
+ public:
+CartesianProductHolder5(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >(
+ new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder5& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+}; // class CartesianProductHolder5
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5, class Generator6>
+class CartesianProductHolder6 {
+ public:
+CartesianProductHolder6(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5,
+ const Generator6& g6)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >(
+ new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_),
+ static_cast<ParamGenerator<T6> >(g6_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder6& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+ const Generator6 g6_;
+}; // class CartesianProductHolder6
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5, class Generator6, class Generator7>
+class CartesianProductHolder7 {
+ public:
+CartesianProductHolder7(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5,
+ const Generator6& g6, const Generator7& g7)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+ T7> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> >(
+ new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_),
+ static_cast<ParamGenerator<T6> >(g6_),
+ static_cast<ParamGenerator<T7> >(g7_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder7& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+ const Generator6 g6_;
+ const Generator7 g7_;
+}; // class CartesianProductHolder7
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5, class Generator6, class Generator7,
+ class Generator8>
+class CartesianProductHolder8 {
+ public:
+CartesianProductHolder8(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5,
+ const Generator6& g6, const Generator7& g7, const Generator8& g8)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+ g8_(g8) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7,
+ T8> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
+ new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_),
+ static_cast<ParamGenerator<T6> >(g6_),
+ static_cast<ParamGenerator<T7> >(g7_),
+ static_cast<ParamGenerator<T8> >(g8_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder8& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+ const Generator6 g6_;
+ const Generator7 g7_;
+ const Generator8 g8_;
+}; // class CartesianProductHolder8
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5, class Generator6, class Generator7,
+ class Generator8, class Generator9>
+class CartesianProductHolder9 {
+ public:
+CartesianProductHolder9(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5,
+ const Generator6& g6, const Generator7& g7, const Generator8& g8,
+ const Generator9& g9)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+ g9_(g9) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+ T9> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+ T9> >(
+ new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_),
+ static_cast<ParamGenerator<T6> >(g6_),
+ static_cast<ParamGenerator<T7> >(g7_),
+ static_cast<ParamGenerator<T8> >(g8_),
+ static_cast<ParamGenerator<T9> >(g9_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder9& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+ const Generator6 g6_;
+ const Generator7 g7_;
+ const Generator8 g8_;
+ const Generator9 g9_;
+}; // class CartesianProductHolder9
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5, class Generator6, class Generator7,
+ class Generator8, class Generator9, class Generator10>
+class CartesianProductHolder10 {
+ public:
+CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5,
+ const Generator6& g6, const Generator7& g7, const Generator8& g8,
+ const Generator9& g9, const Generator10& g10)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+ g9_(g9), g10_(g10) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+ T9, T10> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+ T9, T10> >(
+ new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+ T10>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_),
+ static_cast<ParamGenerator<T6> >(g6_),
+ static_cast<ParamGenerator<T7> >(g7_),
+ static_cast<ParamGenerator<T8> >(g8_),
+ static_cast<ParamGenerator<T9> >(g9_),
+ static_cast<ParamGenerator<T10> >(g10_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder10& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+ const Generator6 g6_;
+ const Generator7 g7_;
+ const Generator8 g8_;
+ const Generator9 g9_;
+ const Generator10 g10_;
+}; // class CartesianProductHolder10
+
+#endif // GTEST_HAS_COMBINE
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_HAS_PARAM_TEST
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
new file mode 100644
index 0000000..0cbb58c
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
@@ -0,0 +1,619 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+// 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>
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+namespace internal {
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Outputs a message explaining invalid registration of different
+// fixture class for the same test case. This may happen when
+// TEST_P macro is used to define two tests with the same name
+// but in different namespaces.
+GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
+ const char* file, int line);
+
+template <typename> class ParamGeneratorInterface;
+template <typename> class ParamGenerator;
+
+// Interface for iterating over elements provided by an implementation
+// of ParamGeneratorInterface<T>.
+template <typename T>
+class ParamIteratorInterface {
+ public:
+ virtual ~ParamIteratorInterface() {}
+ // A pointer to the base generator instance.
+ // Used only for the purposes of iterator comparison
+ // to make sure that two iterators belong to the same generator.
+ virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
+ // Advances iterator to point to the next element
+ // provided by the generator. The caller is responsible
+ // for not calling Advance() on an iterator equal to
+ // BaseGenerator()->End().
+ virtual void Advance() = 0;
+ // Clones the iterator object. Used for implementing copy semantics
+ // of ParamIterator<T>.
+ virtual ParamIteratorInterface* Clone() const = 0;
+ // Dereferences the current iterator and provides (read-only) access
+ // to the pointed value. It is the caller's responsibility not to call
+ // Current() on an iterator equal to BaseGenerator()->End().
+ // Used for implementing ParamGenerator<T>::operator*().
+ virtual const T* Current() const = 0;
+ // Determines whether the given iterator and other point to the same
+ // element in the sequence generated by the generator.
+ // Used for implementing ParamGenerator<T>::operator==().
+ virtual bool Equals(const ParamIteratorInterface& other) const = 0;
+};
+
+// Class iterating over elements provided by an implementation of
+// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
+// and implements the const forward iterator concept.
+template <typename T>
+class ParamIterator {
+ public:
+ typedef T value_type;
+ typedef const T& reference;
+ typedef ptrdiff_t difference_type;
+
+ // ParamIterator assumes ownership of the impl_ pointer.
+ ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
+ ParamIterator& operator=(const ParamIterator& other) {
+ if (this != &other)
+ impl_.reset(other.impl_->Clone());
+ return *this;
+ }
+
+ const T& operator*() const { return *impl_->Current(); }
+ const T* operator->() const { return impl_->Current(); }
+ // Prefix version of operator++.
+ ParamIterator& operator++() {
+ impl_->Advance();
+ return *this;
+ }
+ // Postfix version of operator++.
+ ParamIterator operator++(int /*unused*/) {
+ ParamIteratorInterface<T>* clone = impl_->Clone();
+ impl_->Advance();
+ return ParamIterator(clone);
+ }
+ bool operator==(const ParamIterator& other) const {
+ return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
+ }
+ bool operator!=(const ParamIterator& other) const {
+ return !(*this == other);
+ }
+
+ private:
+ friend class ParamGenerator<T>;
+ explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
+ scoped_ptr<ParamIteratorInterface<T> > impl_;
+};
+
+// ParamGeneratorInterface<T> is the binary interface to access generators
+// defined in other translation units.
+template <typename T>
+class ParamGeneratorInterface {
+ public:
+ typedef T ParamType;
+
+ virtual ~ParamGeneratorInterface() {}
+
+ // Generator interface definition
+ virtual ParamIteratorInterface<T>* Begin() const = 0;
+ virtual ParamIteratorInterface<T>* End() const = 0;
+};
+
+// Wraps ParamGeneratorInterface<T> and provides general generator syntax
+// compatible with the STL Container concept.
+// This class implements copy initialization semantics and the contained
+// ParamGeneratorInterface<T> instance is shared among all copies
+// of the original object. This is possible because that instance is immutable.
+template<typename T>
+class ParamGenerator {
+ public:
+ typedef ParamIterator<T> iterator;
+
+ explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
+ ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
+
+ ParamGenerator& operator=(const ParamGenerator& other) {
+ impl_ = other.impl_;
+ return *this;
+ }
+
+ iterator begin() const { return iterator(impl_->Begin()); }
+ iterator end() const { return iterator(impl_->End()); }
+
+ private:
+ ::testing::internal::linked_ptr<const ParamGeneratorInterface<T> > impl_;
+};
+
+// Generates values from a range of two comparable values. Can be used to
+// generate sequences of user-defined types that implement operator+() and
+// operator<().
+// This class is used in the Range() function.
+template <typename T, typename IncrementT>
+class RangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+ RangeGenerator(T begin, T end, IncrementT step)
+ : begin_(begin), end_(end),
+ step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
+ virtual ~RangeGenerator() {}
+
+ virtual ParamIteratorInterface<T>* Begin() const {
+ return new Iterator(this, begin_, 0, step_);
+ }
+ virtual ParamIteratorInterface<T>* End() const {
+ return new Iterator(this, end_, end_index_, step_);
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<T> {
+ public:
+ Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
+ IncrementT step)
+ : base_(base), value_(value), index_(index), step_(step) {}
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+ return base_;
+ }
+ virtual void Advance() {
+ value_ = value_ + step_;
+ index_++;
+ }
+ virtual ParamIteratorInterface<T>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const T* Current() const { return &value_; }
+ virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const int other_index =
+ CheckedDowncastToActualType<const Iterator>(&other)->index_;
+ return index_ == other_index;
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : ParamIteratorInterface<T>(),
+ base_(other.base_), value_(other.value_), index_(other.index_),
+ step_(other.step_) {}
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<T>* const base_;
+ T value_;
+ int index_;
+ const IncrementT step_;
+ }; // class RangeGenerator::Iterator
+
+ static int CalculateEndIndex(const T& begin,
+ const T& end,
+ const IncrementT& step) {
+ int end_index = 0;
+ for (T i = begin; i < end; i = i + step)
+ end_index++;
+ return end_index;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const RangeGenerator& other);
+
+ const T begin_;
+ const T end_;
+ const IncrementT step_;
+ // The index for the end() iterator. All the elements in the generated
+ // sequence are indexed (0-based) to aid iterator comparison.
+ const int end_index_;
+}; // class RangeGenerator
+
+
+// Generates values from a pair of STL-style iterators. Used in the
+// ValuesIn() function. The elements are copied from the source range
+// since the source can be located on the stack, and the generator
+// is likely to persist beyond that stack frame.
+template <typename T>
+class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+ template <typename ForwardIterator>
+ ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
+ : container_(begin, end) {}
+ virtual ~ValuesInIteratorRangeGenerator() {}
+
+ virtual ParamIteratorInterface<T>* Begin() const {
+ return new Iterator(this, container_.begin());
+ }
+ virtual ParamIteratorInterface<T>* End() const {
+ return new Iterator(this, container_.end());
+ }
+
+ private:
+ typedef typename ::std::vector<T> ContainerType;
+
+ class Iterator : public ParamIteratorInterface<T> {
+ public:
+ Iterator(const ParamGeneratorInterface<T>* base,
+ typename ContainerType::const_iterator iterator)
+ : base_(base), iterator_(iterator) {}
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+ return base_;
+ }
+ virtual void Advance() {
+ ++iterator_;
+ value_.reset();
+ }
+ virtual ParamIteratorInterface<T>* Clone() const {
+ return new Iterator(*this);
+ }
+ // We need to use cached value referenced by iterator_ because *iterator_
+ // can return a temporary object (and of type other then T), so just
+ // having "return &*iterator_;" doesn't work.
+ // value_ is updated here and not in Advance() because Advance()
+ // can advance iterator_ beyond the end of the range, and we cannot
+ // detect that fact. The client code, on the other hand, is
+ // responsible for not calling Current() on an out-of-range iterator.
+ virtual const T* Current() const {
+ if (value_.get() == NULL)
+ value_.reset(new T(*iterator_));
+ return value_.get();
+ }
+ virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ return iterator_ ==
+ CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ // The explicit constructor call suppresses a false warning
+ // emitted by gcc when supplied with the -Wextra option.
+ : ParamIteratorInterface<T>(),
+ base_(other.base_),
+ iterator_(other.iterator_) {}
+
+ const ParamGeneratorInterface<T>* const base_;
+ typename ContainerType::const_iterator iterator_;
+ // A cached value of *iterator_. We keep it here to allow access by
+ // pointer in the wrapping iterator's operator->().
+ // value_ needs to be mutable to be accessed in Current().
+ // Use of scoped_ptr helps manage cached value's lifetime,
+ // which is bound by the lifespan of the iterator itself.
+ mutable scoped_ptr<const T> value_;
+ }; // class ValuesInIteratorRangeGenerator::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const ValuesInIteratorRangeGenerator& other);
+
+ const ContainerType container_;
+}; // class ValuesInIteratorRangeGenerator
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Stores a parameter value and later creates tests parameterized with that
+// value.
+template <class TestClass>
+class ParameterizedTestFactory : public TestFactoryBase {
+ public:
+ typedef typename TestClass::ParamType ParamType;
+ explicit ParameterizedTestFactory(ParamType parameter) :
+ parameter_(parameter) {}
+ virtual Test* CreateTest() {
+ TestClass::SetParam(&parameter_);
+ return new TestClass();
+ }
+
+ private:
+ const ParamType parameter_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactoryBase is a base class for meta-factories that create
+// test factories for passing into MakeAndRegisterTestInfo function.
+template <class ParamType>
+class TestMetaFactoryBase {
+ public:
+ virtual ~TestMetaFactoryBase() {}
+
+ virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactory creates test factories for passing into
+// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
+// ownership of test factory pointer, same factory object cannot be passed
+// into that method twice. But ParameterizedTestCaseInfo is going to call
+// it for each Test/Parameter value combination. Thus it needs meta factory
+// creator class.
+template <class TestCase>
+class TestMetaFactory
+ : public TestMetaFactoryBase<typename TestCase::ParamType> {
+ public:
+ typedef typename TestCase::ParamType ParamType;
+
+ TestMetaFactory() {}
+
+ virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
+ return new ParameterizedTestFactory<TestCase>(parameter);
+ }
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfoBase is a generic interface
+// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
+// accumulates test information provided by TEST_P macro invocations
+// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
+// and uses that information to register all resulting test instances
+// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
+// a collection of pointers to the ParameterizedTestCaseInfo objects
+// and calls RegisterTests() on each of them when asked.
+class ParameterizedTestCaseInfoBase {
+ public:
+ virtual ~ParameterizedTestCaseInfoBase() {}
+
+ // Base part of test case name for display purposes.
+ 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
+ // test case right before running them in RUN_ALL_TESTS macro.
+ // This method should not be called more then once on any single
+ // instance of a ParameterizedTestCaseInfoBase derived class.
+ virtual void RegisterTests() = 0;
+
+ protected:
+ ParameterizedTestCaseInfoBase() {}
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
+// macro invocations for a particular test case and generators
+// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
+// test case. It registers tests with all values generated by all
+// generators when asked.
+template <class TestCase>
+class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
+ public:
+ // ParamType and GeneratorCreationFunc are private types but are required
+ // for declarations of public methods AddTestPattern() and
+ // AddTestCaseInstantiation().
+ typedef typename TestCase::ParamType ParamType;
+ // A function that returns an instance of appropriate generator type.
+ typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
+
+ explicit ParameterizedTestCaseInfo(const char* name)
+ : test_case_name_(name) {}
+
+ // Test case base name for display purposes.
+ 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
+ // about a single test in a LocalTestInfo structure.
+ // test_case_name is the base name of the test case (without invocation
+ // prefix). test_base_name is the name of an individual test without
+ // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
+ // test case base name and DoBar is test base name.
+ void AddTestPattern(const char* test_case_name,
+ const char* test_base_name,
+ TestMetaFactoryBase<ParamType>* meta_factory) {
+ tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
+ test_base_name,
+ meta_factory)));
+ }
+ // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
+ // about a generator.
+ int AddTestCaseInstantiation(const char* instantiation_name,
+ GeneratorCreationFunc* func,
+ const char* /* file */,
+ int /* line */) {
+ instantiations_.push_back(::std::make_pair(instantiation_name, func));
+ return 0; // Return value used only to run this method in namespace scope.
+ }
+ // UnitTest class invokes this method to register tests in this test case
+ // test cases right before running tests in RUN_ALL_TESTS macro.
+ // This method should not be called more then once on any single
+ // instance of a ParameterizedTestCaseInfoBase derived class.
+ // UnitTest has a guard to prevent from calling this method more then once.
+ virtual void RegisterTests() {
+ for (typename TestInfoContainer::iterator test_it = tests_.begin();
+ test_it != tests_.end(); ++test_it) {
+ linked_ptr<TestInfo> test_info = *test_it;
+ for (typename InstantiationContainer::iterator gen_it =
+ instantiations_.begin(); gen_it != instantiations_.end();
+ ++gen_it) {
+ 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();
+
+ 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_case_name_stream.GetString().c_str(),
+ test_name_stream.GetString().c_str(),
+ "", // test_case_comment
+ "", // comment; TODO(vladl@google.com): provide parameter value
+ // representation.
+ GetTestCaseTypeId(),
+ TestCase::SetUpTestCase,
+ TestCase::TearDownTestCase,
+ test_info->test_meta_factory->CreateTestFactory(*param_it));
+ } // for param_it
+ } // for gen_it
+ } // for test_it
+ } // RegisterTests
+
+ private:
+ // LocalTestInfo structure keeps information about a single test registered
+ // with TEST_P macro.
+ struct TestInfo {
+ TestInfo(const char* a_test_case_base_name,
+ const char* a_test_base_name,
+ TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
+ test_case_base_name(a_test_case_base_name),
+ 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 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*> >
+ InstantiationContainer;
+
+ const String test_case_name_;
+ TestInfoContainer tests_;
+ InstantiationContainer instantiations_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
+}; // class ParameterizedTestCaseInfo
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
+// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
+// macros use it to locate their corresponding ParameterizedTestCaseInfo
+// descriptors.
+class ParameterizedTestCaseRegistry {
+ public:
+ ParameterizedTestCaseRegistry() {}
+ ~ParameterizedTestCaseRegistry() {
+ for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+ it != test_case_infos_.end(); ++it) {
+ delete *it;
+ }
+ }
+
+ // Looks up or creates and returns a structure containing information about
+ // tests and instantiations of a particular test case.
+ template <class TestCase>
+ ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
+ const char* test_case_name,
+ const char* file,
+ int line) {
+ ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
+ for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+ it != test_case_infos_.end(); ++it) {
+ if ((*it)->GetTestCaseName() == test_case_name) {
+ if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
+ // Complain about incorrect usage of Google Test facilities
+ // 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();
+ } 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
+ // without further checks.
+ typed_test_info = CheckedDowncastToActualType<
+ ParameterizedTestCaseInfo<TestCase> >(*it);
+ }
+ break;
+ }
+ }
+ if (typed_test_info == NULL) {
+ typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
+ test_case_infos_.push_back(typed_test_info);
+ }
+ return typed_test_info;
+ }
+ void RegisterTests() {
+ for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+ it != test_case_infos_.end(); ++it) {
+ (*it)->RegisterTests();
+ }
+ }
+
+ private:
+ typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
+
+ TestCaseInfoContainer test_case_infos_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
+};
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_HAS_PARAM_TEST
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port.h
new file mode 100644
index 0000000..9683271
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port.h
@@ -0,0 +1,1501 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan)
+//
+// Low-level types and utilities for porting Google Test to various
+// platforms. They are subject to change without notice. DO NOT USE
+// THEM IN USER CODE.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+// The user can define the following macros in the build script to
+// control Google Test's behavior. If the user doesn't define a macro
+// in this list, Google Test will define it.
+//
+// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2)
+// is/isn't available.
+// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions
+// are enabled.
+// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string
+// is/isn't available (some systems define
+// ::string, which is different to std::string).
+// 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_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
+// enabled.
+// GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that
+// std::wstring does/doesn't work (Google Test can
+// be used where std::wstring is unavailable).
+// GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple
+// is/isn't available.
+// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the
+// compiler supports Microsoft's "Structured
+// Exception Handling".
+// 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
+// GTEST_HAS_TR1_TUPLE to 0.
+// GTEST_LINKED_AS_SHARED_LIBRARY
+// - Define to 1 when compiling tests that use
+// Google Test as a shared library (known as
+// DLL on Windows).
+// GTEST_CREATE_SHARED_LIBRARY
+// - Define to 1 when compiling Google Test itself
+// as a shared library.
+
+// This header defines the following utilities:
+//
+// Macros indicating the current platform (defined to 1 if compiled on
+// the given platform; otherwise undefined):
+// GTEST_OS_AIX - IBM AIX
+// GTEST_OS_CYGWIN - Cygwin
+// GTEST_OS_HAIKU - Haiku
+// GTEST_OS_LINUX - Linux
+// GTEST_OS_MAC - Mac OS X
+// GTEST_OS_SOLARIS - Sun Solaris
+// GTEST_OS_SYMBIAN - Symbian
+// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile)
+// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop
+// GTEST_OS_WINDOWS_MINGW - MinGW
+// GTEST_OS_WINDOWS_MOBILE - Windows Mobile
+// GTEST_OS_ZOS - z/OS
+//
+// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the
+// most stable support. Since core members of the Google Test project
+// don't have access to other platforms, support for them may be less
+// stable. If you notice any problems on your platform, please notify
+// googletestframework@googlegroups.com (patches for fixing them are
+// even more welcome!).
+//
+// Note that it is possible that none of the GTEST_OS_* macros are defined.
+//
+// Macros indicating available Google Test features (defined to 1 if
+// the corresponding feature is supported; otherwise undefined):
+// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized
+// tests)
+// GTEST_HAS_DEATH_TEST - death tests
+// 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_SIMPLE_RE - our own simple regex is used;
+// the above two are mutually exclusive.
+// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
+//
+// Macros for basic C++ coding:
+// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
+// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a
+// variable don't have to be used.
+// GTEST_DISALLOW_ASSIGN_ - disables operator=.
+// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
+// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used.
+//
+// Synchronization:
+// Mutex, MutexLock, ThreadLocal, GetThreadCount()
+// - synchronization primitives.
+// GTEST_IS_THREADSAFE - defined to 1 to indicate that the above
+// synchronization primitives have real implementations
+// and Google Test is thread-safe; or 0 otherwise.
+//
+// Template meta programming:
+// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only.
+//
+// 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.
+//
+// Logging:
+// GTEST_LOG_() - logs messages at the specified severity level.
+// LogToStderr() - directs all log messages to stderr.
+// FlushInfoLog() - flushes informational log messages.
+//
+// Stdout and stderr capturing:
+// CaptureStdout() - starts capturing stdout.
+// GetCapturedStdout() - stops capturing stdout and returns the captured
+// string.
+// CaptureStderr() - starts capturing stderr.
+// GetCapturedStderr() - stops capturing stderr and returns the captured
+// string.
+//
+// Integer types:
+// TypeWithSize - maps an integer to a int type.
+// Int32, UInt32, Int64, UInt64, TimeInMillis
+// - integers of known sizes.
+// BiggestInt - the biggest signed integer type.
+//
+// Command-line utilities:
+// GTEST_FLAG() - references a flag.
+// GTEST_DECLARE_*() - declares a flag.
+// GTEST_DEFINE_*() - defines a flag.
+// GetArgvs() - returns the command line as a vector of strings.
+//
+// Environment variable utilities:
+// GetEnv() - gets the value of an environment variable.
+// BoolFromGTestEnv() - parses a bool environment variable.
+// Int32FromGTestEnv() - parses an Int32 environment variable.
+// StringFromGTestEnv() - parses a string environment variable.
+
+#include <stddef.h> // For ptrdiff_t
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32_WCE
+#include <sys/stat.h>
+#endif // !_WIN32_WCE
+
+#include <iostream> // NOLINT
+#include <sstream> // NOLINT
+#include <string> // NOLINT
+
+#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
+#define GTEST_FLAG_PREFIX_ "gtest_"
+#define GTEST_FLAG_PREFIX_DASH_ "gtest-"
+#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
+#define GTEST_NAME_ "Google Test"
+#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/"
+
+// Determines the version of gcc that is used to compile this.
+#ifdef __GNUC__
+// 40302 means version 4.3.2.
+#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
+#elif defined __SYMBIAN32__
+#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
+#elif defined __APPLE__
+#define GTEST_OS_MAC 1
+#elif defined __linux__
+#define GTEST_OS_LINUX 1
+#elif defined __MVS__
+#define GTEST_OS_ZOS 1
+#elif defined(__sun) && defined(__SVR4)
+#define GTEST_OS_SOLARIS 1
+#elif defined(_AIX)
+#define GTEST_OS_AIX 1
+#elif defined(__HAIKU__)
+#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
+
+// 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
+
+#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
+
+#else
+
+// <regex.h> may not be available on this platform. Use our own
+// simple regex implementation instead.
+#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
+
+#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__)
+// 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
+// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#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
+// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#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__)
+#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
+#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."
+#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
+
+#endif // GTEST_HAS_GLOBAL_STRING
+
+#ifndef GTEST_HAS_STD_WSTRING
+// The user didn't tell us whether ::std::wstring is available, so we need
+// to figure it out.
+// TODO(wan@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.
+// Minix currently doesn't support it either.
+#define GTEST_HAS_STD_WSTRING (!(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 \
+ (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+// Determines whether RTTI is available.
+#ifndef GTEST_HAS_RTTI
+// The user didn't tell us whether RTTI is enabled, so we need to
+// figure it out.
+
+#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
+
+// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
+#elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+
+#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)
+
+#ifdef __RTTI_ALL__
+#define GTEST_HAS_RTTI 1
+#else
+#define GTEST_HAS_RTTI 0
+#endif
+
+#else
+
+// For all other compilers, we assume RTTI is enabled.
+#define GTEST_HAS_RTTI 1
+
+#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>
+#endif
+
+// Determines whether Google Test can use the pthreads library.
+#ifndef GTEST_HAS_PTHREAD
+// The user didn't tell us explicitly, so we assume pthreads support is
+// available on Linux and Mac.
+//
+// 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)
+#endif // GTEST_HAS_PTHREAD
+
+// 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
+#endif // GTEST_HAS_TR1_TUPLE
+
+// Determines whether Google Test's own tr1 tuple implementation
+// should be used.
+#ifndef GTEST_USE_OWN_TR1_TUPLE
+// The user didn't tell us, so we need to figure it out.
+
+// We use our own TR1 tuple if we aren't sure the user has an
+// implementation of it already. At this time, GCC 4.0.0+ and MSVC
+// 2010 are the only mainstream compilers that come with a TR1 tuple
+// implementation. NVIDIA's CUDA NVCC compiler pretends to be GCC by
+// 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__) && (GTEST_GCC_VER_ >= 40000)) \
+ || _MSC_VER >= 1600
+#define GTEST_USE_OWN_TR1_TUPLE 0
+#else
+#define GTEST_USE_OWN_TR1_TUPLE 1
+#endif
+
+#endif // GTEST_USE_OWN_TR1_TUPLE
+
+// To avoid conditional compilation everywhere, we make it
+// gtest-port.h's responsibility to #include the header implementing
+// tr1/tuple.
+#if GTEST_HAS_TR1_TUPLE
+
+#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
+
+// 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>
+
+#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
+// 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
+ // <tr1/functional> if he chooses to.
+#else
+#include <tr1/tuple> // NOLINT
+#endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+
+#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
+
+#endif // GTEST_HAS_TR1_TUPLE
+
+// Determines whether clone(2) is supported.
+// Usually it will only be available on Linux, excluding
+// Linux on the Itanium architecture.
+// Also see http://linux.die.net/man/2/clone.
+#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__)
+
+#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
+
+// Determines whether to support death tests.
+// Google Test does not support death tests for VC 7.1 and earlier as
+// abort() in a VC 7.1 application compiled as GUI in debug config
+// 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
+#endif
+
+// We don't support MSVC 7.1 with exceptions disabled now. Therefore
+// all the compilers we care about are adequate for supporting
+// value-parameterized tests.
+#define GTEST_HAS_PARAM_TEST 1
+
+// 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.
+#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
+ defined(__IBMCPP__)
+#define GTEST_HAS_TYPED_TEST 1
+#define GTEST_HAS_TYPED_TEST_P 1
+#endif
+
+// Determines whether to support Combine(). This only makes sense when
+// value-parameterized tests are enabled. The implementation doesn't
+// 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
+#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)
+
+// Defines some utility macros.
+
+// The GNU compiler emits a warning if nested "if" statements are followed by
+// an "else" statement and braces are not used to explicitly disambiguate the
+// "else" binding. This leads to problems with code like:
+//
+// if (gate)
+// ASSERT_*(condition) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#ifdef __INTEL_COMPILER
+#define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+#else
+#define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: // NOLINT
+#endif
+
+// Use this annotation at the end of a struct/class definition to
+// prevent the compiler from optimizing away instances that are never
+// used. This is useful when all interesting logic happens inside the
+// c'tor and / or d'tor. Example:
+//
+// struct Foo {
+// Foo() { ... }
+// } GTEST_ATTRIBUTE_UNUSED_;
+//
+// 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))
+#else
+#define GTEST_ATTRIBUTE_UNUSED_
+#endif
+
+// A macro to disallow operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_ASSIGN_(type)\
+ void operator=(type const &)
+
+// A macro to disallow copy constructor and operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\
+ type(type const &);\
+ GTEST_DISALLOW_ASSIGN_(type)
+
+// Tell the compiler to warn about unused return values for functions declared
+// with this macro. The macro should be used on function declarations
+// following the argument list:
+//
+// 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))
+#else
+#define GTEST_MUST_USE_RESULT_
+#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
+
+// Determine whether the compiler supports Microsoft's Structured Exception
+// Handling. This is supported by several Windows compilers but generally
+// does not exist on any other system.
+#ifndef GTEST_HAS_SEH
+// The user didn't tell us, so we need to figure it out.
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// These two compilers are known to support SEH.
+#define GTEST_HAS_SEH 1
+#else
+// Assume no SEH.
+#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
+
+#endif // _MSC_VER
+
+#ifndef GTEST_API_
+#define GTEST_API_
+#endif
+
+namespace testing {
+
+class Message;
+
+namespace internal {
+
+class String;
+
+typedef ::std::stringstream StrStream;
+
+// A helper for suppressing warnings on constant condition. It just
+// returns 'condition'.
+GTEST_API_ bool IsTrue(bool condition);
+
+// Defines scoped_ptr.
+
+// This implementation of scoped_ptr is PARTIAL - it only contains
+// enough stuff to satisfy Google Test's need.
+template <typename T>
+class scoped_ptr {
+ public:
+ typedef T element_type;
+
+ explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
+ ~scoped_ptr() { reset(); }
+
+ T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+ T* get() const { return ptr_; }
+
+ T* release() {
+ T* const ptr = ptr_;
+ ptr_ = NULL;
+ return ptr;
+ }
+
+ void reset(T* p = NULL) {
+ if (p != ptr_) {
+ if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type.
+ delete ptr_;
+ }
+ ptr_ = p;
+ }
+ }
+ private:
+ T* ptr_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr);
+};
+
+// Defines RE.
+
+// A simple C++ wrapper for <regex.h>. It uses the POSIX Extended
+// Regular Expression syntax.
+class GTEST_API_ RE {
+ public:
+ // A copy constructor is required by the Standard to initialize object
+ // references from r-values.
+ RE(const RE& other) { Init(other.pattern()); }
+
+ // Constructs an RE from a string.
+ 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
+ ~RE();
+
+ // Returns the string representation of the regex.
+ const char* pattern() const { return pattern_; }
+
+ // FullMatch(str, re) returns true iff regular expression re matches
+ // the entire str.
+ // PartialMatch(str, re) returns true iff regular expression re
+ // matches a substring of str (including str itself).
+ //
+ // TODO(wan@google.com): make FullMatch() and PartialMatch() work
+ // when str contains NUL characters.
+ static bool FullMatch(const ::std::string& str, const RE& re) {
+ return FullMatch(str.c_str(), re);
+ }
+ static bool PartialMatch(const ::std::string& str, const RE& re) {
+ return PartialMatch(str.c_str(), re);
+ }
+
+#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);
+ static bool PartialMatch(const char* str, const RE& re);
+
+ private:
+ void Init(const char* regex);
+
+ // We use a const char* instead of a string, as Google Test may be used
+ // where string is not available. We also do not use Google Test's own
+ // String type here, in order to simplify dependencies between the
+ // 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);
+};
+
+// Defines logging utilities:
+// GTEST_LOG_(severity) - logs messages at the specified severity level. The
+// message itself is streamed into the macro.
+// LogToStderr() - directs all log messages to stderr.
+// FlushInfoLog() - flushes informational log messages.
+
+enum GTestLogSeverity {
+ GTEST_INFO,
+ GTEST_WARNING,
+ GTEST_ERROR,
+ GTEST_FATAL
+};
+
+// Formats log entry severity, provides a stream object for streaming the
+// log message, and terminates the message with a newline when going out of
+// scope.
+class GTEST_API_ GTestLog {
+ public:
+ GTestLog(GTestLogSeverity severity, const char* file, int line);
+
+ // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+ ~GTestLog();
+
+ ::std::ostream& GetStream() { return ::std::cerr; }
+
+ private:
+ const GTestLogSeverity severity_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog);
+};
+
+#define GTEST_LOG_(severity) \
+ ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
+ __FILE__, __LINE__).GetStream()
+
+inline void LogToStderr() {}
+inline void FlushInfoLog() { fflush(NULL); }
+
+// INTERNAL IMPLEMENTATION - DO NOT USE.
+//
+// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
+// is not satisfied.
+// Synopsys:
+// GTEST_CHECK_(boolean_condition);
+// or
+// GTEST_CHECK_(boolean_condition) << "Additional message";
+//
+// This checks the condition and if the condition is not satisfied
+// it prints message about the condition violation, including the
+// condition itself, plus additional message streamed into it, if any,
+// and then it aborts the program. It aborts the program irrespective of
+// whether it is built in the debug mode or not.
+#define GTEST_CHECK_(condition) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::IsTrue(condition)) \
+ ; \
+ else \
+ GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
+
+// An all-mode assert to verify that the given POSIX-style function
+// call returns 0 (indicating success). Known limitation: this
+// doesn't expand to a balanced 'if' statement, so enclose the macro
+// in {} if you need to use it as the only statement in an 'if'
+// branch.
+#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
+ if (const int gtest_error = (posix_call)) \
+ GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
+ << gtest_error
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// 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.
+// When RTTI is available, the function performs a runtime
+// check to enforce this.
+template <class Derived, class Base>
+Derived* CheckedDowncastToActualType(Base* base) {
+#if GTEST_HAS_RTTI
+ GTEST_CHECK_(typeid(*base) == typeid(Derived));
+ return dynamic_cast<Derived*>(base); // NOLINT
+#else
+ return static_cast<Derived*>(base); // Poor man's downcast.
+#endif
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION_
+
+// Defines the stderr capturer:
+// CaptureStdout - starts capturing stdout.
+// GetCapturedStdout - stops capturing stdout and returns the captured string.
+// CaptureStderr - starts capturing stderr.
+// GetCapturedStderr - stops capturing stderr and returns the captured string.
+//
+GTEST_API_ void CaptureStdout();
+GTEST_API_ String GetCapturedStdout();
+GTEST_API_ void CaptureStderr();
+GTEST_API_ String GetCapturedStderr();
+
+#endif // GTEST_HAS_STREAM_REDIRECTION_
+
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments. Set by InitGoogleTest().
+extern ::std::vector<String> g_argvs;
+
+// GTEST_HAS_DEATH_TEST implies we have ::std::string.
+const ::std::vector<String>& GetArgvs();
+
+#endif // GTEST_HAS_DEATH_TEST
+
+// Defines synchronization primitives.
+
+#if GTEST_HAS_PTHREAD
+
+// Sleeps for (roughly) n milli-seconds. This function is only for
+// testing Google Test's own constructs. Don't use it in user tests,
+// either directly or indirectly.
+inline void SleepMilliseconds(int n) {
+ const timespec time = {
+ 0, // 0 seconds.
+ n * 1000L * 1000L, // And n ms.
+ };
+ nanosleep(&time, NULL);
+}
+
+// Allows a controller thread to pause execution of newly created
+// threads until notified. Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class Notification {
+ public:
+ Notification() : notified_(false) {}
+
+ // Notifies all threads created with this notification to start. Must
+ // be called from the controller thread.
+ void Notify() { notified_ = true; }
+
+ // Blocks until the controller thread notifies. Must be called from a test
+ // thread.
+ void WaitForNotification() {
+ while(!notified_) {
+ SleepMilliseconds(10);
+ }
+ }
+
+ private:
+ volatile bool notified_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+
+// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
+// Consequently, it cannot select a correct instantiation of ThreadWithParam
+// in order to call its Run(). Introducing ThreadWithParamBase as a
+// non-templated base class for ThreadWithParam allows us to bypass this
+// problem.
+class ThreadWithParamBase {
+ public:
+ virtual ~ThreadWithParamBase() {}
+ virtual void Run() = 0;
+};
+
+// pthread_create() accepts a pointer to a function type with the C linkage.
+// According to the Standard (7.5/1), function types with different linkages
+// are different even if they are otherwise identical. Some compilers (for
+// example, SunStudio) treat them as different types. Since class methods
+// cannot be defined with C-linkage we need to define a free C-function to
+// pass into pthread_create().
+extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
+ static_cast<ThreadWithParamBase*>(thread)->Run();
+ return NULL;
+}
+
+// Helper class for testing Google Test's multi-threading constructs.
+// To use it, write:
+//
+// void ThreadFunc(int param) { /* Do things with param */ }
+// Notification thread_can_start;
+// ...
+// // The thread_can_start parameter is optional; you can supply NULL.
+// ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
+// thread_can_start.Notify();
+//
+// These classes are only for testing Google Test's own constructs. Do
+// not use them in user tests, either directly or indirectly.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+ typedef void (*UserThreadFunc)(T);
+
+ ThreadWithParam(
+ UserThreadFunc func, T param, Notification* thread_can_start)
+ : func_(func),
+ param_(param),
+ thread_can_start_(thread_can_start),
+ finished_(false) {
+ ThreadWithParamBase* const base = this;
+ // The thread can be created only after all fields except thread_
+ // have been initialized.
+ GTEST_CHECK_POSIX_SUCCESS_(
+ pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base));
+ }
+ ~ThreadWithParam() { Join(); }
+
+ void Join() {
+ if (!finished_) {
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0));
+ finished_ = true;
+ }
+ }
+
+ virtual void Run() {
+ if (thread_can_start_ != NULL)
+ thread_can_start_->WaitForNotification();
+ func_(param_);
+ }
+
+ private:
+ const UserThreadFunc func_; // User-supplied thread function.
+ const T param_; // User-supplied parameter to the thread function.
+ // When non-NULL, used to block execution until the controller thread
+ // notifies.
+ Notification* const thread_can_start_;
+ bool finished_; // true iff we know that the thread function has finished.
+ pthread_t thread_; // The native thread object.
+
+ 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:
+//
+// Mutex mutex;
+// ...
+// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end
+// // of the current scope.
+//
+// MutexBase implements behavior for both statically and dynamically
+// allocated mutexes. Do not use MutexBase directly. Instead, write
+// the following to define a static mutex:
+//
+// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
+//
+// You can forward declare a static mutex like this:
+//
+// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
+//
+// To create a dynamic mutex, just define an object of type Mutex.
+class MutexBase {
+ public:
+ // Acquires this mutex.
+ void Lock() {
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
+ owner_ = pthread_self();
+ }
+
+ // Releases this mutex.
+ void Unlock() {
+ // We don't protect writing to owner_ here, as it's the caller's
+ // responsibility to ensure that the current thread holds the
+ // mutex when this is called.
+ owner_ = 0;
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
+ }
+
+ // Does nothing if the current thread holds the mutex. Otherwise, crashes
+ // with high probability.
+ void AssertHeld() const {
+ GTEST_CHECK_(owner_ == pthread_self())
+ << "The current thread is not holding the mutex @" << this;
+ }
+
+ // A static mutex may be used before main() is entered. It may even
+ // be used before the dynamic initialization stage. Therefore we
+ // must be able to initialize a static mutex object at link time.
+ // This means MutexBase has to be a POD and its member variables
+ // have to be public.
+ public:
+ pthread_mutex_t mutex_; // The underlying pthread mutex.
+ pthread_t owner_; // The thread holding the mutex; 0 means no one holds it.
+};
+
+// Forward-declares a static 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) \
+ ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 }
+
+// The Mutex class can only be used for mutexes created at runtime. It
+// shares its API with MutexBase otherwise.
+class Mutex : public MutexBase {
+ public:
+ Mutex() {
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+ owner_ = 0;
+ }
+ ~Mutex() {
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
+ }
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+// We cannot name this class MutexLock as the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+ explicit GTestMutexLock(MutexBase* mutex)
+ : mutex_(mutex) { mutex_->Lock(); }
+
+ ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+ MutexBase* const mutex_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Helpers for ThreadLocal.
+
+// pthread_key_create() requires DeleteThreadLocalValue() to have
+// C-linkage. Therefore it cannot be templatized to access
+// ThreadLocal<T>. Hence the need for class
+// ThreadLocalValueHolderBase.
+class ThreadLocalValueHolderBase {
+ public:
+ virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Called by pthread to delete thread-local data stored by
+// pthread_setspecific().
+extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
+ delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
+}
+
+// Implements thread-local storage on pthreads-based systems.
+//
+// // Thread 1
+// ThreadLocal<int> tl(100); // 100 is the default value for each thread.
+//
+// // Thread 2
+// tl.set(150); // Changes the value for thread 2 only.
+// EXPECT_EQ(150, tl.get());
+//
+// // Thread 1
+// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value.
+// tl.set(200);
+// EXPECT_EQ(200, tl.get());
+//
+// The template type argument T must have a public copy constructor.
+// In addition, the default ThreadLocal constructor requires T to have
+// a public default constructor.
+//
+// An object managed for a thread by a ThreadLocal instance is deleted
+// when the thread exits. Or, if the ThreadLocal instance dies in
+// that thread, when the ThreadLocal dies. It's the user's
+// responsibility to ensure that all other threads using a ThreadLocal
+// have exited when it dies, or the per-thread objects for those
+// threads will not be deleted.
+//
+// Google Test only uses global ThreadLocal objects. That means they
+// will die after main() has returned. Therefore, no per-thread
+// object managed by Google Test will be leaked as long as all threads
+// using Google Test have exited when main() returns.
+template <typename T>
+class ThreadLocal {
+ public:
+ ThreadLocal() : key_(CreateKey()),
+ default_() {}
+ explicit ThreadLocal(const T& value) : key_(CreateKey()),
+ default_(value) {}
+
+ ~ThreadLocal() {
+ // Destroys the managed object for the current thread, if any.
+ DeleteThreadLocalValue(pthread_getspecific(key_));
+
+ // Releases resources associated with the key. This will *not*
+ // delete managed objects for other threads.
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
+ }
+
+ T* pointer() { return GetOrCreateValue(); }
+ const T* pointer() const { return GetOrCreateValue(); }
+ const T& get() const { return *pointer(); }
+ void set(const T& value) { *pointer() = value; }
+
+ private:
+ // Holds a value of type T.
+ class ValueHolder : public ThreadLocalValueHolderBase {
+ public:
+ explicit ValueHolder(const T& value) : value_(value) {}
+
+ T* pointer() { return &value_; }
+
+ private:
+ T value_;
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+ };
+
+ static pthread_key_t CreateKey() {
+ pthread_key_t key;
+ // When a thread exits, DeleteThreadLocalValue() will be called on
+ // the object managed for that thread.
+ GTEST_CHECK_POSIX_SUCCESS_(
+ pthread_key_create(&key, &DeleteThreadLocalValue));
+ return key;
+ }
+
+ T* GetOrCreateValue() const {
+ ThreadLocalValueHolderBase* const holder =
+ static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
+ if (holder != NULL) {
+ return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
+ }
+
+ ValueHolder* const new_holder = new ValueHolder(default_);
+ ThreadLocalValueHolderBase* const holder_base = new_holder;
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
+ return new_holder->pointer();
+ }
+
+ // A key pthreads uses for looking up per-thread values.
+ const pthread_key_t key_;
+ const T default_; // The default value for each thread.
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+#define GTEST_IS_THREADSAFE 1
+
+#else // GTEST_HAS_PTHREAD
+
+// A dummy implementation of synchronization primitives (mutex, lock,
+// and thread-local variable). Necessary for compiling Google Test where
+// mutex is not supported - using Google Test in multiple threads is not
+// supported on such platforms.
+
+class Mutex {
+ public:
+ Mutex() {}
+ void AssertHeld() const {}
+};
+
+#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+ extern ::testing::internal::Mutex mutex
+
+#define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+
+class GTestMutexLock {
+ public:
+ explicit GTestMutexLock(Mutex*) {} // NOLINT
+};
+
+typedef GTestMutexLock MutexLock;
+
+template <typename T>
+class ThreadLocal {
+ public:
+ ThreadLocal() : value_() {}
+ explicit ThreadLocal(const T& value) : value_(value) {}
+ T* pointer() { return &value_; }
+ const T* pointer() const { return &value_; }
+ const T& get() const { return value_; }
+ void set(const T& value) { value_ = value; }
+ private:
+ T value_;
+};
+
+// The above synchronization primitives have dummy implementations.
+// Therefore Google Test is not thread-safe.
+#define GTEST_IS_THREADSAFE 0
+
+#endif // GTEST_HAS_PTHREAD
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+GTEST_API_ size_t GetThreadCount();
+
+// Passing non-POD classes through ellipsis (...) crashes the ARM
+// compiler and generates a warning in Sun Studio. The Nokia Symbian
+// and the IBM XL C/C++ compiler try to instantiate a copy constructor
+// for objects passed through ellipsis (...), failing for uncopyable
+// objects. We define this to ensure that only POD is passed through
+// ellipsis on these systems.
+#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
+#else
+#define GTEST_CAN_COMPARE_NULL 1
+#endif
+
+// 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.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
+#define GTEST_NEEDS_IS_POINTER_ 1
+#endif
+
+template <bool bool_value>
+struct bool_constant {
+ typedef bool_constant<bool_value> type;
+ static const bool value = bool_value;
+};
+template <bool bool_value> const bool bool_constant<bool_value>::value;
+
+typedef bool_constant<false> false_type;
+typedef bool_constant<true> true_type;
+
+template <typename T>
+struct is_pointer : public false_type {};
+
+template <typename T>
+struct is_pointer<T*> : public true_type {};
+
+#if GTEST_OS_WINDOWS
+#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
+typedef long long BiggestInt; // NOLINT
+#endif // GTEST_OS_WINDOWS
+
+// 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
+// standard functions as macros, the wrapper cannot have the same name
+// as the wrapped function.
+
+namespace posix {
+
+// Functions with a different name on Windows.
+
+#if GTEST_OS_WINDOWS
+
+typedef struct _stat StatStruct;
+
+#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
+inline int IsATTY(int /* fd */) { return 0; }
+#else
+inline int IsATTY(int fd) { return _isatty(fd); }
+#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__
+
+#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
+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
+
+#else
+
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+ return strcasecmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+
+#endif // GTEST_OS_WINDOWS
+
+// Functions deprecated by MSVC 8.0.
+
+#ifdef _MSC_VER
+// Temporarily disable warning 4996 (deprecated function).
+#pragma warning(push)
+#pragma warning(disable:4996)
+#endif
+
+inline const char* StrNCpy(char* dest, const char* src, size_t n) {
+ return strncpy(dest, src, n);
+}
+
+// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
+// StrError() aren't needed on Windows CE at this time and thus not
+// defined there.
+
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int ChDir(const char* dir) { return chdir(dir); }
+#endif
+inline FILE* FOpen(const char* path, const char* mode) {
+ return fopen(path, mode);
+}
+#if !GTEST_OS_WINDOWS_MOBILE
+inline FILE *FReopen(const char* path, const char* mode, FILE* stream) {
+ return freopen(path, mode, stream);
+}
+inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
+#endif
+inline int FClose(FILE* fp) { return fclose(fp); }
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int Read(int fd, void* buf, unsigned int count) {
+ return static_cast<int>(read(fd, buf, count));
+}
+inline int Write(int fd, const void* buf, unsigned int count) {
+ return static_cast<int>(write(fd, buf, count));
+}
+inline int Close(int fd) { return close(fd); }
+inline const char* StrError(int errnum) { return strerror(errnum); }
+#endif
+inline const char* GetEnv(const char* name) {
+#if GTEST_OS_WINDOWS_MOBILE
+ // We are on Windows CE, which has no environment variables.
+ return NULL;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+ // Environment variables which we programmatically clear will be set to the
+ // empty string rather than unset (NULL). Handle that case.
+ const char* const env = getenv(name);
+ return (env != NULL && env[0] != '\0') ? env : NULL;
+#else
+ return getenv(name);
+#endif
+}
+
+#ifdef _MSC_VER
+#pragma warning(pop) // Restores the warning state.
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Windows CE has no C library. The abort() function is used in
+// several places in Google Test. This implementation provides a reasonable
+// imitation of standard behaviour.
+void Abort();
+#else
+inline void Abort() { abort(); }
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+} // namespace posix
+
+// The maximum number a BiggestInt can represent. This definition
+// works no matter BiggestInt is represented in one's complement or
+// two's complement.
+//
+// We cannot rely on numeric_limits in STL, as __int64 and long long
+// are not part of standard C++ and numeric_limits doesn't need to be
+// defined for them.
+const BiggestInt kMaxBiggestInt =
+ ~(static_cast<BiggestInt>(1) << (8*sizeof(BiggestInt) - 1));
+
+// This template class serves as a compile-time function from size to
+// type. It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+// TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs. Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+ // This prevents the user from using TypeWithSize<N> with incorrect
+ // values of N.
+ typedef void UInt;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+ // unsigned int has size 4 in both gcc and MSVC.
+ //
+ // As base/basictypes.h doesn't compile on Windows, we cannot use
+ // uint32, uint64, and etc here.
+ typedef int Int;
+ typedef unsigned int UInt;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+#if GTEST_OS_WINDOWS
+ typedef __int64 Int;
+ typedef unsigned __int64 UInt;
+#else
+ typedef long long Int; // NOLINT
+ typedef unsigned long long UInt; // NOLINT
+#endif // GTEST_OS_WINDOWS
+};
+
+// Integer types of known sizes.
+typedef TypeWithSize<4>::Int Int32;
+typedef TypeWithSize<4>::UInt UInt32;
+typedef TypeWithSize<8>::Int Int64;
+typedef TypeWithSize<8>::UInt UInt64;
+typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds.
+
+// Utilities for command line flags and environment variables.
+
+// Macro for referencing flags.
+#define GTEST_FLAG(name) FLAGS_gtest_##name
+
+// Macros for declaring flags.
+#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
+#define GTEST_DECLARE_int32_(name) \
+ GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name)
+#define GTEST_DECLARE_string_(name) \
+ GTEST_API_ extern ::testing::internal::String GTEST_FLAG(name)
+
+// Macros for defining flags.
+#define GTEST_DEFINE_bool_(name, default_val, doc) \
+ GTEST_API_ bool GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_int32_(name, default_val, doc) \
+ GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_string_(name, default_val, doc) \
+ GTEST_API_ ::testing::internal::String GTEST_FLAG(name) = (default_val)
+
+// Parses 'str' for a 32-bit signed integer. If successful, writes the result
+// to *value and returns true; otherwise leaves *value unchanged and returns
+// false.
+// TODO(chandlerc): Find a better way to refactor flag and environment parsing
+// out of both gtest-port.cc and gtest.cc to avoid exporting this utility
+// function.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value);
+
+// Parses a bool/Int32/string from the environment variable
+// corresponding to the given Google Test flag.
+bool BoolFromGTestEnv(const char* flag, bool default_val);
+GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
+const char* StringFromGTestEnv(const char* flag, const char* default_val);
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-string.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-string.h
new file mode 100644
index 0000000..aff093d
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-string.h
@@ -0,0 +1,350 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares the String class and functions used internally by
+// Google Test. They are subject to change without notice. They should not used
+// by code external to Google Test.
+//
+// This header file is #included by <gtest/internal/gtest-internal.h>.
+// It should not be #included by other files.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+#ifdef __BORLANDC__
+// string.h is not guaranteed to provide strcpy on C++ Builder.
+#include <mem.h>
+#endif
+
+#include <string.h>
+#include <gtest/internal/gtest-port.h>
+
+#include <string>
+
+namespace testing {
+namespace internal {
+
+// String - a UTF-8 string class.
+//
+// For historic reasons, we don't use std::string.
+//
+// TODO(wan@google.com): replace this class with std::string or
+// implement it in terms of the latter.
+//
+// Note that String can represent both NULL and the empty string,
+// while std::string cannot represent NULL.
+//
+// NULL and the empty string are considered different. NULL is less
+// than anything (including the empty string) except itself.
+//
+// This class only provides minimum functionality necessary for
+// implementing Google Test. We do not intend to implement a full-fledged
+// string class here.
+//
+// Since the purpose of this class is to provide a substitute for
+// std::string on platforms where it cannot be used, we define a copy
+// constructor and assignment operators such that we don't need
+// conditional compilation in a lot of places.
+//
+// In order to make the representation efficient, the d'tor of String
+// is not virtual. Therefore DO NOT INHERIT FROM String.
+class GTEST_API_ String {
+ public:
+ // Static utility methods
+
+ // Returns the input enclosed in double quotes if it's not NULL;
+ // otherwise returns "(null)". For example, "\"Hello\"" is returned
+ // for input "Hello".
+ //
+ // This is useful for printing a C string in the syntax of a literal.
+ //
+ // Known issue: escape sequences are not handled yet.
+ static String ShowCStringQuoted(const char* c_str);
+
+ // Clones a 0-terminated C string, allocating memory using new. The
+ // caller is responsible for deleting the return value using
+ // delete[]. Returns the cloned string, or NULL if the input is
+ // NULL.
+ //
+ // This is different from strdup() in string.h, which allocates
+ // memory using malloc().
+ static const char* CloneCString(const char* c_str);
+
+#if GTEST_OS_WINDOWS_MOBILE
+ // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
+ // able to pass strings to Win32 APIs on CE we need to convert them
+ // to 'Unicode', UTF-16.
+
+ // Creates a UTF-16 wide string from the given ANSI string, allocating
+ // memory using new. The caller is responsible for deleting the return
+ // value using delete[]. Returns the wide string, or NULL if the
+ // input is NULL.
+ //
+ // The wide string is created using the ANSI codepage (CP_ACP) to
+ // match the behaviour of the ANSI versions of Win32 calls and the
+ // C runtime.
+ static LPCWSTR AnsiToUtf16(const char* c_str);
+
+ // Creates an ANSI string from the given wide string, allocating
+ // memory using new. The caller is responsible for deleting the return
+ // value using delete[]. Returns the ANSI string, or NULL if the
+ // input is NULL.
+ //
+ // The returned string is created using the ANSI codepage (CP_ACP) to
+ // match the behaviour of the ANSI versions of Win32 calls and the
+ // C runtime.
+ static const char* Utf16ToAnsi(LPCWSTR utf16_str);
+#endif
+
+ // Compares two C strings. Returns true iff they have the same content.
+ //
+ // Unlike strcmp(), this function can handle NULL argument(s). A
+ // NULL C string is considered different to any non-NULL C string,
+ // including the empty string.
+ static bool CStringEquals(const char* lhs, const char* rhs);
+
+ // Converts a wide C string to a String using the UTF-8 encoding.
+ // NULL will be converted to "(null)". If an error occurred during
+ // the conversion, "(failed to convert from wide string)" is
+ // returned.
+ static String ShowWideCString(const wchar_t* wide_c_str);
+
+ // Similar to ShowWideCString(), except that this function encloses
+ // the converted string in double quotes.
+ static String ShowWideCStringQuoted(const wchar_t* wide_c_str);
+
+ // Compares two wide C strings. Returns true iff they have the same
+ // content.
+ //
+ // Unlike wcscmp(), this function can handle NULL argument(s). A
+ // NULL C string is considered different to any non-NULL C string,
+ // including the empty string.
+ static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
+
+ // Compares two C strings, ignoring case. Returns true iff they
+ // have the same content.
+ //
+ // Unlike strcasecmp(), this function can handle NULL argument(s).
+ // A NULL C string is considered different to any non-NULL C string,
+ // including the empty string.
+ static bool CaseInsensitiveCStringEquals(const char* lhs,
+ const char* rhs);
+
+ // Compares two wide C strings, ignoring case. Returns true iff they
+ // have the same content.
+ //
+ // Unlike wcscasecmp(), this function can handle NULL argument(s).
+ // A NULL C string is considered different to any non-NULL wide C string,
+ // including the empty string.
+ // NB: The implementations on different platforms slightly differ.
+ // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+ // environment variable. On GNU platform this method uses wcscasecmp
+ // which compares according to LC_CTYPE category of the current locale.
+ // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+ // current locale.
+ static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+ const wchar_t* rhs);
+
+ // Formats a list of arguments to a String, using the same format
+ // spec string as for printf.
+ //
+ // We do not use the StringPrintf class as it is not universally
+ // available.
+ //
+ // The result is limited to 4096 characters (including the tailing
+ // 0). If 4096 characters are not enough to format the input,
+ // "<buffer exceeded>" is returned.
+ static String Format(const char* format, ...);
+
+ // C'tors
+
+ // The default c'tor constructs a NULL string.
+ String() : c_str_(NULL), length_(0) {}
+
+ // Constructs a String by cloning a 0-terminated C string.
+ String(const char* a_c_str) { // NOLINT
+ if (a_c_str == NULL) {
+ c_str_ = NULL;
+ length_ = 0;
+ } else {
+ ConstructNonNull(a_c_str, strlen(a_c_str));
+ }
+ }
+
+ // Constructs a String by copying a given number of chars from a
+ // buffer. E.g. String("hello", 3) creates the string "hel",
+ // String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "",
+ // and String(NULL, 1) results in access violation.
+ String(const char* buffer, size_t a_length) {
+ ConstructNonNull(buffer, a_length);
+ }
+
+ // The copy c'tor creates a new copy of the string. The two
+ // String objects do not share content.
+ String(const String& str) : c_str_(NULL), length_(0) { *this = str; }
+
+ // D'tor. String is intended to be a final class, so the d'tor
+ // doesn't need to be virtual.
+ ~String() { delete[] c_str_; }
+
+ // Allows a String to be implicitly converted to an ::std::string or
+ // ::string, and vice versa. Converting a String containing a NULL
+ // pointer to ::std::string or ::string is undefined behavior.
+ // Converting a ::std::string or ::string containing an embedded NUL
+ // character to a String will result in the prefix up to the first
+ // NUL character.
+ String(const ::std::string& str) {
+ ConstructNonNull(str.c_str(), str.length());
+ }
+
+ operator ::std::string() const { return ::std::string(c_str(), length()); }
+
+#if GTEST_HAS_GLOBAL_STRING
+ String(const ::string& str) {
+ ConstructNonNull(str.c_str(), str.length());
+ }
+
+ operator ::string() const { return ::string(c_str(), length()); }
+#endif // GTEST_HAS_GLOBAL_STRING
+
+ // Returns true iff this is an empty string (i.e. "").
+ bool empty() const { return (c_str() != NULL) && (length() == 0); }
+
+ // Compares this with another String.
+ // Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
+ // if this is greater than rhs.
+ int Compare(const String& rhs) const;
+
+ // Returns true iff this String equals the given C string. A NULL
+ // string and a non-NULL string are considered not equal.
+ bool operator==(const char* a_c_str) const { return Compare(a_c_str) == 0; }
+
+ // Returns true iff this String is less than the given String. A
+ // NULL string is considered less than "".
+ bool operator<(const String& rhs) const { return Compare(rhs) < 0; }
+
+ // Returns true iff this String doesn't equal the given C string. A NULL
+ // string and a non-NULL string are considered not equal.
+ bool operator!=(const char* a_c_str) const { return !(*this == a_c_str); }
+
+ // Returns true iff this String ends with the given suffix. *Any*
+ // String is considered to end with a NULL or empty suffix.
+ bool EndsWith(const char* suffix) const;
+
+ // Returns true iff this String ends with the given suffix, not considering
+ // case. Any String is considered to end with a NULL or empty suffix.
+ bool EndsWithCaseInsensitive(const char* suffix) const;
+
+ // Returns the length of the encapsulated string, or 0 if the
+ // string is NULL.
+ size_t length() const { return length_; }
+
+ // Gets the 0-terminated C string this String object represents.
+ // The String object still owns the string. Therefore the caller
+ // should NOT delete the return value.
+ const char* c_str() const { return c_str_; }
+
+ // Assigns a C string to this object. Self-assignment works.
+ const String& operator=(const char* a_c_str) {
+ return *this = String(a_c_str);
+ }
+
+ // Assigns a String object to this object. Self-assignment works.
+ const String& operator=(const String& rhs) {
+ if (this != &rhs) {
+ delete[] c_str_;
+ if (rhs.c_str() == NULL) {
+ c_str_ = NULL;
+ length_ = 0;
+ } else {
+ ConstructNonNull(rhs.c_str(), rhs.length());
+ }
+ }
+
+ return *this;
+ }
+
+ private:
+ // Constructs a non-NULL String from the given content. This
+ // function can only be called when data_ 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) {
+ char* const str = new char[a_length + 1];
+ memcpy(str, buffer, a_length);
+ str[a_length] = '\0';
+ c_str_ = str;
+ length_ = a_length;
+ }
+
+ const char* c_str_;
+ size_t length_;
+}; // class String
+
+// Streams a String to an ostream. Each '\0' character in the String
+// is replaced with "\\0".
+inline ::std::ostream& operator<<(::std::ostream& os, const String& str) {
+ if (str.c_str() == NULL) {
+ os << "(null)";
+ } else {
+ const char* const c_str = str.c_str();
+ for (size_t i = 0; i != str.length(); i++) {
+ if (c_str[i] == '\0') {
+ os << "\\0";
+ } else {
+ os << c_str[i];
+ }
+ }
+ }
+ return os;
+}
+
+// Gets the content of the StrStream's buffer as a String. Each '\0'
+// character in the buffer is replaced with "\\0".
+GTEST_API_ String StrStreamToString(StrStream* stream);
+
+// Converts a streamable value to a String. A NULL pointer is
+// converted to "(null)". When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+
+// Declared here but defined in gtest.h, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable);
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h
new file mode 100644
index 0000000..16178fc
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h
@@ -0,0 +1,968 @@
+// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility> // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined). This
+// hack bypasses the bug by declaring the members that should otherwise be
+// 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:
+#else
+#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
+ private:
+#endif
+
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
+ void, void, void>
+#define GTEST_2_TUPLE_(T) tuple<T##0, T##1, void, void, void, void, void, \
+ void, void, void>
+#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2, void, void, void, void, \
+ void, void, void>
+#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, void, void, void, \
+ void, void, void>
+#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, void, void, \
+ void, void, void>
+#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, void, \
+ void, void, void>
+#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+ void, void, void>
+#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+ T##7, void, void>
+#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+ T##7, T##8, void>
+#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+ T##7, T##8, T##9>
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+#define GTEST_0_TYPENAMES_(T)
+#define GTEST_1_TYPENAMES_(T) typename T##0
+#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1
+#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2
+#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3
+#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4
+#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5
+#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6
+#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6, typename T##7
+#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6, \
+ typename T##7, typename T##8
+#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6, \
+ typename T##7, typename T##8, typename T##9
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior. We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <typename T0 = void, typename T1 = void, typename T2 = void,
+ typename T3 = void, typename T4 = void, typename T5 = void,
+ typename T6 = void, typename T7 = void, typename T8 = void,
+ typename T9 = void>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; }; // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&. This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; }; // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>. kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 0, GTEST_10_TUPLE_(T)> { typedef T0 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 1, GTEST_10_TUPLE_(T)> { typedef T1 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 2, GTEST_10_TUPLE_(T)> { typedef T2 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 3, GTEST_10_TUPLE_(T)> { typedef T3 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 4, GTEST_10_TUPLE_(T)> { typedef T4 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 5, GTEST_10_TUPLE_(T)> { typedef T5 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 6, GTEST_10_TUPLE_(T)> { typedef T6 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 7, GTEST_10_TUPLE_(T)> { typedef T7 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 8, GTEST_10_TUPLE_(T)> { typedef T8 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 9, GTEST_10_TUPLE_(T)> { typedef T9 type; };
+
+} // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+ tuple() {}
+ tuple(const tuple& /* t */) {}
+ tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+class GTEST_1_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
+
+ tuple(const tuple& t) : f0_(t.f0_) {}
+
+ template <GTEST_1_TYPENAMES_(U)>
+ tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_1_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_1_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_1_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ return *this;
+ }
+
+ T0 f0_;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+class GTEST_2_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
+ f1_(f1) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {}
+
+ template <GTEST_2_TYPENAMES_(U)>
+ tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {}
+ template <typename U0, typename U1>
+ tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_2_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_2_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+ template <typename U0, typename U1>
+ tuple& operator=(const ::std::pair<U0, U1>& p) {
+ f0_ = p.first;
+ f1_ = p.second;
+ return *this;
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_2_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+class GTEST_3_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+ template <GTEST_3_TYPENAMES_(U)>
+ tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_3_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_3_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_3_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+class GTEST_4_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
+ f3_(f3) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {}
+
+ template <GTEST_4_TYPENAMES_(U)>
+ tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_4_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_4_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_4_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+class GTEST_5_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
+ GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_) {}
+
+ template <GTEST_5_TYPENAMES_(U)>
+ tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_5_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_5_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_5_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+class GTEST_6_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+ f5_(f5) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_) {}
+
+ template <GTEST_6_TYPENAMES_(U)>
+ tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_6_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_6_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_6_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+class GTEST_7_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2),
+ f3_(f3), f4_(f4), f5_(f5), f6_(f6) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+ template <GTEST_7_TYPENAMES_(U)>
+ tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_7_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_7_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_7_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+class GTEST_8_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6,
+ GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+ f5_(f5), f6_(f6), f7_(f7) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+ template <GTEST_8_TYPENAMES_(U)>
+ tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_8_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_8_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_8_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ f7_ = t.f7_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+ T7 f7_;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+class GTEST_9_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+ GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+ f5_(f5), f6_(f6), f7_(f7), f8_(f8) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+ template <GTEST_9_TYPENAMES_(U)>
+ tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_9_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_9_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_9_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ f7_ = t.f7_;
+ f8_ = t.f8_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+ T7 f7_;
+ T8 f8_;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+class tuple {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
+ f9_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+ GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2),
+ f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {}
+
+ template <GTEST_10_TYPENAMES_(U)>
+ tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_),
+ f9_(t.f9_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_10_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_10_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_10_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ f7_ = t.f7_;
+ f8_ = t.f8_;
+ f9_ = t.f9_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+ T7 f7_;
+ T8 f8_;
+ T9 f9_;
+};
+
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple(). And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+template <GTEST_1_TYPENAMES_(T)>
+inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) {
+ return GTEST_1_TUPLE_(T)(f0);
+}
+
+template <GTEST_2_TYPENAMES_(T)>
+inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) {
+ return GTEST_2_TUPLE_(T)(f0, f1);
+}
+
+template <GTEST_3_TYPENAMES_(T)>
+inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) {
+ return GTEST_3_TUPLE_(T)(f0, f1, f2);
+}
+
+template <GTEST_4_TYPENAMES_(T)>
+inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3) {
+ return GTEST_4_TUPLE_(T)(f0, f1, f2, f3);
+}
+
+template <GTEST_5_TYPENAMES_(T)>
+inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4) {
+ return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4);
+}
+
+template <GTEST_6_TYPENAMES_(T)>
+inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5) {
+ return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5);
+}
+
+template <GTEST_7_TYPENAMES_(T)>
+inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6) {
+ return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6);
+}
+
+template <GTEST_8_TYPENAMES_(T)>
+inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) {
+ return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7);
+}
+
+template <GTEST_9_TYPENAMES_(T)>
+inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+ const T8& f8) {
+ return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
+}
+
+template <GTEST_10_TYPENAMES_(T)>
+inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+ const T8& f8, const T9& f9) {
+ return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
+}
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+template <GTEST_0_TYPENAMES_(T)>
+struct tuple_size<GTEST_0_TUPLE_(T)> { static const int value = 0; };
+
+template <GTEST_1_TYPENAMES_(T)>
+struct tuple_size<GTEST_1_TUPLE_(T)> { static const int value = 1; };
+
+template <GTEST_2_TYPENAMES_(T)>
+struct tuple_size<GTEST_2_TUPLE_(T)> { static const int value = 2; };
+
+template <GTEST_3_TYPENAMES_(T)>
+struct tuple_size<GTEST_3_TUPLE_(T)> { static const int value = 3; };
+
+template <GTEST_4_TYPENAMES_(T)>
+struct tuple_size<GTEST_4_TUPLE_(T)> { static const int value = 4; };
+
+template <GTEST_5_TYPENAMES_(T)>
+struct tuple_size<GTEST_5_TUPLE_(T)> { static const int value = 5; };
+
+template <GTEST_6_TYPENAMES_(T)>
+struct tuple_size<GTEST_6_TUPLE_(T)> { static const int value = 6; };
+
+template <GTEST_7_TYPENAMES_(T)>
+struct tuple_size<GTEST_7_TUPLE_(T)> { static const int value = 7; };
+
+template <GTEST_8_TYPENAMES_(T)>
+struct tuple_size<GTEST_8_TUPLE_(T)> { static const int value = 8; };
+
+template <GTEST_9_TYPENAMES_(T)>
+struct tuple_size<GTEST_9_TUPLE_(T)> { static const int value = 9; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct tuple_size<GTEST_10_TUPLE_(T)> { static const int value = 10; };
+
+template <int k, class Tuple>
+struct tuple_element {
+ typedef typename gtest_internal::TupleElement<
+ k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+template <>
+class Get<0> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+ Field(Tuple& t) { return t.f0_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+ ConstField(const Tuple& t) { return t.f0_; }
+};
+
+template <>
+class Get<1> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+ Field(Tuple& t) { return t.f1_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+ ConstField(const Tuple& t) { return t.f1_; }
+};
+
+template <>
+class Get<2> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+ Field(Tuple& t) { return t.f2_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+ ConstField(const Tuple& t) { return t.f2_; }
+};
+
+template <>
+class Get<3> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+ Field(Tuple& t) { return t.f3_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+ ConstField(const Tuple& t) { return t.f3_; }
+};
+
+template <>
+class Get<4> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+ Field(Tuple& t) { return t.f4_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+ ConstField(const Tuple& t) { return t.f4_; }
+};
+
+template <>
+class Get<5> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+ Field(Tuple& t) { return t.f5_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+ ConstField(const Tuple& t) { return t.f5_; }
+};
+
+template <>
+class Get<6> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+ Field(Tuple& t) { return t.f6_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+ ConstField(const Tuple& t) { return t.f6_; }
+};
+
+template <>
+class Get<7> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+ Field(Tuple& t) { return t.f7_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+ ConstField(const Tuple& t) { return t.f7_; }
+};
+
+template <>
+class Get<8> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+ Field(Tuple& t) { return t.f8_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+ ConstField(const Tuple& t) { return t.f8_; }
+};
+
+template <>
+class Get<9> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+ Field(Tuple& t) { return t.f9_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+ ConstField(const Tuple& t) { return t.f9_; }
+};
+
+} // namespace gtest_internal
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(GTEST_10_TUPLE_(T)& t) {
+ return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(const GTEST_10_TUPLE_(T)& t) {
+ return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+ template <class Tuple1, class Tuple2>
+ static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+ return true;
+ }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+ template <class Tuple1, class Tuple2>
+ static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+ return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+ ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+ }
+};
+
+} // namespace gtest_internal
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator==(const GTEST_10_TUPLE_(T)& t,
+ const GTEST_10_TUPLE_(U)& u) {
+ return gtest_internal::SameSizeTuplePrefixComparator<
+ tuple_size<GTEST_10_TUPLE_(T)>::value,
+ tuple_size<GTEST_10_TUPLE_(U)>::value>::Eq(t, u);
+}
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
+ const GTEST_10_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+} // namespace tr1
+} // namespace std
+
+#undef GTEST_0_TUPLE_
+#undef GTEST_1_TUPLE_
+#undef GTEST_2_TUPLE_
+#undef GTEST_3_TUPLE_
+#undef GTEST_4_TUPLE_
+#undef GTEST_5_TUPLE_
+#undef GTEST_6_TUPLE_
+#undef GTEST_7_TUPLE_
+#undef GTEST_8_TUPLE_
+#undef GTEST_9_TUPLE_
+#undef GTEST_10_TUPLE_
+
+#undef GTEST_0_TYPENAMES_
+#undef GTEST_1_TYPENAMES_
+#undef GTEST_2_TYPENAMES_
+#undef GTEST_3_TYPENAMES_
+#undef GTEST_4_TYPENAMES_
+#undef GTEST_5_TYPENAMES_
+#undef GTEST_6_TYPENAMES_
+#undef GTEST_7_TYPENAMES_
+#undef GTEST_8_TYPENAMES_
+#undef GTEST_9_TYPENAMES_
+#undef GTEST_10_TYPENAMES_
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
diff --git a/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h
new file mode 100644
index 0000000..093eee6
--- /dev/null
+++ b/contrib/llvm/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h
@@ -0,0 +1,3321 @@
+// This file was GENERATED by command:
+// pump.py gtest-type-util.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
+//
+// Currently we support at most 50 types in a list, and at most 50
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework@googlegroups.com if you need
+// more.
+
+#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
+
+// #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__
+
+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.
+template <typename T>
+String GetTypeName() {
+#if GTEST_HAS_RTTI
+
+ const char* const name = typeid(T).name();
+#ifdef __GLIBCXX__
+ 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);
+ const String name_str(status == 0 ? readable_name : name);
+ free(readable_name);
+ return name_str;
+#else
+ return name;
+#endif // __GLIBCXX__
+
+#else
+ return "<type>";
+#endif // GTEST_HAS_RTTI
+}
+
+// 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
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists. In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+ typedef T1 Head;
+ typedef Types0 Tail;
+};
+template <typename T1, typename T2>
+struct Types2 {
+ typedef T1 Head;
+ typedef Types1<T2> Tail;
+};
+
+template <typename T1, typename T2, typename T3>
+struct Types3 {
+ typedef T1 Head;
+ typedef Types2<T2, T3> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types4 {
+ typedef T1 Head;
+ typedef Types3<T2, T3, T4> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types5 {
+ typedef T1 Head;
+ typedef Types4<T2, T3, T4, T5> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+struct Types6 {
+ typedef T1 Head;
+ typedef Types5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+struct Types7 {
+ typedef T1 Head;
+ typedef Types6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+struct Types8 {
+ typedef T1 Head;
+ typedef Types7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+struct Types9 {
+ typedef T1 Head;
+ typedef Types8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types10 {
+ typedef T1 Head;
+ typedef Types9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11>
+struct Types11 {
+ typedef T1 Head;
+ typedef Types10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12>
+struct Types12 {
+ typedef T1 Head;
+ typedef Types11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13>
+struct Types13 {
+ typedef T1 Head;
+ typedef Types12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14>
+struct Types14 {
+ typedef T1 Head;
+ typedef Types13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types15 {
+ typedef T1 Head;
+ typedef Types14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16>
+struct Types16 {
+ typedef T1 Head;
+ typedef Types15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17>
+struct Types17 {
+ typedef T1 Head;
+ typedef Types16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18>
+struct Types18 {
+ typedef T1 Head;
+ typedef Types17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19>
+struct Types19 {
+ typedef T1 Head;
+ typedef Types18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types20 {
+ typedef T1 Head;
+ typedef Types19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21>
+struct Types21 {
+ typedef T1 Head;
+ typedef Types20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22>
+struct Types22 {
+ typedef T1 Head;
+ typedef Types21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23>
+struct Types23 {
+ typedef T1 Head;
+ typedef Types22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24>
+struct Types24 {
+ typedef T1 Head;
+ typedef Types23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types25 {
+ typedef T1 Head;
+ typedef Types24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26>
+struct Types26 {
+ typedef T1 Head;
+ typedef Types25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27>
+struct Types27 {
+ typedef T1 Head;
+ typedef Types26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28>
+struct Types28 {
+ typedef T1 Head;
+ typedef Types27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29>
+struct Types29 {
+ typedef T1 Head;
+ typedef Types28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types30 {
+ typedef T1 Head;
+ typedef Types29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31>
+struct Types31 {
+ typedef T1 Head;
+ typedef Types30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32>
+struct Types32 {
+ typedef T1 Head;
+ typedef Types31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33>
+struct Types33 {
+ typedef T1 Head;
+ typedef Types32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34>
+struct Types34 {
+ typedef T1 Head;
+ typedef Types33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types35 {
+ typedef T1 Head;
+ typedef Types34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36>
+struct Types36 {
+ typedef T1 Head;
+ typedef Types35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37>
+struct Types37 {
+ typedef T1 Head;
+ typedef Types36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38>
+struct Types38 {
+ typedef T1 Head;
+ typedef Types37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39>
+struct Types39 {
+ typedef T1 Head;
+ typedef Types38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types40 {
+ typedef T1 Head;
+ typedef Types39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41>
+struct Types41 {
+ typedef T1 Head;
+ typedef Types40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42>
+struct Types42 {
+ typedef T1 Head;
+ typedef Types41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43>
+struct Types43 {
+ typedef T1 Head;
+ typedef Types42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44>
+struct Types44 {
+ typedef T1 Head;
+ typedef Types43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types45 {
+ typedef T1 Head;
+ typedef Types44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46>
+struct Types46 {
+ typedef T1 Head;
+ typedef Types45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47>
+struct Types47 {
+ typedef T1 Head;
+ typedef Types46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48>
+struct Types48 {
+ typedef T1 Head;
+ typedef Types47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49>
+struct Types49 {
+ typedef T1 Head;
+ typedef Types48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49, typename T50>
+struct Types50 {
+ typedef T1 Head;
+ typedef Types49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+} // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length. Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable. The translation is done by the 'type' member of the
+// Types template.
+template <typename T1 = internal::None, typename T2 = internal::None,
+ typename T3 = internal::None, typename T4 = internal::None,
+ typename T5 = internal::None, typename T6 = internal::None,
+ typename T7 = internal::None, typename T8 = internal::None,
+ typename T9 = internal::None, typename T10 = internal::None,
+ typename T11 = internal::None, typename T12 = internal::None,
+ typename T13 = internal::None, typename T14 = internal::None,
+ typename T15 = internal::None, typename T16 = internal::None,
+ typename T17 = internal::None, typename T18 = internal::None,
+ typename T19 = internal::None, typename T20 = internal::None,
+ typename T21 = internal::None, typename T22 = internal::None,
+ typename T23 = internal::None, typename T24 = internal::None,
+ typename T25 = internal::None, typename T26 = internal::None,
+ typename T27 = internal::None, typename T28 = internal::None,
+ typename T29 = internal::None, typename T30 = internal::None,
+ typename T31 = internal::None, typename T32 = internal::None,
+ typename T33 = internal::None, typename T34 = internal::None,
+ typename T35 = internal::None, typename T36 = internal::None,
+ typename T37 = internal::None, typename T38 = internal::None,
+ typename T39 = internal::None, typename T40 = internal::None,
+ typename T41 = internal::None, typename T42 = internal::None,
+ typename T43 = internal::None, typename T44 = internal::None,
+ typename T45 = internal::None, typename T46 = internal::None,
+ typename T47 = internal::None, typename T48 = internal::None,
+ typename T49 = internal::None, typename T50 = internal::None>
+struct Types {
+ typedef internal::Types50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Types<internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types0 type;
+};
+template <typename T1>
+struct Types<T1, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types1<T1> type;
+};
+template <typename T1, typename T2>
+struct Types<T1, T2, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types2<T1, T2> type;
+};
+template <typename T1, typename T2, typename T3>
+struct Types<T1, T2, T3, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types3<T1, T2, T3> type;
+};
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types<T1, T2, T3, T4, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types4<T1, T2, T3, T4> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types<T1, T2, T3, T4, T5, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types5<T1, T2, T3, T4, T5> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+struct Types<T1, T2, T3, T4, T5, T6, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types6<T1, T2, T3, T4, T5, T6> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+struct Types<T1, T2, T3, T4, T5, T6, T7, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+ T46, internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+ T46, T47, internal::None, internal::None, internal::None> {
+ typedef internal::Types47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46, T47> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+ T46, T47, T48, internal::None, internal::None> {
+ typedef internal::Types48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+ T46, T47, T48, T49, internal::None> {
+ typedef internal::Types49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+namespace internal {
+
+#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
+// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>. This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+ template <typename T>
+ struct Bind {
+ typedef Tmpl<T> type;
+ };
+};
+
+#define GTEST_BIND_(TmplSel, T) \
+ TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates. This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists. In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN). Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates0 Tail;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates2 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates1<T2> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates3 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates2<T2, T3> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4>
+struct Templates4 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates3<T2, T3, T4> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates5 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates4<T2, T3, T4, T5> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates6 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7>
+struct Templates7 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates8 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates9 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10>
+struct Templates10 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates11 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates12 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13>
+struct Templates13 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates14 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates15 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16>
+struct Templates16 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates17 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates18 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19>
+struct Templates19 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates20 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates21 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22>
+struct Templates22 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates23 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates24 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25>
+struct Templates25 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates26 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates27 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28>
+struct Templates28 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates29 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates30 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31>
+struct Templates31 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates32 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates33 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34>
+struct Templates34 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates35 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates36 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37>
+struct Templates37 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates38 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates39 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40>
+struct Templates40 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates41 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates42 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43>
+struct Templates43 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates44 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates45 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46>
+struct Templates46 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45, T46> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates47 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45, T46, T47> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates48 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45, T46, T47, T48> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+ GTEST_TEMPLATE_ T49>
+struct Templates49 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+ GTEST_TEMPLATE_ T49, GTEST_TEMPLATE_ T50>
+struct Templates50 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length. Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable. The translation is done by the 'type' member of the
+// Templates template.
+template <GTEST_TEMPLATE_ T1 = NoneT, GTEST_TEMPLATE_ T2 = NoneT,
+ GTEST_TEMPLATE_ T3 = NoneT, GTEST_TEMPLATE_ T4 = NoneT,
+ GTEST_TEMPLATE_ T5 = NoneT, GTEST_TEMPLATE_ T6 = NoneT,
+ GTEST_TEMPLATE_ T7 = NoneT, GTEST_TEMPLATE_ T8 = NoneT,
+ GTEST_TEMPLATE_ T9 = NoneT, GTEST_TEMPLATE_ T10 = NoneT,
+ GTEST_TEMPLATE_ T11 = NoneT, GTEST_TEMPLATE_ T12 = NoneT,
+ GTEST_TEMPLATE_ T13 = NoneT, GTEST_TEMPLATE_ T14 = NoneT,
+ GTEST_TEMPLATE_ T15 = NoneT, GTEST_TEMPLATE_ T16 = NoneT,
+ GTEST_TEMPLATE_ T17 = NoneT, GTEST_TEMPLATE_ T18 = NoneT,
+ GTEST_TEMPLATE_ T19 = NoneT, GTEST_TEMPLATE_ T20 = NoneT,
+ GTEST_TEMPLATE_ T21 = NoneT, GTEST_TEMPLATE_ T22 = NoneT,
+ GTEST_TEMPLATE_ T23 = NoneT, GTEST_TEMPLATE_ T24 = NoneT,
+ GTEST_TEMPLATE_ T25 = NoneT, GTEST_TEMPLATE_ T26 = NoneT,
+ GTEST_TEMPLATE_ T27 = NoneT, GTEST_TEMPLATE_ T28 = NoneT,
+ GTEST_TEMPLATE_ T29 = NoneT, GTEST_TEMPLATE_ T30 = NoneT,
+ GTEST_TEMPLATE_ T31 = NoneT, GTEST_TEMPLATE_ T32 = NoneT,
+ GTEST_TEMPLATE_ T33 = NoneT, GTEST_TEMPLATE_ T34 = NoneT,
+ GTEST_TEMPLATE_ T35 = NoneT, GTEST_TEMPLATE_ T36 = NoneT,
+ GTEST_TEMPLATE_ T37 = NoneT, GTEST_TEMPLATE_ T38 = NoneT,
+ GTEST_TEMPLATE_ T39 = NoneT, GTEST_TEMPLATE_ T40 = NoneT,
+ GTEST_TEMPLATE_ T41 = NoneT, GTEST_TEMPLATE_ T42 = NoneT,
+ GTEST_TEMPLATE_ T43 = NoneT, GTEST_TEMPLATE_ T44 = NoneT,
+ GTEST_TEMPLATE_ T45 = NoneT, GTEST_TEMPLATE_ T46 = NoneT,
+ GTEST_TEMPLATE_ T47 = NoneT, GTEST_TEMPLATE_ T48 = NoneT,
+ GTEST_TEMPLATE_ T49 = NoneT, GTEST_TEMPLATE_ T50 = NoneT>
+struct Templates {
+ typedef Templates50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Templates<NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT> {
+ typedef Templates0 type;
+};
+template <GTEST_TEMPLATE_ T1>
+struct Templates<T1, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT> {
+ typedef Templates1<T1> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates<T1, T2, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT> {
+ typedef Templates2<T1, T2> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates<T1, T2, T3, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates3<T1, T2, T3> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4>
+struct Templates<T1, T2, T3, T4, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates4<T1, T2, T3, T4> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates<T1, T2, T3, T4, T5, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates5<T1, T2, T3, T4, T5> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates<T1, T2, T3, T4, T5, T6, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates6<T1, T2, T3, T4, T5, T6> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT> {
+ typedef Templates22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT> {
+ typedef Templates23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT> {
+ typedef Templates24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT> {
+ typedef Templates25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT> {
+ typedef Templates26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT> {
+ typedef Templates27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT> {
+ typedef Templates28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT> {
+ typedef Templates29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ T45, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ T45, T46, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45, T46> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ T45, T46, T47, NoneT, NoneT, NoneT> {
+ typedef Templates47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45, T46, T47> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ T45, T46, T47, T48, NoneT, NoneT> {
+ typedef Templates48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+ GTEST_TEMPLATE_ T49>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ T45, T46, T47, T48, T49, NoneT> {
+ typedef Templates49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList { typedef Types1<T> type; };
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49, typename T50>
+struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48, T49, T50> > {
+ typedef typename Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
+};
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/contrib/llvm/utils/valgrind/i386-pc-linux-gnu.supp b/contrib/llvm/utils/valgrind/i386-pc-linux-gnu.supp
new file mode 100644
index 0000000..c9f68a0
--- /dev/null
+++ b/contrib/llvm/utils/valgrind/i386-pc-linux-gnu.supp
@@ -0,0 +1,41 @@
+{
+ False leak under RegisterPass
+ Memcheck:Leak
+ ...
+ fun:_ZN83_GLOBAL_*PassRegistrar12RegisterPassERKN4llvm8PassInfoE
+ fun:_ZN4llvm8PassInfo12registerPassEv
+}
+
+# Python false positives according to
+# http://svn.python.org/projects/python/trunk/Misc/README.valgrind
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Addr4
+ obj:/usr/bin/python2.5
+}
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Value4
+ obj:/usr/bin/python2.5
+}
+
+{
+ ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value
+ Memcheck:Cond
+ obj:/usr/bin/python2.5
+}
+
+{
+ We don't care if as leaks
+ Memcheck:Leak
+ obj:/usr/bin/as
+}
+
+{
+ We don't care if python leaks
+ Memcheck:Leak
+ fun:malloc
+ obj:/usr/bin/python2.5
+}
diff --git a/contrib/llvm/utils/valgrind/x86_64-pc-linux-gnu.supp b/contrib/llvm/utils/valgrind/x86_64-pc-linux-gnu.supp
new file mode 100644
index 0000000..f5aae99
--- /dev/null
+++ b/contrib/llvm/utils/valgrind/x86_64-pc-linux-gnu.supp
@@ -0,0 +1,46 @@
+{
+ False leak under RegisterPass
+ Memcheck:Leak
+ ...
+ fun:_ZN4llvm12PassRegistry12registerPassERKNS_8PassInfoE
+}
+
+# Python false positives according to
+# http://svn.python.org/projects/python/trunk/Misc/README.valgrind
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Addr4
+ obj:/usr/bin/python2.5
+}
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Value8
+ obj:/usr/bin/python2.5
+}
+
+{
+ ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value
+ Memcheck:Cond
+ obj:/usr/bin/python2.5
+}
+
+{
+ We don't care if as leaks
+ Memcheck:Leak
+ obj:/usr/bin/as
+}
+
+{
+ We don't care if grep leaks
+ Memcheck:Leak
+ obj:/bin/grep
+}
+
+{
+ We don't care if python leaks
+ Memcheck:Leak
+ fun:malloc
+ obj:/usr/bin/python2.5
+}
diff --git a/contrib/llvm/utils/vim/README b/contrib/llvm/utils/vim/README
new file mode 100644
index 0000000..bca25bf
--- /dev/null
+++ b/contrib/llvm/utils/vim/README
@@ -0,0 +1,43 @@
+-*- llvm/utils/vim/README -*-
+
+These are syntax highlighting files for the VIM editor. Included are:
+
+* llvm.vim
+
+ Syntax highlighting mode for LLVM assembly files. To use, copy `llvm.vim' to
+ ~/.vim/syntax and add this code to your ~/.vimrc :
+
+ augroup filetype
+ au! BufRead,BufNewFile *.ll set filetype=llvm
+ augroup END
+
+* tablegen.vim
+
+ Syntax highlighting mode for TableGen description files. To use, copy
+ `tablegen.vim' to ~/.vim/syntax and add this code to your ~/.vimrc :
+
+ augroup filetype
+ au! BufRead,BufNewFile *.td set filetype=tablegen
+ augroup END
+
+
+If you prefer, instead of making copies you can make symlinks from
+~/.vim/syntax/... to the syntax files in your LLVM source tree. Apparently
+this did not work with older versions of vim however, so if this doesn't
+work you may need to make actual copies of the files.
+
+Another option, if you do not already have a ~/.vim/syntax directory, is
+to symlink ~/.vim/syntax itself to llvm/utils/vim .
+
+Note: If you notice missing or incorrect syntax highlighting, please contact
+<llvmbugs [at] cs.uiuc.edu>; if you wish to provide a patch to improve the
+functionality, it will be most appreciated. Thank you.
+
+If you find yourself working with LLVM Makefiles often, but you don't get syntax
+highlighting (because the files have names such as Makefile.rules or
+TEST.nightly.Makefile), add the following to your ~/.vimrc:
+
+ " LLVM Makefile highlighting mode
+ augroup filetype
+ au! BufRead,BufNewFile *Makefile* set filetype=make
+ augroup END
diff --git a/contrib/llvm/utils/vim/llvm.vim b/contrib/llvm/utils/vim/llvm.vim
new file mode 100644
index 0000000..acebc20
--- /dev/null
+++ b/contrib/llvm/utils/vim/llvm.vim
@@ -0,0 +1,109 @@
+" Vim syntax file
+" Language: llvm
+" Maintainer: The LLVM team, http://llvm.org/
+" Version: $Revision: 112382 $
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+syn case match
+
+" Types.
+" Types also include struct, array, vector, etc. but these don't
+" benefit as much from having dedicated highlighting rules.
+syn keyword llvmType void float double
+syn keyword llvmType x86_fp80 fp128 ppc_fp128
+syn keyword llvmType type label opaque
+syn match llvmType /\<i\d\+\>/
+
+" Instructions.
+" The true and false tokens can be used for comparison opcodes, but it's
+" much more common for these tokens to be used for boolean constants.
+syn keyword llvmStatement add fadd sub fsub mul fmul
+syn keyword llvmStatement sdiv udiv fdiv srem urem frem
+syn keyword llvmStatement and or xor
+syn keyword llvmStatement icmp fcmp
+syn keyword llvmStatement eq ne ugt uge ult ule sgt sge slt sle
+syn keyword llvmStatement oeq ogt oge olt ole one ord ueq ugt uge
+syn keyword llvmStatement ult ule une uno
+syn keyword llvmStatement nuw nsw exact inbounds
+syn keyword llvmStatement phi call select shl lshr ashr va_arg
+syn keyword llvmStatement trunc zext sext
+syn keyword llvmStatement fptrunc fpext fptoui fptosi uitofp sitofp
+syn keyword llvmStatement ptrtoint inttoptr bitcast
+syn keyword llvmStatement ret br indirectbr switch invoke unwind unreachable
+syn keyword llvmStatement malloc alloca free load store getelementptr
+syn keyword llvmStatement extractelement insertelement shufflevector
+syn keyword llvmStatement extractvalue insertvalue
+
+" Keywords.
+syn keyword llvmKeyword define declare global constant
+syn keyword llvmKeyword internal external private
+syn keyword llvmKeyword linkonce linkonce_odr weak weak_odr appending
+syn keyword llvmKeyword common extern_weak
+syn keyword llvmKeyword thread_local dllimport dllexport
+syn keyword llvmKeyword hidden protected default
+syn keyword llvmKeyword except deplibs
+syn keyword llvmKeyword volatile fastcc coldcc cc ccc
+syn keyword llvmKeyword x86_stdcallcc x86_fastcallcc
+syn keyword llvmKeyword signext zeroext inreg sret nounwind noreturn
+syn keyword llvmKeyword nocapture byval nest readnone readonly noalias
+syn keyword llvmKeyword inlinehint noinline alwaysinline optsize ssp sspreq
+syn keyword llvmKeyword noredzone noimplicitfloat naked alignstack
+syn keyword llvmKeyword module asm align tail to
+syn keyword llvmKeyword addrspace section alias sideeffect c gc
+syn keyword llvmKeyword target datalayout triple
+syn keyword llvmKeyword blockaddress
+
+" Obsolete keywords.
+syn keyword llvmError getresult begin end
+
+" Misc syntax.
+syn match llvmNoName /[%@]\d\+\>/
+syn match llvmNumber /-\?\<\d\+\>/
+syn match llvmFloat /-\?\<\d\+\.\d*\(e[+-]\d\+\)\?\>/
+syn match llvmFloat /\<0x\x\+\>/
+syn keyword llvmBoolean true false
+syn keyword llvmConstant zeroinitializer undef null
+syn match llvmComment /;.*$/
+syn region llvmString start=/"/ skip=/\\"/ end=/"/
+syn match llvmLabel /[-a-zA-Z$._][-a-zA-Z$._0-9]*:/
+syn match llvmIdentifier /[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*/
+
+" Syntax-highlight dejagnu test commands.
+syn match llvmSpecialComment /;\s*RUN:.*$/
+syn match llvmSpecialComment /;\s*PR\d*\s*$/
+syn match llvmSpecialComment /;\s*END\.\s*$/
+syn match llvmSpecialComment /;\s*XFAIL:.*$/
+syn match llvmSpecialComment /;\s*XTARGET:.*$/
+
+if version >= 508 || !exists("did_c_syn_inits")
+ if version < 508
+ let did_c_syn_inits = 1
+ command -nargs=+ HiLink hi link <args>
+ else
+ command -nargs=+ HiLink hi def link <args>
+ endif
+
+ HiLink llvmType Type
+ HiLink llvmStatement Statement
+ HiLink llvmNumber Number
+ HiLink llvmComment Comment
+ HiLink llvmString String
+ HiLink llvmLabel Label
+ HiLink llvmKeyword Keyword
+ HiLink llvmBoolean Boolean
+ HiLink llvmFloat Float
+ HiLink llvmNoName Identifier
+ HiLink llvmConstant Constant
+ HiLink llvmSpecialComment SpecialComment
+ HiLink llvmError Error
+ HiLink llvmIdentifier Identifier
+
+ delcommand HiLink
+endif
+
+let b:current_syntax = "llvm"
diff --git a/contrib/llvm/utils/vim/tablegen.vim b/contrib/llvm/utils/vim/tablegen.vim
new file mode 100644
index 0000000..11a4d80
--- /dev/null
+++ b/contrib/llvm/utils/vim/tablegen.vim
@@ -0,0 +1,54 @@
+" Vim syntax file
+" Language: TableGen
+" Maintainer: The LLVM team, http://llvm.org/
+" Version: $Revision: 97271 $
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+" May be changed if you have a really slow machine
+syntax sync minlines=100
+
+syn case match
+
+syn keyword tgKeyword def let in code dag field include defm
+syn keyword tgType class int string list bit bits multiclass
+
+syn match tgNumber /\<\d\+\>/
+syn match tgNumber /\<\d\+\.\d*\>/
+syn match tgNumber /\<0b[01]\+\>/
+syn match tgNumber /\<0x[0-9a-fA-F]\+\>/
+syn region tgString start=/"/ skip=/\\"/ end=/"/ oneline
+
+syn region tgCode start=/\[{/ end=/}\]/
+
+syn keyword tgTodo contained TODO FIXME
+syn match tgComment /\/\/.*$/ contains=tgTodo
+" Handle correctly imbricated comment
+syn region tgComment2 matchgroup=tgComment2 start=+/\*+ end=+\*/+ contains=tgTodo,tgComment2
+
+if version >= 508 || !exists("did_c_syn_inits")
+ if version < 508
+ let did_c_syn_inits = 1
+ command -nargs=+ HiLink hi link <args>
+ else
+ command -nargs=+ HiLink hi def link <args>
+ endif
+
+ HiLink tgKeyword Statement
+ HiLink tgType Type
+ HiLink tgNumber Number
+ HiLink tgComment Comment
+ HiLink tgComment2 Comment
+ HiLink tgString String
+ " May find a better Hilight group...
+ HiLink tgCode Special
+ HiLink tgTodo Todo
+
+ delcommand HiLink
+endif
+
+let b:current_syntax = "tablegen"
diff --git a/contrib/llvm/utils/vim/vimrc b/contrib/llvm/utils/vim/vimrc
new file mode 100644
index 0000000..1f314c2
--- /dev/null
+++ b/contrib/llvm/utils/vim/vimrc
@@ -0,0 +1,220 @@
+" LLVM coding guidelines conformance for VIM
+" $Revision: 112982 $
+"
+" Maintainer: The LLVM Team, http://llvm.org
+" WARNING: Read before you source in all these commands and macros! Some
+" of them may change VIM behavior that you depend on.
+"
+" You can run VIM with these settings without changing your current setup with:
+" $ vim -u /path/to/llvm/utils/vim/vimrc
+
+" It's VIM, not VI
+set nocompatible
+
+" A tab produces a 2-space indentation
+set softtabstop=2
+set shiftwidth=2
+set expandtab
+
+" Highlight trailing whitespace and lines longer than 80 columns.
+highlight LongLine ctermbg=DarkYellow guibg=DarkYellow
+highlight WhitespaceEOL ctermbg=DarkYellow guibg=DarkYellow
+if v:version >= 702
+ " Lines longer than 80 columns.
+ au BufWinEnter * let w:m0=matchadd('LongLine', '\%>80v.\+', -1)
+
+ " Whitespace at the end of a line. This little dance suppresses
+ " whitespace that has just been typed.
+ au BufWinEnter * let w:m1=matchadd('WhitespaceEOL', '\s\+$', -1)
+ au InsertEnter * call matchdelete(w:m1)
+ au InsertEnter * let w:m2=matchadd('WhitespaceEOL', '\s\+\%#\@<!$', -1)
+ au InsertLeave * call matchdelete(w:m2)
+ au InsertLeave * let w:m1=matchadd('WhitespaceEOL', '\s\+$', -1)
+else
+ au BufRead,BufNewFile * syntax match LongLine /\%>80v.\+/
+ au InsertEnter * syntax match WhitespaceEOL /\s\+\%#\@<!$/
+ au InsertLeave * syntax match WhitespaceEOL /\s\+$/
+endif
+
+" Enable filetype detection
+filetype on
+
+" Optional
+" C/C++ programming helpers
+augroup csrc
+ au!
+ autocmd FileType * set nocindent smartindent
+ autocmd FileType c,cpp set cindent
+augroup END
+" Set a few indentation parameters. See the VIM help for cinoptions-values for
+" details. These aren't absolute rules; they're just an approximation of
+" common style in LLVM source.
+set cinoptions=:0,g0,(0,Ws,l1
+" Add and delete spaces in increments of `shiftwidth' for tabs
+set smarttab
+
+" Highlight syntax in programming languages
+syntax on
+
+" LLVM Makefiles can have names such as Makefile.rules or TEST.nightly.Makefile,
+" so it's important to categorize them as such.
+augroup filetype
+ au! BufRead,BufNewFile *Makefile* set filetype=make
+augroup END
+
+" In Makefiles, don't expand tabs to spaces, since we need the actual tabs
+autocmd FileType make set noexpandtab
+
+" Useful macros for cleaning up code to conform to LLVM coding guidelines
+
+" Delete trailing whitespace and tabs at the end of each line
+command! DeleteTrailingWs :%s/\s\+$//
+
+" Convert all tab characters to two spaces
+command! Untab :%s/\t/ /g
+
+" Enable syntax highlighting for LLVM files. To use, copy
+" utils/vim/llvm.vim to ~/.vim/syntax .
+augroup filetype
+ au! BufRead,BufNewFile *.ll set filetype=llvm
+augroup END
+
+" Enable syntax highlighting for tablegen files. To use, copy
+" utils/vim/tablegen.vim to ~/.vim/syntax .
+augroup filetype
+ au! BufRead,BufNewFile *.td set filetype=tablegen
+augroup END
+
+" Additional vim features to optionally uncomment.
+"set showcmd
+"set showmatch
+"set showmode
+"set incsearch
+"set ruler
+
+" Clang code-completion support. This is highly experimental!
+
+" A path to a clang executable.
+let g:clang_path = "clang++"
+
+" A list of options to add to the clang commandline, for example to add
+" include paths, predefined macros, and language options.
+let g:clang_opts = [
+ \ "-x","c++",
+ \ "-D__STDC_LIMIT_MACROS=1","-D__STDC_CONSTANT_MACROS=1",
+ \ "-Iinclude" ]
+
+function! ClangComplete(findstart, base)
+ if a:findstart == 1
+ " In findstart mode, look for the beginning of the current identifier.
+ let l:line = getline('.')
+ let l:start = col('.') - 1
+ while l:start > 0 && l:line[l:start - 1] =~ '\i'
+ let l:start -= 1
+ endwhile
+ return l:start
+ endif
+
+ " Get the current line and column numbers.
+ let l:l = line('.')
+ let l:c = col('.')
+
+ " Build a clang commandline to do code completion on stdin.
+ let l:the_command = shellescape(g:clang_path) .
+ \ " -cc1 -code-completion-at=-:" . l:l . ":" . l:c
+ for l:opt in g:clang_opts
+ let l:the_command .= " " . shellescape(l:opt)
+ endfor
+
+ " Copy the contents of the current buffer into a string for stdin.
+ " TODO: The extra space at the end is for working around clang's
+ " apparent inability to do code completion at the very end of the
+ " input.
+ " TODO: Is it better to feed clang the entire file instead of truncating
+ " it at the current line?
+ let l:process_input = join(getline(1, l:l), "\n") . " "
+
+ " Run it!
+ let l:input_lines = split(system(l:the_command, l:process_input), "\n")
+
+ " Parse the output.
+ for l:input_line in l:input_lines
+ " Vim's substring operator is annoyingly inconsistent with python's.
+ if l:input_line[:11] == 'COMPLETION: '
+ let l:value = l:input_line[12:]
+
+ " Chop off anything after " : ", if present, and move it to the menu.
+ let l:menu = ""
+ let l:spacecolonspace = stridx(l:value, " : ")
+ if l:spacecolonspace != -1
+ let l:menu = l:value[l:spacecolonspace+3:]
+ let l:value = l:value[:l:spacecolonspace-1]
+ endif
+
+ " Chop off " (Hidden)", if present, and move it to the menu.
+ let l:hidden = stridx(l:value, " (Hidden)")
+ if l:hidden != -1
+ let l:menu .= " (Hidden)"
+ let l:value = l:value[:l:hidden-1]
+ endif
+
+ " Handle "Pattern". TODO: Make clang less weird.
+ if l:value == "Pattern"
+ let l:value = l:menu
+ let l:pound = stridx(l:value, "#")
+ " Truncate the at the first [#, <#, or {#.
+ if l:pound != -1
+ let l:value = l:value[:l:pound-2]
+ endif
+ endif
+
+ " Filter out results which don't match the base string.
+ if a:base != ""
+ if l:value[:strlen(a:base)-1] != a:base
+ continue
+ end
+ endif
+
+ " TODO: Don't dump the raw input into info, though it's nice for now.
+ " TODO: The kind string?
+ let l:item = {
+ \ "word": l:value,
+ \ "menu": l:menu,
+ \ "info": l:input_line,
+ \ "dup": 1 }
+
+ " Report a result.
+ if complete_add(l:item) == 0
+ return []
+ endif
+ if complete_check()
+ return []
+ endif
+
+ elseif l:input_line[:9] == "OVERLOAD: "
+ " An overload candidate. Use a crazy hack to get vim to
+ " display the results. TODO: Make this better.
+ let l:value = l:input_line[10:]
+ let l:item = {
+ \ "word": " ",
+ \ "menu": l:value,
+ \ "info": l:input_line,
+ \ "dup": 1}
+
+ " Report a result.
+ if complete_add(l:item) == 0
+ return []
+ endif
+ if complete_check()
+ return []
+ endif
+
+ endif
+ endfor
+
+
+ return []
+endfunction ClangComplete
+
+" Uncomment this to enable the highly-broken autocompletion support.
+"set omnifunc=ClangComplete
diff --git a/contrib/llvm/utils/webNLT.pl b/contrib/llvm/utils/webNLT.pl
new file mode 100755
index 0000000..fb29fd2
--- /dev/null
+++ b/contrib/llvm/utils/webNLT.pl
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+
+use DBI;
+use CGI;
+
+$q = new CGI;
+print $q->header();
+print $q->start_html(-title=>"Nightly Tester DB");
+
+unless($q->param('pwd'))
+ {
+ print $q->startform();
+ print $q->password_field(-name=>"pwd", -size=>20, -maxlength=>20);
+ print $q->submit();
+ print $q->endform();
+ }
+else
+ {
+ # database information
+ $db="llvmalpha";
+ $host="localhost";
+ $userid="llvmdbuser";
+ $passwd=$q->param('pwd');
+ $connectionInfo="dbi:mysql:$db;$host";
+
+ # make connection to database
+ $dbh = DBI->connect($connectionInfo,$userid,$passwd) or die DBI->errstr;
+ $query = "Select DISTINCT(NAME) from Tests";
+ my $sth = $dbh->prepare($query) || die "Can't prepare statement: $DBI::errstr";
+ my $rc = $sth->execute or die DBI->errstr;
+ while (($n) = $sth->fetchrow_array)
+ {
+ push @names, ($n);
+# print "$n<P>";
+ }
+ $query = "Select DISTINCT(TEST) from Tests";
+ my $sth = $dbh->prepare($query) || die "Can't prepare statement: $DBI::errstr";
+ my $rc = $sth->execute or die DBI->errstr;
+ while (($n) = $sth->fetchrow_array)
+ {
+ push @tests, ($n);
+# print "$n\n";
+ }
+
+# print join "<BR>", @names;
+
+ print $q->startform();
+ print $q->scrolling_list(-name=>"test", -values=>\@tests, -multiple=>'true');
+ print "<P>";
+ print $q->scrolling_list(-name=>"name", -values=>\@names, -multiple=>'true');
+ print "<P>";
+ print $q->submit();
+ print $q->hidden("pwd", $q->param('pwd'));
+ print $q->endform();
+
+ # disconnect from database
+ $dbh->disconnect;
+
+ #now generate the urls to the chart
+ if ($q->param('test') && $q->param('name'))
+ {
+ my @names = $q->param('name');
+ my @tests = $q->param('test');
+ print "<P>";
+ print join "<BR>", @names;
+ print "<P>";
+ print join "<BR>", @tests;
+ print "<P>";
+ $str = "pwd=" . $q->param('pwd');
+ $count = 0;
+ foreach $n (@names)
+ {
+ foreach $t (@tests)
+ {
+ $str = "$str&t$count=$t&n$count=$n";
+ $count++;
+ }
+ }
+ print "<img src=\"cgiplotNLT.pl?$str\">";
+ }
+ }
+
+print $q->end_html();
OpenPOWER on IntegriCloud